Skip to content

Commit b95bf03

Browse files
committed
fix: transfer action fix #735
1 parent ee0a3aa commit b95bf03

File tree

3 files changed

+77
-34
lines changed

3 files changed

+77
-34
lines changed

packages/plugin-evm/src/actions/transfer.ts

+4-10
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,14 @@ export { transferTemplate };
99
export class TransferAction {
1010
constructor(private walletProvider: WalletProvider) {}
1111

12-
async transfer(
13-
runtime: IAgentRuntime,
14-
params: TransferParams
15-
): Promise<Transaction> {
12+
async transfer(params: TransferParams): Promise<Transaction> {
1613
const walletClient = this.walletProvider.getWalletClient(
1714
params.fromChain
1815
);
19-
const [fromAddress] = await walletClient.getAddresses();
20-
21-
this.walletProvider.switchChain(params.fromChain);
2216

2317
try {
2418
const hash = await walletClient.sendTransaction({
25-
account: fromAddress,
19+
account: walletClient.account,
2620
to: params.toAddress,
2721
value: parseEther(params.amount),
2822
data: params.data as Hex,
@@ -42,7 +36,7 @@ export class TransferAction {
4236

4337
return {
4438
hash,
45-
from: fromAddress,
39+
from: walletClient.account.address,
4640
to: params.toAddress,
4741
value: parseEther(params.amount),
4842
data: params.data as Hex,
@@ -67,7 +61,7 @@ export const transferAction = {
6761
) as `0x${string}`;
6862
const walletProvider = new WalletProvider(privateKey);
6963
const action = new TransferAction(walletProvider);
70-
return action.transfer(runtime, options);
64+
return action.transfer(options);
7165
},
7266
template: transferTemplate,
7367
validate: async (runtime: IAgentRuntime) => {

packages/plugin-evm/src/providers/wallet.ts

+18-24
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
Chain,
99
HttpTransport,
1010
Account,
11+
PrivateKeyAccount,
1112
} from "viem";
1213
import * as viemChains from "viem/chains";
1314
import { privateKeyToAccount } from "viem/accounts";
@@ -17,7 +18,7 @@ import type { SupportedChain } from "../types";
1718
export class WalletProvider {
1819
private currentChain: SupportedChain = "mainnet";
1920
chains: Record<string, Chain> = { mainnet: viemChains.mainnet };
20-
account: Account;
21+
account: PrivateKeyAccount;
2122

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

39-
getPublicClient(
40-
chainName: SupportedChain
41-
): PublicClient<HttpTransport, Chain, Account | undefined> {
42-
const { publicClient } = this.createClients(chainName);
40+
getPublicClient(chainName: SupportedChain): PublicClient<HttpTransport, Chain, Account | undefined> {
41+
const transport = this.createHttpTransport(chainName);
42+
43+
const publicClient = createPublicClient({
44+
chain: this.chains[chainName],
45+
transport,
46+
})
4347
return publicClient;
4448
}
4549

46-
getWalletClient(chainName: SupportedChain): WalletClient {
47-
const { walletClient } = this.createClients(chainName);
50+
getWalletClient(chainName: SupportedChain):WalletClient {
51+
const transport = this.createHttpTransport(chainName);
52+
53+
const walletClient = createWalletClient({
54+
chain: this.chains[chainName],
55+
transport,
56+
account: this.account,
57+
})
58+
4859
return walletClient;
4960
}
5061

@@ -127,23 +138,6 @@ export class WalletProvider {
127138
return http(chain.rpcUrls.default.http[0]);
128139
};
129140

130-
private createClients = (chain: SupportedChain) => {
131-
const transport = this.createHttpTransport(chain);
132-
133-
return {
134-
chain: this.chains[chain],
135-
publicClient: createPublicClient({
136-
chain: this.chains[chain],
137-
transport,
138-
}),
139-
walletClient: createWalletClient<HttpTransport>({
140-
chain: this.chains[chain],
141-
transport,
142-
account: this.account,
143-
}),
144-
};
145-
};
146-
147141
static genChainFromName(
148142
chainName: string,
149143
customRpcUrl?: string | null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { describe, it, expect, beforeEach } from "vitest";
2+
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
3+
import { Account, Chain } from "viem";
4+
5+
import { TransferAction } from "../actions/transfer";
6+
import { WalletProvider } from "../providers/wallet";
7+
8+
describe("Transfer Action", () => {
9+
let wp: WalletProvider;
10+
11+
beforeEach(async () => {
12+
const pk = generatePrivateKey();
13+
const customChains = prepareChains();
14+
wp = new WalletProvider(pk, customChains);
15+
});
16+
describe("Constructor", () => {
17+
it("should initialize with wallet provider", () => {
18+
const ta = new TransferAction(wp);
19+
20+
expect(ta).to.toBeDefined();
21+
});
22+
});
23+
describe("Transfer", () => {
24+
let ta: TransferAction;
25+
let receiver: Account;
26+
27+
beforeEach(() => {
28+
ta = new TransferAction(wp);
29+
receiver = privateKeyToAccount(generatePrivateKey());
30+
});
31+
32+
it("throws if not enough gas", async () => {
33+
await expect(
34+
ta.transfer({
35+
fromChain: "iotexTestnet",
36+
toAddress: receiver.address,
37+
amount: "1",
38+
})
39+
).rejects.toThrow(
40+
"Transfer failed: The total cost (gas * gas fee + value) of executing this transaction exceeds the balance of the account."
41+
);
42+
});
43+
});
44+
});
45+
46+
const prepareChains = () => {
47+
let customChains: Record<string, Chain> = {};
48+
const chainNames = ["iotexTestnet"];
49+
chainNames.forEach(
50+
(chain) =>
51+
(customChains[chain] = WalletProvider.genChainFromName(chain))
52+
);
53+
54+
return customChains;
55+
};

0 commit comments

Comments
 (0)