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.
- package/dist/cjs/adapters/ethers5.js +1 -1
- package/dist/cjs/adapters/ethers5.js.map +1 -1
- package/dist/cjs/auth/verify-hash.js +13 -8
- package/dist/cjs/auth/verify-hash.js.map +1 -1
- package/dist/cjs/contract/types.js +3 -0
- package/dist/cjs/contract/types.js.map +1 -0
- package/dist/cjs/exports/thirdweb.js +5 -1
- package/dist/cjs/exports/thirdweb.js.map +1 -1
- package/dist/cjs/exports/transaction.js +3 -1
- package/dist/cjs/exports/transaction.js.map +1 -1
- package/dist/cjs/exports/wallets.js +3 -1
- package/dist/cjs/exports/wallets.js.map +1 -1
- package/dist/cjs/extensions/erc721/lazyMinting/read/getBatchesToReveal.js +1 -1
- package/dist/cjs/extensions/erc721/lazyMinting/read/getBatchesToReveal.js.map +1 -1
- package/dist/cjs/extensions/types.js +3 -0
- package/dist/cjs/extensions/types.js.map +1 -0
- package/dist/cjs/gas/estimate-l1-fee.js +3 -4
- package/dist/cjs/gas/estimate-l1-fee.js.map +1 -1
- package/dist/cjs/react/core/hooks/contract/useReadContract.js +31 -29
- package/dist/cjs/react/core/hooks/contract/useReadContract.js.map +1 -1
- package/dist/cjs/react/core/hooks/types.js +3 -0
- package/dist/cjs/react/core/hooks/types.js.map +1 -0
- package/dist/cjs/transaction/actions/eip7702/authorization.js +33 -0
- package/dist/cjs/transaction/actions/eip7702/authorization.js.map +1 -0
- package/dist/cjs/transaction/actions/estimate-gas.js +16 -4
- package/dist/cjs/transaction/actions/estimate-gas.js.map +1 -1
- package/dist/cjs/transaction/actions/send-transaction.js +32 -1
- package/dist/cjs/transaction/actions/send-transaction.js.map +1 -1
- package/dist/cjs/transaction/actions/to-serializable-transaction.js +13 -4
- package/dist/cjs/transaction/actions/to-serializable-transaction.js.map +1 -1
- package/dist/cjs/transaction/prepare-transaction.js.map +1 -1
- package/dist/cjs/transaction/serialize-transaction.js +11 -0
- package/dist/cjs/transaction/serialize-transaction.js.map +1 -1
- package/dist/cjs/utils/abi/decodeError.js +3 -3
- package/dist/cjs/utils/abi/decodeError.js.map +1 -1
- package/dist/cjs/utils/abi/decodeFunctionData.js +3 -3
- package/dist/cjs/utils/abi/decodeFunctionData.js.map +1 -1
- package/dist/cjs/utils/abi/decodeFunctionResult.js +3 -3
- package/dist/cjs/utils/abi/decodeFunctionResult.js.map +1 -1
- package/dist/cjs/utils/hashing/hashMessage.js +2 -2
- package/dist/cjs/utils/hashing/hashMessage.js.map +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/version.js.map +1 -1
- package/dist/cjs/wallets/create-wallet.js +16 -0
- package/dist/cjs/wallets/create-wallet.js.map +1 -1
- package/dist/cjs/wallets/in-app/core/wallet/in-app-core.js +9 -3
- package/dist/cjs/wallets/in-app/core/wallet/in-app-core.js.map +1 -1
- package/dist/cjs/wallets/in-app/core/wallet/index.js +8 -10
- package/dist/cjs/wallets/in-app/core/wallet/index.js.map +1 -1
- package/dist/cjs/wallets/private-key.js +9 -0
- package/dist/cjs/wallets/private-key.js.map +1 -1
- package/dist/cjs/wallets/smart/index.js +34 -32
- package/dist/cjs/wallets/smart/index.js.map +1 -1
- package/dist/cjs/wallets/smart/lib/signing.js +139 -54
- package/dist/cjs/wallets/smart/lib/signing.js.map +1 -1
- package/dist/cjs/wallets/smart/presets/7579.js +11 -10
- package/dist/cjs/wallets/smart/presets/7579.js.map +1 -1
- package/dist/cjs/wallets/smart/smart-wallet.js +12 -10
- package/dist/cjs/wallets/smart/smart-wallet.js.map +1 -1
- package/dist/esm/adapters/ethers5.js +1 -1
- package/dist/esm/adapters/ethers5.js.map +1 -1
- package/dist/esm/auth/verify-hash.js +13 -9
- package/dist/esm/auth/verify-hash.js.map +1 -1
- package/dist/esm/contract/types.js +2 -0
- package/dist/esm/contract/types.js.map +1 -0
- package/dist/esm/exports/thirdweb.js +2 -0
- package/dist/esm/exports/thirdweb.js.map +1 -1
- package/dist/esm/exports/transaction.js +1 -0
- package/dist/esm/exports/transaction.js.map +1 -1
- package/dist/esm/exports/wallets.js +1 -0
- package/dist/esm/exports/wallets.js.map +1 -1
- package/dist/esm/extensions/erc721/lazyMinting/read/getBatchesToReveal.js +1 -1
- package/dist/esm/extensions/erc721/lazyMinting/read/getBatchesToReveal.js.map +1 -1
- package/dist/esm/extensions/types.js +2 -0
- package/dist/esm/extensions/types.js.map +1 -0
- package/dist/esm/gas/estimate-l1-fee.js +2 -3
- package/dist/esm/gas/estimate-l1-fee.js.map +1 -1
- package/dist/esm/react/core/hooks/contract/useReadContract.js +31 -29
- package/dist/esm/react/core/hooks/contract/useReadContract.js.map +1 -1
- package/dist/esm/react/core/hooks/types.js +2 -0
- package/dist/esm/react/core/hooks/types.js.map +1 -0
- package/dist/esm/transaction/actions/eip7702/authorization.js +30 -0
- package/dist/esm/transaction/actions/eip7702/authorization.js.map +1 -0
- package/dist/esm/transaction/actions/estimate-gas.js +16 -4
- package/dist/esm/transaction/actions/estimate-gas.js.map +1 -1
- package/dist/esm/transaction/actions/send-transaction.js +32 -1
- package/dist/esm/transaction/actions/send-transaction.js.map +1 -1
- package/dist/esm/transaction/actions/to-serializable-transaction.js +13 -4
- package/dist/esm/transaction/actions/to-serializable-transaction.js.map +1 -1
- package/dist/esm/transaction/prepare-transaction.js.map +1 -1
- package/dist/esm/transaction/serialize-transaction.js +11 -0
- package/dist/esm/transaction/serialize-transaction.js.map +1 -1
- package/dist/esm/utils/abi/decodeError.js +3 -3
- package/dist/esm/utils/abi/decodeError.js.map +1 -1
- package/dist/esm/utils/abi/decodeFunctionData.js +3 -3
- package/dist/esm/utils/abi/decodeFunctionData.js.map +1 -1
- package/dist/esm/utils/abi/decodeFunctionResult.js +3 -3
- package/dist/esm/utils/abi/decodeFunctionResult.js.map +1 -1
- package/dist/esm/utils/hashing/hashMessage.js +1 -1
- package/dist/esm/utils/hashing/hashMessage.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/esm/wallets/create-wallet.js +16 -0
- package/dist/esm/wallets/create-wallet.js.map +1 -1
- package/dist/esm/wallets/in-app/core/wallet/in-app-core.js +9 -3
- package/dist/esm/wallets/in-app/core/wallet/in-app-core.js.map +1 -1
- package/dist/esm/wallets/in-app/core/wallet/index.js +8 -10
- package/dist/esm/wallets/in-app/core/wallet/index.js.map +1 -1
- package/dist/esm/wallets/private-key.js +9 -0
- package/dist/esm/wallets/private-key.js.map +1 -1
- package/dist/esm/wallets/smart/index.js +32 -30
- package/dist/esm/wallets/smart/index.js.map +1 -1
- package/dist/esm/wallets/smart/lib/signing.js +137 -53
- package/dist/esm/wallets/smart/lib/signing.js.map +1 -1
- package/dist/esm/wallets/smart/presets/7579.js +11 -10
- package/dist/esm/wallets/smart/presets/7579.js.map +1 -1
- package/dist/esm/wallets/smart/smart-wallet.js +12 -10
- package/dist/esm/wallets/smart/smart-wallet.js.map +1 -1
- package/dist/types/auth/verify-hash.d.ts +6 -0
- package/dist/types/auth/verify-hash.d.ts.map +1 -1
- package/dist/types/contract/types.d.ts +7 -0
- package/dist/types/contract/types.d.ts.map +1 -0
- package/dist/types/exports/thirdweb.d.ts +6 -0
- package/dist/types/exports/thirdweb.d.ts.map +1 -1
- package/dist/types/exports/transaction.d.ts +5 -0
- package/dist/types/exports/transaction.d.ts.map +1 -1
- package/dist/types/exports/wallets.d.ts +1 -0
- package/dist/types/exports/wallets.d.ts.map +1 -1
- package/dist/types/extensions/erc721/lazyMinting/read/getBatchesToReveal.d.ts +1 -1
- package/dist/types/extensions/erc721/lazyMinting/read/getBatchesToReveal.d.ts.map +1 -1
- package/dist/types/extensions/types.d.ts +4 -0
- package/dist/types/extensions/types.d.ts.map +1 -0
- package/dist/types/gas/estimate-l1-fee.d.ts.map +1 -1
- package/dist/types/react/core/hooks/contract/useReadContract.d.ts +9 -16
- package/dist/types/react/core/hooks/contract/useReadContract.d.ts.map +1 -1
- package/dist/types/react/core/hooks/types.d.ts +13 -0
- package/dist/types/react/core/hooks/types.d.ts.map +1 -0
- package/dist/types/transaction/actions/eip7702/authorization.d.ts +48 -0
- package/dist/types/transaction/actions/eip7702/authorization.d.ts.map +1 -0
- package/dist/types/transaction/actions/estimate-gas.d.ts +3 -1
- package/dist/types/transaction/actions/estimate-gas.d.ts.map +1 -1
- package/dist/types/transaction/actions/send-transaction.d.ts +31 -0
- package/dist/types/transaction/actions/send-transaction.d.ts.map +1 -1
- package/dist/types/transaction/actions/to-serializable-transaction.d.ts +19 -2
- package/dist/types/transaction/actions/to-serializable-transaction.d.ts.map +1 -1
- package/dist/types/transaction/prepare-transaction.d.ts +2 -0
- package/dist/types/transaction/prepare-transaction.d.ts.map +1 -1
- package/dist/types/transaction/serialize-transaction.d.ts +2 -0
- package/dist/types/transaction/serialize-transaction.d.ts.map +1 -1
- package/dist/types/utils/abi/decodeError.d.ts +2 -2
- package/dist/types/utils/abi/decodeError.d.ts.map +1 -1
- package/dist/types/utils/abi/decodeFunctionData.d.ts +6 -4
- package/dist/types/utils/abi/decodeFunctionData.d.ts.map +1 -1
- package/dist/types/utils/abi/decodeFunctionResult.d.ts +6 -4
- package/dist/types/utils/abi/decodeFunctionResult.d.ts.map +1 -1
- package/dist/types/utils/hashing/hashMessage.d.ts +1 -1
- package/dist/types/utils/hashing/hashMessage.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/version.d.ts.map +1 -1
- package/dist/types/wallets/create-wallet.d.ts +16 -0
- package/dist/types/wallets/create-wallet.d.ts.map +1 -1
- package/dist/types/wallets/in-app/core/wallet/in-app-core.d.ts.map +1 -1
- package/dist/types/wallets/in-app/core/wallet/index.d.ts +10 -2
- package/dist/types/wallets/in-app/core/wallet/index.d.ts.map +1 -1
- package/dist/types/wallets/interfaces/wallet.d.ts +9 -0
- package/dist/types/wallets/interfaces/wallet.d.ts.map +1 -1
- package/dist/types/wallets/private-key.d.ts.map +1 -1
- package/dist/types/wallets/smart/index.d.ts +2 -2
- package/dist/types/wallets/smart/index.d.ts.map +1 -1
- package/dist/types/wallets/smart/lib/signing.d.ts +46 -2
- package/dist/types/wallets/smart/lib/signing.d.ts.map +1 -1
- package/dist/types/wallets/smart/presets/7579.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/adapters/ethers5.ts +1 -1
- package/src/auth/verify-hash.ts +12 -9
- package/src/contract/types.ts +8 -0
- package/src/exports/thirdweb.ts +10 -0
- package/src/exports/transaction.ts +9 -0
- package/src/exports/wallets.ts +2 -0
- package/src/extensions/erc721/lazyMinting/read/getBatchesToReveal.ts +2 -2
- package/src/extensions/types.ts +6 -0
- package/src/gas/estimate-l1-fee.ts +2 -3
- package/src/react/core/hooks/contract/useReadContract.ts +83 -74
- package/src/react/core/hooks/types.ts +13 -0
- package/src/transaction/actions/eip7702/authorization.test.ts +27 -0
- package/src/transaction/actions/eip7702/authorization.ts +58 -0
- package/src/transaction/actions/estimate-gas.ts +26 -9
- package/src/transaction/actions/send-transaction.ts +32 -2
- package/src/transaction/actions/to-serializable-transaction.test.ts +68 -0
- package/src/transaction/actions/to-serializable-transaction.ts +42 -30
- package/src/transaction/prepare-transaction.test.ts +28 -0
- package/src/transaction/prepare-transaction.ts +3 -0
- package/src/transaction/serialize-transaction.test.ts +108 -1
- package/src/transaction/serialize-transaction.ts +18 -0
- package/src/utils/abi/decodeError.ts +5 -4
- package/src/utils/abi/decodeFunctionData.ts +7 -5
- package/src/utils/abi/decodeFunctionResult.ts +7 -5
- package/src/utils/hashing/hashMessage.ts +1 -1
- package/src/utils/signatures/sign-message.test.ts +2 -2
- package/src/version.ts +1 -1
- package/src/wallets/create-wallet.ts +16 -0
- package/src/wallets/in-app/core/wallet/in-app-core.test.ts +115 -54
- package/src/wallets/in-app/core/wallet/in-app-core.ts +22 -11
- package/src/wallets/in-app/core/wallet/index.ts +10 -13
- package/src/wallets/interfaces/wallet.ts +15 -0
- package/src/wallets/private-key.test.ts +1 -0
- package/src/wallets/private-key.ts +10 -0
- package/src/wallets/smart/index.ts +34 -37
- package/src/wallets/smart/lib/signing.ts +154 -59
- package/src/wallets/smart/presets/7579.ts +13 -12
- package/src/wallets/smart/smart-wallet-integration-v07.test.ts +49 -9
- package/src/wallets/smart/smart-wallet-integration.test.ts +48 -1
- package/src/wallets/smart/smart-wallet.ts +13 -13
- package/src/wallets/smart/smart.test.ts +19 -39
@@ -69,28 +69,26 @@ export function isSmartWallet(
|
|
69
69
|
}
|
70
70
|
|
71
71
|
/**
|
72
|
-
*
|
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
|
76
|
-
|
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
|
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(
|
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
|
-
|
181
|
-
|
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
|
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 =
|
189
|
+
const personalAccount = smartAccountToAdminAccountMap.get(account);
|
194
190
|
if (personalAccount) {
|
195
191
|
// remove the mappings
|
196
|
-
|
197
|
-
|
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
|
-
|
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
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
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:
|
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 {
|
296
|
-
return
|
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 {
|
317
|
-
return
|
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 {
|
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
|
-
|
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
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
84
|
-
|
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
|
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
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
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
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
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
|
-
|
171
|
-
|
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
|
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
|
-
|
60
|
+
ox__Hex.validate(options.overrides.accountSalt)
|
60
61
|
? options.overrides.accountSalt
|
61
|
-
:
|
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:
|
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:
|
103
|
-
executionCalldata:
|
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:
|
121
|
-
executionCalldata:
|
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 =
|
156
|
-
`${defaultValidator}${
|
156
|
+
const withValidator = ox__Hex.from(
|
157
|
+
`${defaultValidator}${ox__Hex.fromNumber(entryPointNonce).slice(42)}`,
|
157
158
|
);
|
158
|
-
return
|
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:
|
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 {
|
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
|
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,
|