thirdweb 5.105.3-nightly-6d1d344c48302d45aeb63532c84cc8e79c93e26f-20250628000422 → 5.105.4-nightly-1f72396d7fa4748efef179821a7a796b53679bcb-20250629000440
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/engine/server-wallet.js +64 -19
- package/dist/cjs/engine/server-wallet.js.map +1 -1
- package/dist/cjs/engine/wait-for-tx-hash.js +1 -1
- package/dist/cjs/engine/wait-for-tx-hash.js.map +1 -1
- package/dist/cjs/exports/wallets/in-app.js +5 -1
- package/dist/cjs/exports/wallets/in-app.js.map +1 -1
- package/dist/cjs/exports/wallets/in-app.native.js +5 -1
- package/dist/cjs/exports/wallets/in-app.native.js.map +1 -1
- package/dist/cjs/extensions/erc7702/account/createSessionKey.js +127 -0
- package/dist/cjs/extensions/erc7702/account/createSessionKey.js.map +1 -0
- package/dist/cjs/extensions/erc7702/account/types.js +57 -0
- package/dist/cjs/extensions/erc7702/account/types.js.map +1 -0
- package/dist/cjs/react/web/ui/Bridge/BridgeOrchestrator.js +2 -2
- package/dist/cjs/react/web/ui/Bridge/BridgeOrchestrator.js.map +1 -1
- package/dist/cjs/react/web/ui/Bridge/BuyWidget.js +1 -1
- package/dist/cjs/react/web/ui/Bridge/BuyWidget.js.map +1 -1
- package/dist/cjs/react/web/ui/Bridge/CheckoutWidget.js +1 -1
- package/dist/cjs/react/web/ui/Bridge/CheckoutWidget.js.map +1 -1
- package/dist/cjs/react/web/ui/Bridge/TransactionWidget.js +1 -1
- package/dist/cjs/react/web/ui/Bridge/TransactionWidget.js.map +1 -1
- package/dist/cjs/react/web/ui/Bridge/payment-details/PaymentDetails.js +1 -1
- package/dist/cjs/react/web/ui/Bridge/payment-details/PaymentDetails.js.map +1 -1
- package/dist/cjs/react/web/ui/Bridge/payment-selection/PaymentSelection.js +3 -3
- package/dist/cjs/react/web/ui/Bridge/payment-selection/PaymentSelection.js.map +1 -1
- package/dist/cjs/react/web/ui/Bridge/payment-selection/WalletFiatSelection.js +37 -37
- package/dist/cjs/react/web/ui/Bridge/payment-selection/WalletFiatSelection.js.map +1 -1
- package/dist/cjs/react/web/ui/PayEmbed.js +11 -4
- package/dist/cjs/react/web/ui/PayEmbed.js.map +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/wallets/in-app/core/authentication/backend.js +2 -1
- package/dist/cjs/wallets/in-app/core/authentication/backend.js.map +1 -1
- package/dist/cjs/wallets/in-app/core/authentication/guest.js +2 -8
- package/dist/cjs/wallets/in-app/core/authentication/guest.js.map +1 -1
- package/dist/cjs/wallets/in-app/core/eip7702/minimal-account.js +1 -1
- package/dist/cjs/wallets/in-app/native/native-connector.js +1 -1
- package/dist/cjs/wallets/in-app/native/native-connector.js.map +1 -1
- package/dist/cjs/wallets/in-app/web/lib/web-connector.js +1 -1
- package/dist/cjs/wallets/in-app/web/lib/web-connector.js.map +1 -1
- package/dist/esm/engine/server-wallet.js +65 -20
- package/dist/esm/engine/server-wallet.js.map +1 -1
- package/dist/esm/engine/wait-for-tx-hash.js +1 -1
- package/dist/esm/engine/wait-for-tx-hash.js.map +1 -1
- package/dist/esm/exports/wallets/in-app.js +2 -0
- package/dist/esm/exports/wallets/in-app.js.map +1 -1
- package/dist/esm/exports/wallets/in-app.native.js +2 -0
- package/dist/esm/exports/wallets/in-app.native.js.map +1 -1
- package/dist/esm/extensions/erc7702/account/createSessionKey.js +123 -0
- package/dist/esm/extensions/erc7702/account/createSessionKey.js.map +1 -0
- package/dist/esm/extensions/erc7702/account/types.js +54 -0
- package/dist/esm/extensions/erc7702/account/types.js.map +1 -0
- package/dist/esm/react/web/ui/Bridge/BridgeOrchestrator.js +2 -2
- package/dist/esm/react/web/ui/Bridge/BridgeOrchestrator.js.map +1 -1
- package/dist/esm/react/web/ui/Bridge/BuyWidget.js +1 -1
- package/dist/esm/react/web/ui/Bridge/BuyWidget.js.map +1 -1
- package/dist/esm/react/web/ui/Bridge/CheckoutWidget.js +1 -1
- package/dist/esm/react/web/ui/Bridge/CheckoutWidget.js.map +1 -1
- package/dist/esm/react/web/ui/Bridge/TransactionWidget.js +1 -1
- package/dist/esm/react/web/ui/Bridge/TransactionWidget.js.map +1 -1
- package/dist/esm/react/web/ui/Bridge/payment-details/PaymentDetails.js +1 -1
- package/dist/esm/react/web/ui/Bridge/payment-details/PaymentDetails.js.map +1 -1
- package/dist/esm/react/web/ui/Bridge/payment-selection/PaymentSelection.js +3 -3
- package/dist/esm/react/web/ui/Bridge/payment-selection/PaymentSelection.js.map +1 -1
- package/dist/esm/react/web/ui/Bridge/payment-selection/WalletFiatSelection.js +37 -37
- package/dist/esm/react/web/ui/Bridge/payment-selection/WalletFiatSelection.js.map +1 -1
- package/dist/esm/react/web/ui/PayEmbed.js +11 -4
- package/dist/esm/react/web/ui/PayEmbed.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/wallets/in-app/core/authentication/backend.js +2 -1
- package/dist/esm/wallets/in-app/core/authentication/backend.js.map +1 -1
- package/dist/esm/wallets/in-app/core/authentication/guest.js +2 -8
- package/dist/esm/wallets/in-app/core/authentication/guest.js.map +1 -1
- package/dist/esm/wallets/in-app/core/eip7702/minimal-account.js +1 -1
- package/dist/esm/wallets/in-app/native/native-connector.js +1 -1
- package/dist/esm/wallets/in-app/native/native-connector.js.map +1 -1
- package/dist/esm/wallets/in-app/web/lib/web-connector.js +1 -1
- package/dist/esm/wallets/in-app/web/lib/web-connector.js.map +1 -1
- package/dist/types/engine/server-wallet.d.ts +5 -2
- package/dist/types/engine/server-wallet.d.ts.map +1 -1
- package/dist/types/exports/wallets/in-app.d.ts +2 -0
- package/dist/types/exports/wallets/in-app.d.ts.map +1 -1
- package/dist/types/exports/wallets/in-app.native.d.ts +2 -0
- package/dist/types/exports/wallets/in-app.native.d.ts.map +1 -1
- package/dist/types/extensions/erc7702/account/createSessionKey.d.ts +69 -0
- package/dist/types/extensions/erc7702/account/createSessionKey.d.ts.map +1 -0
- package/dist/types/extensions/erc7702/account/types.d.ts +107 -0
- package/dist/types/extensions/erc7702/account/types.d.ts.map +1 -0
- package/dist/types/react/web/ui/Bridge/BridgeOrchestrator.d.ts +6 -1
- package/dist/types/react/web/ui/Bridge/BridgeOrchestrator.d.ts.map +1 -1
- package/dist/types/react/web/ui/Bridge/BuyWidget.d.ts +5 -0
- package/dist/types/react/web/ui/Bridge/BuyWidget.d.ts.map +1 -1
- package/dist/types/react/web/ui/Bridge/CheckoutWidget.d.ts +5 -0
- package/dist/types/react/web/ui/Bridge/CheckoutWidget.d.ts.map +1 -1
- package/dist/types/react/web/ui/Bridge/TransactionWidget.d.ts +5 -0
- package/dist/types/react/web/ui/Bridge/TransactionWidget.d.ts.map +1 -1
- package/dist/types/react/web/ui/Bridge/payment-details/PaymentDetails.d.ts.map +1 -1
- package/dist/types/react/web/ui/Bridge/payment-selection/PaymentSelection.d.ts +6 -1
- package/dist/types/react/web/ui/Bridge/payment-selection/PaymentSelection.d.ts.map +1 -1
- package/dist/types/react/web/ui/Bridge/payment-selection/WalletFiatSelection.d.ts +2 -1
- package/dist/types/react/web/ui/Bridge/payment-selection/WalletFiatSelection.d.ts.map +1 -1
- package/dist/types/react/web/ui/PayEmbed.d.ts +0 -1
- package/dist/types/react/web/ui/PayEmbed.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/wallets/in-app/core/authentication/backend.d.ts.map +1 -1
- package/dist/types/wallets/in-app/core/authentication/guest.d.ts +2 -2
- package/dist/types/wallets/in-app/core/authentication/guest.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/engine/server-wallet.test.ts +23 -28
- package/src/engine/server-wallet.ts +80 -26
- package/src/engine/wait-for-tx-hash.ts +1 -1
- package/src/exports/wallets/in-app.native.ts +10 -0
- package/src/exports/wallets/in-app.ts +10 -0
- package/src/extensions/erc7702/account/createSessionKey.ts +181 -0
- package/src/extensions/erc7702/account/sessionkey.test.ts +132 -0
- package/src/extensions/erc7702/account/types.ts +94 -0
- package/src/react/web/ui/Bridge/BridgeOrchestrator.tsx +8 -0
- package/src/react/web/ui/Bridge/BuyWidget.tsx +7 -0
- package/src/react/web/ui/Bridge/CheckoutWidget.tsx +7 -0
- package/src/react/web/ui/Bridge/TransactionWidget.tsx +7 -0
- package/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx +3 -7
- package/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx +10 -2
- package/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx +133 -124
- package/src/react/web/ui/PayEmbed.tsx +17 -1
- package/src/version.ts +1 -1
- package/src/wallets/in-app/core/authentication/backend.test.ts +1 -0
- package/src/wallets/in-app/core/authentication/backend.ts +2 -1
- package/src/wallets/in-app/core/authentication/guest.ts +4 -11
- package/src/wallets/in-app/core/eip7702/minimal-account.ts +1 -1
- package/src/wallets/in-app/native/native-connector.ts +1 -1
- package/src/wallets/in-app/web/lib/in-app-gateway.test.ts +126 -0
- package/src/wallets/in-app/web/lib/web-connector.ts +1 -1
@@ -1,7 +1,8 @@
|
|
1
1
|
import {
|
2
|
-
|
3
|
-
type
|
4
|
-
type
|
2
|
+
isSuccessResponse,
|
3
|
+
type SendTransactionData,
|
4
|
+
type SignMessageData,
|
5
|
+
type SpecificExecutionOptions,
|
5
6
|
sendTransaction,
|
6
7
|
signMessage,
|
7
8
|
signTypedData,
|
@@ -16,12 +17,15 @@ import { type Hex, toHex } from "../utils/encoding/hex.js";
|
|
16
17
|
import { getClientFetch } from "../utils/fetch.js";
|
17
18
|
import { stringify } from "../utils/json.js";
|
18
19
|
import { resolvePromisedValue } from "../utils/promise/resolve-promised-value.js";
|
20
|
+
import type { Prettify } from "../utils/type-utils.js";
|
19
21
|
import type {
|
20
22
|
Account,
|
21
23
|
SendTransactionOption,
|
22
24
|
} from "../wallets/interfaces/wallet.js";
|
23
25
|
import { waitForTransactionHash } from "./wait-for-tx-hash.js";
|
24
26
|
|
27
|
+
type ExecutionOptions = Prettify<SpecificExecutionOptions>;
|
28
|
+
|
25
29
|
/**
|
26
30
|
* Options for creating an server wallet.
|
27
31
|
*/
|
@@ -45,10 +49,7 @@ export type ServerWalletOptions = {
|
|
45
49
|
/**
|
46
50
|
* Optional custom execution options to use for sending transactions and signing data.
|
47
51
|
*/
|
48
|
-
executionOptions?:
|
49
|
-
| Omit<AaExecutionOptions, "chainId">
|
50
|
-
| Omit<AaZksyncExecutionOptions, "chainId">
|
51
|
-
| Omit<EoaExecutionOptions, "chainId">;
|
52
|
+
executionOptions?: ExecutionOptions;
|
52
53
|
};
|
53
54
|
|
54
55
|
export type ServerWallet = Account & {
|
@@ -150,20 +151,74 @@ export type ServerWallet = Account & {
|
|
150
151
|
export function serverWallet(options: ServerWalletOptions): ServerWallet {
|
151
152
|
const { client, vaultAccessToken, address, chain, executionOptions } =
|
152
153
|
options;
|
154
|
+
|
153
155
|
const headers: HeadersInit = {
|
154
156
|
"x-vault-access-token": vaultAccessToken,
|
155
157
|
};
|
156
158
|
|
157
|
-
const
|
158
|
-
|
159
|
-
|
159
|
+
const getExecutionOptionsWithChainId = (
|
160
|
+
chainId: number,
|
161
|
+
): SendTransactionData["body"]["executionOptions"] => {
|
162
|
+
if (!executionOptions) {
|
163
|
+
return {
|
164
|
+
chainId,
|
165
|
+
from: address,
|
166
|
+
type: "auto",
|
167
|
+
};
|
168
|
+
}
|
169
|
+
switch (executionOptions.type) {
|
170
|
+
case "auto":
|
171
|
+
return {
|
172
|
+
chainId,
|
173
|
+
from: address,
|
174
|
+
type: "auto",
|
175
|
+
};
|
176
|
+
case "ERC4337":
|
177
|
+
return {
|
178
|
+
...executionOptions,
|
179
|
+
chainId,
|
180
|
+
type: "ERC4337",
|
181
|
+
};
|
182
|
+
}
|
183
|
+
};
|
184
|
+
|
185
|
+
const getSigningOptions = (
|
186
|
+
chainId: number | undefined,
|
187
|
+
): SignMessageData["body"]["signingOptions"] => {
|
188
|
+
// if no chainId passed specifically for this signature
|
189
|
+
// we HAVE TO fallback to EOA signature
|
190
|
+
if (!chainId) {
|
191
|
+
return {
|
192
|
+
from: address,
|
193
|
+
type: "eoa",
|
194
|
+
};
|
195
|
+
}
|
196
|
+
|
197
|
+
if (!executionOptions) {
|
198
|
+
return {
|
199
|
+
chainId,
|
200
|
+
from: address,
|
201
|
+
type: "auto",
|
202
|
+
};
|
203
|
+
}
|
204
|
+
|
205
|
+
switch (executionOptions.type) {
|
206
|
+
case "ERC4337": {
|
207
|
+
return {
|
208
|
+
chainId,
|
160
209
|
...executionOptions,
|
161
|
-
|
162
|
-
}
|
163
|
-
|
164
|
-
|
210
|
+
type: "ERC4337",
|
211
|
+
};
|
212
|
+
}
|
213
|
+
|
214
|
+
case "auto": {
|
215
|
+
return {
|
216
|
+
chainId,
|
165
217
|
from: address,
|
218
|
+
type: "auto",
|
166
219
|
};
|
220
|
+
}
|
221
|
+
}
|
167
222
|
};
|
168
223
|
|
169
224
|
const enqueueTx = async (transaction: SendTransactionOption[]) => {
|
@@ -184,10 +239,10 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet {
|
|
184
239
|
}
|
185
240
|
}
|
186
241
|
const body = {
|
187
|
-
executionOptions:
|
242
|
+
executionOptions: getExecutionOptionsWithChainId(chainId),
|
188
243
|
params: transaction.map((t) => ({
|
189
244
|
data: t.data,
|
190
|
-
to: t.to
|
245
|
+
to: t.to,
|
191
246
|
value: t.value?.toString(),
|
192
247
|
})),
|
193
248
|
};
|
@@ -307,17 +362,16 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet {
|
|
307
362
|
if (!signingChainId) {
|
308
363
|
throw new Error("Chain ID is required for signing messages");
|
309
364
|
}
|
310
|
-
|
311
365
|
const signResult = await signMessage({
|
312
366
|
baseUrl: getThirdwebBaseUrl("engineCloud"),
|
313
367
|
body: {
|
314
|
-
executionOptions: getExecutionOptions(signingChainId),
|
315
368
|
params: [
|
316
369
|
{
|
370
|
+
format: isBytes ? "hex" : "text",
|
317
371
|
message: engineMessage,
|
318
|
-
messageFormat: isBytes ? "hex" : "text",
|
319
372
|
},
|
320
373
|
],
|
374
|
+
signingOptions: getSigningOptions(signingChainId),
|
321
375
|
},
|
322
376
|
bodySerializer: stringify,
|
323
377
|
fetch: getClientFetch(client),
|
@@ -330,13 +384,13 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet {
|
|
330
384
|
);
|
331
385
|
}
|
332
386
|
|
333
|
-
const signatureResult = signResult.data?.result
|
334
|
-
if (signatureResult
|
387
|
+
const signatureResult = signResult.data?.result[0];
|
388
|
+
if (signatureResult && isSuccessResponse(signatureResult)) {
|
335
389
|
return signatureResult.result.signature as Hex;
|
336
390
|
}
|
337
391
|
|
338
392
|
throw new Error(
|
339
|
-
`Failed to sign message: ${signatureResult?.error
|
393
|
+
`Failed to sign message: ${stringify(signatureResult?.error) || "Unknown error"}`,
|
340
394
|
);
|
341
395
|
},
|
342
396
|
signTypedData: async (typedData) => {
|
@@ -348,9 +402,9 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet {
|
|
348
402
|
const signResult = await signTypedData({
|
349
403
|
baseUrl: getThirdwebBaseUrl("engineCloud"),
|
350
404
|
body: {
|
351
|
-
executionOptions: getExecutionOptions(signingChainId),
|
352
405
|
// biome-ignore lint/suspicious/noExplicitAny: TODO: fix ts / hey-api type clash
|
353
406
|
params: [typedData as any],
|
407
|
+
signingOptions: getSigningOptions(signingChainId),
|
354
408
|
},
|
355
409
|
bodySerializer: stringify,
|
356
410
|
fetch: getClientFetch(client),
|
@@ -363,13 +417,13 @@ export function serverWallet(options: ServerWalletOptions): ServerWallet {
|
|
363
417
|
);
|
364
418
|
}
|
365
419
|
|
366
|
-
const signatureResult = signResult.data?.result
|
367
|
-
if (signatureResult
|
420
|
+
const signatureResult = signResult.data?.result[0];
|
421
|
+
if (signatureResult && isSuccessResponse(signatureResult)) {
|
368
422
|
return signatureResult.result.signature as Hex;
|
369
423
|
}
|
370
424
|
|
371
425
|
throw new Error(
|
372
|
-
`Failed to sign message: ${signatureResult?.error
|
426
|
+
`Failed to sign message: ${stringify(signatureResult?.error) || "Unknown error"}`,
|
373
427
|
);
|
374
428
|
},
|
375
429
|
};
|
@@ -38,7 +38,7 @@ export async function waitForTransactionHash(args: {
|
|
38
38
|
switch (status) {
|
39
39
|
case "FAILED": {
|
40
40
|
throw new Error(
|
41
|
-
`Transaction failed: ${executionResult.error || "Unknown error"}`,
|
41
|
+
`Transaction failed: ${stringify(executionResult.error) || "Unknown error"}`,
|
42
42
|
);
|
43
43
|
}
|
44
44
|
case "CONFIRMED": {
|
@@ -1,5 +1,15 @@
|
|
1
1
|
// --- KEEEP IN SYNC with exports/wallets/in-app.ts ---
|
2
2
|
|
3
|
+
//ACCOUNT
|
4
|
+
export {
|
5
|
+
type CreateSessionKeyOptions,
|
6
|
+
createSessionKey,
|
7
|
+
isCreateSessionKeySupported,
|
8
|
+
} from "../../extensions/erc7702/account/createSessionKey.js";
|
9
|
+
export type {
|
10
|
+
Condition,
|
11
|
+
LimitType,
|
12
|
+
} from "../../extensions/erc7702/account/types.js";
|
3
13
|
export type {
|
4
14
|
GetAuthenticatedUserParams,
|
5
15
|
MultiStepAuthArgsType,
|
@@ -1,5 +1,15 @@
|
|
1
1
|
// --- KEEEP IN SYNC with exports/wallets/in-app.native.ts ---
|
2
2
|
|
3
|
+
//ACCOUNT
|
4
|
+
export {
|
5
|
+
type CreateSessionKeyOptions,
|
6
|
+
createSessionKey,
|
7
|
+
isCreateSessionKeySupported,
|
8
|
+
} from "../../extensions/erc7702/account/createSessionKey.js";
|
9
|
+
export type {
|
10
|
+
Condition,
|
11
|
+
LimitType,
|
12
|
+
} from "../../extensions/erc7702/account/types.js";
|
3
13
|
export {
|
4
14
|
getSocialIcon,
|
5
15
|
socialIcons,
|
@@ -0,0 +1,181 @@
|
|
1
|
+
import type { BaseTransactionOptions } from "../../../transaction/types.js";
|
2
|
+
import { randomBytesHex } from "../../../utils/random.js";
|
3
|
+
import type { Account } from "../../../wallets/interfaces/wallet.js";
|
4
|
+
import {
|
5
|
+
createSessionWithSig,
|
6
|
+
isCreateSessionWithSigSupported,
|
7
|
+
} from "../__generated__/MinimalAccount/write/createSessionWithSig.js";
|
8
|
+
import {
|
9
|
+
type CallSpecInput,
|
10
|
+
CallSpecRequest,
|
11
|
+
ConstraintRequest,
|
12
|
+
SessionSpecRequest,
|
13
|
+
type TransferSpecInput,
|
14
|
+
TransferSpecRequest,
|
15
|
+
UsageLimitRequest,
|
16
|
+
} from "./types.js";
|
17
|
+
|
18
|
+
/**
|
19
|
+
* @extension ERC7702
|
20
|
+
*/
|
21
|
+
export type CreateSessionKeyOptions = {
|
22
|
+
/**
|
23
|
+
* The admin account that will perform the operation.
|
24
|
+
*/
|
25
|
+
account: Account;
|
26
|
+
/**
|
27
|
+
* The address to add as a session key.
|
28
|
+
*/
|
29
|
+
sessionKeyAddress: string;
|
30
|
+
/**
|
31
|
+
* How long the session key should be valid for, in seconds.
|
32
|
+
*/
|
33
|
+
durationInSeconds: number;
|
34
|
+
/**
|
35
|
+
* Whether to grant full execution permissions to the session key.
|
36
|
+
*/
|
37
|
+
grantFullPermissions?: boolean;
|
38
|
+
/**
|
39
|
+
* Smart contract interaction policies to apply to the session key, ignored if grantFullPermissions is true.
|
40
|
+
*/
|
41
|
+
callPolicies?: CallSpecInput[];
|
42
|
+
/**
|
43
|
+
* Value transfer policies to apply to the session key, ignored if grantFullPermissions is true.
|
44
|
+
*/
|
45
|
+
transferPolicies?: TransferSpecInput[];
|
46
|
+
};
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Creates session key permissions for a specified address.
|
50
|
+
* @param options - The options for the createSessionKey function.
|
51
|
+
* @param {Contract} options.contract - The EIP-7702 smart EOA contract to create the session key from
|
52
|
+
* @returns The transaction object to be sent.
|
53
|
+
* @example
|
54
|
+
* ```ts
|
55
|
+
* import { createSessionKey } from 'thirdweb/extensions/7702';
|
56
|
+
* import { sendTransaction } from 'thirdweb';
|
57
|
+
*
|
58
|
+
* const transaction = createSessionKey({
|
59
|
+
* account: account,
|
60
|
+
* contract: accountContract,
|
61
|
+
* sessionKeyAddress: TEST_ACCOUNT_A.address,
|
62
|
+
* durationInSeconds: 86400, // 1 day
|
63
|
+
* grantFullPermissions: true
|
64
|
+
*})
|
65
|
+
*
|
66
|
+
* await sendTransaction({ transaction, account });
|
67
|
+
* ```
|
68
|
+
* @extension ERC7702
|
69
|
+
*/
|
70
|
+
export function createSessionKey(
|
71
|
+
options: BaseTransactionOptions<CreateSessionKeyOptions>,
|
72
|
+
) {
|
73
|
+
const {
|
74
|
+
contract,
|
75
|
+
account,
|
76
|
+
sessionKeyAddress,
|
77
|
+
durationInSeconds,
|
78
|
+
grantFullPermissions,
|
79
|
+
callPolicies,
|
80
|
+
transferPolicies,
|
81
|
+
} = options;
|
82
|
+
|
83
|
+
if (durationInSeconds <= 0) {
|
84
|
+
throw new Error("durationInSeconds must be positive");
|
85
|
+
}
|
86
|
+
|
87
|
+
return createSessionWithSig({
|
88
|
+
async asyncParams() {
|
89
|
+
const req = {
|
90
|
+
callPolicies: (callPolicies || []).map((policy) => ({
|
91
|
+
constraints: (policy.constraints || []).map((constraint) => ({
|
92
|
+
condition: Number(constraint.condition),
|
93
|
+
index: constraint.index || BigInt(0),
|
94
|
+
limit: constraint.limit
|
95
|
+
? {
|
96
|
+
limit: constraint.limit.limit,
|
97
|
+
limitType: Number(constraint.limit.limitType),
|
98
|
+
period: constraint.limit.period,
|
99
|
+
}
|
100
|
+
: {
|
101
|
+
limit: BigInt(0),
|
102
|
+
limitType: 0,
|
103
|
+
period: BigInt(0),
|
104
|
+
},
|
105
|
+
refValue: constraint.refValue || "0x",
|
106
|
+
})),
|
107
|
+
maxValuePerUse: policy.maxValuePerUse || BigInt(0),
|
108
|
+
selector: policy.selector,
|
109
|
+
target: policy.target,
|
110
|
+
valueLimit: policy.valueLimit
|
111
|
+
? {
|
112
|
+
limit: policy.valueLimit.limit,
|
113
|
+
limitType: Number(policy.valueLimit.limitType),
|
114
|
+
period: policy.valueLimit.period,
|
115
|
+
}
|
116
|
+
: {
|
117
|
+
limit: BigInt(0),
|
118
|
+
limitType: 0,
|
119
|
+
period: BigInt(0),
|
120
|
+
},
|
121
|
+
})),
|
122
|
+
expiresAt: BigInt(Math.floor(Date.now() / 1000) + durationInSeconds),
|
123
|
+
isWildcard: grantFullPermissions ?? true,
|
124
|
+
signer: sessionKeyAddress,
|
125
|
+
transferPolicies: (transferPolicies || []).map((policy) => ({
|
126
|
+
maxValuePerUse: policy.maxValuePerUse || BigInt(0),
|
127
|
+
target: policy.target,
|
128
|
+
valueLimit: policy.valueLimit
|
129
|
+
? {
|
130
|
+
limit: policy.valueLimit.limit,
|
131
|
+
limitType: Number(policy.valueLimit.limitType),
|
132
|
+
period: policy.valueLimit.period,
|
133
|
+
}
|
134
|
+
: {
|
135
|
+
limit: BigInt(0),
|
136
|
+
limitType: 0,
|
137
|
+
period: BigInt(0),
|
138
|
+
},
|
139
|
+
})),
|
140
|
+
uid: await randomBytesHex(),
|
141
|
+
};
|
142
|
+
|
143
|
+
const signature = await account.signTypedData({
|
144
|
+
domain: {
|
145
|
+
chainId: contract.chain.id,
|
146
|
+
name: "MinimalAccount",
|
147
|
+
verifyingContract: contract.address,
|
148
|
+
version: "1",
|
149
|
+
},
|
150
|
+
message: req,
|
151
|
+
primaryType: "SessionSpec",
|
152
|
+
types: {
|
153
|
+
CallSpec: CallSpecRequest,
|
154
|
+
Constraint: ConstraintRequest,
|
155
|
+
SessionSpec: SessionSpecRequest,
|
156
|
+
TransferSpec: TransferSpecRequest,
|
157
|
+
UsageLimit: UsageLimitRequest,
|
158
|
+
},
|
159
|
+
});
|
160
|
+
|
161
|
+
return { sessionSpec: req, signature };
|
162
|
+
},
|
163
|
+
contract,
|
164
|
+
});
|
165
|
+
}
|
166
|
+
|
167
|
+
/**
|
168
|
+
* Checks if the `isCreateSessionKeySupported` method is supported by the given contract.
|
169
|
+
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
|
170
|
+
* @returns A boolean indicating if the `isAddSessionKeySupported` method is supported.
|
171
|
+
* @extension ERC7702
|
172
|
+
* @example
|
173
|
+
* ```ts
|
174
|
+
* import { isCreateSessionKeySupported } from "thirdweb/extensions/erc7702";
|
175
|
+
*
|
176
|
+
* const supported = isCreateSessionKeySupported(["0x..."]);
|
177
|
+
* ```
|
178
|
+
*/
|
179
|
+
export function isCreateSessionKeySupported(availableSelectors: string[]) {
|
180
|
+
return isCreateSessionWithSigSupported(availableSelectors);
|
181
|
+
}
|
@@ -0,0 +1,132 @@
|
|
1
|
+
import { defineChain } from "src/chains/utils.js";
|
2
|
+
import { prepareTransaction } from "src/transaction/prepare-transaction.js";
|
3
|
+
import { inAppWallet } from "src/wallets/in-app/web/in-app.js";
|
4
|
+
import type { Account } from "src/wallets/interfaces/wallet.js";
|
5
|
+
import { beforeAll, describe, expect, it } from "vitest";
|
6
|
+
import { TEST_CLIENT } from "../../../../test/src/test-clients.js";
|
7
|
+
import { TEST_ACCOUNT_A } from "../../../../test/src/test-wallets.js";
|
8
|
+
import { ZERO_ADDRESS } from "../../../constants/addresses.js";
|
9
|
+
import {
|
10
|
+
getContract,
|
11
|
+
type ThirdwebContract,
|
12
|
+
} from "../../../contract/contract.js";
|
13
|
+
import { parseEventLogs } from "../../../event/actions/parse-logs.js";
|
14
|
+
import { sendAndConfirmTransaction } from "../../../transaction/actions/send-and-confirm-transaction.js";
|
15
|
+
import { sessionCreatedEvent } from "../__generated__/MinimalAccount/events/SessionCreated.js";
|
16
|
+
import { createSessionKey } from "./createSessionKey.js";
|
17
|
+
import { Condition, LimitType } from "./types.js";
|
18
|
+
|
19
|
+
describe.runIf(process.env.TW_SECRET_KEY)(
|
20
|
+
"Session Key Behavior",
|
21
|
+
{
|
22
|
+
retry: 0,
|
23
|
+
timeout: 240_000,
|
24
|
+
},
|
25
|
+
() => {
|
26
|
+
const chainId = 11155111;
|
27
|
+
let account: Account;
|
28
|
+
let accountContract: ThirdwebContract;
|
29
|
+
|
30
|
+
beforeAll(async () => {
|
31
|
+
// Create 7702 Smart EOA
|
32
|
+
const wallet = inAppWallet({
|
33
|
+
executionMode: {
|
34
|
+
mode: "EIP7702",
|
35
|
+
sponsorGas: true,
|
36
|
+
},
|
37
|
+
});
|
38
|
+
account = await wallet.connect({
|
39
|
+
chain: defineChain(chainId),
|
40
|
+
client: TEST_CLIENT,
|
41
|
+
strategy: "guest",
|
42
|
+
});
|
43
|
+
|
44
|
+
// Send a null tx to trigger deploy/upgrade
|
45
|
+
await sendAndConfirmTransaction({
|
46
|
+
account: account,
|
47
|
+
transaction: prepareTransaction({
|
48
|
+
chain: defineChain(chainId),
|
49
|
+
client: TEST_CLIENT,
|
50
|
+
to: account.address,
|
51
|
+
value: 0n,
|
52
|
+
}),
|
53
|
+
});
|
54
|
+
|
55
|
+
// Will auto resolve abi since it's deployed
|
56
|
+
accountContract = getContract({
|
57
|
+
address: account.address,
|
58
|
+
chain: defineChain(chainId),
|
59
|
+
client: TEST_CLIENT,
|
60
|
+
});
|
61
|
+
}, 120_000);
|
62
|
+
|
63
|
+
it("should allow adding adminlike session keys", async () => {
|
64
|
+
const receipt = await sendAndConfirmTransaction({
|
65
|
+
account: account,
|
66
|
+
transaction: createSessionKey({
|
67
|
+
account: account,
|
68
|
+
contract: accountContract,
|
69
|
+
durationInSeconds: 86400,
|
70
|
+
grantFullPermissions: true, // 1 day
|
71
|
+
sessionKeyAddress: TEST_ACCOUNT_A.address,
|
72
|
+
}),
|
73
|
+
});
|
74
|
+
const logs = parseEventLogs({
|
75
|
+
events: [sessionCreatedEvent()],
|
76
|
+
logs: receipt.logs,
|
77
|
+
});
|
78
|
+
expect(logs[0]?.args.signer).toBe(TEST_ACCOUNT_A.address);
|
79
|
+
});
|
80
|
+
|
81
|
+
it("should allow adding granular session keys", async () => {
|
82
|
+
const receipt = await sendAndConfirmTransaction({
|
83
|
+
account: account,
|
84
|
+
transaction: createSessionKey({
|
85
|
+
account: account,
|
86
|
+
callPolicies: [
|
87
|
+
{
|
88
|
+
constraints: [
|
89
|
+
{
|
90
|
+
condition: Condition.Unconstrained,
|
91
|
+
index: 0n,
|
92
|
+
refValue:
|
93
|
+
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
94
|
+
},
|
95
|
+
],
|
96
|
+
maxValuePerUse: 0n,
|
97
|
+
selector: "0x00000000",
|
98
|
+
target: ZERO_ADDRESS,
|
99
|
+
valueLimit: {
|
100
|
+
limit: 0n,
|
101
|
+
limitType: LimitType.Unlimited,
|
102
|
+
period: 0n,
|
103
|
+
},
|
104
|
+
},
|
105
|
+
],
|
106
|
+
contract: accountContract,
|
107
|
+
durationInSeconds: 86400, // 1 day
|
108
|
+
grantFullPermissions: false,
|
109
|
+
sessionKeyAddress: TEST_ACCOUNT_A.address,
|
110
|
+
transferPolicies: [
|
111
|
+
{
|
112
|
+
maxValuePerUse: 0n,
|
113
|
+
target: ZERO_ADDRESS,
|
114
|
+
valueLimit: {
|
115
|
+
limit: 0n,
|
116
|
+
limitType: 0,
|
117
|
+
period: 0n,
|
118
|
+
},
|
119
|
+
},
|
120
|
+
],
|
121
|
+
}),
|
122
|
+
});
|
123
|
+
const logs = parseEventLogs({
|
124
|
+
events: [sessionCreatedEvent()],
|
125
|
+
logs: receipt.logs,
|
126
|
+
});
|
127
|
+
expect(logs[0]?.args.signer).toBe(TEST_ACCOUNT_A.address);
|
128
|
+
expect(logs[0]?.args.sessionSpec.callPolicies).toHaveLength(1);
|
129
|
+
expect(logs[0]?.args.sessionSpec.transferPolicies).toHaveLength(1);
|
130
|
+
});
|
131
|
+
},
|
132
|
+
);
|
@@ -0,0 +1,94 @@
|
|
1
|
+
/* ────────────────────────────────
|
2
|
+
Enums
|
3
|
+
──────────────────────────────── */
|
4
|
+
|
5
|
+
export enum LimitType {
|
6
|
+
Unlimited = 0,
|
7
|
+
Lifetime = 1,
|
8
|
+
Allowance = 2,
|
9
|
+
}
|
10
|
+
|
11
|
+
export enum Condition {
|
12
|
+
Unconstrained = 0,
|
13
|
+
Equal = 1,
|
14
|
+
Greater = 2,
|
15
|
+
Less = 3,
|
16
|
+
GreaterOrEqual = 4,
|
17
|
+
LessOrEqual = 5,
|
18
|
+
NotEqual = 6,
|
19
|
+
}
|
20
|
+
|
21
|
+
/* ────────────────────────────────
|
22
|
+
Input types
|
23
|
+
──────────────────────────────── */
|
24
|
+
|
25
|
+
/* ---------- UsageLimit ---------- */
|
26
|
+
interface UsageLimitInput {
|
27
|
+
limitType: LimitType;
|
28
|
+
limit: bigint;
|
29
|
+
period: bigint;
|
30
|
+
}
|
31
|
+
|
32
|
+
/* ---------- Constraint ---------- */
|
33
|
+
interface ConstraintInput {
|
34
|
+
condition: Condition;
|
35
|
+
index: bigint;
|
36
|
+
refValue: `0x${string}`;
|
37
|
+
limit?: UsageLimitInput;
|
38
|
+
}
|
39
|
+
|
40
|
+
/* ---------- CallSpec ---------- */
|
41
|
+
export interface CallSpecInput {
|
42
|
+
target: `0x${string}`;
|
43
|
+
selector: `0x${string}`;
|
44
|
+
maxValuePerUse?: bigint;
|
45
|
+
valueLimit?: UsageLimitInput;
|
46
|
+
constraints?: ConstraintInput[];
|
47
|
+
}
|
48
|
+
|
49
|
+
/* ---------- TransferSpec ---------- */
|
50
|
+
export interface TransferSpecInput {
|
51
|
+
target: `0x${string}`;
|
52
|
+
maxValuePerUse?: bigint;
|
53
|
+
valueLimit?: UsageLimitInput;
|
54
|
+
}
|
55
|
+
|
56
|
+
/* ────────────────────────────────
|
57
|
+
EIP-712 structs
|
58
|
+
──────────────────────────────── */
|
59
|
+
|
60
|
+
export const UsageLimitRequest = [
|
61
|
+
{ name: "limitType", type: "uint8" },
|
62
|
+
{ name: "limit", type: "uint256" },
|
63
|
+
{ name: "period", type: "uint256" },
|
64
|
+
] as const;
|
65
|
+
|
66
|
+
export const ConstraintRequest = [
|
67
|
+
{ name: "condition", type: "uint8" },
|
68
|
+
{ name: "index", type: "uint64" },
|
69
|
+
{ name: "refValue", type: "bytes32" },
|
70
|
+
{ name: "limit", type: "UsageLimit" },
|
71
|
+
] as const;
|
72
|
+
|
73
|
+
export const CallSpecRequest = [
|
74
|
+
{ name: "target", type: "address" },
|
75
|
+
{ name: "selector", type: "bytes4" },
|
76
|
+
{ name: "maxValuePerUse", type: "uint256" },
|
77
|
+
{ name: "valueLimit", type: "UsageLimit" },
|
78
|
+
{ name: "constraints", type: "Constraint[]" },
|
79
|
+
] as const;
|
80
|
+
|
81
|
+
export const TransferSpecRequest = [
|
82
|
+
{ name: "target", type: "address" },
|
83
|
+
{ name: "maxValuePerUse", type: "uint256" },
|
84
|
+
{ name: "valueLimit", type: "UsageLimit" },
|
85
|
+
] as const;
|
86
|
+
|
87
|
+
export const SessionSpecRequest = [
|
88
|
+
{ name: "signer", type: "address" },
|
89
|
+
{ name: "isWildcard", type: "bool" },
|
90
|
+
{ name: "expiresAt", type: "uint256" },
|
91
|
+
{ name: "callPolicies", type: "CallSpec[]" },
|
92
|
+
{ name: "transferPolicies", type: "TransferSpec[]" },
|
93
|
+
{ name: "uid", type: "bytes32" },
|
94
|
+
] as const;
|
@@ -113,6 +113,12 @@ export interface BridgeOrchestratorProps {
|
|
113
113
|
* Quick buy amounts
|
114
114
|
*/
|
115
115
|
presetOptions: [number, number, number] | undefined;
|
116
|
+
|
117
|
+
/**
|
118
|
+
* Allowed payment methods
|
119
|
+
* @default ["crypto", "card"]
|
120
|
+
*/
|
121
|
+
paymentMethods?: ("crypto" | "card")[];
|
116
122
|
}
|
117
123
|
|
118
124
|
export function BridgeOrchestrator({
|
@@ -127,6 +133,7 @@ export function BridgeOrchestrator({
|
|
127
133
|
purchaseData,
|
128
134
|
paymentLinkId,
|
129
135
|
presetOptions,
|
136
|
+
paymentMethods = ["crypto", "card"],
|
130
137
|
}: BridgeOrchestratorProps) {
|
131
138
|
// Initialize adapters
|
132
139
|
const adapters = useMemo(
|
@@ -270,6 +277,7 @@ export function BridgeOrchestrator({
|
|
270
277
|
}}
|
271
278
|
onError={handleError}
|
272
279
|
onPaymentMethodSelected={handlePaymentMethodSelected}
|
280
|
+
paymentMethods={paymentMethods}
|
273
281
|
receiverAddress={state.context.receiverAddress}
|
274
282
|
/>
|
275
283
|
)}
|
@@ -160,6 +160,12 @@ export type BuyWidgetProps = {
|
|
160
160
|
* @hidden
|
161
161
|
*/
|
162
162
|
paymentLinkId?: string;
|
163
|
+
|
164
|
+
/**
|
165
|
+
* Allowed payment methods
|
166
|
+
* @default ["crypto", "card"]
|
167
|
+
*/
|
168
|
+
paymentMethods?: ("crypto" | "card")[];
|
163
169
|
};
|
164
170
|
|
165
171
|
// Enhanced UIOptions to handle unsupported token state
|
@@ -378,6 +384,7 @@ export function BuyWidget(props: BuyWidgetProps) {
|
|
378
384
|
props.onError?.(err);
|
379
385
|
}}
|
380
386
|
paymentLinkId={props.paymentLinkId}
|
387
|
+
paymentMethods={props.paymentMethods}
|
381
388
|
presetOptions={props.presetOptions}
|
382
389
|
purchaseData={props.purchaseData}
|
383
390
|
receiverAddress={undefined}
|