@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,102 @@
1
+ import { ObbyxError } from '@obbyx/obyte';
2
+ import { moduleLogger } from '@obbyx/obyte/logger';
3
+ import { hubCall } from '../hub/hub-call.js';
4
+ import { parseHistory } from '../hub/schemas.js';
5
+ import { inputKey, selectCoins, unspentOutputs } from './selection.js';
6
+ /**
7
+ * Installs the reserving coin picker on an obyte.js client and serializes
8
+ * composes for the wallet. Use `compose(fn)` around every `client.compose.*`.
9
+ */
10
+ export class ReservingComposer {
11
+ options;
12
+ queue = Promise.resolve();
13
+ lastPick = [];
14
+ log;
15
+ now;
16
+ constructor(options) {
17
+ this.options = options;
18
+ this.log = moduleLogger(options.logger, 'x402.coins', { address: options.address });
19
+ this.now = options.now ?? (() => Math.floor(Date.now() / 1000));
20
+ const api = options.client.api;
21
+ api['pickDivisibleCoinsForAmount'] = (params) => this.pick(params);
22
+ }
23
+ /** Runs `fn` (which composes exactly one unit) with reservations; returns its unit. */
24
+ compose(fn, opts = {}) {
25
+ const run = this.queue.then(async () => {
26
+ await this.sweep();
27
+ this.lastPick = [];
28
+ try {
29
+ const unit = await fn();
30
+ const hash = typeof unit.unit === 'string' ? unit.unit : undefined;
31
+ if (hash === undefined)
32
+ throw new ObbyxError('compose_failed', 'Composed unit has no hash');
33
+ this.options.reservations.bind(this.options.network, this.lastPick, hash, opts.holdUntil);
34
+ this.log.debug({ unit: hash, inputs: this.lastPick.length }, 'inputs reserved for unit');
35
+ return unit;
36
+ }
37
+ catch (err) {
38
+ this.options.reservations.releaseUnbound(this.options.network, this.lastPick);
39
+ throw err;
40
+ }
41
+ finally {
42
+ this.lastPick = [];
43
+ }
44
+ });
45
+ this.queue = run.catch(() => undefined);
46
+ return run;
47
+ }
48
+ /** Releases the inputs of a unit that was composed but provably never sent anywhere. */
49
+ discard(unit) {
50
+ this.options.reservations.endUnit(this.options.network, unit);
51
+ }
52
+ /** Ends reservations of units now known to the hub, or provably expired. */
53
+ async sweep() {
54
+ const { reservations, network, client } = this.options;
55
+ const releaseAfter = this.options.releaseAfterSeconds ?? 1200;
56
+ reservations.dropStaleUnbound(network, this.now() - 600);
57
+ for (const { unit, reservedAt, holdUntil } of reservations.boundUnits(network)) {
58
+ const res = await hubCall(() => client.api.getJoint(unit), this.options.hubTimeoutMs ?? 15_000);
59
+ if (res.kind !== 'ok')
60
+ return; // unknown: keep everything reserved (fail-safe)
61
+ if (res.value.joint !== undefined) {
62
+ reservations.endUnit(network, unit); // the hub knows the spend now
63
+ }
64
+ else if (this.now() - reservedAt > releaseAfter && this.now() > (holdUntil ?? 0)) {
65
+ reservations.endUnit(network, unit);
66
+ this.log.info({ unit }, 'unit was never published; inputs released');
67
+ }
68
+ }
69
+ }
70
+ async pick(params) {
71
+ const { client, network, address, reservations } = this.options;
72
+ if (params.addresses.length !== 1 || params.addresses[0] !== address) {
73
+ throw new ObbyxError('coins_wrong_address', 'The reserving picker serves a single address');
74
+ }
75
+ const asset = params.asset ?? 'base';
76
+ const t = this.options.hubTimeoutMs ?? 15_000;
77
+ const history = await hubCall(() => client.api
78
+ .getWitnesses()
79
+ .then((witnesses) => client.api.getHistory({ witnesses, addresses: [address] })), t);
80
+ if (history.kind !== 'ok')
81
+ throw new ObbyxError('ledger_unavailable', `history: ${history.error}`);
82
+ const parsedHistory = parseHistory(history.value);
83
+ if (parsedHistory === undefined)
84
+ throw new ObbyxError('ledger_unavailable', 'history: malformed hub answer');
85
+ const joints = parsedHistory.joints;
86
+ const reserved = reservations.reservedKeys(network);
87
+ const free = unspentOutputs(joints, address, params.last_ball_mci).filter((u) => !reserved.has(inputKey(network, u)));
88
+ const picked = selectCoins(free, asset, BigInt(params.amount));
89
+ if (picked === undefined) {
90
+ throw new ObbyxError('insufficient_funds', `Not enough unreserved ${asset} (some coins may be reserved by pending payments)`);
91
+ }
92
+ reservations.reserve(network, address, picked);
93
+ this.lastPick.push(...picked);
94
+ return {
95
+ inputs_with_proofs: picked.map((u) => ({
96
+ input: { unit: u.unit, message_index: u.messageIndex, output_index: u.outputIndex },
97
+ })),
98
+ total_amount: Number(picked.reduce((s, u) => s + u.amount, 0n)),
99
+ };
100
+ }
101
+ }
102
+ //# sourceMappingURL=composer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composer.js","sourceRoot":"","sources":["../../src/coins/composer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { type ReservationRow, CoinReservations } from './reservations.js';
2
+ export { type HistoryJoint, type Utxo, inputKey, selectCoins, unspentOutputs, } from './selection.js';
3
+ export { ReservingComposer, type ReservingComposerOptions } from './composer.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/coins/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,IAAI,EACT,QAAQ,EACR,WAAW,EACX,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { CoinReservations } from './reservations.js';
2
+ export { inputKey, selectCoins, unspentOutputs, } from './selection.js';
3
+ export { ReservingComposer } from './composer.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/coins/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EAGL,QAAQ,EACR,WAAW,EACX,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAiC,MAAM,eAAe,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { type Utxo } from './selection.js';
2
+ /** Durable (SQLite) reservations of the wallet's coins, bound to the unit that spends them. */
3
+ export interface ReservationRow {
4
+ input_key: string;
5
+ network: string;
6
+ payment_unit: string | null;
7
+ reserved_at: number;
8
+ }
9
+ export declare class CoinReservations {
10
+ private readonly now;
11
+ private readonly db;
12
+ constructor(path: string, now?: () => number);
13
+ close(): void;
14
+ reservedKeys(network: string): Set<string>;
15
+ /** Reserves all inputs atomically; fails if any is already reserved. */
16
+ reserve(network: string, address: string, inputs: readonly Utxo[]): void;
17
+ /**
18
+ * Binds the inputs reserved for a compose to the resulting unit hash.
19
+ * `holdUntil`: the unit may still be published until then (offer validity +
20
+ * the facilitator's publication window), so its inputs are never released earlier.
21
+ */
22
+ bind(network: string, inputs: readonly Utxo[], unit: string, holdUntil?: number): void;
23
+ /** Releases inputs whose compose failed (no unit was produced). */
24
+ releaseUnbound(network: string, inputs: readonly Utxo[]): void;
25
+ /** Units with live reservations, oldest first. */
26
+ boundUnits(network: string): {
27
+ unit: string;
28
+ reservedAt: number;
29
+ holdUntil: number | null;
30
+ }[];
31
+ /** Ends all reservations of a unit (seen on the ledger, or provably never published). */
32
+ endUnit(network: string, unit: string): number;
33
+ /** Drops reservations of composes that crashed before producing a unit. */
34
+ dropStaleUnbound(network: string, olderThan: number): number;
35
+ rows(): ReservationRow[];
36
+ }
37
+ //# sourceMappingURL=reservations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reservations.d.ts","sourceRoot":"","sources":["../../src/coins/reservations.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,IAAI,EAAY,MAAM,gBAAgB,CAAC;AAErD,+FAA+F;AAC/F,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,gBAAgB;IAKzB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAJtB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAe;gBAGhC,IAAI,EAAE,MAAM,EACK,GAAG,GAAE,MAAM,MAA4C;IAyB1E,KAAK,IAAI,IAAI;IAIb,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAS1C,wEAAwE;IACxE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,IAAI,EAAE,GAAG,IAAI;IAiBxE;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAOtF,mEAAmE;IACnE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,IAAI,EAAE,GAAG,IAAI;IAO9D,kDAAkD;IAClD,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE;IAmB7F,yFAAyF;IACzF,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAQ9C,2EAA2E;IAC3E,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAU5D,IAAI,IAAI,cAAc,EAAE;CAKzB"}
@@ -0,0 +1,102 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ import { ObbyxError } from '@obbyx/obyte';
3
+ import { inputKey } from './selection.js';
4
+ export class CoinReservations {
5
+ now;
6
+ db;
7
+ constructor(path, now = () => Math.floor(Date.now() / 1000)) {
8
+ this.now = now;
9
+ this.db = new DatabaseSync(path);
10
+ this.db.exec(`
11
+ PRAGMA journal_mode = WAL;
12
+ PRAGMA synchronous = FULL;
13
+ PRAGMA busy_timeout = 5000;
14
+ CREATE TABLE IF NOT EXISTS coin_reservations (
15
+ input_key TEXT PRIMARY KEY,
16
+ network TEXT NOT NULL,
17
+ address TEXT NOT NULL,
18
+ payment_unit TEXT,
19
+ reserved_at INTEGER NOT NULL,
20
+ hold_until INTEGER
21
+ ) STRICT;
22
+ `);
23
+ // Databases created before hold_until existed.
24
+ const columns = this.db.prepare('PRAGMA table_info(coin_reservations)').all();
25
+ if (!columns.some((c) => c.name === 'hold_until')) {
26
+ this.db.exec('ALTER TABLE coin_reservations ADD COLUMN hold_until INTEGER');
27
+ }
28
+ }
29
+ close() {
30
+ this.db.close();
31
+ }
32
+ reservedKeys(network) {
33
+ const rows = this.db
34
+ .prepare('SELECT input_key FROM coin_reservations WHERE network = ?')
35
+ .all(network);
36
+ return new Set(rows.map((r) => r.input_key));
37
+ }
38
+ /** Reserves all inputs atomically; fails if any is already reserved. */
39
+ reserve(network, address, inputs) {
40
+ const ts = this.now();
41
+ this.db.exec('BEGIN IMMEDIATE');
42
+ try {
43
+ const insert = this.db.prepare('INSERT INTO coin_reservations (input_key, network, address, payment_unit, reserved_at) VALUES (?, ?, ?, NULL, ?)');
44
+ for (const u of inputs)
45
+ insert.run(inputKey(network, u), network, address, ts);
46
+ this.db.exec('COMMIT');
47
+ }
48
+ catch (err) {
49
+ this.db.exec('ROLLBACK');
50
+ throw new ObbyxError('coins_reserved', 'An input is already reserved by another payment', {
51
+ cause: err,
52
+ });
53
+ }
54
+ }
55
+ /**
56
+ * Binds the inputs reserved for a compose to the resulting unit hash.
57
+ * `holdUntil`: the unit may still be published until then (offer validity +
58
+ * the facilitator's publication window), so its inputs are never released earlier.
59
+ */
60
+ bind(network, inputs, unit, holdUntil) {
61
+ const update = this.db.prepare('UPDATE coin_reservations SET payment_unit = ?, hold_until = ? WHERE input_key = ? AND payment_unit IS NULL');
62
+ for (const u of inputs)
63
+ update.run(unit, holdUntil ?? null, inputKey(network, u));
64
+ }
65
+ /** Releases inputs whose compose failed (no unit was produced). */
66
+ releaseUnbound(network, inputs) {
67
+ const del = this.db.prepare('DELETE FROM coin_reservations WHERE input_key = ? AND payment_unit IS NULL');
68
+ for (const u of inputs)
69
+ del.run(inputKey(network, u));
70
+ }
71
+ /** Units with live reservations, oldest first. */
72
+ boundUnits(network) {
73
+ const rows = this.db
74
+ .prepare(`SELECT payment_unit, MIN(reserved_at) AS reserved_at, MAX(hold_until) AS hold_until
75
+ FROM coin_reservations
76
+ WHERE network = ? AND payment_unit IS NOT NULL GROUP BY payment_unit ORDER BY reserved_at`)
77
+ .all(network);
78
+ return rows.map((r) => ({
79
+ unit: r.payment_unit,
80
+ reservedAt: r.reserved_at,
81
+ holdUntil: r.hold_until,
82
+ }));
83
+ }
84
+ /** Ends all reservations of a unit (seen on the ledger, or provably never published). */
85
+ endUnit(network, unit) {
86
+ return Number(this.db
87
+ .prepare('DELETE FROM coin_reservations WHERE network = ? AND payment_unit = ?')
88
+ .run(network, unit).changes);
89
+ }
90
+ /** Drops reservations of composes that crashed before producing a unit. */
91
+ dropStaleUnbound(network, olderThan) {
92
+ return Number(this.db
93
+ .prepare('DELETE FROM coin_reservations WHERE network = ? AND payment_unit IS NULL AND reserved_at < ?')
94
+ .run(network, olderThan).changes);
95
+ }
96
+ rows() {
97
+ return this.db
98
+ .prepare('SELECT input_key, network, payment_unit, reserved_at FROM coin_reservations')
99
+ .all();
100
+ }
101
+ }
102
+ //# sourceMappingURL=reservations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reservations.js","sourceRoot":"","sources":["../../src/coins/reservations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /** Coin selection from a light history (pure functions). */
2
+ export interface Utxo {
3
+ readonly unit: string;
4
+ readonly messageIndex: number;
5
+ readonly outputIndex: number;
6
+ readonly asset: string;
7
+ readonly amount: bigint;
8
+ }
9
+ export declare function inputKey(network: string, u: Pick<Utxo, 'unit' | 'messageIndex' | 'outputIndex'>): string;
10
+ export interface HistoryJoint {
11
+ unit: {
12
+ unit: string;
13
+ main_chain_index?: number | null;
14
+ authors?: {
15
+ address: string;
16
+ }[];
17
+ messages?: {
18
+ app: string;
19
+ payload?: {
20
+ asset?: string;
21
+ inputs?: {
22
+ unit?: string;
23
+ message_index?: number;
24
+ output_index?: number;
25
+ }[];
26
+ outputs?: {
27
+ address: string;
28
+ amount: number;
29
+ }[];
30
+ };
31
+ }[];
32
+ };
33
+ ball?: string;
34
+ }
35
+ /**
36
+ * Unspent outputs of `address` from a `light/get_history` response.
37
+ * Others' outputs count only if stable and at or before `lastBallMci`.
38
+ */
39
+ export declare function unspentOutputs(joints: readonly HistoryJoint[], address: string, lastBallMci: number): Utxo[];
40
+ /** Largest-first selection until the target is covered. */
41
+ export declare function selectCoins(utxos: readonly Utxo[], asset: string, target: bigint): Utxo[] | undefined;
42
+ //# sourceMappingURL=selection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../src/coins/selection.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,QAAQ,CACtB,OAAO,EAAE,MAAM,EACf,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,aAAa,CAAC,GACrD,MAAM,CAER;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjC,OAAO,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAChC,QAAQ,CAAC,EAAE;YACT,GAAG,EAAE,MAAM,CAAC;YACZ,OAAO,CAAC,EAAE;gBACR,KAAK,CAAC,EAAE,MAAM,CAAC;gBACf,MAAM,CAAC,EAAE;oBAAE,IAAI,CAAC,EAAE,MAAM,CAAC;oBAAC,aAAa,CAAC,EAAE,MAAM,CAAC;oBAAC,YAAY,CAAC,EAAE,MAAM,CAAA;iBAAE,EAAE,CAAC;gBAC5E,OAAO,CAAC,EAAE;oBAAE,OAAO,EAAE,MAAM,CAAC;oBAAC,MAAM,EAAE,MAAM,CAAA;iBAAE,EAAE,CAAC;aACjD,CAAC;SACH,EAAE,CAAC;KACL,CAAC;IACF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,IAAI,EAAE,CAgCR;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,IAAI,EAAE,GAAG,SAAS,CAYpB"}
@@ -0,0 +1,60 @@
1
+ export function inputKey(network, u) {
2
+ return `${network}:${u.unit}:${u.messageIndex}:${u.outputIndex}`;
3
+ }
4
+ /**
5
+ * Unspent outputs of `address` from a `light/get_history` response.
6
+ * Others' outputs count only if stable and at or before `lastBallMci`.
7
+ */
8
+ export function unspentOutputs(joints, address, lastBallMci) {
9
+ const spent = new Set();
10
+ for (const j of joints) {
11
+ for (const m of j.unit.messages ?? []) {
12
+ if (m.app !== 'payment')
13
+ continue;
14
+ for (const i of m.payload?.inputs ?? []) {
15
+ if (i.unit !== undefined)
16
+ spent.add(`${i.unit}:${i.message_index}:${i.output_index}`);
17
+ }
18
+ }
19
+ }
20
+ const utxos = [];
21
+ for (const j of joints) {
22
+ const own = j.unit.authors?.some((a) => a.address === address) === true;
23
+ const stable = j.ball !== undefined;
24
+ const mci = j.unit.main_chain_index;
25
+ if (!own && !(stable && typeof mci === 'number' && mci <= lastBallMci))
26
+ continue;
27
+ (j.unit.messages ?? []).forEach((m, messageIndex) => {
28
+ if (m.app !== 'payment')
29
+ return;
30
+ (m.payload?.outputs ?? []).forEach((o, outputIndex) => {
31
+ if (o.address !== address || spent.has(`${j.unit.unit}:${messageIndex}:${outputIndex}`))
32
+ return;
33
+ utxos.push({
34
+ unit: j.unit.unit,
35
+ messageIndex,
36
+ outputIndex,
37
+ asset: m.payload?.asset ?? 'base',
38
+ amount: BigInt(o.amount),
39
+ });
40
+ });
41
+ });
42
+ }
43
+ return utxos;
44
+ }
45
+ /** Largest-first selection until the target is covered. */
46
+ export function selectCoins(utxos, asset, target) {
47
+ const candidates = utxos
48
+ .filter((u) => u.asset === asset)
49
+ .sort((a, b) => (a.amount > b.amount ? -1 : a.amount < b.amount ? 1 : 0));
50
+ const picked = [];
51
+ let total = 0n;
52
+ for (const u of candidates) {
53
+ if (total >= target)
54
+ break;
55
+ picked.push(u);
56
+ total += u.amount;
57
+ }
58
+ return total >= target ? picked : undefined;
59
+ }
60
+ //# sourceMappingURL=selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.js","sourceRoot":"","sources":["../../src/coins/selection.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,QAAQ,CACtB,OAAe,EACf,CAAsD;IAEtD,OAAO,GAAG,OAAO,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AACnE,CAAC;AAmBD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,MAA+B,EAC/B,OAAe,EACf,WAAmB;IAEnB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;YACtC,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS;gBAAE,SAAS;YAClC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;gBACxC,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;oBAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;YACxF,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,KAAK,IAAI,CAAC;QACxE,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;QACpC,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC;QACpC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,IAAI,WAAW,CAAC;YAAE,SAAS;QACjF,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE;YAClD,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS;gBAAE,OAAO;YAChC,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE;gBACpD,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,YAAY,IAAI,WAAW,EAAE,CAAC;oBACrF,OAAO;gBACT,KAAK,CAAC,IAAI,CAAC;oBACT,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;oBACjB,YAAY;oBACZ,WAAW;oBACX,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,IAAI,MAAM;oBACjC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;iBACzB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,WAAW,CACzB,KAAsB,EACtB,KAAa,EACb,MAAc;IAEd,MAAM,UAAU,GAAG,KAAK;SACrB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC;SAChC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAW,EAAE,CAAC;IAC1B,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,KAAK,IAAI,MAAM;YAAE,MAAM;QAC3B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACf,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC;IACpB,CAAC;IACD,OAAO,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { PaymentPayloadContext, PaymentPayloadResult, PaymentRequirements, SchemeNetworkClient } from '@x402/core/types';
2
+ import { type Logger } from '@obbyx/obyte/logger';
3
+ import type obyte from 'obyte';
4
+ import type { ReservingComposer } from '../coins/index.js';
5
+ /**
6
+ * Client side of `exact` on Obyte: composes and signs (but does NOT
7
+ * broadcast) a unit paying `payTo` with the seller's binding in a data
8
+ * message — obyte.js `client.compose.message` used directly.
9
+ *
10
+ * With a `composer` (ReservingComposer) inputs are reserved per payment and
11
+ * composes are serialized, so concurrent payments never pick the same coins.
12
+ */
13
+ export interface ExactObyteClientOptions {
14
+ /** obyte.js client connected to a hub of `network`. */
15
+ readonly client: obyte.Client;
16
+ readonly network: string;
17
+ readonly privateKey: Uint8Array;
18
+ readonly logger: Logger;
19
+ /** Refuse requirements above this amount (atomic units) per asset. */
20
+ readonly maxAmount?: ReadonlyMap<string, bigint>;
21
+ /** Reserves inputs and serializes composes (strongly recommended; see coins.ts). */
22
+ readonly composer?: ReservingComposer;
23
+ /** Refuse units whose network fees (headers + payload + tps) exceed this (bytes). */
24
+ readonly maxFee?: bigint;
25
+ }
26
+ export declare class ExactObyteClient implements SchemeNetworkClient {
27
+ private readonly options;
28
+ readonly scheme = "exact";
29
+ private readonly log;
30
+ constructor(options: ExactObyteClientOptions);
31
+ createPaymentPayload(x402Version: number, requirements: PaymentRequirements, context?: PaymentPayloadContext): Promise<PaymentPayloadResult>;
32
+ }
33
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/exact/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,qBAAqB,CAAC;AAChE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAI3D;;;;;;;GAOG;AACH,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IACtC,qFAAqF;IACrF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAWD,qBAAa,gBAAiB,YAAW,mBAAmB;IAI9C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,QAAQ,CAAC,MAAM,WAAgB;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;gBAEA,OAAO,EAAE,uBAAuB;IAIvD,oBAAoB,CACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,mBAAmB,EACjC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,oBAAoB,CAAC;CAuFjC"}
@@ -0,0 +1,93 @@
1
+ import { ObbyxError, toSafeNumber } from '@obbyx/obyte';
2
+ import { moduleLogger } from '@obbyx/obyte/logger';
3
+ import { requirementsV1ToV2 } from './facilitator-v1.js';
4
+ import { EXACT_SCHEME, parseExactRequirements } from './requirements.js';
5
+ /**
6
+ * Inputs of a signed unit stay reserved at least until the offer expires plus
7
+ * this margin (covers the facilitator's default publication window). An Obyte
8
+ * unit never expires, so any release is a heuristic; releasing too early can
9
+ * only make a LATER payment of ours fail (one of two units spending the same
10
+ * input becomes final-bad), it cannot pay twice.
11
+ */
12
+ const PUBLICATION_MARGIN_SECONDS = 900;
13
+ export class ExactObyteClient {
14
+ options;
15
+ scheme = EXACT_SCHEME;
16
+ log;
17
+ constructor(options) {
18
+ this.options = options;
19
+ this.log = moduleLogger(options.logger, 'x402.exact.client');
20
+ }
21
+ async createPaymentPayload(x402Version, requirements, context) {
22
+ if (x402Version !== 1 && x402Version !== 2) {
23
+ throw new ObbyxError('invalid_x402_version', 'Only x402 v1 and v2 are supported');
24
+ }
25
+ // v1 requirements (maxAmountRequired, plain network name) → v2 shape.
26
+ const v2 = x402Version === 1
27
+ ? requirementsV1ToV2(requirements)
28
+ : requirements;
29
+ const parsed = parseExactRequirements(v2);
30
+ if (!parsed.ok)
31
+ throw new ObbyxError(parsed.reason, parsed.message);
32
+ const req = parsed.value;
33
+ if (req.network.caip2 !== this.options.network) {
34
+ throw new ObbyxError('invalid_network', `This client pays on ${this.options.network}`);
35
+ }
36
+ const cap = this.options.maxAmount?.get(req.asset);
37
+ if (cap !== undefined && req.amount > cap) {
38
+ throw new ObbyxError('amount_over_limit', `Price ${req.amount} exceeds the limit ${cap} for ${req.asset}`);
39
+ }
40
+ if (context?.maxAmountPerPayment !== undefined &&
41
+ req.amount > BigInt(context.maxAmountPerPayment)) {
42
+ throw new ObbyxError('amount_over_limit', 'Price exceeds maxAmountPerPayment');
43
+ }
44
+ if (req.extra.validUntil < Math.floor(Date.now() / 1000)) {
45
+ throw new ObbyxError('quote_expired', 'The payment offer has expired');
46
+ }
47
+ const output = { address: req.payTo, amount: toSafeNumber(req.amount) };
48
+ const payment = req.asset === 'base'
49
+ ? { app: 'payment', payload: { outputs: [output] } }
50
+ : { app: 'payment', payload: { asset: req.asset, outputs: [output] } };
51
+ const data = {
52
+ app: 'data',
53
+ payload: { x402: { binding: req.extra.binding, quoteId: req.extra.quoteId } },
54
+ };
55
+ const compose = () => this.options.client.compose.message('multi', [payment, data], {
56
+ privateKey: this.options.privateKey,
57
+ testnet: req.network.testnet,
58
+ });
59
+ // The signed unit stays publishable until the offer expires plus the
60
+ // facilitator's publication window: keep its inputs reserved that long.
61
+ const holdUntil = req.extra.validUntil + PUBLICATION_MARGIN_SECONDS;
62
+ const unit = await (this.options.composer
63
+ ? this.options.composer.compose(compose, { holdUntil })
64
+ : compose());
65
+ const fee = BigInt(Number(unit['headers_commission'] ?? 0)) +
66
+ BigInt(Number(unit['payload_commission'] ?? 0)) +
67
+ BigInt(Number(unit['tps_fee'] ?? 0)) +
68
+ BigInt(Number(unit['burn_fee'] ?? 0)); // same total the facilitator checks
69
+ if (this.options.maxFee !== undefined && fee > this.options.maxFee) {
70
+ // The unit was never sent anywhere: its inputs can be released at once.
71
+ this.options.composer?.discard(String(unit['unit']));
72
+ throw new ObbyxError('fee_over_limit', `Network fee ${fee} exceeds the limit ${this.options.maxFee} bytes`);
73
+ }
74
+ this.log.info({
75
+ proofId: unit['unit'],
76
+ payTo: req.payTo,
77
+ asset: req.asset,
78
+ amount: req.amount.toString(),
79
+ binding: req.extra.binding,
80
+ }, 'payment unit signed (not broadcast)');
81
+ // v1: the mechanism returns the complete payload (core passes it through as-is).
82
+ if (x402Version === 1) {
83
+ return {
84
+ x402Version: 1,
85
+ scheme: EXACT_SCHEME,
86
+ network: requirements.network,
87
+ payload: { unit },
88
+ };
89
+ }
90
+ return { x402Version, payload: { unit } };
91
+ }
92
+ }
93
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/exact/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { Network, PaymentPayload, PaymentRequirements, SchemeNetworkFacilitator, SettleResponse, VerifyResponse } from '@x402/core/types';
2
+ import type { ExactObyteFacilitator } from './facilitator.js';
3
+ /**
4
+ * x402 **v1** for the Obyte `exact` scheme.
5
+ *
6
+ * v1 differs in shape only: plain network names (`obyte-testnet`),
7
+ * `maxAmountRequired`, `resource`/`mimeType` inside the requirements, and a
8
+ * payload without `accepted`. This adapter converts to the v2 shapes and runs
9
+ * the SAME v2 mechanism with the SAME store: settlement keys use the CAIP-2 id,
10
+ * so a proof spent through v1 can never be spent again through v2 (and vice versa).
11
+ */
12
+ export interface PaymentRequirementsV1 {
13
+ readonly scheme: string;
14
+ readonly network: string;
15
+ readonly maxAmountRequired: string;
16
+ readonly resource: string;
17
+ readonly description: string;
18
+ readonly mimeType: string;
19
+ readonly outputSchema?: Record<string, unknown>;
20
+ readonly payTo: string;
21
+ readonly maxTimeoutSeconds: number;
22
+ readonly asset: string;
23
+ readonly extra: Record<string, unknown>;
24
+ }
25
+ export interface PaymentPayloadV1 {
26
+ readonly x402Version: 1;
27
+ readonly scheme: string;
28
+ readonly network: string;
29
+ readonly payload: Record<string, unknown>;
30
+ }
31
+ export declare function requirementsV1ToV2(req: PaymentRequirementsV1): PaymentRequirements;
32
+ export declare function requirementsV2ToV1(req: PaymentRequirements, resource: {
33
+ url: string;
34
+ description?: string;
35
+ mimeType?: string;
36
+ }): PaymentRequirementsV1;
37
+ export declare class ExactObyteFacilitatorV1 implements SchemeNetworkFacilitator {
38
+ private readonly v2;
39
+ readonly scheme = "exact";
40
+ readonly caipFamily = "obyte-*";
41
+ constructor(v2: ExactObyteFacilitator);
42
+ getExtra(network: Network): Record<string, unknown> | undefined;
43
+ getSigners(): string[];
44
+ verify(payload: PaymentPayload, requirements: PaymentRequirements): Promise<VerifyResponse>;
45
+ settle(payload: PaymentPayload, requirements: PaymentRequirements): Promise<SettleResponse>;
46
+ private convert;
47
+ }
48
+ //# sourceMappingURL=facilitator-v1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facilitator-v1.d.ts","sourceRoot":"","sources":["../../src/exact/facilitator-v1.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,mBAAmB,EACnB,wBAAwB,EACxB,cAAc,EACd,cAAc,EACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAG9D;;;;;;;;GAQG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,qBAAqB,GAAG,mBAAmB,CAUlF;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,mBAAmB,EACxB,QAAQ,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACjE,qBAAqB,CAcvB;AAED,qBAAa,uBAAwB,YAAW,wBAAwB;IAI1D,OAAO,CAAC,QAAQ,CAAC,EAAE;IAH/B,QAAQ,CAAC,MAAM,WAAgB;IAC/B,QAAQ,CAAC,UAAU,aAAa;gBAEH,EAAE,EAAE,qBAAqB;IAEtD,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAI/D,UAAU,IAAI,MAAM,EAAE;IAIhB,MAAM,CACV,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,mBAAmB,GAChC,OAAO,CAAC,cAAc,CAAC;IAMpB,MAAM,CACV,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,mBAAmB,GAChC,OAAO,CAAC,cAAc,CAAC;IAS1B,OAAO,CAAC,OAAO;CA4BhB"}