diff --git a/packages/thirdweb/README.md b/packages/thirdweb/README.md index 56bf59556b1..45b0fb74993 100644 --- a/packages/thirdweb/README.md +++ b/packages/thirdweb/README.md @@ -60,7 +60,7 @@ const tx = contract.transaction({ }); // Step 6: execute the transaction with the wallet -const receipt = await wallet.execute(tx); +const receipt = await wallet.sendTransaction(tx); console.log("tx hash", receipt.transactionHash); diff --git a/packages/thirdweb/src/transaction/actions/estimate-gas.ts b/packages/thirdweb/src/transaction/actions/estimate-gas.ts index 6563f6724e0..3ec9946f4e4 100644 --- a/packages/thirdweb/src/transaction/actions/estimate-gas.ts +++ b/packages/thirdweb/src/transaction/actions/estimate-gas.ts @@ -1,9 +1,9 @@ import type { AbiFunction, Address } from "abitype"; import type { Transaction } from "../index.js"; -import type { IWallet } from "../../wallets/utils/wallet.js"; import { getDefaultGasOverrides } from "../../gas/fee-data.js"; import { encode } from "./encode.js"; import { formatTransactionRequest, hexToBigInt } from "viem/utils"; +import type { IWallet } from "../../wallets/interfaces/wallet.js"; export async function estimateGas< const abiFn extends AbiFunction, diff --git a/packages/thirdweb/src/transaction/actions/execute.ts b/packages/thirdweb/src/transaction/actions/execute.ts index 419a1a933cf..aa09cf16ec1 100644 --- a/packages/thirdweb/src/transaction/actions/execute.ts +++ b/packages/thirdweb/src/transaction/actions/execute.ts @@ -1,11 +1,6 @@ -import type { AbiFunction, Address } from "abitype"; +import type { AbiFunction } from "abitype"; import type { Transaction } from "../index.js"; -import type { IWallet } from "../../wallets/utils/wallet.js"; -import { getDefaultGasOverrides } from "../../gas/fee-data.js"; -import { encode } from "./encode.js"; -import { estimateGas } from "./estimate-gas.js"; -import { transactionCount } from "../../rpc/methods.js"; -import type { Hash } from "viem"; +import type { IWallet } from "../../wallets/interfaces/wallet.js"; export async function execute< const abiFn extends AbiFunction, @@ -14,39 +9,5 @@ export async function execute< if (!wallet || !wallet.address) { throw new Error("no wallet to sign with"); } - const rpcRequest = tx.client.rpc({ chainId: tx.inputs.chainId }); - - const [gasOverrides, encodedData, nextNonce, estimatedGas] = - await Promise.all([ - getDefaultGasOverrides(tx.client, tx.inputs.chainId), - encode(tx), - transactionCount(rpcRequest, wallet.address), - estimateGas(tx, wallet), - ]); - - const signedTx = await wallet.signTransaction({ - gas: estimatedGas, - to: tx.inputs.address as Address, - chainId: tx.inputs.chainId, - data: encodedData, - nonce: nextNonce, - ...gasOverrides, - }); - - // send the tx - // TODO: move into rpc/methods - const { result } = await rpcRequest({ - method: "eth_sendRawTransaction", - params: [signedTx], - }); - - tx.transactionHash = result as Hash; - - return { - transactionHash: result as Hash, - wait: async () => { - const { waitForTxReceipt } = await import("./wait-for-tx-receipt.js"); - return waitForTxReceipt(tx); - }, - }; + return wallet.sendTransaction(tx); } diff --git a/packages/thirdweb/src/transaction/actions/index.ts b/packages/thirdweb/src/transaction/actions/index.ts index 53be7791973..523b5617132 100644 --- a/packages/thirdweb/src/transaction/actions/index.ts +++ b/packages/thirdweb/src/transaction/actions/index.ts @@ -1,5 +1,4 @@ export { encode } from "./encode.js"; export { estimateGas } from "./estimate-gas.js"; -export { execute } from "./execute.js"; export { read } from "./read.js"; export { waitForTxReceipt } from "./wait-for-tx-receipt.js"; diff --git a/packages/thirdweb/src/wallets/utils/wallet.ts b/packages/thirdweb/src/wallets/interfaces/wallet.d.ts similarity index 53% rename from packages/thirdweb/src/wallets/utils/wallet.ts rename to packages/thirdweb/src/wallets/interfaces/wallet.d.ts index 98fa7d9b499..ac7bc5ccde6 100644 --- a/packages/thirdweb/src/wallets/utils/wallet.ts +++ b/packages/thirdweb/src/wallets/interfaces/wallet.d.ts @@ -1,7 +1,10 @@ +import type { Transaction } from "../../transaction/index.js"; import type { + AbiFunction, Address, Hex, SignableMessage, + TransactionReceipt, TransactionSerializable, TypedData, TypedDataDefinition, @@ -13,11 +16,22 @@ export interface IWallet { disconnect: () => Promise; // signMessage: (_message: SignableMessage) => Promise; - signTransaction: (_tx: TransactionSerializable) => Promise; - signTypedData: < + signTransaction?: (_tx: TransactionSerializable) => Promise; + signTypedData?: < const typedData extends TypedData | Record, primaryType extends keyof typedData | "EIP712Domain" = keyof typedData, >( _typedData: TypedDataDefinition, ) => Promise; + + // TX methods + sendTransaction: ( + _tx: Transaction, + ) => Promise<{ + transactionHash: Hex, + wait: () => Promise, + }>; + estimateGas: ( + _tx: Transaction, + ) => Promise; } diff --git a/packages/thirdweb/src/wallets/private-key.ts b/packages/thirdweb/src/wallets/private-key.ts index 8967f8051b8..ed1ab718dc7 100644 --- a/packages/thirdweb/src/wallets/private-key.ts +++ b/packages/thirdweb/src/wallets/private-key.ts @@ -1,4 +1,5 @@ import type { + Hash, Hex, PrivateKeyAccount, SignableMessage, @@ -6,12 +7,9 @@ import type { TypedDataDefinition, } from "viem"; import type { ThirdwebClient } from "../client/client.js"; -import type { IWallet } from "./utils/wallet.js"; -import { privateKeyToAccount } from "viem/accounts"; -import type { AbiFunction, TypedData } from "abitype"; +import type { AbiFunction, Address, TypedData } from "abitype"; import type { Transaction } from "../transaction/index.js"; -import { estimateGas } from "../transaction/actions/estimate-gas.js"; -import { execute } from "../transaction/actions/execute.js"; +import type { IWallet } from "./interfaces/wallet.js"; export function privateKeyWallet(client: ThirdwebClient) { return new PrivateKeyWallet(client); @@ -22,7 +20,6 @@ type PrivateKeyWalletConnectOptions = { }; class PrivateKeyWallet implements IWallet { - // private _client: ThirdwebClient; private account: PrivateKeyAccount | null = null; get address() { @@ -31,11 +28,12 @@ class PrivateKeyWallet implements IWallet { // eslint-disable-next-line @typescript-eslint/no-unused-vars constructor(_client: ThirdwebClient) { - // this._client = client; + // this.client = client; } public async connect(options: PrivateKeyWalletConnectOptions) { const { pkey } = options; + const { privateKeyToAccount } = await import("viem/accounts"); this.account = privateKeyToAccount(pkey as Hex); } @@ -65,18 +63,67 @@ class PrivateKeyWallet implements IWallet { // tx functions - public async estimateGas(tx: Transaction) { - if (!this.account) { + public async sendTransaction( + tx: Transaction, + ) { + if (!this.account || !this.address) { throw new Error("not connected"); } - return estimateGas(tx, this); + const rpcRequest = tx.client.rpc({ chainId: tx.inputs.chainId }); + + const [getDefaultGasOverrides, encode, transactionCount] = + await Promise.all([ + import("../gas/fee-data.js").then((m) => m.getDefaultGasOverrides), + import("../transaction/actions/encode.js").then((m) => m.encode), + import("../rpc/methods.js").then((m) => m.transactionCount), + ]); + + const [gasOverrides, encodedData, nextNonce, estimatedGas] = + await Promise.all([ + getDefaultGasOverrides(tx.client, tx.inputs.chainId), + encode(tx), + transactionCount(rpcRequest, this.address), + this.estimateGas(tx), + ]); + + const signedTx = await this.signTransaction({ + gas: estimatedGas, + to: tx.inputs.address as Address, + chainId: tx.inputs.chainId, + data: encodedData, + nonce: nextNonce, + ...gasOverrides, + }); + + // send the tx + // TODO: move into rpc/methods + const { result } = await rpcRequest({ + method: "eth_sendRawTransaction", + params: [signedTx], + }); + tx.transactionHash = result as Hash; + + return { + transactionHash: result as Hash, + wait: async () => { + const { waitForTxReceipt } = await import( + "../transaction/actions/wait-for-tx-receipt.js" + ); + return waitForTxReceipt(tx); + }, + }; } - public async execute(tx: Transaction) { + public async estimateGas( + tx: Transaction, + ): Promise { if (!this.account) { throw new Error("not connected"); } - return execute(tx, this); + const { estimateGas } = await import( + "../transaction/actions/estimate-gas.js" + ); + return estimateGas(tx, this); } public async disconnect() {