@metamask/smart-accounts-kit 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -64
- package/dist/actions/index.cjs +4 -4
- package/dist/actions/index.d.cts +3 -3
- package/dist/actions/index.d.ts +3 -3
- package/dist/actions/index.mjs +3 -3
- package/dist/{caveats-gqMBZKkI.d.cts → caveats-BEKgygS8.d.cts} +1 -1
- package/dist/{caveats-B2OssjV4.d.ts → caveats-DPuxVdYU.d.ts} +1 -1
- package/dist/{chunk-JKVSTPEC.cjs → chunk-32RDDE5N.cjs} +13 -13
- package/dist/{chunk-JKVSTPEC.cjs.map → chunk-32RDDE5N.cjs.map} +1 -1
- package/dist/{chunk-TNGQTVSY.mjs → chunk-3KWKQ7PV.mjs} +2 -2
- package/dist/{chunk-TNGQTVSY.mjs.map → chunk-3KWKQ7PV.mjs.map} +1 -1
- package/dist/{chunk-EPU4O7FY.cjs → chunk-4GOGI2TA.cjs} +106 -106
- package/dist/{chunk-EPU4O7FY.cjs.map → chunk-4GOGI2TA.cjs.map} +1 -1
- package/dist/{chunk-2ZOWIAP3.cjs → chunk-6TSLFRJC.cjs} +62 -62
- package/dist/{chunk-2ZOWIAP3.cjs.map → chunk-6TSLFRJC.cjs.map} +1 -1
- package/dist/{chunk-YVU66KSH.mjs → chunk-EMPAUTIV.mjs} +2 -2
- package/dist/{chunk-W6HPAK4M.cjs → chunk-GHGCGV3C.cjs} +2 -2
- package/dist/{chunk-W6HPAK4M.cjs.map → chunk-GHGCGV3C.cjs.map} +1 -1
- package/dist/{chunk-L3EZCIY6.mjs → chunk-IERUQUKJ.mjs} +4 -4
- package/dist/{chunk-DCI2AN4N.cjs → chunk-KIXYMA7J.cjs} +15 -15
- package/dist/{chunk-DCI2AN4N.cjs.map → chunk-KIXYMA7J.cjs.map} +1 -1
- package/dist/{chunk-UJQ3JN3U.mjs → chunk-T6SWQZRX.mjs} +3 -3
- package/dist/{chunk-AZYTTGON.mjs → chunk-XUBMIW33.mjs} +3 -3
- package/dist/{chunk-K7GTZGKJ.mjs → chunk-YCNLPEPH.mjs} +2 -2
- package/dist/{chunk-PQPAEHJZ.cjs → chunk-YPUEM6YV.cjs} +12 -12
- package/dist/{chunk-PQPAEHJZ.cjs.map → chunk-YPUEM6YV.cjs.map} +1 -1
- package/dist/contracts/index.cjs +5 -5
- package/dist/contracts/index.d.cts +4 -4
- package/dist/contracts/index.d.ts +4 -4
- package/dist/contracts/index.mjs +4 -4
- package/dist/{decodeRevertReason-CmmCpmZ_.d.cts → decodeRevertReason-CSOClzsa.d.cts} +3 -3
- package/dist/{decodeRevertReason-dOTpJx2h.d.ts → decodeRevertReason-WjHVQ_Sz.d.ts} +3 -3
- package/dist/experimental/index.cjs +66 -38
- package/dist/experimental/index.cjs.map +1 -1
- package/dist/experimental/index.d.cts +4 -2
- package/dist/experimental/index.d.ts +4 -2
- package/dist/experimental/index.mjs +50 -22
- package/dist/experimental/index.mjs.map +1 -1
- package/dist/{index-B1Cmezvh.d.cts → index-BHm75OFP.d.cts} +1 -1
- package/dist/{index-BkgdU4LI.d.ts → index-BNHYZ9iU.d.ts} +2 -2
- package/dist/{index-DUJmm8Wz.d.ts → index-CgGKjHSr.d.ts} +2 -2
- package/dist/{index-Dv4jPzhe.d.cts → index-CsjbdUp_.d.cts} +2 -2
- package/dist/{index-LqiEgBjV.d.ts → index-DWvEgBtg.d.ts} +1 -1
- package/dist/{index-X7Qn3JTg.d.cts → index-DYJjOeTn.d.cts} +2 -2
- package/dist/index.cjs +19 -19
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.mjs +6 -6
- package/dist/{resolveCaveats-A9xC29l8.d.ts → resolveCaveats-aQPEogPk.d.cts} +2 -2
- package/dist/{resolveCaveats-A9xC29l8.d.cts → resolveCaveats-aQPEogPk.d.ts} +2 -2
- package/dist/utils/index.cjs +4 -4
- package/dist/utils/index.d.cts +5 -5
- package/dist/utils/index.d.ts +5 -5
- package/dist/utils/index.mjs +3 -3
- package/package.json +8 -8
- /package/dist/{chunk-YVU66KSH.mjs.map → chunk-EMPAUTIV.mjs.map} +0 -0
- /package/dist/{chunk-L3EZCIY6.mjs.map → chunk-IERUQUKJ.mjs.map} +0 -0
- /package/dist/{chunk-UJQ3JN3U.mjs.map → chunk-T6SWQZRX.mjs.map} +0 -0
- /package/dist/{chunk-AZYTTGON.mjs.map → chunk-XUBMIW33.mjs.map} +0 -0
- /package/dist/{chunk-K7GTZGKJ.mjs.map → chunk-YCNLPEPH.mjs.map} +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
3
|
var _chunkIQT6XFDTcjs = require('../chunk-IQT6XFDT.cjs');
|
|
4
|
-
require('../chunk-
|
|
4
|
+
require('../chunk-KIXYMA7J.cjs');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
var _chunk2OS36DVVcjs = require('../chunk-2OS36DVV.cjs');
|
|
8
|
-
require('../chunk-
|
|
8
|
+
require('../chunk-32RDDE5N.cjs');
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ require('../chunk-JKVSTPEC.cjs');
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
var
|
|
17
|
+
var _chunkGHGCGV3Ccjs = require('../chunk-GHGCGV3C.cjs');
|
|
18
18
|
|
|
19
19
|
// src/experimental/delegationStorage.ts
|
|
20
20
|
var _viem = require('viem');
|
|
@@ -35,7 +35,7 @@ var DelegationStorageClient = class {
|
|
|
35
35
|
#apiUrl;
|
|
36
36
|
constructor(config) {
|
|
37
37
|
const { apiUrl } = config.environment;
|
|
38
|
-
|
|
38
|
+
_chunkGHGCGV3Ccjs.trackSmartAccountsKitFunctionCall.call(void 0,
|
|
39
39
|
"experimental.DelegationStorageClient.constructor",
|
|
40
40
|
{
|
|
41
41
|
environment: getDelegationStorageEnvironment(apiUrl)
|
|
@@ -81,13 +81,13 @@ var DelegationStorageClient = class {
|
|
|
81
81
|
* is not found.
|
|
82
82
|
*/
|
|
83
83
|
async getDelegationChain(leafDelegationOrDelegationHash) {
|
|
84
|
-
|
|
84
|
+
_chunkGHGCGV3Ccjs.trackSmartAccountsKitFunctionCall.call(void 0,
|
|
85
85
|
"experimental.DelegationStorageClient.getDelegationChain",
|
|
86
86
|
{
|
|
87
87
|
inputKind: typeof leafDelegationOrDelegationHash === "string" ? "hash" : "delegation"
|
|
88
88
|
}
|
|
89
89
|
);
|
|
90
|
-
const leafDelegationHash = typeof leafDelegationOrDelegationHash === "string" ? leafDelegationOrDelegationHash :
|
|
90
|
+
const leafDelegationHash = typeof leafDelegationOrDelegationHash === "string" ? leafDelegationOrDelegationHash : _chunkGHGCGV3Ccjs.hashDelegation.call(void 0, leafDelegationOrDelegationHash);
|
|
91
91
|
const response = await this.#fetcher(
|
|
92
92
|
`${this.#apiUrl}/delegation/chain/${leafDelegationHash}`,
|
|
93
93
|
{
|
|
@@ -117,7 +117,7 @@ var DelegationStorageClient = class {
|
|
|
117
117
|
* empty array if the delegations are not found.
|
|
118
118
|
*/
|
|
119
119
|
async fetchDelegations(deleGatorAddress, filterMode = "RECEIVED" /* Received */) {
|
|
120
|
-
|
|
120
|
+
_chunkGHGCGV3Ccjs.trackSmartAccountsKitFunctionCall.call(void 0,
|
|
121
121
|
"experimental.DelegationStorageClient.fetchDelegations",
|
|
122
122
|
{ filterMode }
|
|
123
123
|
);
|
|
@@ -144,14 +144,14 @@ var DelegationStorageClient = class {
|
|
|
144
144
|
* @returns A promise that resolves to the delegation hash indicating successful storage.
|
|
145
145
|
*/
|
|
146
146
|
async storeDelegation(delegation) {
|
|
147
|
-
|
|
147
|
+
_chunkGHGCGV3Ccjs.trackSmartAccountsKitFunctionCall.call(void 0,
|
|
148
148
|
"experimental.DelegationStorageClient.storeDelegation",
|
|
149
149
|
{ caveatCount: delegation.caveats.length }
|
|
150
150
|
);
|
|
151
151
|
if (!delegation.signature || delegation.signature === "0x") {
|
|
152
152
|
throw new Error("Delegation must be signed to be stored");
|
|
153
153
|
}
|
|
154
|
-
const delegationHash =
|
|
154
|
+
const delegationHash = _chunkGHGCGV3Ccjs.hashDelegation.call(void 0, delegation);
|
|
155
155
|
const body = JSON.stringify(
|
|
156
156
|
{
|
|
157
157
|
...delegation,
|
|
@@ -266,22 +266,45 @@ var ensureExpirySufficientlyConstrained = ({
|
|
|
266
266
|
};
|
|
267
267
|
return [...caveats, timestampCaveat];
|
|
268
268
|
};
|
|
269
|
-
var
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
existingDelegations,
|
|
273
|
-
redeemerAddresses,
|
|
274
|
-
requireRedeemers
|
|
269
|
+
var resolveRedeemerAddresses = ({
|
|
270
|
+
facilitatorAddresses,
|
|
271
|
+
redeemerAddresses
|
|
275
272
|
}) => {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
273
|
+
if (!facilitatorAddresses) {
|
|
274
|
+
if (!redeemerAddresses) {
|
|
275
|
+
return void 0;
|
|
276
|
+
}
|
|
277
|
+
return redeemerAddresses;
|
|
278
|
+
}
|
|
279
|
+
if (!redeemerAddresses) {
|
|
280
|
+
return facilitatorAddresses;
|
|
281
|
+
}
|
|
282
|
+
const normalizedFacilitatorAddresses = facilitatorAddresses.map(normalizeAddress);
|
|
283
|
+
const normalizedRedeemerAddressSet = new Set(
|
|
284
|
+
redeemerAddresses.map(normalizeAddress)
|
|
285
|
+
);
|
|
286
|
+
const redeemerAddressesIntersection = normalizedFacilitatorAddresses.filter(
|
|
287
|
+
(address) => normalizedRedeemerAddressSet.has(address)
|
|
288
|
+
);
|
|
289
|
+
return redeemerAddressesIntersection;
|
|
290
|
+
};
|
|
291
|
+
var ensureRedeemerSufficientlyConstrained = (config) => {
|
|
292
|
+
const redeemerAddresses = resolveRedeemerAddresses(config);
|
|
293
|
+
if (_optionalChain([redeemerAddresses, 'optionalAccess', _3 => _3.length]) === 0) {
|
|
294
|
+
throw new Error(
|
|
295
|
+
"No valid redeemer addresses were resolved. If both `redeemers.addresses` and `extra.facilitatorAddresses` are provided, they must overlap. If only one is provided, it must include at least one address."
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
const { caveats, existingDelegations, redeemerEnforcer } = config;
|
|
299
|
+
const redeemerEnforcerNormalized = normalizeAddress(redeemerEnforcer);
|
|
300
|
+
if (!redeemerAddresses) {
|
|
301
|
+
if (!config.requireRedeemers) {
|
|
279
302
|
return caveats;
|
|
280
303
|
}
|
|
281
304
|
const hasExistingRedeemerCaveat = hasMatchingCaveats(
|
|
282
305
|
caveats,
|
|
283
306
|
existingDelegations,
|
|
284
|
-
({ enforcer }) => normalizeAddress(enforcer) ===
|
|
307
|
+
({ enforcer }) => normalizeAddress(enforcer) === redeemerEnforcerNormalized
|
|
285
308
|
);
|
|
286
309
|
if (!hasExistingRedeemerCaveat) {
|
|
287
310
|
throw new Error(
|
|
@@ -290,13 +313,12 @@ var ensureRedeemerSufficientlyConstrained = ({
|
|
|
290
313
|
}
|
|
291
314
|
return caveats;
|
|
292
315
|
}
|
|
293
|
-
const
|
|
294
|
-
const redeemerAddressesSet = new Set(redeemerAddressesNormalized);
|
|
316
|
+
const redeemerAddressesSet = new Set(redeemerAddresses.map(normalizeAddress));
|
|
295
317
|
const hasSupersedingRedeemerCaveat = hasMatchingCaveats(
|
|
296
318
|
caveats,
|
|
297
319
|
existingDelegations,
|
|
298
320
|
(caveat) => {
|
|
299
|
-
if (normalizeAddress(caveat.enforcer) !==
|
|
321
|
+
if (normalizeAddress(caveat.enforcer) !== redeemerEnforcerNormalized) {
|
|
300
322
|
return false;
|
|
301
323
|
}
|
|
302
324
|
const allowedRedeemerAddresses = _delegationcore.decodeRedeemerTerms.call(void 0,
|
|
@@ -372,23 +394,19 @@ var resolvex402DelegationCaveats = ({
|
|
|
372
394
|
if (!timestampEnforcer) {
|
|
373
395
|
throw new Error("TimestampEnforcer not found in environment");
|
|
374
396
|
}
|
|
375
|
-
const initialCaveats =
|
|
397
|
+
const initialCaveats = _chunkGHGCGV3Ccjs.resolveCaveats.call(void 0, {
|
|
376
398
|
environment,
|
|
377
399
|
caveats: caveatsConfig,
|
|
378
400
|
// Resolve caveats first so downstream constraint checks can append as needed.
|
|
379
401
|
// Scope is still attached later during delegation creation.
|
|
380
402
|
isScopeOptional: true
|
|
381
403
|
});
|
|
382
|
-
const allRedeemerAddresses = new Set(
|
|
383
|
-
[..._nullishCoalesce(facilitatorAddresses, () => ( [])), ..._nullishCoalesce(redeemerAddresses, () => ( []))].map(
|
|
384
|
-
normalizeAddress
|
|
385
|
-
)
|
|
386
|
-
);
|
|
387
404
|
const caveatsWithRedeemer = ensureRedeemerSufficientlyConstrained({
|
|
388
405
|
redeemerEnforcer,
|
|
406
|
+
facilitatorAddresses,
|
|
407
|
+
redeemerAddresses,
|
|
389
408
|
caveats: initialCaveats,
|
|
390
409
|
existingDelegations,
|
|
391
|
-
redeemerAddresses: Array.from(allRedeemerAddresses),
|
|
392
410
|
requireRedeemers
|
|
393
411
|
});
|
|
394
412
|
const caveatsWithPayee = ensurePayeeSufficientlyConstrained({
|
|
@@ -413,9 +431,9 @@ var resolveDelegationCreationContext = async (config, requirements) => {
|
|
|
413
431
|
config.redeemers,
|
|
414
432
|
requirements
|
|
415
433
|
);
|
|
416
|
-
const requireRedeemers = _nullishCoalesce(_optionalChain([redeemersConfig, 'optionalAccess',
|
|
434
|
+
const requireRedeemers = _nullishCoalesce(_optionalChain([redeemersConfig, 'optionalAccess', _4 => _4.requireRedeemers]), () => ( false));
|
|
417
435
|
const redeemerAddresses = await resolveMaybeDeferred(
|
|
418
|
-
_optionalChain([redeemersConfig, 'optionalAccess',
|
|
436
|
+
_optionalChain([redeemersConfig, 'optionalAccess', _5 => _5.addresses]),
|
|
419
437
|
requirements
|
|
420
438
|
);
|
|
421
439
|
const specifiedEnvironment = await resolveMaybeDeferred(
|
|
@@ -439,8 +457,8 @@ var resolveDelegationCreationContext = async (config, requirements) => {
|
|
|
439
457
|
tokenAddress: requirements.asset,
|
|
440
458
|
maxAmount: BigInt(requirements.amount)
|
|
441
459
|
};
|
|
442
|
-
const facilitatorAddresses = _optionalChain([requirements, 'access',
|
|
443
|
-
const existingDelegations = parentPermissionContext ?
|
|
460
|
+
const facilitatorAddresses = _optionalChain([requirements, 'access', _6 => _6.extra, 'optionalAccess', _7 => _7.facilitatorAddresses]);
|
|
461
|
+
const existingDelegations = parentPermissionContext ? _chunkGHGCGV3Ccjs.decodeDelegations.call(void 0, parentPermissionContext) : [];
|
|
444
462
|
const { DelegationManager: delegationManager } = environment;
|
|
445
463
|
const caveats = resolvex402DelegationCaveats({
|
|
446
464
|
environment,
|
|
@@ -475,7 +493,7 @@ var resolveDelegationCreationContext = async (config, requirements) => {
|
|
|
475
493
|
scope
|
|
476
494
|
};
|
|
477
495
|
}
|
|
478
|
-
const rootDelegator = _nullishCoalesce(_optionalChain([existingDelegations, 'access',
|
|
496
|
+
const rootDelegator = _nullishCoalesce(_optionalChain([existingDelegations, 'access', _8 => _8[existingDelegations.length - 1], 'optionalAccess', _9 => _9.delegator]), () => ( from));
|
|
479
497
|
return {
|
|
480
498
|
account,
|
|
481
499
|
createDelegationConfig,
|
|
@@ -486,6 +504,14 @@ var resolveDelegationCreationContext = async (config, requirements) => {
|
|
|
486
504
|
};
|
|
487
505
|
|
|
488
506
|
// src/experimental/x402DelegationProvider.ts
|
|
507
|
+
var METAMASK_FACILITATOR_ADDRESSES = [
|
|
508
|
+
"0xB01caEa8c6C47bbf4F4b4c5080Ca642043359C2E",
|
|
509
|
+
"0xC066ac5D385419B1A8c43A0E146fA439837a8B8c",
|
|
510
|
+
"0xB42F812A44c22cc6b861478900401ee759EbEAD6"
|
|
511
|
+
];
|
|
512
|
+
var METAMASK_FACILITATOR_ADDRESSES_DEV = [
|
|
513
|
+
"0xb4827A2a066CD2Ef88560EFdf063dD05C6c41cC7"
|
|
514
|
+
];
|
|
489
515
|
function createx402DelegationProvider(config) {
|
|
490
516
|
return async (requirements) => {
|
|
491
517
|
const {
|
|
@@ -495,9 +521,9 @@ function createx402DelegationProvider(config) {
|
|
|
495
521
|
existingDelegations,
|
|
496
522
|
rootDelegator
|
|
497
523
|
} = await resolveDelegationCreationContext(config, requirements);
|
|
498
|
-
const delegation =
|
|
524
|
+
const delegation = _chunkGHGCGV3Ccjs.createOpenDelegation.call(void 0, createDelegationConfig);
|
|
499
525
|
const chainId = parseEip155ChainId(requirements.network);
|
|
500
|
-
const typedData =
|
|
526
|
+
const typedData = _chunkGHGCGV3Ccjs.prepareSignDelegationTypedData.call(void 0, {
|
|
501
527
|
delegationManager,
|
|
502
528
|
chainId,
|
|
503
529
|
delegation
|
|
@@ -510,7 +536,7 @@ function createx402DelegationProvider(config) {
|
|
|
510
536
|
...delegation,
|
|
511
537
|
signature
|
|
512
538
|
};
|
|
513
|
-
const permissionContext =
|
|
539
|
+
const permissionContext = _chunkGHGCGV3Ccjs.encodeDelegations.call(void 0, [
|
|
514
540
|
signedDelegation,
|
|
515
541
|
...existingDelegations
|
|
516
542
|
]);
|
|
@@ -526,5 +552,7 @@ function createx402DelegationProvider(config) {
|
|
|
526
552
|
|
|
527
553
|
|
|
528
554
|
|
|
529
|
-
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
exports.DelegationStorageClient = DelegationStorageClient; exports.DelegationStorageEnvironment = DelegationStorageEnvironment; exports.METAMASK_FACILITATOR_ADDRESSES = METAMASK_FACILITATOR_ADDRESSES; exports.METAMASK_FACILITATOR_ADDRESSES_DEV = METAMASK_FACILITATOR_ADDRESSES_DEV; exports.createx402DelegationProvider = createx402DelegationProvider; exports.parseEip155ChainId = parseEip155ChainId;
|
|
530
558
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/smart-accounts-kit/smart-accounts-kit/packages/smart-accounts-kit/dist/experimental/index.cjs","../../src/experimental/delegationStorage.ts","../../src/experimental/x402DelegationProviderUtils.ts","../../src/experimental/x402DelegationProvider.ts"],"names":[],"mappings":"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","file":"/home/runner/work/smart-accounts-kit/smart-accounts-kit/packages/smart-accounts-kit/dist/experimental/index.cjs","sourcesContent":[null,"import { type Hex, toHex } from 'viem';\n\nimport { trackSmartAccountsKitFunctionCall } from '../analytics';\nimport { hashDelegation } from '../delegation';\nimport type { Delegation } from '../types';\n\ntype ErrorResponse = {\n error: string;\n data?: any;\n};\n\nexport type APIStoreDelegationResponse = {\n delegationHash: Hex;\n};\n\n/**\n * Represents the allowed filters when querying the data store for delegations.\n */\nexport enum DelegationStoreFilter {\n Given = 'GIVEN',\n Received = 'RECEIVED',\n All = 'ALL',\n}\n\n/**\n * Public Delegation Storage Service environments. To be used in the\n * DeleGationStorageService config.\n */\nexport const DelegationStorageEnvironment: {\n [K in 'dev' | 'prod']: Environment;\n} = {\n dev: { apiUrl: 'https://passkeys.dev-api.cx.metamask.io' },\n prod: { apiUrl: 'https://passkeys.api.cx.metamask.io' },\n};\n\n/**\n * Returns the DelegationStorageEnvironment ('dev' or 'prod') for a given apiUrl,\n * or 'custom' if the apiUrl does not match a known environment.\n *\n * @param apiUrl - The API URL to check.\n * @returns The environment key ('dev' or 'prod'), or 'custom'.\n */\nfunction getDelegationStorageEnvironment(\n apiUrl: string,\n): 'dev' | 'prod' | 'custom' {\n const matchingEnvironment = Object.entries(DelegationStorageEnvironment).find(\n ([_, env]) => env.apiUrl === apiUrl,\n ) as [keyof typeof DelegationStorageEnvironment, Environment] | undefined;\n\n return matchingEnvironment ? matchingEnvironment[0] : 'custom';\n}\n\nexport type Environment = {\n apiUrl: string;\n};\n\nexport type DelegationStorageConfig = {\n apiKey: string;\n apiKeyId: string;\n environment: Environment;\n fetcher?: typeof fetch;\n};\n\nexport class DelegationStorageClient {\n readonly #apiVersionPrefix = 'api/v0';\n\n readonly #config: DelegationStorageConfig;\n\n readonly #fetcher: typeof fetch;\n\n readonly #apiUrl: string;\n\n constructor(config: DelegationStorageConfig) {\n const { apiUrl } = config.environment;\n\n trackSmartAccountsKitFunctionCall(\n 'experimental.DelegationStorageClient.constructor',\n {\n environment: getDelegationStorageEnvironment(apiUrl),\n },\n );\n\n if (apiUrl.endsWith(this.#apiVersionPrefix)) {\n this.#apiUrl = apiUrl;\n } else {\n const separator = apiUrl.endsWith('/') ? '' : '/';\n this.#apiUrl = `${apiUrl}${separator}${this.#apiVersionPrefix}`;\n }\n this.#fetcher = this.#initializeFetcher(config);\n this.#config = config;\n }\n\n /**\n * Initializes the fetch function for HTTP requests.\n *\n * - Uses `config.fetcher` if provided.\n * - Falls back to global `fetch` if available.\n * - Throws an error if no fetch function is available.\n *\n * @param config - Configuration object that may include a custom fetch function.\n * @returns The fetch function to be used for HTTP requests.\n * @throws Error if no fetch function is available in the environment.\n */\n #initializeFetcher(config: DelegationStorageConfig): typeof fetch {\n if (config.fetcher) {\n return config.fetcher;\n } else if (typeof globalThis?.fetch === 'function') {\n return globalThis.fetch.bind(globalThis);\n }\n throw new Error(\n 'Fetch API is not available in this environment. Please provide a fetch function in the config.',\n );\n }\n\n /**\n * Fetches the delegation chain from the Delegation Storage Service, ending with\n * the specified leaf delegation.\n *\n * @param leafDelegationOrDelegationHash - The leaf delegation, or the hash\n * of the leaf delegation.\n * @returns A promise that resolves to the delegation chain - empty array if the delegation\n * is not found.\n */\n async getDelegationChain(\n leafDelegationOrDelegationHash: Hex | Delegation,\n ): Promise<Delegation[]> {\n trackSmartAccountsKitFunctionCall(\n 'experimental.DelegationStorageClient.getDelegationChain',\n {\n inputKind:\n typeof leafDelegationOrDelegationHash === 'string'\n ? 'hash'\n : 'delegation',\n },\n );\n const leafDelegationHash =\n typeof leafDelegationOrDelegationHash === 'string'\n ? leafDelegationOrDelegationHash\n : hashDelegation(leafDelegationOrDelegationHash);\n\n const response = await this.#fetcher(\n `${this.#apiUrl}/delegation/chain/${leafDelegationHash}`,\n {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${this.#config.apiKey}`,\n 'x-api-key-id': this.#config.apiKeyId,\n },\n },\n );\n\n const responseData: Delegation[] | ErrorResponse = await response.json();\n\n if ('error' in responseData) {\n throw new Error(\n `Failed to fetch delegation chain: ${responseData.error}`,\n );\n }\n\n return responseData;\n }\n\n /**\n * Fetches the delegations from the Delegation Storage Service, either `Received`\n * by, or `Given` by, (or both: `All`) the specified deleGatorAddress. Defaults\n * to `Received`.\n *\n * @param deleGatorAddress - The deleGatorAddress to retrieve the delegations for.\n * @param filterMode - The DelegationStoreFilter mode - defaults to Received.\n * @returns A promise that resolves to the list of delegations received by the deleGatorAddress,\n * empty array if the delegations are not found.\n */\n async fetchDelegations(\n deleGatorAddress: Hex,\n filterMode = DelegationStoreFilter.Received,\n ): Promise<Delegation[]> {\n trackSmartAccountsKitFunctionCall(\n 'experimental.DelegationStorageClient.fetchDelegations',\n { filterMode },\n );\n const response = await this.#fetcher(\n `${this.#apiUrl}/delegation/accounts/${deleGatorAddress}?filter=${filterMode}`,\n {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${this.#config.apiKey}`,\n 'x-api-key-id': this.#config.apiKeyId,\n },\n },\n );\n\n const responseData: Delegation[] | ErrorResponse = await response.json();\n\n if ('error' in responseData) {\n throw new Error(`Failed to fetch delegations: ${responseData.error}`);\n }\n\n return responseData;\n }\n\n /**\n * Stores the specified delegation in the Delegation Storage Service.\n *\n * @param delegation - The delegation to store.\n * @returns A promise that resolves to the delegation hash indicating successful storage.\n */\n async storeDelegation(delegation: Delegation): Promise<Hex> {\n trackSmartAccountsKitFunctionCall(\n 'experimental.DelegationStorageClient.storeDelegation',\n { caveatCount: delegation.caveats.length },\n );\n if (!delegation.signature || delegation.signature === '0x') {\n throw new Error('Delegation must be signed to be stored');\n }\n\n const delegationHash = hashDelegation(delegation);\n\n const body = JSON.stringify(\n {\n ...delegation,\n metadata: [],\n },\n (_, value: any) =>\n typeof value === 'bigint' || typeof value === 'number'\n ? toHex(value)\n : value,\n 2,\n );\n\n const response = await this.#fetcher(`${this.#apiUrl}/delegation/store`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.#config.apiKey}`,\n 'x-api-key-id': this.#config.apiKeyId,\n 'Content-Type': 'application/json',\n },\n body,\n });\n\n const responseData: APIStoreDelegationResponse | ErrorResponse =\n await response.json();\n\n if ('error' in responseData) {\n throw new Error(responseData.error);\n }\n\n if (responseData.delegationHash !== delegationHash) {\n throw new Error(\n 'Failed to store the Delegation, the hash returned from the MM delegation storage API does not match the hash of the delegation',\n );\n }\n\n return responseData.delegationHash;\n }\n}\n","import {\n createAllowedCalldataTerms,\n createRedeemerTerms,\n createTimestampTerms,\n decodeRedeemerTerms,\n decodeTimestampTerms,\n} from '@metamask/delegation-core';\nimport { parseCaipChainId } from '@metamask/utils';\nimport { pad, type Account, type Address, type Hex } from 'viem';\n\nimport type { Caveats } from '../caveatBuilder';\nimport { resolveCaveats } from '../caveatBuilder';\nimport { ScopeType } from '../constants';\nimport type { createOpenDelegation } from '../delegation';\nimport { decodeDelegations } from '../delegation';\nimport { getSmartAccountsEnvironment } from '../smartAccountsEnvironment';\nimport type {\n Caveat,\n Delegation,\n PermissionContext,\n SmartAccountsEnvironment,\n} from '../types';\nimport type {\n MaybeDeferred,\n PaymentRequirements,\n x402DelegationProviderConfig,\n} from './x402DelegationProviderTypes';\nimport { generateSalt } from '../utils/';\n\n/**\n * Inputs for redeemer constraint enforcement.\n */\ntype EnsureRedeemerSufficientlyConstrainedParams = {\n redeemerEnforcer: Hex;\n caveats: Caveat[];\n existingDelegations: Delegation[];\n redeemerAddresses: Hex[];\n requireRedeemers: boolean;\n};\n\n/**\n * Inputs for payee constraint enforcement.\n */\ntype EnsurePayeeSufficientlyConstrainedParams = {\n allowedCalldataEnforcer: Hex;\n caveats: Caveat[];\n existingDelegations: Delegation[];\n payee: Hex;\n};\n\n/**\n * Inputs for expiry constraint enforcement.\n */\ntype EnsureExpirySufficientlyConstrainedParams = {\n timestampEnforcer: Hex;\n caveats: Caveat[];\n existingDelegations: Delegation[];\n expirySeconds: number;\n};\n\n/**\n * Resolved context required to build and sign an x402 delegation.\n */\nexport type DelegationCreationContext = {\n account: Account;\n createDelegationConfig: Parameters<typeof createOpenDelegation>[0];\n delegationManager: Address;\n existingDelegations: Delegation[];\n rootDelegator: Address;\n};\n\n/**\n * Inputs for resolving delegation caveats with x402-specific constraints.\n */\nexport type Resolvex402DelegationCaveatsParams = {\n environment: SmartAccountsEnvironment;\n caveatsConfig: Caveats | undefined;\n existingDelegations: Delegation[];\n facilitatorAddresses: Hex[] | undefined;\n payee: Hex;\n expirySeconds?: number;\n requireRedeemers: boolean;\n redeemerAddresses: Address[] | undefined;\n};\n\n/**\n * Resolves eager or deferred values against payment requirements.\n *\n * @param maybeDeferred - Value or async resolver function.\n * @param requirements - Payment requirements passed to deferred resolvers.\n * @returns The resolved value, or undefined when no value is provided.\n */\nasync function resolveMaybeDeferred<TResult>(\n maybeDeferred: MaybeDeferred<TResult>,\n requirements: PaymentRequirements,\n): Promise<TResult> {\n if (typeof maybeDeferred === 'function') {\n const deferred = maybeDeferred as (\n deferredRequirements: PaymentRequirements,\n ) => Promise<TResult> | TResult;\n\n return await deferred(requirements);\n }\n\n return maybeDeferred;\n}\n\n/**\n * Parses an EIP-155 CAIP network identifier into a numeric chain ID.\n *\n * @param network - CAIP network identifier (for example, `eip155:1`).\n * @returns Parsed numeric chain ID.\n * @throws If the CAIP namespace is not `eip155`.\n */\nexport function parseEip155ChainId(\n network: PaymentRequirements['network'],\n): number {\n const { namespace, reference } = parseCaipChainId(\n network as `${string}:${string}`,\n );\n\n if (namespace !== 'eip155') {\n throw new Error('Unsupported chain namespace');\n }\n\n const parsedChainId = Number(reference);\n\n if (isNaN(parsedChainId)) {\n throw new Error('Invalid chain id');\n }\n\n return parsedChainId;\n}\n\n/**\n * ERC-20 `transfer(address to, uint256 value)` calldata index for `to`.\n */\nconst TRANSFER_PAYEE_INDEX = 4;\n\n/**\n * Normalizes an address-like hex string for case-insensitive comparisons.\n *\n * @param address - Address value to normalize.\n * @returns Lowercased hex string.\n */\nconst normalizeAddress = (address: Address): Address =>\n address.toLowerCase() as Address;\n\n/**\n * Returns whether any caveat in local or inherited delegations matches a predicate.\n *\n * @param caveats - Current caveat list.\n * @param delegations - Existing delegations whose caveats should also be searched.\n * @param match - Predicate used to match caveats.\n * @returns True when at least one caveat satisfies `match`.\n */\nconst hasMatchingCaveats = (\n caveats: Caveat[],\n delegations: Delegation[],\n match: (caveat: Caveat) => boolean,\n): boolean => {\n for (const caveat of caveats) {\n if (match(caveat)) {\n return true;\n }\n }\n\n for (const delegation of delegations) {\n for (const caveat of delegation.caveats) {\n if (match(caveat)) {\n return true;\n }\n }\n }\n\n return false;\n};\n\n/**\n * Ensures caveats include an expiry timestamp constraint when requested.\n *\n * If an existing timestamp caveat already enforces a tighter (earlier) or equal\n * `validBefore` threshold than requested, caveats are returned unchanged.\n * Otherwise a new timestamp caveat is appended with `afterThreshold = 0`.\n *\n * @param options0 - Expiry constraint evaluation inputs.\n * @param options0.timestampEnforcer - Address of the TimestampEnforcer caveat contract.\n * @param options0.caveats - Currently resolved caveats for the delegation being created.\n * @param options0.existingDelegations - Existing parent-chain delegations to inspect for inherited constraints.\n * @param options0.expirySeconds - Relative expiry from \"now\" in seconds.\n * @returns The original caveats when sufficiently constrained, otherwise caveats with a timestamp caveat appended.\n */\nexport const ensureExpirySufficientlyConstrained = ({\n timestampEnforcer,\n caveats,\n existingDelegations,\n expirySeconds,\n}: EnsureExpirySufficientlyConstrainedParams): Caveat[] => {\n if (expirySeconds < 0) {\n throw new Error('Expiry seconds must be a positive number');\n }\n const beforeThreshold = Math.floor(Date.now() / 1000) + expirySeconds;\n const timestampEnforcerNormalized = normalizeAddress(timestampEnforcer);\n\n const hasSupersedingTimestampConstraint = hasMatchingCaveats(\n caveats,\n existingDelegations,\n (caveat) => {\n if (normalizeAddress(caveat.enforcer) !== timestampEnforcerNormalized) {\n return false;\n }\n\n const { beforeThreshold: existingBeforeThreshold } = decodeTimestampTerms(\n caveat.terms,\n );\n return (\n existingBeforeThreshold !== 0 &&\n existingBeforeThreshold <= beforeThreshold\n );\n },\n );\n\n if (hasSupersedingTimestampConstraint) {\n return caveats;\n }\n\n const timestampCaveat: Caveat = {\n enforcer: timestampEnforcer,\n terms: createTimestampTerms({\n afterThreshold: 0,\n beforeThreshold,\n }),\n args: '0x',\n };\n\n return [...caveats, timestampCaveat];\n};\n\n/**\n * Ensures caveats include a sufficiently strict redeemer constraint.\n *\n * Returns the caveat list unchanged when an existing redeemer caveat is already\n * strict enough, or appends a new redeemer caveat scoped to facilitator addresses.\n *\n * @param options0 - Redeemer constraint evaluation inputs.\n * @param options0.redeemerEnforcer - Address of the redeemer enforcer caveat contract.\n * @param options0.caveats - Currently resolved caveats for the delegation being created.\n * @param options0.existingDelegations - Existing parent-chain delegations to inspect for inherited constraints.\n * @param options0.redeemerAddresses - Optional addresses to which redemption should be constrained.\n * @param options0.requireRedeemers - Whether at least one redeemer constraint must exist when no redeemer addresses are supplied.\n * @returns The original caveats when sufficiently constrained, otherwise caveats with a redeemer caveat appended.\n * @throws If no facilitator addresses are provided and no redeemer constraint exists.\n */\nexport const ensureRedeemerSufficientlyConstrained = ({\n redeemerEnforcer,\n caveats,\n existingDelegations,\n redeemerAddresses,\n requireRedeemers,\n}: EnsureRedeemerSufficientlyConstrainedParams): Caveat[] => {\n const redeemerAddressNormalized = normalizeAddress(redeemerEnforcer);\n\n if (redeemerAddresses.length === 0) {\n if (!requireRedeemers) {\n return caveats;\n }\n\n const hasExistingRedeemerCaveat = hasMatchingCaveats(\n caveats,\n existingDelegations,\n ({ enforcer }) =>\n normalizeAddress(enforcer) === redeemerAddressNormalized,\n );\n\n if (!hasExistingRedeemerCaveat) {\n throw new Error(\n 'Redeemer must be constrained, either in the specified `caveats`, `parentPermissionContext`, or the `PaymentRequirements` as `extra.facilitatorAddresses`.',\n );\n }\n\n return caveats;\n }\n\n const redeemerAddressesNormalized = redeemerAddresses.map(normalizeAddress);\n const redeemerAddressesSet = new Set(redeemerAddressesNormalized);\n\n const hasSupersedingRedeemerCaveat = hasMatchingCaveats(\n caveats,\n existingDelegations,\n (caveat) => {\n if (normalizeAddress(caveat.enforcer) !== redeemerAddressNormalized) {\n return false;\n }\n\n const allowedRedeemerAddresses = decodeRedeemerTerms(\n caveat.terms,\n ).redeemers.map(normalizeAddress);\n\n // If this redeemer caveat only allows facilitator addresses, it is sufficiently constrained.\n return allowedRedeemerAddresses.every((item) =>\n redeemerAddressesSet.has(item),\n );\n },\n );\n\n if (hasSupersedingRedeemerCaveat) {\n return caveats;\n }\n\n const redeemerCaveat: Caveat = {\n enforcer: redeemerEnforcer,\n terms: createRedeemerTerms({ redeemers: redeemerAddresses }),\n args: '0x',\n };\n\n return [...caveats, redeemerCaveat];\n};\n\n/**\n * Ensures caveats include an allowed-calldata constraint for the payment payee.\n *\n * Scans both the in-progress caveat list and parent delegation caveats for an\n * `AllowedCalldataEnforcer` caveat whose terms match the encoded payee calldata\n * constraint. If found, returns caveats unchanged; otherwise appends a payee caveat.\n *\n * @param options0 - Payee constraint evaluation inputs.\n * @param options0.allowedCalldataEnforcer - Address of the AllowedCalldataEnforcer caveat contract.\n * @param options0.caveats - Currently resolved caveats for the delegation being created.\n * @param options0.existingDelegations - Existing parent-chain delegations to inspect for inherited constraints.\n * @param options0.payee - Expected ERC-20 transfer recipient to enforce in calldata.\n * @returns The original caveats when an equivalent payee constraint exists, otherwise caveats with a payee caveat appended.\n */\nexport const ensurePayeeSufficientlyConstrained = ({\n allowedCalldataEnforcer,\n caveats,\n existingDelegations,\n payee,\n}: EnsurePayeeSufficientlyConstrainedParams): Caveat[] => {\n const allowedCalldataTerms = createAllowedCalldataTerms({\n startIndex: TRANSFER_PAYEE_INDEX,\n value: pad(payee, { size: 32 }),\n });\n\n const allowedCalldataEnforcerNormalized = normalizeAddress(\n allowedCalldataEnforcer,\n );\n\n const lowercaseCalldataTerms = allowedCalldataTerms.toLowerCase();\n\n const hasSupersedingAllowedCalldataConstraint = hasMatchingCaveats(\n caveats,\n existingDelegations,\n ({ enforcer, terms }) =>\n normalizeAddress(enforcer) === allowedCalldataEnforcerNormalized &&\n terms.toLowerCase() === lowercaseCalldataTerms,\n );\n\n if (hasSupersedingAllowedCalldataConstraint) {\n return caveats;\n }\n\n const payeeCaveat: Caveat = {\n enforcer: allowedCalldataEnforcer,\n terms: allowedCalldataTerms,\n args: '0x',\n };\n\n return [...caveats, payeeCaveat];\n};\n\n/**\n * Resolves caveats and applies x402-specific redeemer and payee constraints.\n *\n * @param options0 - Caveat resolution inputs.\n * @param options0.environment - Environment containing caveat enforcer addresses.\n * @param options0.caveatsConfig - Optional caveat builder config.\n * @param options0.existingDelegations - Existing parent-chain delegations.\n * @param options0.facilitatorAddresses - Optional facilitator addresses used for redeemer constraints.\n * @param options0.payee - Payee address used for allowed calldata constraints.\n * @param options0.expirySeconds - Optional relative expiry in seconds for adding timestamp constraints.\n * @param options0.requireRedeemers - Whether redeemer constraints are mandatory when no facilitator or configured redeemer addresses are present.\n * @param options0.redeemerAddresses - Optional redeemer addresses from provider config to merge with facilitator addresses.\n * @returns Caveats after redeemer and payee constraints are enforced.\n */\nexport const resolvex402DelegationCaveats = ({\n environment,\n caveatsConfig,\n existingDelegations,\n facilitatorAddresses,\n payee,\n expirySeconds,\n requireRedeemers,\n redeemerAddresses,\n}: Resolvex402DelegationCaveatsParams): Caveat[] => {\n const {\n caveatEnforcers: {\n RedeemerEnforcer: redeemerEnforcer,\n AllowedCalldataEnforcer: allowedCalldataEnforcer,\n TimestampEnforcer: timestampEnforcer,\n },\n } = environment;\n\n if (!redeemerEnforcer) {\n throw new Error('RedeemerEnforcer not found in environment');\n }\n\n if (!allowedCalldataEnforcer) {\n throw new Error('AllowedCalldataEnforcer not found in environment');\n }\n\n if (!timestampEnforcer) {\n throw new Error('TimestampEnforcer not found in environment');\n }\n\n const initialCaveats = resolveCaveats({\n environment,\n caveats: caveatsConfig,\n // Resolve caveats first so downstream constraint checks can append as needed.\n // Scope is still attached later during delegation creation.\n isScopeOptional: true,\n });\n\n const allRedeemerAddresses = new Set(\n [...(facilitatorAddresses ?? []), ...(redeemerAddresses ?? [])].map(\n normalizeAddress,\n ),\n );\n\n const caveatsWithRedeemer = ensureRedeemerSufficientlyConstrained({\n redeemerEnforcer,\n caveats: initialCaveats,\n existingDelegations,\n redeemerAddresses: Array.from(allRedeemerAddresses),\n requireRedeemers,\n });\n\n const caveatsWithPayee = ensurePayeeSufficientlyConstrained({\n allowedCalldataEnforcer,\n caveats: caveatsWithRedeemer,\n existingDelegations,\n payee,\n });\n\n if (expirySeconds === undefined) {\n return caveatsWithPayee;\n }\n\n return ensureExpirySufficientlyConstrained({\n timestampEnforcer,\n caveats: caveatsWithPayee,\n existingDelegations,\n expirySeconds,\n });\n};\n\n/**\n * Builds the delegation creation context from provider config and requirements.\n *\n * @param config - Delegation provider config for context construction.\n * @param requirements - Payment requirements used to scope caveats.\n * @returns The resolved context used to create and sign a delegation.\n */\nexport const resolveDelegationCreationContext = async (\n config: x402DelegationProviderConfig,\n requirements: PaymentRequirements,\n): Promise<DelegationCreationContext> => {\n const account = await resolveMaybeDeferred(config.account, requirements);\n const redeemersConfig = await resolveMaybeDeferred(\n config.redeemers,\n requirements,\n );\n\n const requireRedeemers = redeemersConfig?.requireRedeemers ?? false;\n const redeemerAddresses = await resolveMaybeDeferred(\n redeemersConfig?.addresses,\n requirements,\n );\n\n const specifiedEnvironment = await resolveMaybeDeferred(\n config.environment,\n requirements,\n );\n const environment =\n specifiedEnvironment ??\n getSmartAccountsEnvironment(parseEip155ChainId(requirements.network));\n\n const caveatsConfig: Caveats | undefined = await resolveMaybeDeferred(\n config.caveats,\n requirements,\n );\n const parentPermissionContext: PermissionContext | undefined =\n await resolveMaybeDeferred(config.parentPermissionContext, requirements);\n const expirySeconds = await resolveMaybeDeferred(\n config.expirySeconds,\n requirements,\n );\n\n const from =\n (await resolveMaybeDeferred(config.from, requirements)) ?? account.address;\n const salt =\n (await resolveMaybeDeferred(config.salt, requirements)) ?? generateSalt();\n\n const scope = {\n type: ScopeType.Erc20TransferAmount,\n tokenAddress: requirements.asset as Hex,\n maxAmount: BigInt(requirements.amount),\n } as const;\n\n const facilitatorAddresses = requirements.extra?.facilitatorAddresses as\n | Hex[]\n | undefined;\n\n const existingDelegations = parentPermissionContext\n ? decodeDelegations(parentPermissionContext)\n : [];\n\n const { DelegationManager: delegationManager } = environment;\n const caveats = resolvex402DelegationCaveats({\n environment,\n caveatsConfig,\n existingDelegations,\n facilitatorAddresses,\n payee: requirements.payTo as Hex,\n expirySeconds,\n requireRedeemers,\n redeemerAddresses,\n });\n\n let createDelegationConfig: Parameters<typeof createOpenDelegation>[0];\n\n if (parentPermissionContext) {\n const parentDelegation = existingDelegations[0];\n\n if (!parentDelegation) {\n throw new Error('Parent permission context is not a valid delegation');\n }\n\n createDelegationConfig = {\n environment,\n from,\n caveats,\n salt,\n scope,\n parentDelegation,\n };\n } else {\n createDelegationConfig = {\n environment,\n from,\n caveats,\n salt,\n scope,\n };\n }\n\n const rootDelegator =\n existingDelegations[existingDelegations.length - 1]?.delegator ?? from;\n\n return {\n account,\n createDelegationConfig,\n delegationManager,\n existingDelegations,\n rootDelegator,\n };\n};\n","import {\n createOpenDelegation,\n encodeDelegations,\n prepareSignDelegationTypedData,\n} from '../delegation';\nimport type {\n PaymentRequirements,\n x402DelegationProvider,\n x402DelegationProviderConfig,\n x402DelegationProviderPaymentPayload,\n} from './x402DelegationProviderTypes';\nimport {\n parseEip155ChainId,\n resolveDelegationCreationContext,\n} from './x402DelegationProviderUtils';\n\nexport type {\n MaybeDeferred,\n PaymentRequirements,\n x402DelegationProvider,\n x402DelegationProviderConfig,\n x402DelegationProviderPaymentPayload,\n} from './x402DelegationProviderTypes';\n\nexport { parseEip155ChainId } from './x402DelegationProviderUtils';\n\n/**\n * Creates a delegation provider function for x402 payment requirements.\n *\n * The returned provider resolves deferred config values using incoming payment\n * requirements, creates an open delegation, signs it, and returns an encoded\n * permission context payload.\n *\n * @param config - Delegation creation and signing configuration.\n * @returns A provider that maps payment requirements to a signed delegation payload.\n */\nexport function createx402DelegationProvider(\n config: x402DelegationProviderConfig,\n): x402DelegationProvider {\n return async (\n requirements: PaymentRequirements,\n ): Promise<x402DelegationProviderPaymentPayload> => {\n const {\n account,\n createDelegationConfig,\n delegationManager,\n existingDelegations,\n rootDelegator,\n } = await resolveDelegationCreationContext(config, requirements);\n\n const delegation = createOpenDelegation(createDelegationConfig);\n\n const chainId = parseEip155ChainId(requirements.network);\n\n const typedData = prepareSignDelegationTypedData({\n delegationManager,\n chainId,\n delegation,\n });\n\n if (!account.signTypedData) {\n throw new Error('Account does not support signTypedData');\n }\n\n const signature = await account.signTypedData(typedData);\n\n const signedDelegation = {\n ...delegation,\n signature,\n };\n\n const permissionContext = encodeDelegations([\n signedDelegation,\n ...existingDelegations,\n ]);\n\n return {\n delegationManager,\n permissionContext,\n delegator: rootDelegator,\n };\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/smart-accounts-kit/smart-accounts-kit/packages/smart-accounts-kit/dist/experimental/index.cjs","../../src/experimental/delegationStorage.ts","../../src/experimental/x402DelegationProviderUtils.ts","../../src/experimental/x402DelegationProvider.ts"],"names":[],"mappings":"AAAA;AACE;AACF,yDAA8B;AAC9B,iCAA8B;AAC9B;AACE;AACF,yDAA8B;AAC9B,iCAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B;AACA;AClBA,4BAAgC;AA4BzB,IAAM,6BAAA,EAET;AAAA,EACF,GAAA,EAAK,EAAE,MAAA,EAAQ,0CAA0C,CAAA;AAAA,EACzD,IAAA,EAAM,EAAE,MAAA,EAAQ,sCAAsC;AACxD,CAAA;AASA,SAAS,+BAAA,CACP,MAAA,EAC2B;AAC3B,EAAA,MAAM,oBAAA,EAAsB,MAAA,CAAO,OAAA,CAAQ,4BAA4B,CAAA,CAAE,IAAA;AAAA,IACvE,CAAC,CAAC,CAAA,EAAG,GAAG,CAAA,EAAA,GAAM,GAAA,CAAI,OAAA,IAAW;AAAA,EAC/B,CAAA;AAEA,EAAA,OAAO,oBAAA,EAAsB,mBAAA,CAAoB,CAAC,EAAA,EAAI,QAAA;AACxD;AAaO,IAAM,wBAAA,EAAN,MAA8B;AAAA,EAC1B,CAAA,iBAAA,EAAoB,QAAA;AAAA,EAEpB,CAAA,MAAA;AAAA,EAEA,CAAA,OAAA;AAAA,EAEA,CAAA,MAAA;AAAA,EAET,WAAA,CAAY,MAAA,EAAiC;AAC3C,IAAA,MAAM,EAAE,OAAO,EAAA,EAAI,MAAA,CAAO,WAAA;AAE1B,IAAA,iEAAA;AAAA,MACE,kDAAA;AAAA,MACA;AAAA,QACE,WAAA,EAAa,+BAAA,CAAgC,MAAM;AAAA,MACrD;AAAA,IACF,CAAA;AAEA,IAAA,GAAA,CAAI,MAAA,CAAO,QAAA,CAAS,IAAA,CAAK,CAAA,gBAAiB,CAAA,EAAG;AAC3C,MAAA,IAAA,CAAK,CAAA,OAAA,EAAU,MAAA;AAAA,IACjB,EAAA,KAAO;AACL,MAAA,MAAM,UAAA,EAAY,MAAA,CAAO,QAAA,CAAS,GAAG,EAAA,EAAI,GAAA,EAAK,GAAA;AAC9C,MAAA,IAAA,CAAK,CAAA,OAAA,EAAU,CAAA,EAAA;AACjB,IAAA;AACgB,IAAA;AACD,IAAA;AACjB,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAamB,EAAA;AACN,IAAA;AACK,MAAA;AACE,IAAA;AACT,MAAA;AACT,IAAA;AACU,IAAA;AACR,MAAA;AACF,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWM,EAAA;AAGJ,IAAA;AACE,MAAA;AACA,MAAA;AAEI,QAAA;AAGJ,MAAA;AACF,IAAA;AACM,IAAA;AAKW,IAAA;AACA,MAAA;AACf,MAAA;AACU,QAAA;AACC,QAAA;AACP,UAAA;AACA,UAAA;AACF,QAAA;AACF,MAAA;AACF,IAAA;AAEM,IAAA;AAES,IAAA;AACH,MAAA;AACR,QAAA;AACF,MAAA;AACF,IAAA;AAEO,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYM,EAAA;AAIJ,IAAA;AACE,MAAA;AACa,MAAA;AACf,IAAA;AACiB,IAAA;AACA,MAAA;AACf,MAAA;AACU,QAAA;AACC,QAAA;AACP,UAAA;AACA,UAAA;AACF,QAAA;AACF,MAAA;AACF,IAAA;AAEM,IAAA;AAES,IAAA;AACG,MAAA;AAClB,IAAA;AAEO,IAAA;AACT,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQM,EAAA;AACJ,IAAA;AACE,MAAA;AACe,MAAA;AACjB,IAAA;AACgB,IAAA;AACE,MAAA;AAClB,IAAA;AAEM,IAAA;AAEY,IAAA;AAChB,MAAA;AACK,QAAA;AACQ,QAAA;AACb,MAAA;AAEE,MAAA;AAGF,MAAA;AACF,IAAA;AAEiB,IAAA;AACP,MAAA;AACC,MAAA;AACP,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACD,IAAA;AAEK,IAAA;AAGS,IAAA;AACG,MAAA;AAClB,IAAA;AAEiB,IAAA;AACL,MAAA;AACR,QAAA;AACF,MAAA;AACF,IAAA;AAEO,IAAA;AACT,EAAA;AACF;ADvEsB;AACA;AExLtB;AACE;AACA;AACA;AACA;AACA;AACK;AACE;AACiD;AA6F3C;AAIF,EAAA;AACQ,IAAA;AAIJ,IAAA;AACf,EAAA;AAEO,EAAA;AACT;AASgB;AAGK,EAAA;AACjB,IAAA;AACF,EAAA;AAEkB,EAAA;AACA,IAAA;AAClB,EAAA;AAEM,EAAA;AAEI,EAAA;AACQ,IAAA;AAClB,EAAA;AAEO,EAAA;AACT;AAKM;AAQA;AAWA;AAKO,EAAA;AACO,IAAA;AACP,MAAA;AACT,IAAA;AACF,EAAA;AAEW,EAAA;AACE,IAAA;AACO,MAAA;AACP,QAAA;AACT,MAAA;AACF,IAAA;AACF,EAAA;AAEO,EAAA;AACT;AAgBa;AACX,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACyD;AACrC,EAAA;AACF,IAAA;AAClB,EAAA;AACM,EAAA;AACA,EAAA;AAEA,EAAA;AACJ,IAAA;AACA,IAAA;AACY,IAAA;AACN,MAAA;AACK,QAAA;AACT,MAAA;AAEQ,MAAA;AACC,QAAA;AACT,MAAA;AAEE,MAAA;AAGJ,IAAA;AACF,EAAA;AAEI,EAAA;AACK,IAAA;AACT,EAAA;AAEM,EAAA;AACM,IAAA;AACH,IAAA;AACW,MAAA;AAChB,MAAA;AACD,IAAA;AACK,IAAA;AACR,EAAA;AAEoB,EAAA;AACtB;AAcM;AACJ,EAAA;AACA,EAAA;AAC2D;AACtD,EAAA;AACE,IAAA;AACI,MAAA;AACT,IAAA;AACO,IAAA;AACT,EAAA;AAEK,EAAA;AACI,IAAA;AACT,EAAA;AAEM,EAAA;AAGA,EAAA;AACc,IAAA;AACpB,EAAA;AAEM,EAAA;AACS,IAAA;AACf,EAAA;AAEO,EAAA;AACT;AAkBa;AAML,EAAA;AAGF,EAAA;AACQ,IAAA;AACR,MAAA;AACF,IAAA;AACF,EAAA;AAEiB,EAAA;AAEX,EAAA;AAED,EAAA;AACS,IAAA;AACH,MAAA;AACT,IAAA;AAEM,IAAA;AACJ,MAAA;AACA,MAAA;AACY,MAAA;AAEd,IAAA;AAEK,IAAA;AACO,MAAA;AACR,QAAA;AACF,MAAA;AACF,IAAA;AAEO,IAAA;AACT,EAAA;AAEM,EAAA;AAEA,EAAA;AACJ,IAAA;AACA,IAAA;AACY,IAAA;AACN,MAAA;AACK,QAAA;AACT,MAAA;AAEM,MAAA;AACG,QAAA;AACO,MAAA;AAGT,MAAA;AACL,QAAA;AACF,MAAA;AACF,IAAA;AACF,EAAA;AAEI,EAAA;AACK,IAAA;AACT,EAAA;AAEM,EAAA;AACM,IAAA;AACH,IAAA;AACD,IAAA;AACR,EAAA;AAEoB,EAAA;AACtB;AAgBa;AACX,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACwD;AAClD,EAAA;AACQ,IAAA;AACM,IAAA;AACnB,EAAA;AAEK,EAAA;AACJ,IAAA;AACF,EAAA;AAEM,EAAA;AAEA,EAAA;AACJ,IAAA;AACA,IAAA;AACa,IAAA;AAGf,EAAA;AAEI,EAAA;AACK,IAAA;AACT,EAAA;AAE4B,EAAA;AAChB,IAAA;AACH,IAAA;AACD,IAAA;AACR,EAAA;AAEoB,EAAA;AACtB;AAgBa;AACX,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACkD;AAC5C,EAAA;AACa,IAAA;AACf,MAAA;AACA,MAAA;AACA,MAAA;AACF,IAAA;AACE,EAAA;AAEC,EAAA;AACa,IAAA;AAClB,EAAA;AAEK,EAAA;AACa,IAAA;AAClB,EAAA;AAEK,EAAA;AACa,IAAA;AAClB,EAAA;AAEM,EAAA;AACJ,IAAA;AACS,IAAA;AAAA;AAAA;AAGQ,IAAA;AAClB,EAAA;AAEK,EAAA;AACJ,IAAA;AACA,IAAA;AACA,IAAA;AACS,IAAA;AACT,IAAA;AACA,IAAA;AACD,EAAA;AAEK,EAAA;AACJ,IAAA;AACS,IAAA;AACT,IAAA;AACA,IAAA;AACD,EAAA;AAEG,EAAA;AACK,IAAA;AACT,EAAA;AAEO,EAAA;AACL,IAAA;AACS,IAAA;AACT,IAAA;AACA,IAAA;AACD,EAAA;AACH;AASa;AAIK,EAAA;AACV,EAAA;AACG,IAAA;AACP,IAAA;AACF,EAAA;AAEM,EAAA;AACA,EAAA;AACa,oBAAA;AACjB,IAAA;AACF,EAAA;AAEM,EAAA;AACG,IAAA;AACP,IAAA;AACF,EAAA;AAEE,EAAA;AAGI,EAAA;AACG,IAAA;AACP,IAAA;AACF,EAAA;AACM,EAAA;AAEA,EAAA;AACG,IAAA;AACP,IAAA;AACF,EAAA;AAGS,EAAA;AAEA,EAAA;AAEK,EAAA;AACZ,IAAA;AACc,IAAA;AACI,IAAA;AACpB,EAAA;AAEM,EAAA;AAIA,EAAA;AAIE,EAAA;AACQ,EAAA;AACd,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACO,IAAA;AACP,IAAA;AACA,IAAA;AACA,IAAA;AACD,EAAA;AAEG,EAAA;AAEA,EAAA;AACI,IAAA;AAED,IAAA;AACa,MAAA;AAClB,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACF,IAAA;AACK,EAAA;AACL,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACF,IAAA;AACF,EAAA;AAEM,EAAA;AAGC,EAAA;AACL,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACF;AFpHsB;AACA;AG7dT;AACX,EAAA;AACA,EAAA;AACA,EAAA;AACF;AACa;AACX,EAAA;AACF;AAYgB;AAIZ,EAAA;AAEM,IAAA;AACJ,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACQ,IAAA;AAEJ,IAAA;AAEU,IAAA;AAEE,IAAA;AAChB,MAAA;AACA,MAAA;AACA,MAAA;AACD,IAAA;AAEY,IAAA;AACK,MAAA;AAClB,IAAA;AAEkB,IAAA;AAEZ,IAAA;AACD,MAAA;AACH,MAAA;AACF,IAAA;AAEM,IAAA;AACJ,MAAA;AACG,MAAA;AACJ,IAAA;AAEM,IAAA;AACL,MAAA;AACA,MAAA;AACW,MAAA;AACb,IAAA;AACF,EAAA;AACF;AHwcsB;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/smart-accounts-kit/smart-accounts-kit/packages/smart-accounts-kit/dist/experimental/index.cjs","sourcesContent":[null,"import { type Hex, toHex } from 'viem';\n\nimport { trackSmartAccountsKitFunctionCall } from '../analytics';\nimport { hashDelegation } from '../delegation';\nimport type { Delegation } from '../types';\n\ntype ErrorResponse = {\n error: string;\n data?: any;\n};\n\nexport type APIStoreDelegationResponse = {\n delegationHash: Hex;\n};\n\n/**\n * Represents the allowed filters when querying the data store for delegations.\n */\nexport enum DelegationStoreFilter {\n Given = 'GIVEN',\n Received = 'RECEIVED',\n All = 'ALL',\n}\n\n/**\n * Public Delegation Storage Service environments. To be used in the\n * DeleGationStorageService config.\n */\nexport const DelegationStorageEnvironment: {\n [K in 'dev' | 'prod']: Environment;\n} = {\n dev: { apiUrl: 'https://passkeys.dev-api.cx.metamask.io' },\n prod: { apiUrl: 'https://passkeys.api.cx.metamask.io' },\n};\n\n/**\n * Returns the DelegationStorageEnvironment ('dev' or 'prod') for a given apiUrl,\n * or 'custom' if the apiUrl does not match a known environment.\n *\n * @param apiUrl - The API URL to check.\n * @returns The environment key ('dev' or 'prod'), or 'custom'.\n */\nfunction getDelegationStorageEnvironment(\n apiUrl: string,\n): 'dev' | 'prod' | 'custom' {\n const matchingEnvironment = Object.entries(DelegationStorageEnvironment).find(\n ([_, env]) => env.apiUrl === apiUrl,\n ) as [keyof typeof DelegationStorageEnvironment, Environment] | undefined;\n\n return matchingEnvironment ? matchingEnvironment[0] : 'custom';\n}\n\nexport type Environment = {\n apiUrl: string;\n};\n\nexport type DelegationStorageConfig = {\n apiKey: string;\n apiKeyId: string;\n environment: Environment;\n fetcher?: typeof fetch;\n};\n\nexport class DelegationStorageClient {\n readonly #apiVersionPrefix = 'api/v0';\n\n readonly #config: DelegationStorageConfig;\n\n readonly #fetcher: typeof fetch;\n\n readonly #apiUrl: string;\n\n constructor(config: DelegationStorageConfig) {\n const { apiUrl } = config.environment;\n\n trackSmartAccountsKitFunctionCall(\n 'experimental.DelegationStorageClient.constructor',\n {\n environment: getDelegationStorageEnvironment(apiUrl),\n },\n );\n\n if (apiUrl.endsWith(this.#apiVersionPrefix)) {\n this.#apiUrl = apiUrl;\n } else {\n const separator = apiUrl.endsWith('/') ? '' : '/';\n this.#apiUrl = `${apiUrl}${separator}${this.#apiVersionPrefix}`;\n }\n this.#fetcher = this.#initializeFetcher(config);\n this.#config = config;\n }\n\n /**\n * Initializes the fetch function for HTTP requests.\n *\n * - Uses `config.fetcher` if provided.\n * - Falls back to global `fetch` if available.\n * - Throws an error if no fetch function is available.\n *\n * @param config - Configuration object that may include a custom fetch function.\n * @returns The fetch function to be used for HTTP requests.\n * @throws Error if no fetch function is available in the environment.\n */\n #initializeFetcher(config: DelegationStorageConfig): typeof fetch {\n if (config.fetcher) {\n return config.fetcher;\n } else if (typeof globalThis?.fetch === 'function') {\n return globalThis.fetch.bind(globalThis);\n }\n throw new Error(\n 'Fetch API is not available in this environment. Please provide a fetch function in the config.',\n );\n }\n\n /**\n * Fetches the delegation chain from the Delegation Storage Service, ending with\n * the specified leaf delegation.\n *\n * @param leafDelegationOrDelegationHash - The leaf delegation, or the hash\n * of the leaf delegation.\n * @returns A promise that resolves to the delegation chain - empty array if the delegation\n * is not found.\n */\n async getDelegationChain(\n leafDelegationOrDelegationHash: Hex | Delegation,\n ): Promise<Delegation[]> {\n trackSmartAccountsKitFunctionCall(\n 'experimental.DelegationStorageClient.getDelegationChain',\n {\n inputKind:\n typeof leafDelegationOrDelegationHash === 'string'\n ? 'hash'\n : 'delegation',\n },\n );\n const leafDelegationHash =\n typeof leafDelegationOrDelegationHash === 'string'\n ? leafDelegationOrDelegationHash\n : hashDelegation(leafDelegationOrDelegationHash);\n\n const response = await this.#fetcher(\n `${this.#apiUrl}/delegation/chain/${leafDelegationHash}`,\n {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${this.#config.apiKey}`,\n 'x-api-key-id': this.#config.apiKeyId,\n },\n },\n );\n\n const responseData: Delegation[] | ErrorResponse = await response.json();\n\n if ('error' in responseData) {\n throw new Error(\n `Failed to fetch delegation chain: ${responseData.error}`,\n );\n }\n\n return responseData;\n }\n\n /**\n * Fetches the delegations from the Delegation Storage Service, either `Received`\n * by, or `Given` by, (or both: `All`) the specified deleGatorAddress. Defaults\n * to `Received`.\n *\n * @param deleGatorAddress - The deleGatorAddress to retrieve the delegations for.\n * @param filterMode - The DelegationStoreFilter mode - defaults to Received.\n * @returns A promise that resolves to the list of delegations received by the deleGatorAddress,\n * empty array if the delegations are not found.\n */\n async fetchDelegations(\n deleGatorAddress: Hex,\n filterMode = DelegationStoreFilter.Received,\n ): Promise<Delegation[]> {\n trackSmartAccountsKitFunctionCall(\n 'experimental.DelegationStorageClient.fetchDelegations',\n { filterMode },\n );\n const response = await this.#fetcher(\n `${this.#apiUrl}/delegation/accounts/${deleGatorAddress}?filter=${filterMode}`,\n {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${this.#config.apiKey}`,\n 'x-api-key-id': this.#config.apiKeyId,\n },\n },\n );\n\n const responseData: Delegation[] | ErrorResponse = await response.json();\n\n if ('error' in responseData) {\n throw new Error(`Failed to fetch delegations: ${responseData.error}`);\n }\n\n return responseData;\n }\n\n /**\n * Stores the specified delegation in the Delegation Storage Service.\n *\n * @param delegation - The delegation to store.\n * @returns A promise that resolves to the delegation hash indicating successful storage.\n */\n async storeDelegation(delegation: Delegation): Promise<Hex> {\n trackSmartAccountsKitFunctionCall(\n 'experimental.DelegationStorageClient.storeDelegation',\n { caveatCount: delegation.caveats.length },\n );\n if (!delegation.signature || delegation.signature === '0x') {\n throw new Error('Delegation must be signed to be stored');\n }\n\n const delegationHash = hashDelegation(delegation);\n\n const body = JSON.stringify(\n {\n ...delegation,\n metadata: [],\n },\n (_, value: any) =>\n typeof value === 'bigint' || typeof value === 'number'\n ? toHex(value)\n : value,\n 2,\n );\n\n const response = await this.#fetcher(`${this.#apiUrl}/delegation/store`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.#config.apiKey}`,\n 'x-api-key-id': this.#config.apiKeyId,\n 'Content-Type': 'application/json',\n },\n body,\n });\n\n const responseData: APIStoreDelegationResponse | ErrorResponse =\n await response.json();\n\n if ('error' in responseData) {\n throw new Error(responseData.error);\n }\n\n if (responseData.delegationHash !== delegationHash) {\n throw new Error(\n 'Failed to store the Delegation, the hash returned from the MM delegation storage API does not match the hash of the delegation',\n );\n }\n\n return responseData.delegationHash;\n }\n}\n","import {\n createAllowedCalldataTerms,\n createRedeemerTerms,\n createTimestampTerms,\n decodeRedeemerTerms,\n decodeTimestampTerms,\n} from '@metamask/delegation-core';\nimport { parseCaipChainId } from '@metamask/utils';\nimport { pad, type Account, type Address, type Hex } from 'viem';\n\nimport type { Caveats } from '../caveatBuilder';\nimport { resolveCaveats } from '../caveatBuilder';\nimport { ScopeType } from '../constants';\nimport type { createOpenDelegation } from '../delegation';\nimport { decodeDelegations } from '../delegation';\nimport { getSmartAccountsEnvironment } from '../smartAccountsEnvironment';\nimport type {\n Caveat,\n Delegation,\n PermissionContext,\n SmartAccountsEnvironment,\n} from '../types';\nimport type {\n MaybeDeferred,\n PaymentRequirements,\n x402DelegationProviderConfig,\n} from './x402DelegationProviderTypes';\nimport { generateSalt } from '../utils/';\n\n/**\n * Inputs for redeemer constraint enforcement.\n */\ntype EnsureRedeemerSufficientlyConstrainedParams = {\n redeemerEnforcer: Hex;\n caveats: Caveat[];\n existingDelegations: Delegation[];\n facilitatorAddresses: Address[] | undefined;\n redeemerAddresses: Address[] | undefined;\n requireRedeemers: boolean;\n};\n\n/**\n * Inputs for payee constraint enforcement.\n */\ntype EnsurePayeeSufficientlyConstrainedParams = {\n allowedCalldataEnforcer: Hex;\n caveats: Caveat[];\n existingDelegations: Delegation[];\n payee: Hex;\n};\n\n/**\n * Inputs for expiry constraint enforcement.\n */\ntype EnsureExpirySufficientlyConstrainedParams = {\n timestampEnforcer: Hex;\n caveats: Caveat[];\n existingDelegations: Delegation[];\n expirySeconds: number;\n};\n\n/**\n * Inputs for resolving allowed redeemer addresses.\n */\ntype ResolveRedeemerAddressesParams = Pick<\n EnsureRedeemerSufficientlyConstrainedParams,\n 'facilitatorAddresses' | 'redeemerAddresses'\n>;\n\n/**\n * Resolved context required to build and sign an x402 delegation.\n */\nexport type DelegationCreationContext = {\n account: Account;\n createDelegationConfig: Parameters<typeof createOpenDelegation>[0];\n delegationManager: Address;\n existingDelegations: Delegation[];\n rootDelegator: Address;\n};\n\n/**\n * Inputs for resolving delegation caveats with x402-specific constraints.\n */\nexport type Resolvex402DelegationCaveatsParams = {\n environment: SmartAccountsEnvironment;\n caveatsConfig: Caveats | undefined;\n existingDelegations: Delegation[];\n facilitatorAddresses: Hex[] | undefined;\n payee: Hex;\n expirySeconds?: number;\n requireRedeemers: boolean;\n redeemerAddresses: Address[] | undefined;\n};\n\n/**\n * Resolves eager or deferred values against payment requirements.\n *\n * @param maybeDeferred - Value or async resolver function.\n * @param requirements - Payment requirements passed to deferred resolvers.\n * @returns The resolved value, or undefined when no value is provided.\n */\nasync function resolveMaybeDeferred<TResult>(\n maybeDeferred: MaybeDeferred<TResult>,\n requirements: PaymentRequirements,\n): Promise<TResult> {\n if (typeof maybeDeferred === 'function') {\n const deferred = maybeDeferred as (\n deferredRequirements: PaymentRequirements,\n ) => Promise<TResult> | TResult;\n\n return await deferred(requirements);\n }\n\n return maybeDeferred;\n}\n\n/**\n * Parses an EIP-155 CAIP network identifier into a numeric chain ID.\n *\n * @param network - CAIP network identifier (for example, `eip155:1`).\n * @returns Parsed numeric chain ID.\n * @throws If the CAIP namespace is not `eip155`.\n */\nexport function parseEip155ChainId(\n network: PaymentRequirements['network'],\n): number {\n const { namespace, reference } = parseCaipChainId(\n network as `${string}:${string}`,\n );\n\n if (namespace !== 'eip155') {\n throw new Error('Unsupported chain namespace');\n }\n\n const parsedChainId = Number(reference);\n\n if (isNaN(parsedChainId)) {\n throw new Error('Invalid chain id');\n }\n\n return parsedChainId;\n}\n\n/**\n * ERC-20 `transfer(address to, uint256 value)` calldata index for `to`.\n */\nconst TRANSFER_PAYEE_INDEX = 4;\n\n/**\n * Normalizes an address-like hex string for case-insensitive comparisons.\n *\n * @param address - Address value to normalize.\n * @returns Lowercased hex string.\n */\nconst normalizeAddress = (address: Address): Address =>\n address.toLowerCase() as Address;\n\n/**\n * Returns whether any caveat in local or inherited delegations matches a predicate.\n *\n * @param caveats - Current caveat list.\n * @param delegations - Existing delegations whose caveats should also be searched.\n * @param match - Predicate used to match caveats.\n * @returns True when at least one caveat satisfies `match`.\n */\nconst hasMatchingCaveats = (\n caveats: Caveat[],\n delegations: Delegation[],\n match: (caveat: Caveat) => boolean,\n): boolean => {\n for (const caveat of caveats) {\n if (match(caveat)) {\n return true;\n }\n }\n\n for (const delegation of delegations) {\n for (const caveat of delegation.caveats) {\n if (match(caveat)) {\n return true;\n }\n }\n }\n\n return false;\n};\n\n/**\n * Ensures caveats include an expiry timestamp constraint when requested.\n *\n * If an existing timestamp caveat already enforces a tighter (earlier) or equal\n * `validBefore` threshold than requested, caveats are returned unchanged.\n * Otherwise a new timestamp caveat is appended with `afterThreshold = 0`.\n *\n * @param options0 - Expiry constraint evaluation inputs.\n * @param options0.timestampEnforcer - Address of the TimestampEnforcer caveat contract.\n * @param options0.caveats - Currently resolved caveats for the delegation being created.\n * @param options0.existingDelegations - Existing parent-chain delegations to inspect for inherited constraints.\n * @param options0.expirySeconds - Relative expiry from \"now\" in seconds.\n * @returns The original caveats when sufficiently constrained, otherwise caveats with a timestamp caveat appended.\n */\nexport const ensureExpirySufficientlyConstrained = ({\n timestampEnforcer,\n caveats,\n existingDelegations,\n expirySeconds,\n}: EnsureExpirySufficientlyConstrainedParams): Caveat[] => {\n if (expirySeconds < 0) {\n throw new Error('Expiry seconds must be a positive number');\n }\n const beforeThreshold = Math.floor(Date.now() / 1000) + expirySeconds;\n const timestampEnforcerNormalized = normalizeAddress(timestampEnforcer);\n\n const hasSupersedingTimestampConstraint = hasMatchingCaveats(\n caveats,\n existingDelegations,\n (caveat) => {\n if (normalizeAddress(caveat.enforcer) !== timestampEnforcerNormalized) {\n return false;\n }\n\n const { beforeThreshold: existingBeforeThreshold } = decodeTimestampTerms(\n caveat.terms,\n );\n return (\n existingBeforeThreshold !== 0 &&\n existingBeforeThreshold <= beforeThreshold\n );\n },\n );\n\n if (hasSupersedingTimestampConstraint) {\n return caveats;\n }\n\n const timestampCaveat: Caveat = {\n enforcer: timestampEnforcer,\n terms: createTimestampTerms({\n afterThreshold: 0,\n beforeThreshold,\n }),\n args: '0x',\n };\n\n return [...caveats, timestampCaveat];\n};\n\n/**\n * Resolves allowed redeemer addresses from facilitator and configured redeemer inputs.\n *\n * If both inputs are provided, returns their intersection.\n * If only one input is provided, returns that input.\n * If neither input is provided, returns undefined.\n *\n * @param options - Redeemer address inputs.\n * @param options.facilitatorAddresses - Optional facilitator addresses from the PaymentRequirements.\n * @param options.redeemerAddresses - Optional redeemer addresses from the RedeemersConfig.\n * @returns Resolved allowed redeemer addresses, or undefined when no input is provided.\n */\nconst resolveRedeemerAddresses = ({\n facilitatorAddresses,\n redeemerAddresses,\n}: ResolveRedeemerAddressesParams): Address[] | undefined => {\n if (!facilitatorAddresses) {\n if (!redeemerAddresses) {\n return undefined;\n }\n return redeemerAddresses;\n }\n\n if (!redeemerAddresses) {\n return facilitatorAddresses;\n }\n\n const normalizedFacilitatorAddresses =\n facilitatorAddresses.map(normalizeAddress);\n\n const normalizedRedeemerAddressSet = new Set(\n redeemerAddresses.map(normalizeAddress),\n );\n\n const redeemerAddressesIntersection = normalizedFacilitatorAddresses.filter(\n (address) => normalizedRedeemerAddressSet.has(address),\n );\n\n return redeemerAddressesIntersection;\n};\n\n/**\n * Ensures caveats include a sufficiently strict redeemer constraint.\n *\n * Returns the caveat list unchanged when an existing redeemer caveat is already\n * strict enough, or appends a new redeemer caveat scoped to facilitator addresses.\n *\n * @param config - Redeemer constraint evaluation inputs.\n * @param config.redeemerEnforcer - Address of the redeemer enforcer caveat contract.\n * @param config.caveats - Currently resolved caveats for the delegation being created.\n * @param config.existingDelegations - Existing parent-chain delegations to inspect for inherited constraints.\n * @param config.redeemerAddresses - Optional addresses to which redemption should be constrained.\n * @param config.requireRedeemers - Whether at least one redeemer constraint must exist.\n * @returns The original caveats when sufficiently constrained, otherwise caveats with a redeemer caveat appended.\n * @throws If either facilitatorAddresses and/or redeemerAddresses are provided, but the intersection is empty.\n * @throws If requireRedeemers is true, but no valid redeemer addresses are provided, and no existing redeemer caveat is found in the existingDelegations.\n */\nexport const ensureRedeemerSufficientlyConstrained = (\n config: EnsureRedeemerSufficientlyConstrainedParams,\n): Caveat[] => {\n // `redeemerAddresses` is the intersection of `facilitatorAddresses` and `redeemerAddresses`.\n // If either is undefined, it implies no constraint is specified by that value, and the other is returned.\n // If both are undefined, it implies that no constraint is specified overall.\n const redeemerAddresses = resolveRedeemerAddresses(config);\n\n // If the result is defined, but zero-length, it implies no redeemers are allowed, which is a non-satisfiable constraint, so an error is thrown.\n if (redeemerAddresses?.length === 0) {\n throw new Error(\n 'No valid redeemer addresses were resolved. If both `redeemers.addresses` and `extra.facilitatorAddresses` are provided, they must overlap. If only one is provided, it must include at least one address.',\n );\n }\n\n const { caveats, existingDelegations, redeemerEnforcer } = config;\n\n const redeemerEnforcerNormalized = normalizeAddress(redeemerEnforcer);\n\n if (!redeemerAddresses) {\n if (!config.requireRedeemers) {\n return caveats;\n }\n\n const hasExistingRedeemerCaveat = hasMatchingCaveats(\n caveats,\n existingDelegations,\n ({ enforcer }) =>\n normalizeAddress(enforcer) === redeemerEnforcerNormalized,\n );\n\n if (!hasExistingRedeemerCaveat) {\n throw new Error(\n 'Redeemer must be constrained, either in the specified `caveats`, `parentPermissionContext`, or the `PaymentRequirements` as `extra.facilitatorAddresses`.',\n );\n }\n\n return caveats;\n }\n\n const redeemerAddressesSet = new Set(redeemerAddresses.map(normalizeAddress));\n\n const hasSupersedingRedeemerCaveat = hasMatchingCaveats(\n caveats,\n existingDelegations,\n (caveat) => {\n if (normalizeAddress(caveat.enforcer) !== redeemerEnforcerNormalized) {\n return false;\n }\n\n const allowedRedeemerAddresses = decodeRedeemerTerms(\n caveat.terms,\n ).redeemers.map(normalizeAddress);\n\n // If this redeemer caveat only allows redeemer addresses, it is sufficiently constrained.\n return allowedRedeemerAddresses.every((item) =>\n redeemerAddressesSet.has(item),\n );\n },\n );\n\n if (hasSupersedingRedeemerCaveat) {\n return caveats;\n }\n\n const redeemerCaveat: Caveat = {\n enforcer: redeemerEnforcer,\n terms: createRedeemerTerms({ redeemers: redeemerAddresses }),\n args: '0x',\n };\n\n return [...caveats, redeemerCaveat];\n};\n\n/**\n * Ensures caveats include an allowed-calldata constraint for the payment payee.\n *\n * Scans both the in-progress caveat list and parent delegation caveats for an\n * `AllowedCalldataEnforcer` caveat whose terms match the encoded payee calldata\n * constraint. If found, returns caveats unchanged; otherwise appends a payee caveat.\n *\n * @param options0 - Payee constraint evaluation inputs.\n * @param options0.allowedCalldataEnforcer - Address of the AllowedCalldataEnforcer caveat contract.\n * @param options0.caveats - Currently resolved caveats for the delegation being created.\n * @param options0.existingDelegations - Existing parent-chain delegations to inspect for inherited constraints.\n * @param options0.payee - Expected ERC-20 transfer recipient to enforce in calldata.\n * @returns The original caveats when an equivalent payee constraint exists, otherwise caveats with a payee caveat appended.\n */\nexport const ensurePayeeSufficientlyConstrained = ({\n allowedCalldataEnforcer,\n caveats,\n existingDelegations,\n payee,\n}: EnsurePayeeSufficientlyConstrainedParams): Caveat[] => {\n const allowedCalldataTerms = createAllowedCalldataTerms({\n startIndex: TRANSFER_PAYEE_INDEX,\n value: pad(payee, { size: 32 }),\n });\n\n const allowedCalldataEnforcerNormalized = normalizeAddress(\n allowedCalldataEnforcer,\n );\n\n const lowercaseCalldataTerms = allowedCalldataTerms.toLowerCase();\n\n const hasSupersedingAllowedCalldataConstraint = hasMatchingCaveats(\n caveats,\n existingDelegations,\n ({ enforcer, terms }) =>\n normalizeAddress(enforcer) === allowedCalldataEnforcerNormalized &&\n terms.toLowerCase() === lowercaseCalldataTerms,\n );\n\n if (hasSupersedingAllowedCalldataConstraint) {\n return caveats;\n }\n\n const payeeCaveat: Caveat = {\n enforcer: allowedCalldataEnforcer,\n terms: allowedCalldataTerms,\n args: '0x',\n };\n\n return [...caveats, payeeCaveat];\n};\n\n/**\n * Resolves caveats and applies x402-specific redeemer and payee constraints.\n *\n * @param options0 - Caveat resolution inputs.\n * @param options0.environment - Environment containing caveat enforcer addresses.\n * @param options0.caveatsConfig - Optional caveat builder config.\n * @param options0.existingDelegations - Existing parent-chain delegations.\n * @param options0.facilitatorAddresses - Optional facilitator addresses used for redeemer constraints.\n * @param options0.payee - Payee address used for allowed calldata constraints.\n * @param options0.expirySeconds - Optional relative expiry in seconds for adding timestamp constraints.\n * @param options0.requireRedeemers - Whether redeemer constraints are mandatory when no facilitator or configured redeemer addresses are present.\n * @param options0.redeemerAddresses - Optional redeemer addresses from provider config to merge with facilitator addresses.\n * @returns Caveats after redeemer and payee constraints are enforced.\n */\nexport const resolvex402DelegationCaveats = ({\n environment,\n caveatsConfig,\n existingDelegations,\n facilitatorAddresses,\n payee,\n expirySeconds,\n requireRedeemers,\n redeemerAddresses,\n}: Resolvex402DelegationCaveatsParams): Caveat[] => {\n const {\n caveatEnforcers: {\n RedeemerEnforcer: redeemerEnforcer,\n AllowedCalldataEnforcer: allowedCalldataEnforcer,\n TimestampEnforcer: timestampEnforcer,\n },\n } = environment;\n\n if (!redeemerEnforcer) {\n throw new Error('RedeemerEnforcer not found in environment');\n }\n\n if (!allowedCalldataEnforcer) {\n throw new Error('AllowedCalldataEnforcer not found in environment');\n }\n\n if (!timestampEnforcer) {\n throw new Error('TimestampEnforcer not found in environment');\n }\n\n const initialCaveats = resolveCaveats({\n environment,\n caveats: caveatsConfig,\n // Resolve caveats first so downstream constraint checks can append as needed.\n // Scope is still attached later during delegation creation.\n isScopeOptional: true,\n });\n\n const caveatsWithRedeemer = ensureRedeemerSufficientlyConstrained({\n redeemerEnforcer,\n facilitatorAddresses,\n redeemerAddresses,\n caveats: initialCaveats,\n existingDelegations,\n requireRedeemers,\n });\n\n const caveatsWithPayee = ensurePayeeSufficientlyConstrained({\n allowedCalldataEnforcer,\n caveats: caveatsWithRedeemer,\n existingDelegations,\n payee,\n });\n\n if (expirySeconds === undefined) {\n return caveatsWithPayee;\n }\n\n return ensureExpirySufficientlyConstrained({\n timestampEnforcer,\n caveats: caveatsWithPayee,\n existingDelegations,\n expirySeconds,\n });\n};\n\n/**\n * Builds the delegation creation context from provider config and requirements.\n *\n * @param config - Delegation provider config for context construction.\n * @param requirements - Payment requirements used to scope caveats.\n * @returns The resolved context used to create and sign a delegation.\n */\nexport const resolveDelegationCreationContext = async (\n config: x402DelegationProviderConfig,\n requirements: PaymentRequirements,\n): Promise<DelegationCreationContext> => {\n const account = await resolveMaybeDeferred(config.account, requirements);\n const redeemersConfig = await resolveMaybeDeferred(\n config.redeemers,\n requirements,\n );\n\n const requireRedeemers = redeemersConfig?.requireRedeemers ?? false;\n const redeemerAddresses = await resolveMaybeDeferred(\n redeemersConfig?.addresses,\n requirements,\n );\n\n const specifiedEnvironment = await resolveMaybeDeferred(\n config.environment,\n requirements,\n );\n const environment =\n specifiedEnvironment ??\n getSmartAccountsEnvironment(parseEip155ChainId(requirements.network));\n\n const caveatsConfig: Caveats | undefined = await resolveMaybeDeferred(\n config.caveats,\n requirements,\n );\n const parentPermissionContext: PermissionContext | undefined =\n await resolveMaybeDeferred(config.parentPermissionContext, requirements);\n const expirySeconds = await resolveMaybeDeferred(\n config.expirySeconds,\n requirements,\n );\n\n const from =\n (await resolveMaybeDeferred(config.from, requirements)) ?? account.address;\n const salt =\n (await resolveMaybeDeferred(config.salt, requirements)) ?? generateSalt();\n\n const scope = {\n type: ScopeType.Erc20TransferAmount,\n tokenAddress: requirements.asset as Hex,\n maxAmount: BigInt(requirements.amount),\n } as const;\n\n const facilitatorAddresses = requirements.extra?.facilitatorAddresses as\n | Hex[]\n | undefined;\n\n const existingDelegations = parentPermissionContext\n ? decodeDelegations(parentPermissionContext)\n : [];\n\n const { DelegationManager: delegationManager } = environment;\n const caveats = resolvex402DelegationCaveats({\n environment,\n caveatsConfig,\n existingDelegations,\n facilitatorAddresses,\n payee: requirements.payTo as Hex,\n expirySeconds,\n requireRedeemers,\n redeemerAddresses,\n });\n\n let createDelegationConfig: Parameters<typeof createOpenDelegation>[0];\n\n if (parentPermissionContext) {\n const parentDelegation = existingDelegations[0];\n\n if (!parentDelegation) {\n throw new Error('Parent permission context is not a valid delegation');\n }\n\n createDelegationConfig = {\n environment,\n from,\n caveats,\n salt,\n scope,\n parentDelegation,\n };\n } else {\n createDelegationConfig = {\n environment,\n from,\n caveats,\n salt,\n scope,\n };\n }\n\n const rootDelegator =\n existingDelegations[existingDelegations.length - 1]?.delegator ?? from;\n\n return {\n account,\n createDelegationConfig,\n delegationManager,\n existingDelegations,\n rootDelegator,\n };\n};\n","import type { Address } from 'viem';\n\nimport {\n createOpenDelegation,\n encodeDelegations,\n prepareSignDelegationTypedData,\n} from '../delegation';\nimport type {\n PaymentRequirements,\n x402DelegationProvider,\n x402DelegationProviderConfig,\n x402DelegationProviderPaymentPayload,\n} from './x402DelegationProviderTypes';\nimport {\n parseEip155ChainId,\n resolveDelegationCreationContext,\n} from './x402DelegationProviderUtils';\n\nexport type {\n MaybeDeferred,\n PaymentRequirements,\n x402DelegationProvider,\n x402DelegationProviderConfig,\n x402DelegationProviderPaymentPayload,\n} from './x402DelegationProviderTypes';\n\nexport { parseEip155ChainId } from './x402DelegationProviderUtils';\n\nexport const METAMASK_FACILITATOR_ADDRESSES: readonly Address[] = [\n '0xB01caEa8c6C47bbf4F4b4c5080Ca642043359C2E',\n '0xC066ac5D385419B1A8c43A0E146fA439837a8B8c',\n '0xB42F812A44c22cc6b861478900401ee759EbEAD6',\n];\nexport const METAMASK_FACILITATOR_ADDRESSES_DEV: readonly Address[] = [\n '0xb4827A2a066CD2Ef88560EFdf063dD05C6c41cC7',\n];\n\n/**\n * Creates a delegation provider function for x402 payment requirements.\n *\n * The returned provider resolves deferred config values using incoming payment\n * requirements, creates an open delegation, signs it, and returns an encoded\n * permission context payload.\n *\n * @param config - Delegation creation and signing configuration.\n * @returns A provider that maps payment requirements to a signed delegation payload.\n */\nexport function createx402DelegationProvider(\n config: x402DelegationProviderConfig,\n): x402DelegationProvider {\n return async (\n requirements: PaymentRequirements,\n ): Promise<x402DelegationProviderPaymentPayload> => {\n const {\n account,\n createDelegationConfig,\n delegationManager,\n existingDelegations,\n rootDelegator,\n } = await resolveDelegationCreationContext(config, requirements);\n\n const delegation = createOpenDelegation(createDelegationConfig);\n\n const chainId = parseEip155ChainId(requirements.network);\n\n const typedData = prepareSignDelegationTypedData({\n delegationManager,\n chainId,\n delegation,\n });\n\n if (!account.signTypedData) {\n throw new Error('Account does not support signTypedData');\n }\n\n const signature = await account.signTypedData(typedData);\n\n const signedDelegation = {\n ...delegation,\n signature,\n };\n\n const permissionContext = encodeDelegations([\n signedDelegation,\n ...existingDelegations,\n ]);\n\n return {\n delegationManager,\n permissionContext,\n delegator: rootDelegator,\n };\n };\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hex, Account, Address } from 'viem';
|
|
2
|
-
import { D as Delegation, S as SmartAccountsEnvironment,
|
|
2
|
+
import { D as Delegation, S as SmartAccountsEnvironment, C as Caveats, P as PermissionContext } from '../resolveCaveats-aQPEogPk.cjs';
|
|
3
3
|
import '@metamask/delegation-abis';
|
|
4
4
|
import 'viem/account-abstraction';
|
|
5
5
|
import 'viem/chains';
|
|
@@ -63,6 +63,8 @@ type x402DelegationProviderConfig = {
|
|
|
63
63
|
|
|
64
64
|
declare function parseEip155ChainId(network: PaymentRequirements['network']): number;
|
|
65
65
|
|
|
66
|
+
declare const METAMASK_FACILITATOR_ADDRESSES: readonly Address[];
|
|
67
|
+
declare const METAMASK_FACILITATOR_ADDRESSES_DEV: readonly Address[];
|
|
66
68
|
declare function createx402DelegationProvider(config: x402DelegationProviderConfig): x402DelegationProvider;
|
|
67
69
|
|
|
68
|
-
export { DelegationStorageClient, type DelegationStorageConfig, DelegationStorageEnvironment, DelegationStoreFilter, type Environment, type MaybeDeferred, type PaymentRequirements, createx402DelegationProvider, parseEip155ChainId, type x402DelegationProvider, type x402DelegationProviderConfig, type x402DelegationProviderPaymentPayload };
|
|
70
|
+
export { DelegationStorageClient, type DelegationStorageConfig, DelegationStorageEnvironment, DelegationStoreFilter, type Environment, METAMASK_FACILITATOR_ADDRESSES, METAMASK_FACILITATOR_ADDRESSES_DEV, type MaybeDeferred, type PaymentRequirements, createx402DelegationProvider, parseEip155ChainId, type x402DelegationProvider, type x402DelegationProviderConfig, type x402DelegationProviderPaymentPayload };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hex, Account, Address } from 'viem';
|
|
2
|
-
import { D as Delegation, S as SmartAccountsEnvironment,
|
|
2
|
+
import { D as Delegation, S as SmartAccountsEnvironment, C as Caveats, P as PermissionContext } from '../resolveCaveats-aQPEogPk.js';
|
|
3
3
|
import '@metamask/delegation-abis';
|
|
4
4
|
import 'viem/account-abstraction';
|
|
5
5
|
import 'viem/chains';
|
|
@@ -63,6 +63,8 @@ type x402DelegationProviderConfig = {
|
|
|
63
63
|
|
|
64
64
|
declare function parseEip155ChainId(network: PaymentRequirements['network']): number;
|
|
65
65
|
|
|
66
|
+
declare const METAMASK_FACILITATOR_ADDRESSES: readonly Address[];
|
|
67
|
+
declare const METAMASK_FACILITATOR_ADDRESSES_DEV: readonly Address[];
|
|
66
68
|
declare function createx402DelegationProvider(config: x402DelegationProviderConfig): x402DelegationProvider;
|
|
67
69
|
|
|
68
|
-
export { DelegationStorageClient, type DelegationStorageConfig, DelegationStorageEnvironment, DelegationStoreFilter, type Environment, type MaybeDeferred, type PaymentRequirements, createx402DelegationProvider, parseEip155ChainId, type x402DelegationProvider, type x402DelegationProviderConfig, type x402DelegationProviderPaymentPayload };
|
|
70
|
+
export { DelegationStorageClient, type DelegationStorageConfig, DelegationStorageEnvironment, DelegationStoreFilter, type Environment, METAMASK_FACILITATOR_ADDRESSES, METAMASK_FACILITATOR_ADDRESSES_DEV, type MaybeDeferred, type PaymentRequirements, createx402DelegationProvider, parseEip155ChainId, type x402DelegationProvider, type x402DelegationProviderConfig, type x402DelegationProviderPaymentPayload };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generateSalt
|
|
3
3
|
} from "../chunk-IMO6XNDJ.mjs";
|
|
4
|
-
import "../chunk-
|
|
4
|
+
import "../chunk-T6SWQZRX.mjs";
|
|
5
5
|
import {
|
|
6
6
|
getSmartAccountsEnvironment
|
|
7
7
|
} from "../chunk-GMGJRC3D.mjs";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-EMPAUTIV.mjs";
|
|
9
9
|
import {
|
|
10
10
|
createOpenDelegation,
|
|
11
11
|
decodeDelegations,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
prepareSignDelegationTypedData,
|
|
15
15
|
resolveCaveats,
|
|
16
16
|
trackSmartAccountsKitFunctionCall
|
|
17
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-3KWKQ7PV.mjs";
|
|
18
18
|
|
|
19
19
|
// src/experimental/delegationStorage.ts
|
|
20
20
|
import { toHex } from "viem";
|
|
@@ -266,22 +266,45 @@ var ensureExpirySufficientlyConstrained = ({
|
|
|
266
266
|
};
|
|
267
267
|
return [...caveats, timestampCaveat];
|
|
268
268
|
};
|
|
269
|
-
var
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
existingDelegations,
|
|
273
|
-
redeemerAddresses,
|
|
274
|
-
requireRedeemers
|
|
269
|
+
var resolveRedeemerAddresses = ({
|
|
270
|
+
facilitatorAddresses,
|
|
271
|
+
redeemerAddresses
|
|
275
272
|
}) => {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
273
|
+
if (!facilitatorAddresses) {
|
|
274
|
+
if (!redeemerAddresses) {
|
|
275
|
+
return void 0;
|
|
276
|
+
}
|
|
277
|
+
return redeemerAddresses;
|
|
278
|
+
}
|
|
279
|
+
if (!redeemerAddresses) {
|
|
280
|
+
return facilitatorAddresses;
|
|
281
|
+
}
|
|
282
|
+
const normalizedFacilitatorAddresses = facilitatorAddresses.map(normalizeAddress);
|
|
283
|
+
const normalizedRedeemerAddressSet = new Set(
|
|
284
|
+
redeemerAddresses.map(normalizeAddress)
|
|
285
|
+
);
|
|
286
|
+
const redeemerAddressesIntersection = normalizedFacilitatorAddresses.filter(
|
|
287
|
+
(address) => normalizedRedeemerAddressSet.has(address)
|
|
288
|
+
);
|
|
289
|
+
return redeemerAddressesIntersection;
|
|
290
|
+
};
|
|
291
|
+
var ensureRedeemerSufficientlyConstrained = (config) => {
|
|
292
|
+
const redeemerAddresses = resolveRedeemerAddresses(config);
|
|
293
|
+
if (redeemerAddresses?.length === 0) {
|
|
294
|
+
throw new Error(
|
|
295
|
+
"No valid redeemer addresses were resolved. If both `redeemers.addresses` and `extra.facilitatorAddresses` are provided, they must overlap. If only one is provided, it must include at least one address."
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
const { caveats, existingDelegations, redeemerEnforcer } = config;
|
|
299
|
+
const redeemerEnforcerNormalized = normalizeAddress(redeemerEnforcer);
|
|
300
|
+
if (!redeemerAddresses) {
|
|
301
|
+
if (!config.requireRedeemers) {
|
|
279
302
|
return caveats;
|
|
280
303
|
}
|
|
281
304
|
const hasExistingRedeemerCaveat = hasMatchingCaveats(
|
|
282
305
|
caveats,
|
|
283
306
|
existingDelegations,
|
|
284
|
-
({ enforcer }) => normalizeAddress(enforcer) ===
|
|
307
|
+
({ enforcer }) => normalizeAddress(enforcer) === redeemerEnforcerNormalized
|
|
285
308
|
);
|
|
286
309
|
if (!hasExistingRedeemerCaveat) {
|
|
287
310
|
throw new Error(
|
|
@@ -290,13 +313,12 @@ var ensureRedeemerSufficientlyConstrained = ({
|
|
|
290
313
|
}
|
|
291
314
|
return caveats;
|
|
292
315
|
}
|
|
293
|
-
const
|
|
294
|
-
const redeemerAddressesSet = new Set(redeemerAddressesNormalized);
|
|
316
|
+
const redeemerAddressesSet = new Set(redeemerAddresses.map(normalizeAddress));
|
|
295
317
|
const hasSupersedingRedeemerCaveat = hasMatchingCaveats(
|
|
296
318
|
caveats,
|
|
297
319
|
existingDelegations,
|
|
298
320
|
(caveat) => {
|
|
299
|
-
if (normalizeAddress(caveat.enforcer) !==
|
|
321
|
+
if (normalizeAddress(caveat.enforcer) !== redeemerEnforcerNormalized) {
|
|
300
322
|
return false;
|
|
301
323
|
}
|
|
302
324
|
const allowedRedeemerAddresses = decodeRedeemerTerms(
|
|
@@ -379,16 +401,12 @@ var resolvex402DelegationCaveats = ({
|
|
|
379
401
|
// Scope is still attached later during delegation creation.
|
|
380
402
|
isScopeOptional: true
|
|
381
403
|
});
|
|
382
|
-
const allRedeemerAddresses = new Set(
|
|
383
|
-
[...facilitatorAddresses ?? [], ...redeemerAddresses ?? []].map(
|
|
384
|
-
normalizeAddress
|
|
385
|
-
)
|
|
386
|
-
);
|
|
387
404
|
const caveatsWithRedeemer = ensureRedeemerSufficientlyConstrained({
|
|
388
405
|
redeemerEnforcer,
|
|
406
|
+
facilitatorAddresses,
|
|
407
|
+
redeemerAddresses,
|
|
389
408
|
caveats: initialCaveats,
|
|
390
409
|
existingDelegations,
|
|
391
|
-
redeemerAddresses: Array.from(allRedeemerAddresses),
|
|
392
410
|
requireRedeemers
|
|
393
411
|
});
|
|
394
412
|
const caveatsWithPayee = ensurePayeeSufficientlyConstrained({
|
|
@@ -486,6 +504,14 @@ var resolveDelegationCreationContext = async (config, requirements) => {
|
|
|
486
504
|
};
|
|
487
505
|
|
|
488
506
|
// src/experimental/x402DelegationProvider.ts
|
|
507
|
+
var METAMASK_FACILITATOR_ADDRESSES = [
|
|
508
|
+
"0xB01caEa8c6C47bbf4F4b4c5080Ca642043359C2E",
|
|
509
|
+
"0xC066ac5D385419B1A8c43A0E146fA439837a8B8c",
|
|
510
|
+
"0xB42F812A44c22cc6b861478900401ee759EbEAD6"
|
|
511
|
+
];
|
|
512
|
+
var METAMASK_FACILITATOR_ADDRESSES_DEV = [
|
|
513
|
+
"0xb4827A2a066CD2Ef88560EFdf063dD05C6c41cC7"
|
|
514
|
+
];
|
|
489
515
|
function createx402DelegationProvider(config) {
|
|
490
516
|
return async (requirements) => {
|
|
491
517
|
const {
|
|
@@ -524,6 +550,8 @@ function createx402DelegationProvider(config) {
|
|
|
524
550
|
export {
|
|
525
551
|
DelegationStorageClient,
|
|
526
552
|
DelegationStorageEnvironment,
|
|
553
|
+
METAMASK_FACILITATOR_ADDRESSES,
|
|
554
|
+
METAMASK_FACILITATOR_ADDRESSES_DEV,
|
|
527
555
|
createx402DelegationProvider,
|
|
528
556
|
parseEip155ChainId
|
|
529
557
|
};
|