Skip to content

Commit 0eb7471

Browse files
committed
fix: transfer action fix elizaOS#735
1 parent f96fbf5 commit 0eb7471

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
@@ -10,6 +10,7 @@ import {
1010
type HttpTransport,
1111
type Address,
1212
Account,
13+
PrivateKeyAccount,
1314
} from "viem";
1415
import * as viemChains from "viem/chains";
1516
import { privateKeyToAccount } from "viem/accounts";
@@ -19,7 +20,7 @@ import type { SupportedChain } from "../types";
1920
export class WalletProvider {
2021
private currentChain: SupportedChain = "mainnet";
2122
chains: Record<string, Chain> = { mainnet: viemChains.mainnet };
22-
account: Account;
23+
account: PrivateKeyAccount;
2324

2425
constructor(privateKey: `0x${string}`, chains?: Record<string, Chain>) {
2526
this.setAccount(privateKey);
@@ -38,15 +39,25 @@ export class WalletProvider {
3839
return this.chains[this.currentChain];
3940
}
4041

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

48-
getWalletClient(chainName: SupportedChain): WalletClient {
49-
const { walletClient } = this.createClients(chainName);
52+
getWalletClient(chainName: SupportedChain):WalletClient {
53+
const transport = this.createHttpTransport(chainName);
54+
55+
const walletClient = createWalletClient({
56+
chain: this.chains[chainName],
57+
transport,
58+
account: this.account,
59+
})
60+
5061
return walletClient;
5162
}
5263

@@ -129,23 +140,6 @@ export class WalletProvider {
129140
return http(chain.rpcUrls.default.http[0]);
130141
};
131142

132-
private createClients = (chain: SupportedChain) => {
133-
const transport = this.createHttpTransport(chain);
134-
135-
return {
136-
chain: this.chains[chain],
137-
publicClient: createPublicClient({
138-
chain: this.chains[chain],
139-
transport,
140-
}),
141-
walletClient: createWalletClient<HttpTransport>({
142-
chain: this.chains[chain],
143-
transport,
144-
account: this.account,
145-
}),
146-
};
147-
};
148-
149143
static genChainFromName(
150144
chainName: string,
151145
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)