thirdweb 5.89.0 → 5.90.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/adapters/ethers5.js +2 -0
- package/dist/cjs/adapters/ethers5.js.map +1 -1
- package/dist/cjs/chains/constants.js +17 -2
- package/dist/cjs/chains/constants.js.map +1 -1
- package/dist/cjs/contract/actions/resolve-abi.js +9 -11
- package/dist/cjs/contract/actions/resolve-abi.js.map +1 -1
- package/dist/cjs/exports/extensions/erc721.js +4 -2
- package/dist/cjs/exports/extensions/erc721.js.map +1 -1
- package/dist/cjs/exports/wallets/smart.js +2 -1
- package/dist/cjs/exports/wallets/smart.js.map +1 -1
- package/dist/cjs/extensions/erc721/read/getNFT.js +30 -7
- package/dist/cjs/extensions/erc721/read/getNFT.js.map +1 -1
- package/dist/cjs/extensions/erc721/read/getNFTs.js.map +1 -1
- package/dist/cjs/gas/fee-data.js +22 -15
- package/dist/cjs/gas/fee-data.js.map +1 -1
- package/dist/cjs/storage/download.js +16 -0
- package/dist/cjs/storage/download.js.map +1 -1
- package/dist/cjs/storage/mock.js +46 -0
- package/dist/cjs/storage/mock.js.map +1 -0
- package/dist/cjs/storage/upload/web-node.js +6 -1
- package/dist/cjs/storage/upload/web-node.js.map +1 -1
- package/dist/cjs/transaction/actions/estimate-gas-cost.js +1 -1
- package/dist/cjs/transaction/actions/estimate-gas-cost.js.map +1 -1
- package/dist/cjs/transaction/actions/to-serializable-transaction.js +3 -1
- package/dist/cjs/transaction/actions/to-serializable-transaction.js.map +1 -1
- package/dist/cjs/transaction/prepare-transaction.js +8 -0
- package/dist/cjs/transaction/prepare-transaction.js.map +1 -1
- package/dist/cjs/utils/process.js +4 -1
- package/dist/cjs/utils/process.js.map +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/wallets/manager/index.js +1 -1
- package/dist/cjs/wallets/manager/index.js.map +1 -1
- package/dist/cjs/wallets/smart/index.js +1 -0
- package/dist/cjs/wallets/smart/index.js.map +1 -1
- package/dist/cjs/wallets/smart/lib/bundler.js +75 -0
- package/dist/cjs/wallets/smart/lib/bundler.js.map +1 -1
- package/dist/cjs/wallets/smart/lib/calls.js +13 -7
- package/dist/cjs/wallets/smart/lib/calls.js.map +1 -1
- package/dist/cjs/wallets/smart/lib/userop.js +42 -17
- package/dist/cjs/wallets/smart/lib/userop.js.map +1 -1
- package/dist/esm/adapters/ethers5.js +2 -0
- package/dist/esm/adapters/ethers5.js.map +1 -1
- package/dist/esm/chains/constants.js +17 -2
- package/dist/esm/chains/constants.js.map +1 -1
- package/dist/esm/contract/actions/resolve-abi.js +9 -11
- package/dist/esm/contract/actions/resolve-abi.js.map +1 -1
- package/dist/esm/exports/extensions/erc721.js +1 -0
- package/dist/esm/exports/extensions/erc721.js.map +1 -1
- package/dist/esm/exports/wallets/smart.js +1 -1
- package/dist/esm/exports/wallets/smart.js.map +1 -1
- package/dist/esm/extensions/erc721/read/getNFT.js +30 -7
- package/dist/esm/extensions/erc721/read/getNFT.js.map +1 -1
- package/dist/esm/extensions/erc721/read/getNFTs.js.map +1 -1
- package/dist/esm/gas/fee-data.js +22 -15
- package/dist/esm/gas/fee-data.js.map +1 -1
- package/dist/esm/storage/download.js +16 -0
- package/dist/esm/storage/download.js.map +1 -1
- package/dist/esm/storage/mock.js +42 -0
- package/dist/esm/storage/mock.js.map +1 -0
- package/dist/esm/storage/upload/web-node.js +6 -1
- package/dist/esm/storage/upload/web-node.js.map +1 -1
- package/dist/esm/transaction/actions/estimate-gas-cost.js +1 -1
- package/dist/esm/transaction/actions/estimate-gas-cost.js.map +1 -1
- package/dist/esm/transaction/actions/to-serializable-transaction.js +3 -1
- package/dist/esm/transaction/actions/to-serializable-transaction.js.map +1 -1
- package/dist/esm/transaction/prepare-transaction.js +7 -0
- package/dist/esm/transaction/prepare-transaction.js.map +1 -1
- package/dist/esm/utils/process.js +3 -0
- package/dist/esm/utils/process.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/wallets/manager/index.js +1 -1
- package/dist/esm/wallets/manager/index.js.map +1 -1
- package/dist/esm/wallets/smart/index.js +1 -1
- package/dist/esm/wallets/smart/index.js.map +1 -1
- package/dist/esm/wallets/smart/lib/bundler.js +74 -0
- package/dist/esm/wallets/smart/lib/bundler.js.map +1 -1
- package/dist/esm/wallets/smart/lib/calls.js +13 -7
- package/dist/esm/wallets/smart/lib/calls.js.map +1 -1
- package/dist/esm/wallets/smart/lib/userop.js +41 -17
- package/dist/esm/wallets/smart/lib/userop.js.map +1 -1
- package/dist/types/adapters/ethers5.d.ts.map +1 -1
- package/dist/types/chains/constants.d.ts +1 -1
- package/dist/types/chains/constants.d.ts.map +1 -1
- package/dist/types/chains/types.d.ts +2 -0
- package/dist/types/chains/types.d.ts.map +1 -1
- package/dist/types/contract/actions/resolve-abi.d.ts.map +1 -1
- package/dist/types/exports/extensions/erc721.d.ts +1 -0
- package/dist/types/exports/extensions/erc721.d.ts.map +1 -1
- package/dist/types/exports/wallets/smart.d.ts +1 -1
- package/dist/types/exports/wallets/smart.d.ts.map +1 -1
- package/dist/types/extensions/erc721/read/getNFT.d.ts +19 -0
- package/dist/types/extensions/erc721/read/getNFT.d.ts.map +1 -1
- package/dist/types/extensions/erc721/read/getNFTs.d.ts +7 -0
- package/dist/types/extensions/erc721/read/getNFTs.d.ts.map +1 -1
- package/dist/types/gas/fee-data.d.ts +6 -5
- package/dist/types/gas/fee-data.d.ts.map +1 -1
- package/dist/types/storage/download.d.ts.map +1 -1
- package/dist/types/storage/mock.d.ts +11 -0
- package/dist/types/storage/mock.d.ts.map +1 -0
- package/dist/types/storage/upload/web-node.d.ts.map +1 -1
- package/dist/types/transaction/actions/to-serializable-transaction.d.ts +2 -0
- package/dist/types/transaction/actions/to-serializable-transaction.d.ts.map +1 -1
- package/dist/types/transaction/prepare-transaction.d.ts +3 -0
- package/dist/types/transaction/prepare-transaction.d.ts.map +1 -1
- package/dist/types/utils/process.d.ts +1 -0
- package/dist/types/utils/process.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/wallets/manager/index.d.ts +1 -1
- package/dist/types/wallets/manager/index.d.ts.map +1 -1
- package/dist/types/wallets/smart/index.d.ts +2 -0
- package/dist/types/wallets/smart/index.d.ts.map +1 -1
- package/dist/types/wallets/smart/lib/bundler.d.ts +30 -1
- package/dist/types/wallets/smart/lib/bundler.d.ts.map +1 -1
- package/dist/types/wallets/smart/lib/calls.d.ts.map +1 -1
- package/dist/types/wallets/smart/lib/userop.d.ts +10 -0
- package/dist/types/wallets/smart/lib/userop.d.ts.map +1 -1
- package/package.json +33 -33
- package/src/adapters/ethers5.ts +5 -1
- package/src/adapters/viem-legacy.test.ts +1 -1
- package/src/chains/constants.ts +17 -2
- package/src/chains/types.ts +3 -0
- package/src/contract/actions/resolve-abi.test.ts +3 -3
- package/src/contract/actions/resolve-abi.ts +27 -25
- package/src/exports/extensions/erc721.ts +1 -0
- package/src/exports/wallets/smart.ts +1 -0
- package/src/extensions/erc1155/customDrop1155.test.ts +3 -14
- package/src/extensions/erc1155/drop1155.test.ts +3 -14
- package/src/extensions/erc1155/token1155.test.ts +16 -109
- package/src/extensions/erc20/read/getCurrencyMetadata.test.ts +1 -1
- package/src/extensions/erc721/customDrop721.test.ts +3 -13
- package/src/extensions/erc721/drop721.test.ts +3 -13
- package/src/extensions/erc721/read/getNFT.ts +37 -7
- package/src/extensions/erc721/read/getNFTs.test.ts +1 -1
- package/src/extensions/erc721/read/getNFTs.ts +7 -0
- package/src/extensions/erc721/read/getOwnedTokenIds.test.ts +1 -1
- package/src/extensions/lens/read/resolveAddress.test.ts +1 -1
- package/src/extensions/prebuilts/deploy-vote.test.ts +1 -1
- package/src/extensions/unstoppable-domains/read/resolveAddress.test.ts +1 -1
- package/src/extensions/unstoppable-domains/read/resolveName.test.ts +1 -1
- package/src/gas/fee-data.ts +32 -19
- package/src/pay/convert/cryptoToFiat.test.ts +4 -4
- package/src/pay/convert/fiatToCrypto.test.ts +4 -4
- package/src/react/core/hooks/wallets/useConnect.test.tsx +3 -3
- package/src/react/web/ui/prebuilt/Account/balance.test.tsx +7 -13
- package/src/react/web/ui/prebuilt/Chain/icon.test.tsx +1 -1
- package/src/react/web/ui/prebuilt/NFT/description.test.tsx +1 -1
- package/src/react/web/ui/prebuilt/NFT/media.test.tsx +1 -1
- package/src/react/web/ui/prebuilt/NFT/name.test.tsx +1 -1
- package/src/react/web/ui/prebuilt/NFT/utils.test.ts +1 -1
- package/src/react/web/ui/prebuilt/Token/name.test.tsx +1 -1
- package/src/react/web/ui/prebuilt/Token/symbol.test.tsx +1 -1
- package/src/react/web/ui/prebuilt/Wallet/icon.test.tsx +1 -1
- package/src/react/web/ui/prebuilt/Wallet/name.test.tsx +1 -1
- package/src/react/web/ui/prebuilt/thirdweb/ClaimButton/ClaimButton.test.tsx +1 -1
- package/src/storage/download.test.ts +1 -1
- package/src/storage/download.ts +17 -0
- package/src/storage/mock.ts +52 -0
- package/src/storage/upload/web-node.test.ts +2 -1
- package/src/storage/upload/web-node.ts +8 -1
- package/src/transaction/actions/encode.test.ts +1 -1
- package/src/transaction/actions/estimate-gas-cost.ts +1 -1
- package/src/transaction/actions/to-serializable-transaction.ts +46 -35
- package/src/transaction/prepare-transaction.ts +11 -0
- package/src/utils/nft/fetch-token-metadata.test.ts +1 -1
- package/src/utils/process.ts +4 -0
- package/src/version.ts +1 -1
- package/src/wallets/manager/index.ts +6 -2
- package/src/wallets/smart/index.ts +1 -1
- package/src/wallets/smart/lib/bundler.ts +95 -0
- package/src/wallets/smart/lib/calls.ts +18 -9
- package/src/wallets/smart/lib/userop.ts +53 -18
- package/src/wallets/smart/smart-wallet-integration-v07.test.ts +23 -16
- package/src/wallets/smart/smart-wallet-integration.test.ts +21 -1
- package/src/wallets/smart/smart-wallet-modular.test.ts +1 -1
@@ -1,27 +1,37 @@
|
|
1
1
|
import { decodeErrorResult } from "viem";
|
2
|
+
import type { ThirdwebClient } from "../../../client/client.js";
|
3
|
+
import { getContract } from "../../../contract/contract.js";
|
2
4
|
import { parseEventLogs } from "../../../event/actions/parse-logs.js";
|
3
5
|
import { userOperationRevertReasonEvent } from "../../../extensions/erc4337/__generated__/IEntryPoint/events/UserOperationRevertReason.js";
|
4
6
|
import { postOpRevertReasonEvent } from "../../../extensions/erc4337/__generated__/IEntryPoint_v07/events/PostOpRevertReason.js";
|
7
|
+
import type { PreparedTransaction } from "../../../transaction/prepare-transaction.js";
|
5
8
|
import type { SerializableTransaction } from "../../../transaction/serialize-transaction.js";
|
6
9
|
import type { TransactionReceipt } from "../../../transaction/types.js";
|
10
|
+
import { isContractDeployed } from "../../../utils/bytecode/is-contract-deployed.js";
|
7
11
|
import { type Hex, hexToBigInt } from "../../../utils/encoding/hex.js";
|
8
12
|
import { getClientFetch } from "../../../utils/fetch.js";
|
9
13
|
import { stringify } from "../../../utils/json.js";
|
14
|
+
import { toEther } from "../../../utils/units.js";
|
15
|
+
import type { Account } from "../../interfaces/wallet.js";
|
16
|
+
import { getEntrypointFromFactory } from "../index.js";
|
10
17
|
import {
|
11
18
|
type BundlerOptions,
|
12
19
|
type EstimationResult,
|
13
20
|
type GasPriceResult,
|
14
21
|
type PmTransactionData,
|
22
|
+
type SmartWalletOptions,
|
15
23
|
type UserOperationReceipt,
|
16
24
|
type UserOperationV06,
|
17
25
|
type UserOperationV07,
|
18
26
|
formatUserOperationReceipt,
|
19
27
|
} from "../types.js";
|
28
|
+
import { predictSmartAccountAddress } from "./calls.js";
|
20
29
|
import {
|
21
30
|
ENTRYPOINT_ADDRESS_v0_6,
|
22
31
|
MANAGED_ACCOUNT_GAS_BUFFER,
|
23
32
|
getDefaultBundlerUrl,
|
24
33
|
} from "./constants.js";
|
34
|
+
import { prepareUserOp } from "./userop.js";
|
25
35
|
import { hexlifyUserOp } from "./utils.js";
|
26
36
|
|
27
37
|
/**
|
@@ -111,6 +121,91 @@ export async function estimateUserOpGas(
|
|
111
121
|
};
|
112
122
|
}
|
113
123
|
|
124
|
+
/**
|
125
|
+
* Estimate the gas cost of a user operation.
|
126
|
+
* @param args - The options for estimating the gas cost of a user operation.
|
127
|
+
* @returns The estimated gas cost of the user operation.
|
128
|
+
* @example
|
129
|
+
* ```ts
|
130
|
+
* import { estimateUserOpGasCost } from "thirdweb/wallets/smart";
|
131
|
+
*
|
132
|
+
* const gasCost = await estimateUserOpGasCost({
|
133
|
+
* transactions,
|
134
|
+
* adminAccount,
|
135
|
+
* client,
|
136
|
+
* smartWalletOptions,
|
137
|
+
* });
|
138
|
+
* ```
|
139
|
+
* @walletUtils
|
140
|
+
*/
|
141
|
+
export async function estimateUserOpGasCost(args: {
|
142
|
+
transactions: PreparedTransaction[];
|
143
|
+
adminAccount: Account;
|
144
|
+
client: ThirdwebClient;
|
145
|
+
smartWalletOptions: SmartWalletOptions;
|
146
|
+
}) {
|
147
|
+
// if factory is passed, but no entrypoint, try to resolve entrypoint from factory
|
148
|
+
if (
|
149
|
+
args.smartWalletOptions.factoryAddress &&
|
150
|
+
!args.smartWalletOptions.overrides?.entrypointAddress
|
151
|
+
) {
|
152
|
+
const entrypointAddress = await getEntrypointFromFactory(
|
153
|
+
args.smartWalletOptions.factoryAddress,
|
154
|
+
args.client,
|
155
|
+
args.smartWalletOptions.chain,
|
156
|
+
);
|
157
|
+
if (entrypointAddress) {
|
158
|
+
args.smartWalletOptions.overrides = {
|
159
|
+
...args.smartWalletOptions.overrides,
|
160
|
+
entrypointAddress,
|
161
|
+
};
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
const userOp = await prepareUserOp({
|
166
|
+
transactions: args.transactions,
|
167
|
+
adminAccount: args.adminAccount,
|
168
|
+
client: args.client,
|
169
|
+
smartWalletOptions: args.smartWalletOptions,
|
170
|
+
isDeployedOverride: await isContractDeployed(
|
171
|
+
getContract({
|
172
|
+
address: await predictSmartAccountAddress({
|
173
|
+
adminAddress: args.adminAccount.address,
|
174
|
+
factoryAddress: args.smartWalletOptions.factoryAddress,
|
175
|
+
chain: args.smartWalletOptions.chain,
|
176
|
+
client: args.client,
|
177
|
+
}),
|
178
|
+
chain: args.smartWalletOptions.chain,
|
179
|
+
client: args.client,
|
180
|
+
}),
|
181
|
+
),
|
182
|
+
});
|
183
|
+
|
184
|
+
let gasLimit = 0n;
|
185
|
+
if ("paymasterVerificationGasLimit" in userOp) {
|
186
|
+
// v0.7
|
187
|
+
gasLimit =
|
188
|
+
BigInt(userOp.paymasterVerificationGasLimit ?? 0) +
|
189
|
+
BigInt(userOp.paymasterPostOpGasLimit ?? 0) +
|
190
|
+
BigInt(userOp.verificationGasLimit ?? 0) +
|
191
|
+
BigInt(userOp.preVerificationGas ?? 0) +
|
192
|
+
BigInt(userOp.callGasLimit ?? 0);
|
193
|
+
} else {
|
194
|
+
// v0.6
|
195
|
+
gasLimit =
|
196
|
+
BigInt(userOp.verificationGasLimit ?? 0) +
|
197
|
+
BigInt(userOp.preVerificationGas ?? 0) +
|
198
|
+
BigInt(userOp.callGasLimit ?? 0);
|
199
|
+
}
|
200
|
+
|
201
|
+
const gasCost = gasLimit * (userOp.maxFeePerGas ?? 0n);
|
202
|
+
|
203
|
+
return {
|
204
|
+
ether: toEther(gasCost),
|
205
|
+
wei: gasCost,
|
206
|
+
};
|
207
|
+
}
|
208
|
+
|
114
209
|
/**
|
115
210
|
* Get the gas fees of a user operation.
|
116
211
|
* @param args - The options for getting the gas price of a user operation.
|
@@ -8,6 +8,7 @@ import { prepareContractCall } from "../../../transaction/prepare-contract-call.
|
|
8
8
|
import type { PreparedTransaction } from "../../../transaction/prepare-transaction.js";
|
9
9
|
import { readContract } from "../../../transaction/read-contract.js";
|
10
10
|
import { isHex, stringToHex } from "../../../utils/encoding/hex.js";
|
11
|
+
import { withCache } from "../../../utils/promise/withCache.js";
|
11
12
|
import type { SendTransactionOption } from "../../interfaces/wallet.js";
|
12
13
|
import { DEFAULT_ACCOUNT_FACTORY_V0_6 } from "./constants.js";
|
13
14
|
|
@@ -90,15 +91,23 @@ export async function predictAddress(args: {
|
|
90
91
|
"Account address is required to predict the smart wallet address.",
|
91
92
|
);
|
92
93
|
}
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
94
|
+
return withCache(
|
95
|
+
async () => {
|
96
|
+
const saltHex =
|
97
|
+
accountSalt && isHex(accountSalt)
|
98
|
+
? accountSalt
|
99
|
+
: stringToHex(accountSalt ?? "");
|
100
|
+
return readContract({
|
101
|
+
contract: factoryContract,
|
102
|
+
method: "function getAddress(address, bytes) returns (address)",
|
103
|
+
params: [adminAddress, saltHex],
|
104
|
+
});
|
105
|
+
},
|
106
|
+
{
|
107
|
+
cacheKey: `${args.factoryContract.chain.id}-${args.factoryContract.address}-${args.adminAddress}-${args.accountSalt}`,
|
108
|
+
cacheTime: 1000 * 60 * 60 * 24, // 1 day
|
109
|
+
},
|
110
|
+
);
|
102
111
|
}
|
103
112
|
|
104
113
|
/**
|
@@ -136,6 +136,7 @@ export async function createUnsignedUserOp(args: {
|
|
136
136
|
adminAddress: string;
|
137
137
|
sponsorGas: boolean;
|
138
138
|
waitForDeployment?: boolean;
|
139
|
+
isDeployedOverride?: boolean;
|
139
140
|
overrides?: SmartWalletOptions["overrides"];
|
140
141
|
}): Promise<UserOperationV06 | UserOperationV07> {
|
141
142
|
const {
|
@@ -146,6 +147,7 @@ export async function createUnsignedUserOp(args: {
|
|
146
147
|
overrides,
|
147
148
|
sponsorGas,
|
148
149
|
waitForDeployment = true,
|
150
|
+
isDeployedOverride,
|
149
151
|
} = args;
|
150
152
|
const chain = executeTx.chain;
|
151
153
|
const client = executeTx.client;
|
@@ -163,7 +165,11 @@ export async function createUnsignedUserOp(args: {
|
|
163
165
|
|
164
166
|
const [isDeployed, callData, callGasLimit, gasFees, nonce] =
|
165
167
|
await Promise.all([
|
166
|
-
|
168
|
+
typeof isDeployedOverride === "boolean"
|
169
|
+
? isDeployedOverride
|
170
|
+
: isContractDeployed(accountContract).then(
|
171
|
+
(isDeployed) => isDeployed || isAccountDeploying(accountContract),
|
172
|
+
),
|
167
173
|
encode(executeTx),
|
168
174
|
resolvePromisedValue(executeTx.gas),
|
169
175
|
getGasFees({
|
@@ -299,7 +305,7 @@ async function populateUserOp_v0_7(args: {
|
|
299
305
|
|
300
306
|
let factory: string | undefined;
|
301
307
|
let factoryData: Hex;
|
302
|
-
if (isDeployed
|
308
|
+
if (isDeployed) {
|
303
309
|
factoryData = "0x";
|
304
310
|
if (waitForDeployment) {
|
305
311
|
// lock until account is deployed if needed to avoid 'sender already created' errors when sending multiple transactions in parallel
|
@@ -462,7 +468,7 @@ async function populateUserOp_v0_6(args: {
|
|
462
468
|
const { chain, client } = bundlerOptions;
|
463
469
|
let initCode: Hex;
|
464
470
|
|
465
|
-
if (isDeployed
|
471
|
+
if (isDeployed) {
|
466
472
|
initCode = "0x";
|
467
473
|
if (waitForDeployment) {
|
468
474
|
// lock until account is deployed if needed to avoid 'sender already created' errors when sending multiple transactions in parallel
|
@@ -699,6 +705,33 @@ export async function createAndSignUserOp(options: {
|
|
699
705
|
client: ThirdwebClient;
|
700
706
|
smartWalletOptions: SmartWalletOptions;
|
701
707
|
waitForDeployment?: boolean;
|
708
|
+
isDeployedOverride?: boolean;
|
709
|
+
}) {
|
710
|
+
const unsignedUserOp = await prepareUserOp({
|
711
|
+
transactions: options.transactions,
|
712
|
+
adminAccount: options.adminAccount,
|
713
|
+
client: options.client,
|
714
|
+
smartWalletOptions: options.smartWalletOptions,
|
715
|
+
waitForDeployment: options.waitForDeployment,
|
716
|
+
isDeployedOverride: options.isDeployedOverride,
|
717
|
+
});
|
718
|
+
const signedUserOp = await signUserOp({
|
719
|
+
client: options.client,
|
720
|
+
chain: options.smartWalletOptions.chain,
|
721
|
+
adminAccount: options.adminAccount,
|
722
|
+
entrypointAddress: options.smartWalletOptions.overrides?.entrypointAddress,
|
723
|
+
userOp: unsignedUserOp,
|
724
|
+
});
|
725
|
+
return signedUserOp;
|
726
|
+
}
|
727
|
+
|
728
|
+
export async function prepareUserOp(options: {
|
729
|
+
transactions: PreparedTransaction[];
|
730
|
+
adminAccount: Account;
|
731
|
+
client: ThirdwebClient;
|
732
|
+
smartWalletOptions: SmartWalletOptions;
|
733
|
+
waitForDeployment?: boolean;
|
734
|
+
isDeployedOverride?: boolean;
|
702
735
|
}) {
|
703
736
|
const config = options.smartWalletOptions;
|
704
737
|
const factoryContract = getContract({
|
@@ -724,6 +757,7 @@ export async function createAndSignUserOp(options: {
|
|
724
757
|
let executeTx: PreparedTransaction;
|
725
758
|
if (options.transactions.length === 1) {
|
726
759
|
const tx = options.transactions[0] as PreparedTransaction;
|
760
|
+
// for single tx, simulate fully
|
727
761
|
const serializedTx = await toSerializableTransaction({
|
728
762
|
transaction: tx,
|
729
763
|
from: accountAddress,
|
@@ -734,13 +768,21 @@ export async function createAndSignUserOp(options: {
|
|
734
768
|
executeOverride: config.overrides?.execute,
|
735
769
|
});
|
736
770
|
} else {
|
771
|
+
// for multiple txs, we can't simulate, just encode
|
737
772
|
const serializedTxs = await Promise.all(
|
738
|
-
options.transactions.map((tx) =>
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
773
|
+
options.transactions.map(async (tx) => {
|
774
|
+
const [data, to, value] = await Promise.all([
|
775
|
+
encode(tx),
|
776
|
+
resolvePromisedValue(tx.to),
|
777
|
+
resolvePromisedValue(tx.value),
|
778
|
+
]);
|
779
|
+
return {
|
780
|
+
data,
|
781
|
+
to,
|
782
|
+
value,
|
783
|
+
chainId: tx.chain.id,
|
784
|
+
};
|
785
|
+
}),
|
744
786
|
);
|
745
787
|
executeTx = prepareBatchExecute({
|
746
788
|
accountContract,
|
@@ -749,7 +791,7 @@ export async function createAndSignUserOp(options: {
|
|
749
791
|
});
|
750
792
|
}
|
751
793
|
|
752
|
-
|
794
|
+
return createUnsignedUserOp({
|
753
795
|
transaction: executeTx,
|
754
796
|
factoryContract,
|
755
797
|
accountContract,
|
@@ -757,15 +799,8 @@ export async function createAndSignUserOp(options: {
|
|
757
799
|
sponsorGas: "sponsorGas" in config ? config.sponsorGas : config.gasless,
|
758
800
|
overrides: config.overrides,
|
759
801
|
waitForDeployment: options.waitForDeployment,
|
802
|
+
isDeployedOverride: options.isDeployedOverride,
|
760
803
|
});
|
761
|
-
const signedUserOp = await signUserOp({
|
762
|
-
client: options.client,
|
763
|
-
chain: config.chain,
|
764
|
-
adminAccount: options.adminAccount,
|
765
|
-
entrypointAddress: config.overrides?.entrypointAddress,
|
766
|
-
userOp: unsignedUserOp,
|
767
|
-
});
|
768
|
-
return signedUserOp;
|
769
804
|
}
|
770
805
|
|
771
806
|
async function waitForAccountDeployed(accountContract: ThirdwebContract) {
|
@@ -16,7 +16,6 @@ import {
|
|
16
16
|
} from "../../exports/extensions/erc4337.js";
|
17
17
|
import { claimTo } from "../../extensions/erc1155/drops/write/claimTo.js";
|
18
18
|
import { setContractURI } from "../../extensions/marketplace/__generated__/IMarketplace/write/setContractURI.js";
|
19
|
-
import { estimateGasCost } from "../../transaction/actions/estimate-gas-cost.js";
|
20
19
|
import { sendAndConfirmTransaction } from "../../transaction/actions/send-and-confirm-transaction.js";
|
21
20
|
import { sendBatchTransaction } from "../../transaction/actions/send-batch-transaction.js";
|
22
21
|
import { waitForReceipt } from "../../transaction/actions/wait-for-tx-receipt.js";
|
@@ -27,6 +26,7 @@ import { hashTypedData } from "../../utils/hashing/hashTypedData.js";
|
|
27
26
|
import { sleep } from "../../utils/sleep.js";
|
28
27
|
import type { Account, Wallet } from "../interfaces/wallet.js";
|
29
28
|
import { generateAccount } from "../utils/generateAccount.js";
|
29
|
+
import { estimateUserOpGasCost } from "./lib/bundler.js";
|
30
30
|
import { predictSmartAccountAddress } from "./lib/calls.js";
|
31
31
|
import { DEFAULT_ACCOUNT_FACTORY_V0_7 } from "./lib/constants.js";
|
32
32
|
import {
|
@@ -49,10 +49,9 @@ const contract = getContract({
|
|
49
49
|
address: "0xe2cb0eb5147b42095c2FfA6F7ec953bb0bE347D8",
|
50
50
|
});
|
51
51
|
|
52
|
-
describe.
|
52
|
+
describe.sequential(
|
53
53
|
"SmartWallet 0.7 core tests",
|
54
54
|
{
|
55
|
-
retry: 0,
|
56
55
|
timeout: 240_000,
|
57
56
|
},
|
58
57
|
() => {
|
@@ -88,6 +87,27 @@ describe.runIf(process.env.TW_SECRET_KEY)(
|
|
88
87
|
expect(predictedAddress).toEqual(smartWalletAddress);
|
89
88
|
});
|
90
89
|
|
90
|
+
it("can estimate gas cost", async () => {
|
91
|
+
const gasCost = await estimateUserOpGasCost({
|
92
|
+
transactions: [
|
93
|
+
claimTo({
|
94
|
+
contract,
|
95
|
+
quantity: 1n,
|
96
|
+
to: smartWalletAddress,
|
97
|
+
tokenId: 0n,
|
98
|
+
}),
|
99
|
+
],
|
100
|
+
adminAccount: personalAccount,
|
101
|
+
client: TEST_CLIENT,
|
102
|
+
smartWalletOptions: {
|
103
|
+
chain,
|
104
|
+
sponsorGas: true,
|
105
|
+
factoryAddress: DEFAULT_ACCOUNT_FACTORY_V0_7,
|
106
|
+
},
|
107
|
+
});
|
108
|
+
expect(gasCost.ether).not.toBe("0");
|
109
|
+
});
|
110
|
+
|
91
111
|
it("can sign a msg", async () => {
|
92
112
|
const signature = await smartAccount.signMessage({
|
93
113
|
message: "hello world",
|
@@ -203,19 +223,6 @@ describe.runIf(process.env.TW_SECRET_KEY)(
|
|
203
223
|
expect(isDeployed).toEqual(true);
|
204
224
|
});
|
205
225
|
|
206
|
-
it("can estimate a tx", async () => {
|
207
|
-
const estimates = await estimateGasCost({
|
208
|
-
transaction: claimTo({
|
209
|
-
contract,
|
210
|
-
quantity: 1n,
|
211
|
-
to: smartWalletAddress,
|
212
|
-
tokenId: 0n,
|
213
|
-
}),
|
214
|
-
account: smartAccount,
|
215
|
-
});
|
216
|
-
expect(estimates.wei.toString()).not.toBe("0");
|
217
|
-
});
|
218
|
-
|
219
226
|
it("can execute a batched tx", async () => {
|
220
227
|
const tx = await sendBatchTransaction({
|
221
228
|
account: smartAccount,
|
@@ -29,6 +29,7 @@ import { hashTypedData } from "../../utils/hashing/hashTypedData.js";
|
|
29
29
|
import { sleep } from "../../utils/sleep.js";
|
30
30
|
import type { Account, Wallet } from "../interfaces/wallet.js";
|
31
31
|
import { generateAccount } from "../utils/generateAccount.js";
|
32
|
+
import { estimateUserOpGasCost } from "./lib/bundler.js";
|
32
33
|
import { predictSmartAccountAddress } from "./lib/calls.js";
|
33
34
|
import { deploySmartAccount } from "./lib/signing.js";
|
34
35
|
import { smartWallet } from "./smart-wallet.js";
|
@@ -51,7 +52,6 @@ const factoryAddress = "0x564cf6453a1b0FF8DB603E92EA4BbD410dea45F3"; // pre 712
|
|
51
52
|
describe.runIf(process.env.TW_SECRET_KEY).sequential(
|
52
53
|
"SmartWallet core tests",
|
53
54
|
{
|
54
|
-
retry: 0,
|
55
55
|
timeout: 240_000,
|
56
56
|
},
|
57
57
|
() => {
|
@@ -75,6 +75,26 @@ describe.runIf(process.env.TW_SECRET_KEY).sequential(
|
|
75
75
|
});
|
76
76
|
});
|
77
77
|
|
78
|
+
it("can estimate gas cost", async () => {
|
79
|
+
const gasCost = await estimateUserOpGasCost({
|
80
|
+
transactions: [
|
81
|
+
claimTo({
|
82
|
+
contract,
|
83
|
+
quantity: 1n,
|
84
|
+
to: smartWalletAddress,
|
85
|
+
tokenId: 0n,
|
86
|
+
}),
|
87
|
+
],
|
88
|
+
adminAccount: personalAccount,
|
89
|
+
client: TEST_CLIENT,
|
90
|
+
smartWalletOptions: {
|
91
|
+
chain,
|
92
|
+
sponsorGas: true,
|
93
|
+
},
|
94
|
+
});
|
95
|
+
expect(gasCost.ether).not.toBe("0");
|
96
|
+
});
|
97
|
+
|
78
98
|
it("can connect", async () => {
|
79
99
|
expect(smartWalletAddress).toHaveLength(42);
|
80
100
|
const predictedAddress = await predictSmartAccountAddress({
|
@@ -28,7 +28,7 @@ const client = TEST_CLIENT;
|
|
28
28
|
const DEFAULT_FACTORY_ADDRESS = "0xB1846E893CA01c5Dcdaa40371C1e13f2e0Df5717";
|
29
29
|
const DEFAULT_VALIDATOR_ADDRESS = "0x7D3631d823e0De311DC86f580946EeF2eEC81fba";
|
30
30
|
|
31
|
-
describe.
|
31
|
+
describe.sequential(
|
32
32
|
"SmartWallet modular tests",
|
33
33
|
{
|
34
34
|
retry: 0,
|