@obbyx/x402-obyte 0.0.0-stage → 0.2.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.
Files changed (128) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +65 -2
  3. package/dist/batch/client-store.d.ts +50 -0
  4. package/dist/batch/client-store.d.ts.map +1 -0
  5. package/dist/batch/client-store.js +93 -0
  6. package/dist/batch/client-store.js.map +1 -0
  7. package/dist/batch/client.d.ts +63 -0
  8. package/dist/batch/client.d.ts.map +1 -0
  9. package/dist/batch/client.js +226 -0
  10. package/dist/batch/client.js.map +1 -0
  11. package/dist/batch/facilitator.d.ts +73 -0
  12. package/dist/batch/facilitator.d.ts.map +1 -0
  13. package/dist/batch/facilitator.js +341 -0
  14. package/dist/batch/facilitator.js.map +1 -0
  15. package/dist/batch/gateway.d.ts +21 -0
  16. package/dist/batch/gateway.d.ts.map +1 -0
  17. package/dist/batch/gateway.js +2 -0
  18. package/dist/batch/gateway.js.map +1 -0
  19. package/dist/batch/requirements.d.ts +52 -0
  20. package/dist/batch/requirements.d.ts.map +1 -0
  21. package/dist/batch/requirements.js +80 -0
  22. package/dist/batch/requirements.js.map +1 -0
  23. package/dist/batch/store.d.ts +112 -0
  24. package/dist/batch/store.d.ts.map +1 -0
  25. package/dist/batch/store.js +198 -0
  26. package/dist/batch/store.js.map +1 -0
  27. package/dist/batch/watcher-protocol.d.ts +91 -0
  28. package/dist/batch/watcher-protocol.d.ts.map +1 -0
  29. package/dist/batch/watcher-protocol.js +82 -0
  30. package/dist/batch/watcher-protocol.js.map +1 -0
  31. package/dist/binding/binding.d.ts +32 -0
  32. package/dist/binding/binding.d.ts.map +1 -0
  33. package/dist/binding/binding.js +19 -0
  34. package/dist/binding/binding.js.map +1 -0
  35. package/dist/coins/composer.d.ts +58 -0
  36. package/dist/coins/composer.d.ts.map +1 -0
  37. package/dist/coins/composer.js +102 -0
  38. package/dist/coins/composer.js.map +1 -0
  39. package/dist/coins/index.d.ts +4 -0
  40. package/dist/coins/index.d.ts.map +1 -0
  41. package/dist/coins/index.js +4 -0
  42. package/dist/coins/index.js.map +1 -0
  43. package/dist/coins/reservations.d.ts +37 -0
  44. package/dist/coins/reservations.d.ts.map +1 -0
  45. package/dist/coins/reservations.js +102 -0
  46. package/dist/coins/reservations.js.map +1 -0
  47. package/dist/coins/selection.d.ts +42 -0
  48. package/dist/coins/selection.d.ts.map +1 -0
  49. package/dist/coins/selection.js +60 -0
  50. package/dist/coins/selection.js.map +1 -0
  51. package/dist/exact/client.d.ts +33 -0
  52. package/dist/exact/client.d.ts.map +1 -0
  53. package/dist/exact/client.js +93 -0
  54. package/dist/exact/client.js.map +1 -0
  55. package/dist/exact/facilitator-v1.d.ts +48 -0
  56. package/dist/exact/facilitator-v1.d.ts.map +1 -0
  57. package/dist/exact/facilitator-v1.js +81 -0
  58. package/dist/exact/facilitator-v1.js.map +1 -0
  59. package/dist/exact/facilitator.d.ts +94 -0
  60. package/dist/exact/facilitator.d.ts.map +1 -0
  61. package/dist/exact/facilitator.js +361 -0
  62. package/dist/exact/facilitator.js.map +1 -0
  63. package/dist/exact/finality.d.ts +18 -0
  64. package/dist/exact/finality.d.ts.map +1 -0
  65. package/dist/exact/finality.js +45 -0
  66. package/dist/exact/finality.js.map +1 -0
  67. package/dist/exact/ledger-checks.d.ts +15 -0
  68. package/dist/exact/ledger-checks.d.ts.map +1 -0
  69. package/dist/exact/ledger-checks.js +85 -0
  70. package/dist/exact/ledger-checks.js.map +1 -0
  71. package/dist/exact/reasons.d.ts +29 -0
  72. package/dist/exact/reasons.d.ts.map +1 -0
  73. package/dist/exact/reasons.js +21 -0
  74. package/dist/exact/reasons.js.map +1 -0
  75. package/dist/exact/requirements.d.ts +37 -0
  76. package/dist/exact/requirements.d.ts.map +1 -0
  77. package/dist/exact/requirements.js +80 -0
  78. package/dist/exact/requirements.js.map +1 -0
  79. package/dist/exact/store.d.ts +136 -0
  80. package/dist/exact/store.d.ts.map +1 -0
  81. package/dist/exact/store.js +217 -0
  82. package/dist/exact/store.js.map +1 -0
  83. package/dist/hub/heartbeat.d.ts +12 -0
  84. package/dist/hub/heartbeat.d.ts.map +1 -0
  85. package/dist/hub/heartbeat.js +17 -0
  86. package/dist/hub/heartbeat.js.map +1 -0
  87. package/dist/hub/hub-call.d.ts +20 -0
  88. package/dist/hub/hub-call.d.ts.map +1 -0
  89. package/dist/hub/hub-call.js +30 -0
  90. package/dist/hub/hub-call.js.map +1 -0
  91. package/dist/hub/schemas.d.ts +41 -0
  92. package/dist/hub/schemas.d.ts.map +1 -0
  93. package/dist/hub/schemas.js +71 -0
  94. package/dist/hub/schemas.js.map +1 -0
  95. package/dist/index.d.ts +19 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +19 -0
  98. package/dist/index.js.map +1 -0
  99. package/dist/util/keyed-queue.d.ts +13 -0
  100. package/dist/util/keyed-queue.d.ts.map +1 -0
  101. package/dist/util/keyed-queue.js +25 -0
  102. package/dist/util/keyed-queue.js.map +1 -0
  103. package/package.json +51 -3
  104. package/src/batch/client-store.ts +167 -0
  105. package/src/batch/client.ts +317 -0
  106. package/src/batch/facilitator.ts +461 -0
  107. package/src/batch/gateway.ts +22 -0
  108. package/src/batch/requirements.ts +108 -0
  109. package/src/batch/store.ts +359 -0
  110. package/src/batch/watcher-protocol.ts +89 -0
  111. package/src/binding/binding.ts +50 -0
  112. package/src/coins/composer.ts +159 -0
  113. package/src/coins/index.ts +9 -0
  114. package/src/coins/reservations.ts +139 -0
  115. package/src/coins/selection.ts +93 -0
  116. package/src/exact/client.ts +144 -0
  117. package/src/exact/facilitator-v1.ts +137 -0
  118. package/src/exact/facilitator.ts +496 -0
  119. package/src/exact/finality.ts +56 -0
  120. package/src/exact/ledger-checks.ts +113 -0
  121. package/src/exact/reasons.ts +25 -0
  122. package/src/exact/requirements.ts +109 -0
  123. package/src/exact/store.ts +399 -0
  124. package/src/hub/heartbeat.ts +18 -0
  125. package/src/hub/hub-call.ts +46 -0
  126. package/src/hub/schemas.ts +89 -0
  127. package/src/index.ts +111 -0
  128. package/src/util/keyed-queue.ts +25 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finality.js","sourceRoot":"","sources":["../../src/exact/finality.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;GAGG;AACH;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAElG,8FAA8F;AAC9F,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAyF,EACzF,MAAoB,EACpB,QAAgB;IAEhB,MAAM,GAAG,GAAG,MAAM,OAAO,CACvB,GAAG,EAAE,CACH,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAC3C,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;QACpB,SAAS;QACT,SAAS,EAAE,CAAC,GAAG,CAAC,mBAAmB,IAAI,qBAAqB,CAAC;QAC7D,gBAAgB,EAAE,CAAC,QAAQ,CAAC;KACpB,CAAC,CACZ,EACH,GAAG,CAAC,YAAY,CACjB,CAAC;IACF,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IACvF,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzC,OAAO,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,qBAAqB,GAAG;IAC5B,4BAA4B;IAC5B,kBAAkB;IAClB,iBAAiB;IACjB,gBAAgB;IAChB,SAAS;IACT,aAAa;CACd,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAC9B,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type obyte from 'obyte';
2
+ import type { ExactUnitFacts } from '@obbyx/obyte';
3
+ import { type Check } from './reasons.js';
4
+ import type { ParsedExactRequirements } from './requirements.js';
5
+ export interface LedgerCheckContext {
6
+ readonly hubTimeoutMs: number;
7
+ readonly maxLastBallAgeSeconds: number;
8
+ readonly now: () => number;
9
+ }
10
+ /**
11
+ * Ledger checks (hub-trusted, ADR-0001/0002): last ball recency, inputs
12
+ * exist and belong to the payer, amounts + fees balance, inputs unspent.
13
+ */
14
+ export declare function checkLedger(ctx: LedgerCheckContext, client: obyte.Client, req: ParsedExactRequirements, facts: ExactUnitFacts, unit: Record<string, unknown>): Promise<Check<null>>;
15
+ //# sourceMappingURL=ledger-checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger-checks.d.ts","sourceRoot":"","sources":["../../src/exact/ledger-checks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,OAAO,EAAE,KAAK,KAAK,EAA8B,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAEjE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,kBAAkB,EACvB,MAAM,EAAE,KAAK,CAAC,MAAM,EACpB,GAAG,EAAE,uBAAuB,EAC5B,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAyFtB"}
@@ -0,0 +1,85 @@
1
+ import { hubCall } from '../hub/hub-call.js';
2
+ import { parseHistory, parseLedgerUnit } from '../hub/schemas.js';
3
+ import { EXACT_SETTLE_REASONS, fail } from './reasons.js';
4
+ /**
5
+ * Ledger checks (hub-trusted, ADR-0001/0002): last ball recency, inputs
6
+ * exist and belong to the payer, amounts + fees balance, inputs unspent.
7
+ */
8
+ export async function checkLedger(ctx, client, req, facts, unit) {
9
+ const t = ctx.hubTimeoutMs;
10
+ const lastBall = await hubCall(() => client.api.getJoint(facts.lastBallUnit), t);
11
+ if (lastBall.kind !== 'ok')
12
+ return fail(EXACT_SETTLE_REASONS.ledger, `last ball: ${lastBall.error}`);
13
+ const lastBallTs = lastBall.value.joint?.unit.timestamp;
14
+ if (typeof lastBallTs !== 'number')
15
+ return fail(EXACT_SETTLE_REASONS.stale, 'Unknown last ball unit');
16
+ const lastBallAge = ctx.now() - lastBallTs;
17
+ if (lastBallAge > ctx.maxLastBallAgeSeconds) {
18
+ return fail(EXACT_SETTLE_REASONS.stale, `Last ball is ${lastBallAge} s old; the limit is ${ctx.maxLastBallAgeSeconds} s (MAX_LAST_BALL_AGE_SECONDS)`);
19
+ }
20
+ // Inputs: each referenced output exists, belongs to the payer, has the right asset.
21
+ const totals = new Map();
22
+ const sources = new Map();
23
+ for (const input of facts.inputs) {
24
+ let source = sources.get(input.unit);
25
+ if (source === undefined) {
26
+ const res = await hubCall(() => client.api.getJoint(input.unit), t);
27
+ if (res.kind !== 'ok')
28
+ return fail(EXACT_SETTLE_REASONS.ledger, `input source: ${res.error}`);
29
+ if (res.value.joint === undefined)
30
+ return fail(EXACT_SETTLE_REASONS.inputs, 'Input source unit not found');
31
+ const parsedSource = parseLedgerUnit(res.value.joint.unit);
32
+ if (parsedSource === undefined)
33
+ return fail(EXACT_SETTLE_REASONS.ledger, 'input source: malformed hub answer');
34
+ source = parsedSource;
35
+ sources.set(input.unit, source);
36
+ }
37
+ const message = source.messages?.[input.messageIndex];
38
+ const output = message?.payload?.outputs?.[input.outputIndex];
39
+ const asset = message?.payload?.asset ?? 'base';
40
+ if (message?.app !== 'payment' || output === undefined) {
41
+ return fail(EXACT_SETTLE_REASONS.inputs, 'Input refers to a missing output');
42
+ }
43
+ if (output.address !== facts.payer ||
44
+ asset !== input.asset ||
45
+ !Number.isSafeInteger(output.amount)) {
46
+ return fail(EXACT_SETTLE_REASONS.inputs, 'Input output does not belong to the payer in this asset');
47
+ }
48
+ totals.set(asset, (totals.get(asset) ?? 0n) + BigInt(output.amount));
49
+ }
50
+ const fees = BigInt(facts.commissions.headers + facts.commissions.payload) +
51
+ BigInt(unit['tps_fee'] ?? 0) +
52
+ BigInt(unit['burn_fee'] ?? 0);
53
+ for (const [asset, outTotal] of Object.entries(facts.outputTotals)) {
54
+ const expected = asset === 'base' ? outTotal + fees : outTotal;
55
+ if (totals.get(asset) !== expected) {
56
+ return fail(EXACT_SETTLE_REASONS.inputs, `Inputs and outputs do not balance in ${asset}`);
57
+ }
58
+ }
59
+ // Unspent: no other unit of the payer spends these inputs (best effort
60
+ // until stability; the network decides double-spends definitively).
61
+ const history = await hubCall(() => client.api
62
+ .getWitnesses()
63
+ .then((witnesses) => client.api.getHistory({ witnesses, addresses: [facts.payer] })), t);
64
+ if (history.kind !== 'ok')
65
+ return fail(EXACT_SETTLE_REASONS.ledger, `history: ${history.error}`);
66
+ const parsedHistory = parseHistory(history.value);
67
+ if (parsedHistory === undefined)
68
+ return fail(EXACT_SETTLE_REASONS.ledger, 'history: malformed hub answer');
69
+ const wanted = new Set(facts.inputs.map((i) => `${i.unit}:${i.messageIndex}:${i.outputIndex}`));
70
+ for (const joint of parsedHistory.joints) {
71
+ if (joint.unit.unit === facts.unitHash)
72
+ continue;
73
+ for (const m of joint.unit.messages ?? []) {
74
+ if (m.app !== 'payment')
75
+ continue;
76
+ for (const inp of m.payload?.inputs ?? []) {
77
+ if (wanted.has(`${inp.unit}:${inp.message_index}:${inp.output_index}`)) {
78
+ return fail(EXACT_SETTLE_REASONS.inputs, 'An input is already spent by another unit');
79
+ }
80
+ }
81
+ }
82
+ }
83
+ return { ok: true, value: null };
84
+ }
85
+ //# sourceMappingURL=ledger-checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger-checks.js","sourceRoot":"","sources":["../../src/exact/ledger-checks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /** Settlement/verification reasons of the `exact` facilitator beyond the unit profile ones. */
2
+ export declare const EXACT_SETTLE_REASONS: {
3
+ readonly pending: "settlement_pending";
4
+ readonly rejected: "invalid_exact_obyte_rejected_by_network";
5
+ readonly finalBad: "invalid_exact_obyte_double_spend";
6
+ readonly expired: "invalid_exact_obyte_publication_window_expired";
7
+ readonly ledger: "invalid_exact_obyte_ledger_unavailable";
8
+ readonly inputs: "invalid_exact_obyte_inputs";
9
+ readonly stale: "invalid_exact_obyte_stale";
10
+ readonly quoteExpired: "invalid_exact_obyte_quote_expired";
11
+ readonly payToAa: "invalid_exact_obyte_payto_is_aa";
12
+ readonly acceptedMismatch: "invalid_payment_requirements";
13
+ readonly version: "invalid_x402_version";
14
+ readonly payload: "invalid_payload";
15
+ };
16
+ export type Check<T> = {
17
+ ok: true;
18
+ value: T;
19
+ } | {
20
+ ok: false;
21
+ reason: string;
22
+ message: string;
23
+ };
24
+ export declare const fail: (reason: string, message: string) => {
25
+ ok: false;
26
+ reason: string;
27
+ message: string;
28
+ };
29
+ //# sourceMappingURL=reasons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasons.d.ts","sourceRoot":"","sources":["../../src/exact/reasons.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;CAavB,CAAC;AAEX,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAC/F,eAAO,MAAM,IAAI,GACf,QAAQ,MAAM,EACd,SAAS,MAAM,KACd;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAI7C,CAAC"}
@@ -0,0 +1,21 @@
1
+ /** Settlement/verification reasons of the `exact` facilitator beyond the unit profile ones. */
2
+ export const EXACT_SETTLE_REASONS = {
3
+ pending: 'settlement_pending',
4
+ rejected: 'invalid_exact_obyte_rejected_by_network',
5
+ finalBad: 'invalid_exact_obyte_double_spend',
6
+ expired: 'invalid_exact_obyte_publication_window_expired',
7
+ ledger: 'invalid_exact_obyte_ledger_unavailable',
8
+ inputs: 'invalid_exact_obyte_inputs',
9
+ stale: 'invalid_exact_obyte_stale',
10
+ quoteExpired: 'invalid_exact_obyte_quote_expired',
11
+ payToAa: 'invalid_exact_obyte_payto_is_aa',
12
+ acceptedMismatch: 'invalid_payment_requirements',
13
+ version: 'invalid_x402_version',
14
+ payload: 'invalid_payload',
15
+ };
16
+ export const fail = (reason, message) => ({
17
+ ok: false,
18
+ reason,
19
+ message,
20
+ });
21
+ //# sourceMappingURL=reasons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasons.js","sourceRoot":"","sources":["../../src/exact/reasons.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,OAAO,EAAE,oBAAoB;IAC7B,QAAQ,EAAE,yCAAyC;IACnD,QAAQ,EAAE,kCAAkC;IAC5C,OAAO,EAAE,gDAAgD;IACzD,MAAM,EAAE,wCAAwC;IAChD,MAAM,EAAE,4BAA4B;IACpC,KAAK,EAAE,2BAA2B;IAClC,YAAY,EAAE,mCAAmC;IACjD,OAAO,EAAE,iCAAiC;IAC1C,gBAAgB,EAAE,8BAA8B;IAChD,OAAO,EAAE,sBAAsB;IAC/B,OAAO,EAAE,iBAAiB;CAClB,CAAC;AAGX,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,MAAc,EACd,OAAe,EACiC,EAAE,CAAC,CAAC;IACpD,EAAE,EAAE,KAAK;IACT,MAAM;IACN,OAAO;CACR,CAAC,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { PaymentPayload, PaymentRequirements } from '@x402/core/types';
2
+ import { type ObyteNetwork, type Verdict } from '@obbyx/obyte';
3
+ import { z } from 'zod';
4
+ export declare const EXACT_SCHEME = "exact";
5
+ /**
6
+ * Scheme-specific `extra` of x402 PaymentRequirements for `exact` on Obyte.
7
+ *
8
+ * `binding` is computed by the seller per request (an HMAC over the quote and
9
+ * the request fingerprint, see `@obbyx/sdk`) and must be signed by the client
10
+ * inside the unit's data message. `quoteId`/`validUntil` bound the offer.
11
+ */
12
+ export declare const exactExtraSchema: z.ZodObject<{
13
+ binding: z.ZodString;
14
+ quoteId: z.ZodString;
15
+ validUntil: z.ZodNumber;
16
+ paymentFlow: z.ZodOptional<z.ZodEnum<{
17
+ authorization: "authorization";
18
+ upfront: "upfront";
19
+ }>>;
20
+ }, z.core.$strict>;
21
+ export type ExactExtra = z.infer<typeof exactExtraSchema>;
22
+ export interface ParsedExactRequirements {
23
+ readonly network: ObyteNetwork;
24
+ readonly asset: string;
25
+ readonly amount: bigint;
26
+ readonly payTo: string;
27
+ readonly maxTimeoutSeconds: number;
28
+ readonly extra: ExactExtra;
29
+ }
30
+ export declare function parseExactRequirements(req: PaymentRequirements): Verdict<ParsedExactRequirements>;
31
+ /**
32
+ * x402 core does not compare the client's `accepted` requirements with the
33
+ * server's; a mismatch could let a client pay under different terms.
34
+ */
35
+ export declare function acceptedMatches(payload: PaymentPayload, req: PaymentRequirements): boolean;
36
+ export declare function canonical(value: unknown): string;
37
+ //# sourceMappingURL=requirements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirements.d.ts","sourceRoot":"","sources":["../../src/exact/requirements.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,OAAO,EAQb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,YAAY,UAAU,CAAC;AAEpC;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;kBAclB,CAAC;AAEZ,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC5B;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CA8BjG;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAY1F;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQhD"}
@@ -0,0 +1,80 @@
1
+ import { accept, getNetwork, isAddress, isAssetId, isObyteNetwork, parseAmount, reject, } from '@obbyx/obyte';
2
+ import { z } from 'zod';
3
+ export const EXACT_SCHEME = 'exact';
4
+ /**
5
+ * Scheme-specific `extra` of x402 PaymentRequirements for `exact` on Obyte.
6
+ *
7
+ * `binding` is computed by the seller per request (an HMAC over the quote and
8
+ * the request fingerprint, see `@obbyx/sdk`) and must be signed by the client
9
+ * inside the unit's data message. `quoteId`/`validUntil` bound the offer.
10
+ */
11
+ export const exactExtraSchema = z
12
+ .object({
13
+ binding: z.string().regex(/^[0-9a-f]{64}$/, 'binding must be 64 lowercase hex chars'),
14
+ quoteId: z
15
+ .string()
16
+ .min(8)
17
+ .max(64)
18
+ .regex(/^[A-Za-z0-9_-]+$/),
19
+ validUntil: z.number().int().positive(),
20
+ // x402 §6.1: Obyte supports the `upfront` flow (settle, then serve) and the
21
+ // default `authorization` flow; `escrow` and any asset transfer method
22
+ // (there is none on Obyte: the payer signs the transfer itself) are refused.
23
+ paymentFlow: z.enum(['authorization', 'upfront']).optional(),
24
+ })
25
+ .strict();
26
+ export function parseExactRequirements(req) {
27
+ if (req.scheme !== EXACT_SCHEME)
28
+ return reject('unsupported_scheme', 'Scheme is not exact');
29
+ if (!isObyteNetwork(req.network))
30
+ return reject('invalid_network', 'Not an Obyte network');
31
+ if (!isAssetId(req.asset))
32
+ return reject('invalid_payment_requirements', 'Invalid asset');
33
+ if (!isAddress(req.payTo))
34
+ return reject('invalid_payment_requirements', 'Invalid payTo');
35
+ if (!Number.isSafeInteger(req.maxTimeoutSeconds) || req.maxTimeoutSeconds <= 0) {
36
+ return reject('invalid_payment_requirements', 'Invalid maxTimeoutSeconds');
37
+ }
38
+ let amount;
39
+ try {
40
+ amount = parseAmount(req.amount);
41
+ }
42
+ catch {
43
+ return reject('invalid_payment_requirements', 'Invalid amount');
44
+ }
45
+ if (amount <= 0n)
46
+ return reject('invalid_payment_requirements', 'Amount must be positive');
47
+ const extra = exactExtraSchema.safeParse(req.extra);
48
+ if (!extra.success) {
49
+ return reject('invalid_payment_requirements', `Invalid extra: ${extra.error.issues[0]?.message}`);
50
+ }
51
+ return accept({
52
+ network: getNetwork(req.network),
53
+ asset: req.asset,
54
+ amount,
55
+ payTo: req.payTo,
56
+ maxTimeoutSeconds: req.maxTimeoutSeconds,
57
+ extra: extra.data,
58
+ });
59
+ }
60
+ /**
61
+ * x402 core does not compare the client's `accepted` requirements with the
62
+ * server's; a mismatch could let a client pay under different terms.
63
+ */
64
+ export function acceptedMatches(payload, req) {
65
+ const a = payload.accepted;
66
+ return (a !== undefined &&
67
+ a.scheme === req.scheme &&
68
+ a.network === req.network &&
69
+ a.asset === req.asset &&
70
+ a.amount === req.amount &&
71
+ a.payTo === req.payTo &&
72
+ a.maxTimeoutSeconds === req.maxTimeoutSeconds &&
73
+ canonical(a.extra) === canonical(req.extra));
74
+ }
75
+ export function canonical(value) {
76
+ return JSON.stringify(value, (_k, v) => v && typeof v === 'object' && !Array.isArray(v)
77
+ ? Object.fromEntries(Object.entries(v).sort(([x], [y]) => x.localeCompare(y)))
78
+ : v);
79
+ }
80
+ //# sourceMappingURL=requirements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirements.js","sourceRoot":"","sources":["../../src/exact/requirements.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ import { ObbyxError } from '@obbyx/obyte';
3
+ /**
4
+ * Settlement state machine storage for the `exact` scheme (ADR-0002, ADR-0005).
5
+ *
6
+ * claimed → broadcasting → accepted → stable_good
7
+ * │ └────→ final_bad
8
+ * ├──→ rejected
9
+ * └──→ expired
10
+ *
11
+ * - One row per (network, unit). The row is created (claimed) BEFORE the unit
12
+ * is broadcast (outbox), so a crash between broadcast and the next write is
13
+ * recovered by re-reading non-terminal rows on startup.
14
+ * - Transitions are compare-and-set on the current state inside one
15
+ * SQLite transaction; a lost race returns `false` instead of overwriting.
16
+ * - One facilitator process per database file: the connection takes an
17
+ * exclusive lock at open, so a second process fails fast.
18
+ */
19
+ export type SettlementState = 'claimed' | 'broadcasting' | 'accepted' | 'stable_good' | 'final_bad' | 'rejected' | 'expired';
20
+ export declare const TERMINAL_STATES: ReadonlySet<SettlementState>;
21
+ export interface SettlementRecord {
22
+ readonly key: string;
23
+ readonly network: string;
24
+ readonly unitHash: string;
25
+ readonly binding: string;
26
+ readonly payer: string;
27
+ readonly payTo: string;
28
+ readonly asset: string;
29
+ readonly amount: string;
30
+ readonly state: SettlementState;
31
+ /** Signed unit JSON; deleted (null) after a terminal state and retention. */
32
+ readonly unitJson: string | null;
33
+ /** After this time (unix s) an unpublished unit is never broadcast. */
34
+ readonly publishDeadline: number;
35
+ readonly attempts: number;
36
+ readonly lastError: string | null;
37
+ readonly createdAt: number;
38
+ readonly updatedAt: number;
39
+ }
40
+ export interface NewSettlement {
41
+ readonly key: string;
42
+ readonly network: string;
43
+ readonly unitHash: string;
44
+ readonly binding: string;
45
+ readonly payer: string;
46
+ readonly payTo: string;
47
+ readonly asset: string;
48
+ readonly amount: string;
49
+ readonly unitJson: string;
50
+ readonly publishDeadline: number;
51
+ }
52
+ export interface SettlementEvent {
53
+ readonly key: string;
54
+ readonly kind: string;
55
+ readonly from?: SettlementState | null;
56
+ readonly to?: SettlementState | null;
57
+ readonly data?: Record<string, unknown>;
58
+ }
59
+ /**
60
+ * Port for the `exact` settlement state machine (implemented with node:sqlite
61
+ * here, and with Prisma in apps/facilitator). All implementations must pass
62
+ * the shared contract tests: unique claim, compare-and-set transitions,
63
+ * single process per database.
64
+ */
65
+ export interface SettlementStore {
66
+ get(key: string): Promise<SettlementRecord | undefined>;
67
+ claim(input: NewSettlement): Promise<{
68
+ created: boolean;
69
+ record: SettlementRecord;
70
+ }>;
71
+ transition(key: string, from: readonly SettlementState[], to: SettlementState, patch?: TransitionPatch): Promise<SettlementRecord | undefined>;
72
+ event(event: SettlementEvent): Promise<void>;
73
+ listActive(limit?: number): Promise<SettlementRecord[]>;
74
+ /** Marks a non-terminal record as just looked at (fair rotation in the recovery worker). */
75
+ touch(key: string): Promise<void>;
76
+ events(key: string): Promise<{
77
+ kind: string;
78
+ from: string | null;
79
+ to: string | null;
80
+ data: unknown;
81
+ }[]>;
82
+ pruneUnitBodies(olderThan: number): Promise<number>;
83
+ close(): Promise<void>;
84
+ }
85
+ export interface TransitionPatch {
86
+ readonly lastError?: string | null;
87
+ readonly incrementAttempts?: boolean;
88
+ readonly data?: Record<string, unknown>;
89
+ }
90
+ export declare class StoreLockedError extends ObbyxError {
91
+ constructor(path: string, cause: unknown);
92
+ }
93
+ export declare class SqliteSettlementStore implements SettlementStore {
94
+ private readonly db;
95
+ private readonly now;
96
+ /**
97
+ * @param path SQLite file, or `:memory:` for tests.
98
+ * @param now Clock in unix seconds (injectable for tests).
99
+ */
100
+ constructor(path: string, now?: () => number);
101
+ close(): Promise<void>;
102
+ /** The exclusive connection, shared with other facilitator stores (e.g. BatchStore). */
103
+ get database(): DatabaseSync;
104
+ get(key: string): Promise<SettlementRecord | undefined>;
105
+ private getSync;
106
+ /**
107
+ * Inserts a new settlement in state `claimed` unless the key exists.
108
+ * Returns the stored record and whether this call created it.
109
+ */
110
+ claim(input: NewSettlement): Promise<{
111
+ created: boolean;
112
+ record: SettlementRecord;
113
+ }>;
114
+ /**
115
+ * Compare-and-set transition. Returns the new record, or `undefined` if the
116
+ * current state is not one of `from` (someone else moved it first).
117
+ */
118
+ transition(key: string, from: readonly SettlementState[], to: SettlementState, patch?: TransitionPatch): Promise<SettlementRecord | undefined>;
119
+ /** Records a non-transition event (e.g. a retry) in the payment journal. */
120
+ event(event: SettlementEvent): Promise<void>;
121
+ /** Non-terminal settlements, oldest first — resumed by the recovery worker. */
122
+ touch(key: string): Promise<void>;
123
+ listActive(limit?: number): Promise<SettlementRecord[]>;
124
+ events(key: string): Promise<{
125
+ kind: string;
126
+ from: string | null;
127
+ to: string | null;
128
+ data: unknown;
129
+ }[]>;
130
+ /** Drops signed unit bodies of terminal settlements older than `olderThan` (unix s). */
131
+ pruneUnitBodies(olderThan: number): Promise<number>;
132
+ private insertEvent;
133
+ private mustGet;
134
+ private tx;
135
+ }
136
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/exact/store.ts"],"names":[],"mappings":"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"}