warpmetal 0.7.8 → 0.7.9
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 +6 -0
- package/package.json +1 -1
- package/src/payment.js +42 -0
package/README.md
CHANGED
|
@@ -124,6 +124,12 @@ treasury; the merchant tenant's active allowance controls sponsorship
|
|
|
124
124
|
admission but is not charged actual gas. Payment authority depends on execution
|
|
125
125
|
context:
|
|
126
126
|
|
|
127
|
+
WarpMetal can advertise any currently executable subset of those rails, from a
|
|
128
|
+
single alternative through all three. Agent Kit requires the sponsorship and
|
|
129
|
+
external-recipient extension bindings to match the advertised alternatives
|
|
130
|
+
exactly, then preserves the chosen authorization artifact byte-for-byte for
|
|
131
|
+
every pending or ambiguous retry.
|
|
132
|
+
|
|
127
133
|
- When a human is actively chatting with the agent, show the exact live terms
|
|
128
134
|
and ask for confirmation immediately before authorizing and submitting.
|
|
129
135
|
- In an unattended run, a pre-funded dedicated wallet is standing spend
|
package/package.json
CHANGED
package/src/payment.js
CHANGED
|
@@ -338,6 +338,47 @@ function externalRecipientBinds(requirement, extensions) {
|
|
|
338
338
|
return matches.length === 1;
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
+
function exactExtensionBindings(accepts, sponsorship, extensions) {
|
|
342
|
+
if (!sponsorship) return;
|
|
343
|
+
const sponsoredAccepts = new Set(
|
|
344
|
+
accepts.map(
|
|
345
|
+
(requirement) =>
|
|
346
|
+
`${requirement.network}|${requirement.asset.toLowerCase()}|${requirement.extra.payloadProfile}`,
|
|
347
|
+
),
|
|
348
|
+
);
|
|
349
|
+
const sponsorshipBindings = new Set(
|
|
350
|
+
sponsorship.requirements.map(
|
|
351
|
+
(binding) =>
|
|
352
|
+
`${binding.network}|${binding.asset.toLowerCase()}|${binding.payloadProfile}`,
|
|
353
|
+
),
|
|
354
|
+
);
|
|
355
|
+
const recipients = extensions["com.k1hub.external-recipient"]?.info?.recipients;
|
|
356
|
+
const acceptedRecipients = new Set(
|
|
357
|
+
accepts.map(
|
|
358
|
+
(requirement) =>
|
|
359
|
+
`${requirement.network}|${requirement.asset}|${requirement.payTo}`,
|
|
360
|
+
),
|
|
361
|
+
);
|
|
362
|
+
const recipientBindings = new Set(
|
|
363
|
+
Array.isArray(recipients)
|
|
364
|
+
? recipients.map(
|
|
365
|
+
(recipient) =>
|
|
366
|
+
`${recipient.network}|${recipient.asset}|${recipient.payTo}`,
|
|
367
|
+
)
|
|
368
|
+
: [],
|
|
369
|
+
);
|
|
370
|
+
if (
|
|
371
|
+
sponsoredAccepts.size !== sponsorshipBindings.size ||
|
|
372
|
+
[...sponsoredAccepts].some((identity) => !sponsorshipBindings.has(identity)) ||
|
|
373
|
+
acceptedRecipients.size !== recipientBindings.size ||
|
|
374
|
+
[...acceptedRecipients].some((identity) => !recipientBindings.has(identity))
|
|
375
|
+
) {
|
|
376
|
+
throw invalid(
|
|
377
|
+
"The x402 sponsorship and recipient bindings do not exactly match PAYMENT-REQUIRED.",
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
341
382
|
function agentWalletSupports(requirement, sponsorship, extensions) {
|
|
342
383
|
const profile = requirement.extra.payloadProfile;
|
|
343
384
|
const baseExtra = Object.keys(requirement.extra).sort().join(",");
|
|
@@ -397,6 +438,7 @@ export function parsePaymentRequired(value, expectedUrl) {
|
|
|
397
438
|
"The x402 challenge extension",
|
|
398
439
|
);
|
|
399
440
|
const sponsorship = extensions[GAS_SPONSORSHIP_EXTENSION]?.info;
|
|
441
|
+
exactExtensionBindings(accepts, sponsorship, extensions);
|
|
400
442
|
return {
|
|
401
443
|
challenge: parsed,
|
|
402
444
|
paymentRequiredDigest: digestJson(parsed),
|