@obbyx/x402-obyte 0.0.0-stage → 0.1.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 (123) 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 +222 -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 +350 -0
  14. package/dist/batch/facilitator.js.map +1 -0
  15. package/dist/batch/gateway.d.ts +19 -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 +104 -0
  24. package/dist/batch/store.d.ts.map +1 -0
  25. package/dist/batch/store.js +192 -0
  26. package/dist/batch/store.js.map +1 -0
  27. package/dist/batch/watcher-protocol.d.ts +89 -0
  28. package/dist/batch/watcher-protocol.d.ts.map +1 -0
  29. package/dist/batch/watcher-protocol.js +80 -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 +77 -0
  60. package/dist/exact/facilitator.d.ts.map +1 -0
  61. package/dist/exact/facilitator.js +331 -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 +133 -0
  80. package/dist/exact/store.d.ts.map +1 -0
  81. package/dist/exact/store.js +212 -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 +18 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +18 -0
  98. package/dist/index.js.map +1 -0
  99. package/package.json +51 -3
  100. package/src/batch/client-store.ts +167 -0
  101. package/src/batch/client.ts +314 -0
  102. package/src/batch/facilitator.ts +469 -0
  103. package/src/batch/gateway.ts +20 -0
  104. package/src/batch/requirements.ts +108 -0
  105. package/src/batch/store.ts +343 -0
  106. package/src/batch/watcher-protocol.ts +87 -0
  107. package/src/binding/binding.ts +50 -0
  108. package/src/coins/composer.ts +159 -0
  109. package/src/coins/index.ts +9 -0
  110. package/src/coins/reservations.ts +139 -0
  111. package/src/coins/selection.ts +93 -0
  112. package/src/exact/client.ts +144 -0
  113. package/src/exact/facilitator-v1.ts +137 -0
  114. package/src/exact/facilitator.ts +451 -0
  115. package/src/exact/finality.ts +56 -0
  116. package/src/exact/ledger-checks.ts +113 -0
  117. package/src/exact/reasons.ts +25 -0
  118. package/src/exact/requirements.ts +109 -0
  119. package/src/exact/store.ts +391 -0
  120. package/src/hub/heartbeat.ts +18 -0
  121. package/src/hub/hub-call.ts +46 -0
  122. package/src/hub/schemas.ts +89 -0
  123. package/src/index.ts +110 -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,77 @@
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
+ private step;
73
+ private move;
74
+ private respond;
75
+ private key;
76
+ }
77
+ //# sourceMappingURL=facilitator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facilitator.d.ts","sourceRoot":"","sources":["../../src/exact/facilitator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,331 @@
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
+ export { EXACT_SETTLE_REASONS } from './reasons.js';
10
+ export { HISTORY_PROBE_ADDRESS, isTransientPostError } from './finality.js';
11
+ export class ExactObyteFacilitator {
12
+ options;
13
+ scheme = EXACT_SCHEME;
14
+ caipFamily = OBYTE_CAIP_FAMILY;
15
+ log;
16
+ finality;
17
+ hubTimeoutMs;
18
+ skew;
19
+ publishWindow;
20
+ maxLastBallAge;
21
+ now;
22
+ /** Serializes settle/resume per settlement key inside this process. */
23
+ inFlight = new Map();
24
+ constructor(options) {
25
+ this.options = options;
26
+ this.log = moduleLogger(options.logger, 'x402.exact', { scheme: EXACT_SCHEME });
27
+ this.finality = options.finality ?? 'stable';
28
+ this.hubTimeoutMs = options.hubTimeoutMs ?? 15_000;
29
+ this.skew = options.maxClockSkewSeconds ?? 120;
30
+ this.publishWindow = options.publishWindowSeconds ?? 300;
31
+ this.maxLastBallAge = options.maxLastBallAgeSeconds ?? 10_800;
32
+ this.now = options.now ?? (() => Math.floor(Date.now() / 1000));
33
+ }
34
+ getExtra(network) {
35
+ const assets = this.options.allowedAssets.get(network);
36
+ return { finality: this.finality, assets: assets === undefined ? [] : [...assets] };
37
+ }
38
+ /** The payer pays its own fees; the facilitator signs nothing in `exact`. */
39
+ getSigners() {
40
+ return [];
41
+ }
42
+ async verify(payload, requirements) {
43
+ return withLogContext({ scheme: EXACT_SCHEME, network: requirements.network }, async () => {
44
+ const checked = await this.check(payload, requirements);
45
+ if (!checked.ok) {
46
+ this.log.info({ reason: checked.reason, detail: checked.message }, 'verify rejected');
47
+ return { isValid: false, invalidReason: checked.reason, invalidMessage: checked.message };
48
+ }
49
+ const { facts } = checked.value;
50
+ this.log.info({ proofId: facts.unitHash, payer: facts.payer }, 'verify ok');
51
+ return { isValid: true, payer: facts.payer };
52
+ });
53
+ }
54
+ async settle(payload, requirements) {
55
+ return withLogContext({ scheme: EXACT_SCHEME, network: requirements.network }, async () => {
56
+ const network = requirements.network;
57
+ const unitHash = unitHashOf(payload);
58
+ if (unitHash === undefined) {
59
+ return failure(network, EXACT_SETTLE_REASONS.payload, 'Missing unit');
60
+ }
61
+ if (!isObyteNetwork(requirements.network)) {
62
+ return failure(network, 'invalid_network', 'Not an Obyte network');
63
+ }
64
+ const existing = await this.options.store.get(this.key(requirements.network, unitHash));
65
+ if (existing === undefined) {
66
+ const checked = await this.check(payload, requirements);
67
+ if (!checked.ok) {
68
+ this.log.info({ proofId: unitHash, reason: checked.reason }, 'settle rejected at verification');
69
+ return failure(network, checked.reason, checked.message);
70
+ }
71
+ const { facts, req } = checked.value;
72
+ const { created, record } = await this.options.store.claim({
73
+ key: this.key(requirements.network, facts.unitHash),
74
+ network: requirements.network,
75
+ unitHash: facts.unitHash,
76
+ binding: req.extra.binding,
77
+ payer: facts.payer,
78
+ payTo: req.payTo,
79
+ asset: req.asset,
80
+ amount: req.amount.toString(),
81
+ unitJson: JSON.stringify(payload.payload['unit']),
82
+ publishDeadline: this.now() + this.publishWindow,
83
+ });
84
+ this.log.info({ proofId: facts.unitHash, created, binding: req.extra.binding }, 'settlement claimed');
85
+ return this.drive(record);
86
+ }
87
+ // Idempotent resume: the same unit is bound to exactly one binding.
88
+ const binding = requirements.extra.binding;
89
+ if (existing.binding !== binding || existing.payTo !== requirements.payTo) {
90
+ return failure(network, 'invalid_payment_reused', 'This payment is bound to another operation');
91
+ }
92
+ return this.drive(existing);
93
+ });
94
+ }
95
+ /** Re-drives a non-terminal settlement (used by the recovery worker). */
96
+ resume(record) {
97
+ return withLogContext({ scheme: EXACT_SCHEME, network: record.network, proofId: record.unitHash }, () => this.drive(record));
98
+ }
99
+ // --- verification ---------------------------------------------------------
100
+ async check(payload, requirements) {
101
+ if (payload.x402Version !== 2)
102
+ return fail(EXACT_SETTLE_REASONS.version, 'Only x402 v2 is supported here');
103
+ if (!acceptedMatches(payload, requirements)) {
104
+ return fail(EXACT_SETTLE_REASONS.acceptedMismatch, 'Accepted requirements differ from the server requirements');
105
+ }
106
+ const parsed = parseExactRequirements(requirements);
107
+ if (!parsed.ok)
108
+ return fail(parsed.reason, parsed.message);
109
+ const req = parsed.value;
110
+ const now = this.now();
111
+ if (req.extra.validUntil < now)
112
+ return fail(EXACT_SETTLE_REASONS.quoteExpired, 'The payment offer has expired');
113
+ if (!this.options.allowedAssets.get(req.network.caip2)?.has(req.asset)) {
114
+ return fail(EXACT_REASONS.asset, 'Asset is not accepted by this facilitator');
115
+ }
116
+ const client = this.options.clients.get(req.network.caip2);
117
+ if (client === undefined)
118
+ return fail('invalid_network', 'Network is not served');
119
+ const unit = payload.payload['unit'];
120
+ const expectation = {
121
+ network: req.network,
122
+ payTo: req.payTo,
123
+ asset: req.asset,
124
+ amount: req.amount,
125
+ binding: req.extra.binding,
126
+ quoteId: req.extra.quoteId,
127
+ ...(this.options.facilitatorAddresses
128
+ ? { facilitatorAddresses: this.options.facilitatorAddresses }
129
+ : {}),
130
+ };
131
+ let local = validateExactUnit(unit, expectation);
132
+ if (!local.ok && local.reason === EXACT_REASONS.definitionRequired) {
133
+ const definition = await this.fetchDefinition(client, unit);
134
+ if (!definition.ok)
135
+ return definition;
136
+ local = validateExactUnit(unit, expectation, { authorDefinition: definition.value });
137
+ }
138
+ if (!local.ok)
139
+ return fail(local.reason, local.message);
140
+ const facts = local.value;
141
+ // Clock sanity: the unit was composed recently.
142
+ if (Math.abs(facts.timestamp - now) > this.skew + req.maxTimeoutSeconds) {
143
+ return fail(EXACT_SETTLE_REASONS.stale, 'Unit timestamp is outside the acceptance window');
144
+ }
145
+ // payTo must be a plain address: a payment to an autonomous agent triggers
146
+ // it, and the AA may bounce the funds back to the payer (the unit is still
147
+ // valid and final, so the seller would serve without being paid).
148
+ const recipient = await this.recipientIsNotAa(client, req.payTo);
149
+ if (!recipient.ok)
150
+ return recipient;
151
+ const ledger = await checkLedger({
152
+ hubTimeoutMs: this.hubTimeoutMs,
153
+ maxLastBallAgeSeconds: this.maxLastBallAge,
154
+ now: this.now,
155
+ }, client, req, facts, unit);
156
+ if (!ledger.ok)
157
+ return ledger;
158
+ return { ok: true, value: { facts, req } };
159
+ }
160
+ /** Known plain (non-AA) recipients; an address can never turn into an AA. */
161
+ plainRecipients = new Set();
162
+ async recipientIsNotAa(client, payTo) {
163
+ if (this.plainRecipients.has(payTo))
164
+ return { ok: true, value: null };
165
+ const res = await hubCall(() => client.api.getDefinition(payTo), this.hubTimeoutMs);
166
+ if (res.kind !== 'ok')
167
+ return fail(EXACT_SETTLE_REASONS.ledger, `Cannot read the payTo definition: ${res.error}`);
168
+ const definition = res.value;
169
+ if (Array.isArray(definition) && definition[0] === 'autonomous agent') {
170
+ return fail(EXACT_SETTLE_REASONS.payToAa, 'payTo is an autonomous agent');
171
+ }
172
+ // An unused address has no definition yet (null): fine, but not cached.
173
+ if (definition !== null && definition !== undefined)
174
+ this.plainRecipients.add(payTo);
175
+ return { ok: true, value: null };
176
+ }
177
+ async fetchDefinition(client, unit) {
178
+ const address = unit.authors?.[0]?.address;
179
+ if (typeof address !== 'string')
180
+ return fail(EXACT_REASONS.unsupported, 'Malformed author');
181
+ const res = await hubCall(() => client.api.getDefinition(address), this.hubTimeoutMs);
182
+ if (res.kind !== 'ok')
183
+ return fail(EXACT_SETTLE_REASONS.ledger, `Cannot read definition: ${res.error}`);
184
+ if (!isSigDefinition(res.value)) {
185
+ return fail(EXACT_REASONS.definition, 'Payer definition is unknown or not a single-sig definition');
186
+ }
187
+ return { ok: true, value: res.value };
188
+ }
189
+ // --- settlement state machine --------------------------------------------------
190
+ drive(record) {
191
+ const running = this.inFlight.get(record.key);
192
+ if (running !== undefined)
193
+ return running;
194
+ const promise = this.step(record).finally(() => this.inFlight.delete(record.key));
195
+ this.inFlight.set(record.key, promise);
196
+ return promise;
197
+ }
198
+ async step(initial) {
199
+ const store = this.options.store;
200
+ const client = this.options.clients.get(initial.network);
201
+ let record = (await store.get(initial.key)) ?? initial;
202
+ if (client === undefined)
203
+ return this.respond(record, 'Network is not served');
204
+ const t = this.hubTimeoutMs;
205
+ if (record.state === 'claimed' || record.state === 'broadcasting') {
206
+ // Is it already on the ledger (we or someone else published it)?
207
+ const known = await hubCall(() => client.api.getJoint(record.unitHash), t);
208
+ if (known.kind === 'ok' && known.value.joint !== undefined) {
209
+ record = await this.move(record, 'accepted', { data: { via: 'get_joint' } });
210
+ }
211
+ else if (known.kind !== 'ok') {
212
+ await store.event({
213
+ key: record.key,
214
+ kind: 'hub_unavailable',
215
+ data: { op: 'get_joint', error: known.error },
216
+ });
217
+ return this.respond(record);
218
+ }
219
+ else if (this.now() > record.publishDeadline) {
220
+ record = await this.move(record, 'expired', { lastError: 'publication window closed' });
221
+ return this.respond(record);
222
+ }
223
+ else {
224
+ if (record.state === 'claimed')
225
+ record = await this.move(record, 'broadcasting');
226
+ if (record.unitJson === null)
227
+ return this.respond(record, 'Unit body is no longer stored');
228
+ const unit = JSON.parse(record.unitJson);
229
+ const posted = await hubCall(() => client.api.postJoint({ unit }), t);
230
+ await store.event({ key: record.key, kind: 'post_joint', data: { outcome: posted.kind } });
231
+ if (posted.kind === 'ok') {
232
+ record = await this.move(record, 'accepted', {
233
+ incrementAttempts: true,
234
+ data: { response: posted.value },
235
+ });
236
+ }
237
+ else if (posted.kind === 'hub_error' && isTransientPostError(posted.error)) {
238
+ // The hub is still working on it or lacks context: not a rejection.
239
+ // Stay in broadcasting; the next attempt resolves it via get_joint.
240
+ this.log.info({ proofId: record.unitHash, hubError: posted.error }, 'broadcast not final yet (transient hub answer)');
241
+ return this.respond(record);
242
+ }
243
+ else if (posted.kind === 'hub_error') {
244
+ // Definite rejection — unless the unit is known after all (e.g. posted earlier).
245
+ const recheck = await hubCall(() => client.api.getJoint(record.unitHash), t);
246
+ if (recheck.kind === 'ok' && recheck.value.joint !== undefined) {
247
+ record = await this.move(record, 'accepted', {
248
+ data: { via: 'get_joint after hub error' },
249
+ });
250
+ }
251
+ else if (recheck.kind === 'ok') {
252
+ record = await this.move(record, 'rejected', {
253
+ lastError: posted.error,
254
+ incrementAttempts: true,
255
+ });
256
+ this.log.warn({ proofId: record.unitHash, hubError: posted.error }, 'unit rejected by the network');
257
+ return this.respond(record);
258
+ }
259
+ else {
260
+ return this.respond(record);
261
+ }
262
+ }
263
+ else {
264
+ // Unknown outcome: stay in broadcasting; the next attempt resolves it via get_joint.
265
+ this.log.warn({ proofId: record.unitHash, error: posted.error }, 'broadcast outcome unknown');
266
+ return this.respond(record);
267
+ }
268
+ }
269
+ }
270
+ if (record.state === 'accepted') {
271
+ const finality = await finalityOf({ hubTimeoutMs: this.hubTimeoutMs, historyProbeAddress: this.options.historyProbeAddress }, client, record.unitHash);
272
+ if (finality === 'good')
273
+ record = await this.move(record, 'stable_good');
274
+ else if (finality === 'final_bad') {
275
+ record = await this.move(record, 'final_bad', { lastError: 'double spend (final-bad)' });
276
+ this.log.error({ proofId: record.unitHash }, 'settled unit became final-bad');
277
+ }
278
+ }
279
+ return this.respond(record);
280
+ }
281
+ async move(record, to, patch = {}) {
282
+ const next = await this.options.store.transition(record.key, [record.state], to, patch);
283
+ if (next === undefined) {
284
+ // Lost a race (another path moved it); continue from the stored state.
285
+ return (await this.options.store.get(record.key)) ?? record;
286
+ }
287
+ this.log.info({ proofId: record.unitHash, from: record.state, to }, 'settlement state changed');
288
+ return next;
289
+ }
290
+ respond(record, problem) {
291
+ const network = record.network;
292
+ const base = { payer: record.payer, network, transaction: record.unitHash };
293
+ const success = record.state === 'stable_good' ||
294
+ (record.state === 'accepted' && this.finality === 'accepted');
295
+ if (success)
296
+ return { success: true, ...base, amount: record.amount };
297
+ if (!TERMINAL_STATES.has(record.state)) {
298
+ return {
299
+ success: false,
300
+ errorReason: EXACT_SETTLE_REASONS.pending,
301
+ errorMessage: problem ?? `Settlement is ${record.state}`,
302
+ // x402: settlement_pending carries a non-empty transaction; the unit
303
+ // hash is deterministic even before the unit is broadcast.
304
+ ...base,
305
+ };
306
+ }
307
+ const reason = record.state === 'final_bad'
308
+ ? EXACT_SETTLE_REASONS.finalBad
309
+ : record.state === 'expired'
310
+ ? EXACT_SETTLE_REASONS.expired
311
+ : EXACT_SETTLE_REASONS.rejected;
312
+ return {
313
+ success: false,
314
+ errorReason: reason,
315
+ errorMessage: record.lastError ?? record.state,
316
+ ...base,
317
+ };
318
+ }
319
+ key(network, unitHash) {
320
+ return networkKey(getNetwork(network), 'unit', unitHash);
321
+ }
322
+ }
323
+ function unitHashOf(payload) {
324
+ const unit = payload.payload?.['unit'];
325
+ const hash = unit && typeof unit === 'object' ? unit.unit : undefined;
326
+ return typeof hash === 'string' && /^[A-Za-z0-9+/]{43}=$/.test(hash) ? hash : undefined;
327
+ }
328
+ function failure(network, reason, message) {
329
+ return { success: false, errorReason: reason, errorMessage: message, transaction: '', network };
330
+ }
331
+ //# 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
@@ -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"}