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.
Files changed (174) hide show
  1. package/dist/cjs/adapters/ethers5.js +2 -0
  2. package/dist/cjs/adapters/ethers5.js.map +1 -1
  3. package/dist/cjs/chains/constants.js +17 -2
  4. package/dist/cjs/chains/constants.js.map +1 -1
  5. package/dist/cjs/contract/actions/resolve-abi.js +9 -11
  6. package/dist/cjs/contract/actions/resolve-abi.js.map +1 -1
  7. package/dist/cjs/exports/extensions/erc721.js +4 -2
  8. package/dist/cjs/exports/extensions/erc721.js.map +1 -1
  9. package/dist/cjs/exports/wallets/smart.js +2 -1
  10. package/dist/cjs/exports/wallets/smart.js.map +1 -1
  11. package/dist/cjs/extensions/erc721/read/getNFT.js +30 -7
  12. package/dist/cjs/extensions/erc721/read/getNFT.js.map +1 -1
  13. package/dist/cjs/extensions/erc721/read/getNFTs.js.map +1 -1
  14. package/dist/cjs/gas/fee-data.js +22 -15
  15. package/dist/cjs/gas/fee-data.js.map +1 -1
  16. package/dist/cjs/storage/download.js +16 -0
  17. package/dist/cjs/storage/download.js.map +1 -1
  18. package/dist/cjs/storage/mock.js +46 -0
  19. package/dist/cjs/storage/mock.js.map +1 -0
  20. package/dist/cjs/storage/upload/web-node.js +6 -1
  21. package/dist/cjs/storage/upload/web-node.js.map +1 -1
  22. package/dist/cjs/transaction/actions/estimate-gas-cost.js +1 -1
  23. package/dist/cjs/transaction/actions/estimate-gas-cost.js.map +1 -1
  24. package/dist/cjs/transaction/actions/to-serializable-transaction.js +3 -1
  25. package/dist/cjs/transaction/actions/to-serializable-transaction.js.map +1 -1
  26. package/dist/cjs/transaction/prepare-transaction.js +8 -0
  27. package/dist/cjs/transaction/prepare-transaction.js.map +1 -1
  28. package/dist/cjs/utils/process.js +4 -1
  29. package/dist/cjs/utils/process.js.map +1 -1
  30. package/dist/cjs/version.js +1 -1
  31. package/dist/cjs/wallets/manager/index.js +1 -1
  32. package/dist/cjs/wallets/manager/index.js.map +1 -1
  33. package/dist/cjs/wallets/smart/index.js +1 -0
  34. package/dist/cjs/wallets/smart/index.js.map +1 -1
  35. package/dist/cjs/wallets/smart/lib/bundler.js +75 -0
  36. package/dist/cjs/wallets/smart/lib/bundler.js.map +1 -1
  37. package/dist/cjs/wallets/smart/lib/calls.js +13 -7
  38. package/dist/cjs/wallets/smart/lib/calls.js.map +1 -1
  39. package/dist/cjs/wallets/smart/lib/userop.js +42 -17
  40. package/dist/cjs/wallets/smart/lib/userop.js.map +1 -1
  41. package/dist/esm/adapters/ethers5.js +2 -0
  42. package/dist/esm/adapters/ethers5.js.map +1 -1
  43. package/dist/esm/chains/constants.js +17 -2
  44. package/dist/esm/chains/constants.js.map +1 -1
  45. package/dist/esm/contract/actions/resolve-abi.js +9 -11
  46. package/dist/esm/contract/actions/resolve-abi.js.map +1 -1
  47. package/dist/esm/exports/extensions/erc721.js +1 -0
  48. package/dist/esm/exports/extensions/erc721.js.map +1 -1
  49. package/dist/esm/exports/wallets/smart.js +1 -1
  50. package/dist/esm/exports/wallets/smart.js.map +1 -1
  51. package/dist/esm/extensions/erc721/read/getNFT.js +30 -7
  52. package/dist/esm/extensions/erc721/read/getNFT.js.map +1 -1
  53. package/dist/esm/extensions/erc721/read/getNFTs.js.map +1 -1
  54. package/dist/esm/gas/fee-data.js +22 -15
  55. package/dist/esm/gas/fee-data.js.map +1 -1
  56. package/dist/esm/storage/download.js +16 -0
  57. package/dist/esm/storage/download.js.map +1 -1
  58. package/dist/esm/storage/mock.js +42 -0
  59. package/dist/esm/storage/mock.js.map +1 -0
  60. package/dist/esm/storage/upload/web-node.js +6 -1
  61. package/dist/esm/storage/upload/web-node.js.map +1 -1
  62. package/dist/esm/transaction/actions/estimate-gas-cost.js +1 -1
  63. package/dist/esm/transaction/actions/estimate-gas-cost.js.map +1 -1
  64. package/dist/esm/transaction/actions/to-serializable-transaction.js +3 -1
  65. package/dist/esm/transaction/actions/to-serializable-transaction.js.map +1 -1
  66. package/dist/esm/transaction/prepare-transaction.js +7 -0
  67. package/dist/esm/transaction/prepare-transaction.js.map +1 -1
  68. package/dist/esm/utils/process.js +3 -0
  69. package/dist/esm/utils/process.js.map +1 -1
  70. package/dist/esm/version.js +1 -1
  71. package/dist/esm/wallets/manager/index.js +1 -1
  72. package/dist/esm/wallets/manager/index.js.map +1 -1
  73. package/dist/esm/wallets/smart/index.js +1 -1
  74. package/dist/esm/wallets/smart/index.js.map +1 -1
  75. package/dist/esm/wallets/smart/lib/bundler.js +74 -0
  76. package/dist/esm/wallets/smart/lib/bundler.js.map +1 -1
  77. package/dist/esm/wallets/smart/lib/calls.js +13 -7
  78. package/dist/esm/wallets/smart/lib/calls.js.map +1 -1
  79. package/dist/esm/wallets/smart/lib/userop.js +41 -17
  80. package/dist/esm/wallets/smart/lib/userop.js.map +1 -1
  81. package/dist/types/adapters/ethers5.d.ts.map +1 -1
  82. package/dist/types/chains/constants.d.ts +1 -1
  83. package/dist/types/chains/constants.d.ts.map +1 -1
  84. package/dist/types/chains/types.d.ts +2 -0
  85. package/dist/types/chains/types.d.ts.map +1 -1
  86. package/dist/types/contract/actions/resolve-abi.d.ts.map +1 -1
  87. package/dist/types/exports/extensions/erc721.d.ts +1 -0
  88. package/dist/types/exports/extensions/erc721.d.ts.map +1 -1
  89. package/dist/types/exports/wallets/smart.d.ts +1 -1
  90. package/dist/types/exports/wallets/smart.d.ts.map +1 -1
  91. package/dist/types/extensions/erc721/read/getNFT.d.ts +19 -0
  92. package/dist/types/extensions/erc721/read/getNFT.d.ts.map +1 -1
  93. package/dist/types/extensions/erc721/read/getNFTs.d.ts +7 -0
  94. package/dist/types/extensions/erc721/read/getNFTs.d.ts.map +1 -1
  95. package/dist/types/gas/fee-data.d.ts +6 -5
  96. package/dist/types/gas/fee-data.d.ts.map +1 -1
  97. package/dist/types/storage/download.d.ts.map +1 -1
  98. package/dist/types/storage/mock.d.ts +11 -0
  99. package/dist/types/storage/mock.d.ts.map +1 -0
  100. package/dist/types/storage/upload/web-node.d.ts.map +1 -1
  101. package/dist/types/transaction/actions/to-serializable-transaction.d.ts +2 -0
  102. package/dist/types/transaction/actions/to-serializable-transaction.d.ts.map +1 -1
  103. package/dist/types/transaction/prepare-transaction.d.ts +3 -0
  104. package/dist/types/transaction/prepare-transaction.d.ts.map +1 -1
  105. package/dist/types/utils/process.d.ts +1 -0
  106. package/dist/types/utils/process.d.ts.map +1 -1
  107. package/dist/types/version.d.ts +1 -1
  108. package/dist/types/wallets/manager/index.d.ts +1 -1
  109. package/dist/types/wallets/manager/index.d.ts.map +1 -1
  110. package/dist/types/wallets/smart/index.d.ts +2 -0
  111. package/dist/types/wallets/smart/index.d.ts.map +1 -1
  112. package/dist/types/wallets/smart/lib/bundler.d.ts +30 -1
  113. package/dist/types/wallets/smart/lib/bundler.d.ts.map +1 -1
  114. package/dist/types/wallets/smart/lib/calls.d.ts.map +1 -1
  115. package/dist/types/wallets/smart/lib/userop.d.ts +10 -0
  116. package/dist/types/wallets/smart/lib/userop.d.ts.map +1 -1
  117. package/package.json +33 -33
  118. package/src/adapters/ethers5.ts +5 -1
  119. package/src/adapters/viem-legacy.test.ts +1 -1
  120. package/src/chains/constants.ts +17 -2
  121. package/src/chains/types.ts +3 -0
  122. package/src/contract/actions/resolve-abi.test.ts +3 -3
  123. package/src/contract/actions/resolve-abi.ts +27 -25
  124. package/src/exports/extensions/erc721.ts +1 -0
  125. package/src/exports/wallets/smart.ts +1 -0
  126. package/src/extensions/erc1155/customDrop1155.test.ts +3 -14
  127. package/src/extensions/erc1155/drop1155.test.ts +3 -14
  128. package/src/extensions/erc1155/token1155.test.ts +16 -109
  129. package/src/extensions/erc20/read/getCurrencyMetadata.test.ts +1 -1
  130. package/src/extensions/erc721/customDrop721.test.ts +3 -13
  131. package/src/extensions/erc721/drop721.test.ts +3 -13
  132. package/src/extensions/erc721/read/getNFT.ts +37 -7
  133. package/src/extensions/erc721/read/getNFTs.test.ts +1 -1
  134. package/src/extensions/erc721/read/getNFTs.ts +7 -0
  135. package/src/extensions/erc721/read/getOwnedTokenIds.test.ts +1 -1
  136. package/src/extensions/lens/read/resolveAddress.test.ts +1 -1
  137. package/src/extensions/prebuilts/deploy-vote.test.ts +1 -1
  138. package/src/extensions/unstoppable-domains/read/resolveAddress.test.ts +1 -1
  139. package/src/extensions/unstoppable-domains/read/resolveName.test.ts +1 -1
  140. package/src/gas/fee-data.ts +32 -19
  141. package/src/pay/convert/cryptoToFiat.test.ts +4 -4
  142. package/src/pay/convert/fiatToCrypto.test.ts +4 -4
  143. package/src/react/core/hooks/wallets/useConnect.test.tsx +3 -3
  144. package/src/react/web/ui/prebuilt/Account/balance.test.tsx +7 -13
  145. package/src/react/web/ui/prebuilt/Chain/icon.test.tsx +1 -1
  146. package/src/react/web/ui/prebuilt/NFT/description.test.tsx +1 -1
  147. package/src/react/web/ui/prebuilt/NFT/media.test.tsx +1 -1
  148. package/src/react/web/ui/prebuilt/NFT/name.test.tsx +1 -1
  149. package/src/react/web/ui/prebuilt/NFT/utils.test.ts +1 -1
  150. package/src/react/web/ui/prebuilt/Token/name.test.tsx +1 -1
  151. package/src/react/web/ui/prebuilt/Token/symbol.test.tsx +1 -1
  152. package/src/react/web/ui/prebuilt/Wallet/icon.test.tsx +1 -1
  153. package/src/react/web/ui/prebuilt/Wallet/name.test.tsx +1 -1
  154. package/src/react/web/ui/prebuilt/thirdweb/ClaimButton/ClaimButton.test.tsx +1 -1
  155. package/src/storage/download.test.ts +1 -1
  156. package/src/storage/download.ts +17 -0
  157. package/src/storage/mock.ts +52 -0
  158. package/src/storage/upload/web-node.test.ts +2 -1
  159. package/src/storage/upload/web-node.ts +8 -1
  160. package/src/transaction/actions/encode.test.ts +1 -1
  161. package/src/transaction/actions/estimate-gas-cost.ts +1 -1
  162. package/src/transaction/actions/to-serializable-transaction.ts +46 -35
  163. package/src/transaction/prepare-transaction.ts +11 -0
  164. package/src/utils/nft/fetch-token-metadata.test.ts +1 -1
  165. package/src/utils/process.ts +4 -0
  166. package/src/version.ts +1 -1
  167. package/src/wallets/manager/index.ts +6 -2
  168. package/src/wallets/smart/index.ts +1 -1
  169. package/src/wallets/smart/lib/bundler.ts +95 -0
  170. package/src/wallets/smart/lib/calls.ts +18 -9
  171. package/src/wallets/smart/lib/userop.ts +53 -18
  172. package/src/wallets/smart/smart-wallet-integration-v07.test.ts +23 -16
  173. package/src/wallets/smart/smart-wallet-integration.test.ts +21 -1
  174. 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
- const saltHex =
94
- accountSalt && isHex(accountSalt)
95
- ? accountSalt
96
- : stringToHex(accountSalt ?? "");
97
- return readContract({
98
- contract: factoryContract,
99
- method: "function getAddress(address, bytes) returns (address)",
100
- params: [adminAddress, saltHex],
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
- isContractDeployed(accountContract),
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 || isAccountDeploying(accountContract)) {
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 || isAccountDeploying(accountContract)) {
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
- toSerializableTransaction({
740
- transaction: tx,
741
- from: accountAddress,
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
- const unsignedUserOp = await createUnsignedUserOp({
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.runIf(process.env.TW_SECRET_KEY)(
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.runIf(process.env.TW_SECRET_KEY).sequential(
31
+ describe.sequential(
32
32
  "SmartWallet modular tests",
33
33
  {
34
34
  retry: 0,