Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 806
feat: python/create-onchain-agent - improved cli network selection & template selection#498
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Uh oh!
There was an error while loading. Please reload this page.
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
a14f660
feat: initial draft of improved network selection
CarsonRoscoe 22bf646
bump agentkit dependency in template
CarsonRoscoe 0517ffd
feat: refactor cli so it can build with local template
CarsonRoscoe 9de1986
feat: refactored development flag into template src flag
CarsonRoscoe 127cf8a
chore: changelog
CarsonRoscoe 4fec024
fix: removed unsupported networks from selection
CarsonRoscoe 0be55b7
chore: reworked network/chain/rpc logic to be tighter
CarsonRoscoe 468ce9e
chore: updated default to base-sepolia
CarsonRoscoe 69c917e
chore: improved network handling if only chain_id was received
CarsonRoscoe 5f23935
chore: removed condition that will always be true
CarsonRoscoe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Added revised network selection |
174 changes: 120 additions & 54 deletions
174 python/create-onchain-agent/create_onchain_agent/cli.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -39,18 +39,18 @@ | ||
| # "selected": "bold cyan", # Selected option | ||
| }) | ||
| NETWORK_CHOICES = [ | ||
| ("Ethereum Mainnet", "ethereum-mainnet"), | ||
| ("Ethereum Sepolia", "ethereum-sepolia"), | ||
| ("Polygon Mainnet", "polygon-mainnet"), | ||
| ("Polygon Mumbai", "polygon-mumbai"), | ||
| ("Base Mainnet", "base-mainnet"), | ||
| ("Base Sepolia (default)", "base-sepolia"), | ||
| ("Arbitrum Mainnet", "arbitrum-mainnet"), | ||
| ("Arbitrum Sepolia", "arbitrum-sepolia"), | ||
| ("Optimism Mainnet", "optimism-mainnet"), | ||
| ("Optimism Sepolia", "optimism-sepolia"), | ||
| ("Other (Enter EVM Chain ID)", "other"), | ||
| # Network constants | ||
| EVM_NETWORKS = [ | ||
| ("base-mainnet", "Base Mainnet"), | ||
| ("base-sepolia", "Base Sepolia"), | ||
| ("ethereum-mainnet", "Ethereum Mainnet"), | ||
| ("ethereum-sepolia", "Ethereum Sepolia"), | ||
| ("arbitrum-mainnet", "Arbitrum Mainnet"), | ||
| ("arbitrum-sepolia", "Arbitrum Sepolia"), | ||
| ("optimism-mainnet", "Optimism Mainnet"), | ||
| ("optimism-sepolia", "Optimism Sepolia"), | ||
| ("polygon-mainnet", "Polygon Mainnet"), | ||
| ("polygon-mumbai", "Polygon Mumbai"), | ||
| ] | ||
| CDP_SUPPORTED_NETWORKS = { | ||
| @@ -64,8 +64,26 @@ | ||
| VALID_PACKAGE_NAME_REGEX = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$") | ||
| def download_and_extract_template(): | ||
| """Downloads and extracts the chatbot template to a persistent location.""" | ||
| def get_template_path(template_path: str | None = None) -> str: | ||
| """Gets the template path either from a local directory or downloaded from GitHub. | ||
| Args: | ||
| template_path: Optional path to local template directory | ||
| Returns: | ||
| str: Path to the template directory | ||
| """ | ||
| if template_path: | ||
| # Use provided template path | ||
| local_template_path = Path(template_path) | ||
| if not local_template_path.exists(): | ||
| raise FileNotFoundError( | ||
| f"Template path not found at {local_template_path}. " | ||
| "Please provide a valid template directory path." | ||
| ) | ||
| return str(local_template_path) | ||
| # No template provided - download from GitHub | ||
| LOCAL_CACHE_DIR.mkdir(parents=True, exist_ok=True) | ||
| zip_path = LOCAL_CACHE_DIR / "repo.zip" | ||
| extract_path = LOCAL_CACHE_DIR / "templates" | ||
| @@ -94,8 +112,17 @@ def download_and_extract_template(): | ||
| return str(extract_path) | ||
| def get_network_choices(network_type: str) -> list: | ||
| """Filter network choices based on network type (mainnet/testnet).""" | ||
| return [ | ||
| (name, id) for id, name in EVM_NETWORKS | ||
| if (network_type == "mainnet" and "mainnet" in id) or | ||
| (network_type == "testnet" and any(net in id for net in ["sepolia", "mumbai", "devnet", "testnet"])) | ||
| ] | ||
| @click.command() | ||
| def create_project(): | ||
| @click.option('--template', type=str, help='Path to local template directory', default=None) | ||
| def create_project(template): | ||
| """Creates a new onchain agent project with interactive prompts.""" | ||
| ascii_art = """ | ||
| @@ -131,56 +158,95 @@ def create_project(): | ||
| else: | ||
| package_name = suggested_package_name | ||
| # Select network using arrow keys | ||
| # console.print("\n[cyan]Select a network:[/cyan]") | ||
| network_name = questionary.select( | ||
| "Choose a network network:", | ||
| choices=[name for name, _ in NETWORK_CHOICES], | ||
| default="Base Sepolia (default)", | ||
| style=custom_style # Apply custom styling | ||
| # Choose network type | ||
| network_type = questionary.select( | ||
| "Choose network type:", | ||
| choices=[ | ||
| "Mainnet", | ||
| "Testnet", | ||
| "Custom Chain ID", | ||
| ], | ||
| style=custom_style | ||
| ).ask() | ||
| # Map selection to network key | ||
| network = next(n for n in NETWORK_CHOICES if n[0] == network_name)[1] | ||
| network = None | ||
| chain_id = None | ||
| rpc_url = None | ||
| # If "Other" is selected, prompt for EVM Chain ID | ||
| if network == "other": | ||
| network = questionary.text( | ||
| "Enter the EVM Chain ID for your custom network:", | ||
| if network_type == "Custom Chain ID": | ||
| # Handle custom EVM network | ||
| chain_id = questionary.text( | ||
| "Enter your chain ID:", | ||
| validate=lambda text: text.strip().isdigit() or "Chain ID must be a number", | ||
| style=custom_style | ||
| ).ask().strip() | ||
| # Determine wallet provider | ||
| if network in CDP_SUPPORTED_NETWORKS: | ||
| wallet_provider = questionary.select( | ||
| "Select a wallet provider:", | ||
| choices=["CDP Wallet Provider", "Ethereum Account Wallet Provider"], | ||
| default="CDP Wallet Provider", | ||
| style=custom_style # Apply custom styling | ||
| ).ask() | ||
| wallet_provider = "cdp" if wallet_provider.startswith("CDP") else "eth" | ||
| rpc_url = questionary.text( | ||
| "Enter your RPC URL:", | ||
| validate=lambda text: ( | ||
| text.strip().startswith(("http://", "https://")) or | ||
| "RPC URL must start with http:// or https://" | ||
0xRAG marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ), | ||
| style=custom_style | ||
| ).ask() | ||
| wallet_provider = "eth" # Default to eth wallet provider for custom networks | ||
| else: | ||
| console.print(f"[yellow]⚠️ CDP is not supported on {network}. Defaulting to Ethereum Account Wallet Provider.[/yellow]") | ||
| wallet_provider = "eth" | ||
| # Filter networks based on mainnet/testnet selection | ||
| network_choices = get_network_choices(network_type.lower()) | ||
| network_name = questionary.select( | ||
| "Choose a network:", | ||
| choices=[ | ||
| name + (" (default)" if id == "base-sepolia" else "") | ||
| for name, id in network_choices | ||
| ], | ||
| default="Base Sepolia (default)" if network_type == "Testnet" else None, | ||
| style=custom_style | ||
| ).ask() | ||
| # Remove " (default)" suffix if present | ||
| network_name = network_name.replace(" (default)", "") | ||
| network = next(id for name, id in network_choices if name == network_name) | ||
| # Determine wallet provider | ||
| if network: | ||
| if network in CDP_SUPPORTED_NETWORKS: | ||
| wallet_choices = [ | ||
| "CDP Wallet Provider", | ||
| "Ethereum Account Wallet Provider" | ||
| ] | ||
| wallet_selection = questionary.select( | ||
| "Select a wallet provider:", | ||
| choices=wallet_choices, | ||
| default="CDP Wallet Provider", | ||
| style=custom_style | ||
| ).ask() | ||
| wallet_provider = "cdp" if wallet_selection.startswith("CDP") else "eth" | ||
| else: | ||
| console.print(f"[yellow]⚠️ CDP is not supported on {network}. Defaulting to Ethereum Account Wallet Provider.[/yellow]") | ||
| wallet_provider = "eth" | ||
| console.print(f"\n[blue]Creating your onchain agent project: {project_name}[/blue]") | ||
| template_path = download_and_extract_template() | ||
| # Run Copier with collected answers | ||
| run_copy( | ||
| template_path, | ||
| project_path, | ||
| data={ | ||
| "_project_name": project_name, | ||
| "_package_name": package_name, | ||
| "_network": network, | ||
| "_wallet_provider": wallet_provider, | ||
| }, | ||
| ) | ||
| # Update the Copier data dict to include new fields | ||
| copier_data = { | ||
| "_project_name": project_name, | ||
| "_package_name": package_name, | ||
| "_network": network, | ||
| "_wallet_provider": wallet_provider, | ||
| } | ||
| if chain_id: | ||
| copier_data["_chain_id"] = chain_id | ||
| if rpc_url: | ||
| copier_data["_rpc_url"] = rpc_url | ||
| try: | ||
| template_path = get_template_path(template) | ||
| run_copy(template_path, project_path, data=copier_data) | ||
| except FileNotFoundError as e: | ||
| console.print(f"[red]Error: {str(e)}[/red]") | ||
| return | ||
| console.print(f"[bold blue]Successfully created your AgentKit project in {project_path}[/bold blue]") | ||
8 changes: 8 additions & 0 deletions
8 python/create-onchain-agent/templates/chatbot/.env.local.jinja
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 33 additions & 1 deletion
34 python/create-onchain-agent/templates/chatbot/chatbot.py.jinja
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -31,6 +31,7 @@ from coinbase_agentkit import ( | ||
| from coinbase_agentkit_langchain import get_langchain_tools | ||
| {% if _wallet_provider == "eth" %} | ||
| from eth_account import Account | ||
| from coinbase_agentkit.network import NETWORK_ID_TO_CHAIN_ID, NETWORK_ID_TO_CHAIN, CHAIN_ID_TO_NETWORK_ID | ||
| {% endif %} | ||
| """ | ||
| AgentKit Integration | ||
| @@ -119,10 +120,41 @@ def initialize_agent(): | ||
| # Create Ethereum account from private key | ||
| account = Account.from_key(private_key) | ||
| # Get chain configuration | ||
| chain_id = os.getenv("CHAIN_ID") | ||
| rpc_url = os.getenv("RPC_URL") | ||
| network = os.getenv("NETWORK") | ||
| if chain_id and rpc_url: | ||
| pass | ||
| elif network: | ||
| chain_id = NETWORK_ID_TO_CHAIN_ID.get(network) | ||
| if not chain_id: | ||
| raise ValueError(f"Unknown network ID: {network}") | ||
| if not rpc_url: | ||
| chain = NETWORK_ID_TO_CHAIN[network] | ||
| rpc_url = chain["rpc_urls"]["default"]["http"][0] | ||
| elif chain_id: | ||
| # Try to find the network ID from the chain ID | ||
| network = CHAIN_ID_TO_NETWORK_ID.get(chain_id) | ||
| if network: | ||
| chain = NETWORK_ID_TO_CHAIN[network] | ||
| rpc_url = chain["rpc_urls"]["default"]["http"][0] | ||
| else: | ||
| raise ValueError("When using chain_id, you must also provide an RPC_URL if the chain is not recognized") | ||
| else: | ||
| print("No network configuration provided. Defaulting to Base Sepolia...") | ||
| network = "base-sepolia" | ||
| chain_id = NETWORK_ID_TO_CHAIN_ID[network] | ||
| chain = NETWORK_ID_TO_CHAIN[network] | ||
| rpc_url = chain["rpc_urls"]["default"]["http"][0] | ||
| wallet_provider = EthAccountWalletProvider( | ||
| config=EthAccountWalletProviderConfig( | ||
| account=account, | ||
| chain_id="84532" | ||
| chain_id=chain_id, | ||
| rpc_url=rpc_url | ||
CarsonRoscoe marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ) | ||
| ) | ||
| {% endif %} | ||
2 changes: 1 addition & 1 deletion
2 python/create-onchain-agent/templates/chatbot/pyproject.toml.jinja
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this new option be documented?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh nvm, just saw in the PR description that this is local-only