From d494ced2ddb5419717d6d3eef605c9c4d1d675f8 Mon Sep 17 00:00:00 2001 From: nicoback2 <36916764+nicoback2@users.noreply.github.com> Date: Thu, 21 Dec 2023 20:53:04 -0800 Subject: [PATCH] [Discovery] Add bulk get dashboard wallet users to Discovery Api [C-3532] (#6984) Co-authored-by: Nikki Kang --- packages/discovery-provider/src/api/v1/api.py | 2 + .../src/api/v1/dashboard_wallet_users.py | 59 +++++++++++++++++++ .../discovery-provider/src/api/v1/helpers.py | 7 +++ .../api/v1/models/dashboard_wallet_user.py | 13 ++++ .../src/queries/get_dashboard_wallet_users.py | 35 +++++++++++ 5 files changed, 116 insertions(+) create mode 100644 packages/discovery-provider/src/api/v1/dashboard_wallet_users.py create mode 100644 packages/discovery-provider/src/api/v1/models/dashboard_wallet_user.py create mode 100644 packages/discovery-provider/src/queries/get_dashboard_wallet_users.py diff --git a/packages/discovery-provider/src/api/v1/api.py b/packages/discovery-provider/src/api/v1/api.py index 8adc04e0aac..d298a52cbf6 100644 --- a/packages/discovery-provider/src/api/v1/api.py +++ b/packages/discovery-provider/src/api/v1/api.py @@ -4,6 +4,7 @@ from src.api.v1.challenges import ns as challenges_ns from src.api.v1.cid_data import full_ns as cid_data_full_ns +from src.api.v1.dashboard_wallet_users import ns as dashboard_wallet_users_ns from src.api.v1.developer_apps import ns as developer_apps_ns from src.api.v1.metrics import ns as metrics_ns from src.api.v1.models.users import ns as models_ns @@ -42,6 +43,7 @@ def specs_url(self): api_v1.add_namespace(challenges_ns) api_v1.add_namespace(tips_ns) api_v1.add_namespace(developer_apps_ns) +api_v1.add_namespace(dashboard_wallet_users_ns) api_v1.add_namespace(metrics_ns) api_v1.add_namespace(resolve_ns) diff --git a/packages/discovery-provider/src/api/v1/dashboard_wallet_users.py b/packages/discovery-provider/src/api/v1/dashboard_wallet_users.py new file mode 100644 index 00000000000..4895486d9e9 --- /dev/null +++ b/packages/discovery-provider/src/api/v1/dashboard_wallet_users.py @@ -0,0 +1,59 @@ +from flask_restx import Namespace, Resource, fields, marshal_with, reqparse + +from src.api.v1.helpers import ( + DescriptiveArgument, + format_dashboard_wallet_user, + make_response, + success_response, +) +from src.api.v1.models.dashboard_wallet_user import dashboard_wallet_user +from src.queries.get_dashboard_wallet_users import get_bulk_dashboard_wallet_users +from src.utils.redis_cache import cache +from src.utils.redis_metrics import record_metrics + +ns = Namespace( + "dashboard_wallet_users", + description="Protocol dashboard wallet users related operations", +) + +get_dashboard_wallet_users_parser = reqparse.RequestParser( + argument_class=DescriptiveArgument +) +get_dashboard_wallet_users_parser.add_argument( + "wallets", + required=True, + action="split", + description="The wallets for which to fetch connected Audius user profiles.", +) + +get_dashboard_wallet_users_response = make_response( + "dashboard_wallet_users_response", + ns, + fields.List(fields.Nested(dashboard_wallet_user)), +) + + +@ns.route("") +class BulkDashboardWalletUsers(Resource): + @record_metrics + @ns.doc( + id="Bulk get dashboard wallet users", + description="Gets Audius user profiles connected to given dashboard wallet addresses", + responses={ + 200: "Success", + 400: "Bad request", + 404: "No such dashboard wallets", + 500: "Server error", + }, + ) + @ns.expect(get_dashboard_wallet_users_parser) + @marshal_with(get_dashboard_wallet_users_response) + @cache(ttl_sec=5) + def get(self): + args = get_dashboard_wallet_users_parser.parse_args() + wallets_arg = args.get("wallets") + dashboard_wallet_users = get_bulk_dashboard_wallet_users(wallets_arg) + dashboard_wallet_users = list( + map(format_dashboard_wallet_user, dashboard_wallet_users) + ) + return success_response(dashboard_wallet_users) diff --git a/packages/discovery-provider/src/api/v1/helpers.py b/packages/discovery-provider/src/api/v1/helpers.py index d98e6e5edda..2d42c057a2a 100644 --- a/packages/discovery-provider/src/api/v1/helpers.py +++ b/packages/discovery-provider/src/api/v1/helpers.py @@ -975,6 +975,13 @@ def format_authorized_app(authorized_app): } +def format_dashboard_wallet_user(dashboard_wallet_user): + return { + "wallet": dashboard_wallet_user["wallet"], + "user": extend_user(dashboard_wallet_user["user"]), + } + + def get_prefixed_eth_address(address: str): if not address.startswith("0x"): return "0x" + address diff --git a/packages/discovery-provider/src/api/v1/models/dashboard_wallet_user.py b/packages/discovery-provider/src/api/v1/models/dashboard_wallet_user.py new file mode 100644 index 00000000000..99d34bc0763 --- /dev/null +++ b/packages/discovery-provider/src/api/v1/models/dashboard_wallet_user.py @@ -0,0 +1,13 @@ +from flask_restx import fields + +from src.api.v1.models.users import user_model + +from .common import ns + +dashboard_wallet_user = ns.model( + "dashboard_wallet_user", + { + "wallet": fields.String(required=True), + "user": fields.Nested(user_model, required=True), + }, +) diff --git a/packages/discovery-provider/src/queries/get_dashboard_wallet_users.py b/packages/discovery-provider/src/queries/get_dashboard_wallet_users.py new file mode 100644 index 00000000000..9e8983ccd56 --- /dev/null +++ b/packages/discovery-provider/src/queries/get_dashboard_wallet_users.py @@ -0,0 +1,35 @@ +import logging +from typing import Dict, List + +from sqlalchemy import func + +from src.models.dashboard_wallet_user.dashboard_wallet_user import DashboardWalletUser +from src.models.users.user import User +from src.utils import db_session +from src.utils.helpers import model_to_dictionary + +logger = logging.getLogger(__name__) + + +def get_bulk_dashboard_wallet_users(wallets: List[str]) -> List[Dict]: + """ + Returns dashboard wallet users matching array of wallets + + Args: + wallets: List of wallet addresses + + Returns: + List of dashboard wallet users + """ + lc_wallets = [wallet.lower() for wallet in wallets] + db = db_session.get_db_read_replica() + with db.scoped_session() as session: + rows = ( + session.query(DashboardWalletUser.wallet, User) + .join(User, User.user_id == DashboardWalletUser.user_id) + .filter(func.lower(DashboardWalletUser.wallet).in_(lc_wallets)) + .filter(DashboardWalletUser.is_delete == False) + .all() + ) + res = [{"wallet": row[0], "user": model_to_dictionary(row[1])} for row in rows] + return res