@rhinestone/sdk 1.4.1 → 1.4.2
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/src/accounts/index.d.ts +1 -0
- package/dist/src/accounts/index.d.ts.map +1 -1
- package/dist/src/accounts/index.js +8 -2
- package/dist/src/accounts/json-rpc/providers.js +1 -1
- package/dist/src/actions/recovery.test.js +1 -1
- package/dist/src/execution/signing.test.d.ts +2 -0
- package/dist/src/execution/signing.test.d.ts.map +1 -0
- package/dist/src/execution/signing.test.js +465 -0
- package/dist/src/execution/utils.d.ts +1 -0
- package/dist/src/execution/utils.d.ts.map +1 -1
- package/dist/src/execution/utils.js +76 -7
- package/dist/src/execution/utils.test.js +183 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/modules/validators/index.d.ts +2 -2
- package/dist/src/modules/validators/index.d.ts.map +1 -1
- package/dist/src/modules/validators/index.js +4 -1
- package/dist/src/modules/validators/policies/claim/permit2.d.ts +55 -0
- package/dist/src/modules/validators/policies/claim/permit2.d.ts.map +1 -0
- package/dist/src/modules/validators/policies/claim/permit2.js +239 -0
- package/dist/src/modules/validators/policies/claim/permit2.test.d.ts +2 -0
- package/dist/src/modules/validators/policies/claim/permit2.test.d.ts.map +1 -0
- package/dist/src/modules/validators/policies/claim/permit2.test.js +519 -0
- package/dist/src/modules/validators/policies/claim/types.d.ts +12 -0
- package/dist/src/modules/validators/policies/claim/types.d.ts.map +1 -0
- package/dist/src/modules/validators/policies/claim/types.js +18 -0
- package/dist/src/modules/validators/smart-sessions.d.ts +14 -3
- package/dist/src/modules/validators/smart-sessions.d.ts.map +1 -1
- package/dist/src/modules/validators/smart-sessions.js +51 -16
- package/dist/src/modules/validators/smart-sessions.test.js +266 -16
- package/dist/src/orchestrator/client.d.ts.map +1 -1
- package/dist/src/orchestrator/client.js +1 -0
- package/dist/src/orchestrator/consts.d.ts +3 -2
- package/dist/src/orchestrator/consts.d.ts.map +1 -1
- package/dist/src/orchestrator/consts.js +4 -2
- package/dist/src/orchestrator/index.d.ts +2 -2
- package/dist/src/orchestrator/index.d.ts.map +1 -1
- package/dist/src/orchestrator/registry.d.ts.map +1 -1
- package/dist/src/orchestrator/registry.js +5 -1
- package/dist/src/orchestrator/types.d.ts +1 -0
- package/dist/src/orchestrator/types.d.ts.map +1 -1
- package/dist/src/types.d.ts +38 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/test/utils/utils.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PERMIT2_CLAIM_POLICY_ADDRESS = void 0;
|
|
4
|
+
exports.buildPermit2ClaimPolicyCalldata = buildPermit2ClaimPolicyCalldata;
|
|
5
|
+
exports.encodePermit2ClaimPolicyInitData = encodePermit2ClaimPolicyInitData;
|
|
6
|
+
const viem_1 = require("viem");
|
|
7
|
+
const types_1 = require("./types");
|
|
8
|
+
// EIP-712 type definitions for Permit2/Mandate struct encoding.
|
|
9
|
+
// Note: the token-out struct is named 'Token' in the Solidity contract (matching the
|
|
10
|
+
// signed Permit2 message types in execution/permit2.ts).
|
|
11
|
+
const PERMIT2_TYPES = {
|
|
12
|
+
TokenPermissions: [
|
|
13
|
+
{ name: 'token', type: 'address' },
|
|
14
|
+
{ name: 'amount', type: 'uint256' },
|
|
15
|
+
],
|
|
16
|
+
Token: [
|
|
17
|
+
{ name: 'token', type: 'address' },
|
|
18
|
+
{ name: 'amount', type: 'uint256' },
|
|
19
|
+
],
|
|
20
|
+
Ops: [
|
|
21
|
+
{ name: 'to', type: 'address' },
|
|
22
|
+
{ name: 'value', type: 'uint256' },
|
|
23
|
+
{ name: 'data', type: 'bytes' },
|
|
24
|
+
],
|
|
25
|
+
Op: [
|
|
26
|
+
{ name: 'vt', type: 'bytes32' },
|
|
27
|
+
{ name: 'ops', type: 'Ops[]' },
|
|
28
|
+
],
|
|
29
|
+
Target: [
|
|
30
|
+
{ name: 'recipient', type: 'address' },
|
|
31
|
+
{ name: 'tokenOut', type: 'Token[]' },
|
|
32
|
+
{ name: 'targetChain', type: 'uint256' },
|
|
33
|
+
{ name: 'fillExpiry', type: 'uint256' },
|
|
34
|
+
],
|
|
35
|
+
Mandate: [
|
|
36
|
+
{ name: 'target', type: 'Target' },
|
|
37
|
+
{ name: 'minGas', type: 'uint128' },
|
|
38
|
+
{ name: 'originOps', type: 'Op' },
|
|
39
|
+
{ name: 'destOps', type: 'Op' },
|
|
40
|
+
{ name: 'q', type: 'bytes32' },
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
// --- EIP-712 hash helpers ---
|
|
44
|
+
function hashArray(hashes) {
|
|
45
|
+
return (0, viem_1.keccak256)(hashes.length > 0 ? (0, viem_1.concat)(hashes) : '0x');
|
|
46
|
+
}
|
|
47
|
+
function hashTokenPermissionsArray(permitted) {
|
|
48
|
+
return hashArray(permitted.map(({ token, amount }) => (0, viem_1.hashStruct)({
|
|
49
|
+
primaryType: 'TokenPermissions',
|
|
50
|
+
types: PERMIT2_TYPES,
|
|
51
|
+
data: { token, amount },
|
|
52
|
+
})));
|
|
53
|
+
}
|
|
54
|
+
function hashTokenOutArray(tokenOut) {
|
|
55
|
+
return hashArray(tokenOut.map(({ token, amount }) => (0, viem_1.hashStruct)({
|
|
56
|
+
primaryType: 'Token',
|
|
57
|
+
types: PERMIT2_TYPES,
|
|
58
|
+
data: { token, amount },
|
|
59
|
+
})));
|
|
60
|
+
}
|
|
61
|
+
function hashOpStruct(op) {
|
|
62
|
+
return (0, viem_1.hashStruct)({
|
|
63
|
+
primaryType: 'Op',
|
|
64
|
+
types: PERMIT2_TYPES,
|
|
65
|
+
data: { vt: op.vt, ops: Array.from(op.ops) },
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function hashMandateStruct(mandate) {
|
|
69
|
+
return (0, viem_1.hashStruct)({
|
|
70
|
+
primaryType: 'Mandate',
|
|
71
|
+
types: PERMIT2_TYPES,
|
|
72
|
+
data: {
|
|
73
|
+
target: {
|
|
74
|
+
recipient: mandate.target.recipient,
|
|
75
|
+
tokenOut: Array.from(mandate.target.tokenOut),
|
|
76
|
+
targetChain: mandate.target.targetChain,
|
|
77
|
+
fillExpiry: mandate.target.fillExpiry,
|
|
78
|
+
},
|
|
79
|
+
minGas: mandate.minGas,
|
|
80
|
+
originOps: {
|
|
81
|
+
vt: mandate.originOps.vt,
|
|
82
|
+
ops: Array.from(mandate.originOps.ops),
|
|
83
|
+
},
|
|
84
|
+
destOps: { vt: mandate.destOps.vt, ops: Array.from(mandate.destOps.ops) },
|
|
85
|
+
q: mandate.q,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// --- Token array encoding helpers ---
|
|
90
|
+
/** Encodes a token+amount pair as [token_as_uint256:32][amount:32] (64 bytes) */
|
|
91
|
+
function encodeTokenEntry(token, amount) {
|
|
92
|
+
return (0, viem_1.encodeAbiParameters)([{ type: 'address' }, { type: 'uint256' }], [token, amount]);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Builds the policySpecificData calldata for a Permit2ClaimPolicy EIP-1271 check.
|
|
96
|
+
*
|
|
97
|
+
* Format (derived from Permit2ClaimPolicy.sol calldata layout):
|
|
98
|
+
* Header: [spender:20][nonce:32][deadline:32]
|
|
99
|
+
* TokenIn: expanded [count:1][token:32][amount:32]... OR pre-computed hash [32]
|
|
100
|
+
* Mandate: if any target check enabled — expanded target + minGas:16 + ops hashes + q
|
|
101
|
+
* else — pre-computed mandateHash [32]
|
|
102
|
+
*
|
|
103
|
+
*/
|
|
104
|
+
function buildPermit2ClaimPolicyCalldata(policy, message) {
|
|
105
|
+
const tokenInEnabled = !!policy.tokensIn?.length;
|
|
106
|
+
const recipientEnabled = !!policy.recipients?.length;
|
|
107
|
+
const fillExpiryEnabled = !!policy.fillExpiryBounds?.length;
|
|
108
|
+
const tokenOutEnabled = !!policy.tokensOut?.length;
|
|
109
|
+
const recipientIsSponsorEnabled = !!policy.recipientIsSponsor;
|
|
110
|
+
// hasAnyTargetCheck mirrors the Solidity MASK_TARGET_CHECKS logic for our supported fields
|
|
111
|
+
const hasAnyTargetCheck = recipientEnabled ||
|
|
112
|
+
fillExpiryEnabled ||
|
|
113
|
+
tokenOutEnabled ||
|
|
114
|
+
recipientIsSponsorEnabled;
|
|
115
|
+
const parts = [];
|
|
116
|
+
// Header: [spender:20][nonce:32][deadline:32] (spender == arbiter in Permit2 context)
|
|
117
|
+
parts.push((0, viem_1.encodePacked)(['address', 'uint256', 'uint256'], [message.spender, message.nonce, message.deadline]));
|
|
118
|
+
// TokenIn section
|
|
119
|
+
if (tokenInEnabled) {
|
|
120
|
+
// Expanded: [count:1][token_as_uint256:32][amount:32]...
|
|
121
|
+
if (message.permitted.length > 255)
|
|
122
|
+
throw new Error('permitted array exceeds max length of 255');
|
|
123
|
+
parts.push((0, viem_1.toHex)(message.permitted.length, { size: 1 }));
|
|
124
|
+
for (const { token, amount } of message.permitted) {
|
|
125
|
+
parts.push(encodeTokenEntry(token, amount));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
parts.push(hashTokenPermissionsArray(message.permitted));
|
|
130
|
+
}
|
|
131
|
+
// Mandate section
|
|
132
|
+
if (!hasAnyTargetCheck) {
|
|
133
|
+
// No mandate-level checks enabled — provide pre-computed mandateHash
|
|
134
|
+
parts.push(hashMandateStruct(message.mandate));
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// Expanded mandate: target fields + minGas + ops hashes + q
|
|
138
|
+
const target = message.mandate.target;
|
|
139
|
+
// Target: [recipient:20][targetChain:32][fillExpiry:32]
|
|
140
|
+
parts.push((0, viem_1.encodePacked)(['address', 'uint256', 'uint256'], [target.recipient, target.targetChain, target.fillExpiry]));
|
|
141
|
+
// TokenOut (inside target)
|
|
142
|
+
if (tokenOutEnabled) {
|
|
143
|
+
if (target.tokenOut.length > 255)
|
|
144
|
+
throw new Error('tokenOut array exceeds max length of 255');
|
|
145
|
+
parts.push((0, viem_1.toHex)(target.tokenOut.length, { size: 1 }));
|
|
146
|
+
for (const { token, amount } of target.tokenOut) {
|
|
147
|
+
parts.push(encodeTokenEntry(token, amount));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
parts.push(hashTokenOutArray(target.tokenOut));
|
|
152
|
+
}
|
|
153
|
+
// minGas: uint128 = 16 bytes
|
|
154
|
+
parts.push((0, viem_1.toHex)(message.mandate.minGas, { size: 16 }));
|
|
155
|
+
// originOpsHash and destOpsHash: always 32-byte hashes (we don't support ops checks)
|
|
156
|
+
parts.push(hashOpStruct(message.mandate.originOps));
|
|
157
|
+
parts.push(hashOpStruct(message.mandate.destOps));
|
|
158
|
+
// qualificationHash: q is already keccak256(qualifier.encodedVal)
|
|
159
|
+
parts.push(message.mandate.q);
|
|
160
|
+
}
|
|
161
|
+
return (0, viem_1.concat)(parts);
|
|
162
|
+
}
|
|
163
|
+
exports.PERMIT2_CLAIM_POLICY_ADDRESS = '0x62E3588C6d861C9f986E82EC3757434EDF16ce91';
|
|
164
|
+
function encodePermit2ClaimPolicyInitData(policy) {
|
|
165
|
+
let modeConfig = 0;
|
|
166
|
+
const setMode = (fieldId) => {
|
|
167
|
+
modeConfig |= types_1.MODE_CHECK_STORAGE << (fieldId * 2);
|
|
168
|
+
};
|
|
169
|
+
if (policy.arbiters?.length)
|
|
170
|
+
setMode(types_1.FIELD_ARBITER);
|
|
171
|
+
if (policy.expiryBounds)
|
|
172
|
+
setMode(types_1.FIELD_EXPIRY);
|
|
173
|
+
if (policy.tokensIn?.length)
|
|
174
|
+
setMode(types_1.FIELD_TOKEN_IN);
|
|
175
|
+
if (policy.recipients?.length)
|
|
176
|
+
setMode(types_1.FIELD_RECIPIENT);
|
|
177
|
+
if (policy.fillExpiryBounds?.length)
|
|
178
|
+
setMode(types_1.FIELD_FILL_EXPIRY);
|
|
179
|
+
if (policy.tokensOut?.length)
|
|
180
|
+
setMode(types_1.FIELD_TOKEN_OUT);
|
|
181
|
+
if (policy.recipientIsSponsor)
|
|
182
|
+
setMode(types_1.FIELD_RECIPIENT_IS_SPONSOR);
|
|
183
|
+
const parts = [(0, viem_1.toHex)(modeConfig, { size: 4 })];
|
|
184
|
+
// Arbiter: [count: 1][address: 20] each
|
|
185
|
+
if (policy.arbiters?.length) {
|
|
186
|
+
if (policy.arbiters.length > 255)
|
|
187
|
+
throw new Error('arbiters array exceeds max length of 255');
|
|
188
|
+
parts.push((0, viem_1.encodePacked)(['uint8', ...policy.arbiters.map(() => 'address')], [policy.arbiters.length, ...policy.arbiters]));
|
|
189
|
+
}
|
|
190
|
+
// Expiry: [maxExpiry: 16][minExpiry: 16] packed into uint256
|
|
191
|
+
if (policy.expiryBounds) {
|
|
192
|
+
const mask128 = (1n << 128n) - 1n;
|
|
193
|
+
const min = (policy.expiryBounds.min ?? 0n) & mask128;
|
|
194
|
+
const max = (policy.expiryBounds.max ?? viem_1.maxUint256) & mask128;
|
|
195
|
+
parts.push((0, viem_1.toHex)((min & mask128) | (max << 128n), { size: 32 }));
|
|
196
|
+
}
|
|
197
|
+
// TokenIn: [count: 1][chainId: 32][token: 20] each
|
|
198
|
+
if (policy.tokensIn?.length) {
|
|
199
|
+
if (policy.tokensIn.length > 255)
|
|
200
|
+
throw new Error('tokensIn array exceeds max length of 255');
|
|
201
|
+
parts.push((0, viem_1.toHex)(policy.tokensIn.length, { size: 1 }));
|
|
202
|
+
for (const { chainId, token } of policy.tokensIn) {
|
|
203
|
+
parts.push((0, viem_1.encodePacked)(['uint256', 'address'], [BigInt(chainId), token]));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// Recipient: [count: 1][chainId: 32][recipient: 20] each
|
|
207
|
+
if (policy.recipients?.length) {
|
|
208
|
+
if (policy.recipients.length > 255)
|
|
209
|
+
throw new Error('recipients array exceeds max length of 255');
|
|
210
|
+
parts.push((0, viem_1.toHex)(policy.recipients.length, { size: 1 }));
|
|
211
|
+
for (const { chainId, recipient } of policy.recipients) {
|
|
212
|
+
parts.push((0, viem_1.encodePacked)(['uint256', 'address'], [BigInt(chainId), recipient === 'any' ? types_1.ANY_ADDRESS : recipient]));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// FillExpiry: [count: 1][chainId: 32][max<<128|min packed into uint256] each
|
|
216
|
+
if (policy.fillExpiryBounds?.length) {
|
|
217
|
+
if (policy.fillExpiryBounds.length > 255)
|
|
218
|
+
throw new Error('fillExpiryBounds array exceeds max length of 255');
|
|
219
|
+
const mask128 = (1n << 128n) - 1n;
|
|
220
|
+
parts.push((0, viem_1.toHex)(policy.fillExpiryBounds.length, { size: 1 }));
|
|
221
|
+
for (const { chainId, min: fMin, max: fMax } of policy.fillExpiryBounds) {
|
|
222
|
+
const minVal = (fMin ?? 0n) & mask128;
|
|
223
|
+
const maxVal = (fMax ?? viem_1.maxUint256) & mask128;
|
|
224
|
+
const packed = minVal | (maxVal << 128n);
|
|
225
|
+
parts.push((0, viem_1.encodePacked)(['uint256', 'uint256'], [BigInt(chainId), packed]));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// TokenOut: [count: 1][chainId: 32][token: 20] each
|
|
229
|
+
if (policy.tokensOut?.length) {
|
|
230
|
+
if (policy.tokensOut.length > 255)
|
|
231
|
+
throw new Error('tokensOut array exceeds max length of 255');
|
|
232
|
+
parts.push((0, viem_1.toHex)(policy.tokensOut.length, { size: 1 }));
|
|
233
|
+
for (const { chainId, token } of policy.tokensOut) {
|
|
234
|
+
parts.push((0, viem_1.encodePacked)(['uint256', 'address'], [BigInt(chainId), token]));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// RecipientIsSponsor has no data payload — mode bit alone enables it
|
|
238
|
+
return (0, viem_1.concat)(parts);
|
|
239
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permit2.test.d.ts","sourceRoot":"","sources":["../../../../../../modules/validators/policies/claim/permit2.test.ts"],"names":[],"mappings":""}
|