@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,217 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ import { ObbyxError } from '@obbyx/obyte';
3
+ export const TERMINAL_STATES = new Set([
4
+ 'stable_good',
5
+ 'final_bad',
6
+ 'rejected',
7
+ 'expired',
8
+ ]);
9
+ export class StoreLockedError extends ObbyxError {
10
+ constructor(path, cause) {
11
+ super('store_locked', `Database ${path} is in use by another facilitator process (one instance per database file)`, { cause, details: { path } });
12
+ }
13
+ }
14
+ const SCHEMA = `
15
+ CREATE TABLE IF NOT EXISTS exact_settlements (
16
+ key TEXT PRIMARY KEY,
17
+ network TEXT NOT NULL,
18
+ unit_hash TEXT NOT NULL,
19
+ binding TEXT NOT NULL,
20
+ payer TEXT NOT NULL,
21
+ pay_to TEXT NOT NULL,
22
+ asset TEXT NOT NULL,
23
+ amount TEXT NOT NULL,
24
+ state TEXT NOT NULL,
25
+ unit_json TEXT,
26
+ publish_deadline INTEGER NOT NULL,
27
+ attempts INTEGER NOT NULL DEFAULT 0,
28
+ last_error TEXT,
29
+ created_at INTEGER NOT NULL,
30
+ updated_at INTEGER NOT NULL
31
+ ) STRICT;
32
+ CREATE INDEX IF NOT EXISTS exact_settlements_active ON exact_settlements(state)
33
+ WHERE state IN ('claimed', 'broadcasting', 'accepted');
34
+ CREATE TABLE IF NOT EXISTS events (
35
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
36
+ ts INTEGER NOT NULL,
37
+ key TEXT NOT NULL,
38
+ kind TEXT NOT NULL,
39
+ from_state TEXT,
40
+ to_state TEXT,
41
+ data TEXT
42
+ ) STRICT;
43
+ CREATE INDEX IF NOT EXISTS events_key ON events(key);
44
+ `;
45
+ export class SqliteSettlementStore {
46
+ db;
47
+ now;
48
+ /**
49
+ * @param path SQLite file, or `:memory:` for tests.
50
+ * @param now Clock in unix seconds (injectable for tests).
51
+ */
52
+ constructor(path, now = () => Math.floor(Date.now() / 1000)) {
53
+ this.now = now;
54
+ this.db = new DatabaseSync(path);
55
+ try {
56
+ this.db.exec('PRAGMA busy_timeout = 0');
57
+ this.db.exec('PRAGMA journal_mode = WAL');
58
+ this.db.exec('PRAGMA synchronous = FULL');
59
+ // Exclusive lock for the lifetime of the connection: a second process
60
+ // fails on its first write instead of racing us.
61
+ this.db.exec('PRAGMA locking_mode = EXCLUSIVE');
62
+ this.db.exec('BEGIN IMMEDIATE');
63
+ this.db.exec(SCHEMA);
64
+ this.db.exec('COMMIT');
65
+ }
66
+ catch (err) {
67
+ this.db.close();
68
+ if (isBusy(err))
69
+ throw new StoreLockedError(path, err);
70
+ throw err;
71
+ }
72
+ }
73
+ async close() {
74
+ this.db.close();
75
+ }
76
+ /** The exclusive connection, shared with other facilitator stores (e.g. BatchStore). */
77
+ get database() {
78
+ return this.db;
79
+ }
80
+ async get(key) {
81
+ return this.getSync(key);
82
+ }
83
+ getSync(key) {
84
+ const row = this.db.prepare('SELECT * FROM exact_settlements WHERE key = ?').get(key);
85
+ return row === undefined ? undefined : toRecord(row);
86
+ }
87
+ /**
88
+ * Inserts a new settlement in state `claimed` unless the key exists.
89
+ * Returns the stored record and whether this call created it.
90
+ */
91
+ async claim(input) {
92
+ return this.tx(() => {
93
+ const existing = this.getSync(input.key);
94
+ if (existing !== undefined)
95
+ return { created: false, record: existing };
96
+ const ts = this.now();
97
+ this.db
98
+ .prepare(`INSERT INTO exact_settlements
99
+ (key, network, unit_hash, binding, payer, pay_to, asset, amount, state, unit_json,
100
+ publish_deadline, attempts, created_at, updated_at)
101
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'claimed', ?, ?, 0, ?, ?)`)
102
+ .run(input.key, input.network, input.unitHash, input.binding, input.payer, input.payTo, input.asset, input.amount, input.unitJson, input.publishDeadline, ts, ts);
103
+ this.insertEvent({ key: input.key, kind: 'claimed', from: null, to: 'claimed' }, ts);
104
+ return { created: true, record: this.mustGet(input.key) };
105
+ });
106
+ }
107
+ /**
108
+ * Compare-and-set transition. Returns the new record, or `undefined` if the
109
+ * current state is not one of `from` (someone else moved it first).
110
+ */
111
+ async transition(key, from, to, patch = {}) {
112
+ return this.tx(() => {
113
+ const current = this.getSync(key);
114
+ if (current === undefined || !from.includes(current.state))
115
+ return undefined;
116
+ const ts = this.now();
117
+ this.db
118
+ .prepare(`UPDATE exact_settlements
119
+ SET state = ?, last_error = ?, attempts = attempts + ?, updated_at = ?
120
+ WHERE key = ? AND state = ?`)
121
+ .run(to, patch.lastError === undefined ? current.lastError : patch.lastError, patch.incrementAttempts === true ? 1 : 0, ts, key, current.state);
122
+ this.insertEvent({
123
+ key,
124
+ kind: 'transition',
125
+ from: current.state,
126
+ to,
127
+ ...(patch.data ? { data: patch.data } : {}),
128
+ }, ts);
129
+ return this.mustGet(key);
130
+ });
131
+ }
132
+ /** Records a non-transition event (e.g. a retry) in the payment journal. */
133
+ async event(event) {
134
+ this.insertEvent(event, this.now());
135
+ }
136
+ /** Non-terminal settlements, oldest first — resumed by the recovery worker. */
137
+ async touch(key) {
138
+ this.db
139
+ .prepare('UPDATE exact_settlements SET updated_at = ? WHERE key = ?')
140
+ .run(this.now(), key);
141
+ }
142
+ async listActive(limit = 100) {
143
+ const rows = this.db
144
+ .prepare(`SELECT * FROM exact_settlements
145
+ WHERE state IN ('claimed', 'broadcasting', 'accepted')
146
+ ORDER BY updated_at ASC LIMIT ?`)
147
+ .all(limit);
148
+ return rows.map(toRecord);
149
+ }
150
+ async events(key) {
151
+ const rows = this.db
152
+ .prepare('SELECT kind, from_state, to_state, data FROM events WHERE key = ? ORDER BY id')
153
+ .all(key);
154
+ return rows.map((r) => ({
155
+ kind: r.kind,
156
+ from: r.from_state,
157
+ to: r.to_state,
158
+ data: r.data === null ? null : JSON.parse(r.data),
159
+ }));
160
+ }
161
+ /** Drops signed unit bodies of terminal settlements older than `olderThan` (unix s). */
162
+ async pruneUnitBodies(olderThan) {
163
+ const res = this.db
164
+ .prepare(`UPDATE exact_settlements SET unit_json = NULL
165
+ WHERE unit_json IS NOT NULL AND updated_at < ?
166
+ AND state IN ('stable_good', 'final_bad', 'rejected', 'expired')`)
167
+ .run(olderThan);
168
+ return Number(res.changes);
169
+ }
170
+ insertEvent(event, ts) {
171
+ this.db
172
+ .prepare('INSERT INTO events (ts, key, kind, from_state, to_state, data) VALUES (?, ?, ?, ?, ?, ?)')
173
+ .run(ts, event.key, event.kind, event.from ?? null, event.to ?? null, event.data === undefined ? null : JSON.stringify(event.data));
174
+ }
175
+ mustGet(key) {
176
+ const record = this.getSync(key);
177
+ if (record === undefined)
178
+ throw new ObbyxError('store_inconsistent', `Missing settlement ${key}`);
179
+ return record;
180
+ }
181
+ tx(fn) {
182
+ this.db.exec('BEGIN IMMEDIATE');
183
+ try {
184
+ const result = fn();
185
+ this.db.exec('COMMIT');
186
+ return result;
187
+ }
188
+ catch (err) {
189
+ this.db.exec('ROLLBACK');
190
+ throw err;
191
+ }
192
+ }
193
+ }
194
+ function toRecord(row) {
195
+ return {
196
+ key: row.key,
197
+ network: row.network,
198
+ unitHash: row.unit_hash,
199
+ binding: row.binding,
200
+ payer: row.payer,
201
+ payTo: row.pay_to,
202
+ asset: row.asset,
203
+ amount: row.amount,
204
+ state: row.state,
205
+ unitJson: row.unit_json,
206
+ publishDeadline: row.publish_deadline,
207
+ attempts: row.attempts,
208
+ lastError: row.last_error,
209
+ createdAt: row.created_at,
210
+ updatedAt: row.updated_at,
211
+ };
212
+ }
213
+ function isBusy(err) {
214
+ const message = err instanceof Error ? err.message : String(err);
215
+ return /database is locked|SQLITE_BUSY/i.test(message);
216
+ }
217
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/exact/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAqB1C,MAAM,CAAC,MAAM,eAAe,GAAiC,IAAI,GAAG,CAAC;IACnE,aAAa;IACb,WAAW;IACX,UAAU;IACV,SAAS;CACV,CAAC,CAAC;AA2EH,MAAM,OAAO,gBAAiB,SAAQ,UAAU;IAC9C,YAAY,IAAY,EAAE,KAAc;QACtC,KAAK,CACH,cAAc,EACd,YAAY,IAAI,4EAA4E,EAC5F,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,CAC7B,CAAC;IACJ,CAAC;CACF;AAoBD,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8Bd,CAAC;AAEF,MAAM,OAAO,qBAAqB;IACf,EAAE,CAAe;IACjB,GAAG,CAAe;IAEnC;;;OAGG;IACH,YAAY,IAAY,EAAE,MAAoB,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAC/E,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,EAAE,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;YACxC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YAC1C,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YAC1C,sEAAsE;YACtE,iDAAiD;YACjD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;YAChD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAChC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,MAAM,CAAC,GAAG,CAAC;gBAAE,MAAM,IAAI,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACvD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;IAED,wFAAwF;IACxF,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,EAAE,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAEO,OAAO,CAAC,GAAW;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC,GAAG,CAAC,GAAG,CACnE,CAAC;QAClB,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,KAAoB;QAC9B,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE;YAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzC,IAAI,QAAQ,KAAK,SAAS;gBAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;YACxE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,EAAE;iBACJ,OAAO,CACN;;;qEAG2D,CAC5D;iBACA,GAAG,CACF,KAAK,CAAC,GAAG,EACT,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,QAAQ,EACd,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,QAAQ,EACd,KAAK,CAAC,eAAe,EACrB,EAAE,EACF,EAAE,CACH,CAAC;YACJ,IAAI,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;YACrF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CACd,GAAW,EACX,IAAgC,EAChC,EAAmB,EACnB,QAAyB,EAAE;QAE3B,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE;YAClB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAC;YAC7E,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,EAAE;iBACJ,OAAO,CACN;;uCAE6B,CAC9B;iBACA,GAAG,CACF,EAAE,EACF,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EACnE,KAAK,CAAC,iBAAiB,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACxC,EAAE,EACF,GAAG,EACH,OAAO,CAAC,KAAK,CACd,CAAC;YACJ,IAAI,CAAC,WAAW,CACd;gBACE,GAAG;gBACH,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,OAAO,CAAC,KAAK;gBACnB,EAAE;gBACF,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5C,EACD,EAAE,CACH,CAAC;YACF,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,KAAK,CAAC,KAAsB;QAChC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,+EAA+E;IAC/E,KAAK,CAAC,KAAK,CAAC,GAAW;QACrB,IAAI,CAAC,EAAE;aACJ,OAAO,CAAC,2DAA2D,CAAC;aACpE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;aACjB,OAAO,CACN;;0CAEkC,CACnC;aACA,GAAG,CAAC,KAAK,CAAqB,CAAC;QAClC,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,MAAM,CACV,GAAW;QAEX,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;aACjB,OAAO,CAAC,+EAA+E,CAAC;aACxF,GAAG,CAAC,GAAG,CAKP,CAAC;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACtB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,CAAC,CAAC,UAAU;YAClB,EAAE,EAAE,CAAC,CAAC,QAAQ;YACd,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAa;SAC/D,CAAC,CAAC,CAAC;IACN,CAAC;IAED,wFAAwF;IACxF,KAAK,CAAC,eAAe,CAAC,SAAiB;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE;aAChB,OAAO,CACN;;6EAEqE,CACtE;aACA,GAAG,CAAC,SAAS,CAAC,CAAC;QAClB,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAEO,WAAW,CAAC,KAAsB,EAAE,EAAU;QACpD,IAAI,CAAC,EAAE;aACJ,OAAO,CACN,0FAA0F,CAC3F;aACA,GAAG,CACF,EAAE,EACF,KAAK,CAAC,GAAG,EACT,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,IAAI,IAAI,IAAI,EAClB,KAAK,CAAC,EAAE,IAAI,IAAI,EAChB,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAC7D,CAAC;IACN,CAAC;IAEO,OAAO,CAAC,GAAW;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,SAAS;YACtB,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,sBAAsB,GAAG,EAAE,CAAC,CAAC;QAC1E,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,EAAE,CAAI,EAAW;QACvB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,EAAE,EAAE,CAAC;YACpB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzB,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;CACF;AAED,SAAS,QAAQ,CAAC,GAAQ;IACxB,OAAO;QACL,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,KAAK,EAAE,GAAG,CAAC,MAAM;QACjB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,eAAe,EAAE,GAAG,CAAC,gBAAgB;QACrC,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,GAAY;IAC1B,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,OAAO,iCAAiC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type obyte from 'obyte';
2
+ /**
3
+ * Keeps an obyte.js hub connection alive. obyte.js does not schedule
4
+ * heartbeats itself: the application must call `client.api.heartbeat()`
5
+ * periodically (its WSClient then skips the call if traffic was recent,
6
+ * and closes a connection whose heartbeat goes unanswered, letting
7
+ * `reconnect: true` re-establish it). Hubs drop idle peers without this.
8
+ *
9
+ * Returns a function that stops the timer.
10
+ */
11
+ export declare function startHeartbeat(client: obyte.Client, intervalMs?: number): () => void;
12
+ //# sourceMappingURL=heartbeat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../../src/hub/heartbeat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,SAAS,GAAG,MAAM,IAAI,CAMpF"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Keeps an obyte.js hub connection alive. obyte.js does not schedule
3
+ * heartbeats itself: the application must call `client.api.heartbeat()`
4
+ * periodically (its WSClient then skips the call if traffic was recent,
5
+ * and closes a connection whose heartbeat goes unanswered, letting
6
+ * `reconnect: true` re-establish it). Hubs drop idle peers without this.
7
+ *
8
+ * Returns a function that stops the timer.
9
+ */
10
+ export function startHeartbeat(client, intervalMs = 10_000) {
11
+ const timer = setInterval(() => {
12
+ client.api.heartbeat().catch(() => undefined); // closed/reconnecting: the next tick retries
13
+ }, intervalMs);
14
+ timer.unref();
15
+ return () => clearInterval(timer);
16
+ }
17
+ //# sourceMappingURL=heartbeat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../src/hub/heartbeat.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,MAAoB,EAAE,UAAU,GAAG,MAAM;IACtE,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,6CAA6C;IAC9F,CAAC,EAAE,UAAU,CAAC,CAAC;IACf,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Outcome of one obyte.js hub request (ADR-0006, invariant I7).
3
+ *
4
+ * obyte.js requests have no timeout. It rejects with the hub's error value
5
+ * (usually a string) for definite hub errors, and with an `Error` for transport
6
+ * failures. A timeout or transport failure is an UNKNOWN outcome — for
7
+ * `postJoint` the unit may have been accepted.
8
+ */
9
+ export type HubOutcome<T> = {
10
+ readonly kind: 'ok';
11
+ readonly value: T;
12
+ } | {
13
+ readonly kind: 'hub_error';
14
+ readonly error: string;
15
+ } | {
16
+ readonly kind: 'unknown';
17
+ readonly error: string;
18
+ };
19
+ export declare function hubCall<T>(request: () => Promise<T>, timeoutMs: number): Promise<HubOutcome<T>>;
20
+ //# sourceMappingURL=hub-call.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hub-call.d.ts","sourceRoot":"","sources":["../../src/hub/hub-call.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAC1C;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD,wBAAsB,OAAO,CAAC,CAAC,EAC7B,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAqBxB"}
@@ -0,0 +1,30 @@
1
+ export async function hubCall(request, timeoutMs) {
2
+ let timer;
3
+ try {
4
+ const value = await Promise.race([
5
+ request(),
6
+ new Promise((_, rejectTimeout) => {
7
+ timer = setTimeout(() => rejectTimeout(new Error(`hub request timed out after ${timeoutMs} ms`)), timeoutMs);
8
+ }),
9
+ ]);
10
+ return { kind: 'ok', value };
11
+ }
12
+ catch (err) {
13
+ if (err instanceof Error || err === null || err === undefined) {
14
+ return { kind: 'unknown', error: err instanceof Error ? err.message : 'no error value' };
15
+ }
16
+ return { kind: 'hub_error', error: typeof err === 'string' ? err : safeJson(err) };
17
+ }
18
+ finally {
19
+ clearTimeout(timer);
20
+ }
21
+ }
22
+ function safeJson(value) {
23
+ try {
24
+ return JSON.stringify(value);
25
+ }
26
+ catch {
27
+ return String(value);
28
+ }
29
+ }
30
+ //# sourceMappingURL=hub-call.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hub-call.js","sourceRoot":"","sources":["../../src/hub/hub-call.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,OAAyB,EACzB,SAAiB;IAEjB,IAAI,KAAiC,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAC/B,OAAO,EAAE;YACT,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,aAAa,EAAE,EAAE;gBACtC,KAAK,GAAG,UAAU,CAChB,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,+BAA+B,SAAS,KAAK,CAAC,CAAC,EAC7E,SAAS,CACV,CAAC;YACJ,CAAC,CAAC;SACH,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC9D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC;QAC3F,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;IACrF,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ import type { HistoryJoint } from '../coins/index.js';
3
+ export declare const paymentPayloadSchema: z.ZodObject<{
4
+ asset: z.ZodOptional<z.ZodString>;
5
+ inputs: z.ZodOptional<z.ZodArray<z.ZodObject<{
6
+ unit: z.ZodOptional<z.ZodString>;
7
+ message_index: z.ZodOptional<z.ZodNumber>;
8
+ output_index: z.ZodOptional<z.ZodNumber>;
9
+ }, z.core.$loose>>>;
10
+ outputs: z.ZodOptional<z.ZodArray<z.ZodObject<{
11
+ address: z.ZodString;
12
+ amount: z.ZodNumber;
13
+ }, z.core.$loose>>>;
14
+ }, z.core.$loose>;
15
+ export declare const ledgerUnitSchema: z.ZodObject<{
16
+ unit: z.ZodString;
17
+ timestamp: z.ZodOptional<z.ZodNumber>;
18
+ main_chain_index: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
19
+ authors: z.ZodOptional<z.ZodArray<z.ZodObject<{
20
+ address: z.ZodString;
21
+ }, z.core.$loose>>>;
22
+ messages: z.ZodDefault<z.ZodArray<z.ZodObject<{
23
+ app: z.ZodString;
24
+ payload: z.ZodOptional<z.ZodUnknown>;
25
+ }, z.core.$loose>>>;
26
+ }, z.core.$loose>;
27
+ export type LedgerUnit = HistoryJoint['unit'];
28
+ /** A unit from `get_joint` (undefined when malformed). */
29
+ export declare function parseLedgerUnit(raw: unknown): LedgerUnit | undefined;
30
+ export interface ProofchainBall {
31
+ readonly unit: string;
32
+ readonly is_nonserial?: boolean | undefined;
33
+ }
34
+ /** `light/get_history` (undefined when malformed). */
35
+ export declare function parseHistory(raw: unknown): {
36
+ joints: HistoryJoint[];
37
+ proofchainBalls: ProofchainBall[];
38
+ } | undefined;
39
+ /** `light/get_aa_state_vars`: a plain record (undefined when malformed). */
40
+ export declare function parseStateVars(raw: unknown): Record<string, unknown> | undefined;
41
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/hub/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAStD,eAAO,MAAM,oBAAoB;;;;;;;;;;;iBAgBvB,CAAC;AAYX,eAAO,MAAM,gBAAgB;;;;;;;;;;;iBAQnB,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAa9C,0DAA0D;AAC1D,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAGpE;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC7C;AAED,sDAAsD;AACtD,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,GACX;IAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAAC,eAAe,EAAE,cAAc,EAAE,CAAA;CAAE,GAAG,SAAS,CAO3E;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAGhF"}
@@ -0,0 +1,71 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Shapes of the hub (light vendor) answers we rely on. The hub is trusted for
4
+ * ledger reads (ADR-0001), but a malformed or unexpected answer must fail
5
+ * closed ("ledger unavailable"), never crash or be half-read.
6
+ */
7
+ const safeAmount = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
8
+ export const paymentPayloadSchema = z
9
+ .object({
10
+ asset: z.string().optional(),
11
+ inputs: z
12
+ .array(z
13
+ .object({
14
+ unit: z.string().optional(),
15
+ message_index: z.number().int().optional(),
16
+ output_index: z.number().int().optional(),
17
+ })
18
+ .loose())
19
+ .optional(),
20
+ outputs: z.array(z.object({ address: z.string(), amount: safeAmount }).loose()).optional(),
21
+ })
22
+ .loose();
23
+ /** A message; payment payloads are validated (positions of messages/outputs are kept). */
24
+ const messageSchema = z
25
+ .object({ app: z.string(), payload: z.unknown().optional() })
26
+ .loose()
27
+ .superRefine((m, ctx) => {
28
+ if (m.app === 'payment' && !paymentPayloadSchema.safeParse(m.payload).success) {
29
+ ctx.addIssue({ code: 'custom', message: 'malformed payment payload' });
30
+ }
31
+ });
32
+ export const ledgerUnitSchema = z
33
+ .object({
34
+ unit: z.string(),
35
+ timestamp: z.number().optional(),
36
+ main_chain_index: z.number().nullable().optional(),
37
+ authors: z.array(z.object({ address: z.string() }).loose()).optional(),
38
+ messages: z.array(messageSchema).default([]),
39
+ })
40
+ .loose();
41
+ const historySchema = z
42
+ .object({
43
+ joints: z
44
+ .array(z.object({ unit: ledgerUnitSchema, ball: z.string().optional() }).loose())
45
+ .default([]),
46
+ proofchain_balls: z
47
+ .array(z.object({ unit: z.string(), is_nonserial: z.boolean().optional() }).loose())
48
+ .default([]),
49
+ })
50
+ .loose();
51
+ /** A unit from `get_joint` (undefined when malformed). */
52
+ export function parseLedgerUnit(raw) {
53
+ const parsed = ledgerUnitSchema.safeParse(raw);
54
+ return parsed.success ? parsed.data : undefined;
55
+ }
56
+ /** `light/get_history` (undefined when malformed). */
57
+ export function parseHistory(raw) {
58
+ const parsed = historySchema.safeParse(raw);
59
+ if (!parsed.success)
60
+ return undefined;
61
+ return {
62
+ joints: parsed.data.joints,
63
+ proofchainBalls: parsed.data.proofchain_balls,
64
+ };
65
+ }
66
+ /** `light/get_aa_state_vars`: a plain record (undefined when malformed). */
67
+ export function parseStateVars(raw) {
68
+ const parsed = z.record(z.string(), z.unknown()).safeParse(raw);
69
+ return parsed.success ? parsed.data : undefined;
70
+ }
71
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/hub/schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export { type HubOutcome, hubCall } from './hub/hub-call.js';
2
+ export { EXACT_SCHEME, type ExactExtra, type ParsedExactRequirements, acceptedMatches, canonical, exactExtraSchema, parseExactRequirements, } from './exact/requirements.js';
3
+ export { type NewSettlement, type SettlementEvent, type SettlementRecord, type SettlementState, type SettlementStore, SqliteSettlementStore, type TransitionPatch, StoreLockedError, TERMINAL_STATES, } from './exact/store.js';
4
+ export { EXACT_SETTLE_REASONS, HISTORY_PROBE_ADDRESS, ExactObyteFacilitator, type ExactObyteFacilitatorOptions, type FinalityPolicy, } from './exact/facilitator.js';
5
+ export { ExactObyteClient, type ExactObyteClientOptions } from './exact/client.js';
6
+ export { type WatcherGateway, type WatcherHealth } from './batch/gateway.js';
7
+ export { BATCH_REASONS, BATCH_SCHEME, type BatchExtra, type ParsedBatchRequirements, type VoucherMessage, batchExtraSchema, parseBatchRequirements, voucherMessageSchema, } from './batch/requirements.js';
8
+ export { type AppendInput, type AppendResult, type BatchStore, SqliteBatchStore, type ChannelRow, type CommitmentRow, type CommitmentState, } from './batch/store.js';
9
+ export { BatchObyteFacilitator, type BatchObyteFacilitatorOptions } from './batch/facilitator.js';
10
+ export { type ClientMessage, type CommitmentMessage, type ServerMessage, WATCHER_LOGIN_PURPOSE, clientMessageSchema, commitmentMessageSchema, loginMessage, serverMessageSchema, verifyWatcherLogin, } from './batch/watcher-protocol.js';
11
+ export { startHeartbeat } from './hub/heartbeat.js';
12
+ export { ClientChannelStore, type ClientChannel, type PendingVoucher, } from './batch/client-store.js';
13
+ export { BatchObyteClient, type BatchClientOptions, MIN_DEPOSIT, TRIGGER_FEE, addressOfKey, closeChannel, confirmClose, deposit, openChannel, } from './batch/client.js';
14
+ export { CoinReservations, type HistoryJoint, type ReservationRow, ReservingComposer, type ReservingComposerOptions, type Utxo, inputKey, selectCoins, unspentOutputs, } from './coins/index.js';
15
+ export { type BindingInput, bindingsEqual, computeBinding, newQuoteId, sha256Hex, } from './binding/binding.js';
16
+ export { ExactObyteFacilitatorV1, type PaymentPayloadV1, type PaymentRequirementsV1, requirementsV1ToV2, requirementsV2ToV1, } from './exact/facilitator-v1.js';
17
+ export { type LedgerUnit, type ProofchainBall, parseHistory, parseLedgerUnit, parseStateVars, } from './hub/schemas.js';
18
+ export { KeyedQueue } from './util/keyed-queue.js';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,eAAe,EACf,SAAS,EACT,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,eAAe,EACpB,gBAAgB,EAChB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EACL,aAAa,EACb,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACnB,gBAAgB,EAChB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,KAAK,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,uBAAuB,EACvB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EACL,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,IAAI,EACT,QAAQ,EACR,WAAW,EACX,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,KAAK,YAAY,EACjB,aAAa,EACb,cAAc,EACd,UAAU,EACV,SAAS,GACV,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,YAAY,EACZ,eAAe,EACf,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ export { hubCall } from './hub/hub-call.js';
2
+ export { EXACT_SCHEME, acceptedMatches, canonical, exactExtraSchema, parseExactRequirements, } from './exact/requirements.js';
3
+ export { SqliteSettlementStore, StoreLockedError, TERMINAL_STATES, } from './exact/store.js';
4
+ export { EXACT_SETTLE_REASONS, HISTORY_PROBE_ADDRESS, ExactObyteFacilitator, } from './exact/facilitator.js';
5
+ export { ExactObyteClient } from './exact/client.js';
6
+ export {} from './batch/gateway.js';
7
+ export { BATCH_REASONS, BATCH_SCHEME, batchExtraSchema, parseBatchRequirements, voucherMessageSchema, } from './batch/requirements.js';
8
+ export { SqliteBatchStore, } from './batch/store.js';
9
+ export { BatchObyteFacilitator } from './batch/facilitator.js';
10
+ export { WATCHER_LOGIN_PURPOSE, clientMessageSchema, commitmentMessageSchema, loginMessage, serverMessageSchema, verifyWatcherLogin, } from './batch/watcher-protocol.js';
11
+ export { startHeartbeat } from './hub/heartbeat.js';
12
+ export { ClientChannelStore, } from './batch/client-store.js';
13
+ export { BatchObyteClient, MIN_DEPOSIT, TRIGGER_FEE, addressOfKey, closeChannel, confirmClose, deposit, openChannel, } from './batch/client.js';
14
+ export { CoinReservations, ReservingComposer, inputKey, selectCoins, unspentOutputs, } from './coins/index.js';
15
+ export { bindingsEqual, computeBinding, newQuoteId, sha256Hex, } from './binding/binding.js';
16
+ export { ExactObyteFacilitatorV1, requirementsV1ToV2, requirementsV2ToV1, } from './exact/facilitator-v1.js';
17
+ export { parseHistory, parseLedgerUnit, parseStateVars, } from './hub/schemas.js';
18
+ export { KeyedQueue } from './util/keyed-queue.js';
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,YAAY,EAGZ,eAAe,EACf,SAAS,EACT,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAML,qBAAqB,EAErB,gBAAgB,EAChB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GAGtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAgC,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAA2C,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EACL,aAAa,EACb,YAAY,EAIZ,gBAAgB,EAChB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAIL,gBAAgB,GAIjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAqC,MAAM,wBAAwB,CAAC;AAClG,OAAO,EAIL,qBAAqB,EACrB,mBAAmB,EACnB,uBAAuB,EACvB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EACL,kBAAkB,GAGnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,gBAAgB,EAEhB,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAGhB,iBAAiB,EAGjB,QAAQ,EACR,WAAW,EACX,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAEL,aAAa,EACb,cAAc,EACd,UAAU,EACV,SAAS,GACV,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,uBAAuB,EAGvB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAGL,YAAY,EACZ,eAAe,EACf,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Runs tasks one at a time per key, in arrival order; different keys run in
3
+ * parallel. A failing task never blocks the ones queued after it. Used where
4
+ * check-then-act must not interleave within one process: per channel in the
5
+ * batch facilitator and in the seller watcher.
6
+ */
7
+ export declare class KeyedQueue {
8
+ private readonly tails;
9
+ run<T>(key: string, task: () => Promise<T>): Promise<T>;
10
+ /** Keys with queued or running tasks (for tests and diagnostics). */
11
+ get size(): number;
12
+ }
13
+ //# sourceMappingURL=keyed-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyed-queue.d.ts","sourceRoot":"","sources":["../../src/util/keyed-queue.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;IAE7D,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAWvD,qEAAqE;IACrE,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Runs tasks one at a time per key, in arrival order; different keys run in
3
+ * parallel. A failing task never blocks the ones queued after it. Used where
4
+ * check-then-act must not interleave within one process: per channel in the
5
+ * batch facilitator and in the seller watcher.
6
+ */
7
+ export class KeyedQueue {
8
+ tails = new Map();
9
+ run(key, task) {
10
+ const previous = this.tails.get(key) ?? Promise.resolve();
11
+ const result = previous.then(task, task);
12
+ const tail = result.catch(() => undefined);
13
+ this.tails.set(key, tail);
14
+ void tail.then(() => {
15
+ if (this.tails.get(key) === tail)
16
+ this.tails.delete(key);
17
+ });
18
+ return result;
19
+ }
20
+ /** Keys with queued or running tasks (for tests and diagnostics). */
21
+ get size() {
22
+ return this.tails.size;
23
+ }
24
+ }
25
+ //# sourceMappingURL=keyed-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyed-queue.js","sourceRoot":"","sources":["../../src/util/keyed-queue.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,OAAO,UAAU;IACJ,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAC;IAE7D,GAAG,CAAI,GAAW,EAAE,IAAsB;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YAClB,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI;gBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,qEAAqE;IACrE,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,54 @@
1
1
  {
2
2
  "name": "@obbyx/x402-obyte",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
4
+ "description": "x402 payment mechanisms for the Obyte network: exact (on-chain unit) and batch-settlement (AA payment channels)",
5
+ "keywords": [
6
+ "x402",
7
+ "obyte",
8
+ "payments",
9
+ "micropayments",
10
+ "payment-channels",
11
+ "http-402"
12
+ ],
13
+ "license": "MIT",
14
+ "author": "Alexander Ponomarev",
15
+ "homepage": "https://github.com/Taump/obbyx/tree/master/packages/x402-obyte#readme",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/Taump/obbyx.git",
19
+ "directory": "packages/x402-obyte"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/Taump/obbyx/issues"
23
+ },
24
+ "type": "module",
25
+ "sideEffects": false,
26
+ "engines": {
27
+ "node": ">=24"
28
+ },
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "default": "./dist/index.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "src",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "dependencies": {
45
+ "@obbyx/obyte": "^0.1.0",
46
+ "@x402/core": "^2.29.0",
47
+ "obyte": "0.2.1",
48
+ "zod": "^4.6.7"
49
+ },
50
+ "scripts": {
51
+ "build": "tsc -p tsconfig.build.json",
52
+ "typecheck": "tsc -p tsconfig.json --noEmit"
53
+ }
6
54
  }