Skip to content

Commit

Permalink
fix: transfer action fix for EVM Plugin can't run any action elizaOS#735
Browse files Browse the repository at this point in the history
  • Loading branch information
nicky-ru committed Dec 11, 2024
1 parent b95bf03 commit ee43b45
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 33 deletions.
63 changes: 53 additions & 10 deletions packages/plugin-evm/src/actions/transfer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { ByteArray, parseEther, type Hex } from "viem";
import type { IAgentRuntime, Memory, State } from "@ai16z/eliza";
import { ByteArray, formatEther, parseEther, type Hex } from "viem";
import {
composeContext,
generateObjectDEPRECATED,
HandlerCallback,
ModelClass,
type IAgentRuntime,
type Memory,
type State,
} from "@ai16z/eliza";

import { WalletProvider } from "../providers/wallet";
import { initWalletProvider, WalletProvider } from "../providers/wallet";
import type { Transaction, TransferParams } from "../types";
import { transferTemplate } from "../templates";

Expand Down Expand Up @@ -54,14 +62,49 @@ export const transferAction = {
runtime: IAgentRuntime,
message: Memory,
state: State,
options: any
options: any,
callback?: HandlerCallback
) => {
const privateKey = runtime.getSetting(
"EVM_PRIVATE_KEY"
) as `0x${string}`;
const walletProvider = new WalletProvider(privateKey);
const action = new TransferAction(walletProvider);
return action.transfer(options);
try {
const walletProvider = initWalletProvider(runtime);
const action = new TransferAction(walletProvider);

const context = composeContext({
state,
template: transferTemplate,
});

const transferDetails = await generateObjectDEPRECATED({
runtime,
context,
modelClass: ModelClass.SMALL,
});

const tx = await action.transfer(transferDetails);

if (callback) {
callback({
text: `Successfully transferred ${formatEther(tx.value)} tokens to ${tx.to}\nTransaction hash: ${tx.hash}`,
content: {
success: true,
hash: tx.hash,
amount: formatEther(tx.value),
recipient: tx.to,
},
});
}

return true;
} catch (error) {
console.error("Error during token transfer:", error);
if (callback) {
callback({
text: `Error transferring tokens: ${error.message}`,
content: { error: error.message },
});
}
return false;
}
},
template: transferTemplate,
validate: async (runtime: IAgentRuntime) => {
Expand Down
35 changes: 19 additions & 16 deletions packages/plugin-evm/src/providers/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,26 @@ export class WalletProvider {
return this.chains[this.currentChain];
}

getPublicClient(chainName: SupportedChain): PublicClient<HttpTransport, Chain, Account | undefined> {
getPublicClient(
chainName: SupportedChain
): PublicClient<HttpTransport, Chain, Account | undefined> {
const transport = this.createHttpTransport(chainName);

const publicClient = createPublicClient({
chain: this.chains[chainName],
transport,
})
});
return publicClient;
}

getWalletClient(chainName: SupportedChain):WalletClient {
getWalletClient(chainName: SupportedChain): WalletClient {
const transport = this.createHttpTransport(chainName);

const walletClient = createWalletClient({
chain: this.chains[chainName],
transport,
account: this.account,
})
});

return walletClient;
}
Expand Down Expand Up @@ -191,28 +193,29 @@ const genChainsFromRuntime = (
return chains;
};

export const initWalletProvider = (runtime: IAgentRuntime) => {
const privateKey = runtime.getSetting("EVM_PRIVATE_KEY");
if (!privateKey) {
return null;
}

const chains = genChainsFromRuntime(runtime);

return new WalletProvider(privateKey as `0x${string}`, chains);
};

export const evmWalletProvider: Provider = {
async get(
runtime: IAgentRuntime,
message: Memory,
state?: State
): Promise<string | null> {
const privateKey = runtime.getSetting("EVM_PRIVATE_KEY");
if (!privateKey) {
return null;
}

const chains = genChainsFromRuntime(runtime);

try {
const walletProvider = new WalletProvider(
privateKey as `0x${string}`,
chains
);
const walletProvider = initWalletProvider(runtime);
const address = walletProvider.getAddress();
const balance = await walletProvider.getWalletBalance();
const chain = walletProvider.getCurrentChain();
return `EVM Wallet Address: ${address}\nBalance: ${balance} ETH\nChain ID: ${chain.id}, Name: ${chain.name}, Native Currency: ${chain.nativeCurrency}`;
return `EVM Wallet Address: ${address}\nBalance: ${balance} ${chain.nativeCurrency.symbol}\nChain ID: ${chain.id}, Name: ${chain.name}`;
} catch (error) {
console.error("Error in EVM wallet provider:", error);
return null;
Expand Down
12 changes: 5 additions & 7 deletions packages/plugin-evm/src/templates/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,17 @@ export const transferTemplate = `Given the recent messages and wallet informatio
{{walletInfo}}
Extract the following information about the requested transfer:
- Chain to execute on
- Amount to transfer
- Chain to execute on (like in viem/chains)
- Amount to transfer (only number without coin symbol)
- Recipient address
- Token symbol or address (if not native token)
Respond with a JSON markdown block containing only the extracted values:
\`\`\`json
{
"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
"fromChain": "ethereum" | "base" | ...,
"amount": string,
"toAddress": string
}
\`\`\`
`;
Expand Down

0 comments on commit ee43b45

Please sign in to comment.