Skip to content

Commit e4d243e

Browse files
authored
fix(adapters): sendTransaction within viemAdapter.walletClient.toViem() (#2662)
1 parent 421ffa0 commit e4d243e

File tree

7 files changed

+51
-68
lines changed

7 files changed

+51
-68
lines changed

.changeset/selfish-trainers-jam.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
fix `sendTransaction` within `viemAdapter.walletClient.toViem()`

packages/thirdweb/src/adapters/ethers6.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as ethers6 from "ethers6";
33
import { privateKeyAccount } from "../wallets/private-key.js";
44
import { TEST_CLIENT } from "../../test/src/test-clients.js";
55
import { toEthersSigner } from "./ethers6.js";
6-
import { defineChain } from "../chains/utils.js";
6+
import { ANVIL_CHAIN } from "../../test/src/chains.js";
77

88
const FAKE_PKEY =
99
"0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
@@ -19,7 +19,7 @@ describe("toEthersSigner", () => {
1919
ethers6,
2020
TEST_CLIENT,
2121
account,
22-
defineChain(31337),
22+
ANVIL_CHAIN,
2323
);
2424
expect(signer).toBeDefined();
2525
expect(signer.signMessage).toBeDefined();
@@ -30,7 +30,7 @@ describe("toEthersSigner", () => {
3030
ethers6,
3131
TEST_CLIENT,
3232
account,
33-
defineChain(31337),
33+
ANVIL_CHAIN,
3434
);
3535
expect(signer.signTypedData).toBeDefined();
3636

packages/thirdweb/src/adapters/viem.test.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@ import { describe, test, expect, beforeAll } from "vitest";
22
import { privateKeyAccount } from "../wallets/private-key.js";
33
import { TEST_CLIENT } from "../../test/src/test-clients.js";
44
import { viemAdapter } from "./viem.js";
5-
import { defineChain } from "../chains/utils.js";
6-
import type { WalletClient } from "viem";
5+
import { zeroAddress } from "viem";
76

87
import { typedData } from "~test/typed-data.js";
98
import { ANVIL_PKEY_A } from "~test/test-wallets.js";
9+
import { ANVIL_CHAIN } from "../../test/src/chains.js";
1010

1111
const account = privateKeyAccount({
1212
privateKey: ANVIL_PKEY_A,
1313
client: TEST_CLIENT,
1414
});
1515

1616
describe("walletClient.toViem", () => {
17-
let walletClient: WalletClient;
17+
let walletClient: ReturnType<typeof viemAdapter.walletClient.toViem>;
1818

1919
beforeAll(() => {
2020
walletClient = viemAdapter.walletClient.toViem({
2121
client: TEST_CLIENT,
2222
account,
23-
chain: defineChain(31337),
23+
chain: ANVIL_CHAIN,
2424
});
2525
});
2626

@@ -47,7 +47,19 @@ describe("walletClient.toViem", () => {
4747
);
4848
});
4949

50-
test("should contain a local account", async () => {
51-
expect(walletClient.account?.type).toBe("local");
50+
test("should contain a json-rpc account", async () => {
51+
expect(walletClient.account?.type).toBe("json-rpc");
52+
});
53+
54+
test("should send a transaction", async () => {
55+
if (!walletClient.account) {
56+
throw new Error("Account not found");
57+
}
58+
const txHash = await walletClient.sendTransaction({
59+
to: zeroAddress,
60+
value: 0n,
61+
});
62+
expect(txHash).toBeDefined();
63+
expect(txHash.slice(0, 2)).toBe("0x");
5264
});
5365
});

packages/thirdweb/src/adapters/viem.ts

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@ import {
44
type GetContractReturnType,
55
type PublicClient,
66
type Chain as ViemChain,
7-
type Account as ViemAccount,
87
type WalletClient,
98
createWalletClient,
109
custom,
1110
type TransactionSerializableEIP1559,
1211
} from "viem";
1312
import { getContract, type ThirdwebContract } from "../contract/contract.js";
14-
import type { Abi, Address } from "abitype";
13+
import type { Abi } from "abitype";
1514
import type { Chain } from "../chains/types.js";
1615
import type { ThirdwebClient } from "../client/client.js";
1716
import { resolveContractAbi } from "../contract/actions/resolve-abi.js";
1817
import { getRpcUrlForChain } from "../chains/utils.js";
19-
import { type Account, getAccountKey } from "../wallets/interfaces/wallet.js";
18+
import type { Account } from "../wallets/interfaces/wallet.js";
2019
import { getRpcClient } from "../rpc/rpc.js";
21-
import { secp256k1 } from "@noble/curves/secp256k1";
22-
import { toHex } from "../utils/encoding/hex.js";
20+
import { sendTransaction } from "../transaction/actions/send-transaction.js";
21+
import { prepareTransaction } from "../transaction/prepare-transaction.js";
22+
import { estimateGas } from "../transaction/actions/estimate-gas.js";
2323

2424
export const viemAdapter = {
2525
contract: {
@@ -170,7 +170,7 @@ type ToViemWalletClientOptions = {
170170
chain: Chain;
171171
};
172172

173-
function toViemWalletClient(options: ToViemWalletClientOptions): WalletClient {
173+
function toViemWalletClient(options: ToViemWalletClientOptions) {
174174
const { account, chain, client } = options;
175175
if (!account) {
176176
throw new Error("Wallet not connected.");
@@ -194,13 +194,25 @@ function toViemWalletClient(options: ToViemWalletClientOptions): WalletClient {
194194
const transport = custom({
195195
request: async (request) => {
196196
if (request.method === "eth_sendTransaction") {
197-
const result = await account.sendTransaction(request.params[0]);
197+
const result = await sendTransaction({
198+
transaction: prepareTransaction({
199+
...request.params[0],
200+
chain,
201+
client,
202+
}),
203+
account: account,
204+
});
198205
return result.transactionHash;
199206
}
200207
if (request.method === "eth_estimateGas") {
201-
if (account.estimateGas) {
202-
return account.estimateGas(request.params[0]);
203-
}
208+
return estimateGas({
209+
transaction: prepareTransaction({
210+
...request.params[0],
211+
chain,
212+
client,
213+
}),
214+
account: account,
215+
});
204216
}
205217
if (request.method === "personal_sign") {
206218
return account.signMessage({
@@ -217,26 +229,9 @@ function toViemWalletClient(options: ToViemWalletClientOptions): WalletClient {
217229
},
218230
});
219231

220-
// viem defaults to JsonRpcAccounts so we pass the whole account if it's locally generated
221-
let viemAccountOrAddress: ViemAccount | Address;
222-
const possibleAccountKey = getAccountKey(account);
223-
if (possibleAccountKey && account.signTransaction) {
224-
viemAccountOrAddress = {
225-
...account,
226-
signTransaction: account.signTransaction,
227-
source: "custom",
228-
type: "local" as const,
229-
publicKey: toHex(
230-
secp256k1.getPublicKey(possibleAccountKey.slice(2), false),
231-
),
232-
};
233-
} else {
234-
viemAccountOrAddress = account.address;
235-
}
236-
237232
return createWalletClient({
238233
transport,
239-
account: viemAccountOrAddress,
234+
account: account.address,
240235
chain: viemChain,
241236
key: "thirdweb-wallet",
242237
});

packages/thirdweb/src/wallets/interfaces/wallet.ts

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,6 @@ export type Wallet<TWalletId extends WalletId = WalletId> = {
4242
getConfig: () => CreateWalletArgs<TWalletId>[1];
4343
};
4444

45-
// Symbols to track account key internally for downstream adapters
46-
// eslint-disable-next-line better-tree-shaking/no-top-level-side-effects
47-
const accountKeySymbol: unique symbol = Symbol("key");
48-
49-
/**
50-
* @internal
51-
*/
52-
export function getAccountKey(account: Account): Hex | undefined {
53-
return account[accountKeySymbol];
54-
}
55-
56-
/**
57-
* @internal
58-
*/
59-
export function setAccountKey(account: Account, key: Hex) {
60-
account[accountKeySymbol] = key;
61-
}
62-
6345
export type Account = {
6446
// REQUIRED
6547
address: Address;
@@ -80,13 +62,4 @@ export type Account = {
8062
sendBatchTransaction?: (
8163
txs: SendTransactionOption[],
8264
) => Promise<SendTransactionResult>;
83-
} & (
84-
| {
85-
// if a private key account, signTransaction will be defined and an accountKeySymbol assigned
86-
signTransaction: (tx: TransactionSerializable) => Promise<Hex>;
87-
[accountKeySymbol]: Hex;
88-
}
89-
| {
90-
[accountKeySymbol]?: never;
91-
}
92-
);
65+
};

packages/thirdweb/src/wallets/private-key.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ test("default", () => {
1515
"signMessage": [Function],
1616
"signTransaction": [Function],
1717
"signTypedData": [Function],
18-
Symbol(key): "${ANVIL_PKEY_A}",
1918
}
2019
`);
2120
});

packages/thirdweb/src/wallets/private-key.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { ThirdwebClient } from "../client/client.js";
99
import { defineChain } from "../chains/utils.js";
1010
import { getRpcClient } from "../rpc/rpc.js";
1111
import { eth_sendRawTransaction } from "../rpc/actions/eth_sendRawTransaction.js";
12-
import { setAccountKey, type Account } from "./interfaces/wallet.js";
12+
import type { Account } from "./interfaces/wallet.js";
1313
import { toHex, type Hex } from "../utils/encoding/hex.js";
1414
import { secp256k1 } from "@noble/curves/secp256k1";
1515
import { signTransaction } from "../transaction/actions/sign-transaction.js";
@@ -119,6 +119,5 @@ export function privateKeyAccount(options: PrivateKeyAccountOptions): Account {
119119
},
120120
};
121121

122-
setAccountKey(account, privateKey);
123122
return account satisfies Account;
124123
}

0 commit comments

Comments
 (0)