Skip to content

Commit

Permalink
fix: transfer action fix #735
Browse files Browse the repository at this point in the history
  • Loading branch information
nicky-ru committed Dec 11, 2024
1 parent ee0a3aa commit b95bf03
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 34 deletions.
14 changes: 4 additions & 10 deletions packages/plugin-evm/src/actions/transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,14 @@ export { transferTemplate };
export class TransferAction {
constructor(private walletProvider: WalletProvider) {}

async transfer(
runtime: IAgentRuntime,
params: TransferParams
): Promise<Transaction> {
async transfer(params: TransferParams): Promise<Transaction> {
const walletClient = this.walletProvider.getWalletClient(
params.fromChain
);
const [fromAddress] = await walletClient.getAddresses();

this.walletProvider.switchChain(params.fromChain);

try {
const hash = await walletClient.sendTransaction({
account: fromAddress,
account: walletClient.account,
to: params.toAddress,
value: parseEther(params.amount),
data: params.data as Hex,
Expand All @@ -42,7 +36,7 @@ export class TransferAction {

return {
hash,
from: fromAddress,
from: walletClient.account.address,
to: params.toAddress,
value: parseEther(params.amount),
data: params.data as Hex,
Expand All @@ -67,7 +61,7 @@ export const transferAction = {
) as `0x${string}`;
const walletProvider = new WalletProvider(privateKey);
const action = new TransferAction(walletProvider);
return action.transfer(runtime, options);
return action.transfer(options);
},
template: transferTemplate,
validate: async (runtime: IAgentRuntime) => {
Expand Down
42 changes: 18 additions & 24 deletions packages/plugin-evm/src/providers/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
Chain,
HttpTransport,
Account,
PrivateKeyAccount,
} from "viem";
import * as viemChains from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
Expand All @@ -17,7 +18,7 @@ import type { SupportedChain } from "../types";
export class WalletProvider {
private currentChain: SupportedChain = "mainnet";
chains: Record<string, Chain> = { mainnet: viemChains.mainnet };
account: Account;
account: PrivateKeyAccount;

constructor(privateKey: `0x${string}`, chains?: Record<string, Chain>) {
this.setAccount(privateKey);
Expand All @@ -36,15 +37,25 @@ export class WalletProvider {
return this.chains[this.currentChain];
}

getPublicClient(
chainName: SupportedChain
): PublicClient<HttpTransport, Chain, Account | undefined> {
const { publicClient } = this.createClients(chainName);
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 {
const { walletClient } = this.createClients(chainName);
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 @@ -127,23 +138,6 @@ export class WalletProvider {
return http(chain.rpcUrls.default.http[0]);
};

private createClients = (chain: SupportedChain) => {
const transport = this.createHttpTransport(chain);

return {
chain: this.chains[chain],
publicClient: createPublicClient({
chain: this.chains[chain],
transport,
}),
walletClient: createWalletClient<HttpTransport>({
chain: this.chains[chain],
transport,
account: this.account,
}),
};
};

static genChainFromName(
chainName: string,
customRpcUrl?: string | null
Expand Down
55 changes: 55 additions & 0 deletions packages/plugin-evm/src/tests/transfer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { describe, it, expect, beforeEach } from "vitest";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import { Account, Chain } from "viem";

import { TransferAction } from "../actions/transfer";
import { WalletProvider } from "../providers/wallet";

describe("Transfer Action", () => {
let wp: WalletProvider;

beforeEach(async () => {
const pk = generatePrivateKey();
const customChains = prepareChains();
wp = new WalletProvider(pk, customChains);
});
describe("Constructor", () => {
it("should initialize with wallet provider", () => {
const ta = new TransferAction(wp);

expect(ta).to.toBeDefined();
});
});
describe("Transfer", () => {
let ta: TransferAction;
let receiver: Account;

beforeEach(() => {
ta = new TransferAction(wp);
receiver = privateKeyToAccount(generatePrivateKey());
});

it("throws if not enough gas", async () => {
await expect(
ta.transfer({
fromChain: "iotexTestnet",
toAddress: receiver.address,
amount: "1",
})
).rejects.toThrow(
"Transfer failed: The total cost (gas * gas fee + value) of executing this transaction exceeds the balance of the account."
);
});
});
});

const prepareChains = () => {
let customChains: Record<string, Chain> = {};
const chainNames = ["iotexTestnet"];
chainNames.forEach(
(chain) =>
(customChains[chain] = WalletProvider.genChainFromName(chain))
);

return customChains;
};

0 comments on commit b95bf03

Please sign in to comment.