@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,81 @@
1
+ import { getNetwork, isObyteNetwork } from '@obbyx/obyte';
2
+ import { EXACT_SCHEME } from './requirements.js';
3
+ export function requirementsV1ToV2(req) {
4
+ return {
5
+ scheme: req.scheme,
6
+ network: getNetwork(req.network).caip2,
7
+ asset: req.asset,
8
+ amount: req.maxAmountRequired,
9
+ payTo: req.payTo,
10
+ maxTimeoutSeconds: req.maxTimeoutSeconds,
11
+ extra: req.extra ?? {},
12
+ };
13
+ }
14
+ export function requirementsV2ToV1(req, resource) {
15
+ return {
16
+ scheme: req.scheme,
17
+ network: getNetwork(req.network).v1Name,
18
+ maxAmountRequired: req.amount,
19
+ resource: resource.url,
20
+ description: resource.description ?? '',
21
+ mimeType: resource.mimeType ?? '',
22
+ outputSchema: {},
23
+ payTo: req.payTo,
24
+ maxTimeoutSeconds: req.maxTimeoutSeconds,
25
+ asset: req.asset,
26
+ extra: req.extra,
27
+ };
28
+ }
29
+ export class ExactObyteFacilitatorV1 {
30
+ v2;
31
+ scheme = EXACT_SCHEME;
32
+ caipFamily = 'obyte-*';
33
+ constructor(v2) {
34
+ this.v2 = v2;
35
+ }
36
+ getExtra(network) {
37
+ return this.v2.getExtra(getNetwork(network).caip2);
38
+ }
39
+ getSigners() {
40
+ return [];
41
+ }
42
+ async verify(payload, requirements) {
43
+ const converted = this.convert(payload, requirements);
44
+ if (!converted.ok)
45
+ return { isValid: false, invalidReason: converted.reason };
46
+ return this.v2.verify(converted.payload, converted.requirements);
47
+ }
48
+ async settle(payload, requirements) {
49
+ const converted = this.convert(payload, requirements);
50
+ const v1Network = requirements.network;
51
+ if (!converted.ok)
52
+ return { success: false, errorReason: converted.reason, transaction: '', network: v1Network };
53
+ const res = await this.v2.settle(converted.payload, converted.requirements);
54
+ return { ...res, network: v1Network };
55
+ }
56
+ convert(payload, requirements) {
57
+ const p = payload;
58
+ const r = requirements;
59
+ if (p.x402Version !== 1)
60
+ return { ok: false, reason: 'invalid_x402_version' };
61
+ if (p.scheme !== EXACT_SCHEME || r.scheme !== EXACT_SCHEME)
62
+ return { ok: false, reason: 'unsupported_scheme' };
63
+ if (!isObyteNetwork(r.network) || p.network !== r.network)
64
+ return { ok: false, reason: 'invalid_network' };
65
+ if (typeof r.maxAmountRequired !== 'string')
66
+ return { ok: false, reason: 'invalid_payment_requirements' };
67
+ const v2req = requirementsV1ToV2(r);
68
+ // v1 has no `accepted`: the client paid the requirements the server sent.
69
+ return {
70
+ ok: true,
71
+ requirements: v2req,
72
+ payload: {
73
+ x402Version: 2,
74
+ resource: { url: r.resource, description: r.description, mimeType: r.mimeType },
75
+ accepted: v2req,
76
+ payload: p.payload,
77
+ },
78
+ };
79
+ }
80
+ }
81
+ //# sourceMappingURL=facilitator-v1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facilitator-v1.js","sourceRoot":"","sources":["../../src/exact/facilitator-v1.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import type { Network, PaymentPayload, PaymentRequirements, SchemeNetworkFacilitator, SettleResponse, VerifyResponse } from '@x402/core/types';
2
+ import { type Logger } from '@obbyx/obyte/logger';
3
+ import type obyte from 'obyte';
4
+ import { type SettlementRecord, type SettlementStore } from './store.js';
5
+ /**
6
+ * x402 `exact` facilitator for Obyte (ADR-0002).
7
+ *
8
+ * The client signs a unit paying `payTo` and carrying the seller's binding in a
9
+ * data message; it does not broadcast. `/verify` checks it read-only (local
10
+ * profile + ledger reads); `/settle` claims it in the store, broadcasts it and
11
+ * reports success only when the configured finality policy is met.
12
+ *
13
+ * obyte.js is used directly (`client.api.*`); every hub call goes through
14
+ * {@link hubCall} for timeouts and unknown-outcome classification (I7).
15
+ */
16
+ export type FinalityPolicy = 'stable' | 'accepted';
17
+ export { EXACT_SETTLE_REASONS } from './reasons.js';
18
+ export { HISTORY_PROBE_ADDRESS, isTransientPostError } from './finality.js';
19
+ export interface ExactObyteFacilitatorOptions {
20
+ /** obyte.js clients by CAIP-2 network id. */
21
+ readonly clients: ReadonlyMap<string, obyte.Client>;
22
+ readonly store: SettlementStore;
23
+ readonly logger: Logger;
24
+ /** Allowed assets per CAIP-2 network ('base' = bytes). */
25
+ readonly allowedAssets: ReadonlyMap<string, ReadonlySet<string>>;
26
+ readonly finality?: FinalityPolicy;
27
+ /** Addresses controlled by the facilitator; they may never be the payer. */
28
+ readonly facilitatorAddresses?: readonly string[];
29
+ readonly hubTimeoutMs?: number;
30
+ /** Tolerated clock difference between client, hub and us (seconds). */
31
+ readonly maxClockSkewSeconds?: number;
32
+ /** After acceptance, how long a claimed unit may still be (re)broadcast. */
33
+ readonly publishWindowSeconds?: number;
34
+ /**
35
+ * Oldest accepted `last_ball` of a payment unit, seconds (default 10800 = 3 h).
36
+ * Independent of `maxTimeoutSeconds`: with few transactions the network's
37
+ * stable point normally lags up to ~2 hours, while the unit's freshness is already guaranteed by the
38
+ * offer binding (it contains a random quoteId issued at most quote-TTL ago).
39
+ */
40
+ readonly maxLastBallAgeSeconds?: number;
41
+ /** Address with no history for the mandatory `addresses` of history requests. */
42
+ readonly historyProbeAddress?: string;
43
+ readonly now?: () => number;
44
+ }
45
+ export declare class ExactObyteFacilitator implements SchemeNetworkFacilitator {
46
+ private readonly options;
47
+ readonly scheme = "exact";
48
+ readonly caipFamily: "obyte:*";
49
+ private readonly log;
50
+ private readonly finality;
51
+ private readonly hubTimeoutMs;
52
+ private readonly skew;
53
+ private readonly publishWindow;
54
+ private readonly maxLastBallAge;
55
+ private readonly now;
56
+ /** Serializes settle/resume per settlement key inside this process. */
57
+ private readonly inFlight;
58
+ constructor(options: ExactObyteFacilitatorOptions);
59
+ getExtra(network: Network): Record<string, unknown> | undefined;
60
+ /** The payer pays its own fees; the facilitator signs nothing in `exact`. */
61
+ getSigners(): string[];
62
+ verify(payload: PaymentPayload, requirements: PaymentRequirements): Promise<VerifyResponse>;
63
+ settle(payload: PaymentPayload, requirements: PaymentRequirements): Promise<SettleResponse>;
64
+ /** Re-drives a non-terminal settlement (used by the recovery worker). */
65
+ resume(record: SettlementRecord): Promise<SettleResponse>;
66
+ private check;
67
+ /** Known plain (non-AA) recipients; an address can never turn into an AA. */
68
+ private readonly plainRecipients;
69
+ private recipientIsNotAa;
70
+ private fetchDefinition;
71
+ private drive;
72
+ /**
73
+ * One pass of the state machine: publish (or find) the unit, then follow it
74
+ * to finality. Every hop is a compare-and-set; anything unknown leaves the
75
+ * record where it is, to be resumed by a retry or the recovery worker.
76
+ */
77
+ private step;
78
+ /** Before acceptance: find the unit on the ledger, otherwise post it while the window is open. */
79
+ private publish;
80
+ /**
81
+ * Past the publication window we never post. A unit we never posted expires.
82
+ * One we posted (outcome unknown or "not yet") may still land, so it is
83
+ * looked for during a grace period before it expires.
84
+ */
85
+ private afterPublishWindow;
86
+ /** Posts the unit once and classifies the hub's answer. */
87
+ private broadcast;
88
+ /** After acceptance: stable and good, final-bad, or still waiting (rotated for recovery). */
89
+ private awaitFinality;
90
+ private move;
91
+ private respond;
92
+ private key;
93
+ }
94
+ //# sourceMappingURL=facilitator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facilitator.d.ts","sourceRoot":"","sources":["../../src/exact/facilitator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,mBAAmB,EACnB,wBAAwB,EACxB,cAAc,EACd,cAAc,EACf,MAAM,kBAAkB,CAAC;AAY1B,OAAO,EAAE,KAAK,MAAM,EAAgC,MAAM,qBAAqB,CAAC;AAChF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAmB,MAAM,YAAY,CAAC;AAE1F;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,UAAU,CAAC;AAInD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE5E,MAAM,WAAW,4BAA4B;IAC3C,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IACjE,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;IACnC,4EAA4E;IAC5E,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,4EAA4E;IAC5E,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACxC,iFAAiF;IACjF,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,qBAAa,qBAAsB,YAAW,wBAAwB;IAcxD,OAAO,CAAC,QAAQ,CAAC,OAAO;IAbpC,QAAQ,CAAC,MAAM,WAAgB;IAC/B,QAAQ,CAAC,UAAU,YAAqB;IAExC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8C;gBAE1C,OAAO,EAAE,4BAA4B;IAUlE,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAK/D,6EAA6E;IAC7E,UAAU,IAAI,MAAM,EAAE;IAIhB,MAAM,CACV,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,mBAAmB,GAChC,OAAO,CAAC,cAAc,CAAC;IAapB,MAAM,CACV,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,mBAAmB,GAChC,OAAO,CAAC,cAAc,CAAC;IA+D1B,yEAAyE;IACzE,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC;YAS3C,KAAK;IAqEnB,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;YAEvC,gBAAgB;YAchB,eAAe;IAoB7B,OAAO,CAAC,KAAK;IAQb;;;;OAIG;YACW,IAAI;IAYlB,kGAAkG;YACpF,OAAO;IAuBrB;;;;OAIG;YACW,kBAAkB;IAWhC,2DAA2D;YAC7C,SAAS;IAyCvB,6FAA6F;YAC/E,aAAa;YAkBb,IAAI;IAclB,OAAO,CAAC,OAAO;IA+Bf,OAAO,CAAC,GAAG;CAGZ"}
@@ -0,0 +1,361 @@
1
+ import { EXACT_REASONS, OBYTE_CAIP_FAMILY, getNetwork, isObyteNetwork, isSigDefinition, networkKey, validateExactUnit, } from '@obbyx/obyte';
2
+ import { moduleLogger, withLogContext } from '@obbyx/obyte/logger';
3
+ import { hubCall } from '../hub/hub-call.js';
4
+ import { finalityOf, isTransientPostError } from './finality.js';
5
+ import { checkLedger } from './ledger-checks.js';
6
+ import { EXACT_SETTLE_REASONS, fail } from './reasons.js';
7
+ import { EXACT_SCHEME, acceptedMatches, parseExactRequirements, } from './requirements.js';
8
+ import { TERMINAL_STATES } from './store.js';
9
+ /** How long a unit we posted is still looked for after the publication window (s). */
10
+ const POSTED_UNIT_GRACE_SECONDS = 86_400;
11
+ export { EXACT_SETTLE_REASONS } from './reasons.js';
12
+ export { HISTORY_PROBE_ADDRESS, isTransientPostError } from './finality.js';
13
+ export class ExactObyteFacilitator {
14
+ options;
15
+ scheme = EXACT_SCHEME;
16
+ caipFamily = OBYTE_CAIP_FAMILY;
17
+ log;
18
+ finality;
19
+ hubTimeoutMs;
20
+ skew;
21
+ publishWindow;
22
+ maxLastBallAge;
23
+ now;
24
+ /** Serializes settle/resume per settlement key inside this process. */
25
+ inFlight = new Map();
26
+ constructor(options) {
27
+ this.options = options;
28
+ this.log = moduleLogger(options.logger, 'x402.exact', { scheme: EXACT_SCHEME });
29
+ this.finality = options.finality ?? 'stable';
30
+ this.hubTimeoutMs = options.hubTimeoutMs ?? 15_000;
31
+ this.skew = options.maxClockSkewSeconds ?? 120;
32
+ this.publishWindow = options.publishWindowSeconds ?? 300;
33
+ this.maxLastBallAge = options.maxLastBallAgeSeconds ?? 10_800;
34
+ this.now = options.now ?? (() => Math.floor(Date.now() / 1000));
35
+ }
36
+ getExtra(network) {
37
+ const assets = this.options.allowedAssets.get(network);
38
+ return { finality: this.finality, assets: assets === undefined ? [] : [...assets] };
39
+ }
40
+ /** The payer pays its own fees; the facilitator signs nothing in `exact`. */
41
+ getSigners() {
42
+ return [];
43
+ }
44
+ async verify(payload, requirements) {
45
+ return withLogContext({ scheme: EXACT_SCHEME, network: requirements.network }, async () => {
46
+ const checked = await this.check(payload, requirements);
47
+ if (!checked.ok) {
48
+ this.log.info({ reason: checked.reason, detail: checked.message }, 'verify rejected');
49
+ return { isValid: false, invalidReason: checked.reason, invalidMessage: checked.message };
50
+ }
51
+ const { facts } = checked.value;
52
+ this.log.info({ proofId: facts.unitHash, payer: facts.payer }, 'verify ok');
53
+ return { isValid: true, payer: facts.payer };
54
+ });
55
+ }
56
+ async settle(payload, requirements) {
57
+ return withLogContext({ scheme: EXACT_SCHEME, network: requirements.network }, async () => {
58
+ const network = requirements.network;
59
+ const unitHash = unitHashOf(payload);
60
+ if (unitHash === undefined) {
61
+ return failure(network, EXACT_SETTLE_REASONS.payload, 'Missing unit');
62
+ }
63
+ if (!isObyteNetwork(requirements.network)) {
64
+ return failure(network, 'invalid_network', 'Not an Obyte network');
65
+ }
66
+ const existing = await this.options.store.get(this.key(requirements.network, unitHash));
67
+ if (existing === undefined) {
68
+ const checked = await this.check(payload, requirements);
69
+ if (!checked.ok) {
70
+ this.log.info({ proofId: unitHash, reason: checked.reason }, 'settle rejected at verification');
71
+ // The hub did not answer: outcome unknown, nothing claimed yet. Pending
72
+ // (non-empty transaction) so callers keep the payment and retry.
73
+ if (checked.reason === EXACT_SETTLE_REASONS.ledger) {
74
+ return {
75
+ success: false,
76
+ errorReason: 'settlement_pending',
77
+ errorMessage: checked.message,
78
+ transaction: unitHash,
79
+ network,
80
+ };
81
+ }
82
+ return failure(network, checked.reason, checked.message);
83
+ }
84
+ const { facts, req } = checked.value;
85
+ const { created, record } = await this.options.store.claim({
86
+ key: this.key(requirements.network, facts.unitHash),
87
+ network: requirements.network,
88
+ unitHash: facts.unitHash,
89
+ binding: req.extra.binding,
90
+ payer: facts.payer,
91
+ payTo: req.payTo,
92
+ asset: req.asset,
93
+ amount: req.amount.toString(),
94
+ unitJson: JSON.stringify(payload.payload['unit']),
95
+ publishDeadline: this.now() + this.publishWindow,
96
+ });
97
+ this.log.info({ proofId: facts.unitHash, created, binding: req.extra.binding }, 'settlement claimed');
98
+ return this.drive(record);
99
+ }
100
+ // Idempotent resume: the same unit is bound to exactly one binding.
101
+ const binding = requirements.extra.binding;
102
+ if (existing.binding !== binding || existing.payTo !== requirements.payTo) {
103
+ return failure(network, 'invalid_payment_reused', 'This payment is bound to another operation');
104
+ }
105
+ return this.drive(existing);
106
+ });
107
+ }
108
+ /** Re-drives a non-terminal settlement (used by the recovery worker). */
109
+ resume(record) {
110
+ return withLogContext({ scheme: EXACT_SCHEME, network: record.network, proofId: record.unitHash }, () => this.drive(record));
111
+ }
112
+ // --- verification ---------------------------------------------------------
113
+ async check(payload, requirements) {
114
+ if (payload.x402Version !== 2)
115
+ return fail(EXACT_SETTLE_REASONS.version, 'Only x402 v2 is supported here');
116
+ if (!acceptedMatches(payload, requirements)) {
117
+ return fail(EXACT_SETTLE_REASONS.acceptedMismatch, 'Accepted requirements differ from the server requirements');
118
+ }
119
+ const parsed = parseExactRequirements(requirements);
120
+ if (!parsed.ok)
121
+ return fail(parsed.reason, parsed.message);
122
+ const req = parsed.value;
123
+ const now = this.now();
124
+ if (req.extra.validUntil < now)
125
+ return fail(EXACT_SETTLE_REASONS.quoteExpired, 'The payment offer has expired');
126
+ if (!this.options.allowedAssets.get(req.network.caip2)?.has(req.asset)) {
127
+ return fail(EXACT_REASONS.asset, 'Asset is not accepted by this facilitator');
128
+ }
129
+ const client = this.options.clients.get(req.network.caip2);
130
+ if (client === undefined)
131
+ return fail('invalid_network', 'Network is not served');
132
+ const unit = payload.payload['unit'];
133
+ const expectation = {
134
+ network: req.network,
135
+ payTo: req.payTo,
136
+ asset: req.asset,
137
+ amount: req.amount,
138
+ binding: req.extra.binding,
139
+ quoteId: req.extra.quoteId,
140
+ ...(this.options.facilitatorAddresses
141
+ ? { facilitatorAddresses: this.options.facilitatorAddresses }
142
+ : {}),
143
+ };
144
+ let local = validateExactUnit(unit, expectation);
145
+ if (!local.ok && local.reason === EXACT_REASONS.definitionRequired) {
146
+ const definition = await this.fetchDefinition(client, unit);
147
+ if (!definition.ok)
148
+ return definition;
149
+ local = validateExactUnit(unit, expectation, { authorDefinition: definition.value });
150
+ }
151
+ if (!local.ok)
152
+ return fail(local.reason, local.message);
153
+ const facts = local.value;
154
+ // Clock sanity: the unit was composed recently.
155
+ if (Math.abs(facts.timestamp - now) > this.skew + req.maxTimeoutSeconds) {
156
+ return fail(EXACT_SETTLE_REASONS.stale, 'Unit timestamp is outside the acceptance window');
157
+ }
158
+ // payTo must be a plain address: a payment to an autonomous agent triggers
159
+ // it, and the AA may bounce the funds back to the payer (the unit is still
160
+ // valid and final, so the seller would serve without being paid).
161
+ const recipient = await this.recipientIsNotAa(client, req.payTo);
162
+ if (!recipient.ok)
163
+ return recipient;
164
+ const ledger = await checkLedger({
165
+ hubTimeoutMs: this.hubTimeoutMs,
166
+ maxLastBallAgeSeconds: this.maxLastBallAge,
167
+ now: this.now,
168
+ }, client, req, facts, unit);
169
+ if (!ledger.ok)
170
+ return ledger;
171
+ return { ok: true, value: { facts, req } };
172
+ }
173
+ /** Known plain (non-AA) recipients; an address can never turn into an AA. */
174
+ plainRecipients = new Set();
175
+ async recipientIsNotAa(client, payTo) {
176
+ if (this.plainRecipients.has(payTo))
177
+ return { ok: true, value: null };
178
+ const res = await hubCall(() => client.api.getDefinition(payTo), this.hubTimeoutMs);
179
+ if (res.kind !== 'ok')
180
+ return fail(EXACT_SETTLE_REASONS.ledger, `Cannot read the payTo definition: ${res.error}`);
181
+ const definition = res.value;
182
+ if (Array.isArray(definition) && definition[0] === 'autonomous agent') {
183
+ return fail(EXACT_SETTLE_REASONS.payToAa, 'payTo is an autonomous agent');
184
+ }
185
+ // An unused address has no definition yet (null): fine, but not cached.
186
+ if (definition !== null && definition !== undefined)
187
+ this.plainRecipients.add(payTo);
188
+ return { ok: true, value: null };
189
+ }
190
+ async fetchDefinition(client, unit) {
191
+ const address = unit.authors?.[0]?.address;
192
+ if (typeof address !== 'string')
193
+ return fail(EXACT_REASONS.unsupported, 'Malformed author');
194
+ const res = await hubCall(() => client.api.getDefinition(address), this.hubTimeoutMs);
195
+ if (res.kind !== 'ok')
196
+ return fail(EXACT_SETTLE_REASONS.ledger, `Cannot read definition: ${res.error}`);
197
+ if (!isSigDefinition(res.value)) {
198
+ return fail(EXACT_REASONS.definition, 'Payer definition is unknown or not a single-sig definition');
199
+ }
200
+ return { ok: true, value: res.value };
201
+ }
202
+ // --- settlement state machine --------------------------------------------------
203
+ drive(record) {
204
+ const running = this.inFlight.get(record.key);
205
+ if (running !== undefined)
206
+ return running;
207
+ const promise = this.step(record).finally(() => this.inFlight.delete(record.key));
208
+ this.inFlight.set(record.key, promise);
209
+ return promise;
210
+ }
211
+ /**
212
+ * One pass of the state machine: publish (or find) the unit, then follow it
213
+ * to finality. Every hop is a compare-and-set; anything unknown leaves the
214
+ * record where it is, to be resumed by a retry or the recovery worker.
215
+ */
216
+ async step(initial) {
217
+ const client = this.options.clients.get(initial.network);
218
+ let record = (await this.options.store.get(initial.key)) ?? initial;
219
+ if (client === undefined)
220
+ return this.respond(record, 'Network is not served');
221
+ let problem;
222
+ if (record.state === 'claimed' || record.state === 'broadcasting') {
223
+ ({ record, problem } = await this.publish(client, record));
224
+ }
225
+ if (record.state === 'accepted')
226
+ record = await this.awaitFinality(client, record);
227
+ return this.respond(record, problem);
228
+ }
229
+ /** Before acceptance: find the unit on the ledger, otherwise post it while the window is open. */
230
+ async publish(client, record) {
231
+ // Is it already on the ledger (we or someone else published it)?
232
+ const known = await hubCall(() => client.api.getJoint(record.unitHash), this.hubTimeoutMs);
233
+ if (known.kind !== 'ok') {
234
+ await this.options.store.event({
235
+ key: record.key,
236
+ kind: 'hub_unavailable',
237
+ data: { op: 'get_joint', error: known.error },
238
+ });
239
+ return { record };
240
+ }
241
+ if (known.value.joint !== undefined) {
242
+ return { record: await this.move(record, 'accepted', { data: { via: 'get_joint' } }) };
243
+ }
244
+ if (this.now() > record.publishDeadline)
245
+ return { record: await this.afterPublishWindow(record) };
246
+ if (record.unitJson === null)
247
+ return { record, problem: 'Unit body is no longer stored' };
248
+ return { record: await this.broadcast(client, record, record.unitJson) };
249
+ }
250
+ /**
251
+ * Past the publication window we never post. A unit we never posted expires.
252
+ * One we posted (outcome unknown or "not yet") may still land, so it is
253
+ * looked for during a grace period before it expires.
254
+ */
255
+ async afterPublishWindow(record) {
256
+ if (record.attempts === 0) {
257
+ return this.move(record, 'expired', { lastError: 'publication window closed' });
258
+ }
259
+ if (this.now() > record.publishDeadline + POSTED_UNIT_GRACE_SECONDS) {
260
+ return this.move(record, 'expired', { lastError: 'posted, but never seen on the ledger' });
261
+ }
262
+ await this.options.store.touch(record.key);
263
+ return record;
264
+ }
265
+ /** Posts the unit once and classifies the hub's answer. */
266
+ async broadcast(client, initial, unitJson) {
267
+ // Count the attempt BEFORE posting: a crash mid-post still counts as "maybe sent".
268
+ const record = await this.move(initial, 'broadcasting', { incrementAttempts: true });
269
+ const unit = JSON.parse(unitJson);
270
+ const posted = await hubCall(() => client.api.postJoint({ unit }), this.hubTimeoutMs);
271
+ await this.options.store.event({
272
+ key: record.key,
273
+ kind: 'post_joint',
274
+ data: { outcome: posted.kind },
275
+ });
276
+ const proofId = record.unitHash;
277
+ if (posted.kind === 'ok') {
278
+ return this.move(record, 'accepted', { data: { response: posted.value } });
279
+ }
280
+ if (posted.kind === 'unknown') {
281
+ this.log.warn({ proofId, error: posted.error }, 'broadcast outcome unknown');
282
+ return record; // resolved via get_joint on the next attempt
283
+ }
284
+ if (isTransientPostError(posted.error)) {
285
+ // The hub is still working on it or lacks context: not a rejection.
286
+ this.log.info({ proofId, hubError: posted.error }, 'broadcast not final yet (transient hub answer)');
287
+ return record;
288
+ }
289
+ // Definite rejection — unless the unit is known after all (e.g. posted earlier).
290
+ const recheck = await hubCall(() => client.api.getJoint(proofId), this.hubTimeoutMs);
291
+ if (recheck.kind !== 'ok')
292
+ return record;
293
+ if (recheck.value.joint !== undefined) {
294
+ return this.move(record, 'accepted', { data: { via: 'get_joint after hub error' } });
295
+ }
296
+ this.log.warn({ proofId, hubError: posted.error }, 'unit rejected by the network');
297
+ return this.move(record, 'rejected', { lastError: posted.error });
298
+ }
299
+ /** After acceptance: stable and good, final-bad, or still waiting (rotated for recovery). */
300
+ async awaitFinality(client, record) {
301
+ const finality = await finalityOf({ hubTimeoutMs: this.hubTimeoutMs, historyProbeAddress: this.options.historyProbeAddress }, client, record.unitHash);
302
+ if (finality === 'good')
303
+ return this.move(record, 'stable_good');
304
+ if (finality === 'final_bad') {
305
+ this.log.error({ proofId: record.unitHash }, 'settled unit became final-bad');
306
+ return this.move(record, 'final_bad', { lastError: 'double spend (final-bad)' });
307
+ }
308
+ await this.options.store.touch(record.key);
309
+ return record;
310
+ }
311
+ async move(record, to, patch = {}) {
312
+ const next = await this.options.store.transition(record.key, [record.state], to, patch);
313
+ if (next === undefined) {
314
+ // Lost a race (another path moved it); continue from the stored state.
315
+ return (await this.options.store.get(record.key)) ?? record;
316
+ }
317
+ this.log.info({ proofId: record.unitHash, from: record.state, to }, 'settlement state changed');
318
+ return next;
319
+ }
320
+ respond(record, problem) {
321
+ const network = record.network;
322
+ const base = { payer: record.payer, network, transaction: record.unitHash };
323
+ const success = record.state === 'stable_good' ||
324
+ (record.state === 'accepted' && this.finality === 'accepted');
325
+ if (success)
326
+ return { success: true, ...base, amount: record.amount };
327
+ if (!TERMINAL_STATES.has(record.state)) {
328
+ return {
329
+ success: false,
330
+ errorReason: EXACT_SETTLE_REASONS.pending,
331
+ errorMessage: problem ?? `Settlement is ${record.state}`,
332
+ // x402: settlement_pending carries a non-empty transaction; the unit
333
+ // hash is deterministic even before the unit is broadcast.
334
+ ...base,
335
+ };
336
+ }
337
+ const reason = record.state === 'final_bad'
338
+ ? EXACT_SETTLE_REASONS.finalBad
339
+ : record.state === 'expired'
340
+ ? EXACT_SETTLE_REASONS.expired
341
+ : EXACT_SETTLE_REASONS.rejected;
342
+ return {
343
+ success: false,
344
+ errorReason: reason,
345
+ errorMessage: record.lastError ?? record.state,
346
+ ...base,
347
+ };
348
+ }
349
+ key(network, unitHash) {
350
+ return networkKey(getNetwork(network), 'unit', unitHash);
351
+ }
352
+ }
353
+ function unitHashOf(payload) {
354
+ const unit = payload.payload?.['unit'];
355
+ const hash = unit && typeof unit === 'object' ? unit.unit : undefined;
356
+ return typeof hash === 'string' && /^[A-Za-z0-9+/]{43}=$/.test(hash) ? hash : undefined;
357
+ }
358
+ function failure(network, reason, message) {
359
+ return { success: false, errorReason: reason, errorMessage: message, transaction: '', network };
360
+ }
361
+ //# sourceMappingURL=facilitator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facilitator.js","sourceRoot":"","sources":["../../src/exact/facilitator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import obyte from 'obyte';
2
+ /**
3
+ * Finality of a broadcast `exact` unit (ADR-0002) and classification of the
4
+ * hub's `post_joint` answers.
5
+ */
6
+ /**
7
+ * `light/get_history` requires a non-empty `addresses` list even when only
8
+ * `requested_joints` matter. This address (chash of a constant definition
9
+ * nobody can sign for) has no history, so the response stays small.
10
+ */
11
+ export declare const HISTORY_PROBE_ADDRESS: string;
12
+ /** Stable + good iff the unit's ball is in the proofchain without is_nonserial (ADR-0002). */
13
+ export declare function finalityOf(ctx: {
14
+ readonly hubTimeoutMs: number;
15
+ readonly historyProbeAddress?: string | undefined;
16
+ }, client: obyte.Client, unitHash: string): Promise<'good' | 'final_bad' | 'pending'>;
17
+ export declare function isTransientPostError(error: string): boolean;
18
+ //# sourceMappingURL=finality.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finality.d.ts","sourceRoot":"","sources":["../../src/exact/finality.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B;;;GAGG;AACH;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,QAA+D,CAAC;AAElG,8FAA8F;AAC9F,wBAAsB,UAAU,CAC9B,GAAG,EAAE;IAAE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,EACzF,MAAM,EAAE,KAAK,CAAC,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC,CAgB3C;AAgBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAG3D"}
@@ -0,0 +1,45 @@
1
+ import obyte from 'obyte';
2
+ import { hubCall } from '../hub/hub-call.js';
3
+ import { parseHistory } from '../hub/schemas.js';
4
+ /**
5
+ * Finality of a broadcast `exact` unit (ADR-0002) and classification of the
6
+ * hub's `post_joint` answers.
7
+ */
8
+ /**
9
+ * `light/get_history` requires a non-empty `addresses` list even when only
10
+ * `requested_joints` matter. This address (chash of a constant definition
11
+ * nobody can sign for) has no history, so the response stays small.
12
+ */
13
+ export const HISTORY_PROBE_ADDRESS = obyte.utils.getChash160(['sig', { pubkey: 'A'.repeat(44) }]);
14
+ /** Stable + good iff the unit's ball is in the proofchain without is_nonserial (ADR-0002). */
15
+ export async function finalityOf(ctx, client, unitHash) {
16
+ const res = await hubCall(() => client.api.getWitnesses().then((witnesses) => client.api.getHistory({
17
+ witnesses,
18
+ addresses: [ctx.historyProbeAddress ?? HISTORY_PROBE_ADDRESS],
19
+ requested_joints: [unitHash],
20
+ })), ctx.hubTimeoutMs);
21
+ if (res.kind !== 'ok')
22
+ return 'pending';
23
+ const ball = parseHistory(res.value)?.proofchainBalls.find((b) => b.unit === unitHash);
24
+ if (ball === undefined)
25
+ return 'pending';
26
+ return ball.is_nonserial === true ? 'final_bad' : 'good';
27
+ }
28
+ /**
29
+ * `post_joint` answers of ocore that do NOT mean the unit was rejected: the hub
30
+ * is validating it, knows it unverified, or lacks its parents / hash tree (it
31
+ * is behind). Anything else from the hub is a validation error (definite).
32
+ */
33
+ const TRANSIENT_POST_ERRORS = [
34
+ 'already handling this unit',
35
+ 'known unverified',
36
+ 'unknown parents',
37
+ 'need hash tree',
38
+ 'timeout',
39
+ 'temporarily',
40
+ ];
41
+ export function isTransientPostError(error) {
42
+ const e = error.toLowerCase();
43
+ return TRANSIENT_POST_ERRORS.some((t) => e.includes(t));
44
+ }
45
+ //# sourceMappingURL=finality.js.map