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.
Files changed (130) hide show
  1. package/dist/cjs/engine/server-wallet.js +64 -19
  2. package/dist/cjs/engine/server-wallet.js.map +1 -1
  3. package/dist/cjs/engine/wait-for-tx-hash.js +1 -1
  4. package/dist/cjs/engine/wait-for-tx-hash.js.map +1 -1
  5. package/dist/cjs/exports/wallets/in-app.js +5 -1
  6. package/dist/cjs/exports/wallets/in-app.js.map +1 -1
  7. package/dist/cjs/exports/wallets/in-app.native.js +5 -1
  8. package/dist/cjs/exports/wallets/in-app.native.js.map +1 -1
  9. package/dist/cjs/extensions/erc7702/account/createSessionKey.js +127 -0
  10. package/dist/cjs/extensions/erc7702/account/createSessionKey.js.map +1 -0
  11. package/dist/cjs/extensions/erc7702/account/types.js +57 -0
  12. package/dist/cjs/extensions/erc7702/account/types.js.map +1 -0
  13. package/dist/cjs/react/web/ui/Bridge/BridgeOrchestrator.js +2 -2
  14. package/dist/cjs/react/web/ui/Bridge/BridgeOrchestrator.js.map +1 -1
  15. package/dist/cjs/react/web/ui/Bridge/BuyWidget.js +1 -1
  16. package/dist/cjs/react/web/ui/Bridge/BuyWidget.js.map +1 -1
  17. package/dist/cjs/react/web/ui/Bridge/CheckoutWidget.js +1 -1
  18. package/dist/cjs/react/web/ui/Bridge/CheckoutWidget.js.map +1 -1
  19. package/dist/cjs/react/web/ui/Bridge/TransactionWidget.js +1 -1
  20. package/dist/cjs/react/web/ui/Bridge/TransactionWidget.js.map +1 -1
  21. package/dist/cjs/react/web/ui/Bridge/payment-details/PaymentDetails.js +1 -1
  22. package/dist/cjs/react/web/ui/Bridge/payment-details/PaymentDetails.js.map +1 -1
  23. package/dist/cjs/react/web/ui/Bridge/payment-selection/PaymentSelection.js +3 -3
  24. package/dist/cjs/react/web/ui/Bridge/payment-selection/PaymentSelection.js.map +1 -1
  25. package/dist/cjs/react/web/ui/Bridge/payment-selection/WalletFiatSelection.js +37 -37
  26. package/dist/cjs/react/web/ui/Bridge/payment-selection/WalletFiatSelection.js.map +1 -1
  27. package/dist/cjs/react/web/ui/PayEmbed.js +11 -4
  28. package/dist/cjs/react/web/ui/PayEmbed.js.map +1 -1
  29. package/dist/cjs/version.js +1 -1
  30. package/dist/cjs/wallets/in-app/core/authentication/backend.js +2 -1
  31. package/dist/cjs/wallets/in-app/core/authentication/backend.js.map +1 -1
  32. package/dist/cjs/wallets/in-app/core/authentication/guest.js +2 -8
  33. package/dist/cjs/wallets/in-app/core/authentication/guest.js.map +1 -1
  34. package/dist/cjs/wallets/in-app/core/eip7702/minimal-account.js +1 -1
  35. package/dist/cjs/wallets/in-app/native/native-connector.js +1 -1
  36. package/dist/cjs/wallets/in-app/native/native-connector.js.map +1 -1
  37. package/dist/cjs/wallets/in-app/web/lib/web-connector.js +1 -1
  38. package/dist/cjs/wallets/in-app/web/lib/web-connector.js.map +1 -1
  39. package/dist/esm/engine/server-wallet.js +65 -20
  40. package/dist/esm/engine/server-wallet.js.map +1 -1
  41. package/dist/esm/engine/wait-for-tx-hash.js +1 -1
  42. package/dist/esm/engine/wait-for-tx-hash.js.map +1 -1
  43. package/dist/esm/exports/wallets/in-app.js +2 -0
  44. package/dist/esm/exports/wallets/in-app.js.map +1 -1
  45. package/dist/esm/exports/wallets/in-app.native.js +2 -0
  46. package/dist/esm/exports/wallets/in-app.native.js.map +1 -1
  47. package/dist/esm/extensions/erc7702/account/createSessionKey.js +123 -0
  48. package/dist/esm/extensions/erc7702/account/createSessionKey.js.map +1 -0
  49. package/dist/esm/extensions/erc7702/account/types.js +54 -0
  50. package/dist/esm/extensions/erc7702/account/types.js.map +1 -0
  51. package/dist/esm/react/web/ui/Bridge/BridgeOrchestrator.js +2 -2
  52. package/dist/esm/react/web/ui/Bridge/BridgeOrchestrator.js.map +1 -1
  53. package/dist/esm/react/web/ui/Bridge/BuyWidget.js +1 -1
  54. package/dist/esm/react/web/ui/Bridge/BuyWidget.js.map +1 -1
  55. package/dist/esm/react/web/ui/Bridge/CheckoutWidget.js +1 -1
  56. package/dist/esm/react/web/ui/Bridge/CheckoutWidget.js.map +1 -1
  57. package/dist/esm/react/web/ui/Bridge/TransactionWidget.js +1 -1
  58. package/dist/esm/react/web/ui/Bridge/TransactionWidget.js.map +1 -1
  59. package/dist/esm/react/web/ui/Bridge/payment-details/PaymentDetails.js +1 -1
  60. package/dist/esm/react/web/ui/Bridge/payment-details/PaymentDetails.js.map +1 -1
  61. package/dist/esm/react/web/ui/Bridge/payment-selection/PaymentSelection.js +3 -3
  62. package/dist/esm/react/web/ui/Bridge/payment-selection/PaymentSelection.js.map +1 -1
  63. package/dist/esm/react/web/ui/Bridge/payment-selection/WalletFiatSelection.js +37 -37
  64. package/dist/esm/react/web/ui/Bridge/payment-selection/WalletFiatSelection.js.map +1 -1
  65. package/dist/esm/react/web/ui/PayEmbed.js +11 -4
  66. package/dist/esm/react/web/ui/PayEmbed.js.map +1 -1
  67. package/dist/esm/version.js +1 -1
  68. package/dist/esm/wallets/in-app/core/authentication/backend.js +2 -1
  69. package/dist/esm/wallets/in-app/core/authentication/backend.js.map +1 -1
  70. package/dist/esm/wallets/in-app/core/authentication/guest.js +2 -8
  71. package/dist/esm/wallets/in-app/core/authentication/guest.js.map +1 -1
  72. package/dist/esm/wallets/in-app/core/eip7702/minimal-account.js +1 -1
  73. package/dist/esm/wallets/in-app/native/native-connector.js +1 -1
  74. package/dist/esm/wallets/in-app/native/native-connector.js.map +1 -1
  75. package/dist/esm/wallets/in-app/web/lib/web-connector.js +1 -1
  76. package/dist/esm/wallets/in-app/web/lib/web-connector.js.map +1 -1
  77. package/dist/types/engine/server-wallet.d.ts +5 -2
  78. package/dist/types/engine/server-wallet.d.ts.map +1 -1
  79. package/dist/types/exports/wallets/in-app.d.ts +2 -0
  80. package/dist/types/exports/wallets/in-app.d.ts.map +1 -1
  81. package/dist/types/exports/wallets/in-app.native.d.ts +2 -0
  82. package/dist/types/exports/wallets/in-app.native.d.ts.map +1 -1
  83. package/dist/types/extensions/erc7702/account/createSessionKey.d.ts +69 -0
  84. package/dist/types/extensions/erc7702/account/createSessionKey.d.ts.map +1 -0
  85. package/dist/types/extensions/erc7702/account/types.d.ts +107 -0
  86. package/dist/types/extensions/erc7702/account/types.d.ts.map +1 -0
  87. package/dist/types/react/web/ui/Bridge/BridgeOrchestrator.d.ts +6 -1
  88. package/dist/types/react/web/ui/Bridge/BridgeOrchestrator.d.ts.map +1 -1
  89. package/dist/types/react/web/ui/Bridge/BuyWidget.d.ts +5 -0
  90. package/dist/types/react/web/ui/Bridge/BuyWidget.d.ts.map +1 -1
  91. package/dist/types/react/web/ui/Bridge/CheckoutWidget.d.ts +5 -0
  92. package/dist/types/react/web/ui/Bridge/CheckoutWidget.d.ts.map +1 -1
  93. package/dist/types/react/web/ui/Bridge/TransactionWidget.d.ts +5 -0
  94. package/dist/types/react/web/ui/Bridge/TransactionWidget.d.ts.map +1 -1
  95. package/dist/types/react/web/ui/Bridge/payment-details/PaymentDetails.d.ts.map +1 -1
  96. package/dist/types/react/web/ui/Bridge/payment-selection/PaymentSelection.d.ts +6 -1
  97. package/dist/types/react/web/ui/Bridge/payment-selection/PaymentSelection.d.ts.map +1 -1
  98. package/dist/types/react/web/ui/Bridge/payment-selection/WalletFiatSelection.d.ts +2 -1
  99. package/dist/types/react/web/ui/Bridge/payment-selection/WalletFiatSelection.d.ts.map +1 -1
  100. package/dist/types/react/web/ui/PayEmbed.d.ts +0 -1
  101. package/dist/types/react/web/ui/PayEmbed.d.ts.map +1 -1
  102. package/dist/types/version.d.ts +1 -1
  103. package/dist/types/wallets/in-app/core/authentication/backend.d.ts.map +1 -1
  104. package/dist/types/wallets/in-app/core/authentication/guest.d.ts +2 -2
  105. package/dist/types/wallets/in-app/core/authentication/guest.d.ts.map +1 -1
  106. package/package.json +2 -2
  107. package/src/engine/server-wallet.test.ts +23 -28
  108. package/src/engine/server-wallet.ts +80 -26
  109. package/src/engine/wait-for-tx-hash.ts +1 -1
  110. package/src/exports/wallets/in-app.native.ts +10 -0
  111. package/src/exports/wallets/in-app.ts +10 -0
  112. package/src/extensions/erc7702/account/createSessionKey.ts +181 -0
  113. package/src/extensions/erc7702/account/sessionkey.test.ts +132 -0
  114. package/src/extensions/erc7702/account/types.ts +94 -0
  115. package/src/react/web/ui/Bridge/BridgeOrchestrator.tsx +8 -0
  116. package/src/react/web/ui/Bridge/BuyWidget.tsx +7 -0
  117. package/src/react/web/ui/Bridge/CheckoutWidget.tsx +7 -0
  118. package/src/react/web/ui/Bridge/TransactionWidget.tsx +7 -0
  119. package/src/react/web/ui/Bridge/payment-details/PaymentDetails.tsx +3 -7
  120. package/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx +10 -2
  121. package/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx +133 -124
  122. package/src/react/web/ui/PayEmbed.tsx +17 -1
  123. package/src/version.ts +1 -1
  124. package/src/wallets/in-app/core/authentication/backend.test.ts +1 -0
  125. package/src/wallets/in-app/core/authentication/backend.ts +2 -1
  126. package/src/wallets/in-app/core/authentication/guest.ts +4 -11
  127. package/src/wallets/in-app/core/eip7702/minimal-account.ts +1 -1
  128. package/src/wallets/in-app/native/native-connector.ts +1 -1
  129. package/src/wallets/in-app/web/lib/in-app-gateway.test.ts +126 -0
  130. package/src/wallets/in-app/web/lib/web-connector.ts +1 -1
@@ -1,7 +1,8 @@
1
1
  import {
2
- type AaExecutionOptions,
3
- type AaZksyncExecutionOptions,
4
- type EoaExecutionOptions,
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 getExecutionOptions = (chainId: number) => {
158
- return executionOptions
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
- chainId: chainId.toString(),
162
- }
163
- : {
164
- chainId: chainId.toString(),
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: getExecutionOptions(chainId),
242
+ executionOptions: getExecutionOptionsWithChainId(chainId),
188
243
  params: transaction.map((t) => ({
189
244
  data: t.data,
190
- to: t.to ?? undefined,
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.results[0];
334
- if (signatureResult?.success) {
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?.message || "Unknown 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.results[0];
367
- if (signatureResult?.success) {
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?.message || "Unknown 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}