thirdweb 5.105.2 → 5.105.3
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/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/ConnectWallet/ConnectButton.js +7 -1
- package/dist/cjs/react/web/ui/ConnectWallet/ConnectButton.js.map +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/wallets/defaultWallets.js +3 -1
- package/dist/cjs/wallets/defaultWallets.js.map +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/eip7702/minimal-account.js +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/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/ConnectWallet/ConnectButton.js +7 -1
- package/dist/esm/react/web/ui/ConnectWallet/ConnectButton.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/wallets/defaultWallets.js +3 -1
- package/dist/esm/wallets/defaultWallets.js.map +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/eip7702/minimal-account.js +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/payment-details/PaymentDetails.d.ts.map +1 -1
- package/dist/types/react/web/ui/ConnectWallet/ConnectButton.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/wallets/defaultWallets.d.ts +2 -0
- package/dist/types/wallets/defaultWallets.d.ts.map +1 -1
- package/dist/types/wallets/in-app/core/authentication/backend.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/payment-details/PaymentDetails.tsx +3 -7
- package/src/react/web/ui/ConnectWallet/ConnectButton.tsx +7 -1
- package/src/version.ts +1 -1
- package/src/wallets/defaultWallets.ts +5 -1
- package/src/wallets/in-app/core/authentication/backend.ts +2 -1
- package/src/wallets/in-app/core/eip7702/minimal-account.ts +1 -1
- package/src/wallets/in-app/web/lib/in-app-gateway.test.ts +126 -0
@@ -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;
|
@@ -370,13 +370,9 @@ export function PaymentDetails({
|
|
370
370
|
}
|
371
371
|
</>
|
372
372
|
) : (
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
(c) => c.chainId === step.originToken.chainId,
|
377
|
-
)?.name
|
378
|
-
}
|
379
|
-
</>
|
373
|
+
chainsMetadata.find(
|
374
|
+
(c) => c.chainId === step.originToken.chainId,
|
375
|
+
)?.name
|
380
376
|
)}
|
381
377
|
</Text>
|
382
378
|
</Container>
|
@@ -292,8 +292,14 @@ export function ConnectButton(props: ConnectButtonProps) {
|
|
292
292
|
getDefaultWallets({
|
293
293
|
appMetadata: props.appMetadata,
|
294
294
|
chains: props.chains,
|
295
|
+
executionMode: props.accountAbstraction
|
296
|
+
? {
|
297
|
+
mode: "EIP4337",
|
298
|
+
smartAccount: props.accountAbstraction,
|
299
|
+
}
|
300
|
+
: undefined,
|
295
301
|
}),
|
296
|
-
[props.wallets, props.appMetadata, props.chains],
|
302
|
+
[props.wallets, props.appMetadata, props.chains, props.accountAbstraction],
|
297
303
|
);
|
298
304
|
const localeQuery = useConnectLocale(props.locale || "en_US");
|
299
305
|
const connectionManager = useConnectionManager();
|
package/src/version.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export const version = "5.105.
|
1
|
+
export const version = "5.105.3";
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import type { Chain } from "../chains/types.js";
|
2
2
|
import { COINBASE, METAMASK, RAINBOW, ZERION } from "./constants.js";
|
3
3
|
import { createWallet } from "./create-wallet.js";
|
4
|
+
import type { ExecutionModeOptions } from "./in-app/core/wallet/types.js";
|
4
5
|
import type { Wallet } from "./interfaces/wallet.js";
|
5
6
|
import type { AppMetadata } from "./types.js";
|
6
7
|
|
@@ -10,9 +11,12 @@ import type { AppMetadata } from "./types.js";
|
|
10
11
|
export function getDefaultWallets(options?: {
|
11
12
|
appMetadata?: AppMetadata;
|
12
13
|
chains?: Chain[];
|
14
|
+
executionMode?: ExecutionModeOptions;
|
13
15
|
}): Wallet[] {
|
14
16
|
return [
|
15
|
-
createWallet("inApp"
|
17
|
+
createWallet("inApp", {
|
18
|
+
executionMode: options?.executionMode,
|
19
|
+
}),
|
16
20
|
createWallet(METAMASK),
|
17
21
|
createWallet(COINBASE, {
|
18
22
|
appMetadata: options?.appMetadata,
|
@@ -31,7 +31,8 @@ export async function backendAuthenticate(args: {
|
|
31
31
|
});
|
32
32
|
|
33
33
|
if (!res.ok) {
|
34
|
-
|
34
|
+
const error = await res.text();
|
35
|
+
throw new Error(`Failed to generate backend account: ${error}`);
|
35
36
|
}
|
36
37
|
|
37
38
|
return (await res.json()) satisfies AuthStoredTokenWithCookieReturnType;
|
@@ -24,7 +24,7 @@ import {
|
|
24
24
|
import type { BundlerOptions } from "../../../smart/types.js";
|
25
25
|
|
26
26
|
const MINIMAL_ACCOUNT_IMPLEMENTATION_ADDRESS =
|
27
|
-
"
|
27
|
+
"0xD6999651Fc0964B9c6B444307a0ab20534a66560";
|
28
28
|
|
29
29
|
export const create7702MinimalAccount = (args: {
|
30
30
|
client: ThirdwebClient;
|
@@ -0,0 +1,126 @@
|
|
1
|
+
import { sendTransaction, signMessage } from "@thirdweb-dev/engine";
|
2
|
+
import { beforeAll, describe, expect, it } from "vitest";
|
3
|
+
import { TEST_CLIENT } from "~test/test-clients.js";
|
4
|
+
import { sepolia } from "../../../../chains/chain-definitions/sepolia.js";
|
5
|
+
import { createThirdwebClient } from "../../../../client/client.js";
|
6
|
+
import { waitForTransactionHash } from "../../../../engine/wait-for-tx-hash.js";
|
7
|
+
import {
|
8
|
+
getThirdwebBaseUrl,
|
9
|
+
setThirdwebDomains,
|
10
|
+
} from "../../../../utils/domains.js";
|
11
|
+
import { getClientFetch } from "../../../../utils/fetch.js";
|
12
|
+
import { stringify } from "../../../../utils/json.js";
|
13
|
+
import type { Account } from "../../../interfaces/wallet.js";
|
14
|
+
import { inAppWallet } from "../in-app.js";
|
15
|
+
|
16
|
+
// TODO: productionize this test
|
17
|
+
describe
|
18
|
+
.runIf(process.env.TW_SECRET_KEY)
|
19
|
+
.skip("InAppWallet Gateway Tests", () => {
|
20
|
+
let account: Account;
|
21
|
+
let authToken: string | null | undefined;
|
22
|
+
const clientIdFetch = getClientFetch(
|
23
|
+
createThirdwebClient({
|
24
|
+
clientId: TEST_CLIENT.clientId,
|
25
|
+
}),
|
26
|
+
);
|
27
|
+
|
28
|
+
beforeAll(async () => {
|
29
|
+
setThirdwebDomains({
|
30
|
+
bundler: "bundler.thirdweb-dev.com",
|
31
|
+
engineCloud: "engine.thirdweb-dev.com",
|
32
|
+
inAppWallet: "embedded-wallet.thirdweb-dev.com",
|
33
|
+
rpc: "rpc.thirdweb-dev.com",
|
34
|
+
});
|
35
|
+
const wallet = inAppWallet();
|
36
|
+
account = await wallet.connect({
|
37
|
+
client: TEST_CLIENT,
|
38
|
+
strategy: "backend",
|
39
|
+
walletSecret: "test-secret",
|
40
|
+
});
|
41
|
+
authToken = wallet.getAuthToken?.();
|
42
|
+
expect(authToken).toBeDefined();
|
43
|
+
});
|
44
|
+
|
45
|
+
it("should sign a message with backend strategy", async () => {
|
46
|
+
const rawSignature = await account.signMessage({
|
47
|
+
message: "Hello, world!",
|
48
|
+
});
|
49
|
+
|
50
|
+
// sign via api
|
51
|
+
const signResult = await signMessage({
|
52
|
+
baseUrl: getThirdwebBaseUrl("engineCloud"),
|
53
|
+
body: {
|
54
|
+
params: [
|
55
|
+
{
|
56
|
+
format: "text",
|
57
|
+
message: "Hello, world!",
|
58
|
+
},
|
59
|
+
],
|
60
|
+
signingOptions: {
|
61
|
+
from: account.address,
|
62
|
+
type: "eoa",
|
63
|
+
},
|
64
|
+
},
|
65
|
+
bodySerializer: stringify,
|
66
|
+
fetch: clientIdFetch,
|
67
|
+
headers: {
|
68
|
+
"x-wallet-access-token": authToken,
|
69
|
+
},
|
70
|
+
});
|
71
|
+
|
72
|
+
const signatureResult = signResult.data?.result?.results[0];
|
73
|
+
if (signatureResult && "result" in signatureResult) {
|
74
|
+
expect(signatureResult.result.signature).toEqual(rawSignature);
|
75
|
+
} else {
|
76
|
+
throw new Error(
|
77
|
+
`Failed to sign message: ${stringify(signatureResult?.error) || "Unknown error"}`,
|
78
|
+
);
|
79
|
+
}
|
80
|
+
});
|
81
|
+
|
82
|
+
it("should queue a 4337 transaction", async () => {
|
83
|
+
const body = {
|
84
|
+
executionOptions: {
|
85
|
+
chainId: sepolia.id,
|
86
|
+
from: account.address,
|
87
|
+
type: "auto" as const,
|
88
|
+
},
|
89
|
+
params: [
|
90
|
+
{
|
91
|
+
data: "0x",
|
92
|
+
to: account.address,
|
93
|
+
value: "0",
|
94
|
+
},
|
95
|
+
],
|
96
|
+
};
|
97
|
+
const result = await sendTransaction({
|
98
|
+
baseUrl: getThirdwebBaseUrl("engineCloud"),
|
99
|
+
body,
|
100
|
+
bodySerializer: stringify,
|
101
|
+
fetch: clientIdFetch,
|
102
|
+
headers: {
|
103
|
+
"x-wallet-access-token": authToken,
|
104
|
+
},
|
105
|
+
});
|
106
|
+
if (result.error) {
|
107
|
+
throw new Error(
|
108
|
+
`Error sending transaction: ${stringify(result.error)}`,
|
109
|
+
);
|
110
|
+
}
|
111
|
+
|
112
|
+
const txId = result.data?.result.transactions[0]?.id;
|
113
|
+
console.log(txId);
|
114
|
+
if (!txId) {
|
115
|
+
throw new Error("No transaction ID found");
|
116
|
+
}
|
117
|
+
|
118
|
+
const tx = await waitForTransactionHash({
|
119
|
+
client: TEST_CLIENT,
|
120
|
+
transactionId: txId,
|
121
|
+
});
|
122
|
+
|
123
|
+
console.log(tx);
|
124
|
+
expect(tx.transactionHash).toBeDefined();
|
125
|
+
});
|
126
|
+
});
|