From 2c54b44d618417e916bf4df14f9f600bd70cc200 Mon Sep 17 00:00:00 2001 From: domsteil Date: Tue, 24 Sep 2024 11:35:16 -0700 Subject: [PATCH 01/49] updating api --- .../moragents_dockers/agents/src/config.py | 7 +++ .../agents/src/dca_agent/src/agent.py | 59 +++++++++++++++++++ .../agents/src/dca_agent/src/config.py | 0 3 files changed, 66 insertions(+) create mode 100644 submodules/moragents_dockers/agents/src/dca_agent/src/agent.py create mode 100644 submodules/moragents_dockers/agents/src/dca_agent/src/config.py diff --git a/submodules/moragents_dockers/agents/src/config.py b/submodules/moragents_dockers/agents/src/config.py index 51274c7..2a1e6b1 100644 --- a/submodules/moragents_dockers/agents/src/config.py +++ b/submodules/moragents_dockers/agents/src/config.py @@ -44,6 +44,13 @@ class Config: "name": "tweet sizzler agent", "upload_required": False, }, + { + "path": "dca_agent.agent", + "class": "DCAAgent", + "description": "If the user wants to set up a dollar-cost averaging strategy for crypto purchases.", + "name": "DCA Agent", + "upload_required": False + }, # { # "path": "claim_agent.src.agent", # "class": "ClaimAgent", diff --git a/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py b/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py new file mode 100644 index 0000000..4a663f9 --- /dev/null +++ b/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py @@ -0,0 +1,59 @@ +import threading +import time +from datetime import datetime, timedelta + +class DCAAgent: + def __init__(self, agent_info, llm, llm_ollama, embeddings, flask_app): + """ + Initialize the DCAAgent. + + Parameters: + - agent_info (dict): Configuration details for the agent. + - llm (object): The main language model instance. + - llm_ollama (object): An additional language model instance. + - embeddings (object): Embedding model for handling vector representations. + - flask_app (Flask): The Flask application instance. + """ + self.agent_info = agent_info + self.llm = llm + self.llm_ollama = llm_ollama + self.embeddings = embeddings + self.flask_app = flask_app + self.scheduled_tasks = {} + + def chat(self, request, user_id): + + # Parse user input to extract token, spend limit, and interval + token = request.get('token', 'ETH') + spend_limit = request.get('spend_limit', 0.01) + interval = request.get('interval', 24) + + # Schedule the purchase + task_id = self.schedule_purchase(user_id, token, spend_limit, interval) + + response = f"Scheduled a recurring purchase of {spend_limit} {token} every {interval} hours. Task ID: {task_id}" + next_turn_agent = self.agent_info["name"] + return response, next_turn_agent + + def schedule_purchase(self, user_id, token, amount, interval): + + task_id = f"{user_id}_{datetime.utcnow().timestamp()}" + + # Schedule the task + def task(): + while True: + self.execute_purchase(token, amount) + time.sleep(interval * 3600) + + t = threading.Thread(target=task) + t.daemon = True + t.start() + + self.scheduled_tasks[task_id] = t + + return task_id + + def execute_purchase(self, token, amount): + + # TODO: Implement the logic to execute the purchase + pass diff --git a/submodules/moragents_dockers/agents/src/dca_agent/src/config.py b/submodules/moragents_dockers/agents/src/dca_agent/src/config.py new file mode 100644 index 0000000..e69de29 From 9ebe26c5a134fb78ef85a9a3af82acff2c4d1081 Mon Sep 17 00:00:00 2001 From: domsteil Date: Tue, 24 Sep 2024 11:43:19 -0700 Subject: [PATCH 02/49] updating api --- requirements.txt | 1 + .../agents/src/dca_agent/src/agent.py | 99 +++++++++++++++---- .../agents/src/dca_agent/src/config.py | 11 +++ 3 files changed, 90 insertions(+), 21 deletions(-) diff --git a/requirements.txt b/requirements.txt index 70969cd..0d69d31 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ customtkinter requests setuptools pyinstaller +cdp-sdk torch diff --git a/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py b/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py index 4a663f9..5c7d3d0 100644 --- a/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py +++ b/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py @@ -1,9 +1,11 @@ import threading import time from datetime import datetime, timedelta +from typing import Dict, Any +from cdp import Wallet class DCAAgent: - def __init__(self, agent_info, llm, llm_ollama, embeddings, flask_app): + def __init__(self, agent_info: Dict[str, Any], llm: Any, llm_ollama: Any, embeddings: Any, flask_app): """ Initialize the DCAAgent. @@ -19,41 +21,96 @@ def __init__(self, agent_info, llm, llm_ollama, embeddings, flask_app): self.llm_ollama = llm_ollama self.embeddings = embeddings self.flask_app = flask_app - self.scheduled_tasks = {} + self.scheduled_tasks: Dict[str, threading.Thread] = {} - def chat(self, request, user_id): + def chat(self, request: Dict[str, Any], user_id: str) -> tuple[str, str]: + """ + Process a chat request and schedule a purchase. + + Parameters: + - request (dict): The user's request containing purchase details. + - user_id (str): The unique identifier for the user. + + Returns: + - tuple: A response message and the next turn agent. + """ + try: + token = request.get('token', 'ETH') + spend_limit = float(request.get('spend_limit', 0.01)) + interval = int(request.get('interval', 24)) - # Parse user input to extract token, spend limit, and interval - token = request.get('token', 'ETH') - spend_limit = request.get('spend_limit', 0.01) - interval = request.get('interval', 24) + if spend_limit <= 0 or interval <= 0: + raise ValueError("Spend limit and interval must be positive numbers.") - # Schedule the purchase - task_id = self.schedule_purchase(user_id, token, spend_limit, interval) + task_id = self.schedule_purchase(user_id, token, spend_limit, interval) - response = f"Scheduled a recurring purchase of {spend_limit} {token} every {interval} hours. Task ID: {task_id}" - next_turn_agent = self.agent_info["name"] - return response, next_turn_agent + response = f"Scheduled a recurring purchase of {spend_limit} {token} every {interval} hours. Task ID: {task_id}" + next_turn_agent = self.agent_info["name"] + return response, next_turn_agent + except ValueError as e: + return f"Error: {str(e)}", self.agent_info["name"] + except Exception as e: + return f"An unexpected error occurred: {str(e)}", self.agent_info["name"] - def schedule_purchase(self, user_id, token, amount, interval): - + def schedule_purchase(self, user_id: str, token: str, amount: float, interval: int) -> str: + """ + Schedule a recurring purchase task. + + Parameters: + - user_id (str): The unique identifier for the user. + - token (str): The token to purchase. + - amount (float): The amount to spend on each purchase. + - interval (int): The time interval between purchases in hours. + + Returns: + - str: The unique task ID for the scheduled purchase. + """ task_id = f"{user_id}_{datetime.utcnow().timestamp()}" - # Schedule the task def task(): while True: - self.execute_purchase(token, amount) + try: + self.execute_purchase(token, amount) + except Exception as e: + print(f"Error executing purchase: {str(e)}") time.sleep(interval * 3600) - t = threading.Thread(target=task) - t.daemon = True + t = threading.Thread(target=task, daemon=True) t.start() self.scheduled_tasks[task_id] = t return task_id - def execute_purchase(self, token, amount): + def execute_purchase(self, token: str, amount: float) -> None: + """ + Execute a single purchase transaction. + + Parameters: + - token (str): The token to purchase. + - amount (float): The amount to spend on the purchase. + + Raises: + - Exception: If the trade fails or an error occurs. + """ + try: + wallet = Wallet.create("base-mainnet") + trade = wallet.trade(amount, "eth", token.lower()).wait() + print(f"Trade successfully completed: {trade}") + except Exception as e: + raise Exception(f"Failed to execute purchase: {str(e)}") - # TODO: Implement the logic to execute the purchase - pass + def cancel_task(self, task_id: str) -> bool: + """ + Cancel a scheduled task. + + Parameters: + - task_id (str): The unique identifier for the task to cancel. + + Returns: + - bool: True if the task was successfully cancelled, False otherwise. + """ + if task_id in self.scheduled_tasks: + del self.scheduled_tasks[task_id] + return True + return False \ No newline at end of file diff --git a/submodules/moragents_dockers/agents/src/dca_agent/src/config.py b/submodules/moragents_dockers/agents/src/dca_agent/src/config.py index e69de29..48ab0d0 100644 --- a/submodules/moragents_dockers/agents/src/dca_agent/src/config.py +++ b/submodules/moragents_dockers/agents/src/dca_agent/src/config.py @@ -0,0 +1,11 @@ +DELEGATOR_CONFIG = { + "agents": [ + { + "path": "dca_agent.agent", + "class": "DCAAgent", + "description": "If the user wants to set up a dollar-cost averaging strategy for crypto purchases.", + "name": "DCA Agent", + "upload": False + } + ] +} From ec3503aece7d4ad122a14539dc6d44899e5d3ce8 Mon Sep 17 00:00:00 2001 From: domsteil Date: Tue, 24 Sep 2024 11:48:49 -0700 Subject: [PATCH 03/49] updating api --- .../agents/src/gasless_agent/src/agent.py | 148 ++++++++++++++++++ .../agents/src/gasless_agent/src/config.py | 11 ++ 2 files changed, 159 insertions(+) create mode 100644 submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py create mode 100644 submodules/moragents_dockers/agents/src/gasless_agent/src/config.py diff --git a/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py b/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py new file mode 100644 index 0000000..53fab9b --- /dev/null +++ b/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py @@ -0,0 +1,148 @@ +import threading +import time +from datetime import datetime +from typing import Dict, Any +from cdp import Wallet + +class GaslessTransactionAgent: + def __init__(self, agent_info: Dict[str, Any], llm: Any, llm_ollama: Any, embeddings: Any, flask_app): + """ + Initialize the GaslessTransactionAgent. + + Parameters: + - agent_info (dict): Configuration details for the agent. + - llm (object): The main language model instance. + - llm_ollama (object): An additional language model instance. + - embeddings (object): Embedding model for handling vector representations. + - flask_app (Flask): The Flask application instance. + """ + self.agent_info = agent_info + self.llm = llm + self.llm_ollama = llm_ollama + self.embeddings = embeddings + self.flask_app = flask_app + self.scheduled_tasks: Dict[str, threading.Thread] = {} + self.wallets: Dict[str, Wallet] = {} + + def chat(self, request: Dict[str, Any], user_id: str) -> tuple[str, str]: + """ + Process a chat request and schedule a gasless transfer. + + Parameters: + - request (dict): The user's request containing transfer details. + - user_id (str): The unique identifier for the user. + + Returns: + - tuple: A response message and the next turn agent. + """ + try: + action = request.get('action', '').lower() + + if action == 'create_wallet': + wallet = self.create_wallet(user_id) + return f"Wallet created successfully. Address: {wallet.address}", self.agent_info["name"] + + elif action == 'transfer': + token = request.get('token', 'USDC') + amount = float(request.get('amount', 0.00001)) + to_user_id = request.get('to_user_id') + + if not to_user_id: + raise ValueError("Recipient user ID is required.") + + if amount <= 0: + raise ValueError("Transfer amount must be positive.") + + task_id = self.schedule_transfer(user_id, to_user_id, token, amount) + return f"Scheduled a gasless transfer of {amount} {token} to user {to_user_id}. Task ID: {task_id}", self.agent_info["name"] + + else: + return "Invalid action. Available actions: create_wallet, transfer", self.agent_info["name"] + + except ValueError as e: + return f"Error: {str(e)}", self.agent_info["name"] + except Exception as e: + return f"An unexpected error occurred: {str(e)}", self.agent_info["name"] + + def create_wallet(self, user_id: str) -> Wallet: + """ + Create a new wallet for a user. + + Parameters: + - user_id (str): The unique identifier for the user. + + Returns: + - Wallet: The newly created wallet object. + """ + wallet = Wallet.create("base-mainnet") + self.wallets[user_id] = wallet + print(f"Wallet successfully created for user {user_id}: {wallet}") + return wallet + + def schedule_transfer(self, from_user_id: str, to_user_id: str, token: str, amount: float) -> str: + """ + Schedule a gasless transfer task. + + Parameters: + - from_user_id (str): The user ID of the sender. + - to_user_id (str): The user ID of the recipient. + - token (str): The token to transfer. + - amount (float): The amount to transfer. + + Returns: + - str: The unique task ID for the scheduled transfer. + """ + task_id = f"{from_user_id}_to_{to_user_id}_{datetime.utcnow().timestamp()}" + + def task(): + try: + self.execute_transfer(from_user_id, to_user_id, token, amount) + except Exception as e: + print(f"Error executing transfer: {str(e)}") + + t = threading.Thread(target=task, daemon=True) + t.start() + + self.scheduled_tasks[task_id] = t + + return task_id + + def execute_transfer(self, from_user_id: str, to_user_id: str, token: str, amount: float) -> None: + """ + Execute a single gasless transfer transaction. + + Parameters: + - from_user_id (str): The user ID of the sender. + - to_user_id (str): The user ID of the recipient. + - token (str): The token to transfer. + - amount (float): The amount to transfer. + + Raises: + - Exception: If the transfer fails or an error occurs. + """ + try: + from_wallet = self.wallets.get(from_user_id) + to_wallet = self.wallets.get(to_user_id) + + if not from_wallet or not to_wallet: + raise ValueError("Both sender and recipient must have created wallets.") + + transfer = from_wallet.transfer(amount, token.lower(), to_wallet, gasless=True).wait() + print(f"Transfer successfully completed: {transfer}") + except Exception as e: + raise Exception(f"Failed to execute transfer: {str(e)}") + + def cancel_task(self, task_id: str) -> bool: + """ + Cancel a scheduled task. + + Parameters: + - task_id (str): The unique identifier for the task to cancel. + + Returns: + - bool: True if the task was successfully cancelled, False otherwise. + """ + if task_id in self.scheduled_tasks: + del self.scheduled_tasks[task_id] + return True + return False \ No newline at end of file diff --git a/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py b/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py new file mode 100644 index 0000000..213f283 --- /dev/null +++ b/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py @@ -0,0 +1,11 @@ +DELEGATOR_CONFIG = { + "agents": [ + { + "path": "gasless_agent.agent", + "class": "GaslessTransactionAgent", + "description": "If the user wants to send a gasless transaction to another user.", + "name": "Gasless Transaction Agent", + "upload": False + } + ] +} \ No newline at end of file From 884e0da9efd544fd64d88929ee0cfd2daf2fda03 Mon Sep 17 00:00:00 2001 From: domsteil Date: Tue, 24 Sep 2024 11:52:45 -0700 Subject: [PATCH 04/49] updating api --- .../moragents_dockers/agents/src/dca_agent/src/agent.py | 4 +++- .../moragents_dockers/agents/src/dca_agent/src/config.py | 5 +++++ .../agents/src/gasless_agent/src/agent.py | 4 +++- .../agents/src/gasless_agent/src/config.py | 7 ++++++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py b/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py index 5c7d3d0..b7f99f6 100644 --- a/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py +++ b/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py @@ -2,7 +2,7 @@ import time from datetime import datetime, timedelta from typing import Dict, Any -from cdp import Wallet +from cdp import Wallet, Cdp class DCAAgent: def __init__(self, agent_info: Dict[str, Any], llm: Any, llm_ollama: Any, embeddings: Any, flask_app): @@ -22,6 +22,8 @@ def __init__(self, agent_info: Dict[str, Any], llm: Any, llm_ollama: Any, embedd self.embeddings = embeddings self.flask_app = flask_app self.scheduled_tasks: Dict[str, threading.Thread] = {} + self.config = Config() + self.cdp = Cdp(self.config.CDP_API_KEY, self.config.CDP_API_SECRET) def chat(self, request: Dict[str, Any], user_id: str) -> tuple[str, str]: """ diff --git a/submodules/moragents_dockers/agents/src/dca_agent/src/config.py b/submodules/moragents_dockers/agents/src/dca_agent/src/config.py index 48ab0d0..2a79113 100644 --- a/submodules/moragents_dockers/agents/src/dca_agent/src/config.py +++ b/submodules/moragents_dockers/agents/src/dca_agent/src/config.py @@ -9,3 +9,8 @@ } ] } + +class Config: + + CDP_API_KEY = "cdp_api_key" + CDP_API_SECRET = "cdp_api_secret" diff --git a/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py b/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py index 53fab9b..9c12a63 100644 --- a/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py +++ b/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py @@ -2,7 +2,7 @@ import time from datetime import datetime from typing import Dict, Any -from cdp import Wallet +from cdp import Wallet, Cdp class GaslessTransactionAgent: def __init__(self, agent_info: Dict[str, Any], llm: Any, llm_ollama: Any, embeddings: Any, flask_app): @@ -23,6 +23,8 @@ def __init__(self, agent_info: Dict[str, Any], llm: Any, llm_ollama: Any, embedd self.flask_app = flask_app self.scheduled_tasks: Dict[str, threading.Thread] = {} self.wallets: Dict[str, Wallet] = {} + self.config = Config() + self.cdp = Cdp(self.config.CDP_API_KEY, self.config.CDP_API_SECRET) def chat(self, request: Dict[str, Any], user_id: str) -> tuple[str, str]: """ diff --git a/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py b/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py index 213f283..4182a9a 100644 --- a/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py +++ b/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py @@ -8,4 +8,9 @@ "upload": False } ] -} \ No newline at end of file +} + +class Config: + + CDP_API_KEY = "cdp_api_key" + CDP_API_SECRET = "cdp_api_secret" \ No newline at end of file From f364c4ef62b06aeb56388cb5c3956eb2b951dd1a Mon Sep 17 00:00:00 2001 From: domsteil Date: Tue, 24 Sep 2024 11:53:58 -0700 Subject: [PATCH 05/49] updating api --- .../moragents_dockers/agents/src/dca_agent/src/config.py | 5 +++++ .../moragents_dockers/agents/src/gasless_agent/src/config.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/submodules/moragents_dockers/agents/src/dca_agent/src/config.py b/submodules/moragents_dockers/agents/src/dca_agent/src/config.py index 2a79113..ba75875 100644 --- a/submodules/moragents_dockers/agents/src/dca_agent/src/config.py +++ b/submodules/moragents_dockers/agents/src/dca_agent/src/config.py @@ -1,3 +1,8 @@ +import logging + +# Logging configuration +logging.basicConfig(level=logging.INFO) + DELEGATOR_CONFIG = { "agents": [ { diff --git a/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py b/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py index 4182a9a..53a6ad7 100644 --- a/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py +++ b/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py @@ -1,3 +1,8 @@ +import logging + +# Logging configuration +logging.basicConfig(level=logging.INFO) + DELEGATOR_CONFIG = { "agents": [ { From 1665d84d29e0796628a9bcf4a56138fddf5ed904 Mon Sep 17 00:00:00 2001 From: domsteil Date: Tue, 24 Sep 2024 11:57:11 -0700 Subject: [PATCH 06/49] updating api --- .../agents/src/gasless_agent/src/agent.py | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py b/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py index 9c12a63..e5498f5 100644 --- a/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py +++ b/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py @@ -7,7 +7,7 @@ class GaslessTransactionAgent: def __init__(self, agent_info: Dict[str, Any], llm: Any, llm_ollama: Any, embeddings: Any, flask_app): """ - Initialize the GaslessTransactionAgent. + Initialize the GaslessTransactionAgent for sending gasless usdc transactions. Parameters: - agent_info (dict): Configuration details for the agent. @@ -28,7 +28,7 @@ def __init__(self, agent_info: Dict[str, Any], llm: Any, llm_ollama: Any, embedd def chat(self, request: Dict[str, Any], user_id: str) -> tuple[str, str]: """ - Process a chat request and schedule a gasless transfer. + Process a chat request and schedule a gasless usdc transfer. Parameters: - request (dict): The user's request containing transfer details. @@ -81,24 +81,24 @@ def create_wallet(self, user_id: str) -> Wallet: print(f"Wallet successfully created for user {user_id}: {wallet}") return wallet - def schedule_transfer(self, from_user_id: str, to_user_id: str, token: str, amount: float) -> str: + def schedule_transfer(self, from_wallet: Wallet, to_wallet: Wallet, token: str, amount: float) -> str: """ Schedule a gasless transfer task. Parameters: - - from_user_id (str): The user ID of the sender. - - to_user_id (str): The user ID of the recipient. + - from_wallet (Wallet): The wallet of the sender. + - to_wallet (Wallet): The wallet of the recipient. - token (str): The token to transfer. - amount (float): The amount to transfer. Returns: - str: The unique task ID for the scheduled transfer. """ - task_id = f"{from_user_id}_to_{to_user_id}_{datetime.utcnow().timestamp()}" + task_id = f"{from_wallet.address}_to_{to_wallet.address}_{datetime.utcnow().timestamp()}" def task(): try: - self.execute_transfer(from_user_id, to_user_id, token, amount) + self.execute_transfer(from_wallet, to_wallet, token, amount) except Exception as e: print(f"Error executing transfer: {str(e)}") @@ -109,13 +109,13 @@ def task(): return task_id - def execute_transfer(self, from_user_id: str, to_user_id: str, token: str, amount: float) -> None: + def execute_transfer(self, from_wallet: Wallet, to_wallet: Wallet, token: str, amount: float) -> None: """ Execute a single gasless transfer transaction. Parameters: - - from_user_id (str): The user ID of the sender. - - to_user_id (str): The user ID of the recipient. + - from_wallet (Wallet): The wallet of the sender. + - to_wallet (Wallet): The wallet of the recipient. - token (str): The token to transfer. - amount (float): The amount to transfer. @@ -123,8 +123,8 @@ def execute_transfer(self, from_user_id: str, to_user_id: str, token: str, amoun - Exception: If the transfer fails or an error occurs. """ try: - from_wallet = self.wallets.get(from_user_id) - to_wallet = self.wallets.get(to_user_id) + from_wallet = self.wallets.get(from_wallet) + to_wallet = self.wallets.get(to_wallet) if not from_wallet or not to_wallet: raise ValueError("Both sender and recipient must have created wallets.") From 9dfd6a0010a07398d4d3653e8035f619e1599606 Mon Sep 17 00:00:00 2001 From: domsteil Date: Tue, 24 Sep 2024 11:58:36 -0700 Subject: [PATCH 07/49] updating api --- submodules/moragents_dockers/agents/src/dca_agent/src/agent.py | 1 - .../moragents_dockers/agents/src/gasless_agent/src/agent.py | 1 - 2 files changed, 2 deletions(-) diff --git a/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py b/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py index b7f99f6..2c6838d 100644 --- a/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py +++ b/submodules/moragents_dockers/agents/src/dca_agent/src/agent.py @@ -22,7 +22,6 @@ def __init__(self, agent_info: Dict[str, Any], llm: Any, llm_ollama: Any, embedd self.embeddings = embeddings self.flask_app = flask_app self.scheduled_tasks: Dict[str, threading.Thread] = {} - self.config = Config() self.cdp = Cdp(self.config.CDP_API_KEY, self.config.CDP_API_SECRET) def chat(self, request: Dict[str, Any], user_id: str) -> tuple[str, str]: diff --git a/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py b/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py index e5498f5..af6ec31 100644 --- a/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py +++ b/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py @@ -23,7 +23,6 @@ def __init__(self, agent_info: Dict[str, Any], llm: Any, llm_ollama: Any, embedd self.flask_app = flask_app self.scheduled_tasks: Dict[str, threading.Thread] = {} self.wallets: Dict[str, Wallet] = {} - self.config = Config() self.cdp = Cdp(self.config.CDP_API_KEY, self.config.CDP_API_SECRET) def chat(self, request: Dict[str, Any], user_id: str) -> tuple[str, str]: From e427554cd55c8133c49335c303f2f2e10bf7a226 Mon Sep 17 00:00:00 2001 From: domsteil Date: Mon, 30 Sep 2024 17:14:41 -0700 Subject: [PATCH 08/49] updating api --- .../moragents_dockers/agents/requirements.txt | 5 +- .../moragents_dockers/agents/src/config.py | 16 +- .../agents/src/gasless_agent/src/agent.py | 59 ++++++- .../agents/src/gasless_agent/src/config.py | 11 +- .../frontend/components/Settings/index.tsx | 151 ++++++++++-------- 5 files changed, 155 insertions(+), 87 deletions(-) diff --git a/submodules/moragents_dockers/agents/requirements.txt b/submodules/moragents_dockers/agents/requirements.txt index e87e422..2df28fb 100644 --- a/submodules/moragents_dockers/agents/requirements.txt +++ b/submodules/moragents_dockers/agents/requirements.txt @@ -2,7 +2,7 @@ llama-cpp-python==0.2.90 transformers==4.43.3 sentencepiece==0.2.0 protobuf==5.27.2 -scikit-learn==1.5.1 +scikit-learn==1.3.2 huggingface-hub==0.24.3 flask==2.2.2 Werkzeug==2.2.2 @@ -14,4 +14,5 @@ langchain-text-splitters==0.2.2 langchain-core==0.2.24 langchain-community==0.2.10 torch -tweepy \ No newline at end of file +tweepy +cdp-sdk==0.0.1 \ No newline at end of file diff --git a/submodules/moragents_dockers/agents/src/config.py b/submodules/moragents_dockers/agents/src/config.py index 2a1e6b1..2d96620 100644 --- a/submodules/moragents_dockers/agents/src/config.py +++ b/submodules/moragents_dockers/agents/src/config.py @@ -45,19 +45,19 @@ class Config: "upload_required": False, }, { - "path": "dca_agent.agent", + "path": "dca_agent.src.agent", "class": "DCAAgent", "description": "If the user wants to set up a dollar-cost averaging strategy for crypto purchases.", "name": "DCA Agent", "upload_required": False }, - # { - # "path": "claim_agent.src.agent", - # "class": "ClaimAgent", - # "description": "Manages the process of claiming rewards or tokens, specifically MOR rewards. Use when the query explicitly mentions claiming rewards or tokens.", - # "name": "claim agent", - # "upload_required": False, - # }, + { + "path": "gasless_agent.src.agent", + "class": "GaslessAgent", + "description": "If the user wants to create a gasless wallet and send a transaction.", + "name": "Gasless Agent", + "upload_required": False + }, { "path": "reward_agent.src.agent", "class": "RewardAgent", diff --git a/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py b/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py index af6ec31..18cd291 100644 --- a/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py +++ b/submodules/moragents_dockers/agents/src/gasless_agent/src/agent.py @@ -1,9 +1,19 @@ import threading import time +import logging from datetime import datetime from typing import Dict, Any from cdp import Wallet, Cdp +from .config import Config + +# Configure logging +logging.basicConfig( + level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" +) +logger = logging.getLogger(__name__) + + class GaslessTransactionAgent: def __init__(self, agent_info: Dict[str, Any], llm: Any, llm_ollama: Any, embeddings: Any, flask_app): """ @@ -65,7 +75,26 @@ def chat(self, request: Dict[str, Any], user_id: str) -> tuple[str, str]: except Exception as e: return f"An unexpected error occurred: {str(e)}", self.agent_info["name"] - def create_wallet(self, user_id: str) -> Wallet: + def set_cdp_api_key(self, request): + + data = request.get_json() + required_keys = [ + "api_key", + "api_secret", + ] + + if not all(key in data for key in required_keys): + logger.warning("Missing required API credentials") + return {"error": Config.ERROR_MISSING_API_CREDENTIALS}, 400 + + # Save these credentials to local storage + for key in required_keys: + self.flask_app.config[key] = data[key] + + return {"success": "API credentials saved successfully"}, 200 + + + def create_wallet(self, user_id: str, request) -> Wallet: """ Create a new wallet for a user. @@ -75,11 +104,31 @@ def create_wallet(self, user_id: str) -> Wallet: Returns: - Wallet: The newly created wallet object. """ - wallet = Wallet.create("base-mainnet") - self.wallets[user_id] = wallet - print(f"Wallet successfully created for user {user_id}: {wallet}") - return wallet + data = request.get_json() + required_keys = [ + "api_key", + "api_secret", + ] + if not all(key in data for key in required_keys): + logger.warning("Missing required API credentials") + return {"error": Config.ERROR_MISSING_API_CREDENTIALS}, 400 + + try: + client = cdp.Client( + consumer_key=data["api_key"], + consumer_secret=data["api_secret"], + ) + + wallet = client.Wallet.create("base-mainnet") + self.wallets[user_id] = wallet + print(f"Wallet successfully created for user {user_id}: {wallet}") + return wallet + + except Exception as e: + logger.error(f"Error creating wallet: {str(e)}") + raise + def schedule_transfer(self, from_wallet: Wallet, to_wallet: Wallet, token: str, amount: float) -> str: """ Schedule a gasless transfer task. diff --git a/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py b/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py index 53a6ad7..7f51047 100644 --- a/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py +++ b/submodules/moragents_dockers/agents/src/gasless_agent/src/config.py @@ -1,7 +1,9 @@ import logging # Logging configuration -logging.basicConfig(level=logging.INFO) +logging.basicConfig( + level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" +) DELEGATOR_CONFIG = { "agents": [ @@ -13,9 +15,4 @@ "upload": False } ] -} - -class Config: - - CDP_API_KEY = "cdp_api_key" - CDP_API_SECRET = "cdp_api_secret" \ No newline at end of file +} \ No newline at end of file diff --git a/submodules/moragents_dockers/frontend/components/Settings/index.tsx b/submodules/moragents_dockers/frontend/components/Settings/index.tsx index fbb3db9..f138f27 100644 --- a/submodules/moragents_dockers/frontend/components/Settings/index.tsx +++ b/submodules/moragents_dockers/frontend/components/Settings/index.tsx @@ -2,39 +2,51 @@ import React, { useState, useEffect } from "react"; import { FaCog } from "react-icons/fa"; import classes from "./index.module.css"; +interface Credentials { + apiKey: string; + apiSecret: string; + accessToken: string; + accessTokenSecret: string; + bearerToken: string; + cdpApiKey: string; + cdpApiSecret: string; +} + const SettingsButton: React.FC = () => { const [isOpen, setIsOpen] = useState(false); - const [credentials, setCredentials] = useState({ + const [credentials, setCredentials] = useState({ apiKey: "", apiSecret: "", accessToken: "", accessTokenSecret: "", bearerToken: "", + cdpApiKey: "", + cdpApiSecret: "", }); - const [displayCredentials, setDisplayCredentials] = useState({ + const [displayCredentials, setDisplayCredentials] = useState({ apiKey: "", apiSecret: "", accessToken: "", accessTokenSecret: "", bearerToken: "", + cdpApiKey: "", + cdpApiSecret: "", }); useEffect(() => { - const storedCredentials = { + const storedCredentials: Credentials = { apiKey: localStorage.getItem("apiKey") || "", apiSecret: localStorage.getItem("apiSecret") || "", accessToken: localStorage.getItem("accessToken") || "", accessTokenSecret: localStorage.getItem("accessTokenSecret") || "", bearerToken: localStorage.getItem("bearerToken") || "", + cdpApiKey: localStorage.getItem("cdpApiKey") || "", + cdpApiSecret: localStorage.getItem("cdpApiSecret") || "", }; setCredentials(storedCredentials); - setDisplayCredentials({ - apiKey: obscureCredential(storedCredentials.apiKey), - apiSecret: obscureCredential(storedCredentials.apiSecret), - accessToken: obscureCredential(storedCredentials.accessToken), - accessTokenSecret: obscureCredential(storedCredentials.accessTokenSecret), - bearerToken: obscureCredential(storedCredentials.bearerToken), - }); + setDisplayCredentials(Object.fromEntries( + Object.entries(storedCredentials).map(([key, value]) => [key, obscureCredential(value)]) + ) as Credentials); }, []); const obscureCredential = (credential: string) => { @@ -46,13 +58,9 @@ const SettingsButton: React.FC = () => { Object.entries(credentials).forEach(([key, value]) => { localStorage.setItem(key, value); }); - setDisplayCredentials({ - apiKey: obscureCredential(credentials.apiKey), - apiSecret: obscureCredential(credentials.apiSecret), - accessToken: obscureCredential(credentials.accessToken), - accessTokenSecret: obscureCredential(credentials.accessTokenSecret), - bearerToken: obscureCredential(credentials.bearerToken), - }); + setDisplayCredentials(Object.fromEntries( + Object.entries(credentials).map(([key, value]) => [key, obscureCredential(value)]) + ) as Credentials); setIsOpen(false); }; @@ -61,23 +69,52 @@ const SettingsButton: React.FC = () => { setCredentials((prev) => ({ ...prev, [name]: value })); }; - const getFieldLabel = (key: string) => { - switch (key) { - case "apiKey": - return "API Key"; - case "apiSecret": - return "API Secret"; - case "accessToken": - return "Access Token"; - case "accessTokenSecret": - return "Access Token Secret"; - case "bearerToken": - return "Bearer Token"; + const getFieldSet = (group: string): (keyof Credentials)[] => { + switch (group) { + case "x": + return ["apiKey", "apiSecret", "accessToken", "accessTokenSecret", "bearerToken"]; + case "cdp": + return ["cdpApiKey", "cdpApiSecret"]; default: - return key; + return []; } }; + const getFieldLabel = (key: keyof Credentials): string => { + const labels: Record = { + apiKey: "API Key", + apiSecret: "API Secret", + accessToken: "Access Token", + accessTokenSecret: "Access Token Secret", + bearerToken: "Bearer Token", + cdpApiKey: "CDP API Key", + cdpApiSecret: "CDP API Secret", + }; + return labels[key] || key; + }; + + const renderCredentialFields = (group: string) => { + const fields = getFieldSet(group); + return fields.map((key) => ( +
+

+ Current {getFieldLabel(key)}:{" "} + + {displayCredentials[key] || "Not set"} + +

+ +
+ )); + }; + return ( <> +

X API Settings

All of these credentials are necessary. The API Key and API Secret @@ -103,41 +147,18 @@ const SettingsButton: React.FC = () => { Token Secret and Bearer Token are found in the X Developer Portal under the Authentication Tokens section.

-
- -
- {Object.entries(credentials).map(([key, value]) => ( -
-

- Current {getFieldLabel(key)}:{" "} - - {displayCredentials[ - key as keyof typeof displayCredentials - ] || "Not set"} - -

- - index < value.length - 4 ? "•" : char - ) - : "" - } - onChange={handleInputChange} - /> -
- ))} +
+ {renderCredentialFields("x")} +
+ +

Coinbase Developer Platform Settings

+

+ Enter your Coinbase Developer Platform API credentials here. You can find these in your Coinbase Developer account settings. +

+
+ {renderCredentialFields("cdp")}
+
+ ))} +
+
+ ))} + + + ); +}; + +export default PrefilledOptions; diff --git a/submodules/moragents_dockers/frontend/components/ChatInput/index.module.css b/submodules/moragents_dockers/frontend/components/ChatInput/index.module.css new file mode 100644 index 0000000..94d81d2 --- /dev/null +++ b/submodules/moragents_dockers/frontend/components/ChatInput/index.module.css @@ -0,0 +1,66 @@ +.container { + position: fixed; + bottom: 0; + left: 0; + right: 0; + background-color: transparent; +} + +.innerContainer { + max-width: 800px; + margin: 0 auto; +} + +.flexContainer { + margin-top: 1rem; + padding-left: 1.5rem; + padding-right: 1.5rem; +} + +.inputGroup { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + margin-bottom: 1rem; + border-radius: 8px; + background-color: #353936; +} + +.fileAddon { + background-color: transparent !important; + border: none !important; + color: #59f886 !important; + cursor: pointer; +} + +.hiddenInput { + display: none; +} + +.disabledIcon { + color: #6c6c6c !important; +} + +.messageInput { + border: none !important; + color: white !important; +} + +.messageInput:focus { + border-color: transparent !important; + box-shadow: none !important; +} + +.rightAddon { + background-color: transparent !important; + border: none !important; +} + +.sendButton { + background-color: transparent !important; + font-size: 24px; + color: #59f886 !important; +} + +.sendButton:hover { + background-color: transparent !important; +} diff --git a/submodules/moragents_dockers/frontend/components/ChatInput/index.tsx b/submodules/moragents_dockers/frontend/components/ChatInput/index.tsx index af03634..192e5b3 100644 --- a/submodules/moragents_dockers/frontend/components/ChatInput/index.tsx +++ b/submodules/moragents_dockers/frontend/components/ChatInput/index.tsx @@ -1,7 +1,7 @@ import React, { FC, useState } from "react"; import { Flex, - Input, + Textarea, InputGroup, InputLeftAddon, InputRightAddon, @@ -9,18 +9,19 @@ import { } from "@chakra-ui/react"; import { AttachmentIcon } from "@chakra-ui/icons"; import { SendIcon } from "../CustomIcon/SendIcon"; -import { availableAgents } from "../../config"; +import PrefilledOptions from "./PrefilledOptions"; +import styles from "./index.module.css"; type ChatInputProps = { onSubmit: (message: string, file: File | null) => Promise; - selectedAgent: string; disabled: boolean; + hasMessages?: boolean; }; export const ChatInput: FC = ({ onSubmit, - selectedAgent, disabled, + hasMessages = false, }) => { const [message, setMessage] = useState(""); const [file, setFile] = useState(null); @@ -34,75 +35,70 @@ export const ChatInput: FC = ({ setFile(null); }; + const handlePrefilledSelect = async (selectedMessage: string) => { + await onSubmit(selectedMessage, null); + }; + return ( - - - {agentSupportsFileUploads && ( - - document - .querySelector('input[type="file"]') - ?.dispatchEvent(new MouseEvent("click")) - } - > - setFile(e.target.files?.[0] || null)} - /> - - - )} - { - if (disabled) return; - if (e.altKey && e.key === "Enter") { - setMessage(message + "\n"); - } else if (e.key === "Enter") { - handleSubmit(); - } - }} - sx={{ - border: "none", - color: "white", - "&:focus": { - borderColor: "none !important", - boxShadow: "none !important", - }, - }} - disabled={disabled || file !== null} - value={message} - onChange={(e) => setMessage(e.target.value)} - placeholder="Type your message here..." - /> - - } - /> - - - + <> + {!hasMessages && } +
+
+ + + {agentSupportsFileUploads && ( + + document + .querySelector('input[type="file"]') + ?.dispatchEvent(new MouseEvent("click")) + } + > + setFile(e.target.files?.[0] || null)} + /> + + + )} +