thirdweb 5.80.1-nightly-430475913d30ef7a30cb3092f6ef09c0c998a9b6-20250106000343 → 5.82.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 (214) hide show
  1. package/dist/cjs/adapters/ethers5.js +1 -1
  2. package/dist/cjs/adapters/ethers5.js.map +1 -1
  3. package/dist/cjs/auth/verify-hash.js +13 -8
  4. package/dist/cjs/auth/verify-hash.js.map +1 -1
  5. package/dist/cjs/contract/types.js +3 -0
  6. package/dist/cjs/contract/types.js.map +1 -0
  7. package/dist/cjs/exports/thirdweb.js +5 -1
  8. package/dist/cjs/exports/thirdweb.js.map +1 -1
  9. package/dist/cjs/exports/transaction.js +3 -1
  10. package/dist/cjs/exports/transaction.js.map +1 -1
  11. package/dist/cjs/exports/wallets.js +3 -1
  12. package/dist/cjs/exports/wallets.js.map +1 -1
  13. package/dist/cjs/extensions/erc721/lazyMinting/read/getBatchesToReveal.js +1 -1
  14. package/dist/cjs/extensions/erc721/lazyMinting/read/getBatchesToReveal.js.map +1 -1
  15. package/dist/cjs/extensions/types.js +3 -0
  16. package/dist/cjs/extensions/types.js.map +1 -0
  17. package/dist/cjs/gas/estimate-l1-fee.js +3 -4
  18. package/dist/cjs/gas/estimate-l1-fee.js.map +1 -1
  19. package/dist/cjs/react/core/hooks/contract/useReadContract.js +31 -29
  20. package/dist/cjs/react/core/hooks/contract/useReadContract.js.map +1 -1
  21. package/dist/cjs/react/core/hooks/types.js +3 -0
  22. package/dist/cjs/react/core/hooks/types.js.map +1 -0
  23. package/dist/cjs/transaction/actions/eip7702/authorization.js +33 -0
  24. package/dist/cjs/transaction/actions/eip7702/authorization.js.map +1 -0
  25. package/dist/cjs/transaction/actions/estimate-gas.js +16 -4
  26. package/dist/cjs/transaction/actions/estimate-gas.js.map +1 -1
  27. package/dist/cjs/transaction/actions/send-transaction.js +32 -1
  28. package/dist/cjs/transaction/actions/send-transaction.js.map +1 -1
  29. package/dist/cjs/transaction/actions/to-serializable-transaction.js +13 -4
  30. package/dist/cjs/transaction/actions/to-serializable-transaction.js.map +1 -1
  31. package/dist/cjs/transaction/prepare-transaction.js.map +1 -1
  32. package/dist/cjs/transaction/serialize-transaction.js +11 -0
  33. package/dist/cjs/transaction/serialize-transaction.js.map +1 -1
  34. package/dist/cjs/utils/abi/decodeError.js +3 -3
  35. package/dist/cjs/utils/abi/decodeError.js.map +1 -1
  36. package/dist/cjs/utils/abi/decodeFunctionData.js +3 -3
  37. package/dist/cjs/utils/abi/decodeFunctionData.js.map +1 -1
  38. package/dist/cjs/utils/abi/decodeFunctionResult.js +3 -3
  39. package/dist/cjs/utils/abi/decodeFunctionResult.js.map +1 -1
  40. package/dist/cjs/utils/hashing/hashMessage.js +2 -2
  41. package/dist/cjs/utils/hashing/hashMessage.js.map +1 -1
  42. package/dist/cjs/version.js +1 -1
  43. package/dist/cjs/version.js.map +1 -1
  44. package/dist/cjs/wallets/create-wallet.js +16 -0
  45. package/dist/cjs/wallets/create-wallet.js.map +1 -1
  46. package/dist/cjs/wallets/in-app/core/wallet/in-app-core.js +9 -3
  47. package/dist/cjs/wallets/in-app/core/wallet/in-app-core.js.map +1 -1
  48. package/dist/cjs/wallets/in-app/core/wallet/index.js +8 -10
  49. package/dist/cjs/wallets/in-app/core/wallet/index.js.map +1 -1
  50. package/dist/cjs/wallets/private-key.js +9 -0
  51. package/dist/cjs/wallets/private-key.js.map +1 -1
  52. package/dist/cjs/wallets/smart/index.js +34 -32
  53. package/dist/cjs/wallets/smart/index.js.map +1 -1
  54. package/dist/cjs/wallets/smart/lib/signing.js +139 -54
  55. package/dist/cjs/wallets/smart/lib/signing.js.map +1 -1
  56. package/dist/cjs/wallets/smart/presets/7579.js +11 -10
  57. package/dist/cjs/wallets/smart/presets/7579.js.map +1 -1
  58. package/dist/cjs/wallets/smart/smart-wallet.js +12 -10
  59. package/dist/cjs/wallets/smart/smart-wallet.js.map +1 -1
  60. package/dist/esm/adapters/ethers5.js +1 -1
  61. package/dist/esm/adapters/ethers5.js.map +1 -1
  62. package/dist/esm/auth/verify-hash.js +13 -9
  63. package/dist/esm/auth/verify-hash.js.map +1 -1
  64. package/dist/esm/contract/types.js +2 -0
  65. package/dist/esm/contract/types.js.map +1 -0
  66. package/dist/esm/exports/thirdweb.js +2 -0
  67. package/dist/esm/exports/thirdweb.js.map +1 -1
  68. package/dist/esm/exports/transaction.js +1 -0
  69. package/dist/esm/exports/transaction.js.map +1 -1
  70. package/dist/esm/exports/wallets.js +1 -0
  71. package/dist/esm/exports/wallets.js.map +1 -1
  72. package/dist/esm/extensions/erc721/lazyMinting/read/getBatchesToReveal.js +1 -1
  73. package/dist/esm/extensions/erc721/lazyMinting/read/getBatchesToReveal.js.map +1 -1
  74. package/dist/esm/extensions/types.js +2 -0
  75. package/dist/esm/extensions/types.js.map +1 -0
  76. package/dist/esm/gas/estimate-l1-fee.js +2 -3
  77. package/dist/esm/gas/estimate-l1-fee.js.map +1 -1
  78. package/dist/esm/react/core/hooks/contract/useReadContract.js +31 -29
  79. package/dist/esm/react/core/hooks/contract/useReadContract.js.map +1 -1
  80. package/dist/esm/react/core/hooks/types.js +2 -0
  81. package/dist/esm/react/core/hooks/types.js.map +1 -0
  82. package/dist/esm/transaction/actions/eip7702/authorization.js +30 -0
  83. package/dist/esm/transaction/actions/eip7702/authorization.js.map +1 -0
  84. package/dist/esm/transaction/actions/estimate-gas.js +16 -4
  85. package/dist/esm/transaction/actions/estimate-gas.js.map +1 -1
  86. package/dist/esm/transaction/actions/send-transaction.js +32 -1
  87. package/dist/esm/transaction/actions/send-transaction.js.map +1 -1
  88. package/dist/esm/transaction/actions/to-serializable-transaction.js +13 -4
  89. package/dist/esm/transaction/actions/to-serializable-transaction.js.map +1 -1
  90. package/dist/esm/transaction/prepare-transaction.js.map +1 -1
  91. package/dist/esm/transaction/serialize-transaction.js +11 -0
  92. package/dist/esm/transaction/serialize-transaction.js.map +1 -1
  93. package/dist/esm/utils/abi/decodeError.js +3 -3
  94. package/dist/esm/utils/abi/decodeError.js.map +1 -1
  95. package/dist/esm/utils/abi/decodeFunctionData.js +3 -3
  96. package/dist/esm/utils/abi/decodeFunctionData.js.map +1 -1
  97. package/dist/esm/utils/abi/decodeFunctionResult.js +3 -3
  98. package/dist/esm/utils/abi/decodeFunctionResult.js.map +1 -1
  99. package/dist/esm/utils/hashing/hashMessage.js +1 -1
  100. package/dist/esm/utils/hashing/hashMessage.js.map +1 -1
  101. package/dist/esm/version.js +1 -1
  102. package/dist/esm/version.js.map +1 -1
  103. package/dist/esm/wallets/create-wallet.js +16 -0
  104. package/dist/esm/wallets/create-wallet.js.map +1 -1
  105. package/dist/esm/wallets/in-app/core/wallet/in-app-core.js +9 -3
  106. package/dist/esm/wallets/in-app/core/wallet/in-app-core.js.map +1 -1
  107. package/dist/esm/wallets/in-app/core/wallet/index.js +8 -10
  108. package/dist/esm/wallets/in-app/core/wallet/index.js.map +1 -1
  109. package/dist/esm/wallets/private-key.js +9 -0
  110. package/dist/esm/wallets/private-key.js.map +1 -1
  111. package/dist/esm/wallets/smart/index.js +32 -30
  112. package/dist/esm/wallets/smart/index.js.map +1 -1
  113. package/dist/esm/wallets/smart/lib/signing.js +137 -53
  114. package/dist/esm/wallets/smart/lib/signing.js.map +1 -1
  115. package/dist/esm/wallets/smart/presets/7579.js +11 -10
  116. package/dist/esm/wallets/smart/presets/7579.js.map +1 -1
  117. package/dist/esm/wallets/smart/smart-wallet.js +12 -10
  118. package/dist/esm/wallets/smart/smart-wallet.js.map +1 -1
  119. package/dist/types/auth/verify-hash.d.ts +6 -0
  120. package/dist/types/auth/verify-hash.d.ts.map +1 -1
  121. package/dist/types/contract/types.d.ts +7 -0
  122. package/dist/types/contract/types.d.ts.map +1 -0
  123. package/dist/types/exports/thirdweb.d.ts +6 -0
  124. package/dist/types/exports/thirdweb.d.ts.map +1 -1
  125. package/dist/types/exports/transaction.d.ts +5 -0
  126. package/dist/types/exports/transaction.d.ts.map +1 -1
  127. package/dist/types/exports/wallets.d.ts +1 -0
  128. package/dist/types/exports/wallets.d.ts.map +1 -1
  129. package/dist/types/extensions/erc721/lazyMinting/read/getBatchesToReveal.d.ts +1 -1
  130. package/dist/types/extensions/erc721/lazyMinting/read/getBatchesToReveal.d.ts.map +1 -1
  131. package/dist/types/extensions/types.d.ts +4 -0
  132. package/dist/types/extensions/types.d.ts.map +1 -0
  133. package/dist/types/gas/estimate-l1-fee.d.ts.map +1 -1
  134. package/dist/types/react/core/hooks/contract/useReadContract.d.ts +9 -16
  135. package/dist/types/react/core/hooks/contract/useReadContract.d.ts.map +1 -1
  136. package/dist/types/react/core/hooks/types.d.ts +13 -0
  137. package/dist/types/react/core/hooks/types.d.ts.map +1 -0
  138. package/dist/types/transaction/actions/eip7702/authorization.d.ts +48 -0
  139. package/dist/types/transaction/actions/eip7702/authorization.d.ts.map +1 -0
  140. package/dist/types/transaction/actions/estimate-gas.d.ts +3 -1
  141. package/dist/types/transaction/actions/estimate-gas.d.ts.map +1 -1
  142. package/dist/types/transaction/actions/send-transaction.d.ts +31 -0
  143. package/dist/types/transaction/actions/send-transaction.d.ts.map +1 -1
  144. package/dist/types/transaction/actions/to-serializable-transaction.d.ts +19 -2
  145. package/dist/types/transaction/actions/to-serializable-transaction.d.ts.map +1 -1
  146. package/dist/types/transaction/prepare-transaction.d.ts +2 -0
  147. package/dist/types/transaction/prepare-transaction.d.ts.map +1 -1
  148. package/dist/types/transaction/serialize-transaction.d.ts +2 -0
  149. package/dist/types/transaction/serialize-transaction.d.ts.map +1 -1
  150. package/dist/types/utils/abi/decodeError.d.ts +2 -2
  151. package/dist/types/utils/abi/decodeError.d.ts.map +1 -1
  152. package/dist/types/utils/abi/decodeFunctionData.d.ts +6 -4
  153. package/dist/types/utils/abi/decodeFunctionData.d.ts.map +1 -1
  154. package/dist/types/utils/abi/decodeFunctionResult.d.ts +6 -4
  155. package/dist/types/utils/abi/decodeFunctionResult.d.ts.map +1 -1
  156. package/dist/types/utils/hashing/hashMessage.d.ts +1 -1
  157. package/dist/types/utils/hashing/hashMessage.d.ts.map +1 -1
  158. package/dist/types/version.d.ts +1 -1
  159. package/dist/types/version.d.ts.map +1 -1
  160. package/dist/types/wallets/create-wallet.d.ts +16 -0
  161. package/dist/types/wallets/create-wallet.d.ts.map +1 -1
  162. package/dist/types/wallets/in-app/core/wallet/in-app-core.d.ts.map +1 -1
  163. package/dist/types/wallets/in-app/core/wallet/index.d.ts +10 -2
  164. package/dist/types/wallets/in-app/core/wallet/index.d.ts.map +1 -1
  165. package/dist/types/wallets/interfaces/wallet.d.ts +9 -0
  166. package/dist/types/wallets/interfaces/wallet.d.ts.map +1 -1
  167. package/dist/types/wallets/private-key.d.ts.map +1 -1
  168. package/dist/types/wallets/smart/index.d.ts +2 -2
  169. package/dist/types/wallets/smart/index.d.ts.map +1 -1
  170. package/dist/types/wallets/smart/lib/signing.d.ts +46 -2
  171. package/dist/types/wallets/smart/lib/signing.d.ts.map +1 -1
  172. package/dist/types/wallets/smart/presets/7579.d.ts.map +1 -1
  173. package/package.json +1 -1
  174. package/src/adapters/ethers5.ts +1 -1
  175. package/src/auth/verify-hash.ts +12 -9
  176. package/src/contract/types.ts +8 -0
  177. package/src/exports/thirdweb.ts +10 -0
  178. package/src/exports/transaction.ts +9 -0
  179. package/src/exports/wallets.ts +2 -0
  180. package/src/extensions/erc721/lazyMinting/read/getBatchesToReveal.ts +2 -2
  181. package/src/extensions/types.ts +6 -0
  182. package/src/gas/estimate-l1-fee.ts +2 -3
  183. package/src/react/core/hooks/contract/useReadContract.ts +83 -74
  184. package/src/react/core/hooks/types.ts +13 -0
  185. package/src/transaction/actions/eip7702/authorization.test.ts +27 -0
  186. package/src/transaction/actions/eip7702/authorization.ts +58 -0
  187. package/src/transaction/actions/estimate-gas.ts +26 -9
  188. package/src/transaction/actions/send-transaction.ts +32 -2
  189. package/src/transaction/actions/to-serializable-transaction.test.ts +68 -0
  190. package/src/transaction/actions/to-serializable-transaction.ts +42 -30
  191. package/src/transaction/prepare-transaction.test.ts +28 -0
  192. package/src/transaction/prepare-transaction.ts +3 -0
  193. package/src/transaction/serialize-transaction.test.ts +108 -1
  194. package/src/transaction/serialize-transaction.ts +18 -0
  195. package/src/utils/abi/decodeError.ts +5 -4
  196. package/src/utils/abi/decodeFunctionData.ts +7 -5
  197. package/src/utils/abi/decodeFunctionResult.ts +7 -5
  198. package/src/utils/hashing/hashMessage.ts +1 -1
  199. package/src/utils/signatures/sign-message.test.ts +2 -2
  200. package/src/version.ts +1 -1
  201. package/src/wallets/create-wallet.ts +16 -0
  202. package/src/wallets/in-app/core/wallet/in-app-core.test.ts +115 -54
  203. package/src/wallets/in-app/core/wallet/in-app-core.ts +22 -11
  204. package/src/wallets/in-app/core/wallet/index.ts +10 -13
  205. package/src/wallets/interfaces/wallet.ts +15 -0
  206. package/src/wallets/private-key.test.ts +1 -0
  207. package/src/wallets/private-key.ts +10 -0
  208. package/src/wallets/smart/index.ts +34 -37
  209. package/src/wallets/smart/lib/signing.ts +154 -59
  210. package/src/wallets/smart/presets/7579.ts +13 -12
  211. package/src/wallets/smart/smart-wallet-integration-v07.test.ts +49 -9
  212. package/src/wallets/smart/smart-wallet-integration.test.ts +48 -1
  213. package/src/wallets/smart/smart-wallet.ts +13 -13
  214. package/src/wallets/smart/smart.test.ts +19 -39
@@ -69,28 +69,26 @@ export function isSmartWallet(
69
69
  }
70
70
 
71
71
  /**
72
- * We can get the personal account for given smart account but not the other way around - this map gives us the reverse lookup
72
+ * For in-app wallets, the smart wallet creation is implicit so we track these to be able to retrieve the personal account for a smart account on the wallet API.
73
+ * Note: We have to go account to account here and NOT wallet to account because the smart wallet itself is never exposed to the in-app wallet, only the account.
73
74
  * @internal
74
75
  */
75
- const personalAccountToSmartAccountMap = new WeakMap<
76
- Account,
77
- Wallet<"smart">
78
- >();
79
-
80
- const smartWalletToPersonalAccountMap = new WeakMap<Wallet<"smart">, Account>();
76
+ const adminAccountToSmartAccountMap = new WeakMap<Account, Account>();
77
+ const smartAccountToAdminAccountMap = new WeakMap<Account, Account>();
81
78
 
82
79
  /**
83
80
  * @internal
84
81
  */
85
- export async function connectSmartWallet(
86
- wallet: Wallet<"smart">,
82
+ export async function connectSmartAccount(
87
83
  connectionOptions: SmartWalletConnectionOptions,
88
84
  creationOptions: SmartWalletOptions,
89
85
  ): Promise<[Account, Chain]> {
90
86
  const { personalAccount, client, chain: connectChain } = connectionOptions;
91
87
 
92
88
  if (!personalAccount) {
93
- throw new Error("Personal wallet does not have an account");
89
+ throw new Error(
90
+ "No personal account provided for smart account connection",
91
+ );
94
92
  }
95
93
 
96
94
  const options = creationOptions;
@@ -177,8 +175,8 @@ export async function connectSmartWallet(
177
175
  client,
178
176
  });
179
177
 
180
- personalAccountToSmartAccountMap.set(personalAccount, wallet);
181
- smartWalletToPersonalAccountMap.set(wallet, personalAccount);
178
+ adminAccountToSmartAccountMap.set(personalAccount, account);
179
+ smartAccountToAdminAccountMap.set(account, personalAccount);
182
180
 
183
181
  return [account, chain] as const;
184
182
  }
@@ -186,15 +184,13 @@ export async function connectSmartWallet(
186
184
  /**
187
185
  * @internal
188
186
  */
189
- export async function disconnectSmartWallet(
190
- wallet: Wallet<"smart">,
191
- ): Promise<void> {
187
+ export async function disconnectSmartAccount(account: Account): Promise<void> {
192
188
  // look up the personalAccount for the smart wallet
193
- const personalAccount = smartWalletToPersonalAccountMap.get(wallet);
189
+ const personalAccount = smartAccountToAdminAccountMap.get(account);
194
190
  if (personalAccount) {
195
191
  // remove the mappings
196
- personalAccountToSmartAccountMap.delete(personalAccount);
197
- smartWalletToPersonalAccountMap.delete(wallet);
192
+ adminAccountToSmartAccountMap.delete(personalAccount);
193
+ smartAccountToAdminAccountMap.delete(account);
198
194
  }
199
195
  }
200
196
 
@@ -214,7 +210,7 @@ async function createSmartAccount(
214
210
  }
215
211
  }
216
212
 
217
- const { accountContract } = options;
213
+ let accountContract = options.accountContract;
218
214
  const account: Account = {
219
215
  address: getAddress(accountContract.address),
220
216
  async sendTransaction(transaction: SendTransactionOption) {
@@ -241,21 +237,17 @@ async function createSmartAccount(
241
237
  paymasterOverride = options.overrides?.paymaster;
242
238
  }
243
239
 
244
- const accountContractForTransaction = (() => {
245
- // If this transaction is for a different chain than the initial one, get the account contract for that chain
246
- if (transaction.chainId !== accountContract.chain.id) {
247
- return getContract({
248
- address: account.address,
249
- chain: getCachedChain(transaction.chainId),
250
- client: options.client,
251
- });
252
- }
253
- // Default to the existing account contract
254
- return accountContract;
255
- })();
240
+ // If this transaction is for a different chain than the initial one, get the account contract for that chain
241
+ if (transaction.chainId !== accountContract.chain.id) {
242
+ accountContract = getContract({
243
+ address: account.address,
244
+ chain: getCachedChain(transaction.chainId),
245
+ client: options.client,
246
+ });
247
+ }
256
248
 
257
249
  const executeTx = prepareExecute({
258
- accountContract: accountContractForTransaction,
250
+ accountContract: accountContract,
259
251
  transaction,
260
252
  executeOverride: options.overrides?.execute,
261
253
  });
@@ -264,6 +256,7 @@ async function createSmartAccount(
264
256
  options: {
265
257
  ...options,
266
258
  chain: getCachedChain(transaction.chainId),
259
+ accountContract,
267
260
  overrides: {
268
261
  ...options.overrides,
269
262
  paymaster: paymasterOverride,
@@ -279,7 +272,11 @@ async function createSmartAccount(
279
272
  });
280
273
  return _sendUserOp({
281
274
  executeTx,
282
- options,
275
+ options: {
276
+ ...options,
277
+ chain: getCachedChain(transactions[0]?.chainId ?? options.chain.id),
278
+ accountContract,
279
+ },
283
280
  });
284
281
  },
285
282
  async signMessage({ message }: { message: SignableMessage }) {
@@ -292,8 +289,8 @@ async function createSmartAccount(
292
289
  });
293
290
  }
294
291
 
295
- const { deployAndSignMessage } = await import("./lib/signing.js");
296
- return deployAndSignMessage({
292
+ const { smartAccountSignMessage } = await import("./lib/signing.js");
293
+ return smartAccountSignMessage({
297
294
  accountContract,
298
295
  factoryContract: options.factoryContract,
299
296
  options,
@@ -313,8 +310,8 @@ async function createSmartAccount(
313
310
  });
314
311
  }
315
312
 
316
- const { deployAndSignTypedData } = await import("./lib/signing.js");
317
- return deployAndSignTypedData({
313
+ const { smartAccountSignTypedData } = await import("./lib/signing.js");
314
+ return smartAccountSignTypedData({
318
315
  accountContract,
319
316
  factoryContract: options.factoryContract,
320
317
  options,
@@ -1,6 +1,11 @@
1
1
  import type * as ox__TypedData from "ox/TypedData";
2
2
  import { serializeErc6492Signature } from "../../../auth/serialize-erc6492-signature.js";
3
- import { verifyHash } from "../../../auth/verify-hash.js";
3
+ import {
4
+ verifyEip1271Signature,
5
+ verifyHash,
6
+ } from "../../../auth/verify-hash.js";
7
+ import type { Chain } from "../../../chains/types.js";
8
+ import type { ThirdwebClient } from "../../../client/client.js";
4
9
  import {
5
10
  type ThirdwebContract,
6
11
  getContract,
@@ -8,14 +13,22 @@ import {
8
13
  import { encode } from "../../../transaction/actions/encode.js";
9
14
  import { readContract } from "../../../transaction/read-contract.js";
10
15
  import { encodeAbiParameters } from "../../../utils/abi/encodeAbiParameters.js";
16
+ import { isContractDeployed } from "../../../utils/bytecode/is-contract-deployed.js";
11
17
  import type { Hex } from "../../../utils/encoding/hex.js";
12
18
  import { hashMessage } from "../../../utils/hashing/hashMessage.js";
13
19
  import { hashTypedData } from "../../../utils/hashing/hashTypedData.js";
14
20
  import type { SignableMessage } from "../../../utils/types.js";
21
+ import type { Account } from "../../../wallets/interfaces/wallet.js";
15
22
  import type { SmartAccountOptions } from "../types.js";
16
23
  import { prepareCreateAccount } from "./calls.js";
17
24
 
18
- export async function deployAndSignMessage({
25
+ /**
26
+ * If the account is already deployed, generate an ERC-1271 signature.
27
+ * If the account is not deployed, generate an ERC-6492 signature unless otherwise specified.
28
+ *
29
+ * @internal
30
+ */
31
+ export async function smartAccountSignMessage({
19
32
  accountContract,
20
33
  factoryContract,
21
34
  options,
@@ -55,40 +68,51 @@ export async function deployAndSignMessage({
55
68
  sig = await options.personalAccount.signMessage({ message });
56
69
  }
57
70
 
58
- const deployTx = prepareCreateAccount({
59
- factoryContract,
60
- adminAddress: options.personalAccount.address,
61
- accountSalt: options.overrides?.accountSalt,
62
- createAccountOverride: options.overrides?.createAccount,
63
- });
64
- if (!deployTx) {
65
- throw new Error("Create account override not provided");
66
- }
67
- const initCode = await encode(deployTx);
68
- const erc6492Sig = serializeErc6492Signature({
69
- address: factoryContract.address,
70
- data: initCode,
71
- signature: sig,
72
- });
71
+ const isDeployed = await isContractDeployed(accountContract);
72
+ if (isDeployed) {
73
+ const isValid = await verifyEip1271Signature({
74
+ hash: originalMsgHash,
75
+ signature: sig,
76
+ contract: accountContract,
77
+ });
78
+ if (isValid) {
79
+ return sig;
80
+ }
81
+ throw new Error("Failed to verify signature");
82
+ } else {
83
+ const deployTx = prepareCreateAccount({
84
+ factoryContract,
85
+ adminAddress: options.personalAccount.address,
86
+ accountSalt: options.overrides?.accountSalt,
87
+ createAccountOverride: options.overrides?.createAccount,
88
+ });
89
+ if (!deployTx) {
90
+ throw new Error("Create account override not provided");
91
+ }
92
+ const initCode = await encode(deployTx);
93
+ const erc6492Sig = serializeErc6492Signature({
94
+ address: factoryContract.address,
95
+ data: initCode,
96
+ signature: sig,
97
+ });
73
98
 
74
- // check if the signature is valid
75
- const isValid = await verifyHash({
76
- hash: originalMsgHash,
77
- signature: erc6492Sig,
78
- address: accountContract.address,
79
- chain: accountContract.chain,
80
- client: accountContract.client,
81
- });
99
+ // check if the signature is valid
100
+ const isValid = await verifyHash({
101
+ hash: originalMsgHash,
102
+ signature: erc6492Sig,
103
+ address: accountContract.address,
104
+ chain: accountContract.chain,
105
+ client: accountContract.client,
106
+ });
82
107
 
83
- if (isValid) {
84
- return erc6492Sig;
108
+ if (isValid) {
109
+ return erc6492Sig;
110
+ }
111
+ throw new Error("Unable to verify ERC-6492 signature after signing.");
85
112
  }
86
- throw new Error(
87
- "Unable to verify signature on smart account, please make sure the admin wallet has permissions and the signature is valid.",
88
- );
89
113
  }
90
114
 
91
- export async function deployAndSignTypedData<
115
+ export async function smartAccountSignTypedData<
92
116
  const typedData extends ox__TypedData.TypedData | Record<string, unknown>,
93
117
  primaryType extends keyof typedData | "EIP712Domain" = keyof typedData,
94
118
  >({
@@ -142,37 +166,50 @@ export async function deployAndSignTypedData<
142
166
  sig = await options.personalAccount.signTypedData(typedData);
143
167
  }
144
168
 
145
- const deployTx = prepareCreateAccount({
146
- factoryContract,
147
- adminAddress: options.personalAccount.address,
148
- accountSalt: options.overrides?.accountSalt,
149
- createAccountOverride: options.overrides?.createAccount,
150
- });
151
- if (!deployTx) {
152
- throw new Error("Create account override not provided");
153
- }
154
- const initCode = await encode(deployTx);
155
- const erc6492Sig = serializeErc6492Signature({
156
- address: factoryContract.address,
157
- data: initCode,
158
- signature: sig,
159
- });
169
+ const isDeployed = await isContractDeployed(accountContract);
170
+ if (isDeployed) {
171
+ const isValid = await verifyEip1271Signature({
172
+ hash: originalMsgHash,
173
+ signature: sig,
174
+ contract: accountContract,
175
+ });
176
+ if (isValid) {
177
+ return sig;
178
+ }
179
+ throw new Error("Failed to verify signature");
180
+ } else {
181
+ const deployTx = prepareCreateAccount({
182
+ factoryContract,
183
+ adminAddress: options.personalAccount.address,
184
+ accountSalt: options.overrides?.accountSalt,
185
+ createAccountOverride: options.overrides?.createAccount,
186
+ });
187
+ if (!deployTx) {
188
+ throw new Error("Create account override not provided");
189
+ }
190
+ const initCode = await encode(deployTx);
191
+ const erc6492Sig = serializeErc6492Signature({
192
+ address: factoryContract.address,
193
+ data: initCode,
194
+ signature: sig,
195
+ });
160
196
 
161
- // check if the signature is valid
162
- const isValid = await verifyHash({
163
- hash: originalMsgHash,
164
- signature: erc6492Sig,
165
- address: accountContract.address,
166
- chain: accountContract.chain,
167
- client: accountContract.client,
168
- });
197
+ // check if the signature is valid
198
+ const isValid = await verifyHash({
199
+ hash: originalMsgHash,
200
+ signature: erc6492Sig,
201
+ address: accountContract.address,
202
+ chain: accountContract.chain,
203
+ client: accountContract.client,
204
+ });
169
205
 
170
- if (isValid) {
171
- return erc6492Sig;
206
+ if (isValid) {
207
+ return erc6492Sig;
208
+ }
209
+ throw new Error(
210
+ "Unable to verify signature on smart account, please make sure the admin wallet has permissions and the signature is valid.",
211
+ );
172
212
  }
173
- throw new Error(
174
- "Unable to verify signature on smart account, please make sure the admin wallet has permissions and the signature is valid.",
175
- );
176
213
  }
177
214
 
178
215
  export async function confirmContractDeployment(args: {
@@ -229,3 +266,61 @@ async function checkFor712Factory({
229
266
  return false;
230
267
  }
231
268
  }
269
+
270
+ /**
271
+ * Deployes a smart account via a dummy transaction.
272
+ *
273
+ * @param args - Arguments for the deployment.
274
+ * @param args.smartAccount - The smart account to deploy.
275
+ * @param args.chain - The chain to deploy on.
276
+ * @param args.client - The client to use for the deployment.
277
+ * @param args.accountContract - The account contract to deploy.
278
+ *
279
+ * @example
280
+ * ```ts
281
+ * import { deploySmartAccount } from "thirdweb";
282
+ *
283
+ * const account = await deploySmartAccount({
284
+ * smartAccount,
285
+ * chain,
286
+ * client,
287
+ * accountContract,
288
+ * });
289
+ * ```
290
+ *
291
+ * @wallets
292
+ */
293
+ export async function deploySmartAccount(args: {
294
+ smartAccount: Account;
295
+ chain: Chain;
296
+ client: ThirdwebClient;
297
+ accountContract: ThirdwebContract;
298
+ }) {
299
+ const { chain, client, smartAccount, accountContract } = args;
300
+ const isDeployed = await isContractDeployed(accountContract);
301
+ if (isDeployed) {
302
+ return;
303
+ }
304
+
305
+ const [{ sendTransaction }, { prepareTransaction }] = await Promise.all([
306
+ import("../../../transaction/actions/send-transaction.js"),
307
+ import("../../../transaction/prepare-transaction.js"),
308
+ ]);
309
+ const dummyTx = prepareTransaction({
310
+ client: client,
311
+ chain: chain,
312
+ to: accountContract.address,
313
+ value: 0n,
314
+ gas: 50000n, // force gas to avoid simulation error
315
+ });
316
+ const deployResult = await sendTransaction({
317
+ transaction: dummyTx,
318
+ account: smartAccount,
319
+ });
320
+
321
+ await confirmContractDeployment({
322
+ accountContract,
323
+ });
324
+
325
+ return deployResult;
326
+ }
@@ -1,4 +1,5 @@
1
- import { AbiParameters, Hex } from "ox";
1
+ import * as ox__AbiParameters from "ox/AbiParameters";
2
+ import * as ox__Hex from "ox/Hex";
2
3
  import { serializeErc6492Signature } from "../../../auth/serialize-erc6492-signature.js";
3
4
  import { verifyHash } from "../../../auth/verify-hash.js";
4
5
  import { ZERO_ADDRESS } from "../../../constants/addresses.js";
@@ -56,9 +57,9 @@ export type ERC7579Config = SmartWalletOptions & {
56
57
  export function erc7579(options: ERC7579Config): SmartWalletOptions {
57
58
  const saltHex =
58
59
  options.overrides?.accountSalt &&
59
- Hex.validate(options.overrides.accountSalt)
60
+ ox__Hex.validate(options.overrides.accountSalt)
60
61
  ? options.overrides.accountSalt
61
- : Hex.fromString(options.overrides?.accountSalt ?? "");
62
+ : ox__Hex.fromString(options.overrides?.accountSalt ?? "");
62
63
  const defaultValidator = getAddress(options.validatorAddress);
63
64
  const modularAccountOptions: SmartWalletOptions = {
64
65
  ...options,
@@ -75,7 +76,7 @@ export function erc7579(options: ERC7579Config): SmartWalletOptions {
75
76
  {
76
77
  moduleTypeId: 1n, // validator type id
77
78
  module: defaultValidator,
78
- initData: Hex.fromString(""),
79
+ initData: ox__Hex.fromString(""),
79
80
  },
80
81
  ];
81
82
  return {
@@ -99,8 +100,8 @@ export function erc7579(options: ERC7579Config): SmartWalletOptions {
99
100
  contract: accountContract,
100
101
  async asyncParams() {
101
102
  return {
102
- mode: Hex.padRight("0x00", 32), // single execution
103
- executionCalldata: AbiParameters.encodePacked(
103
+ mode: ox__Hex.padRight("0x00", 32), // single execution
104
+ executionCalldata: ox__AbiParameters.encodePacked(
104
105
  ["address", "uint256", "bytes"],
105
106
  [
106
107
  transaction.to || ZERO_ADDRESS,
@@ -117,8 +118,8 @@ export function erc7579(options: ERC7579Config): SmartWalletOptions {
117
118
  contract: accountContract,
118
119
  async asyncParams() {
119
120
  return {
120
- mode: Hex.padRight("0x01", 32), // batch execution
121
- executionCalldata: AbiParameters.encode(
121
+ mode: ox__Hex.padRight("0x01", 32), // batch execution
122
+ executionCalldata: ox__AbiParameters.encode(
122
123
  [
123
124
  {
124
125
  type: "tuple[]",
@@ -152,10 +153,10 @@ export function erc7579(options: ERC7579Config): SmartWalletOptions {
152
153
  sender: accountContract.address,
153
154
  });
154
155
  // TODO (msa) - could be different if validator for the deployed account is different
155
- const withValidator = Hex.from(
156
- `${defaultValidator}${Hex.fromNumber(entryPointNonce).slice(42)}`,
156
+ const withValidator = ox__Hex.from(
157
+ `${defaultValidator}${ox__Hex.fromNumber(entryPointNonce).slice(42)}`,
157
158
  );
158
- return Hex.toBigInt(withValidator);
159
+ return ox__Hex.toBigInt(withValidator);
159
160
  },
160
161
  async signMessage(options) {
161
162
  const { accountContract, factoryContract, adminAccount, message } =
@@ -201,7 +202,7 @@ async function generateSignature(options: {
201
202
  accountContract: ThirdwebContract;
202
203
  factoryContract: ThirdwebContract;
203
204
  adminAccount: Account;
204
- originalMsgHash: Hex.Hex;
205
+ originalMsgHash: ox__Hex.Hex;
205
206
  defaultValidator: string;
206
207
  createAccount: (
207
208
  factoryContract: ThirdwebContract,
@@ -6,6 +6,7 @@ import { type ThirdwebContract, getContract } from "../../contract/contract.js";
6
6
  import { parseEventLogs } from "../../event/actions/parse-logs.js";
7
7
 
8
8
  import { TEST_WALLET_A } from "~test/addresses.js";
9
+ import { verifyEip1271Signature } from "../../auth/verify-hash.js";
9
10
  import { verifyTypedData } from "../../auth/verify-typed-data.js";
10
11
  import { baseSepolia } from "../../chains/chain-definitions/base-sepolia.js";
11
12
  import { sepolia } from "../../chains/chain-definitions/sepolia.js";
@@ -13,7 +14,6 @@ import {
13
14
  addAdmin,
14
15
  adminUpdatedEvent,
15
16
  } from "../../exports/extensions/erc4337.js";
16
- import { balanceOf } from "../../extensions/erc1155/__generated__/IERC1155/read/balanceOf.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
19
  import { estimateGasCost } from "../../transaction/actions/estimate-gas-cost.js";
@@ -21,14 +21,18 @@ import { sendAndConfirmTransaction } from "../../transaction/actions/send-and-co
21
21
  import { sendBatchTransaction } from "../../transaction/actions/send-batch-transaction.js";
22
22
  import { waitForReceipt } from "../../transaction/actions/wait-for-tx-receipt.js";
23
23
  import { prepareTransaction } from "../../transaction/prepare-transaction.js";
24
- import { getAddress } from "../../utils/address.js";
25
24
  import { isContractDeployed } from "../../utils/bytecode/is-contract-deployed.js";
25
+ import { hashMessage } from "../../utils/hashing/hashMessage.js";
26
+ import { hashTypedData } from "../../utils/hashing/hashTypedData.js";
26
27
  import { sleep } from "../../utils/sleep.js";
27
28
  import type { Account, Wallet } from "../interfaces/wallet.js";
28
29
  import { generateAccount } from "../utils/generateAccount.js";
29
30
  import { predictSmartAccountAddress } from "./lib/calls.js";
30
31
  import { DEFAULT_ACCOUNT_FACTORY_V0_7 } from "./lib/constants.js";
31
- import { confirmContractDeployment } from "./lib/signing.js";
32
+ import {
33
+ confirmContractDeployment,
34
+ deploySmartAccount,
35
+ } from "./lib/signing.js";
32
36
  import { smartWallet } from "./smart-wallet.js";
33
37
 
34
38
  let wallet: Wallet;
@@ -98,6 +102,27 @@ describe.runIf(process.env.TW_SECRET_KEY)(
98
102
  expect(isValid).toEqual(true);
99
103
  });
100
104
 
105
+ it("should use ERC-1271 signatures after deployment", async () => {
106
+ await deploySmartAccount({
107
+ chain,
108
+ client,
109
+ smartAccount,
110
+ accountContract,
111
+ });
112
+ await new Promise((resolve) => setTimeout(resolve, 1000)); // pause for a second to prevent race condition
113
+
114
+ const signature = await smartAccount.signMessage({
115
+ message: "hello world",
116
+ });
117
+
118
+ const isValid = await verifyEip1271Signature({
119
+ hash: hashMessage("hello world"),
120
+ signature,
121
+ contract: accountContract,
122
+ });
123
+ expect(isValid).toEqual(true);
124
+ });
125
+
101
126
  it("can sign typed data", async () => {
102
127
  const signature = await smartAccount.signTypedData(typedData.basic);
103
128
  const isValid = await verifyTypedData({
@@ -110,6 +135,27 @@ describe.runIf(process.env.TW_SECRET_KEY)(
110
135
  expect(isValid).toEqual(true);
111
136
  });
112
137
 
138
+ it("should use ERC-1271 typed data signatures after deployment", async () => {
139
+ await deploySmartAccount({
140
+ chain,
141
+ client,
142
+ smartAccount,
143
+ accountContract,
144
+ });
145
+
146
+ await new Promise((resolve) => setTimeout(resolve, 1000)); // pause for a second to prevent race condition
147
+
148
+ const signature = await smartAccount.signTypedData(typedData.basic);
149
+
150
+ const messageHash = hashTypedData(typedData.basic);
151
+ const isValid = await verifyEip1271Signature({
152
+ signature,
153
+ hash: messageHash,
154
+ contract: accountContract,
155
+ });
156
+ expect(isValid).toEqual(true);
157
+ });
158
+
113
159
  it("can send a transaction on another chain", async () => {
114
160
  const tx = await sendAndConfirmTransaction({
115
161
  transaction: prepareTransaction({
@@ -155,12 +201,6 @@ describe.runIf(process.env.TW_SECRET_KEY)(
155
201
  await confirmContractDeployment({ accountContract });
156
202
  const isDeployed = await isContractDeployed(accountContract);
157
203
  expect(isDeployed).toEqual(true);
158
- const balance = await balanceOf({
159
- contract,
160
- owner: getAddress(smartWalletAddress),
161
- tokenId: 0n,
162
- });
163
- expect(balance).toEqual(1n);
164
204
  });
165
205
 
166
206
  it("can estimate a tx", async () => {
@@ -2,6 +2,7 @@ import { beforeAll, describe, expect, it } from "vitest";
2
2
  import { TEST_WALLET_A } from "~test/addresses.js";
3
3
  import { TEST_CLIENT } from "../../../test/src/test-clients.js";
4
4
  import { typedData } from "../../../test/src/typed-data.js";
5
+ import { verifyEip1271Signature } from "../../auth/verify-hash.js";
5
6
  import { verifySignature } from "../../auth/verify-signature.js";
6
7
  import { verifyTypedData } from "../../auth/verify-typed-data.js";
7
8
  import { arbitrumSepolia } from "../../chains/chain-definitions/arbitrum-sepolia.js";
@@ -22,10 +23,13 @@ import { sendTransaction } from "../../transaction/actions/send-transaction.js";
22
23
  import { waitForReceipt } from "../../transaction/actions/wait-for-tx-receipt.js";
23
24
  import { prepareTransaction } from "../../transaction/prepare-transaction.js";
24
25
  import { isContractDeployed } from "../../utils/bytecode/is-contract-deployed.js";
26
+ import { hashMessage } from "../../utils/hashing/hashMessage.js";
27
+ import { hashTypedData } from "../../utils/hashing/hashTypedData.js";
25
28
  import { sleep } from "../../utils/sleep.js";
26
29
  import type { Account, Wallet } from "../interfaces/wallet.js";
27
30
  import { generateAccount } from "../utils/generateAccount.js";
28
31
  import { predictSmartAccountAddress } from "./lib/calls.js";
32
+ import { deploySmartAccount } from "./lib/signing.js";
29
33
  import { smartWallet } from "./smart-wallet.js";
30
34
 
31
35
  let wallet: Wallet;
@@ -94,6 +98,27 @@ describe.runIf(process.env.TW_SECRET_KEY).sequential(
94
98
  expect(isValid).toEqual(true);
95
99
  });
96
100
 
101
+ it("should use ERC-1271 signatures after deployment", async () => {
102
+ await deploySmartAccount({
103
+ chain,
104
+ client,
105
+ smartAccount,
106
+ accountContract,
107
+ });
108
+ await new Promise((resolve) => setTimeout(resolve, 1000)); // pause for a second to prevent race condition
109
+
110
+ const signature = await smartAccount.signMessage({
111
+ message: "hello world",
112
+ });
113
+
114
+ const isValid = await verifyEip1271Signature({
115
+ hash: hashMessage("hello world"),
116
+ signature,
117
+ contract: accountContract,
118
+ });
119
+ expect(isValid).toEqual(true);
120
+ });
121
+
97
122
  it("can sign typed data", async () => {
98
123
  const signature = await smartAccount.signTypedData(typedData.basic);
99
124
  const isValid = await verifyTypedData({
@@ -106,6 +131,27 @@ describe.runIf(process.env.TW_SECRET_KEY).sequential(
106
131
  expect(isValid).toEqual(true);
107
132
  });
108
133
 
134
+ it("should use ERC-1271 typed data signatures after deployment", async () => {
135
+ await deploySmartAccount({
136
+ chain,
137
+ client,
138
+ smartAccount,
139
+ accountContract,
140
+ });
141
+
142
+ await new Promise((resolve) => setTimeout(resolve, 1000)); // pause for a second to prevent race condition
143
+
144
+ const signature = await smartAccount.signTypedData(typedData.basic);
145
+
146
+ const messageHash = hashTypedData(typedData.basic);
147
+ const isValid = await verifyEip1271Signature({
148
+ signature,
149
+ hash: messageHash,
150
+ contract: accountContract,
151
+ });
152
+ expect(isValid).toEqual(true);
153
+ });
154
+
109
155
  it("should revert on unsuccessful transactions", async () => {
110
156
  const tx = sendAndConfirmTransaction({
111
157
  transaction: setContractURI({
@@ -184,7 +230,7 @@ describe.runIf(process.env.TW_SECRET_KEY).sequential(
184
230
  expect(result.status).toEqual("success");
185
231
  });
186
232
 
187
- it("can sign and verify 1271 with replay protection", async () => {
233
+ it("can sign and verify with replay protection", async () => {
188
234
  const message = "hello world";
189
235
  const signature = await smartAccount.signMessage({ message });
190
236
  const isValidV1 = await verifySignature({
@@ -371,6 +417,7 @@ describe.runIf(process.env.TW_SECRET_KEY).sequential(
371
417
  expect(txs.every((t) => t.transactionHash.length === 66)).toBe(true);
372
418
 
373
419
  isDeployed = await isContractDeployed(newSmartAccountContract);
420
+ await sleep(1000);
374
421
  expect(isDeployed).toEqual(true);
375
422
  const balance = await balanceOf({
376
423
  contract,