diff --git a/.env.example b/.env.example index aa702a32ce2..67ac7897864 100644 --- a/.env.example +++ b/.env.example @@ -357,6 +357,10 @@ MORALIS_API_KEY= EVM_PRIVATE_KEY= EVM_PROVIDER_URL= +# Zilliqa +ZILLIQA_PRIVATE_KEY= +ZILLIQA_PROVIDER_URL= + # Avalanche AVALANCHE_PRIVATE_KEY= AVALANCHE_PUBLIC_KEY= diff --git a/agent/package.json b/agent/package.json index fdcb2bb03fb..6a43f08cb60 100644 --- a/agent/package.json +++ b/agent/package.json @@ -1,160 +1,161 @@ { - "name": "@elizaos/agent", - "version": "0.1.9-alpha.1", - "main": "src/index.ts", - "type": "module", - "scripts": { - "start": "node --loader ts-node/esm src/index.ts", - "dev": "node --loader ts-node/esm src/index.ts", - "check-types": "tsc --noEmit", - "test": "jest" - }, - "nodemonConfig": { - "watch": [ - "src", - "../core/dist" - ], - "ext": "ts,json", - "exec": "node --enable-source-maps --loader ts-node/esm src/index.ts" - }, - "dependencies": { - "@elizaos/adapter-supabase": "workspace:*", - "@elizaos/adapter-postgres": "workspace:*", - "@elizaos/adapter-redis": "workspace:*", - "@elizaos/adapter-sqlite": "workspace:*", - "@elizaos/adapter-pglite": "workspace:*", - "@elizaos/adapter-qdrant": "workspace:*", - "@elizaos/adapter-mongodb": "workspace:*", - "@elizaos/client-auto": "workspace:*", - "@elizaos/client-direct": "workspace:*", - "@elizaos/client-discord": "workspace:*", - "@elizaos/client-farcaster": "workspace:*", - "@elizaos/client-lens": "workspace:*", - "@elizaos/client-telegram": "workspace:*", - "@elizaos/client-twitter": "workspace:*", - "@elizaos/client-instagram": "workspace:*", - "@elizaos/client-slack": "workspace:*", - "@elizaos/client-alexa": "workspace:*", - "@elizaos/client-simsai": "workspace:*", - "@elizaos/core": "workspace:*", - "@elizaos/plugin-0g": "workspace:*", - "@elizaos/plugin-abstract": "workspace:*", - "@elizaos/plugin-agentkit": "workspace:*", - "@elizaos/plugin-aptos": "workspace:*", - "@elizaos/plugin-birdeye": "workspace:*", - "@elizaos/plugin-coingecko": "workspace:*", - "@elizaos/plugin-coinmarketcap": "workspace:*", - "@elizaos/plugin-zerion": "workspace:*", - "@elizaos/plugin-binance": "workspace:*", - "@elizaos/plugin-avail": "workspace:*", - "@elizaos/plugin-bnb": "workspace:*", - "@elizaos/plugin-bootstrap": "workspace:*", - "@elizaos/plugin-di": "workspace:*", - "@elizaos/plugin-cosmos": "workspace:*", - "@elizaos/plugin-intiface": "workspace:*", - "@elizaos/plugin-coinbase": "workspace:*", - "@elizaos/plugin-conflux": "workspace:*", - "@elizaos/plugin-evm": "workspace:*", - "@elizaos/plugin-echochambers": "workspace:*", - "@elizaos/plugin-flow": "workspace:*", - "@elizaos/plugin-gitbook": "workspace:*", - "@elizaos/plugin-story": "workspace:*", - "@elizaos/plugin-gitcoin-passport": "workspace:*", - "@elizaos/plugin-goat": "workspace:*", - "@elizaos/plugin-lensNetwork": "workspace:*", - "@elizaos/plugin-icp": "workspace:*", - "@elizaos/plugin-initia": "workspace:*", - "@elizaos/plugin-image-generation": "workspace:*", - "@elizaos/plugin-lit": "workspace:*", - "@elizaos/plugin-gelato": "workspace:*", - "@elizaos/plugin-moralis": "workspace:*", - "@elizaos/plugin-mind-network": "workspace:*", - "@elizaos/plugin-movement": "workspace:*", - "@elizaos/plugin-massa": "workspace:*", - "@elizaos/plugin-news": "workspace:*", - "@elizaos/plugin-nft-generation": "workspace:*", - "@elizaos/plugin-node": "workspace:*", - "@elizaos/plugin-quick-intel": "workspace:*", - "@elizaos/plugin-solana": "workspace:*", - "@elizaos/plugin-solana-v2": "workspace:*", - "@elizaos/plugin-injective": "workspace:*", - "@elizaos/plugin-solana-agent-kit": "workspace:*", - "@elizaos/plugin-squid-router": "workspace:*", - "@elizaos/plugin-autonome": "workspace:*", - "@elizaos/plugin-starknet": "workspace:*", - "@elizaos/plugin-stargaze": "workspace:*", - "@elizaos/plugin-giphy": "workspace:*", - "@elizaos/plugin-ton": "workspace:*", - "@elizaos/plugin-sui": "workspace:*", - "@elizaos/plugin-sgx": "workspace:*", - "@elizaos/plugin-iq6900": "workspace:*", - "@elizaos/plugin-tee": "workspace:*", - "@elizaos/plugin-tee-log": "workspace:*", - "@elizaos/plugin-tee-marlin": "workspace:*", - "@elizaos/plugin-multiversx": "workspace:*", - "@elizaos/plugin-near": "workspace:*", - "@elizaos/plugin-zksync-era": "workspace:*", - "@elizaos/plugin-twitter": "workspace:*", - "@elizaos/plugin-primus": "workspace:*", - "@elizaos/plugin-cronoszkevm": "workspace:*", - "@elizaos/plugin-cronos": "workspace:*", - "@elizaos/plugin-3d-generation": "workspace:*", - "@elizaos/plugin-fuel": "workspace:*", - "@elizaos/plugin-avalanche": "workspace:*", - "@elizaos/plugin-video-generation": "workspace:*", - "@elizaos/plugin-web-search": "workspace:*", - "@elizaos/plugin-dexscreener": "workspace:*", - "@elizaos/plugin-letzai": "workspace:*", - "@elizaos/plugin-thirdweb": "workspace:*", - "@elizaos/plugin-genlayer": "workspace:*", - "@elizaos/plugin-tee-verifiable-log": "workspace:*", - "@elizaos/plugin-depin": "workspace:*", - "@elizaos/plugin-open-weather": "workspace:*", - "@elizaos/plugin-obsidian": "workspace:*", - "@elizaos/plugin-arthera": "workspace:*", - "@elizaos/plugin-allora": "workspace:*", - "@elizaos/plugin-opacity": "workspace:*", - "@elizaos/plugin-hyperliquid": "workspace:*", - "@elizaos/plugin-akash": "workspace:*", - "@elizaos/plugin-quai": "workspace:*", - "@elizaos/plugin-lightning": "workspace:*", - "@elizaos/plugin-b2": "workspace:*", - "@elizaos/plugin-nft-collections": "workspace:*", - "@elizaos/plugin-pyth-data": "workspace:*", - "@elizaos/plugin-openai": "workspace:*", - "@elizaos/plugin-devin": "workspace:*", - "@elizaos/plugin-holdstation": "workspace:*", - "@elizaos/plugin-router-nitro": "workspace:*", - "@elizaos/plugin-nvidia-nim": "workspace:*", - "@elizaos/plugin-0x": "workspace:*", - "@elizaos/plugin-bittensor": "workspace:*", - "@elizaos/plugin-chainbase": "workspace:*", - "@elizaos/plugin-dkg": "workspace:*", - "@elizaos/plugin-email": "workspace:*", - "@elizaos/plugin-sei": "workspace:*", - "@elizaos/plugin-omniflix": "workspace:*", - "@elizaos/plugin-suno": "workspace:*", - "@elizaos/plugin-udio": "workspace:*", - "@elizaos/plugin-hyperbolic": "workspace:*", - "@elizaos/plugin-football": "workspace:*", - "@elizaos/plugin-imgflip": "workspace:*", - "@elizaos/plugin-ethstorage": "workspace:*", - "@elizaos/plugin-mina": "workspace:*", - "@elizaos/plugin-email-automation": "workspace:*", - "@elizaos/plugin-dcap": "workspace:*", - "@elizaos/plugin-form": "workspace:*", - "@elizaos/plugin-ankr": "workspace:*", - "@elizaos/client-xmtp": "workspace:*", - "@elizaos/plugin-trikon": "workspace:*", - "readline": "1.3.0", - "ws": "8.18.0", - "yargs": "17.7.2" - }, - "devDependencies": { - "@types/jest": "^29.5.14", - "jest": "^29.7.0", - "ts-jest": "^29.2.5", - "ts-node": "10.9.2", - "tsup": "8.3.5" - } + "name": "@elizaos/agent", + "version": "0.1.9-alpha.1", + "main": "src/index.ts", + "type": "module", + "scripts": { + "start": "node --loader ts-node/esm src/index.ts", + "dev": "node --loader ts-node/esm src/index.ts", + "check-types": "tsc --noEmit", + "test": "jest" + }, + "nodemonConfig": { + "watch": [ + "src", + "../core/dist" + ], + "ext": "ts,json", + "exec": "node --enable-source-maps --loader ts-node/esm src/index.ts" + }, + "dependencies": { + "@elizaos/adapter-supabase": "workspace:*", + "@elizaos/adapter-postgres": "workspace:*", + "@elizaos/adapter-redis": "workspace:*", + "@elizaos/adapter-sqlite": "workspace:*", + "@elizaos/adapter-pglite": "workspace:*", + "@elizaos/adapter-qdrant": "workspace:*", + "@elizaos/adapter-mongodb": "workspace:*", + "@elizaos/client-auto": "workspace:*", + "@elizaos/client-direct": "workspace:*", + "@elizaos/client-discord": "workspace:*", + "@elizaos/client-farcaster": "workspace:*", + "@elizaos/client-lens": "workspace:*", + "@elizaos/client-telegram": "workspace:*", + "@elizaos/client-twitter": "workspace:*", + "@elizaos/client-instagram": "workspace:*", + "@elizaos/client-slack": "workspace:*", + "@elizaos/client-alexa": "workspace:*", + "@elizaos/client-simsai": "workspace:*", + "@elizaos/core": "workspace:*", + "@elizaos/plugin-0g": "workspace:*", + "@elizaos/plugin-abstract": "workspace:*", + "@elizaos/plugin-agentkit": "workspace:*", + "@elizaos/plugin-aptos": "workspace:*", + "@elizaos/plugin-birdeye": "workspace:*", + "@elizaos/plugin-coingecko": "workspace:*", + "@elizaos/plugin-coinmarketcap": "workspace:*", + "@elizaos/plugin-zerion": "workspace:*", + "@elizaos/plugin-binance": "workspace:*", + "@elizaos/plugin-avail": "workspace:*", + "@elizaos/plugin-bnb": "workspace:*", + "@elizaos/plugin-bootstrap": "workspace:*", + "@elizaos/plugin-di": "workspace:*", + "@elizaos/plugin-cosmos": "workspace:*", + "@elizaos/plugin-intiface": "workspace:*", + "@elizaos/plugin-coinbase": "workspace:*", + "@elizaos/plugin-conflux": "workspace:*", + "@elizaos/plugin-evm": "workspace:*", + "@elizaos/plugin-echochambers": "workspace:*", + "@elizaos/plugin-flow": "workspace:*", + "@elizaos/plugin-gitbook": "workspace:*", + "@elizaos/plugin-story": "workspace:*", + "@elizaos/plugin-gitcoin-passport": "workspace:*", + "@elizaos/plugin-goat": "workspace:*", + "@elizaos/plugin-lensNetwork": "workspace:*", + "@elizaos/plugin-icp": "workspace:*", + "@elizaos/plugin-initia": "workspace:*", + "@elizaos/plugin-image-generation": "workspace:*", + "@elizaos/plugin-lit": "workspace:*", + "@elizaos/plugin-gelato": "workspace:*", + "@elizaos/plugin-moralis": "workspace:*", + "@elizaos/plugin-mind-network": "workspace:*", + "@elizaos/plugin-movement": "workspace:*", + "@elizaos/plugin-massa": "workspace:*", + "@elizaos/plugin-news": "workspace:*", + "@elizaos/plugin-nft-generation": "workspace:*", + "@elizaos/plugin-node": "workspace:*", + "@elizaos/plugin-quick-intel": "workspace:*", + "@elizaos/plugin-solana": "workspace:*", + "@elizaos/plugin-solana-v2": "workspace:*", + "@elizaos/plugin-injective": "workspace:*", + "@elizaos/plugin-solana-agent-kit": "workspace:*", + "@elizaos/plugin-squid-router": "workspace:*", + "@elizaos/plugin-autonome": "workspace:*", + "@elizaos/plugin-starknet": "workspace:*", + "@elizaos/plugin-stargaze": "workspace:*", + "@elizaos/plugin-giphy": "workspace:*", + "@elizaos/plugin-ton": "workspace:*", + "@elizaos/plugin-sui": "workspace:*", + "@elizaos/plugin-sgx": "workspace:*", + "@elizaos/plugin-iq6900": "workspace:*", + "@elizaos/plugin-tee": "workspace:*", + "@elizaos/plugin-tee-log": "workspace:*", + "@elizaos/plugin-tee-marlin": "workspace:*", + "@elizaos/plugin-multiversx": "workspace:*", + "@elizaos/plugin-near": "workspace:*", + "@elizaos/plugin-zksync-era": "workspace:*", + "@elizaos/plugin-twitter": "workspace:*", + "@elizaos/plugin-primus": "workspace:*", + "@elizaos/plugin-cronoszkevm": "workspace:*", + "@elizaos/plugin-cronos": "workspace:*", + "@elizaos/plugin-3d-generation": "workspace:*", + "@elizaos/plugin-fuel": "workspace:*", + "@elizaos/plugin-avalanche": "workspace:*", + "@elizaos/plugin-video-generation": "workspace:*", + "@elizaos/plugin-web-search": "workspace:*", + "@elizaos/plugin-dexscreener": "workspace:*", + "@elizaos/plugin-letzai": "workspace:*", + "@elizaos/plugin-thirdweb": "workspace:*", + "@elizaos/plugin-genlayer": "workspace:*", + "@elizaos/plugin-tee-verifiable-log": "workspace:*", + "@elizaos/plugin-depin": "workspace:*", + "@elizaos/plugin-open-weather": "workspace:*", + "@elizaos/plugin-obsidian": "workspace:*", + "@elizaos/plugin-arthera": "workspace:*", + "@elizaos/plugin-allora": "workspace:*", + "@elizaos/plugin-opacity": "workspace:*", + "@elizaos/plugin-hyperliquid": "workspace:*", + "@elizaos/plugin-akash": "workspace:*", + "@elizaos/plugin-quai": "workspace:*", + "@elizaos/plugin-lightning": "workspace:*", + "@elizaos/plugin-b2": "workspace:*", + "@elizaos/plugin-nft-collections": "workspace:*", + "@elizaos/plugin-pyth-data": "workspace:*", + "@elizaos/plugin-openai": "workspace:*", + "@elizaos/plugin-devin": "workspace:*", + "@elizaos/plugin-holdstation": "workspace:*", + "@elizaos/plugin-router-nitro": "workspace:*", + "@elizaos/plugin-nvidia-nim": "workspace:*", + "@elizaos/plugin-0x": "workspace:*", + "@elizaos/plugin-bittensor": "workspace:*", + "@elizaos/plugin-chainbase": "workspace:*", + "@elizaos/plugin-dkg": "workspace:*", + "@elizaos/plugin-email": "workspace:*", + "@elizaos/plugin-sei": "workspace:*", + "@elizaos/plugin-omniflix": "workspace:*", + "@elizaos/plugin-suno": "workspace:*", + "@elizaos/plugin-udio": "workspace:*", + "@elizaos/plugin-hyperbolic": "workspace:*", + "@elizaos/plugin-football": "workspace:*", + "@elizaos/plugin-imgflip": "workspace:*", + "@elizaos/plugin-ethstorage": "workspace:*", + "@elizaos/plugin-mina": "workspace:*", + "@elizaos/plugin-email-automation": "workspace:*", + "@elizaos/plugin-dcap": "workspace:*", + "@elizaos/plugin-form": "workspace:*", + "@elizaos/plugin-ankr": "workspace:*", + "@elizaos/client-xmtp": "workspace:*", + "@elizaos/plugin-trikon": "workspace:*", + "@elizaos/plugin-zilliqa": "workspace:*", + "readline": "1.3.0", + "ws": "8.18.0", + "yargs": "17.7.2" + }, + "devDependencies": { + "@types/jest": "^29.5.14", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "10.9.2", + "tsup": "8.3.5" + } } \ No newline at end of file diff --git a/agent/src/index.ts b/agent/src/index.ts index ddc7edd8208..48b22386fa0 100644 --- a/agent/src/index.ts +++ b/agent/src/index.ts @@ -52,6 +52,8 @@ import { footballPlugin } from "@elizaos/plugin-football" import { bootstrapPlugin } from "@elizaos/plugin-bootstrap" import { normalizeCharacter } from "@elizaos/plugin-di" import createGoatPlugin from "@elizaos/plugin-goat" +import createZilliqaPlugin from "@elizaos/plugin-zilliqa"; + // import { intifacePlugin } from "@elizaos/plugin-intiface"; import { ThreeDGenerationPlugin } from "@elizaos/plugin-3d-generation" import { abstractPlugin } from "@elizaos/plugin-abstract" @@ -750,6 +752,13 @@ export async function createAgent(character: Character, db: IDatabaseAdapter, ca goatPlugin = await createGoatPlugin((secret) => getSecret(character, secret)) } + let zilliqaPlugin: any | undefined; + if (getSecret(character, "ZILLIQA_PRIVATE_KEY")) { + zilliqaPlugin = await createZilliqaPlugin((secret) => + getSecret(character, secret) + ); + } + // Initialize Reclaim adapter if environment variables are present // let verifiableInferenceAdapter; // if ( @@ -846,7 +855,8 @@ export async function createAgent(character: Character, db: IDatabaseAdapter, ca getSecret(character, "ENABLE_TEE_LOG") && ((teeMode !== TEEMode.OFF && walletSecretSalt) || getSecret(character, "SGX")) ? teeLogPlugin : null, getSecret(character, "OMNIFLIX_API_URL") && getSecret(character, "OMNIFLIX_MNEMONIC") ? OmniflixPlugin : null, getSecret(character, "COINBASE_API_KEY") && getSecret(character, "COINBASE_PRIVATE_KEY") && getSecret(character, "COINBASE_NOTIFICATION_URI") ? webhookPlugin : null, - goatPlugin, + goatPlugin, + zilliqaPlugin, getSecret(character, "COINGECKO_API_KEY") || getSecret(character, "COINGECKO_PRO_API_KEY") ? coingeckoPlugin : null, getSecret(character, "MORALIS_API_KEY") ? moralisPlugin : null, getSecret(character, "EVM_PROVIDER_URL") ? goatPlugin : null, diff --git a/packages/plugin-goat/package.json b/packages/plugin-goat/package.json index a868b64ed55..718881a0f53 100644 --- a/packages/plugin-goat/package.json +++ b/packages/plugin-goat/package.json @@ -21,7 +21,7 @@ "dependencies": { "@elizaos/core": "workspace:*", "@goat-sdk/adapter-vercel-ai": "0.2.0", - "@goat-sdk/core": "0.4.0", + "@goat-sdk/core": "0.4.6", "@goat-sdk/plugin-erc20": "0.2.2", "@goat-sdk/plugin-kim": "0.1.2", "@goat-sdk/wallet-evm": "0.2.0", diff --git a/packages/plugin-zilliqa/README.md b/packages/plugin-zilliqa/README.md new file mode 100644 index 00000000000..cadde319a1c --- /dev/null +++ b/packages/plugin-zilliqa/README.md @@ -0,0 +1,50 @@ +# @elizaos/plugin-zilliqa + +A plugin for integrating Zilliqa blockchain capabilities through the GOAT (Great Onchain Agent Toolkit) framework within the ElizaOS ecosystem. + +## Description + +[GOAT](https://ohmygoat.dev/) 🐐 (Great Onchain Agent Toolkit) is an open-source framework for adding blockchain tools such as wallets, being able to hold or trade tokens, or interacting with blockchain smart contracts, to your AI agent. + +- [Chains supported](https://ohmygoat.dev/chains-wallets-plugins) +- [Plugins supported](https://ohmygoat.dev/chains-wallets-plugins) + +This plugin integrates the GOAT Zilliqa plugin and wallet with Eliza. + +## Installation + +```bash +pnpm install @elizaos/plugin-zilliqa +``` + +## Configuration + +### Environment Variables + +```typescript +EVM_PRIVATE_KEY= +EVM_PROVIDER_URL= +ENABLE_ZILLIQA=1 +``` + +## Common Issues & Troubleshooting + +1. **Agent not executing an action**: + + - If you are also using the EVM Plugin, sometimes the agent might confuse the action name with an EVM Plugin action name instead of the GOAT Plugin action. Removing the EVM Plugin should fix this issue. There is no need for you to use both plugins at the same time. + - If you are using Trump as a character it might be tricky to get them to perform any action since the character is full of prompts that aim to change the topic of the conversation. To fix this try using a different character or create your own with prompts that are more suitable to what the agent is supposed to do. + +2. **Wallet Connection Issues** + + - Verify private key is correctly formatted + - Check RPC endpoint availability + - Ensure sufficient network balance + +3. **Transaction Issues** + - Verify gas availability + - Check network congestion + - Confirm transaction parameters + +## License + +This plugin is part of the Eliza project. See the main project repository for license information. diff --git a/packages/plugin-zilliqa/package.json b/packages/plugin-zilliqa/package.json new file mode 100644 index 00000000000..54fa403ff53 --- /dev/null +++ b/packages/plugin-zilliqa/package.json @@ -0,0 +1,26 @@ +{ + "name": "@elizaos/plugin-zilliqa", + "version": "0.1.7-alpha.2", + "main": "dist/index.js", + "type": "module", + "types": "dist/index.d.ts", + "dependencies": { + "@elizaos/core": "workspace:*", + "@goat-sdk/adapter-vercel-ai": "0.2.7", + "@goat-sdk/core": "0.4.6", + "@goat-sdk/plugin-zilliqa": "0.1.3", + "@goat-sdk/wallet-evm": "0.2.6", + "@goat-sdk/wallet-viem": "0.2.6", + "@goat-sdk/wallet-zilliqa": "0.2.6", + "@zilliqa-js/account": "^3.5.0", + "@zilliqa-js/zilliqa": "^3.5.0", + "tsup": "8.3.5" + }, + "scripts": { + "build": "tsup --format esm --dts", + "dev": "tsup --format esm --dts --watch" + }, + "peerDependencies": { + "whatwg-url": "7.1.0" + } +} diff --git a/packages/plugin-zilliqa/src/actions.ts b/packages/plugin-zilliqa/src/actions.ts new file mode 100644 index 00000000000..d77a9b230d9 --- /dev/null +++ b/packages/plugin-zilliqa/src/actions.ts @@ -0,0 +1,320 @@ +import { getOnChainTools } from "@goat-sdk/adapter-vercel-ai"; +import { MODE, USDC, erc20 } from "@goat-sdk/plugin-erc20"; +import { kim } from "@goat-sdk/plugin-kim"; +import { sendETH } from "@goat-sdk/wallet-evm"; +import { WalletClientBase } from "@goat-sdk/core"; +import { zilliqa } from "@goat-sdk/plugin-zilliqa"; + +import { + generateText, + type HandlerCallback, + type IAgentRuntime, + type Memory, + ModelClass, + type State, + composeContext, + elizaLogger, +} from "@elizaos/core"; +import { Zilliqa } from "@zilliqa-js/zilliqa"; + +export async function getOnChainActions( + evmWallet: WalletClientBase, + zilliqaWallet: WalletClientBase +) { + const actionsWithoutHandler = [ + { + name: "GET_BALANCE", + description: + "Retrieve the balance of a zilliqa account using the GET_ZILLIQA_ADDRESS_BALANCE tool or an evm account using the GET_BALANCE tool. Addresses may be expressed as a hex or bech32 address", + similes: [], + validate: async () => true, + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "Tell me the balance of account 0xf0cb24ac66ba7375bf9b9c4fa91e208d9eaabd2e", + action: "GET_BALANCE", + }, + }, + { + user: "{{agentName}}", + content: { + text: "The balance of account 0xf0cb24ac66ba7375bf9b9c4fa91e208d9eaabd2e is 2.01 zil", + action: "GET_BALANCE", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Tell me the balance of the account zil17r9jftrxhfeht0umn386j83q3k0240fwn7g70g", + }, + }, + { + user: "{{agentName}}", + content: { + text: "The balance of account zil17r9jftrxhfeht0umn386j83q3k0240fwn7g70g is 18.05 zil", + action: "GET_BALANCE", + }, + }, + ], + ], + }, + { + name: "CONVERT", + description: + "Convert address formats from bech32 to hex using the CONVERT_FROM_BECH32 tool or from hex to bech32 using the CONVERT_TO_BECH32 tool. The addresses to be converted may be either evm or zilliqa", + similes: [], + validate: async () => true, + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "Convert 0xf0cb24ac66ba7375bf9b9c4fa91e208d9eaabd2e to bech32", + }, + }, + { + user: "{{agentName}}", + content: { + text: "The bech32 address for 0xf0cb24ac66ba7375bf9b9c4fa91e208d9eaabd2e is zil17r9jftrxhfeht0umn386j83q3k0240fwn7g70g", + action: "CONVERT", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Convert zil17r9jftrxhfeht0umn386j83q3k0240fwn7g70g to hex", + }, + }, + { + user: "{{agentName}}", + content: { + text: "The hex address for zil17r9jftrxhfeht0umn386j83q3k0240fwn7g70g is 0xf0cb24ac66ba7375bf9b9c4fa91e208d9eaabd2e", + action: "CONVERT", + }, + }, + ], + ], + }, + { + name: "TRANSFER", + description: + "Transfer funds from a Zilliqa address using TRANSFER_FROM_ZILLIQA_ADDRESS or from an EVM address using TRANSFER_FROM_EVM_ADDRESS. Addresses may be in either bech32 or hex format. Both kinds of transfer return the transaction id in hex.", + similes: [], + validate: async () => true, + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "Transfer 2 ZIL from the EVM address zil17r9jftrxhfeht0umn386j83q3k0240fwn7g70g to 0xf0cb24ac66ba7375bf9b9c4fa91e208d9eaabd2e", + action: "TRANSFER", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Transfer 2 ZIL from the Zilliqa address zil17r9jftrxhfeht0umn386j83q3k0240fwn7g70g to 0xf0cb24ac66ba7375bf9b9c4fa91e208d9eaabd2e", + action: "TRANSFER", + }, + }, + ], + ], + }, + // 1. Add your actions here + ]; + + const tools = await getOnChainTools({ + wallet: evmWallet, + // 2. Configure the plugins you need to perform those actions + plugins: [sendETH()], + }); + + const zilTools = await getOnChainTools({ + wallet: zilliqaWallet, + plugins: [zilliqa()], + }); + + const allTools = { ...zilTools, ...tools }; + // 3. Let GOAT handle all the actions + return actionsWithoutHandler.map((action) => ({ + ...action, + handler: getActionHandler(action.name, action.description, allTools), + })); +} + +function getActionHandler( + actionName: string, + actionDescription: string, + tools +) { + return async ( + runtime: IAgentRuntime, + message: Memory, + state: State | undefined, + options?: Record, + callback?: HandlerCallback + ): Promise => { + let currentState = state ?? (await runtime.composeState(message)); + currentState = await runtime.updateRecentMessageState(currentState); + + try { + // 1. Call the tools needed + const context = composeActionContext( + actionName, + actionDescription, + currentState + ); + const result = await generateText({ + runtime, + context, + tools, + maxSteps: 10, + // Uncomment to see the log each tool call when debugging + onStepFinish: (step) => { + console.log(step.toolResults); + }, + modelClass: ModelClass.LARGE, + }); + + // 2. Compose the response + const response = composeResponseContext(result, currentState); + const responseText = await generateResponse(runtime, response); + + callback?.({ + text: responseText, + content: {}, + }); + return true; + } catch (error) { + const errorMessage = + error instanceof Error ? error.message : String(error); + + // 3. Compose the error response + const errorResponse = composeErrorResponseContext( + errorMessage, + currentState + ); + const errorResponseText = await generateResponse( + runtime, + errorResponse + ); + + callback?.({ + text: errorResponseText, + content: { error: errorMessage }, + }); + return false; + } + }; +} + +function composeActionContext( + actionName: string, + actionDescription: string, + state: State +): string { + const actionTemplate = ` +# Knowledge +{{knowledge}} + +About {{agentName}}: +{{bio}} +{{lore}} + +{{providers}} + +{{attachments}} + + +# Action: ${actionName} +${actionDescription} + +{{recentMessages}} + +Based on the action chosen and the previous messages, execute the action and respond to the user using the tools you were given. +`; + return composeContext({ state, template: actionTemplate }); +} + +function composeResponseContext(result: unknown, state: State): string { + const responseTemplate = ` + # Action Examples +{{actionExamples}} +(Action examples are for reference only. Do not use the information from them in your response.) + +# Knowledge +{{knowledge}} + +# Task: Generate dialog and actions for the character {{agentName}}. +About {{agentName}}: +{{bio}} +{{lore}} + +{{providers}} + +{{attachments}} + +# Capabilities +Note that {{agentName}} is capable of reading/seeing/hearing various forms of media, including images, videos, audio, plaintext and PDFs. Recent attachments have been included above under the "Attachments" section. + +Here is the result: +${JSON.stringify(result)} + +{{actions}} + +Respond to the message knowing that the action was successful and these were the previous messages: +{{recentMessages}} + `; + return composeContext({ state, template: responseTemplate }); +} + +function composeErrorResponseContext( + errorMessage: string, + state: State +): string { + const errorResponseTemplate = ` +# Knowledge +{{knowledge}} + +# Task: Generate dialog and actions for the character {{agentName}}. +About {{agentName}}: +{{bio}} +{{lore}} + +{{providers}} + +{{attachments}} + +# Capabilities +Note that {{agentName}} is capable of reading/seeing/hearing various forms of media, including images, videos, audio, plaintext and PDFs. Recent attachments have been included above under the "Attachments" section. + +{{actions}} + +Respond to the message knowing that the action failed. +The error was: +${errorMessage} + +These were the previous messages: +{{recentMessages}} + `; + return composeContext({ state, template: errorResponseTemplate }); +} + +async function generateResponse( + runtime: IAgentRuntime, + context: string +): Promise { + return generateText({ + runtime, + context, + modelClass: ModelClass.SMALL, + }); +} diff --git a/packages/plugin-zilliqa/src/index.ts b/packages/plugin-zilliqa/src/index.ts new file mode 100644 index 00000000000..84e72c90f08 --- /dev/null +++ b/packages/plugin-zilliqa/src/index.ts @@ -0,0 +1,25 @@ +import type { Plugin } from "@elizaos/core"; +import { getOnChainActions } from "./actions"; +import { getZilliqaWalletClient, getWalletProviders } from "./wallet"; + +export async function zilliqaPlugin( + getSetting: (key: string) => string | undefined +): Promise { + const zilliqaWalletClient = await getZilliqaWalletClient(getSetting); + if (!zilliqaWalletClient) { + throw new Error("Zilliqa wallet client initialization failed. Ensure that ZILLIQA_PRIVATE_KEY and ZILLIQA_PROVIDER_URL are configured."); + } + const walletClient = zilliqaWalletClient!.getEVM(); + const actions = await getOnChainActions(walletClient, zilliqaWalletClient!); + + return { + name: "[ZILLIQA] Onchain Actions", + description: "Zilliqa integration plugin", + providers: getWalletProviders(walletClient, zilliqaWalletClient), + evaluators: [], + services: [], + actions: actions, + }; +} + +export default zilliqaPlugin; diff --git a/packages/plugin-zilliqa/src/wallet.ts b/packages/plugin-zilliqa/src/wallet.ts new file mode 100644 index 00000000000..47fcf7b6941 --- /dev/null +++ b/packages/plugin-zilliqa/src/wallet.ts @@ -0,0 +1,85 @@ +import { WalletClientBase } from "@goat-sdk/core"; +import { viem, type Chain } from "@goat-sdk/wallet-viem"; +import { createWalletClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { mode } from "viem/chains"; +import { + zilliqaChainId, + zilliqaJSViemWalletClient, + ZilliqaWalletClient +} from "@goat-sdk/wallet-zilliqa"; +import { Account } from "@zilliqa-js/zilliqa"; + +// Add the chain you want to use, remember to update also +// the ZILLIQA_PROVIDER_URL to the correct one for the chain +export const chain = mode; + +function getViemChain(provider: string, id: number, decimals: number): Chain { + return { + id: id | 0x8000, + name: "zilliqa", + nativeCurrency: { + decimals: decimals, + name: "Zil", + symbol: "ZIL", + }, + rpcUrls: { + default: { + https: [provider], + }, + }, + }; +} + +export async function getZilliqaWalletClient( + getSetting: (key: string) => string | undefined +) { + const privateKey = getSetting("ZILLIQA_PRIVATE_KEY"); + if (!privateKey) return null; + + const provider = getSetting("ZILLIQA_PROVIDER_URL"); + if (!provider) throw new Error("ZILLIQA_PROVIDER_URL not configured"); + + const chainId = await zilliqaChainId(provider); + const account = new Account(privateKey); + const viemChain = getViemChain(provider, chainId, 18); + const viemWallet = createWalletClient({ + account: privateKeyToAccount(privateKey as `0x${string}`), + chain: viemChain, + transport: http(provider), + }); + + return zilliqaJSViemWalletClient(viemWallet, provider, account, chainId); +} + +export function getWalletProviders( + walletClient: WalletClientBase, + zilliqa: ZilliqaWalletClient +) { + return [ + { + async get(): Promise { + try { + const address = walletClient.getAddress(); + const balance = await walletClient.balanceOf(address); + return `EVM Wallet Address: ${address}\nBalance: ${balance} ZIL`; + } catch (error) { + console.error("Error in EVM wallet provider:", error); + return null; + } + }, + }, + { + async get(): Promise { + try { + const address = + zilliqa.getZilliqa().wallet.defaultAccount?.address; + return `Zilliqa wallet address: ${address}\n`; + } catch (error) { + console.error("Error in zilliqa wallet provider:", error); + return null; + } + }, + }, + ]; +} diff --git a/packages/plugin-zilliqa/tsconfig.json b/packages/plugin-zilliqa/tsconfig.json new file mode 100644 index 00000000000..f642a90aee1 --- /dev/null +++ b/packages/plugin-zilliqa/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../core/tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "./src", + "declaration": true + }, + "include": ["src"] +} diff --git a/packages/plugin-zilliqa/tsup.config.ts b/packages/plugin-zilliqa/tsup.config.ts new file mode 100644 index 00000000000..5385e92cf89 --- /dev/null +++ b/packages/plugin-zilliqa/tsup.config.ts @@ -0,0 +1,22 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + outDir: "dist", + sourcemap: true, + clean: true, + format: ["esm"], // Ensure you're targeting CommonJS + external: [ + "dotenv", // Externalize dotenv to prevent bundling + "crypto", // Externalize crypto to use Node.js built-in module + "fs", // Externalize fs to use Node.js built-in module + "path", // Externalize other built-ins if necessary + "@reflink/reflink", + "@node-llama-cpp", + "https", + "http", + "agentkeepalive", + "viem", + "@lifi/sdk", + ], +});