@agenticprimitives/payments 0.0.0-alpha.3 → 0.0.0-alpha.5

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 (81) hide show
  1. package/dist/entitlement/index.d.ts +92 -0
  2. package/dist/entitlement/index.d.ts.map +1 -0
  3. package/dist/entitlement/index.js +93 -0
  4. package/dist/entitlement/index.js.map +1 -0
  5. package/dist/entitlement/voucher.d.ts +78 -0
  6. package/dist/entitlement/voucher.d.ts.map +1 -0
  7. package/dist/entitlement/voucher.js +102 -0
  8. package/dist/entitlement/voucher.js.map +1 -0
  9. package/dist/index.d.ts +23 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +20 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/mandate-sign.d.ts +173 -0
  14. package/dist/mandate-sign.d.ts.map +1 -0
  15. package/dist/mandate-sign.js +147 -0
  16. package/dist/mandate-sign.js.map +1 -0
  17. package/dist/mandate.d.ts +33 -0
  18. package/dist/mandate.d.ts.map +1 -0
  19. package/dist/mandate.js +40 -0
  20. package/dist/mandate.js.map +1 -0
  21. package/dist/ops.d.ts +55 -0
  22. package/dist/ops.d.ts.map +1 -0
  23. package/dist/ops.js +66 -0
  24. package/dist/ops.js.map +1 -0
  25. package/dist/rails/escrow.d.ts +143 -0
  26. package/dist/rails/escrow.d.ts.map +1 -0
  27. package/dist/rails/escrow.js +90 -0
  28. package/dist/rails/escrow.js.map +1 -0
  29. package/dist/rails/invoice.d.ts +65 -0
  30. package/dist/rails/invoice.d.ts.map +1 -0
  31. package/dist/rails/invoice.js +57 -0
  32. package/dist/rails/invoice.js.map +1 -0
  33. package/dist/rails/recurring.d.ts +56 -0
  34. package/dist/rails/recurring.d.ts.map +1 -0
  35. package/dist/rails/recurring.js +58 -0
  36. package/dist/rails/recurring.js.map +1 -0
  37. package/dist/rails/wallet.d.ts +16 -0
  38. package/dist/rails/wallet.d.ts.map +1 -0
  39. package/dist/rails/wallet.js +20 -0
  40. package/dist/rails/wallet.js.map +1 -0
  41. package/dist/rails/x402/executor.d.ts +109 -0
  42. package/dist/rails/x402/executor.d.ts.map +1 -0
  43. package/dist/rails/x402/executor.js +222 -0
  44. package/dist/rails/x402/executor.js.map +1 -0
  45. package/dist/rails/x402/index.d.ts +11 -0
  46. package/dist/rails/x402/index.d.ts.map +1 -0
  47. package/dist/rails/x402/index.js +8 -0
  48. package/dist/rails/x402/index.js.map +1 -0
  49. package/dist/rails/x402/nonce-store.d.ts +30 -0
  50. package/dist/rails/x402/nonce-store.d.ts.map +1 -0
  51. package/dist/rails/x402/nonce-store.js +35 -0
  52. package/dist/rails/x402/nonce-store.js.map +1 -0
  53. package/dist/rails/x402/quote.d.ts +41 -0
  54. package/dist/rails/x402/quote.d.ts.map +1 -0
  55. package/dist/rails/x402/quote.js +84 -0
  56. package/dist/rails/x402/quote.js.map +1 -0
  57. package/dist/rails/x402/resource.d.ts +42 -0
  58. package/dist/rails/x402/resource.d.ts.map +1 -0
  59. package/dist/rails/x402/resource.js +71 -0
  60. package/dist/rails/x402/resource.js.map +1 -0
  61. package/dist/rails/x402/wire.d.ts +81 -0
  62. package/dist/rails/x402/wire.d.ts.map +1 -0
  63. package/dist/rails/x402/wire.js +125 -0
  64. package/dist/rails/x402/wire.js.map +1 -0
  65. package/dist/receipt.d.ts +36 -0
  66. package/dist/receipt.d.ts.map +1 -0
  67. package/dist/receipt.js +50 -0
  68. package/dist/receipt.js.map +1 -0
  69. package/dist/refund.d.ts +29 -0
  70. package/dist/refund.d.ts.map +1 -0
  71. package/dist/refund.js +19 -0
  72. package/dist/refund.js.map +1 -0
  73. package/dist/split.d.ts +27 -0
  74. package/dist/split.d.ts.map +1 -0
  75. package/dist/split.js +33 -0
  76. package/dist/split.js.map +1 -0
  77. package/dist/transfer.d.ts +51 -0
  78. package/dist/transfer.d.ts.map +1 -0
  79. package/dist/transfer.js +54 -0
  80. package/dist/transfer.js.map +1 -0
  81. package/package.json +6 -5
@@ -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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Split payouts (spec 243 §5.5) — app-triggered payout fan-out.
3
+ *
4
+ * One amount split to N recipients by basis points (Seaport recipient-specific-consideration
5
+ * pattern). `bps` MUST sum to 10000; the rounding remainder is assigned to the first recipient
6
+ * so the legs total EXACTLY `amount` (no dust left in the treasury). Each leg is its own
7
+ * transfer plan (and its own receipt). Connected-account onboarding / KYB stays app layer.
8
+ */
9
+ import type { Address } from '@agenticprimitives/types';
10
+ import { type TransferPlan } from './transfer.js';
11
+ export interface SplitRecipient {
12
+ to: Address;
13
+ bps: number;
14
+ }
15
+ export interface SplitLeg {
16
+ to: Address;
17
+ bps: number;
18
+ amount: bigint;
19
+ plan: TransferPlan;
20
+ }
21
+ export declare const BPS_DENOMINATOR = 10000;
22
+ export declare function buildSplitPayout(input: {
23
+ asset: Address;
24
+ amount: bigint;
25
+ recipients: SplitRecipient[];
26
+ }): SplitLeg[];
27
+ //# sourceMappingURL=split.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split.d.ts","sourceRoot":"","sources":["../src/split.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEtE,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,OAAO,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,eAAO,MAAM,eAAe,QAAS,CAAC;AAEtC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,cAAc,EAAE,CAAA;CAAE,GAAG,QAAQ,EAAE,CAkBpH"}
package/dist/split.js ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Split payouts (spec 243 §5.5) — app-triggered payout fan-out.
3
+ *
4
+ * One amount split to N recipients by basis points (Seaport recipient-specific-consideration
5
+ * pattern). `bps` MUST sum to 10000; the rounding remainder is assigned to the first recipient
6
+ * so the legs total EXACTLY `amount` (no dust left in the treasury). Each leg is its own
7
+ * transfer plan (and its own receipt). Connected-account onboarding / KYB stays app layer.
8
+ */
9
+ import { buildErc20Transfer } from './transfer.js';
10
+ export const BPS_DENOMINATOR = 10_000;
11
+ export function buildSplitPayout(input) {
12
+ const { asset, amount, recipients } = input;
13
+ if (recipients.length === 0)
14
+ throw new Error('[split] at least one recipient required');
15
+ if (amount <= 0n)
16
+ throw new Error('[split] amount must be > 0');
17
+ const totalBps = recipients.reduce((s, r) => s + r.bps, 0);
18
+ if (totalBps !== BPS_DENOMINATOR)
19
+ throw new Error(`[split] bps must sum to ${BPS_DENOMINATOR}, got ${totalBps}`);
20
+ for (const r of recipients)
21
+ if (r.bps <= 0)
22
+ throw new Error('[split] each recipient bps must be > 0');
23
+ const amounts = recipients.map((r) => (amount * BigInt(r.bps)) / BigInt(BPS_DENOMINATOR));
24
+ const remainder = amount - amounts.reduce((s, a) => s + a, 0n);
25
+ amounts[0] += remainder; // assign rounding dust to the first recipient → legs total exactly `amount`
26
+ return recipients.map((r, i) => ({
27
+ to: r.to,
28
+ bps: r.bps,
29
+ amount: amounts[i],
30
+ plan: buildErc20Transfer(asset, r.to, amounts[i]),
31
+ }));
32
+ }
33
+ //# sourceMappingURL=split.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split.js","sourceRoot":"","sources":["../src/split.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,kBAAkB,EAAqB,MAAM,eAAe,CAAC;AActE,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AAEtC,MAAM,UAAU,gBAAgB,CAAC,KAAuE;IACtG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAC5C,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACxF,IAAI,MAAM,IAAI,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC3D,IAAI,QAAQ,KAAK,eAAe;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,eAAe,SAAS,QAAQ,EAAE,CAAC,CAAC;IACjH,KAAK,MAAM,CAAC,IAAI,UAAU;QAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAEtG,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;IAC1F,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/D,OAAO,CAAC,CAAC,CAAE,IAAI,SAAS,CAAC,CAAC,4EAA4E;IAEtG,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/B,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,MAAM,EAAE,OAAO,CAAC,CAAC,CAAE;QACnB,IAAI,EAAE,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAE,CAAC;KACnD,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Shared transfer-plan plumbing for the non-x402 rails (spec 243 §5.5).
3
+ *
4
+ * A `TransferPlan` is the inner call an SA executes (`AgentAccount.execute(to, value, data)`
5
+ * or a UserOp / wallet tx) — the same `{to, value, data}` shape the x402 rail's
6
+ * `buildRedemptionCalldata` returns. Wallet / invoice / refund / split all reduce to one or
7
+ * more ERC-20 transfers from the payer or treasury SA.
8
+ */
9
+ import { type Address, type Hex } from 'viem';
10
+ export interface TransferPlan {
11
+ to: Address;
12
+ value: bigint;
13
+ data: Hex;
14
+ }
15
+ export declare const ERC20_TRANSFER_ABI: readonly [{
16
+ readonly type: "function";
17
+ readonly name: "transfer";
18
+ readonly stateMutability: "nonpayable";
19
+ readonly inputs: readonly [{
20
+ readonly name: "to";
21
+ readonly type: "address";
22
+ }, {
23
+ readonly name: "amount";
24
+ readonly type: "uint256";
25
+ }];
26
+ readonly outputs: readonly [{
27
+ readonly type: "bool";
28
+ }];
29
+ }];
30
+ /** A single ERC-20 transfer: the executing SA calls `asset.transfer(to, amount)`. */
31
+ export declare function buildErc20Transfer(asset: Address, to: Address, amount: bigint): TransferPlan;
32
+ /** A native-value transfer (the executing SA sends `amount` wei to `to`). */
33
+ export declare function buildNativeTransfer(to: Address, amount: bigint): TransferPlan;
34
+ export declare const ERC20_APPROVE_ABI: readonly [{
35
+ readonly type: "function";
36
+ readonly name: "approve";
37
+ readonly stateMutability: "nonpayable";
38
+ readonly inputs: readonly [{
39
+ readonly name: "spender";
40
+ readonly type: "address";
41
+ }, {
42
+ readonly name: "amount";
43
+ readonly type: "uint256";
44
+ }];
45
+ readonly outputs: readonly [{
46
+ readonly type: "bool";
47
+ }];
48
+ }];
49
+ /** An ERC-20 approval — needed before the escrow `deposit` pulls funds via `transferFrom`. */
50
+ export declare function buildErc20Approve(asset: Address, spender: Address, amount: bigint): TransferPlan;
51
+ //# sourceMappingURL=transfer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../src/transfer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAsB,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,GAAG,CAAC;CACX;AAED,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;EAWrB,CAAC;AAEX,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAM5F;AAED,6EAA6E;AAC7E,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAE7E;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;EAWpB,CAAC;AAEX,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAMhG"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Shared transfer-plan plumbing for the non-x402 rails (spec 243 §5.5).
3
+ *
4
+ * A `TransferPlan` is the inner call an SA executes (`AgentAccount.execute(to, value, data)`
5
+ * or a UserOp / wallet tx) — the same `{to, value, data}` shape the x402 rail's
6
+ * `buildRedemptionCalldata` returns. Wallet / invoice / refund / split all reduce to one or
7
+ * more ERC-20 transfers from the payer or treasury SA.
8
+ */
9
+ import { encodeFunctionData } from 'viem';
10
+ export const ERC20_TRANSFER_ABI = [
11
+ {
12
+ type: 'function',
13
+ name: 'transfer',
14
+ stateMutability: 'nonpayable',
15
+ inputs: [
16
+ { name: 'to', type: 'address' },
17
+ { name: 'amount', type: 'uint256' },
18
+ ],
19
+ outputs: [{ type: 'bool' }],
20
+ },
21
+ ];
22
+ /** A single ERC-20 transfer: the executing SA calls `asset.transfer(to, amount)`. */
23
+ export function buildErc20Transfer(asset, to, amount) {
24
+ return {
25
+ to: asset,
26
+ value: 0n,
27
+ data: encodeFunctionData({ abi: ERC20_TRANSFER_ABI, functionName: 'transfer', args: [to, amount] }),
28
+ };
29
+ }
30
+ /** A native-value transfer (the executing SA sends `amount` wei to `to`). */
31
+ export function buildNativeTransfer(to, amount) {
32
+ return { to, value: amount, data: '0x' };
33
+ }
34
+ export const ERC20_APPROVE_ABI = [
35
+ {
36
+ type: 'function',
37
+ name: 'approve',
38
+ stateMutability: 'nonpayable',
39
+ inputs: [
40
+ { name: 'spender', type: 'address' },
41
+ { name: 'amount', type: 'uint256' },
42
+ ],
43
+ outputs: [{ type: 'bool' }],
44
+ },
45
+ ];
46
+ /** An ERC-20 approval — needed before the escrow `deposit` pulls funds via `transferFrom`. */
47
+ export function buildErc20Approve(asset, spender, amount) {
48
+ return {
49
+ to: asset,
50
+ value: 0n,
51
+ data: encodeFunctionData({ abi: ERC20_APPROVE_ABI, functionName: 'approve', args: [spender, amount] }),
52
+ };
53
+ }
54
+ //# sourceMappingURL=transfer.js.map