@x402/extensions 2.6.0 → 2.8.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/README.md +27 -22
- package/dist/cjs/bazaar/index.d.ts +1 -1
- package/dist/cjs/bazaar/index.js +137 -7
- package/dist/cjs/bazaar/index.js.map +1 -1
- package/dist/cjs/{index-CtOzXcjN.d.ts → index-DihVrF7v.d.ts} +49 -9
- package/dist/cjs/index.d.ts +33 -23
- package/dist/cjs/index.js +1015 -20
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/offer-receipt/index.d.ts +702 -0
- package/dist/cjs/offer-receipt/index.js +909 -0
- package/dist/cjs/offer-receipt/index.js.map +1 -0
- package/dist/cjs/sign-in-with-x/index.d.ts +7 -1
- package/dist/cjs/sign-in-with-x/index.js +5 -5
- package/dist/cjs/sign-in-with-x/index.js.map +1 -1
- package/dist/esm/bazaar/index.d.mts +1 -1
- package/dist/esm/bazaar/index.mjs +5 -1
- package/dist/esm/{chunk-O34SGKEP.mjs → chunk-5UYCX7A7.mjs} +6 -6
- package/dist/esm/chunk-5UYCX7A7.mjs.map +1 -0
- package/dist/esm/{chunk-ANAQVNUK.mjs → chunk-I2JLOI4L.mjs} +136 -8
- package/dist/esm/chunk-I2JLOI4L.mjs.map +1 -0
- package/dist/esm/chunk-TYR4QHVX.mjs +828 -0
- package/dist/esm/chunk-TYR4QHVX.mjs.map +1 -0
- package/dist/esm/{index-CtOzXcjN.d.mts → index-DihVrF7v.d.mts} +49 -9
- package/dist/esm/index.d.mts +33 -23
- package/dist/esm/index.mjs +102 -10
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/offer-receipt/index.d.mts +702 -0
- package/dist/esm/offer-receipt/index.mjs +97 -0
- package/dist/esm/offer-receipt/index.mjs.map +1 -0
- package/dist/esm/sign-in-with-x/index.d.mts +7 -1
- package/dist/esm/sign-in-with-x/index.mjs +1 -1
- package/package.json +14 -2
- package/dist/esm/chunk-ANAQVNUK.mjs.map +0 -1
- package/dist/esm/chunk-O34SGKEP.mjs.map +0 -1
package/dist/cjs/index.js
CHANGED
|
@@ -35,10 +35,13 @@ __export(src_exports, {
|
|
|
35
35
|
ERC20_APPROVAL_GAS_SPONSORING: () => ERC20_APPROVAL_GAS_SPONSORING,
|
|
36
36
|
ERC20_APPROVAL_GAS_SPONSORING_VERSION: () => ERC20_APPROVAL_GAS_SPONSORING_VERSION,
|
|
37
37
|
InMemorySIWxStorage: () => InMemorySIWxStorage,
|
|
38
|
+
OFFER_RECEIPT: () => OFFER_RECEIPT,
|
|
39
|
+
OFFER_TYPES: () => OFFER_TYPES,
|
|
38
40
|
PAYMENT_IDENTIFIER: () => PAYMENT_IDENTIFIER,
|
|
39
41
|
PAYMENT_ID_MAX_LENGTH: () => PAYMENT_ID_MAX_LENGTH,
|
|
40
42
|
PAYMENT_ID_MIN_LENGTH: () => PAYMENT_ID_MIN_LENGTH,
|
|
41
43
|
PAYMENT_ID_PATTERN: () => PAYMENT_ID_PATTERN,
|
|
44
|
+
RECEIPT_TYPES: () => RECEIPT_TYPES,
|
|
42
45
|
SIGN_IN_WITH_X: () => SIGN_IN_WITH_X,
|
|
43
46
|
SIWxPayloadSchema: () => SIWxPayloadSchema,
|
|
44
47
|
SOLANA_DEVNET: () => SOLANA_DEVNET,
|
|
@@ -47,7 +50,19 @@ __export(src_exports, {
|
|
|
47
50
|
appendPaymentIdentifierToExtensions: () => appendPaymentIdentifierToExtensions,
|
|
48
51
|
bazaarResourceServerExtension: () => bazaarResourceServerExtension,
|
|
49
52
|
buildSIWxSchema: () => buildSIWxSchema,
|
|
53
|
+
canonicalize: () => canonicalize,
|
|
54
|
+
convertNetworkStringToCAIP2: () => convertNetworkStringToCAIP2,
|
|
55
|
+
createEIP712OfferReceiptIssuer: () => createEIP712OfferReceiptIssuer,
|
|
50
56
|
createErc20ApprovalGasSponsoringExtension: () => createErc20ApprovalGasSponsoringExtension,
|
|
57
|
+
createJWS: () => createJWS,
|
|
58
|
+
createJWSOfferReceiptIssuer: () => createJWSOfferReceiptIssuer,
|
|
59
|
+
createOfferDomain: () => createOfferDomain,
|
|
60
|
+
createOfferEIP712: () => createOfferEIP712,
|
|
61
|
+
createOfferJWS: () => createOfferJWS,
|
|
62
|
+
createOfferReceiptExtension: () => createOfferReceiptExtension,
|
|
63
|
+
createReceiptDomain: () => createReceiptDomain,
|
|
64
|
+
createReceiptEIP712: () => createReceiptEIP712,
|
|
65
|
+
createReceiptJWS: () => createReceiptJWS,
|
|
51
66
|
createSIWxClientHook: () => createSIWxClientHook,
|
|
52
67
|
createSIWxMessage: () => createSIWxMessage,
|
|
53
68
|
createSIWxPayload: () => createSIWxPayload,
|
|
@@ -56,41 +71,68 @@ __export(src_exports, {
|
|
|
56
71
|
declareDiscoveryExtension: () => declareDiscoveryExtension,
|
|
57
72
|
declareEip2612GasSponsoringExtension: () => declareEip2612GasSponsoringExtension,
|
|
58
73
|
declareErc20ApprovalGasSponsoringExtension: () => declareErc20ApprovalGasSponsoringExtension,
|
|
74
|
+
declareOfferReceiptExtension: () => declareOfferReceiptExtension,
|
|
59
75
|
declarePaymentIdentifierExtension: () => declarePaymentIdentifierExtension,
|
|
60
76
|
declareSIWxExtension: () => declareSIWxExtension,
|
|
61
77
|
decodeBase58: () => decodeBase58,
|
|
78
|
+
decodeSignedOffers: () => decodeSignedOffers,
|
|
62
79
|
encodeBase58: () => encodeBase58,
|
|
63
80
|
encodeSIWxHeader: () => encodeSIWxHeader,
|
|
64
81
|
erc20ApprovalGasSponsoringSchema: () => erc20ApprovalGasSponsoringSchema,
|
|
65
82
|
extractAndValidatePaymentIdentifier: () => extractAndValidatePaymentIdentifier,
|
|
83
|
+
extractChainIdFromCAIP2: () => extractChainIdFromCAIP2,
|
|
66
84
|
extractDiscoveryInfo: () => extractDiscoveryInfo,
|
|
67
85
|
extractDiscoveryInfoFromExtension: () => extractDiscoveryInfoFromExtension,
|
|
68
86
|
extractDiscoveryInfoV1: () => extractDiscoveryInfoV1,
|
|
87
|
+
extractEIP155ChainId: () => extractEIP155ChainId,
|
|
69
88
|
extractEVMChainId: () => extractEVMChainId,
|
|
70
89
|
extractEip2612GasSponsoringInfo: () => extractEip2612GasSponsoringInfo,
|
|
71
90
|
extractErc20ApprovalGasSponsoringInfo: () => extractErc20ApprovalGasSponsoringInfo,
|
|
91
|
+
extractJWSHeader: () => extractJWSHeader,
|
|
92
|
+
extractJWSPayload: () => extractJWSPayload,
|
|
93
|
+
extractOfferPayload: () => extractOfferPayload,
|
|
94
|
+
extractOffersFromPaymentRequired: () => extractOffersFromPaymentRequired,
|
|
72
95
|
extractPaymentIdentifier: () => extractPaymentIdentifier,
|
|
96
|
+
extractPublicKeyFromKid: () => extractPublicKeyFromKid,
|
|
97
|
+
extractReceiptFromResponse: () => extractReceiptFromResponse,
|
|
98
|
+
extractReceiptPayload: () => extractReceiptPayload,
|
|
73
99
|
extractResourceMetadataV1: () => extractResourceMetadataV1,
|
|
74
100
|
extractSolanaChainReference: () => extractSolanaChainReference,
|
|
101
|
+
findAcceptsObjectFromSignedOffer: () => findAcceptsObjectFromSignedOffer,
|
|
75
102
|
formatSIWEMessage: () => formatSIWEMessage,
|
|
76
103
|
formatSIWSMessage: () => formatSIWSMessage,
|
|
77
104
|
generatePaymentId: () => generatePaymentId,
|
|
105
|
+
getCanonicalBytes: () => getCanonicalBytes,
|
|
78
106
|
getEVMAddress: () => getEVMAddress,
|
|
79
107
|
getSolanaAddress: () => getSolanaAddress,
|
|
80
108
|
hasPaymentIdentifier: () => hasPaymentIdentifier,
|
|
109
|
+
hashCanonical: () => hashCanonical,
|
|
110
|
+
hashOfferTypedData: () => hashOfferTypedData,
|
|
111
|
+
hashReceiptTypedData: () => hashReceiptTypedData,
|
|
81
112
|
isBodyExtensionConfig: () => isBodyExtensionConfig,
|
|
82
113
|
isDiscoverableV1: () => isDiscoverableV1,
|
|
114
|
+
isEIP712SignedOffer: () => isEIP712SignedOffer,
|
|
115
|
+
isEIP712SignedReceipt: () => isEIP712SignedReceipt,
|
|
116
|
+
isEIP712Signer: () => isEIP712Signer,
|
|
83
117
|
isEVMSigner: () => isEVMSigner,
|
|
118
|
+
isJWSSignedOffer: () => isJWSSignedOffer,
|
|
119
|
+
isJWSSignedReceipt: () => isJWSSignedReceipt,
|
|
120
|
+
isJWSSigner: () => isJWSSigner,
|
|
84
121
|
isMcpExtensionConfig: () => isMcpExtensionConfig,
|
|
85
122
|
isPaymentIdentifierExtension: () => isPaymentIdentifierExtension,
|
|
86
123
|
isPaymentIdentifierRequired: () => isPaymentIdentifierRequired,
|
|
87
124
|
isQueryExtensionConfig: () => isQueryExtensionConfig,
|
|
88
125
|
isSolanaSigner: () => isSolanaSigner,
|
|
89
126
|
isValidPaymentId: () => isValidPaymentId,
|
|
127
|
+
isValidRouteTemplate: () => isValidRouteTemplate,
|
|
90
128
|
parseSIWxHeader: () => parseSIWxHeader,
|
|
91
129
|
paymentIdentifierResourceServerExtension: () => paymentIdentifierResourceServerExtension,
|
|
92
130
|
paymentIdentifierSchema: () => paymentIdentifierSchema,
|
|
131
|
+
prepareOfferForEIP712: () => prepareOfferForEIP712,
|
|
132
|
+
prepareReceiptForEIP712: () => prepareReceiptForEIP712,
|
|
93
133
|
signEVMMessage: () => signEVMMessage,
|
|
134
|
+
signOfferEIP712: () => signOfferEIP712,
|
|
135
|
+
signReceiptEIP712: () => signReceiptEIP712,
|
|
94
136
|
signSolanaMessage: () => signSolanaMessage,
|
|
95
137
|
siwxResourceServerExtension: () => siwxResourceServerExtension,
|
|
96
138
|
validateAndExtract: () => validateAndExtract,
|
|
@@ -99,8 +141,14 @@ __export(src_exports, {
|
|
|
99
141
|
validateErc20ApprovalGasSponsoringInfo: () => validateErc20ApprovalGasSponsoringInfo,
|
|
100
142
|
validatePaymentIdentifier: () => validatePaymentIdentifier,
|
|
101
143
|
validatePaymentIdentifierRequirement: () => validatePaymentIdentifierRequirement,
|
|
144
|
+
validateRouteTemplate: () => validateRouteTemplate,
|
|
102
145
|
validateSIWxMessage: () => validateSIWxMessage,
|
|
103
146
|
verifyEVMSignature: () => verifyEVMSignature,
|
|
147
|
+
verifyOfferSignatureEIP712: () => verifyOfferSignatureEIP712,
|
|
148
|
+
verifyOfferSignatureJWS: () => verifyOfferSignatureJWS,
|
|
149
|
+
verifyReceiptMatchesOffer: () => verifyReceiptMatchesOffer,
|
|
150
|
+
verifyReceiptSignatureEIP712: () => verifyReceiptSignatureEIP712,
|
|
151
|
+
verifyReceiptSignatureJWS: () => verifyReceiptSignatureJWS,
|
|
104
152
|
verifySIWxSignature: () => verifySIWxSignature,
|
|
105
153
|
verifySolanaSignature: () => verifySolanaSignature,
|
|
106
154
|
withBazaar: () => withBazaar,
|
|
@@ -129,6 +177,8 @@ function createQueryDiscoveryExtension({
|
|
|
129
177
|
method,
|
|
130
178
|
input = {},
|
|
131
179
|
inputSchema = { properties: {} },
|
|
180
|
+
pathParams,
|
|
181
|
+
pathParamsSchema,
|
|
132
182
|
output
|
|
133
183
|
}) {
|
|
134
184
|
return {
|
|
@@ -136,7 +186,8 @@ function createQueryDiscoveryExtension({
|
|
|
136
186
|
input: {
|
|
137
187
|
type: "http",
|
|
138
188
|
...method ? { method } : {},
|
|
139
|
-
...input ? { queryParams: input } : {}
|
|
189
|
+
...input ? { queryParams: input } : {},
|
|
190
|
+
...pathParams ? { pathParams } : {}
|
|
140
191
|
},
|
|
141
192
|
...output?.example ? {
|
|
142
193
|
output: {
|
|
@@ -165,9 +216,18 @@ function createQueryDiscoveryExtension({
|
|
|
165
216
|
type: "object",
|
|
166
217
|
...typeof inputSchema === "object" ? inputSchema : {}
|
|
167
218
|
}
|
|
219
|
+
} : {},
|
|
220
|
+
...pathParamsSchema ? {
|
|
221
|
+
pathParams: {
|
|
222
|
+
type: "object",
|
|
223
|
+
...typeof pathParamsSchema === "object" ? pathParamsSchema : {}
|
|
224
|
+
}
|
|
168
225
|
} : {}
|
|
169
226
|
},
|
|
170
227
|
required: ["type"],
|
|
228
|
+
// pathParams and method are not declared here at schema build time --
|
|
229
|
+
// the server extension's enrichDeclaration adds them to both info and schema
|
|
230
|
+
// atomically at request time, keeping data and schema consistent.
|
|
171
231
|
additionalProperties: false
|
|
172
232
|
},
|
|
173
233
|
...output?.example ? {
|
|
@@ -194,6 +254,8 @@ function createBodyDiscoveryExtension({
|
|
|
194
254
|
method,
|
|
195
255
|
input = {},
|
|
196
256
|
inputSchema = { properties: {} },
|
|
257
|
+
pathParams,
|
|
258
|
+
pathParamsSchema,
|
|
197
259
|
bodyType,
|
|
198
260
|
output
|
|
199
261
|
}) {
|
|
@@ -203,7 +265,8 @@ function createBodyDiscoveryExtension({
|
|
|
203
265
|
type: "http",
|
|
204
266
|
...method ? { method } : {},
|
|
205
267
|
bodyType,
|
|
206
|
-
body: input
|
|
268
|
+
body: input,
|
|
269
|
+
...pathParams ? { pathParams } : {}
|
|
207
270
|
},
|
|
208
271
|
...output?.example ? {
|
|
209
272
|
output: {
|
|
@@ -231,9 +294,18 @@ function createBodyDiscoveryExtension({
|
|
|
231
294
|
type: "string",
|
|
232
295
|
enum: ["json", "form-data", "text"]
|
|
233
296
|
},
|
|
234
|
-
body: inputSchema
|
|
297
|
+
body: inputSchema,
|
|
298
|
+
...pathParamsSchema ? {
|
|
299
|
+
pathParams: {
|
|
300
|
+
type: "object",
|
|
301
|
+
...typeof pathParamsSchema === "object" ? pathParamsSchema : {}
|
|
302
|
+
}
|
|
303
|
+
} : {}
|
|
235
304
|
},
|
|
236
305
|
required: ["type", "bodyType", "body"],
|
|
306
|
+
// pathParams and method are not declared here at schema build time --
|
|
307
|
+
// the server extension's enrichDeclaration adds them to both info and schema
|
|
308
|
+
// atomically at request time, keeping data and schema consistent.
|
|
237
309
|
additionalProperties: false
|
|
238
310
|
},
|
|
239
311
|
...output?.example ? {
|
|
@@ -354,9 +426,57 @@ function declareDiscoveryExtension(config) {
|
|
|
354
426
|
}
|
|
355
427
|
|
|
356
428
|
// src/bazaar/server.ts
|
|
429
|
+
var BRACKET_PARAM_REGEX = /\[([^\]]+)\]/;
|
|
430
|
+
var BRACKET_PARAM_REGEX_ALL = /\[([^\]]+)\]/g;
|
|
431
|
+
var COLON_PARAM_REGEX = /:([a-zA-Z_][a-zA-Z0-9_]*)/;
|
|
357
432
|
function isHTTPRequestContext(ctx) {
|
|
358
433
|
return ctx !== null && typeof ctx === "object" && "method" in ctx && "adapter" in ctx;
|
|
359
434
|
}
|
|
435
|
+
function normalizeWildcardPattern(pattern) {
|
|
436
|
+
if (!pattern.includes("*")) {
|
|
437
|
+
return pattern;
|
|
438
|
+
}
|
|
439
|
+
let counter = 0;
|
|
440
|
+
return pattern.split("/").map((seg) => {
|
|
441
|
+
if (seg === "*") {
|
|
442
|
+
counter++;
|
|
443
|
+
return `:var${counter}`;
|
|
444
|
+
}
|
|
445
|
+
return seg;
|
|
446
|
+
}).join("/");
|
|
447
|
+
}
|
|
448
|
+
function extractDynamicRouteInfo(routePattern, urlPath) {
|
|
449
|
+
const hasBracket = BRACKET_PARAM_REGEX.test(routePattern);
|
|
450
|
+
const hasColon = COLON_PARAM_REGEX.test(routePattern);
|
|
451
|
+
if (!hasBracket && !hasColon) {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
const normalizedPattern = hasBracket ? routePattern.replace(BRACKET_PARAM_REGEX_ALL, ":$1") : routePattern;
|
|
455
|
+
const pathParams = extractPathParams(normalizedPattern, urlPath, false);
|
|
456
|
+
return { routeTemplate: normalizedPattern, pathParams };
|
|
457
|
+
}
|
|
458
|
+
function extractPathParams(routePattern, urlPath, isBracket) {
|
|
459
|
+
const paramNames = [];
|
|
460
|
+
const splitRegex = isBracket ? BRACKET_PARAM_REGEX : COLON_PARAM_REGEX;
|
|
461
|
+
const parts = routePattern.split(splitRegex);
|
|
462
|
+
const regexParts = [];
|
|
463
|
+
parts.forEach((part, i) => {
|
|
464
|
+
if (i % 2 === 0) {
|
|
465
|
+
regexParts.push(part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
466
|
+
} else {
|
|
467
|
+
paramNames.push(part);
|
|
468
|
+
regexParts.push("([^/]+)");
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
const regex = new RegExp(`^${regexParts.join("")}$`);
|
|
472
|
+
const match = urlPath.match(regex);
|
|
473
|
+
if (!match) return {};
|
|
474
|
+
const result = {};
|
|
475
|
+
paramNames.forEach((name, idx) => {
|
|
476
|
+
result[name] = match[idx + 1];
|
|
477
|
+
});
|
|
478
|
+
return result;
|
|
479
|
+
}
|
|
360
480
|
var bazaarResourceServerExtension = {
|
|
361
481
|
key: BAZAAR.key,
|
|
362
482
|
enrichDeclaration: (declaration, transportContext) => {
|
|
@@ -376,7 +496,7 @@ var bazaarResourceServerExtension = {
|
|
|
376
496
|
enum: [method]
|
|
377
497
|
}
|
|
378
498
|
};
|
|
379
|
-
|
|
499
|
+
const enrichedResult = {
|
|
380
500
|
...extension,
|
|
381
501
|
info: {
|
|
382
502
|
...extension.info || {},
|
|
@@ -400,6 +520,37 @@ var bazaarResourceServerExtension = {
|
|
|
400
520
|
}
|
|
401
521
|
}
|
|
402
522
|
};
|
|
523
|
+
const rawRoutePattern = transportContext.routePattern;
|
|
524
|
+
const routePattern = rawRoutePattern ? normalizeWildcardPattern(rawRoutePattern) : void 0;
|
|
525
|
+
const dynamicRoute = routePattern ? extractDynamicRouteInfo(routePattern, transportContext.adapter.getPath()) : null;
|
|
526
|
+
if (dynamicRoute) {
|
|
527
|
+
const inputSchemaProps = enrichedResult.schema?.properties?.input?.properties || {};
|
|
528
|
+
const hasPathParamsInSchema = "pathParams" in inputSchemaProps;
|
|
529
|
+
return {
|
|
530
|
+
...enrichedResult,
|
|
531
|
+
routeTemplate: dynamicRoute.routeTemplate,
|
|
532
|
+
info: {
|
|
533
|
+
...enrichedResult.info,
|
|
534
|
+
input: { ...enrichedResult.info.input, pathParams: dynamicRoute.pathParams }
|
|
535
|
+
},
|
|
536
|
+
...!hasPathParamsInSchema ? {
|
|
537
|
+
schema: {
|
|
538
|
+
...enrichedResult.schema,
|
|
539
|
+
properties: {
|
|
540
|
+
...enrichedResult.schema?.properties,
|
|
541
|
+
input: {
|
|
542
|
+
...enrichedResult.schema?.properties?.input,
|
|
543
|
+
properties: {
|
|
544
|
+
...inputSchemaProps,
|
|
545
|
+
pathParams: { type: "object" }
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
} : {}
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
return enrichedResult;
|
|
403
554
|
}
|
|
404
555
|
};
|
|
405
556
|
|
|
@@ -521,6 +672,23 @@ function extractResourceMetadataV1(paymentRequirements) {
|
|
|
521
672
|
}
|
|
522
673
|
|
|
523
674
|
// src/bazaar/facilitator.ts
|
|
675
|
+
var ROUTE_TEMPLATE_REGEX = /^\/[a-zA-Z0-9_/:.\-~%]+$/;
|
|
676
|
+
function isValidRouteTemplate(value) {
|
|
677
|
+
if (!value) return false;
|
|
678
|
+
if (!ROUTE_TEMPLATE_REGEX.test(value)) return false;
|
|
679
|
+
let decoded;
|
|
680
|
+
try {
|
|
681
|
+
decoded = decodeURIComponent(value);
|
|
682
|
+
} catch {
|
|
683
|
+
return false;
|
|
684
|
+
}
|
|
685
|
+
if (decoded.includes("..")) return false;
|
|
686
|
+
if (decoded.includes("://")) return false;
|
|
687
|
+
return true;
|
|
688
|
+
}
|
|
689
|
+
function validateRouteTemplate(value) {
|
|
690
|
+
return isValidRouteTemplate(value) ? value : void 0;
|
|
691
|
+
}
|
|
524
692
|
function validateDiscoveryExtension(extension) {
|
|
525
693
|
try {
|
|
526
694
|
const ajv = new import__.default({ strict: false, allErrors: true });
|
|
@@ -546,12 +714,18 @@ function validateDiscoveryExtension(extension) {
|
|
|
546
714
|
function extractDiscoveryInfo(paymentPayload, paymentRequirements, validate = true) {
|
|
547
715
|
let discoveryInfo = null;
|
|
548
716
|
let resourceUrl;
|
|
717
|
+
let routeTemplate;
|
|
549
718
|
if (paymentPayload.x402Version === 2) {
|
|
550
719
|
resourceUrl = paymentPayload.resource?.url ?? "";
|
|
551
720
|
if (paymentPayload.extensions) {
|
|
552
721
|
const bazaarExtension = paymentPayload.extensions[BAZAAR.key];
|
|
553
722
|
if (bazaarExtension && typeof bazaarExtension === "object") {
|
|
554
723
|
try {
|
|
724
|
+
const rawExt = bazaarExtension;
|
|
725
|
+
const rawTemplate = typeof rawExt.routeTemplate === "string" ? rawExt.routeTemplate : void 0;
|
|
726
|
+
if (isValidRouteTemplate(rawTemplate)) {
|
|
727
|
+
routeTemplate = rawTemplate;
|
|
728
|
+
}
|
|
555
729
|
const extension = bazaarExtension;
|
|
556
730
|
if (validate) {
|
|
557
731
|
const result = validateDiscoveryExtension(extension);
|
|
@@ -581,7 +755,7 @@ function extractDiscoveryInfo(paymentPayload, paymentRequirements, validate = tr
|
|
|
581
755
|
return null;
|
|
582
756
|
}
|
|
583
757
|
const url = new URL(resourceUrl);
|
|
584
|
-
const
|
|
758
|
+
const canonicalUrl = routeTemplate ? `${url.origin}${routeTemplate}` : `${url.origin}${url.pathname}`;
|
|
585
759
|
let description;
|
|
586
760
|
let mimeType;
|
|
587
761
|
if (paymentPayload.x402Version === 2) {
|
|
@@ -593,7 +767,7 @@ function extractDiscoveryInfo(paymentPayload, paymentRequirements, validate = tr
|
|
|
593
767
|
mimeType = requirementsV1.mimeType;
|
|
594
768
|
}
|
|
595
769
|
const base = {
|
|
596
|
-
resourceUrl:
|
|
770
|
+
resourceUrl: canonicalUrl,
|
|
597
771
|
description,
|
|
598
772
|
mimeType,
|
|
599
773
|
x402Version: paymentPayload.x402Version,
|
|
@@ -602,7 +776,7 @@ function extractDiscoveryInfo(paymentPayload, paymentRequirements, validate = tr
|
|
|
602
776
|
if (discoveryInfo.input.type === "mcp") {
|
|
603
777
|
return { ...base, toolName: discoveryInfo.input.toolName };
|
|
604
778
|
}
|
|
605
|
-
return { ...base, method: discoveryInfo.input.method };
|
|
779
|
+
return { ...base, routeTemplate, method: discoveryInfo.input.method };
|
|
606
780
|
}
|
|
607
781
|
function extractDiscoveryInfoFromExtension(extension, validate = true) {
|
|
608
782
|
if (validate) {
|
|
@@ -832,7 +1006,6 @@ function declareSIWxExtension(options = {}) {
|
|
|
832
1006
|
}
|
|
833
1007
|
|
|
834
1008
|
// src/sign-in-with-x/server.ts
|
|
835
|
-
var import_crypto = require("crypto");
|
|
836
1009
|
var siwxResourceServerExtension = {
|
|
837
1010
|
key: SIGN_IN_WITH_X,
|
|
838
1011
|
enrichPaymentRequiredResponse: async (declaration, context) => {
|
|
@@ -852,7 +1025,7 @@ var siwxResourceServerExtension = {
|
|
|
852
1025
|
} else {
|
|
853
1026
|
networks = [...new Set(context.requirements.map((r) => r.network))];
|
|
854
1027
|
}
|
|
855
|
-
const nonce = (
|
|
1028
|
+
const nonce = Array.from(globalThis.crypto.getRandomValues(new Uint8Array(16))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
856
1029
|
const issuedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
857
1030
|
const expirationSeconds = opts.expirationSeconds;
|
|
858
1031
|
const expirationTime = expirationSeconds !== void 0 ? new Date(Date.now() + expirationSeconds * 1e3).toISOString() : void 0;
|
|
@@ -1341,7 +1514,7 @@ function createSIWxRequestHook(options) {
|
|
|
1341
1514
|
"SIWxStorage nonce tracking requires both hasUsedNonce and recordNonce to be implemented"
|
|
1342
1515
|
);
|
|
1343
1516
|
}
|
|
1344
|
-
return async (context) => {
|
|
1517
|
+
return async (context, routeConfig) => {
|
|
1345
1518
|
const header = context.adapter.getHeader(SIGN_IN_WITH_X) || context.adapter.getHeader(SIGN_IN_WITH_X.toLowerCase());
|
|
1346
1519
|
if (!header) return;
|
|
1347
1520
|
try {
|
|
@@ -1364,8 +1537,9 @@ function createSIWxRequestHook(options) {
|
|
|
1364
1537
|
return;
|
|
1365
1538
|
}
|
|
1366
1539
|
}
|
|
1367
|
-
const
|
|
1368
|
-
|
|
1540
|
+
const isAuthOnly = Array.isArray(routeConfig?.accepts) && routeConfig.accepts.length === 0;
|
|
1541
|
+
const shouldGrant = isAuthOnly || await storage.hasPaid(context.path, verification.address);
|
|
1542
|
+
if (shouldGrant) {
|
|
1369
1543
|
if (storage.recordNonce) {
|
|
1370
1544
|
await storage.recordNonce(payload.nonce);
|
|
1371
1545
|
}
|
|
@@ -1412,6 +1586,785 @@ function createSIWxClientHook(signer) {
|
|
|
1412
1586
|
};
|
|
1413
1587
|
}
|
|
1414
1588
|
|
|
1589
|
+
// src/offer-receipt/types.ts
|
|
1590
|
+
var OFFER_RECEIPT = "offer-receipt";
|
|
1591
|
+
function isJWSSignedOffer(offer) {
|
|
1592
|
+
return offer.format === "jws";
|
|
1593
|
+
}
|
|
1594
|
+
function isEIP712SignedOffer(offer) {
|
|
1595
|
+
return offer.format === "eip712";
|
|
1596
|
+
}
|
|
1597
|
+
function isJWSSignedReceipt(receipt) {
|
|
1598
|
+
return receipt.format === "jws";
|
|
1599
|
+
}
|
|
1600
|
+
function isEIP712SignedReceipt(receipt) {
|
|
1601
|
+
return receipt.format === "eip712";
|
|
1602
|
+
}
|
|
1603
|
+
function isJWSSigner(signer) {
|
|
1604
|
+
return signer.format === "jws";
|
|
1605
|
+
}
|
|
1606
|
+
function isEIP712Signer(signer) {
|
|
1607
|
+
return signer.format === "eip712";
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
// src/offer-receipt/signing.ts
|
|
1611
|
+
var jose2 = __toESM(require("jose"));
|
|
1612
|
+
var import_viem2 = require("viem");
|
|
1613
|
+
|
|
1614
|
+
// src/offer-receipt/did.ts
|
|
1615
|
+
var jose = __toESM(require("jose"));
|
|
1616
|
+
var import_base2 = require("@scure/base");
|
|
1617
|
+
var import_secp256k1 = require("@noble/curves/secp256k1");
|
|
1618
|
+
var import_nist = require("@noble/curves/nist");
|
|
1619
|
+
var MULTICODEC_ED25519_PUB = 237;
|
|
1620
|
+
var MULTICODEC_SECP256K1_PUB = 231;
|
|
1621
|
+
var MULTICODEC_P256_PUB = 4608;
|
|
1622
|
+
async function extractPublicKeyFromKid(kid) {
|
|
1623
|
+
const [didPart, fragment] = kid.split("#");
|
|
1624
|
+
const parts = didPart.split(":");
|
|
1625
|
+
if (parts.length < 3 || parts[0] !== "did") {
|
|
1626
|
+
throw new Error(`Invalid DID format: ${kid}`);
|
|
1627
|
+
}
|
|
1628
|
+
const method = parts[1];
|
|
1629
|
+
const identifier = parts.slice(2).join(":");
|
|
1630
|
+
switch (method) {
|
|
1631
|
+
case "key":
|
|
1632
|
+
return extractKeyFromDidKey(identifier);
|
|
1633
|
+
case "jwk":
|
|
1634
|
+
return extractKeyFromDidJwk(identifier);
|
|
1635
|
+
case "web":
|
|
1636
|
+
return resolveDidWeb(identifier, fragment);
|
|
1637
|
+
default:
|
|
1638
|
+
throw new Error(
|
|
1639
|
+
`Unsupported DID method "${method}". Supported: did:key, did:jwk, did:web. Provide the public key directly for other methods.`
|
|
1640
|
+
);
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
async function extractKeyFromDidKey(identifier) {
|
|
1644
|
+
if (!identifier.startsWith("z")) {
|
|
1645
|
+
throw new Error(`Unsupported multibase encoding. Expected 'z' (base58-btc).`);
|
|
1646
|
+
}
|
|
1647
|
+
const decoded = import_base2.base58.decode(identifier.slice(1));
|
|
1648
|
+
const { codec, keyBytes } = readMulticodec(decoded);
|
|
1649
|
+
switch (codec) {
|
|
1650
|
+
case MULTICODEC_ED25519_PUB:
|
|
1651
|
+
return importAsymmetricJWK({
|
|
1652
|
+
kty: "OKP",
|
|
1653
|
+
crv: "Ed25519",
|
|
1654
|
+
x: jose.base64url.encode(keyBytes)
|
|
1655
|
+
});
|
|
1656
|
+
case MULTICODEC_SECP256K1_PUB: {
|
|
1657
|
+
const point = import_secp256k1.secp256k1.Point.fromHex(keyBytes);
|
|
1658
|
+
const uncompressed = point.toBytes(false);
|
|
1659
|
+
return importAsymmetricJWK({
|
|
1660
|
+
kty: "EC",
|
|
1661
|
+
crv: "secp256k1",
|
|
1662
|
+
x: jose.base64url.encode(uncompressed.slice(1, 33)),
|
|
1663
|
+
y: jose.base64url.encode(uncompressed.slice(33, 65))
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1666
|
+
case MULTICODEC_P256_PUB: {
|
|
1667
|
+
const point = import_nist.p256.Point.fromHex(keyBytes);
|
|
1668
|
+
const uncompressed = point.toBytes(false);
|
|
1669
|
+
return importAsymmetricJWK({
|
|
1670
|
+
kty: "EC",
|
|
1671
|
+
crv: "P-256",
|
|
1672
|
+
x: jose.base64url.encode(uncompressed.slice(1, 33)),
|
|
1673
|
+
y: jose.base64url.encode(uncompressed.slice(33, 65))
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
default:
|
|
1677
|
+
throw new Error(
|
|
1678
|
+
`Unsupported key type in did:key (multicodec: 0x${codec.toString(16)}). Supported: Ed25519, secp256k1, P-256.`
|
|
1679
|
+
);
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
async function extractKeyFromDidJwk(identifier) {
|
|
1683
|
+
const jwkJson = new TextDecoder().decode(jose.base64url.decode(identifier));
|
|
1684
|
+
const jwk = JSON.parse(jwkJson);
|
|
1685
|
+
return importAsymmetricJWK(jwk);
|
|
1686
|
+
}
|
|
1687
|
+
async function resolveDidWeb(identifier, fragment) {
|
|
1688
|
+
const parts = identifier.split(":");
|
|
1689
|
+
const domain = decodeURIComponent(parts[0]);
|
|
1690
|
+
const path = parts.slice(1).map(decodeURIComponent).join("/");
|
|
1691
|
+
const host = domain.split(":")[0];
|
|
1692
|
+
const scheme = host === "localhost" || host === "127.0.0.1" ? "http" : "https";
|
|
1693
|
+
const url = path ? `${scheme}://${domain}/${path}/did.json` : `${scheme}://${domain}/.well-known/did.json`;
|
|
1694
|
+
let didDocument;
|
|
1695
|
+
try {
|
|
1696
|
+
const response = await fetch(url, {
|
|
1697
|
+
headers: { Accept: "application/did+json, application/json" }
|
|
1698
|
+
});
|
|
1699
|
+
if (!response.ok) {
|
|
1700
|
+
throw new Error(`HTTP ${response.status}`);
|
|
1701
|
+
}
|
|
1702
|
+
didDocument = await response.json();
|
|
1703
|
+
} catch (error) {
|
|
1704
|
+
throw new Error(
|
|
1705
|
+
`Failed to resolve did:web:${identifier}: ${error instanceof Error ? error.message : error}`
|
|
1706
|
+
);
|
|
1707
|
+
}
|
|
1708
|
+
const fullDid = `did:web:${identifier}`;
|
|
1709
|
+
const keyId = fragment ? `${fullDid}#${fragment}` : void 0;
|
|
1710
|
+
const method = findVerificationMethod(didDocument, keyId);
|
|
1711
|
+
if (!method) {
|
|
1712
|
+
throw new Error(`No verification method found for ${keyId || fullDid}`);
|
|
1713
|
+
}
|
|
1714
|
+
if (method.publicKeyJwk) {
|
|
1715
|
+
return importAsymmetricJWK(method.publicKeyJwk);
|
|
1716
|
+
}
|
|
1717
|
+
if (method.publicKeyMultibase) {
|
|
1718
|
+
return extractKeyFromDidKey(method.publicKeyMultibase);
|
|
1719
|
+
}
|
|
1720
|
+
throw new Error(`Verification method ${method.id} has no supported key format`);
|
|
1721
|
+
}
|
|
1722
|
+
function readMulticodec(bytes) {
|
|
1723
|
+
let codec = 0;
|
|
1724
|
+
let shift = 0;
|
|
1725
|
+
let offset = 0;
|
|
1726
|
+
for (const byte of bytes) {
|
|
1727
|
+
codec |= (byte & 127) << shift;
|
|
1728
|
+
offset++;
|
|
1729
|
+
if ((byte & 128) === 0) break;
|
|
1730
|
+
shift += 7;
|
|
1731
|
+
}
|
|
1732
|
+
return { codec, keyBytes: bytes.slice(offset) };
|
|
1733
|
+
}
|
|
1734
|
+
async function importAsymmetricJWK(jwk) {
|
|
1735
|
+
const key = await jose.importJWK(jwk);
|
|
1736
|
+
if (key instanceof Uint8Array) {
|
|
1737
|
+
throw new Error("Symmetric keys are not supported");
|
|
1738
|
+
}
|
|
1739
|
+
return key;
|
|
1740
|
+
}
|
|
1741
|
+
function findVerificationMethod(doc, keyId) {
|
|
1742
|
+
const methods = doc.verificationMethod || [];
|
|
1743
|
+
if (keyId) {
|
|
1744
|
+
return methods.find((m) => m.id === keyId);
|
|
1745
|
+
}
|
|
1746
|
+
for (const ref of doc.assertionMethod || []) {
|
|
1747
|
+
if (typeof ref === "string") {
|
|
1748
|
+
const m = methods.find((m2) => m2.id === ref);
|
|
1749
|
+
if (m) return m;
|
|
1750
|
+
} else {
|
|
1751
|
+
return ref;
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
for (const ref of doc.authentication || []) {
|
|
1755
|
+
if (typeof ref === "string") {
|
|
1756
|
+
const m = methods.find((m2) => m2.id === ref);
|
|
1757
|
+
if (m) return m;
|
|
1758
|
+
} else {
|
|
1759
|
+
return ref;
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
return methods[0];
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
// src/offer-receipt/signing.ts
|
|
1766
|
+
function canonicalize(value) {
|
|
1767
|
+
return serializeValue(value);
|
|
1768
|
+
}
|
|
1769
|
+
function serializeValue(value) {
|
|
1770
|
+
if (value === null) return "null";
|
|
1771
|
+
if (value === void 0) return "null";
|
|
1772
|
+
const type = typeof value;
|
|
1773
|
+
if (type === "boolean") return value ? "true" : "false";
|
|
1774
|
+
if (type === "number") return serializeNumber(value);
|
|
1775
|
+
if (type === "string") return serializeString(value);
|
|
1776
|
+
if (Array.isArray(value)) return serializeArray(value);
|
|
1777
|
+
if (type === "object") return serializeObject(value);
|
|
1778
|
+
throw new Error(`Cannot canonicalize value of type ${type}`);
|
|
1779
|
+
}
|
|
1780
|
+
function serializeNumber(num) {
|
|
1781
|
+
if (!Number.isFinite(num)) throw new Error("Cannot canonicalize Infinity or NaN");
|
|
1782
|
+
if (Object.is(num, -0)) return "0";
|
|
1783
|
+
return String(num);
|
|
1784
|
+
}
|
|
1785
|
+
function serializeString(str) {
|
|
1786
|
+
let result = '"';
|
|
1787
|
+
for (let i = 0; i < str.length; i++) {
|
|
1788
|
+
const char = str[i];
|
|
1789
|
+
const code = str.charCodeAt(i);
|
|
1790
|
+
if (code < 32) {
|
|
1791
|
+
result += "\\u" + code.toString(16).padStart(4, "0");
|
|
1792
|
+
} else if (char === '"') {
|
|
1793
|
+
result += '\\"';
|
|
1794
|
+
} else if (char === "\\") {
|
|
1795
|
+
result += "\\\\";
|
|
1796
|
+
} else {
|
|
1797
|
+
result += char;
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
return result + '"';
|
|
1801
|
+
}
|
|
1802
|
+
function serializeArray(arr) {
|
|
1803
|
+
return "[" + arr.map(serializeValue).join(",") + "]";
|
|
1804
|
+
}
|
|
1805
|
+
function serializeObject(obj) {
|
|
1806
|
+
const keys = Object.keys(obj).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
1807
|
+
const pairs = [];
|
|
1808
|
+
for (const key of keys) {
|
|
1809
|
+
const value = obj[key];
|
|
1810
|
+
if (value !== void 0) {
|
|
1811
|
+
pairs.push(serializeString(key) + ":" + serializeValue(value));
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
return "{" + pairs.join(",") + "}";
|
|
1815
|
+
}
|
|
1816
|
+
async function hashCanonical(obj) {
|
|
1817
|
+
const canonical = canonicalize(obj);
|
|
1818
|
+
const data = new TextEncoder().encode(canonical);
|
|
1819
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
1820
|
+
return new Uint8Array(hashBuffer);
|
|
1821
|
+
}
|
|
1822
|
+
function getCanonicalBytes(obj) {
|
|
1823
|
+
return new TextEncoder().encode(canonicalize(obj));
|
|
1824
|
+
}
|
|
1825
|
+
async function createJWS(payload, signer) {
|
|
1826
|
+
const headerObj = { alg: signer.algorithm, kid: signer.kid };
|
|
1827
|
+
const headerB64 = jose2.base64url.encode(new TextEncoder().encode(JSON.stringify(headerObj)));
|
|
1828
|
+
const canonical = canonicalize(payload);
|
|
1829
|
+
const payloadB64 = jose2.base64url.encode(new TextEncoder().encode(canonical));
|
|
1830
|
+
const signingInput = new TextEncoder().encode(`${headerB64}.${payloadB64}`);
|
|
1831
|
+
const signatureB64 = await signer.sign(signingInput);
|
|
1832
|
+
return `${headerB64}.${payloadB64}.${signatureB64}`;
|
|
1833
|
+
}
|
|
1834
|
+
function extractJWSHeader(jws) {
|
|
1835
|
+
const parts = jws.split(".");
|
|
1836
|
+
if (parts.length !== 3) throw new Error("Invalid JWS format");
|
|
1837
|
+
const headerJson = jose2.base64url.decode(parts[0]);
|
|
1838
|
+
return JSON.parse(new TextDecoder().decode(headerJson));
|
|
1839
|
+
}
|
|
1840
|
+
function extractJWSPayload(jws) {
|
|
1841
|
+
const parts = jws.split(".");
|
|
1842
|
+
if (parts.length !== 3) throw new Error("Invalid JWS format");
|
|
1843
|
+
const payloadJson = jose2.base64url.decode(parts[1]);
|
|
1844
|
+
return JSON.parse(new TextDecoder().decode(payloadJson));
|
|
1845
|
+
}
|
|
1846
|
+
function createOfferDomain() {
|
|
1847
|
+
return { name: "x402 offer", version: "1", chainId: 1 };
|
|
1848
|
+
}
|
|
1849
|
+
function createReceiptDomain() {
|
|
1850
|
+
return { name: "x402 receipt", version: "1", chainId: 1 };
|
|
1851
|
+
}
|
|
1852
|
+
var OFFER_TYPES = {
|
|
1853
|
+
Offer: [
|
|
1854
|
+
{ name: "version", type: "uint256" },
|
|
1855
|
+
{ name: "resourceUrl", type: "string" },
|
|
1856
|
+
{ name: "scheme", type: "string" },
|
|
1857
|
+
{ name: "network", type: "string" },
|
|
1858
|
+
{ name: "asset", type: "string" },
|
|
1859
|
+
{ name: "payTo", type: "string" },
|
|
1860
|
+
{ name: "amount", type: "string" },
|
|
1861
|
+
{ name: "validUntil", type: "uint256" }
|
|
1862
|
+
]
|
|
1863
|
+
};
|
|
1864
|
+
var RECEIPT_TYPES = {
|
|
1865
|
+
Receipt: [
|
|
1866
|
+
{ name: "version", type: "uint256" },
|
|
1867
|
+
{ name: "network", type: "string" },
|
|
1868
|
+
{ name: "resourceUrl", type: "string" },
|
|
1869
|
+
{ name: "payer", type: "string" },
|
|
1870
|
+
{ name: "issuedAt", type: "uint256" },
|
|
1871
|
+
{ name: "transaction", type: "string" }
|
|
1872
|
+
]
|
|
1873
|
+
};
|
|
1874
|
+
function prepareOfferForEIP712(payload) {
|
|
1875
|
+
return {
|
|
1876
|
+
version: BigInt(payload.version),
|
|
1877
|
+
resourceUrl: payload.resourceUrl,
|
|
1878
|
+
scheme: payload.scheme,
|
|
1879
|
+
network: payload.network,
|
|
1880
|
+
asset: payload.asset,
|
|
1881
|
+
payTo: payload.payTo,
|
|
1882
|
+
amount: payload.amount,
|
|
1883
|
+
validUntil: BigInt(payload.validUntil)
|
|
1884
|
+
};
|
|
1885
|
+
}
|
|
1886
|
+
function prepareReceiptForEIP712(payload) {
|
|
1887
|
+
return {
|
|
1888
|
+
version: BigInt(payload.version),
|
|
1889
|
+
network: payload.network,
|
|
1890
|
+
resourceUrl: payload.resourceUrl,
|
|
1891
|
+
payer: payload.payer,
|
|
1892
|
+
issuedAt: BigInt(payload.issuedAt),
|
|
1893
|
+
transaction: payload.transaction
|
|
1894
|
+
};
|
|
1895
|
+
}
|
|
1896
|
+
function hashOfferTypedData(payload) {
|
|
1897
|
+
return (0, import_viem2.hashTypedData)({
|
|
1898
|
+
domain: createOfferDomain(),
|
|
1899
|
+
types: OFFER_TYPES,
|
|
1900
|
+
primaryType: "Offer",
|
|
1901
|
+
message: prepareOfferForEIP712(payload)
|
|
1902
|
+
});
|
|
1903
|
+
}
|
|
1904
|
+
function hashReceiptTypedData(payload) {
|
|
1905
|
+
return (0, import_viem2.hashTypedData)({
|
|
1906
|
+
domain: createReceiptDomain(),
|
|
1907
|
+
types: RECEIPT_TYPES,
|
|
1908
|
+
primaryType: "Receipt",
|
|
1909
|
+
message: prepareReceiptForEIP712(payload)
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
async function signOfferEIP712(payload, signTypedData) {
|
|
1913
|
+
return signTypedData({
|
|
1914
|
+
domain: createOfferDomain(),
|
|
1915
|
+
types: OFFER_TYPES,
|
|
1916
|
+
primaryType: "Offer",
|
|
1917
|
+
message: prepareOfferForEIP712(payload)
|
|
1918
|
+
});
|
|
1919
|
+
}
|
|
1920
|
+
async function signReceiptEIP712(payload, signTypedData) {
|
|
1921
|
+
return signTypedData({
|
|
1922
|
+
domain: createReceiptDomain(),
|
|
1923
|
+
types: RECEIPT_TYPES,
|
|
1924
|
+
primaryType: "Receipt",
|
|
1925
|
+
message: prepareReceiptForEIP712(payload)
|
|
1926
|
+
});
|
|
1927
|
+
}
|
|
1928
|
+
function extractEIP155ChainId(network) {
|
|
1929
|
+
const match = network.match(/^eip155:(\d+)$/);
|
|
1930
|
+
if (!match) {
|
|
1931
|
+
throw new Error(`Invalid network format: ${network}. Expected "eip155:<chainId>"`);
|
|
1932
|
+
}
|
|
1933
|
+
return parseInt(match[1], 10);
|
|
1934
|
+
}
|
|
1935
|
+
var V1_EVM_NETWORK_CHAIN_IDS = {
|
|
1936
|
+
ethereum: 1,
|
|
1937
|
+
sepolia: 11155111,
|
|
1938
|
+
abstract: 2741,
|
|
1939
|
+
"abstract-testnet": 11124,
|
|
1940
|
+
"base-sepolia": 84532,
|
|
1941
|
+
base: 8453,
|
|
1942
|
+
"avalanche-fuji": 43113,
|
|
1943
|
+
avalanche: 43114,
|
|
1944
|
+
iotex: 4689,
|
|
1945
|
+
sei: 1329,
|
|
1946
|
+
"sei-testnet": 1328,
|
|
1947
|
+
polygon: 137,
|
|
1948
|
+
"polygon-amoy": 80002,
|
|
1949
|
+
peaq: 3338,
|
|
1950
|
+
story: 1514,
|
|
1951
|
+
educhain: 41923,
|
|
1952
|
+
"skale-base-sepolia": 324705682
|
|
1953
|
+
};
|
|
1954
|
+
var V1_SOLANA_NETWORKS = {
|
|
1955
|
+
solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
1956
|
+
"solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
|
|
1957
|
+
"solana-testnet": "solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z"
|
|
1958
|
+
};
|
|
1959
|
+
function convertNetworkStringToCAIP2(network) {
|
|
1960
|
+
if (network.includes(":")) return network;
|
|
1961
|
+
const chainId = V1_EVM_NETWORK_CHAIN_IDS[network.toLowerCase()];
|
|
1962
|
+
if (chainId !== void 0) {
|
|
1963
|
+
return `eip155:${chainId}`;
|
|
1964
|
+
}
|
|
1965
|
+
const solanaNetwork = V1_SOLANA_NETWORKS[network.toLowerCase()];
|
|
1966
|
+
if (solanaNetwork) {
|
|
1967
|
+
return solanaNetwork;
|
|
1968
|
+
}
|
|
1969
|
+
throw new Error(
|
|
1970
|
+
`Unknown network identifier: "${network}". Expected CAIP-2 format (e.g., "eip155:8453") or v1 name (e.g., "base", "solana").`
|
|
1971
|
+
);
|
|
1972
|
+
}
|
|
1973
|
+
function extractChainIdFromCAIP2(network) {
|
|
1974
|
+
const [namespace, reference] = network.split(":");
|
|
1975
|
+
if (namespace === "eip155" && reference) {
|
|
1976
|
+
const chainId = parseInt(reference, 10);
|
|
1977
|
+
return isNaN(chainId) ? void 0 : chainId;
|
|
1978
|
+
}
|
|
1979
|
+
return void 0;
|
|
1980
|
+
}
|
|
1981
|
+
var DEFAULT_MAX_TIMEOUT_SECONDS = 300;
|
|
1982
|
+
var EXTENSION_VERSION = 1;
|
|
1983
|
+
function createOfferPayload(resourceUrl, input) {
|
|
1984
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
1985
|
+
const offerValiditySeconds = input.offerValiditySeconds ?? DEFAULT_MAX_TIMEOUT_SECONDS;
|
|
1986
|
+
return {
|
|
1987
|
+
version: EXTENSION_VERSION,
|
|
1988
|
+
resourceUrl,
|
|
1989
|
+
scheme: input.scheme,
|
|
1990
|
+
network: input.network,
|
|
1991
|
+
asset: input.asset,
|
|
1992
|
+
payTo: input.payTo,
|
|
1993
|
+
amount: input.amount,
|
|
1994
|
+
validUntil: now + offerValiditySeconds
|
|
1995
|
+
};
|
|
1996
|
+
}
|
|
1997
|
+
async function createOfferJWS(resourceUrl, input, signer) {
|
|
1998
|
+
const payload = createOfferPayload(resourceUrl, input);
|
|
1999
|
+
const jws = await createJWS(payload, signer);
|
|
2000
|
+
return {
|
|
2001
|
+
format: "jws",
|
|
2002
|
+
acceptIndex: input.acceptIndex,
|
|
2003
|
+
signature: jws
|
|
2004
|
+
};
|
|
2005
|
+
}
|
|
2006
|
+
async function createOfferEIP712(resourceUrl, input, signTypedData) {
|
|
2007
|
+
const payload = createOfferPayload(resourceUrl, input);
|
|
2008
|
+
const signature = await signOfferEIP712(payload, signTypedData);
|
|
2009
|
+
return {
|
|
2010
|
+
format: "eip712",
|
|
2011
|
+
acceptIndex: input.acceptIndex,
|
|
2012
|
+
payload,
|
|
2013
|
+
signature
|
|
2014
|
+
};
|
|
2015
|
+
}
|
|
2016
|
+
function extractOfferPayload(offer) {
|
|
2017
|
+
if (isJWSSignedOffer(offer)) {
|
|
2018
|
+
return extractJWSPayload(offer.signature);
|
|
2019
|
+
} else if (isEIP712SignedOffer(offer)) {
|
|
2020
|
+
return offer.payload;
|
|
2021
|
+
}
|
|
2022
|
+
throw new Error(`Unknown offer format: ${offer.format}`);
|
|
2023
|
+
}
|
|
2024
|
+
function createReceiptPayloadForEIP712(input) {
|
|
2025
|
+
return {
|
|
2026
|
+
version: EXTENSION_VERSION,
|
|
2027
|
+
network: input.network,
|
|
2028
|
+
resourceUrl: input.resourceUrl,
|
|
2029
|
+
payer: input.payer,
|
|
2030
|
+
issuedAt: Math.floor(Date.now() / 1e3),
|
|
2031
|
+
transaction: input.transaction ?? ""
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
function createReceiptPayloadForJWS(input) {
|
|
2035
|
+
const payload = {
|
|
2036
|
+
version: EXTENSION_VERSION,
|
|
2037
|
+
network: input.network,
|
|
2038
|
+
resourceUrl: input.resourceUrl,
|
|
2039
|
+
payer: input.payer,
|
|
2040
|
+
issuedAt: Math.floor(Date.now() / 1e3)
|
|
2041
|
+
};
|
|
2042
|
+
if (input.transaction) {
|
|
2043
|
+
payload.transaction = input.transaction;
|
|
2044
|
+
}
|
|
2045
|
+
return payload;
|
|
2046
|
+
}
|
|
2047
|
+
async function createReceiptJWS(input, signer) {
|
|
2048
|
+
const payload = createReceiptPayloadForJWS(input);
|
|
2049
|
+
const jws = await createJWS(payload, signer);
|
|
2050
|
+
return { format: "jws", signature: jws };
|
|
2051
|
+
}
|
|
2052
|
+
async function createReceiptEIP712(input, signTypedData) {
|
|
2053
|
+
const payload = createReceiptPayloadForEIP712(input);
|
|
2054
|
+
const signature = await signReceiptEIP712(payload, signTypedData);
|
|
2055
|
+
return { format: "eip712", payload, signature };
|
|
2056
|
+
}
|
|
2057
|
+
function extractReceiptPayload(receipt) {
|
|
2058
|
+
if (isJWSSignedReceipt(receipt)) {
|
|
2059
|
+
return extractJWSPayload(receipt.signature);
|
|
2060
|
+
} else if (isEIP712SignedReceipt(receipt)) {
|
|
2061
|
+
return receipt.payload;
|
|
2062
|
+
}
|
|
2063
|
+
throw new Error(`Unknown receipt format: ${receipt.format}`);
|
|
2064
|
+
}
|
|
2065
|
+
async function verifyOfferSignatureEIP712(offer) {
|
|
2066
|
+
if (offer.format !== "eip712") {
|
|
2067
|
+
throw new Error(`Expected eip712 format, got ${offer.format}`);
|
|
2068
|
+
}
|
|
2069
|
+
if (!offer.payload || !("scheme" in offer.payload)) {
|
|
2070
|
+
throw new Error("Invalid offer: missing or malformed payload");
|
|
2071
|
+
}
|
|
2072
|
+
const signer = await (0, import_viem2.recoverTypedDataAddress)({
|
|
2073
|
+
domain: createOfferDomain(),
|
|
2074
|
+
types: OFFER_TYPES,
|
|
2075
|
+
primaryType: "Offer",
|
|
2076
|
+
message: prepareOfferForEIP712(offer.payload),
|
|
2077
|
+
signature: offer.signature
|
|
2078
|
+
});
|
|
2079
|
+
return { signer, payload: offer.payload };
|
|
2080
|
+
}
|
|
2081
|
+
async function verifyReceiptSignatureEIP712(receipt) {
|
|
2082
|
+
if (receipt.format !== "eip712") {
|
|
2083
|
+
throw new Error(`Expected eip712 format, got ${receipt.format}`);
|
|
2084
|
+
}
|
|
2085
|
+
if (!receipt.payload || !("payer" in receipt.payload)) {
|
|
2086
|
+
throw new Error("Invalid receipt: missing or malformed payload");
|
|
2087
|
+
}
|
|
2088
|
+
const signer = await (0, import_viem2.recoverTypedDataAddress)({
|
|
2089
|
+
domain: createReceiptDomain(),
|
|
2090
|
+
types: RECEIPT_TYPES,
|
|
2091
|
+
primaryType: "Receipt",
|
|
2092
|
+
message: prepareReceiptForEIP712(receipt.payload),
|
|
2093
|
+
signature: receipt.signature
|
|
2094
|
+
});
|
|
2095
|
+
return { signer, payload: receipt.payload };
|
|
2096
|
+
}
|
|
2097
|
+
async function verifyOfferSignatureJWS(offer, publicKey) {
|
|
2098
|
+
if (offer.format !== "jws") {
|
|
2099
|
+
throw new Error(`Expected jws format, got ${offer.format}`);
|
|
2100
|
+
}
|
|
2101
|
+
const key = await resolveVerificationKey(offer.signature, publicKey);
|
|
2102
|
+
const { payload } = await jose2.compactVerify(offer.signature, key);
|
|
2103
|
+
return JSON.parse(new TextDecoder().decode(payload));
|
|
2104
|
+
}
|
|
2105
|
+
async function verifyReceiptSignatureJWS(receipt, publicKey) {
|
|
2106
|
+
if (receipt.format !== "jws") {
|
|
2107
|
+
throw new Error(`Expected jws format, got ${receipt.format}`);
|
|
2108
|
+
}
|
|
2109
|
+
const key = await resolveVerificationKey(receipt.signature, publicKey);
|
|
2110
|
+
const { payload } = await jose2.compactVerify(receipt.signature, key);
|
|
2111
|
+
return JSON.parse(new TextDecoder().decode(payload));
|
|
2112
|
+
}
|
|
2113
|
+
async function resolveVerificationKey(jws, providedKey) {
|
|
2114
|
+
if (providedKey) {
|
|
2115
|
+
if ("kty" in providedKey) {
|
|
2116
|
+
const key = await jose2.importJWK(providedKey);
|
|
2117
|
+
if (key instanceof Uint8Array) {
|
|
2118
|
+
throw new Error("Symmetric keys are not supported for JWS verification");
|
|
2119
|
+
}
|
|
2120
|
+
return key;
|
|
2121
|
+
}
|
|
2122
|
+
return providedKey;
|
|
2123
|
+
}
|
|
2124
|
+
const header = extractJWSHeader(jws);
|
|
2125
|
+
if (!header.kid) {
|
|
2126
|
+
throw new Error("No public key provided and JWS header missing kid");
|
|
2127
|
+
}
|
|
2128
|
+
return extractPublicKeyFromKid(header.kid);
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
// src/offer-receipt/server.ts
|
|
2132
|
+
var OFFER_SCHEMA = {
|
|
2133
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
2134
|
+
type: "object",
|
|
2135
|
+
properties: {
|
|
2136
|
+
offers: {
|
|
2137
|
+
type: "array",
|
|
2138
|
+
items: {
|
|
2139
|
+
type: "object",
|
|
2140
|
+
properties: {
|
|
2141
|
+
format: { type: "string" },
|
|
2142
|
+
acceptIndex: { type: "integer" },
|
|
2143
|
+
payload: {
|
|
2144
|
+
type: "object",
|
|
2145
|
+
properties: {
|
|
2146
|
+
version: { type: "integer" },
|
|
2147
|
+
resourceUrl: { type: "string" },
|
|
2148
|
+
scheme: { type: "string" },
|
|
2149
|
+
network: { type: "string" },
|
|
2150
|
+
asset: { type: "string" },
|
|
2151
|
+
payTo: { type: "string" },
|
|
2152
|
+
amount: { type: "string" },
|
|
2153
|
+
validUntil: { type: "integer" }
|
|
2154
|
+
},
|
|
2155
|
+
required: ["version", "resourceUrl", "scheme", "network", "asset", "payTo", "amount"]
|
|
2156
|
+
},
|
|
2157
|
+
signature: { type: "string" }
|
|
2158
|
+
},
|
|
2159
|
+
required: ["format", "signature"]
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
},
|
|
2163
|
+
required: ["offers"]
|
|
2164
|
+
};
|
|
2165
|
+
var RECEIPT_SCHEMA = {
|
|
2166
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
2167
|
+
type: "object",
|
|
2168
|
+
properties: {
|
|
2169
|
+
receipt: {
|
|
2170
|
+
type: "object",
|
|
2171
|
+
properties: {
|
|
2172
|
+
format: { type: "string" },
|
|
2173
|
+
payload: {
|
|
2174
|
+
type: "object",
|
|
2175
|
+
properties: {
|
|
2176
|
+
version: { type: "integer" },
|
|
2177
|
+
network: { type: "string" },
|
|
2178
|
+
resourceUrl: { type: "string" },
|
|
2179
|
+
payer: { type: "string" },
|
|
2180
|
+
issuedAt: { type: "integer" },
|
|
2181
|
+
transaction: { type: "string" }
|
|
2182
|
+
},
|
|
2183
|
+
required: ["version", "network", "resourceUrl", "payer", "issuedAt"]
|
|
2184
|
+
},
|
|
2185
|
+
signature: { type: "string" }
|
|
2186
|
+
},
|
|
2187
|
+
required: ["format", "signature"]
|
|
2188
|
+
}
|
|
2189
|
+
},
|
|
2190
|
+
required: ["receipt"]
|
|
2191
|
+
};
|
|
2192
|
+
function requirementsToOfferInput(requirements, acceptIndex, offerValiditySeconds) {
|
|
2193
|
+
return {
|
|
2194
|
+
acceptIndex,
|
|
2195
|
+
scheme: requirements.scheme,
|
|
2196
|
+
network: requirements.network,
|
|
2197
|
+
asset: requirements.asset,
|
|
2198
|
+
payTo: requirements.payTo,
|
|
2199
|
+
amount: requirements.amount,
|
|
2200
|
+
offerValiditySeconds: offerValiditySeconds ?? requirements.maxTimeoutSeconds
|
|
2201
|
+
};
|
|
2202
|
+
}
|
|
2203
|
+
function createOfferReceiptExtension(issuer) {
|
|
2204
|
+
return {
|
|
2205
|
+
key: OFFER_RECEIPT,
|
|
2206
|
+
// Add signed offers to 402 PaymentRequired response
|
|
2207
|
+
enrichPaymentRequiredResponse: async (declaration, context) => {
|
|
2208
|
+
const config = declaration;
|
|
2209
|
+
const resourceUrl = context.paymentRequiredResponse.resource?.url || context.transportContext?.request?.adapter?.getUrl?.();
|
|
2210
|
+
if (!resourceUrl) {
|
|
2211
|
+
console.warn("[offer-receipt] No resource URL available for signing offers");
|
|
2212
|
+
return void 0;
|
|
2213
|
+
}
|
|
2214
|
+
const offers = [];
|
|
2215
|
+
for (let i = 0; i < context.requirements.length; i++) {
|
|
2216
|
+
const requirement = context.requirements[i];
|
|
2217
|
+
try {
|
|
2218
|
+
const offerInput = requirementsToOfferInput(requirement, i, config?.offerValiditySeconds);
|
|
2219
|
+
const signedOffer = await issuer.issueOffer(resourceUrl, offerInput);
|
|
2220
|
+
offers.push(signedOffer);
|
|
2221
|
+
} catch (error) {
|
|
2222
|
+
console.error(`[offer-receipt] Failed to sign offer for requirement ${i}:`, error);
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
if (offers.length === 0) {
|
|
2226
|
+
return void 0;
|
|
2227
|
+
}
|
|
2228
|
+
return {
|
|
2229
|
+
info: {
|
|
2230
|
+
offers
|
|
2231
|
+
},
|
|
2232
|
+
schema: OFFER_SCHEMA
|
|
2233
|
+
};
|
|
2234
|
+
},
|
|
2235
|
+
// Add signed receipt to settlement response
|
|
2236
|
+
enrichSettlementResponse: async (declaration, context) => {
|
|
2237
|
+
const config = declaration;
|
|
2238
|
+
if (!context.result.success) {
|
|
2239
|
+
return void 0;
|
|
2240
|
+
}
|
|
2241
|
+
const payer = context.result.payer;
|
|
2242
|
+
if (!payer) {
|
|
2243
|
+
console.warn("[offer-receipt] No payer available for signing receipt");
|
|
2244
|
+
return void 0;
|
|
2245
|
+
}
|
|
2246
|
+
const network = context.result.network;
|
|
2247
|
+
if (!network) {
|
|
2248
|
+
console.warn("[offer-receipt] No network available for signing receipt");
|
|
2249
|
+
return void 0;
|
|
2250
|
+
}
|
|
2251
|
+
const transaction = context.result.transaction;
|
|
2252
|
+
const resourceUrl = context.transportContext?.request?.adapter?.getUrl?.();
|
|
2253
|
+
if (!resourceUrl) {
|
|
2254
|
+
console.warn("[offer-receipt] No resource URL available for signing receipt");
|
|
2255
|
+
return void 0;
|
|
2256
|
+
}
|
|
2257
|
+
const includeTxHash = config?.includeTxHash === true;
|
|
2258
|
+
try {
|
|
2259
|
+
const signedReceipt = await issuer.issueReceipt(
|
|
2260
|
+
resourceUrl,
|
|
2261
|
+
payer,
|
|
2262
|
+
network,
|
|
2263
|
+
includeTxHash ? transaction || void 0 : void 0
|
|
2264
|
+
);
|
|
2265
|
+
return {
|
|
2266
|
+
info: {
|
|
2267
|
+
receipt: signedReceipt
|
|
2268
|
+
},
|
|
2269
|
+
schema: RECEIPT_SCHEMA
|
|
2270
|
+
};
|
|
2271
|
+
} catch (error) {
|
|
2272
|
+
console.error("[offer-receipt] Failed to sign receipt:", error);
|
|
2273
|
+
return void 0;
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2278
|
+
function declareOfferReceiptExtension(config) {
|
|
2279
|
+
return {
|
|
2280
|
+
[OFFER_RECEIPT]: {
|
|
2281
|
+
includeTxHash: config?.includeTxHash,
|
|
2282
|
+
offerValiditySeconds: config?.offerValiditySeconds
|
|
2283
|
+
}
|
|
2284
|
+
};
|
|
2285
|
+
}
|
|
2286
|
+
function createJWSOfferReceiptIssuer(kid, jwsSigner) {
|
|
2287
|
+
return {
|
|
2288
|
+
kid,
|
|
2289
|
+
format: "jws",
|
|
2290
|
+
async issueOffer(resourceUrl, input) {
|
|
2291
|
+
return createOfferJWS(resourceUrl, input, jwsSigner);
|
|
2292
|
+
},
|
|
2293
|
+
async issueReceipt(resourceUrl, payer, network, transaction) {
|
|
2294
|
+
return createReceiptJWS({ resourceUrl, payer, network, transaction }, jwsSigner);
|
|
2295
|
+
}
|
|
2296
|
+
};
|
|
2297
|
+
}
|
|
2298
|
+
function createEIP712OfferReceiptIssuer(kid, signTypedData) {
|
|
2299
|
+
return {
|
|
2300
|
+
kid,
|
|
2301
|
+
format: "eip712",
|
|
2302
|
+
async issueOffer(resourceUrl, input) {
|
|
2303
|
+
return createOfferEIP712(resourceUrl, input, signTypedData);
|
|
2304
|
+
},
|
|
2305
|
+
async issueReceipt(resourceUrl, payer, network, transaction) {
|
|
2306
|
+
return createReceiptEIP712({ resourceUrl, payer, network, transaction }, signTypedData);
|
|
2307
|
+
}
|
|
2308
|
+
};
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
// src/offer-receipt/client.ts
|
|
2312
|
+
var import_http2 = require("@x402/core/http");
|
|
2313
|
+
function verifyReceiptMatchesOffer(receipt, offer, payerAddresses, maxAgeSeconds = 3600) {
|
|
2314
|
+
const payload = extractReceiptPayload(receipt);
|
|
2315
|
+
const resourceUrlMatch = payload.resourceUrl === offer.resourceUrl;
|
|
2316
|
+
const networkMatch = payload.network === offer.network;
|
|
2317
|
+
const payerMatch = payerAddresses.some(
|
|
2318
|
+
(addr) => payload.payer.toLowerCase() === addr.toLowerCase()
|
|
2319
|
+
);
|
|
2320
|
+
const issuedRecently = Math.floor(Date.now() / 1e3) - payload.issuedAt < maxAgeSeconds;
|
|
2321
|
+
return resourceUrlMatch && networkMatch && payerMatch && issuedRecently;
|
|
2322
|
+
}
|
|
2323
|
+
function extractOffersFromPaymentRequired(paymentRequired) {
|
|
2324
|
+
const extData = paymentRequired.extensions?.[OFFER_RECEIPT];
|
|
2325
|
+
return extData?.info?.offers ?? [];
|
|
2326
|
+
}
|
|
2327
|
+
function decodeSignedOffers(offers) {
|
|
2328
|
+
return offers.map((offer) => {
|
|
2329
|
+
const payload = extractOfferPayload(offer);
|
|
2330
|
+
return {
|
|
2331
|
+
// Spread payload fields at top level
|
|
2332
|
+
...payload,
|
|
2333
|
+
// Include metadata
|
|
2334
|
+
signedOffer: offer,
|
|
2335
|
+
format: offer.format,
|
|
2336
|
+
acceptIndex: offer.acceptIndex
|
|
2337
|
+
};
|
|
2338
|
+
});
|
|
2339
|
+
}
|
|
2340
|
+
function findAcceptsObjectFromSignedOffer(offer, accepts) {
|
|
2341
|
+
const isDecoded = "signedOffer" in offer;
|
|
2342
|
+
const payload = isDecoded ? offer : extractOfferPayload(offer);
|
|
2343
|
+
const acceptIndex = isDecoded ? offer.acceptIndex : offer.acceptIndex;
|
|
2344
|
+
if (acceptIndex !== void 0 && acceptIndex < accepts.length) {
|
|
2345
|
+
const hinted = accepts[acceptIndex];
|
|
2346
|
+
if (hinted.network === payload.network && hinted.scheme === payload.scheme && hinted.asset === payload.asset && hinted.payTo === payload.payTo && hinted.amount === payload.amount) {
|
|
2347
|
+
return hinted;
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
return accepts.find(
|
|
2351
|
+
(req) => req.network === payload.network && req.scheme === payload.scheme && req.asset === payload.asset && req.payTo === payload.payTo && req.amount === payload.amount
|
|
2352
|
+
);
|
|
2353
|
+
}
|
|
2354
|
+
function extractReceiptFromResponse(response) {
|
|
2355
|
+
const paymentResponseHeader = response.headers.get("PAYMENT-RESPONSE") || response.headers.get("X-PAYMENT-RESPONSE");
|
|
2356
|
+
if (!paymentResponseHeader) {
|
|
2357
|
+
return void 0;
|
|
2358
|
+
}
|
|
2359
|
+
try {
|
|
2360
|
+
const settlementResponse = (0, import_http2.decodePaymentResponseHeader)(paymentResponseHeader);
|
|
2361
|
+
const receiptExtData = settlementResponse.extensions?.[OFFER_RECEIPT];
|
|
2362
|
+
return receiptExtData?.info?.receipt;
|
|
2363
|
+
} catch {
|
|
2364
|
+
return void 0;
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
|
|
1415
2368
|
// src/payment-identifier/types.ts
|
|
1416
2369
|
var PAYMENT_IDENTIFIER = "payment-identifier";
|
|
1417
2370
|
var PAYMENT_ID_MIN_LENGTH = 16;
|
|
@@ -1717,14 +2670,8 @@ var ERC20_APPROVAL_GAS_SPONSORING = {
|
|
|
1717
2670
|
key: "erc20ApprovalGasSponsoring"
|
|
1718
2671
|
};
|
|
1719
2672
|
var ERC20_APPROVAL_GAS_SPONSORING_VERSION = "1";
|
|
1720
|
-
function createErc20ApprovalGasSponsoringExtension(signer,
|
|
1721
|
-
return {
|
|
1722
|
-
...ERC20_APPROVAL_GAS_SPONSORING,
|
|
1723
|
-
signer: {
|
|
1724
|
-
...signer,
|
|
1725
|
-
sendRawTransaction: client.sendRawTransaction.bind(client)
|
|
1726
|
-
}
|
|
1727
|
-
};
|
|
2673
|
+
function createErc20ApprovalGasSponsoringExtension(signer, signerForNetwork) {
|
|
2674
|
+
return { ...ERC20_APPROVAL_GAS_SPONSORING, signer, signerForNetwork };
|
|
1728
2675
|
}
|
|
1729
2676
|
|
|
1730
2677
|
// src/erc20-approval-gas-sponsoring/resourceService.ts
|
|
@@ -1806,10 +2753,13 @@ function validateErc20ApprovalGasSponsoringInfo(info) {
|
|
|
1806
2753
|
ERC20_APPROVAL_GAS_SPONSORING,
|
|
1807
2754
|
ERC20_APPROVAL_GAS_SPONSORING_VERSION,
|
|
1808
2755
|
InMemorySIWxStorage,
|
|
2756
|
+
OFFER_RECEIPT,
|
|
2757
|
+
OFFER_TYPES,
|
|
1809
2758
|
PAYMENT_IDENTIFIER,
|
|
1810
2759
|
PAYMENT_ID_MAX_LENGTH,
|
|
1811
2760
|
PAYMENT_ID_MIN_LENGTH,
|
|
1812
2761
|
PAYMENT_ID_PATTERN,
|
|
2762
|
+
RECEIPT_TYPES,
|
|
1813
2763
|
SIGN_IN_WITH_X,
|
|
1814
2764
|
SIWxPayloadSchema,
|
|
1815
2765
|
SOLANA_DEVNET,
|
|
@@ -1818,7 +2768,19 @@ function validateErc20ApprovalGasSponsoringInfo(info) {
|
|
|
1818
2768
|
appendPaymentIdentifierToExtensions,
|
|
1819
2769
|
bazaarResourceServerExtension,
|
|
1820
2770
|
buildSIWxSchema,
|
|
2771
|
+
canonicalize,
|
|
2772
|
+
convertNetworkStringToCAIP2,
|
|
2773
|
+
createEIP712OfferReceiptIssuer,
|
|
1821
2774
|
createErc20ApprovalGasSponsoringExtension,
|
|
2775
|
+
createJWS,
|
|
2776
|
+
createJWSOfferReceiptIssuer,
|
|
2777
|
+
createOfferDomain,
|
|
2778
|
+
createOfferEIP712,
|
|
2779
|
+
createOfferJWS,
|
|
2780
|
+
createOfferReceiptExtension,
|
|
2781
|
+
createReceiptDomain,
|
|
2782
|
+
createReceiptEIP712,
|
|
2783
|
+
createReceiptJWS,
|
|
1822
2784
|
createSIWxClientHook,
|
|
1823
2785
|
createSIWxMessage,
|
|
1824
2786
|
createSIWxPayload,
|
|
@@ -1827,41 +2789,68 @@ function validateErc20ApprovalGasSponsoringInfo(info) {
|
|
|
1827
2789
|
declareDiscoveryExtension,
|
|
1828
2790
|
declareEip2612GasSponsoringExtension,
|
|
1829
2791
|
declareErc20ApprovalGasSponsoringExtension,
|
|
2792
|
+
declareOfferReceiptExtension,
|
|
1830
2793
|
declarePaymentIdentifierExtension,
|
|
1831
2794
|
declareSIWxExtension,
|
|
1832
2795
|
decodeBase58,
|
|
2796
|
+
decodeSignedOffers,
|
|
1833
2797
|
encodeBase58,
|
|
1834
2798
|
encodeSIWxHeader,
|
|
1835
2799
|
erc20ApprovalGasSponsoringSchema,
|
|
1836
2800
|
extractAndValidatePaymentIdentifier,
|
|
2801
|
+
extractChainIdFromCAIP2,
|
|
1837
2802
|
extractDiscoveryInfo,
|
|
1838
2803
|
extractDiscoveryInfoFromExtension,
|
|
1839
2804
|
extractDiscoveryInfoV1,
|
|
2805
|
+
extractEIP155ChainId,
|
|
1840
2806
|
extractEVMChainId,
|
|
1841
2807
|
extractEip2612GasSponsoringInfo,
|
|
1842
2808
|
extractErc20ApprovalGasSponsoringInfo,
|
|
2809
|
+
extractJWSHeader,
|
|
2810
|
+
extractJWSPayload,
|
|
2811
|
+
extractOfferPayload,
|
|
2812
|
+
extractOffersFromPaymentRequired,
|
|
1843
2813
|
extractPaymentIdentifier,
|
|
2814
|
+
extractPublicKeyFromKid,
|
|
2815
|
+
extractReceiptFromResponse,
|
|
2816
|
+
extractReceiptPayload,
|
|
1844
2817
|
extractResourceMetadataV1,
|
|
1845
2818
|
extractSolanaChainReference,
|
|
2819
|
+
findAcceptsObjectFromSignedOffer,
|
|
1846
2820
|
formatSIWEMessage,
|
|
1847
2821
|
formatSIWSMessage,
|
|
1848
2822
|
generatePaymentId,
|
|
2823
|
+
getCanonicalBytes,
|
|
1849
2824
|
getEVMAddress,
|
|
1850
2825
|
getSolanaAddress,
|
|
1851
2826
|
hasPaymentIdentifier,
|
|
2827
|
+
hashCanonical,
|
|
2828
|
+
hashOfferTypedData,
|
|
2829
|
+
hashReceiptTypedData,
|
|
1852
2830
|
isBodyExtensionConfig,
|
|
1853
2831
|
isDiscoverableV1,
|
|
2832
|
+
isEIP712SignedOffer,
|
|
2833
|
+
isEIP712SignedReceipt,
|
|
2834
|
+
isEIP712Signer,
|
|
1854
2835
|
isEVMSigner,
|
|
2836
|
+
isJWSSignedOffer,
|
|
2837
|
+
isJWSSignedReceipt,
|
|
2838
|
+
isJWSSigner,
|
|
1855
2839
|
isMcpExtensionConfig,
|
|
1856
2840
|
isPaymentIdentifierExtension,
|
|
1857
2841
|
isPaymentIdentifierRequired,
|
|
1858
2842
|
isQueryExtensionConfig,
|
|
1859
2843
|
isSolanaSigner,
|
|
1860
2844
|
isValidPaymentId,
|
|
2845
|
+
isValidRouteTemplate,
|
|
1861
2846
|
parseSIWxHeader,
|
|
1862
2847
|
paymentIdentifierResourceServerExtension,
|
|
1863
2848
|
paymentIdentifierSchema,
|
|
2849
|
+
prepareOfferForEIP712,
|
|
2850
|
+
prepareReceiptForEIP712,
|
|
1864
2851
|
signEVMMessage,
|
|
2852
|
+
signOfferEIP712,
|
|
2853
|
+
signReceiptEIP712,
|
|
1865
2854
|
signSolanaMessage,
|
|
1866
2855
|
siwxResourceServerExtension,
|
|
1867
2856
|
validateAndExtract,
|
|
@@ -1870,8 +2859,14 @@ function validateErc20ApprovalGasSponsoringInfo(info) {
|
|
|
1870
2859
|
validateErc20ApprovalGasSponsoringInfo,
|
|
1871
2860
|
validatePaymentIdentifier,
|
|
1872
2861
|
validatePaymentIdentifierRequirement,
|
|
2862
|
+
validateRouteTemplate,
|
|
1873
2863
|
validateSIWxMessage,
|
|
1874
2864
|
verifyEVMSignature,
|
|
2865
|
+
verifyOfferSignatureEIP712,
|
|
2866
|
+
verifyOfferSignatureJWS,
|
|
2867
|
+
verifyReceiptMatchesOffer,
|
|
2868
|
+
verifyReceiptSignatureEIP712,
|
|
2869
|
+
verifyReceiptSignatureJWS,
|
|
1875
2870
|
verifySIWxSignature,
|
|
1876
2871
|
verifySolanaSignature,
|
|
1877
2872
|
withBazaar,
|