@agenticprimitives/payments 0.0.0-alpha.10

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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -0
  3. package/dist/entitlement/index.d.ts +125 -0
  4. package/dist/entitlement/index.d.ts.map +1 -0
  5. package/dist/entitlement/index.js +128 -0
  6. package/dist/entitlement/index.js.map +1 -0
  7. package/dist/entitlement/voucher.d.ts +85 -0
  8. package/dist/entitlement/voucher.d.ts.map +1 -0
  9. package/dist/entitlement/voucher.js +109 -0
  10. package/dist/entitlement/voucher.js.map +1 -0
  11. package/dist/index.d.ts +135 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +60 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/mandate-sign.d.ts +187 -0
  16. package/dist/mandate-sign.d.ts.map +1 -0
  17. package/dist/mandate-sign.js +177 -0
  18. package/dist/mandate-sign.js.map +1 -0
  19. package/dist/mandate.d.ts +33 -0
  20. package/dist/mandate.d.ts.map +1 -0
  21. package/dist/mandate.js +40 -0
  22. package/dist/mandate.js.map +1 -0
  23. package/dist/ops.d.ts +55 -0
  24. package/dist/ops.d.ts.map +1 -0
  25. package/dist/ops.js +66 -0
  26. package/dist/ops.js.map +1 -0
  27. package/dist/rails/escrow.d.ts +156 -0
  28. package/dist/rails/escrow.d.ts.map +1 -0
  29. package/dist/rails/escrow.js +88 -0
  30. package/dist/rails/escrow.js.map +1 -0
  31. package/dist/rails/invoice.d.ts +65 -0
  32. package/dist/rails/invoice.d.ts.map +1 -0
  33. package/dist/rails/invoice.js +57 -0
  34. package/dist/rails/invoice.js.map +1 -0
  35. package/dist/rails/recurring.d.ts +56 -0
  36. package/dist/rails/recurring.d.ts.map +1 -0
  37. package/dist/rails/recurring.js +58 -0
  38. package/dist/rails/recurring.js.map +1 -0
  39. package/dist/rails/wallet.d.ts +16 -0
  40. package/dist/rails/wallet.d.ts.map +1 -0
  41. package/dist/rails/wallet.js +20 -0
  42. package/dist/rails/wallet.js.map +1 -0
  43. package/dist/rails/x402/executor.d.ts +118 -0
  44. package/dist/rails/x402/executor.d.ts.map +1 -0
  45. package/dist/rails/x402/executor.js +243 -0
  46. package/dist/rails/x402/executor.js.map +1 -0
  47. package/dist/rails/x402/index.d.ts +11 -0
  48. package/dist/rails/x402/index.d.ts.map +1 -0
  49. package/dist/rails/x402/index.js +8 -0
  50. package/dist/rails/x402/index.js.map +1 -0
  51. package/dist/rails/x402/nonce-store.d.ts +30 -0
  52. package/dist/rails/x402/nonce-store.d.ts.map +1 -0
  53. package/dist/rails/x402/nonce-store.js +35 -0
  54. package/dist/rails/x402/nonce-store.js.map +1 -0
  55. package/dist/rails/x402/quote.d.ts +41 -0
  56. package/dist/rails/x402/quote.d.ts.map +1 -0
  57. package/dist/rails/x402/quote.js +84 -0
  58. package/dist/rails/x402/quote.js.map +1 -0
  59. package/dist/rails/x402/resource.d.ts +42 -0
  60. package/dist/rails/x402/resource.d.ts.map +1 -0
  61. package/dist/rails/x402/resource.js +71 -0
  62. package/dist/rails/x402/resource.js.map +1 -0
  63. package/dist/rails/x402/wire.d.ts +81 -0
  64. package/dist/rails/x402/wire.d.ts.map +1 -0
  65. package/dist/rails/x402/wire.js +125 -0
  66. package/dist/rails/x402/wire.js.map +1 -0
  67. package/dist/receipt.d.ts +36 -0
  68. package/dist/receipt.d.ts.map +1 -0
  69. package/dist/receipt.js +50 -0
  70. package/dist/receipt.js.map +1 -0
  71. package/dist/refund.d.ts +29 -0
  72. package/dist/refund.d.ts.map +1 -0
  73. package/dist/refund.js +19 -0
  74. package/dist/refund.js.map +1 -0
  75. package/dist/split.d.ts +27 -0
  76. package/dist/split.d.ts.map +1 -0
  77. package/dist/split.js +33 -0
  78. package/dist/split.js.map +1 -0
  79. package/dist/transfer.d.ts +51 -0
  80. package/dist/transfer.d.ts.map +1 -0
  81. package/dist/transfer.js +54 -0
  82. package/dist/transfer.js.map +1 -0
  83. package/package.json +61 -0
  84. package/spec.md +5 -0
@@ -0,0 +1,41 @@
1
+ import { type Address } from 'viem';
2
+ import type { Hex32, PaymentResource } from './resource.js';
3
+ /** A priced, bound, expiring offer for one access. `quoteId` is derived from the binding so two quotes
4
+ * for the same request+price are identical and a tampered field changes the id (tamper-evident). */
5
+ export interface PaymentQuote {
6
+ quoteId: Hex32;
7
+ scheme: 'exact';
8
+ network: string;
9
+ asset: Address;
10
+ payTo: Address;
11
+ amount: bigint;
12
+ resource: PaymentResource;
13
+ resourceHash: Hex32;
14
+ nonce: bigint;
15
+ expiresAt: number;
16
+ maxTimeoutSeconds: number;
17
+ }
18
+ /** Deterministic quote id over the binding + price + payee + nonce + expiry. Same inputs → same id;
19
+ * any change (amount, payee, resource field, nonce, expiry) → different id (X402-D9 quote immutability). */
20
+ export declare function computeQuoteId(args: {
21
+ resourceHash: Hex32;
22
+ asset: Address;
23
+ payTo: Address;
24
+ amount: bigint;
25
+ network: string;
26
+ nonce: bigint;
27
+ expiresAt: number;
28
+ }): Hex32;
29
+ /** Build a fully-formed, self-consistent PaymentQuote from a resource + price. */
30
+ export declare function buildPaymentQuote(args: {
31
+ resource: PaymentResource;
32
+ network: string;
33
+ maxTimeoutSeconds?: number;
34
+ }): PaymentQuote;
35
+ /** X402-D9 quote immutability: a re-presented quote MUST match the persisted one on every field that
36
+ * prices or binds the charge. Returns the first mismatch (for telemetry) or null when identical. */
37
+ export declare function quoteMismatch(persisted: PaymentQuote, presented: PaymentQuote): string | null;
38
+ /** CAIP-2 helpers (X402-D6 — wire uses `eip155:<id>`, never a bare chain number). */
39
+ export declare function toCaip2(chainId: number): string;
40
+ export declare function fromCaip2(network: string): number;
41
+ //# sourceMappingURL=quote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote.d.ts","sourceRoot":"","sources":["../../../src/rails/x402/quote.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkC,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AACpE,OAAO,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAG5D;qGACqG;AACrG,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,CAAC;IAC1B,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;6GAC6G;AAC7G,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,KAAK,CAuBR;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,QAAQ,EAAE,eAAe,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,GAAG,YAAY,CAyBf;AAED;qGACqG;AACrG,wBAAgB,aAAa,CAAC,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAU7F;AAED,qFAAqF;AACrF,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/C;AACD,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIjD"}
@@ -0,0 +1,84 @@
1
+ // Spec 272 X402-D9.2 — the immutable PaymentQuote. The 402 carries it; the service persists
2
+ // (taskId → quoteId → resourceHash → amount → payee) and a retry MUST match it. No silent re-pricing.
3
+ import { encodeAbiParameters, keccak256 } from 'viem';
4
+ import { canonicalizePaymentResource } from './resource.js';
5
+ /** Deterministic quote id over the binding + price + payee + nonce + expiry. Same inputs → same id;
6
+ * any change (amount, payee, resource field, nonce, expiry) → different id (X402-D9 quote immutability). */
7
+ export function computeQuoteId(args) {
8
+ return keccak256(encodeAbiParameters([
9
+ { type: 'bytes32' },
10
+ { type: 'address' },
11
+ { type: 'address' },
12
+ { type: 'uint256' },
13
+ { type: 'string' },
14
+ { type: 'uint256' },
15
+ { type: 'uint256' },
16
+ ], [
17
+ args.resourceHash,
18
+ args.asset,
19
+ args.payTo,
20
+ args.amount,
21
+ args.network,
22
+ args.nonce,
23
+ BigInt(args.expiresAt),
24
+ ]));
25
+ }
26
+ /** Build a fully-formed, self-consistent PaymentQuote from a resource + price. */
27
+ export function buildPaymentQuote(args) {
28
+ const { resource } = args;
29
+ const resourceHash = canonicalizePaymentResource(resource);
30
+ const quoteId = computeQuoteId({
31
+ resourceHash,
32
+ asset: resource.asset,
33
+ payTo: resource.treasury,
34
+ amount: resource.amount,
35
+ network: args.network,
36
+ nonce: resource.nonce,
37
+ expiresAt: resource.expiresAt,
38
+ });
39
+ return {
40
+ quoteId,
41
+ scheme: 'exact',
42
+ network: args.network,
43
+ asset: resource.asset,
44
+ payTo: resource.treasury,
45
+ amount: resource.amount,
46
+ resource,
47
+ resourceHash,
48
+ nonce: resource.nonce,
49
+ expiresAt: resource.expiresAt,
50
+ maxTimeoutSeconds: args.maxTimeoutSeconds ?? 300,
51
+ };
52
+ }
53
+ /** X402-D9 quote immutability: a re-presented quote MUST match the persisted one on every field that
54
+ * prices or binds the charge. Returns the first mismatch (for telemetry) or null when identical. */
55
+ export function quoteMismatch(persisted, presented) {
56
+ if (persisted.quoteId !== presented.quoteId)
57
+ return 'quoteId';
58
+ if (persisted.resourceHash !== presented.resourceHash)
59
+ return 'resourceHash';
60
+ if (persisted.amount !== presented.amount)
61
+ return 'amount';
62
+ if (persisted.payTo.toLowerCase() !== presented.payTo.toLowerCase())
63
+ return 'payTo';
64
+ if (persisted.asset.toLowerCase() !== presented.asset.toLowerCase())
65
+ return 'asset';
66
+ if (persisted.network !== presented.network)
67
+ return 'network';
68
+ if (persisted.nonce !== presented.nonce)
69
+ return 'nonce';
70
+ if (persisted.expiresAt !== presented.expiresAt)
71
+ return 'expiresAt';
72
+ return null;
73
+ }
74
+ /** CAIP-2 helpers (X402-D6 — wire uses `eip155:<id>`, never a bare chain number). */
75
+ export function toCaip2(chainId) {
76
+ return `eip155:${chainId}`;
77
+ }
78
+ export function fromCaip2(network) {
79
+ const m = /^eip155:(\d+)$/.exec(network);
80
+ if (!m)
81
+ throw new Error(`[x402] unsupported network "${network}" (expected eip155:<chainId>)`);
82
+ return Number(m[1]);
83
+ }
84
+ //# sourceMappingURL=quote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote.js","sourceRoot":"","sources":["../../../src/rails/x402/quote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { type Address } from 'viem';
2
+ export type Hex32 = `0x${string}`;
3
+ export declare const ZERO_HASH: Hex32;
4
+ /** The full set of fields a payment is bound to. Hashing ALL of them (not just amount) closes
5
+ * substitution/replay: a mandate signed for one (method,url,body,skill,treasury,asset,amount,chain,
6
+ * expiry,nonce) cannot be replayed against a different request. */
7
+ export interface PaymentResource {
8
+ protocol: 'http' | 'a2a';
9
+ method: string;
10
+ url: string;
11
+ bodyHash: Hex32;
12
+ serviceAgent: Address;
13
+ treasury: Address;
14
+ skillId: string;
15
+ taskId: Hex32;
16
+ asset: Address;
17
+ amount: bigint;
18
+ chainId: number;
19
+ expiresAt: number;
20
+ nonce: bigint;
21
+ }
22
+ /** keccak256 over an ABI-encoded canonical tuple of every binding field. Deterministic across HTTP +
23
+ * A2A. NOTE: `quoteId` is NOT an input here (it's derived FROM this hash — see quote.ts) to avoid a
24
+ * circular dependency. */
25
+ export declare function canonicalizePaymentResource(r: PaymentResource): Hex32;
26
+ /** keccak256 of a request body (or ZERO_HASH for empty). The ONLY way bodies enter a binding. */
27
+ export declare function hashRequestBody(body: Uint8Array | string | undefined): Hex32;
28
+ /**
29
+ * PAY-WIRE-6 — strip everything that must never leave the trust boundary in payment metadata (402
30
+ * bodies, receipts, on-chain events, accepts[] extras): licensed text, user queries, PII, full
31
+ * sensitive URLs. Returns a safe projection: the path WITHOUT query string + a hash of the full URL.
32
+ * A platform-level guarantee, not per-app discipline.
33
+ */
34
+ export declare function redactPaymentMetadata(input: {
35
+ url?: string;
36
+ description?: string;
37
+ }): {
38
+ safeRoute: string;
39
+ urlHash: Hex32;
40
+ description?: string;
41
+ };
42
+ //# sourceMappingURL=resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../../src/rails/x402/resource.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkC,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpE,MAAM,MAAM,KAAK,GAAG,KAAK,MAAM,EAAE,CAAC;AAClC,eAAO,MAAM,SAAS,EAAE,KAA4E,CAAC;AAErG;;oEAEoE;AACpE,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,KAAK,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;2BAE2B;AAC3B,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,eAAe,GAAG,KAAK,CAmCrE;AAED,iGAAiG;AACjG,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,CAI5E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,KAAK,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAgB9D"}
@@ -0,0 +1,71 @@
1
+ // Spec 272 PAY-WIRE-5/6 — the resource binding (the security-critical object: bind the payment to the
2
+ // EXACT request, not just the amount) + metadata redaction. ONE shared canonicalizer for HTTP + A2A so
3
+ // workers never hand-roll URL/body hashing.
4
+ import { encodeAbiParameters, keccak256 } from 'viem';
5
+ export const ZERO_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000';
6
+ /** keccak256 over an ABI-encoded canonical tuple of every binding field. Deterministic across HTTP +
7
+ * A2A. NOTE: `quoteId` is NOT an input here (it's derived FROM this hash — see quote.ts) to avoid a
8
+ * circular dependency. */
9
+ export function canonicalizePaymentResource(r) {
10
+ return keccak256(encodeAbiParameters([
11
+ { type: 'string' }, // protocol
12
+ { type: 'string' }, // method
13
+ { type: 'string' }, // url
14
+ { type: 'bytes32' }, // bodyHash
15
+ { type: 'address' }, // serviceAgent
16
+ { type: 'address' }, // treasury
17
+ { type: 'string' }, // skillId
18
+ { type: 'bytes32' }, // taskId
19
+ { type: 'address' }, // asset
20
+ { type: 'uint256' }, // amount
21
+ { type: 'uint256' }, // chainId
22
+ { type: 'uint256' }, // expiresAt
23
+ { type: 'uint256' }, // nonce
24
+ ], [
25
+ r.protocol,
26
+ r.method,
27
+ r.url,
28
+ r.bodyHash,
29
+ r.serviceAgent,
30
+ r.treasury,
31
+ r.skillId,
32
+ r.taskId,
33
+ r.asset,
34
+ r.amount,
35
+ BigInt(r.chainId),
36
+ BigInt(r.expiresAt),
37
+ r.nonce,
38
+ ]));
39
+ }
40
+ /** keccak256 of a request body (or ZERO_HASH for empty). The ONLY way bodies enter a binding. */
41
+ export function hashRequestBody(body) {
42
+ if (body === undefined || body.length === 0)
43
+ return ZERO_HASH;
44
+ const bytes = typeof body === 'string' ? new TextEncoder().encode(body) : body;
45
+ return keccak256(bytes);
46
+ }
47
+ /**
48
+ * PAY-WIRE-6 — strip everything that must never leave the trust boundary in payment metadata (402
49
+ * bodies, receipts, on-chain events, accepts[] extras): licensed text, user queries, PII, full
50
+ * sensitive URLs. Returns a safe projection: the path WITHOUT query string + a hash of the full URL.
51
+ * A platform-level guarantee, not per-app discipline.
52
+ */
53
+ export function redactPaymentMetadata(input) {
54
+ let safeRoute = '';
55
+ let urlHash = ZERO_HASH;
56
+ if (input.url) {
57
+ urlHash = keccak256(new TextEncoder().encode(input.url));
58
+ try {
59
+ const u = new URL(input.url);
60
+ safeRoute = `${u.origin}${u.pathname}`; // drop query + fragment (may carry the user's query/content)
61
+ }
62
+ catch {
63
+ safeRoute = '';
64
+ }
65
+ }
66
+ // A description is allowed ONLY if it's a generic label; callers must not pass licensed text. We pass
67
+ // it through verbatim but truncate to discourage smuggling licensed content into "description".
68
+ const description = input.description ? input.description.slice(0, 80) : undefined;
69
+ return { safeRoute, urlHash, description };
70
+ }
71
+ //# sourceMappingURL=resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.js","sourceRoot":"","sources":["../../../src/rails/x402/resource.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { Address } from 'viem';
2
+ import type { PaymentMandate } from '../../index.js';
3
+ import type { Hex32 } from './resource.js';
4
+ import type { PaymentQuote } from './quote.js';
5
+ export declare const X402_VERSION: 2;
6
+ export declare const HEADER_PAYMENT_REQUIRED = "PAYMENT-REQUIRED";
7
+ export declare const HEADER_PAYMENT_SIGNATURE = "PAYMENT-SIGNATURE";
8
+ export declare const HEADER_PAYMENT_RESPONSE = "PAYMENT-RESPONSE";
9
+ export declare const ASSET_TRANSFER_METHOD: "erc7710-delegation";
10
+ /** One x402 `accepts[]` entry — our delegation-native variant of `scheme: 'exact'`. */
11
+ export interface PaymentRequirements {
12
+ scheme: 'exact';
13
+ network: string;
14
+ amount: string;
15
+ asset: Address;
16
+ payTo: Address;
17
+ maxTimeoutSeconds: number;
18
+ resource: {
19
+ route: string;
20
+ description?: string;
21
+ mimeType?: string;
22
+ };
23
+ extra: {
24
+ assetTransferMethod: typeof ASSET_TRANSFER_METHOD;
25
+ quoteId: Hex32;
26
+ mandateTemplate: {
27
+ resourceHash: Hex32;
28
+ nonce: string;
29
+ expiresAt: number;
30
+ };
31
+ };
32
+ }
33
+ export interface PaymentRequiredBody {
34
+ x402Version: typeof X402_VERSION;
35
+ error?: string;
36
+ accepts: PaymentRequirements[];
37
+ }
38
+ export interface SettlementResponse {
39
+ success: boolean;
40
+ settlementHash?: Hex32;
41
+ mandateId?: Hex32;
42
+ network: string;
43
+ payer?: Address;
44
+ error?: string;
45
+ }
46
+ export declare function serializeMandate(m: PaymentMandate): Record<string, unknown>;
47
+ export declare function deserializeMandate(raw: unknown): PaymentMandate;
48
+ export declare function buildPaymentRequired(quote: PaymentQuote, opts?: {
49
+ error?: string;
50
+ description?: string;
51
+ mimeType?: string;
52
+ }): {
53
+ status: 402;
54
+ headers: Record<string, string>;
55
+ body: PaymentRequiredBody;
56
+ };
57
+ /** Client-side: decode a PAYMENT-REQUIRED header back to the body (for tests + the reader's agent). */
58
+ export declare function parsePaymentRequired(headerValue: string): PaymentRequiredBody;
59
+ export interface PaymentSignaturePayload {
60
+ x402Version: typeof X402_VERSION;
61
+ accepted: PaymentRequirements;
62
+ payload: {
63
+ mandate: PaymentMandate;
64
+ };
65
+ }
66
+ /** Build the PAYMENT-SIGNATURE header (client side). */
67
+ export declare function buildPaymentSignature(accepted: PaymentRequirements, mandate: PaymentMandate): Record<string, string>;
68
+ /**
69
+ * Server side: decode + validate the PAYMENT-SIGNATURE header. Fail-closed (returns null) on a missing
70
+ * header, an unknown x402Version, a non-'exact' scheme, or an unsupported assetTransferMethod. NO v1
71
+ * `X-PAYMENT` fallback (ADR-0013).
72
+ */
73
+ export declare function parsePaymentSignature(headers: {
74
+ get?(name: string): string | null;
75
+ } | Record<string, string | undefined>): {
76
+ accepted: PaymentRequirements;
77
+ mandate: PaymentMandate;
78
+ } | null;
79
+ export declare function buildPaymentResponse(r: SettlementResponse): Record<string, string>;
80
+ export declare function parsePaymentResponse(headerValue: string): SettlementResponse;
81
+ //# sourceMappingURL=wire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../../../src/rails/x402/wire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,125 @@
1
+ // Spec 272 PAY-WIRE-1/2/3 — x402 v2 HTTP wire. Headers: PAYMENT-REQUIRED (402) / PAYMENT-SIGNATURE
2
+ // (client→server) / PAYMENT-RESPONSE (server→client), all base64 JSON, CAIP-2 networks, `accepts[]`
3
+ // shape. The v1 `X-PAYMENT` names are dead — we never parse them (ADR-0013: one wire, fail-closed).
4
+ export const X402_VERSION = 2;
5
+ export const HEADER_PAYMENT_REQUIRED = 'PAYMENT-REQUIRED';
6
+ export const HEADER_PAYMENT_SIGNATURE = 'PAYMENT-SIGNATURE';
7
+ export const HEADER_PAYMENT_RESPONSE = 'PAYMENT-RESPONSE';
8
+ export const ASSET_TRANSFER_METHOD = 'erc7710-delegation'; // Wave 1; 'eip3009' is the Wave-5 sibling
9
+ // ── base64 JSON codec (bigint-safe) ──
10
+ function b64encode(obj) {
11
+ const json = JSON.stringify(obj, (_k, v) => (typeof v === 'bigint' ? v.toString() : v));
12
+ return typeof btoa === 'function' ? btoa(json) : Buffer.from(json, 'utf8').toString('base64');
13
+ }
14
+ function b64decode(b64) {
15
+ const json = typeof atob === 'function' ? atob(b64) : Buffer.from(b64, 'base64').toString('utf8');
16
+ return JSON.parse(json);
17
+ }
18
+ // ── PaymentMandate wire (de)serialize — the bigint fields become decimal strings on the wire ──
19
+ export function serializeMandate(m) {
20
+ return JSON.parse(JSON.stringify(m, (_k, v) => (typeof v === 'bigint' ? v.toString() : v)));
21
+ }
22
+ export function deserializeMandate(raw) {
23
+ const o = raw;
24
+ const ap = o.amountPolicy;
25
+ const cb = o.contextBinding;
26
+ const mc = o.mandateConstraints;
27
+ const big = (v) => BigInt(v);
28
+ return {
29
+ ...o,
30
+ nonce: big(o.nonce),
31
+ amountPolicy: {
32
+ ...ap,
33
+ ...(ap.amount !== undefined ? { amount: big(ap.amount) } : {}),
34
+ ...(ap.minAmount !== undefined ? { minAmount: big(ap.minAmount) } : {}),
35
+ ...(ap.maxAmount !== undefined ? { maxAmount: big(ap.maxAmount) } : {}),
36
+ },
37
+ contextBinding: { ...cb, nonce: big(cb.nonce) },
38
+ ...(mc && mc.maxAggregateAmount !== undefined
39
+ ? { mandateConstraints: { ...mc, maxAggregateAmount: big(mc.maxAggregateAmount) } }
40
+ : {}),
41
+ };
42
+ }
43
+ // ── PAY-WIRE-1: build the 402 ──
44
+ export function buildPaymentRequired(quote, opts) {
45
+ const requirements = {
46
+ scheme: 'exact',
47
+ network: quote.network,
48
+ amount: quote.amount.toString(),
49
+ asset: quote.asset,
50
+ payTo: quote.payTo,
51
+ maxTimeoutSeconds: quote.maxTimeoutSeconds,
52
+ // safe route only (no query string) — PAY-WIRE-6
53
+ resource: { route: safeRoute(quote.resource.url), description: opts?.description, mimeType: opts?.mimeType },
54
+ extra: {
55
+ assetTransferMethod: ASSET_TRANSFER_METHOD,
56
+ quoteId: quote.quoteId,
57
+ mandateTemplate: { resourceHash: quote.resourceHash, nonce: quote.nonce.toString(), expiresAt: quote.expiresAt },
58
+ },
59
+ };
60
+ const body = { x402Version: X402_VERSION, error: opts?.error, accepts: [requirements] };
61
+ return { status: 402, headers: { [HEADER_PAYMENT_REQUIRED]: b64encode(body) }, body };
62
+ }
63
+ /** Client-side: decode a PAYMENT-REQUIRED header back to the body (for tests + the reader's agent). */
64
+ export function parsePaymentRequired(headerValue) {
65
+ const body = b64decode(headerValue);
66
+ if (body.x402Version !== X402_VERSION)
67
+ throw new Error(`[x402] unsupported x402Version ${body.x402Version}`);
68
+ return body;
69
+ }
70
+ /** Build the PAYMENT-SIGNATURE header (client side). */
71
+ export function buildPaymentSignature(accepted, mandate) {
72
+ const body = { x402Version: X402_VERSION, accepted, payload: { mandate: serializeMandate(mandate) } };
73
+ return { [HEADER_PAYMENT_SIGNATURE]: b64encode(body) };
74
+ }
75
+ /**
76
+ * Server side: decode + validate the PAYMENT-SIGNATURE header. Fail-closed (returns null) on a missing
77
+ * header, an unknown x402Version, a non-'exact' scheme, or an unsupported assetTransferMethod. NO v1
78
+ * `X-PAYMENT` fallback (ADR-0013).
79
+ */
80
+ export function parsePaymentSignature(headers) {
81
+ const raw = headerValue(headers, HEADER_PAYMENT_SIGNATURE);
82
+ if (!raw)
83
+ return null;
84
+ let body;
85
+ try {
86
+ body = b64decode(raw);
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ if (body.x402Version !== X402_VERSION)
92
+ return null;
93
+ if (body.accepted?.scheme !== 'exact')
94
+ return null;
95
+ if (body.accepted?.extra?.assetTransferMethod !== ASSET_TRANSFER_METHOD)
96
+ return null;
97
+ if (!body.payload?.mandate)
98
+ return null;
99
+ return { accepted: body.accepted, mandate: deserializeMandate(body.payload.mandate) };
100
+ }
101
+ // ── PAY-WIRE-3: build the settlement response (a projection of the durable receipt) ──
102
+ export function buildPaymentResponse(r) {
103
+ return { [HEADER_PAYMENT_RESPONSE]: b64encode(r) };
104
+ }
105
+ export function parsePaymentResponse(headerValue) {
106
+ return b64decode(headerValue);
107
+ }
108
+ // ── helpers ──
109
+ function headerValue(headers, name) {
110
+ if (typeof headers.get === 'function') {
111
+ return headers.get(name) ?? undefined;
112
+ }
113
+ const rec = headers;
114
+ return rec[name] ?? rec[name.toLowerCase()];
115
+ }
116
+ function safeRoute(url) {
117
+ try {
118
+ const u = new URL(url);
119
+ return `${u.origin}${u.pathname}`;
120
+ }
121
+ catch {
122
+ return '';
123
+ }
124
+ }
125
+ //# sourceMappingURL=wire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire.js","sourceRoot":"","sources":["../../../src/rails/x402/wire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * X402-D9.3 / spec 243 §7 — PaymentReceipt verifiable credential.
3
+ *
4
+ * Every successful redemption (charge, refund, split-out, escrow release) produces
5
+ * an immutable `PaymentReceipt` VC (PMT-INV-11 — no revoke entrypoint; settlement is
6
+ * final). The receipt is evidence-symmetric (273 EXC-D3): a refund leg is the same
7
+ * shape as the charge it reverses, linked by `provenance.refunds`.
8
+ *
9
+ * This builds the UNSIGNED credential (vc envelope is type-only here per the package
10
+ * boundary); the app/rail signs it via `@agenticprimitives/verifiable-credentials`
11
+ * `signCredential` and asserts it via the `attestations` client.
12
+ */
13
+ import type { UnsignedCredential } from '@agenticprimitives/verifiable-credentials';
14
+ import type { Address } from '@agenticprimitives/types';
15
+ import type { PaymentMandate, Hex32 } from './index.js';
16
+ export declare const PAYMENT_RECEIPT_TYPE = "PaymentReceipt";
17
+ /** Coarsen a settlement time to a UTC-day bucket — receipts leak no finer timing (privacy posture §6). */
18
+ export declare function settlementEpochBucket(settledAtSeconds: number): number;
19
+ export interface PaymentReceiptInput {
20
+ /** the settled mandate */
21
+ mandate: PaymentMandate;
22
+ /** the rail executor's SA (VC issuer) */
23
+ issuer: Address;
24
+ /** tx hash, or off-chain settlement id */
25
+ settlementHash: Hex32;
26
+ /** ISO-8601 settlement time */
27
+ settledAt: string;
28
+ /** provenance — set on a refund leg to the original charge's mandateId (EXC-D3) */
29
+ refundsMandateId?: Hex32;
30
+ }
31
+ /**
32
+ * Build the unsigned `PaymentReceipt` credential. The subject id is the payer SA; the
33
+ * full context binding is folded into `contextBindingHash` (never the body — privacy §6).
34
+ */
35
+ export declare function buildPaymentReceiptCredential(input: PaymentReceiptInput): UnsignedCredential;
36
+ //# sourceMappingURL=receipt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../src/receipt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AACpF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAExD,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExD,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AAGrD,0GAA0G;AAC1G,wBAAgB,qBAAqB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,MAAM,WAAW,mBAAmB;IAClC,0BAA0B;IAC1B,OAAO,EAAE,cAAc,CAAC;IACxB,yCAAyC;IACzC,MAAM,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,cAAc,EAAE,KAAK,CAAC;IACtB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,KAAK,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,mBAAmB,GAAG,kBAAkB,CAyB5F"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * X402-D9.3 / spec 243 §7 — PaymentReceipt verifiable credential.
3
+ *
4
+ * Every successful redemption (charge, refund, split-out, escrow release) produces
5
+ * an immutable `PaymentReceipt` VC (PMT-INV-11 — no revoke entrypoint; settlement is
6
+ * final). The receipt is evidence-symmetric (273 EXC-D3): a refund leg is the same
7
+ * shape as the charge it reverses, linked by `provenance.refunds`.
8
+ *
9
+ * This builds the UNSIGNED credential (vc envelope is type-only here per the package
10
+ * boundary); the app/rail signs it via `@agenticprimitives/verifiable-credentials`
11
+ * `signCredential` and asserts it via the `attestations` client.
12
+ */
13
+ import { hashContextBinding, mandateAmount } from './mandate-sign.js';
14
+ export const PAYMENT_RECEIPT_TYPE = 'PaymentReceipt';
15
+ const CREDENTIALS_V2_CONTEXT = 'https://www.w3.org/ns/credentials/v2';
16
+ /** Coarsen a settlement time to a UTC-day bucket — receipts leak no finer timing (privacy posture §6). */
17
+ export function settlementEpochBucket(settledAtSeconds) {
18
+ return Math.floor(settledAtSeconds / 86_400);
19
+ }
20
+ /**
21
+ * Build the unsigned `PaymentReceipt` credential. The subject id is the payer SA; the
22
+ * full context binding is folded into `contextBindingHash` (never the body — privacy §6).
23
+ */
24
+ export function buildPaymentReceiptCredential(input) {
25
+ const { mandate } = input;
26
+ const settledSeconds = Math.floor(Date.parse(input.settledAt) / 1000);
27
+ const credential = {
28
+ '@context': [CREDENTIALS_V2_CONTEXT],
29
+ type: ['VerifiableCredential', PAYMENT_RECEIPT_TYPE],
30
+ issuer: input.issuer,
31
+ validFrom: input.settledAt,
32
+ credentialSubject: {
33
+ id: mandate.payer,
34
+ mandateId: mandate.mandateId,
35
+ rail: mandate.rail,
36
+ payee: mandate.payee,
37
+ amount: mandateAmount(mandate).toString(),
38
+ asset: mandate.amountPolicy.asset.id,
39
+ chain: mandate.contextBinding.chain,
40
+ orderHash: mandate.contextBinding.orderHash ?? null,
41
+ legId: mandate.contextBinding.legId ?? null,
42
+ contextBindingHash: hashContextBinding(mandate.contextBinding),
43
+ settlementHash: input.settlementHash,
44
+ settlementEpochBucket: settlementEpochBucket(settledSeconds),
45
+ ...(input.refundsMandateId ? { provenance: { refunds: input.refundsMandateId } } : {}),
46
+ },
47
+ };
48
+ return credential;
49
+ }
50
+ //# sourceMappingURL=receipt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt.js","sourceRoot":"","sources":["../src/receipt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGtE,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AACrD,MAAM,sBAAsB,GAAG,sCAAsC,CAAC;AAEtE,0GAA0G;AAC1G,MAAM,UAAU,qBAAqB,CAAC,gBAAwB;IAC5D,OAAO,IAAI,CAAC,KAAK,CAAC,gBAAgB,GAAG,MAAM,CAAC,CAAC;AAC/C,CAAC;AAeD;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAAC,KAA0B;IACtE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAC1B,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IACtE,MAAM,UAAU,GAAG;QACjB,UAAU,EAAE,CAAC,sBAAsB,CAAC;QACpC,IAAI,EAAE,CAAC,sBAAsB,EAAE,oBAAoB,CAAC;QACpD,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,iBAAiB,EAAE;YACjB,EAAE,EAAE,OAAO,CAAC,KAAK;YACjB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE;YACzC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;YACpC,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,KAAK;YACnC,SAAS,EAAE,OAAO,CAAC,cAAc,CAAC,SAAS,IAAI,IAAI;YACnD,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,KAAK,IAAI,IAAI;YAC3C,kBAAkB,EAAE,kBAAkB,CAAC,OAAO,CAAC,cAAc,CAAC;YAC9D,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,qBAAqB,EAAE,qBAAqB,CAAC,cAAc,CAAC;YAC5D,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvF;KACF,CAAC;IACF,OAAO,UAA2C,CAAC;AACrD,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Refunds (spec 243 §5.5) — a receipt-linked reverse leg, no enforcer.
3
+ *
4
+ * The treasury (payee) signs a transfer payee → payer carrying `provenance.refunds`
5
+ * pointing at the original charge's mandateId. It emits its OWN PaymentReceipt
6
+ * (audit-equal evidence, 273 EXC-D3). Build the refund receipt with
7
+ * `buildPaymentReceiptCredential({ ..., refundsMandateId })`.
8
+ */
9
+ import type { Address } from '@agenticprimitives/types';
10
+ import { type TransferPlan } from './transfer.js';
11
+ import type { Hex32 } from './index.js';
12
+ export interface RefundInput {
13
+ asset: Address;
14
+ /** refund amount — MUST be ≤ the original charge (caller-enforced) */
15
+ amount: bigint;
16
+ /** where the refund returns — the original charge's payer */
17
+ payer: Address;
18
+ /** the original charge this reverses (provenance) */
19
+ originalMandateId: Hex32;
20
+ }
21
+ export interface RefundPlan {
22
+ plan: TransferPlan;
23
+ provenance: {
24
+ refunds: Hex32;
25
+ };
26
+ }
27
+ /** Build the reverse leg: the treasury executes a transfer back to the original payer. */
28
+ export declare function buildRefund(input: RefundInput): RefundPlan;
29
+ //# sourceMappingURL=refund.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refund.d.ts","sourceRoot":"","sources":["../src/refund.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,KAAK,EAAE,OAAO,CAAC;IACf,qDAAqD;IACrD,iBAAiB,EAAE,KAAK,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,EAAE;QAAE,OAAO,EAAE,KAAK,CAAA;KAAE,CAAC;CAChC;AAED,0FAA0F;AAC1F,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,CAM1D"}
package/dist/refund.js ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Refunds (spec 243 §5.5) — a receipt-linked reverse leg, no enforcer.
3
+ *
4
+ * The treasury (payee) signs a transfer payee → payer carrying `provenance.refunds`
5
+ * pointing at the original charge's mandateId. It emits its OWN PaymentReceipt
6
+ * (audit-equal evidence, 273 EXC-D3). Build the refund receipt with
7
+ * `buildPaymentReceiptCredential({ ..., refundsMandateId })`.
8
+ */
9
+ import { buildErc20Transfer } from './transfer.js';
10
+ /** Build the reverse leg: the treasury executes a transfer back to the original payer. */
11
+ export function buildRefund(input) {
12
+ if (input.amount <= 0n)
13
+ throw new Error('[refund] amount must be > 0');
14
+ return {
15
+ plan: buildErc20Transfer(input.asset, input.payer, input.amount),
16
+ provenance: { refunds: input.originalMandateId },
17
+ };
18
+ }
19
+ //# sourceMappingURL=refund.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refund.js","sourceRoot":"","sources":["../src/refund.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,kBAAkB,EAAqB,MAAM,eAAe,CAAC;AAkBtE,0FAA0F;AAC1F,MAAM,UAAU,WAAW,CAAC,KAAkB;IAC5C,IAAI,KAAK,CAAC,MAAM,IAAI,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACvE,OAAO;QACL,IAAI,EAAE,kBAAkB,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;QAChE,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,iBAAiB,EAAE;KACjD,CAAC;AACJ,CAAC"}