diff --git a/packages/plugin-evm/src/actions/bridge.ts b/packages/plugin-evm/src/actions/bridge.ts index 3d0a38582d6..4d92018e96a 100644 --- a/packages/plugin-evm/src/actions/bridge.ts +++ b/packages/plugin-evm/src/actions/bridge.ts @@ -6,7 +6,8 @@ import { ExtendedChain, getRoutes, } from "@lifi/sdk"; -import { getChainConfigs, WalletProvider } from "../providers/wallet"; +import { WalletProvider } from "../providers/wallet"; +import { getChainConfigs } from "../providers/chainConfigs"; import { bridgeTemplate } from "../templates"; import type { BridgeParams, Transaction } from "../types"; diff --git a/packages/plugin-evm/src/actions/swap.ts b/packages/plugin-evm/src/actions/swap.ts index 4bc23080942..3b22916cb35 100644 --- a/packages/plugin-evm/src/actions/swap.ts +++ b/packages/plugin-evm/src/actions/swap.ts @@ -6,7 +6,8 @@ import { ExtendedChain, getRoutes, } from "@lifi/sdk"; -import { getChainConfigs, WalletProvider } from "../providers/wallet"; +import { WalletProvider } from "../providers/wallet"; +import { getChainConfigs } from "../providers/chainConfigs"; import { swapTemplate } from "../templates"; import type { SwapParams, Transaction } from "../types"; diff --git a/packages/plugin-evm/src/providers/chainConfigs.ts b/packages/plugin-evm/src/providers/chainConfigs.ts new file mode 100644 index 00000000000..a410c56b962 --- /dev/null +++ b/packages/plugin-evm/src/providers/chainConfigs.ts @@ -0,0 +1,339 @@ +import { + mainnet, + base, + sepolia, + bsc, + arbitrum, + avalanche, + polygon, + optimism, + cronos, + gnosis, + fantom, + klaytn, + celo, + moonbeam, + aurora, + harmonyOne, + moonriver, + arbitrumNova, + mantle, + linea, + scroll, + filecoin, + taiko, + zksync, + canto, +} from "viem/chains"; +import type { ChainMetadata, SupportedChain } from "../types"; +import type { IAgentRuntime } from "@ai16z/eliza"; + +export const DEFAULT_CHAIN_CONFIGS: Record = { + ethereum: { + chainId: 1, + name: "Ethereum", + chain: mainnet, + rpcUrl: "https://eth.llamarpc.com", + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + blockExplorerUrl: "https://etherscan.io", + }, + base: { + chainId: 8453, + name: "Base", + chain: base, + rpcUrl: "https://base.llamarpc.com", + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + blockExplorerUrl: "https://basescan.org", + }, + sepolia: { + chainId: 11155111, + name: "Sepolia", + chain: sepolia, + rpcUrl: "https://rpc.sepolia.org", + nativeCurrency: { + name: "Sepolia Ether", + symbol: "ETH", + decimals: 18, + }, + blockExplorerUrl: "https://sepolia.etherscan.io", + }, + bsc: { + chainId: 56, + name: "BNB Smart Chain", + chain: bsc, + rpcUrl: "https://bsc-dataseed1.binance.org/", + nativeCurrency: { + name: "Binance Coin", + symbol: "BNB", + decimals: 18, + }, + blockExplorerUrl: "https://bscscan.com", + }, + arbitrum: { + chainId: 42161, + name: "Arbitrum One", + chain: arbitrum, + rpcUrl: "https://arb1.arbitrum.io/rpc", + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + blockExplorerUrl: "https://arbiscan.io", + }, + avalanche: { + chainId: 43114, + name: "Avalanche C-Chain", + chain: avalanche, + rpcUrl: "https://api.avax.network/ext/bc/C/rpc", + nativeCurrency: { + name: "Avalanche", + symbol: "AVAX", + decimals: 18, + }, + blockExplorerUrl: "https://snowtrace.io", + }, + polygon: { + chainId: 137, + name: "Polygon", + chain: polygon, + rpcUrl: "https://polygon-rpc.com", + nativeCurrency: { + name: "MATIC", + symbol: "MATIC", + decimals: 18, + }, + blockExplorerUrl: "https://polygonscan.com", + }, + optimism: { + chainId: 10, + name: "Optimism", + chain: optimism, + rpcUrl: "https://mainnet.optimism.io", + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + blockExplorerUrl: "https://optimistic.etherscan.io", + }, + cronos: { + chainId: 25, + name: "Cronos", + chain: cronos, + rpcUrl: "https://evm.cronos.org", + nativeCurrency: { + name: "Cronos", + symbol: "CRO", + decimals: 18, + }, + blockExplorerUrl: "https://cronoscan.com", + }, + gnosis: { + chainId: 100, + name: "Gnosis", + chain: gnosis, + rpcUrl: "https://rpc.gnosischain.com", + nativeCurrency: { + name: "xDAI", + symbol: "XDAI", + decimals: 18, + }, + blockExplorerUrl: "https://gnosisscan.io", + }, + fantom: { + chainId: 250, + name: "Fantom", + chain: fantom, + rpcUrl: "https://rpc.ftm.tools", + nativeCurrency: { + name: "Fantom", + symbol: "FTM", + decimals: 18, + }, + blockExplorerUrl: "https://ftmscan.com", + }, + klaytn: { + chainId: 8217, + name: "Klaytn", + chain: klaytn, + rpcUrl: "https://public-node-api.klaytnapi.com/v1/cypress", + nativeCurrency: { + name: "KLAY", + symbol: "KLAY", + decimals: 18, + }, + blockExplorerUrl: "https://scope.klaytn.com", + }, + celo: { + chainId: 42220, + name: "Celo", + chain: celo, + rpcUrl: "https://forno.celo.org", + nativeCurrency: { + name: "Celo", + symbol: "CELO", + decimals: 18, + }, + blockExplorerUrl: "https://celoscan.io", + }, + moonbeam: { + chainId: 1284, + name: "Moonbeam", + chain: moonbeam, + rpcUrl: "https://rpc.api.moonbeam.network", + nativeCurrency: { + name: "Glimmer", + symbol: "GLMR", + decimals: 18, + }, + blockExplorerUrl: "https://moonscan.io", + }, + aurora: { + chainId: 1313161554, + name: "Aurora", + chain: aurora, + rpcUrl: "https://mainnet.aurora.dev", + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + blockExplorerUrl: "https://aurorascan.dev", + }, + harmonyOne: { + chainId: 1666600000, + name: "harmonyOne", + chain: harmonyOne, + rpcUrl: "https://api.harmonyOne.one", + nativeCurrency: { + name: "ONE", + symbol: "ONE", + decimals: 18, + }, + blockExplorerUrl: "https://explorer.harmonyOne.one", + }, + moonriver: { + chainId: 1285, + name: "Moonriver", + chain: moonriver, + rpcUrl: "https://rpc.api.moonriver.moonbeam.network", + nativeCurrency: { + name: "Moonriver", + symbol: "MOVR", + decimals: 18, + }, + blockExplorerUrl: "https://moonriver.moonscan.io", + }, + arbitrumNova: { + chainId: 42170, + name: "Arbitrum Nova", + chain: arbitrumNova, + rpcUrl: "https://nova.arbitrum.io/rpc", + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + blockExplorerUrl: "https://nova-explorer.arbitrum.io", + }, + mantle: { + chainId: 5000, + name: "Mantle", + chain: mantle, + rpcUrl: "https://rpc.mantle.xyz", + nativeCurrency: { + name: "Mantle", + symbol: "MNT", + decimals: 18, + }, + blockExplorerUrl: "https://explorer.mantle.xyz", + }, + linea: { + chainId: 59144, + name: "Linea", + chain: linea, + rpcUrl: "https://linea-mainnet.rpc.build", + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + blockExplorerUrl: "https://lineascan.build", + }, + scroll: { + chainId: 534353, + name: "Scroll Alpha Testnet", + chain: scroll, + rpcUrl: "https://alpha-rpc.scroll.io/l2", + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + blockExplorerUrl: "https://blockscout.scroll.io", + }, + filecoin: { + chainId: 314, + name: "Filecoin", + chain: filecoin, + rpcUrl: "https://api.node.glif.io/rpc/v1", + nativeCurrency: { + name: "Filecoin", + symbol: "FIL", + decimals: 18, + }, + blockExplorerUrl: "https://filfox.info/en", + }, + taiko: { + chainId: 167005, + name: "Taiko (Alpha-3) Testnet", + chain: taiko, + rpcUrl: "https://rpc.a3.taiko.xyz", + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + blockExplorerUrl: "https://explorer.a3.taiko.xyz", + }, + zksync: { + chainId: 324, + name: "zksync Era", + chain: zksync, + rpcUrl: "https://mainnet.era.zksync.io", + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + blockExplorerUrl: "https://explorer.zksync.io", + }, + canto: { + chainId: 7700, + name: "Canto", + chain: canto, + rpcUrl: "https://canto.slingshot.finance", + nativeCurrency: { + name: "CANTO", + symbol: "CANTO", + decimals: 18, + }, + blockExplorerUrl: "https://tuber.build", + }, +} as const; + +export const getChainConfigs = (runtime: IAgentRuntime) => { + return ( + (runtime.character.settings.chains?.evm as ChainMetadata[]) || + DEFAULT_CHAIN_CONFIGS + ); +}; diff --git a/packages/plugin-evm/src/providers/chainUtils.ts b/packages/plugin-evm/src/providers/chainUtils.ts new file mode 100644 index 00000000000..377aa3f3631 --- /dev/null +++ b/packages/plugin-evm/src/providers/chainUtils.ts @@ -0,0 +1,51 @@ +import { createPublicClient, createWalletClient, http } from "viem"; +import type { IAgentRuntime } from "@ai16z/eliza"; +import type { + Account, + Chain, + HttpTransport, + PublicClient, + WalletClient, +} from "viem"; +import type { SupportedChain, ChainConfig } from "../types"; +import { DEFAULT_CHAIN_CONFIGS } from "./chainConfigs"; + +export const createChainClients = ( + chain: SupportedChain, + runtime: IAgentRuntime, + account: Account +): ChainConfig => { + const chainConfig = DEFAULT_CHAIN_CONFIGS[chain]; + const transport = http(chainConfig.rpcUrl); + + return { + chain: chainConfig.chain, + publicClient: createPublicClient({ + chain: chainConfig.chain, + transport, + }) as PublicClient, + walletClient: createWalletClient({ + chain: chainConfig.chain, + transport, + account, + }), + }; +}; + +export const initializeChainConfigs = ( + runtime: IAgentRuntime, + account: Account +): Record => { + return Object.keys(DEFAULT_CHAIN_CONFIGS).reduce( + (configs, chain) => { + const supportedChain = chain as SupportedChain; + configs[supportedChain] = createChainClients( + supportedChain, + runtime, + account + ); + return configs; + }, + {} as Record + ); +}; diff --git a/packages/plugin-evm/src/providers/wallet.ts b/packages/plugin-evm/src/providers/wallet.ts index 01b934300df..a317a861879 100644 --- a/packages/plugin-evm/src/providers/wallet.ts +++ b/packages/plugin-evm/src/providers/wallet.ts @@ -1,53 +1,17 @@ +import { formatUnits } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; import type { IAgentRuntime, Provider, Memory, State } from "@ai16z/eliza"; -import { - createPublicClient, - createWalletClient, - http, - formatUnits, - type PublicClient, - type WalletClient, - type Chain, - type HttpTransport, - type Address, +import type { + Address, + WalletClient, + PublicClient, + Chain, + HttpTransport, Account, } from "viem"; -import { mainnet, base } from "viem/chains"; -import type { SupportedChain, ChainConfig, ChainMetadata } from "../types"; -import { privateKeyToAccount } from "viem/accounts"; - -export const DEFAULT_CHAIN_CONFIGS: Record = { - ethereum: { - chainId: 1, - name: "Ethereum", - chain: mainnet, - rpcUrl: "https://eth.llamarpc.com", - nativeCurrency: { - name: "Ether", - symbol: "ETH", - decimals: 18, - }, - blockExplorerUrl: "https://etherscan.io", - }, - base: { - chainId: 8453, - name: "Base", - chain: base, - rpcUrl: "https://base.llamarpc.com", - nativeCurrency: { - name: "Ether", - symbol: "ETH", - decimals: 18, - }, - blockExplorerUrl: "https://basescan.org", - }, -} as const; - -export const getChainConfigs = (runtime: IAgentRuntime) => { - return ( - (runtime.character.settings.chains?.evm as ChainConfig[]) || - DEFAULT_CHAIN_CONFIGS - ); -}; +import type { SupportedChain, ChainConfig } from "../types"; +import { getChainConfigs } from "./chainConfigs"; +import { initializeChainConfigs } from "./chainUtils"; export class WalletProvider { private chainConfigs: Record; @@ -60,30 +24,11 @@ export class WalletProvider { if (!privateKey) throw new Error("EVM_PRIVATE_KEY not configured"); this.runtime = runtime; - const account = privateKeyToAccount(privateKey as `0x${string}`); this.address = account.address; - const createClients = (chain: SupportedChain): ChainConfig => { - const transport = http(getChainConfigs(runtime)[chain].rpcUrl); - return { - chain: getChainConfigs(runtime)[chain].chain, - publicClient: createPublicClient({ - chain: getChainConfigs(runtime)[chain].chain, - transport, - }) as PublicClient, - walletClient: createWalletClient({ - chain: getChainConfigs(runtime)[chain].chain, - transport, - account, - }), - }; - }; - - this.chainConfigs = { - ethereum: createClients("ethereum"), - base: createClients("base"), - }; + // Initialize all chain configs at once + this.chainConfigs = initializeChainConfigs(runtime, account); } getAddress(): Address { @@ -175,7 +120,6 @@ export const evmWalletProvider: Provider = { message: Memory, state?: State ): Promise { - // Check if the user has an EVM wallet if (!runtime.getSetting("EVM_PRIVATE_KEY")) { return null; } diff --git a/packages/plugin-evm/src/templates/index.ts b/packages/plugin-evm/src/templates/index.ts index d8bccf17d3b..a8c7f1fcc3e 100644 --- a/packages/plugin-evm/src/templates/index.ts +++ b/packages/plugin-evm/src/templates/index.ts @@ -5,7 +5,7 @@ export const transferTemplate = `Given the recent messages and wallet informatio {{walletInfo}} Extract the following information about the requested transfer: -- Chain to execute on (ethereum or base) +- Chain to execute on - Amount to transfer - Recipient address - Token symbol or address (if not native token) @@ -14,7 +14,7 @@ Respond with a JSON markdown block containing only the extracted values: \`\`\`json { - "chain": "ethereum" | "base" | null, + "chain": "ethereum" | "base" | "sepolia" | "bsc" | "arbitrum" | "avalanche" | "polygon" | "optimism" | "cronos" | "gnosis" | "fantom" | "klaytn" | "celo" | "moonbeam" | "aurora" | "harmonyOne" | "moonriver" | "arbitrumNova" | "mantle" | "linea" | "scroll" | "filecoin" | "taiko" | "zksync" | "canto" | null, "amount": string | null, "toAddress": string | null, "token": string | null @@ -30,8 +30,8 @@ export const bridgeTemplate = `Given the recent messages and wallet information Extract the following information about the requested token bridge: - Token symbol or address to bridge -- Source chain (ethereum or base) -- Destination chain (ethereum or base) +- Source chain +- Destination chain - Amount to bridge - Destination address (if specified) @@ -40,8 +40,8 @@ Respond with a JSON markdown block containing only the extracted values: \`\`\`json { "token": string | null, - "fromChain": "ethereum" | "base" | null, - "toChain": "ethereum" | "base" | null, + "fromChain": "ethereum" | "base" | "sepolia" | "bsc" | "arbitrum" | "avalanche" | "polygon" | "optimism" | "cronos" | "gnosis" | "fantom" | "klaytn" | "celo" | "moonbeam" | "aurora" | "harmonyOne" | "moonriver" | "arbitrumNova" | "mantle" | "linea" | "scroll" | "filecoin" | "taiko" | "zksync" | "canto" | null, + "toChain": "ethereum" | "base" | "sepolia" | "bsc" | "arbitrum" | "avalanche" | "polygon" | "optimism" | "cronos" | "gnosis" | "fantom" | "klaytn" | "celo" | "moonbeam" | "aurora" | "harmonyOne" | "moonriver" | "arbitrumNova" | "mantle" | "linea" | "scroll" | "filecoin" | "taiko" | "zksync" | "canto" | null, "amount": string | null, "toAddress": string | null } @@ -58,7 +58,7 @@ Extract the following information about the requested token swap: - Input token symbol or address (the token being sold) - Output token symbol or address (the token being bought) - Amount to swap -- Chain to execute on (ethereum or base) +- Chain to execute on Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined: @@ -67,7 +67,7 @@ Respond with a JSON markdown block containing only the extracted values. Use nul "inputToken": string | null, "outputToken": string | null, "amount": string | null, - "chain": "ethereum" | "base" | null, + "chain": "ethereum" | "base" | "sepolia" | "bsc" | "arbitrum" | "avalanche" | "polygon" | "optimism" | "cronos" | "gnosis" | "fantom" | "klaytn" | "celo" | "moonbeam" | "aurora" | "harmonyOne" | "moonriver" | "arbitrumNova" | "mantle" | "linea" | "scroll" | "filecoin" | "taiko" | "zksync" | "canto" | null, "slippage": number | null } \`\`\` diff --git a/packages/plugin-evm/src/types/index.ts b/packages/plugin-evm/src/types/index.ts index d2bfbca0ede..885f3994fce 100644 --- a/packages/plugin-evm/src/types/index.ts +++ b/packages/plugin-evm/src/types/index.ts @@ -9,7 +9,32 @@ import type { WalletClient, } from "viem"; -export type SupportedChain = "ethereum" | "base"; +export type SupportedChain = + | "ethereum" + | "base" + | "sepolia" + | "bsc" + | "arbitrum" + | "avalanche" + | "polygon" + | "optimism" + | "cronos" + | "gnosis" + | "fantom" + | "klaytn" + | "celo" + | "moonbeam" + | "aurora" + | "harmonyOne" + | "moonriver" + | "arbitrumNova" + | "mantle" + | "linea" + | "scroll" + | "filecoin" + | "taiko" + | "zksync" + | "canto"; // Transaction types export interface Transaction { @@ -87,6 +112,29 @@ export interface EvmPluginConfig { rpcUrl?: { ethereum?: string; base?: string; + sepolia?: string; + bsc?: string; + arbitrum?: string; + avalanche?: string; + polygon?: string; + optimism?: string; + cronos?: string; + gnosis?: string; + fantom?: string; + klaytn?: string; + celo?: string; + moonbeam?: string; + aurora?: string; + harmonyOne?: string; + moonriver?: string; + arbitrumNova?: string; + mantle?: string; + linea?: string; + scroll?: string; + filecoin?: string; + taiko?: string; + zksync?: string; + canto?: string; }; secrets?: { EVM_PRIVATE_KEY: string;