@arkade-os/swap 0.0.6 → 0.0.8

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.
package/dist/nostr.cjs CHANGED
@@ -91,6 +91,20 @@ var SwapRefusal = class extends Error {
91
91
  }
92
92
  };
93
93
  var MIN_HEADROOM_SECONDS = 90 * 60;
94
+ var expectQuote = (payload, rfqId, requestedPair) => {
95
+ const p = payload;
96
+ if (p?.type === "rfq_refusal") throw new SwapRefusal(p.reason ?? "unknown", p.rfq_id ?? rfqId);
97
+ if (p?.type !== "rfq_quote" || p.rfq_id !== rfqId) {
98
+ throw new Error(`unexpected reply: ${p?.type ?? "no payload"}`);
99
+ }
100
+ if (requestedPair !== void 0 && p.pair !== requestedPair) {
101
+ throw new Error(
102
+ `solver quoted ${JSON.stringify(p.pair)}, not the requested ${requestedPair}`
103
+ );
104
+ }
105
+ return payload;
106
+ };
107
+ var pairOf = (payload) => typeof payload.pair === "string" ? payload.pair : void 0;
94
108
  var SEQUENCE_GRANULARITY_SECONDS = 512;
95
109
  var SOLO_REFUND_HEADROOM_SECONDS = 8 * SEQUENCE_GRANULARITY_SECONDS;
96
110
  var MIN_CLAIM_WINDOW_SECONDS = 30 * 60;
@@ -119,14 +133,6 @@ var closeReasons = (raw) => raw.map((entry) => {
119
133
  const { url, reason } = entry ?? {};
120
134
  return url ? `${url}: ${reason ?? "closed"}` : reason ?? "closed";
121
135
  });
122
- var asQuote = (payload, rfqId) => {
123
- const p = payload;
124
- if (p?.type === "rfq_refusal") throw new SwapRefusal(p.reason ?? "unknown", p.rfq_id ?? rfqId);
125
- if (p?.type !== "rfq_quote" || p.rfq_id !== rfqId) {
126
- throw new Error(`unexpected reply: ${p?.type ?? "no payload"}`);
127
- }
128
- return payload;
129
- };
130
136
  var nostrRfqTransport = (options) => {
131
137
  const relays = options.relays;
132
138
  const solverPubkey = options.solverPubkey;
@@ -202,7 +208,7 @@ var nostrRfqTransport = (options) => {
202
208
  const rfqId = String(payload.rfq_id);
203
209
  const reply = awaitReply(rfqId);
204
210
  await send(payload);
205
- return asQuote(await reply, rfqId);
211
+ return expectQuote(await reply, rfqId, pairOf(payload));
206
212
  },
207
213
  async status(rfqId) {
208
214
  const reply = awaitReply(rfqId);
package/dist/nostr.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as RfqTransport } from './rfq-3jWha5xA.cjs';
1
+ import { x as RfqTransport } from './rfq-C-aq5LDJ.cjs';
2
2
  import { SimplePool } from 'nostr-tools';
3
3
  import '@arkade-os/sdk';
4
4
 
package/dist/nostr.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as RfqTransport } from './rfq-3jWha5xA.js';
1
+ import { x as RfqTransport } from './rfq-C-aq5LDJ.js';
2
2
  import { SimplePool } from 'nostr-tools';
3
3
  import '@arkade-os/sdk';
4
4
 
package/dist/nostr.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
- SwapRefusal
3
- } from "./chunk-Q4FAYBXS.js";
2
+ expectQuote,
3
+ pairOf
4
+ } from "./chunk-TU4NGZDP.js";
4
5
 
5
6
  // src/nostr.ts
6
7
  import {
@@ -32,14 +33,6 @@ var closeReasons = (raw) => raw.map((entry) => {
32
33
  const { url, reason } = entry ?? {};
33
34
  return url ? `${url}: ${reason ?? "closed"}` : reason ?? "closed";
34
35
  });
35
- var asQuote = (payload, rfqId) => {
36
- const p = payload;
37
- if (p?.type === "rfq_refusal") throw new SwapRefusal(p.reason ?? "unknown", p.rfq_id ?? rfqId);
38
- if (p?.type !== "rfq_quote" || p.rfq_id !== rfqId) {
39
- throw new Error(`unexpected reply: ${p?.type ?? "no payload"}`);
40
- }
41
- return payload;
42
- };
43
36
  var nostrRfqTransport = (options) => {
44
37
  const relays = options.relays;
45
38
  const solverPubkey = options.solverPubkey;
@@ -115,7 +108,7 @@ var nostrRfqTransport = (options) => {
115
108
  const rfqId = String(payload.rfq_id);
116
109
  const reply = awaitReply(rfqId);
117
110
  await send(payload);
118
- return asQuote(await reply, rfqId);
111
+ return expectQuote(await reply, rfqId, pairOf(payload));
119
112
  },
120
113
  async status(rfqId) {
121
114
  const reply = awaitReply(rfqId);
@@ -33,6 +33,7 @@ var marketsCacheKey = (network, registry) => `arkade-intents-markets-${network}-
33
33
 
34
34
  // src/repositories/realm/repository.ts
35
35
  var SWAPS = "ArkadeAssetSwap";
36
+ var RFQ_SWAPS = "ArkadeRfqSwap";
36
37
  var SCANNED = "ArkadeAssetSwapScannedTxid";
37
38
  var MARKETS = "ArkadeAssetSwapMarketsCache";
38
39
  var RealmAssetSwapRepository = class {
@@ -40,7 +41,7 @@ var RealmAssetSwapRepository = class {
40
41
  this.realm = realm;
41
42
  }
42
43
  realm;
43
- version = 2;
44
+ version = 4;
44
45
  async saveSwap(swap) {
45
46
  this.realm.write(() => {
46
47
  this.realm.create(
@@ -60,6 +61,38 @@ var RealmAssetSwapRepository = class {
60
61
  (o) => JSON.parse(o.data)
61
62
  );
62
63
  }
64
+ async saveRfqSwap(record) {
65
+ this.realm.write(() => {
66
+ this.realm.create(
67
+ RFQ_SWAPS,
68
+ {
69
+ rfqId: record.rfqId,
70
+ state: record.state,
71
+ updatedAt: record.updatedAt,
72
+ data: JSON.stringify(record)
73
+ },
74
+ "modified"
75
+ );
76
+ });
77
+ }
78
+ async getRfqSwap(rfqId) {
79
+ const [found] = [
80
+ ...this.realm.objects(RFQ_SWAPS).filtered("rfqId == $0", rfqId)
81
+ ];
82
+ return found ? JSON.parse(found.data) : void 0;
83
+ }
84
+ async getAllRfqSwaps() {
85
+ return [...this.realm.objects(RFQ_SWAPS)].map(
86
+ (o) => JSON.parse(o.data)
87
+ );
88
+ }
89
+ async removeRfqSwap(rfqId) {
90
+ this.realm.write(() => {
91
+ this.realm.delete(
92
+ this.realm.objects(RFQ_SWAPS).filtered("rfqId == $0", rfqId)
93
+ );
94
+ });
95
+ }
63
96
  async getScannedTxids() {
64
97
  return new Set([...this.realm.objects(SCANNED)].map((o) => o.txid));
65
98
  }
@@ -83,12 +116,12 @@ var RealmAssetSwapRepository = class {
83
116
  );
84
117
  });
85
118
  }
86
- /** All three schemas in one write: clearing swaps but keeping scanned txids
87
- * would leave the restore scan permanently skipping those funding txs, so
88
- * a partial clear must not be observable. */
119
+ /** Every schema in one write: clearing swaps but keeping scanned txids would
120
+ * leave the restore scan permanently skipping those funding txs, so a
121
+ * partial clear must not be observable. */
89
122
  async clear() {
90
123
  this.realm.write(() => {
91
- for (const name of [SWAPS, SCANNED, MARKETS]) {
124
+ for (const name of [SWAPS, RFQ_SWAPS, SCANNED, MARKETS]) {
92
125
  this.realm.delete(this.realm.objects(name));
93
126
  }
94
127
  });
@@ -123,7 +156,18 @@ var ArkadeAssetSwapMarketsCacheSchema = {
123
156
  data: "string"
124
157
  }
125
158
  };
159
+ var ArkadeRfqSwapSchema = {
160
+ name: "ArkadeRfqSwap",
161
+ primaryKey: "rfqId",
162
+ properties: {
163
+ rfqId: "string",
164
+ state: "string",
165
+ updatedAt: "int",
166
+ data: "string"
167
+ }
168
+ };
126
169
  var AssetSwapRealmSchemas = [
170
+ ArkadeRfqSwapSchema,
127
171
  ArkadeAssetSwapSchema,
128
172
  ArkadeAssetSwapScannedTxidSchema,
129
173
  ArkadeAssetSwapMarketsCacheSchema
@@ -1,7 +1,8 @@
1
1
  import { RealmLike } from '@arkade-os/sdk/repositories/realm';
2
- import { A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry } from '../../repository-BwnZ8N62.cjs';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-Dso34L4D.cjs';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
+ import '../../rfq-C-aq5LDJ.cjs';
5
6
 
6
7
  /**
7
8
  * Realm backend for React Native.
@@ -15,24 +16,31 @@ import '@arkade-os/sdk';
15
16
  * record can be dropped. That holds for JSON-safe values: a consumer-added
16
17
  * `Date` comes back a string and a `bigint` throws on save, unlike the
17
18
  * IndexedDB backend's structured clone. `AssetSwap` itself is JSON-safe by
18
- * design.
19
+ * design, and so is `RfqSwapRecord` — including its corridor `profile`, which is
20
+ * plain JSON by the handler contract (see `rfqCorridor.ts`). Whole-record
21
+ * storage is what keeps a nested `profile.hashlock` from being lost the way a
22
+ * field-mapped backend could lose it.
19
23
  *
20
24
  * Realm creates the schemas on open, so there is nothing to initialise. The
21
25
  * consumer owns the Realm lifecycle — `[Symbol.asyncDispose]` is a no-op.
22
26
  */
23
27
  declare class RealmAssetSwapRepository implements AssetSwapRepository {
24
28
  private readonly realm;
25
- readonly version: 2;
29
+ readonly version: 4;
26
30
  constructor(realm: RealmLike);
27
31
  saveSwap(swap: AssetSwap): Promise<void>;
28
32
  getAllSwaps(): Promise<AssetSwap[]>;
33
+ saveRfqSwap(record: RfqSwapRecord): Promise<void>;
34
+ getRfqSwap(rfqId: string): Promise<RfqSwapRecord | undefined>;
35
+ getAllRfqSwaps(): Promise<RfqSwapRecord[]>;
36
+ removeRfqSwap(rfqId: string): Promise<void>;
29
37
  getScannedTxids(): Promise<Set<string>>;
30
38
  markTxidsScanned(txids: Iterable<string>): Promise<void>;
31
39
  getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
32
40
  saveCachedMarkets(network: string, registry: string, entry: MarketsCacheEntry): Promise<void>;
33
- /** All three schemas in one write: clearing swaps but keeping scanned txids
34
- * would leave the restore scan permanently skipping those funding txs, so
35
- * a partial clear must not be observable. */
41
+ /** Every schema in one write: clearing swaps but keeping scanned txids would
42
+ * leave the restore scan permanently skipping those funding txs, so a
43
+ * partial clear must not be observable. */
36
44
  clear(): Promise<void>;
37
45
  [Symbol.asyncDispose](): Promise<void>;
38
46
  }
@@ -50,6 +58,11 @@ declare class RealmAssetSwapRepository implements AssetSwapRepository {
50
58
  * objects conforming to Realm's ObjectSchema shape. They are new, so a consumer
51
59
  * adds them to its Realm config and bumps its own `schemaVersion`; no migration
52
60
  * helper ships here.
61
+ *
62
+ * `ArkadeRfqSwap` arrived after the first three. A consumer already shipping
63
+ * those has to add it and bump `schemaVersion` again — Realm creates schemas on
64
+ * open, so a config that lists three while the code reads four fails on the
65
+ * fourth `realm.objects(…)` rather than at open.
53
66
  */
54
67
  declare const ArkadeAssetSwapSchema: {
55
68
  name: string;
@@ -98,6 +111,15 @@ declare const AssetSwapRealmSchemas: ({
98
111
  key: string;
99
112
  data: string;
100
113
  };
114
+ } | {
115
+ name: string;
116
+ primaryKey: string;
117
+ properties: {
118
+ rfqId: string;
119
+ state: string;
120
+ updatedAt: string;
121
+ data: string;
122
+ };
101
123
  })[];
102
124
 
103
125
  export { ArkadeAssetSwapMarketsCacheSchema, ArkadeAssetSwapScannedTxidSchema, ArkadeAssetSwapSchema, AssetSwapRealmSchemas, RealmAssetSwapRepository };
@@ -1,7 +1,8 @@
1
1
  import { RealmLike } from '@arkade-os/sdk/repositories/realm';
2
- import { A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry } from '../../repository-BwnZ8N62.js';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-BcZ9LXRP.js';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
+ import '../../rfq-C-aq5LDJ.js';
5
6
 
6
7
  /**
7
8
  * Realm backend for React Native.
@@ -15,24 +16,31 @@ import '@arkade-os/sdk';
15
16
  * record can be dropped. That holds for JSON-safe values: a consumer-added
16
17
  * `Date` comes back a string and a `bigint` throws on save, unlike the
17
18
  * IndexedDB backend's structured clone. `AssetSwap` itself is JSON-safe by
18
- * design.
19
+ * design, and so is `RfqSwapRecord` — including its corridor `profile`, which is
20
+ * plain JSON by the handler contract (see `rfqCorridor.ts`). Whole-record
21
+ * storage is what keeps a nested `profile.hashlock` from being lost the way a
22
+ * field-mapped backend could lose it.
19
23
  *
20
24
  * Realm creates the schemas on open, so there is nothing to initialise. The
21
25
  * consumer owns the Realm lifecycle — `[Symbol.asyncDispose]` is a no-op.
22
26
  */
23
27
  declare class RealmAssetSwapRepository implements AssetSwapRepository {
24
28
  private readonly realm;
25
- readonly version: 2;
29
+ readonly version: 4;
26
30
  constructor(realm: RealmLike);
27
31
  saveSwap(swap: AssetSwap): Promise<void>;
28
32
  getAllSwaps(): Promise<AssetSwap[]>;
33
+ saveRfqSwap(record: RfqSwapRecord): Promise<void>;
34
+ getRfqSwap(rfqId: string): Promise<RfqSwapRecord | undefined>;
35
+ getAllRfqSwaps(): Promise<RfqSwapRecord[]>;
36
+ removeRfqSwap(rfqId: string): Promise<void>;
29
37
  getScannedTxids(): Promise<Set<string>>;
30
38
  markTxidsScanned(txids: Iterable<string>): Promise<void>;
31
39
  getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
32
40
  saveCachedMarkets(network: string, registry: string, entry: MarketsCacheEntry): Promise<void>;
33
- /** All three schemas in one write: clearing swaps but keeping scanned txids
34
- * would leave the restore scan permanently skipping those funding txs, so
35
- * a partial clear must not be observable. */
41
+ /** Every schema in one write: clearing swaps but keeping scanned txids would
42
+ * leave the restore scan permanently skipping those funding txs, so a
43
+ * partial clear must not be observable. */
36
44
  clear(): Promise<void>;
37
45
  [Symbol.asyncDispose](): Promise<void>;
38
46
  }
@@ -50,6 +58,11 @@ declare class RealmAssetSwapRepository implements AssetSwapRepository {
50
58
  * objects conforming to Realm's ObjectSchema shape. They are new, so a consumer
51
59
  * adds them to its Realm config and bumps its own `schemaVersion`; no migration
52
60
  * helper ships here.
61
+ *
62
+ * `ArkadeRfqSwap` arrived after the first three. A consumer already shipping
63
+ * those has to add it and bump `schemaVersion` again — Realm creates schemas on
64
+ * open, so a config that lists three while the code reads four fails on the
65
+ * fourth `realm.objects(…)` rather than at open.
53
66
  */
54
67
  declare const ArkadeAssetSwapSchema: {
55
68
  name: string;
@@ -98,6 +111,15 @@ declare const AssetSwapRealmSchemas: ({
98
111
  key: string;
99
112
  data: string;
100
113
  };
114
+ } | {
115
+ name: string;
116
+ primaryKey: string;
117
+ properties: {
118
+ rfqId: string;
119
+ state: string;
120
+ updatedAt: string;
121
+ data: string;
122
+ };
101
123
  })[];
102
124
 
103
125
  export { ArkadeAssetSwapMarketsCacheSchema, ArkadeAssetSwapScannedTxidSchema, ArkadeAssetSwapSchema, AssetSwapRealmSchemas, RealmAssetSwapRepository };
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  marketsCacheKey
3
- } from "../../chunk-WGRU2DBF.js";
3
+ } from "../../chunk-6ZUS47GA.js";
4
4
 
5
5
  // src/repositories/realm/repository.ts
6
6
  var SWAPS = "ArkadeAssetSwap";
7
+ var RFQ_SWAPS = "ArkadeRfqSwap";
7
8
  var SCANNED = "ArkadeAssetSwapScannedTxid";
8
9
  var MARKETS = "ArkadeAssetSwapMarketsCache";
9
10
  var RealmAssetSwapRepository = class {
@@ -11,7 +12,7 @@ var RealmAssetSwapRepository = class {
11
12
  this.realm = realm;
12
13
  }
13
14
  realm;
14
- version = 2;
15
+ version = 4;
15
16
  async saveSwap(swap) {
16
17
  this.realm.write(() => {
17
18
  this.realm.create(
@@ -31,6 +32,38 @@ var RealmAssetSwapRepository = class {
31
32
  (o) => JSON.parse(o.data)
32
33
  );
33
34
  }
35
+ async saveRfqSwap(record) {
36
+ this.realm.write(() => {
37
+ this.realm.create(
38
+ RFQ_SWAPS,
39
+ {
40
+ rfqId: record.rfqId,
41
+ state: record.state,
42
+ updatedAt: record.updatedAt,
43
+ data: JSON.stringify(record)
44
+ },
45
+ "modified"
46
+ );
47
+ });
48
+ }
49
+ async getRfqSwap(rfqId) {
50
+ const [found] = [
51
+ ...this.realm.objects(RFQ_SWAPS).filtered("rfqId == $0", rfqId)
52
+ ];
53
+ return found ? JSON.parse(found.data) : void 0;
54
+ }
55
+ async getAllRfqSwaps() {
56
+ return [...this.realm.objects(RFQ_SWAPS)].map(
57
+ (o) => JSON.parse(o.data)
58
+ );
59
+ }
60
+ async removeRfqSwap(rfqId) {
61
+ this.realm.write(() => {
62
+ this.realm.delete(
63
+ this.realm.objects(RFQ_SWAPS).filtered("rfqId == $0", rfqId)
64
+ );
65
+ });
66
+ }
34
67
  async getScannedTxids() {
35
68
  return new Set([...this.realm.objects(SCANNED)].map((o) => o.txid));
36
69
  }
@@ -54,12 +87,12 @@ var RealmAssetSwapRepository = class {
54
87
  );
55
88
  });
56
89
  }
57
- /** All three schemas in one write: clearing swaps but keeping scanned txids
58
- * would leave the restore scan permanently skipping those funding txs, so
59
- * a partial clear must not be observable. */
90
+ /** Every schema in one write: clearing swaps but keeping scanned txids would
91
+ * leave the restore scan permanently skipping those funding txs, so a
92
+ * partial clear must not be observable. */
60
93
  async clear() {
61
94
  this.realm.write(() => {
62
- for (const name of [SWAPS, SCANNED, MARKETS]) {
95
+ for (const name of [SWAPS, RFQ_SWAPS, SCANNED, MARKETS]) {
63
96
  this.realm.delete(this.realm.objects(name));
64
97
  }
65
98
  });
@@ -94,7 +127,18 @@ var ArkadeAssetSwapMarketsCacheSchema = {
94
127
  data: "string"
95
128
  }
96
129
  };
130
+ var ArkadeRfqSwapSchema = {
131
+ name: "ArkadeRfqSwap",
132
+ primaryKey: "rfqId",
133
+ properties: {
134
+ rfqId: "string",
135
+ state: "string",
136
+ updatedAt: "int",
137
+ data: "string"
138
+ }
139
+ };
97
140
  var AssetSwapRealmSchemas = [
141
+ ArkadeRfqSwapSchema,
98
142
  ArkadeAssetSwapSchema,
99
143
  ArkadeAssetSwapScannedTxidSchema,
100
144
  ArkadeAssetSwapMarketsCacheSchema
@@ -38,14 +38,16 @@ var SQLiteAssetSwapRepository = class {
38
38
  this.db = db;
39
39
  this.prefix = (0, import_sqlite.sanitizeTablePrefix)(options?.prefix ?? DEFAULT_PREFIX);
40
40
  this.swaps = `${this.prefix}asset_swaps`;
41
+ this.rfqSwaps = `${this.prefix}rfq_swaps`;
41
42
  this.scanned = `${this.prefix}asset_swap_scanned_txids`;
42
43
  this.markets = `${this.prefix}asset_swap_markets`;
43
44
  }
44
45
  db;
45
- version = 2;
46
+ version = 4;
46
47
  initPromise = null;
47
48
  prefix;
48
49
  swaps;
50
+ rfqSwaps;
49
51
  scanned;
50
52
  markets;
51
53
  /** A rejected init is not cached. The DDL runs in a transaction on a shared
@@ -77,6 +79,15 @@ var SQLiteAssetSwapRepository = class {
77
79
  await this.db.run(
78
80
  `CREATE INDEX IF NOT EXISTS idx_${this.prefix}asset_swaps_created_at ON ${this.swaps} (created_at)`
79
81
  );
82
+ await this.db.run(`CREATE TABLE IF NOT EXISTS ${this.rfqSwaps} (
83
+ rfq_id TEXT PRIMARY KEY,
84
+ state TEXT NOT NULL,
85
+ updated_at INTEGER NOT NULL,
86
+ data TEXT NOT NULL
87
+ )`);
88
+ await this.db.run(
89
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}rfq_swaps_state ON ${this.rfqSwaps} (state)`
90
+ );
80
91
  await this.db.run(`CREATE TABLE IF NOT EXISTS ${this.scanned} (txid TEXT PRIMARY KEY)`);
81
92
  await this.db.run(
82
93
  `CREATE TABLE IF NOT EXISTS ${this.markets} (cache_key TEXT PRIMARY KEY, data TEXT NOT NULL)`
@@ -107,6 +118,35 @@ var SQLiteAssetSwapRepository = class {
107
118
  const rows = await this.db.all(`SELECT data FROM ${this.swaps}`);
108
119
  return rows.map((r) => JSON.parse(r.data));
109
120
  }
121
+ async saveRfqSwap(record) {
122
+ await this.ensureInit();
123
+ await this.withTx(async () => {
124
+ await this.db.run(
125
+ `INSERT OR REPLACE INTO ${this.rfqSwaps} (rfq_id, state, updated_at, data)
126
+ VALUES (?, ?, ?, ?)`,
127
+ [record.rfqId, record.state, record.updatedAt, JSON.stringify(record)]
128
+ );
129
+ });
130
+ }
131
+ async getRfqSwap(rfqId) {
132
+ await this.ensureInit();
133
+ const row = await this.db.get(
134
+ `SELECT data FROM ${this.rfqSwaps} WHERE rfq_id = ?`,
135
+ [rfqId]
136
+ );
137
+ return row ? JSON.parse(row.data) : void 0;
138
+ }
139
+ async getAllRfqSwaps() {
140
+ await this.ensureInit();
141
+ const rows = await this.db.all(`SELECT data FROM ${this.rfqSwaps}`);
142
+ return rows.map((r) => JSON.parse(r.data));
143
+ }
144
+ async removeRfqSwap(rfqId) {
145
+ await this.ensureInit();
146
+ await this.withTx(async () => {
147
+ await this.db.run(`DELETE FROM ${this.rfqSwaps} WHERE rfq_id = ?`, [rfqId]);
148
+ });
149
+ }
110
150
  async getScannedTxids() {
111
151
  await this.ensureInit();
112
152
  const rows = await this.db.all(`SELECT txid FROM ${this.scanned}`);
@@ -143,13 +183,14 @@ var SQLiteAssetSwapRepository = class {
143
183
  );
144
184
  });
145
185
  }
146
- /** All three tables in one transaction: clearing swaps but keeping scanned
147
- * txids would leave the restore scan permanently skipping those funding
148
- * txs, so a partial clear must not be observable. */
186
+ /** Every table in one transaction: clearing swaps but keeping scanned txids
187
+ * would leave the restore scan permanently skipping those funding txs, so a
188
+ * partial clear must not be observable. */
149
189
  async clear() {
150
190
  await this.ensureInit();
151
191
  await this.withTx(async () => {
152
192
  await this.db.run(`DELETE FROM ${this.swaps}`);
193
+ await this.db.run(`DELETE FROM ${this.rfqSwaps}`);
153
194
  await this.db.run(`DELETE FROM ${this.scanned}`);
154
195
  await this.db.run(`DELETE FROM ${this.markets}`);
155
196
  });
@@ -1,7 +1,8 @@
1
1
  import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
2
- import { A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry } from '../../repository-BwnZ8N62.cjs';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-Dso34L4D.cjs';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
+ import '../../rfq-C-aq5LDJ.cjs';
5
6
 
6
7
  /**
7
8
  * SQLite backend over the SDK's `SQLExecutor`, so any driver plugs in
@@ -11,19 +12,27 @@ import '@arkade-os/sdk';
11
12
  * and `created_at` are mapped out for querying only, so no field of a record
12
13
  * can be dropped. That holds for JSON-safe values: a consumer-added `Date`
13
14
  * comes back a string and a `bigint` throws on save, unlike the IndexedDB
14
- * backend's structured clone. `AssetSwap` itself is JSON-safe by design.
15
+ * backend's structured clone. `AssetSwap` itself is JSON-safe by design, and so
16
+ * is `RfqSwapRecord` — including its corridor `profile`, which is plain JSON by
17
+ * the handler contract (see `rfqCorridor.ts`). Whole-record storage is what
18
+ * keeps a nested `profile.hashlock` from being lost the way a field-mapped
19
+ * backend could lose it.
15
20
  *
16
- * Tables are created lazily on first operation. The consumer owns the
21
+ * Tables are created lazily on first operation, and `CREATE TABLE IF NOT
22
+ * EXISTS` runs on every init — so the `rfq_swaps` table appears for an existing
23
+ * database on its next operation, with no migration and no version to bump.
24
+ * The consumer owns the
17
25
  * `SQLExecutor` lifecycle — `[Symbol.asyncDispose]` is a no-op — and must pass
18
26
  * the **same executor instance** to every repository on the database: the
19
27
  * write chain is keyed by that object, and a per-repository literal splits it.
20
28
  */
21
29
  declare class SQLiteAssetSwapRepository implements AssetSwapRepository {
22
30
  private readonly db;
23
- readonly version: 2;
31
+ readonly version: 4;
24
32
  private initPromise;
25
33
  private readonly prefix;
26
34
  private readonly swaps;
35
+ private readonly rfqSwaps;
27
36
  private readonly scanned;
28
37
  private readonly markets;
29
38
  constructor(db: SQLExecutor, options?: {
@@ -49,13 +58,17 @@ declare class SQLiteAssetSwapRepository implements AssetSwapRepository {
49
58
  private withTx;
50
59
  saveSwap(swap: AssetSwap): Promise<void>;
51
60
  getAllSwaps(): Promise<AssetSwap[]>;
61
+ saveRfqSwap(record: RfqSwapRecord): Promise<void>;
62
+ getRfqSwap(rfqId: string): Promise<RfqSwapRecord | undefined>;
63
+ getAllRfqSwaps(): Promise<RfqSwapRecord[]>;
64
+ removeRfqSwap(rfqId: string): Promise<void>;
52
65
  getScannedTxids(): Promise<Set<string>>;
53
66
  markTxidsScanned(txids: Iterable<string>): Promise<void>;
54
67
  getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
55
68
  saveCachedMarkets(network: string, registry: string, entry: MarketsCacheEntry): Promise<void>;
56
- /** All three tables in one transaction: clearing swaps but keeping scanned
57
- * txids would leave the restore scan permanently skipping those funding
58
- * txs, so a partial clear must not be observable. */
69
+ /** Every table in one transaction: clearing swaps but keeping scanned txids
70
+ * would leave the restore scan permanently skipping those funding txs, so a
71
+ * partial clear must not be observable. */
59
72
  clear(): Promise<void>;
60
73
  [Symbol.asyncDispose](): Promise<void>;
61
74
  }
@@ -1,7 +1,8 @@
1
1
  import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
2
- import { A as AssetSwapRepository, a as AssetSwap, M as MarketsCacheEntry } from '../../repository-BwnZ8N62.js';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-BcZ9LXRP.js';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
+ import '../../rfq-C-aq5LDJ.js';
5
6
 
6
7
  /**
7
8
  * SQLite backend over the SDK's `SQLExecutor`, so any driver plugs in
@@ -11,19 +12,27 @@ import '@arkade-os/sdk';
11
12
  * and `created_at` are mapped out for querying only, so no field of a record
12
13
  * can be dropped. That holds for JSON-safe values: a consumer-added `Date`
13
14
  * comes back a string and a `bigint` throws on save, unlike the IndexedDB
14
- * backend's structured clone. `AssetSwap` itself is JSON-safe by design.
15
+ * backend's structured clone. `AssetSwap` itself is JSON-safe by design, and so
16
+ * is `RfqSwapRecord` — including its corridor `profile`, which is plain JSON by
17
+ * the handler contract (see `rfqCorridor.ts`). Whole-record storage is what
18
+ * keeps a nested `profile.hashlock` from being lost the way a field-mapped
19
+ * backend could lose it.
15
20
  *
16
- * Tables are created lazily on first operation. The consumer owns the
21
+ * Tables are created lazily on first operation, and `CREATE TABLE IF NOT
22
+ * EXISTS` runs on every init — so the `rfq_swaps` table appears for an existing
23
+ * database on its next operation, with no migration and no version to bump.
24
+ * The consumer owns the
17
25
  * `SQLExecutor` lifecycle — `[Symbol.asyncDispose]` is a no-op — and must pass
18
26
  * the **same executor instance** to every repository on the database: the
19
27
  * write chain is keyed by that object, and a per-repository literal splits it.
20
28
  */
21
29
  declare class SQLiteAssetSwapRepository implements AssetSwapRepository {
22
30
  private readonly db;
23
- readonly version: 2;
31
+ readonly version: 4;
24
32
  private initPromise;
25
33
  private readonly prefix;
26
34
  private readonly swaps;
35
+ private readonly rfqSwaps;
27
36
  private readonly scanned;
28
37
  private readonly markets;
29
38
  constructor(db: SQLExecutor, options?: {
@@ -49,13 +58,17 @@ declare class SQLiteAssetSwapRepository implements AssetSwapRepository {
49
58
  private withTx;
50
59
  saveSwap(swap: AssetSwap): Promise<void>;
51
60
  getAllSwaps(): Promise<AssetSwap[]>;
61
+ saveRfqSwap(record: RfqSwapRecord): Promise<void>;
62
+ getRfqSwap(rfqId: string): Promise<RfqSwapRecord | undefined>;
63
+ getAllRfqSwaps(): Promise<RfqSwapRecord[]>;
64
+ removeRfqSwap(rfqId: string): Promise<void>;
52
65
  getScannedTxids(): Promise<Set<string>>;
53
66
  markTxidsScanned(txids: Iterable<string>): Promise<void>;
54
67
  getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
55
68
  saveCachedMarkets(network: string, registry: string, entry: MarketsCacheEntry): Promise<void>;
56
- /** All three tables in one transaction: clearing swaps but keeping scanned
57
- * txids would leave the restore scan permanently skipping those funding
58
- * txs, so a partial clear must not be observable. */
69
+ /** Every table in one transaction: clearing swaps but keeping scanned txids
70
+ * would leave the restore scan permanently skipping those funding txs, so a
71
+ * partial clear must not be observable. */
59
72
  clear(): Promise<void>;
60
73
  [Symbol.asyncDispose](): Promise<void>;
61
74
  }