@arkade-os/swap 0.0.12 → 0.1.0-rc.1

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.
@@ -0,0 +1,295 @@
1
+ // src/node/paths.ts
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ var NETWORK_PATH_SEGMENT = /^[a-z][a-z0-9-]{0,32}$/;
5
+ var assertSafeNetworkPathSegment = (network) => {
6
+ if (NETWORK_PATH_SEGMENT.test(network)) return;
7
+ throw new Error(
8
+ `Invalid network name for swap database path: ${JSON.stringify(network)}. Use lowercase letters, digits, and hyphens, starting with a letter.`
9
+ );
10
+ };
11
+ var configDir = (env = process.env) => {
12
+ if (process.platform === "win32") {
13
+ return env.APPDATA ?? join(homedir(), "AppData", "Roaming");
14
+ }
15
+ if (process.platform === "darwin") {
16
+ return join(homedir(), "Library", "Application Support");
17
+ }
18
+ const xdg = env.XDG_CONFIG_HOME;
19
+ return xdg && xdg.startsWith("/") ? xdg : join(homedir(), ".config");
20
+ };
21
+ var swapDatabasePath = (network, env = process.env) => {
22
+ assertSafeNetworkPathSegment(network);
23
+ return join(configDir(env), "arkade", "swaps", `swaps-${network}.sqlite`);
24
+ };
25
+
26
+ // src/node/executor.ts
27
+ import { DatabaseSync } from "node:sqlite";
28
+ import { mkdirSync } from "node:fs";
29
+ import { dirname } from "node:path";
30
+
31
+ // src/repositories/sqlite/repository.ts
32
+ import {
33
+ runInTransaction,
34
+ sanitizeTablePrefix
35
+ } from "@arkade-os/sdk/repositories/sqlite";
36
+
37
+ // src/repository.ts
38
+ var marketsCacheKey = (network, registry) => `arkade-intents-markets-${network}-${registry}`;
39
+
40
+ // src/repositories/sqlite/repository.ts
41
+ var DEFAULT_PREFIX = "arkade_";
42
+ var INSERT_CHUNK = 500;
43
+ var SQLiteAssetSwapRepository = class {
44
+ constructor(db, options) {
45
+ this.db = db;
46
+ this.prefix = sanitizeTablePrefix(options?.prefix ?? DEFAULT_PREFIX);
47
+ this.swaps = `${this.prefix}asset_swaps`;
48
+ this.rfqSwaps = `${this.prefix}rfq_swaps`;
49
+ this.swapRecords = `${this.prefix}swap_records`;
50
+ this.scanned = `${this.prefix}asset_swap_scanned_txids`;
51
+ this.markets = `${this.prefix}asset_swap_markets`;
52
+ }
53
+ db;
54
+ version = 5;
55
+ initPromise = null;
56
+ prefix;
57
+ swaps;
58
+ rfqSwaps;
59
+ swapRecords;
60
+ scanned;
61
+ markets;
62
+ /** A rejected init is not cached. The DDL runs in a transaction on a shared
63
+ * connection, so it can fail for reasons that pass — a `SQLITE_BUSY` on
64
+ * `BEGIN IMMEDIATE`, a neighbour's rollback — and caching that rejection
65
+ * would strand the instance unusable for the life of the process. Same rule
66
+ * as the IndexedDB backend's `ensureDb`. */
67
+ ensureInit() {
68
+ return this.initPromise ??= this.init().catch((err) => {
69
+ this.initPromise = null;
70
+ throw err;
71
+ });
72
+ }
73
+ /** The DDL is transactional in SQLite too: run raw on a shared connection it
74
+ * would join a neighbour's open transaction and vanish with its rollback,
75
+ * while `initPromise` stayed resolved and every later statement failed with
76
+ * `no such table`. */
77
+ async init() {
78
+ await this.withTx(async () => {
79
+ await this.db.run(`CREATE TABLE IF NOT EXISTS ${this.swaps} (
80
+ id TEXT PRIMARY KEY,
81
+ status TEXT NOT NULL,
82
+ created_at INTEGER NOT NULL,
83
+ data TEXT NOT NULL
84
+ )`);
85
+ await this.db.run(
86
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}asset_swaps_status ON ${this.swaps} (status)`
87
+ );
88
+ await this.db.run(
89
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}asset_swaps_created_at ON ${this.swaps} (created_at)`
90
+ );
91
+ await this.db.run(`CREATE TABLE IF NOT EXISTS ${this.rfqSwaps} (
92
+ rfq_id TEXT PRIMARY KEY,
93
+ state TEXT NOT NULL,
94
+ updated_at INTEGER NOT NULL,
95
+ data TEXT NOT NULL
96
+ )`);
97
+ await this.db.run(
98
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}rfq_swaps_state ON ${this.rfqSwaps} (state)`
99
+ );
100
+ await this.db.run(`CREATE TABLE IF NOT EXISTS ${this.swapRecords} (
101
+ id TEXT PRIMARY KEY,
102
+ family TEXT NOT NULL,
103
+ updated_at INTEGER NOT NULL,
104
+ data TEXT NOT NULL
105
+ )`);
106
+ await this.db.run(
107
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}swap_records_family ON ${this.swapRecords} (family)`
108
+ );
109
+ await this.db.run(`CREATE TABLE IF NOT EXISTS ${this.scanned} (txid TEXT PRIMARY KEY)`);
110
+ await this.db.run(
111
+ `CREATE TABLE IF NOT EXISTS ${this.markets} (cache_key TEXT PRIMARY KEY, data TEXT NOT NULL)`
112
+ );
113
+ });
114
+ }
115
+ /** Every write, including the single-statement ones. The chain serializes
116
+ * transaction *blocks*, not bare statements: one issued between a
117
+ * neighbour's BEGIN IMMEDIATE and its COMMIT becomes part of that
118
+ * transaction and dies with it. `fn` must issue only raw db calls — no
119
+ * repository method, no `ensureInit` — since `runInTransaction` cannot
120
+ * nest. */
121
+ withTx(fn) {
122
+ return runInTransaction(this.db, fn);
123
+ }
124
+ async saveSwap(swap) {
125
+ await this.ensureInit();
126
+ await this.withTx(async () => {
127
+ await this.db.run(
128
+ `INSERT OR REPLACE INTO ${this.swaps} (id, status, created_at, data)
129
+ VALUES (?, ?, ?, ?)`,
130
+ [swap.id, swap.status, swap.createdAt, JSON.stringify(swap)]
131
+ );
132
+ });
133
+ }
134
+ async getAllSwaps() {
135
+ await this.ensureInit();
136
+ const rows = await this.db.all(`SELECT data FROM ${this.swaps}`);
137
+ return rows.map((r) => JSON.parse(r.data));
138
+ }
139
+ async saveRfqSwap(record) {
140
+ await this.ensureInit();
141
+ await this.withTx(async () => {
142
+ await this.db.run(
143
+ `INSERT OR REPLACE INTO ${this.rfqSwaps} (rfq_id, state, updated_at, data)
144
+ VALUES (?, ?, ?, ?)`,
145
+ [record.rfqId, record.state, record.updatedAt, JSON.stringify(record)]
146
+ );
147
+ });
148
+ }
149
+ async getRfqSwap(rfqId) {
150
+ await this.ensureInit();
151
+ const row = await this.db.get(
152
+ `SELECT data FROM ${this.rfqSwaps} WHERE rfq_id = ?`,
153
+ [rfqId]
154
+ );
155
+ return row ? JSON.parse(row.data) : void 0;
156
+ }
157
+ async getAllRfqSwaps() {
158
+ await this.ensureInit();
159
+ const rows = await this.db.all(`SELECT data FROM ${this.rfqSwaps}`);
160
+ return rows.map((r) => JSON.parse(r.data));
161
+ }
162
+ async removeRfqSwap(rfqId) {
163
+ await this.ensureInit();
164
+ await this.withTx(async () => {
165
+ await this.db.run(`DELETE FROM ${this.rfqSwaps} WHERE rfq_id = ?`, [rfqId]);
166
+ });
167
+ }
168
+ async saveSwapRecord(record) {
169
+ await this.ensureInit();
170
+ await this.withTx(async () => {
171
+ await this.db.run(
172
+ `INSERT OR REPLACE INTO ${this.swapRecords} (id, family, updated_at, data)
173
+ VALUES (?, ?, ?, ?)`,
174
+ [record.id, record.family, record.updatedAt, JSON.stringify(record)]
175
+ );
176
+ });
177
+ }
178
+ async getSwapRecord(id) {
179
+ await this.ensureInit();
180
+ const row = await this.db.get(
181
+ `SELECT data FROM ${this.swapRecords} WHERE id = ?`,
182
+ [id]
183
+ );
184
+ return row ? JSON.parse(row.data) : void 0;
185
+ }
186
+ async getAllSwapRecords() {
187
+ await this.ensureInit();
188
+ const rows = await this.db.all(`SELECT data FROM ${this.swapRecords}`);
189
+ return rows.map((r) => JSON.parse(r.data));
190
+ }
191
+ async removeSwapRecord(id) {
192
+ await this.ensureInit();
193
+ await this.withTx(async () => {
194
+ await this.db.run(`DELETE FROM ${this.swapRecords} WHERE id = ?`, [id]);
195
+ });
196
+ }
197
+ async getScannedTxids() {
198
+ await this.ensureInit();
199
+ const rows = await this.db.all(`SELECT txid FROM ${this.scanned}`);
200
+ return new Set(rows.map((r) => r.txid));
201
+ }
202
+ async markTxidsScanned(txids) {
203
+ await this.ensureInit();
204
+ const all = [...txids];
205
+ if (all.length === 0) return;
206
+ await this.withTx(async () => {
207
+ for (let i = 0; i < all.length; i += INSERT_CHUNK) {
208
+ const chunk = all.slice(i, i + INSERT_CHUNK);
209
+ await this.db.run(
210
+ `INSERT OR IGNORE INTO ${this.scanned} (txid) VALUES ${chunk.map(() => "(?)").join(", ")}`,
211
+ chunk
212
+ );
213
+ }
214
+ });
215
+ }
216
+ async getCachedMarkets(network, registry) {
217
+ await this.ensureInit();
218
+ const row = await this.db.get(
219
+ `SELECT data FROM ${this.markets} WHERE cache_key = ?`,
220
+ [marketsCacheKey(network, registry)]
221
+ );
222
+ return row ? JSON.parse(row.data) : void 0;
223
+ }
224
+ async saveCachedMarkets(network, registry, entry) {
225
+ await this.ensureInit();
226
+ await this.withTx(async () => {
227
+ await this.db.run(
228
+ `INSERT OR REPLACE INTO ${this.markets} (cache_key, data) VALUES (?, ?)`,
229
+ [marketsCacheKey(network, registry), JSON.stringify(entry)]
230
+ );
231
+ });
232
+ }
233
+ /** Every table in one transaction: clearing swaps but keeping scanned txids
234
+ * would leave the restore scan permanently skipping those funding txs, so a
235
+ * partial clear must not be observable. */
236
+ async clear() {
237
+ await this.ensureInit();
238
+ await this.withTx(async () => {
239
+ await this.db.run(`DELETE FROM ${this.swaps}`);
240
+ await this.db.run(`DELETE FROM ${this.rfqSwaps}`);
241
+ await this.db.run(`DELETE FROM ${this.swapRecords}`);
242
+ await this.db.run(`DELETE FROM ${this.scanned}`);
243
+ await this.db.run(`DELETE FROM ${this.markets}`);
244
+ });
245
+ }
246
+ async [Symbol.asyncDispose]() {
247
+ }
248
+ };
249
+
250
+ // src/node/executor.ts
251
+ var bindable = (params) => (params ?? []).map((p) => p === void 0 ? null : p);
252
+ var createNodeSqlExecutor = (path) => {
253
+ mkdirSync(dirname(path), { recursive: true });
254
+ const db = new DatabaseSync(path);
255
+ let open = true;
256
+ return {
257
+ async run(sql, params) {
258
+ db.prepare(sql).run(...bindable(params));
259
+ },
260
+ async get(sql, params) {
261
+ return db.prepare(sql).get(...bindable(params)) ?? void 0;
262
+ },
263
+ async all(sql, params) {
264
+ return db.prepare(sql).all(...bindable(params));
265
+ },
266
+ async close() {
267
+ if (!open) return;
268
+ open = false;
269
+ db.close();
270
+ }
271
+ };
272
+ };
273
+ var nodeSwapRepository = (options) => {
274
+ const executor = createNodeSqlExecutor(options.path ?? swapDatabasePath(options.network));
275
+ return new NodeSwapRepository(
276
+ executor,
277
+ options.prefix === void 0 ? void 0 : { prefix: options.prefix }
278
+ );
279
+ };
280
+ var NodeSwapRepository = class extends SQLiteAssetSwapRepository {
281
+ constructor(executor, options) {
282
+ super(executor, options);
283
+ this.executor = executor;
284
+ }
285
+ executor;
286
+ async [Symbol.asyncDispose]() {
287
+ await this.executor.close();
288
+ }
289
+ };
290
+ export {
291
+ configDir,
292
+ createNodeSqlExecutor,
293
+ nodeSwapRepository,
294
+ swapDatabasePath
295
+ };
package/dist/nostr.cjs CHANGED
@@ -82,11 +82,14 @@ var LIGHTNING_RECEIVE_PAIR = rfqPair(LIGHTNING_BTC, ARKADE_BTC);
82
82
  var ONCHAIN_SEND_PAIR = rfqPair(ARKADE_BTC, ONCHAIN_BTC);
83
83
  var ONCHAIN_RECEIVE_PAIR = rfqPair(ONCHAIN_BTC, ARKADE_BTC);
84
84
  var SwapRefusal = class extends Error {
85
+ /** Literal-typed so the v2 error taxonomy's union discriminates on `name`
86
+ * — a `string` here collapses the discriminant for every member. Same value
87
+ * the constructor has always set, moved to a field initializer. */
88
+ name = "SwapRefusal";
85
89
  reason;
86
90
  rfqId;
87
91
  constructor(reason, rfqId) {
88
92
  super(`solver refused: ${reason}`);
89
- this.name = "SwapRefusal";
90
93
  this.reason = reason;
91
94
  this.rfqId = rfqId;
92
95
  }
package/dist/nostr.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as RfqTransport } from './rfq-DzsmhXX3.cjs';
1
+ import { R as RfqTransport } from './rfq-D0KGjmnn.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 { R as RfqTransport } from './rfq-DzsmhXX3.js';
1
+ import { R as RfqTransport } from './rfq-D0KGjmnn.js';
2
2
  import { SimplePool } from 'nostr-tools';
3
3
  import '@arkade-os/sdk';
4
4
 
package/dist/nostr.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  expectQuote,
3
3
  pairOf
4
- } from "./chunk-XXWOODUE.js";
4
+ } from "./chunk-OEKSNYJW.js";
5
5
 
6
6
  // src/nostr.ts
7
7
  import {
@@ -23,6 +23,8 @@ __export(realm_exports, {
23
23
  ArkadeAssetSwapMarketsCacheSchema: () => ArkadeAssetSwapMarketsCacheSchema,
24
24
  ArkadeAssetSwapScannedTxidSchema: () => ArkadeAssetSwapScannedTxidSchema,
25
25
  ArkadeAssetSwapSchema: () => ArkadeAssetSwapSchema,
26
+ ArkadeRfqSwapSchema: () => ArkadeRfqSwapSchema,
27
+ ArkadeSwapRecordSchema: () => ArkadeSwapRecordSchema,
26
28
  AssetSwapRealmSchemas: () => AssetSwapRealmSchemas,
27
29
  RealmAssetSwapRepository: () => RealmAssetSwapRepository
28
30
  });
@@ -34,6 +36,7 @@ var marketsCacheKey = (network, registry) => `arkade-intents-markets-${network}-
34
36
  // src/repositories/realm/repository.ts
35
37
  var SWAPS = "ArkadeAssetSwap";
36
38
  var RFQ_SWAPS = "ArkadeRfqSwap";
39
+ var SWAP_RECORDS = "ArkadeSwapRecord";
37
40
  var SCANNED = "ArkadeAssetSwapScannedTxid";
38
41
  var MARKETS = "ArkadeAssetSwapMarketsCache";
39
42
  var RealmAssetSwapRepository = class {
@@ -41,7 +44,7 @@ var RealmAssetSwapRepository = class {
41
44
  this.realm = realm;
42
45
  }
43
46
  realm;
44
- version = 4;
47
+ version = 5;
45
48
  async saveSwap(swap) {
46
49
  this.realm.write(() => {
47
50
  this.realm.create(
@@ -93,6 +96,38 @@ var RealmAssetSwapRepository = class {
93
96
  );
94
97
  });
95
98
  }
99
+ async saveSwapRecord(record) {
100
+ this.realm.write(() => {
101
+ this.realm.create(
102
+ SWAP_RECORDS,
103
+ {
104
+ id: record.id,
105
+ family: record.family,
106
+ updatedAt: record.updatedAt,
107
+ data: JSON.stringify(record)
108
+ },
109
+ "modified"
110
+ );
111
+ });
112
+ }
113
+ async getSwapRecord(id) {
114
+ const [found] = [
115
+ ...this.realm.objects(SWAP_RECORDS).filtered("id == $0", id)
116
+ ];
117
+ return found ? JSON.parse(found.data) : void 0;
118
+ }
119
+ async getAllSwapRecords() {
120
+ return [...this.realm.objects(SWAP_RECORDS)].map(
121
+ (o) => JSON.parse(o.data)
122
+ );
123
+ }
124
+ async removeSwapRecord(id) {
125
+ this.realm.write(() => {
126
+ this.realm.delete(
127
+ this.realm.objects(SWAP_RECORDS).filtered("id == $0", id)
128
+ );
129
+ });
130
+ }
96
131
  async getScannedTxids() {
97
132
  return new Set([...this.realm.objects(SCANNED)].map((o) => o.txid));
98
133
  }
@@ -121,7 +156,7 @@ var RealmAssetSwapRepository = class {
121
156
  * partial clear must not be observable. */
122
157
  async clear() {
123
158
  this.realm.write(() => {
124
- for (const name of [SWAPS, RFQ_SWAPS, SCANNED, MARKETS]) {
159
+ for (const name of [SWAPS, RFQ_SWAPS, SWAP_RECORDS, SCANNED, MARKETS]) {
125
160
  this.realm.delete(this.realm.objects(name));
126
161
  }
127
162
  });
@@ -166,8 +201,19 @@ var ArkadeRfqSwapSchema = {
166
201
  data: "string"
167
202
  }
168
203
  };
204
+ var ArkadeSwapRecordSchema = {
205
+ name: "ArkadeSwapRecord",
206
+ primaryKey: "id",
207
+ properties: {
208
+ id: "string",
209
+ family: "string",
210
+ updatedAt: "int",
211
+ data: "string"
212
+ }
213
+ };
169
214
  var AssetSwapRealmSchemas = [
170
215
  ArkadeRfqSwapSchema,
216
+ ArkadeSwapRecordSchema,
171
217
  ArkadeAssetSwapSchema,
172
218
  ArkadeAssetSwapScannedTxidSchema,
173
219
  ArkadeAssetSwapMarketsCacheSchema
@@ -177,6 +223,8 @@ var AssetSwapRealmSchemas = [
177
223
  ArkadeAssetSwapMarketsCacheSchema,
178
224
  ArkadeAssetSwapScannedTxidSchema,
179
225
  ArkadeAssetSwapSchema,
226
+ ArkadeRfqSwapSchema,
227
+ ArkadeSwapRecordSchema,
180
228
  AssetSwapRealmSchemas,
181
229
  RealmAssetSwapRepository
182
230
  });
@@ -1,8 +1,8 @@
1
1
  import { RealmLike } from '@arkade-os/sdk/repositories/realm';
2
- import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-DaK1RzRq.cjs';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, b as SwapRecord, M as MarketsCacheEntry } from '../../repository-oeW8KZo1.cjs';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-DzsmhXX3.cjs';
5
+ import '../../rfq-D0KGjmnn.cjs';
6
6
 
7
7
  /**
8
8
  * Realm backend for React Native.
@@ -26,7 +26,7 @@ import '../../rfq-DzsmhXX3.cjs';
26
26
  */
27
27
  declare class RealmAssetSwapRepository implements AssetSwapRepository {
28
28
  private readonly realm;
29
- readonly version: 4;
29
+ readonly version: 5;
30
30
  constructor(realm: RealmLike);
31
31
  saveSwap(swap: AssetSwap): Promise<void>;
32
32
  getAllSwaps(): Promise<AssetSwap[]>;
@@ -34,6 +34,10 @@ declare class RealmAssetSwapRepository implements AssetSwapRepository {
34
34
  getRfqSwap(rfqId: string): Promise<RfqSwapRecord | undefined>;
35
35
  getAllRfqSwaps(): Promise<RfqSwapRecord[]>;
36
36
  removeRfqSwap(rfqId: string): Promise<void>;
37
+ saveSwapRecord(record: SwapRecord): Promise<void>;
38
+ getSwapRecord(id: string): Promise<SwapRecord | undefined>;
39
+ getAllSwapRecords(): Promise<SwapRecord[]>;
40
+ removeSwapRecord(id: string): Promise<void>;
37
41
  getScannedTxids(): Promise<Set<string>>;
38
42
  markTxidsScanned(txids: Iterable<string>): Promise<void>;
39
43
  getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
@@ -49,8 +53,8 @@ declare class RealmAssetSwapRepository implements AssetSwapRepository {
49
53
  * Realm object schemas for the asset-swap repository.
50
54
  *
51
55
  * The names land in the **consuming application's** schema namespace, next to
52
- * its own models and the SDK's `Ark*` / the Boltz plugin's `Boltz*`, so they
53
- * are prefixed with `ArkadeAssetSwap`. Unlike the SQLite backend there is no
56
+ * its own models and the SDK's `Ark*`, so they are prefixed with
57
+ * `ArkadeAssetSwap`. Unlike the SQLite backend there is no
54
58
  * prefix option: a Realm schema name is baked into the schema objects the
55
59
  * consumer registers and into every `realm.objects(…)` call here.
56
60
  *
@@ -59,10 +63,12 @@ declare class RealmAssetSwapRepository implements AssetSwapRepository {
59
63
  * adds them to its Realm config and bumps its own `schemaVersion`; no migration
60
64
  * helper ships here.
61
65
  *
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.
66
+ * `ArkadeRfqSwap` arrived after the first three, and `ArkadeSwapRecord` after
67
+ * that. A consumer already shipping the earlier set has to add the new one and
68
+ * bump `schemaVersion` again — Realm creates schemas on open, so a config that
69
+ * lists four while the code reads five fails on the fifth `realm.objects(…)`
70
+ * rather than at open. Export {@link AssetSwapRealmSchemas} into the config
71
+ * rather than listing names by hand and the mismatch cannot happen.
66
72
  */
67
73
  declare const ArkadeAssetSwapSchema: {
68
74
  name: string;
@@ -89,6 +95,36 @@ declare const ArkadeAssetSwapMarketsCacheSchema: {
89
95
  data: string;
90
96
  };
91
97
  };
98
+ /** Monitored RFQ swaps, keyed by `rfqId`. `state` and `updatedAt` are mapped out
99
+ * for querying and for the retention sweep (`shouldRetainRfqSwap`); the record
100
+ * itself goes in whole, `profile` included. */
101
+ declare const ArkadeRfqSwapSchema: {
102
+ name: string;
103
+ primaryKey: string;
104
+ properties: {
105
+ rfqId: string;
106
+ state: string;
107
+ updatedAt: string;
108
+ data: string;
109
+ };
110
+ };
111
+ /**
112
+ * The v2 client's accept records, keyed by the client-minted quote id.
113
+ *
114
+ * `family` and `updatedAt` are mapped out for querying; the record itself goes
115
+ * in whole, which is what keeps a nested corridor `profile` from being lost the
116
+ * way a field-mapped schema could lose it.
117
+ */
118
+ declare const ArkadeSwapRecordSchema: {
119
+ name: string;
120
+ primaryKey: string;
121
+ properties: {
122
+ id: string;
123
+ family: string;
124
+ updatedAt: string;
125
+ data: string;
126
+ };
127
+ };
92
128
  declare const AssetSwapRealmSchemas: ({
93
129
  name: string;
94
130
  primaryKey: string;
@@ -120,6 +156,15 @@ declare const AssetSwapRealmSchemas: ({
120
156
  updatedAt: string;
121
157
  data: string;
122
158
  };
159
+ } | {
160
+ name: string;
161
+ primaryKey: string;
162
+ properties: {
163
+ id: string;
164
+ family: string;
165
+ updatedAt: string;
166
+ data: string;
167
+ };
123
168
  })[];
124
169
 
125
- export { ArkadeAssetSwapMarketsCacheSchema, ArkadeAssetSwapScannedTxidSchema, ArkadeAssetSwapSchema, AssetSwapRealmSchemas, RealmAssetSwapRepository };
170
+ export { ArkadeAssetSwapMarketsCacheSchema, ArkadeAssetSwapScannedTxidSchema, ArkadeAssetSwapSchema, ArkadeRfqSwapSchema, ArkadeSwapRecordSchema, AssetSwapRealmSchemas, RealmAssetSwapRepository };
@@ -1,8 +1,8 @@
1
1
  import { RealmLike } from '@arkade-os/sdk/repositories/realm';
2
- import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-DlLvj_y6.js';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, b as SwapRecord, M as MarketsCacheEntry } from '../../repository-DoR-ahHc.js';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-DzsmhXX3.js';
5
+ import '../../rfq-D0KGjmnn.js';
6
6
 
7
7
  /**
8
8
  * Realm backend for React Native.
@@ -26,7 +26,7 @@ import '../../rfq-DzsmhXX3.js';
26
26
  */
27
27
  declare class RealmAssetSwapRepository implements AssetSwapRepository {
28
28
  private readonly realm;
29
- readonly version: 4;
29
+ readonly version: 5;
30
30
  constructor(realm: RealmLike);
31
31
  saveSwap(swap: AssetSwap): Promise<void>;
32
32
  getAllSwaps(): Promise<AssetSwap[]>;
@@ -34,6 +34,10 @@ declare class RealmAssetSwapRepository implements AssetSwapRepository {
34
34
  getRfqSwap(rfqId: string): Promise<RfqSwapRecord | undefined>;
35
35
  getAllRfqSwaps(): Promise<RfqSwapRecord[]>;
36
36
  removeRfqSwap(rfqId: string): Promise<void>;
37
+ saveSwapRecord(record: SwapRecord): Promise<void>;
38
+ getSwapRecord(id: string): Promise<SwapRecord | undefined>;
39
+ getAllSwapRecords(): Promise<SwapRecord[]>;
40
+ removeSwapRecord(id: string): Promise<void>;
37
41
  getScannedTxids(): Promise<Set<string>>;
38
42
  markTxidsScanned(txids: Iterable<string>): Promise<void>;
39
43
  getCachedMarkets(network: string, registry: string): Promise<MarketsCacheEntry | undefined>;
@@ -49,8 +53,8 @@ declare class RealmAssetSwapRepository implements AssetSwapRepository {
49
53
  * Realm object schemas for the asset-swap repository.
50
54
  *
51
55
  * The names land in the **consuming application's** schema namespace, next to
52
- * its own models and the SDK's `Ark*` / the Boltz plugin's `Boltz*`, so they
53
- * are prefixed with `ArkadeAssetSwap`. Unlike the SQLite backend there is no
56
+ * its own models and the SDK's `Ark*`, so they are prefixed with
57
+ * `ArkadeAssetSwap`. Unlike the SQLite backend there is no
54
58
  * prefix option: a Realm schema name is baked into the schema objects the
55
59
  * consumer registers and into every `realm.objects(…)` call here.
56
60
  *
@@ -59,10 +63,12 @@ declare class RealmAssetSwapRepository implements AssetSwapRepository {
59
63
  * adds them to its Realm config and bumps its own `schemaVersion`; no migration
60
64
  * helper ships here.
61
65
  *
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.
66
+ * `ArkadeRfqSwap` arrived after the first three, and `ArkadeSwapRecord` after
67
+ * that. A consumer already shipping the earlier set has to add the new one and
68
+ * bump `schemaVersion` again — Realm creates schemas on open, so a config that
69
+ * lists four while the code reads five fails on the fifth `realm.objects(…)`
70
+ * rather than at open. Export {@link AssetSwapRealmSchemas} into the config
71
+ * rather than listing names by hand and the mismatch cannot happen.
66
72
  */
67
73
  declare const ArkadeAssetSwapSchema: {
68
74
  name: string;
@@ -89,6 +95,36 @@ declare const ArkadeAssetSwapMarketsCacheSchema: {
89
95
  data: string;
90
96
  };
91
97
  };
98
+ /** Monitored RFQ swaps, keyed by `rfqId`. `state` and `updatedAt` are mapped out
99
+ * for querying and for the retention sweep (`shouldRetainRfqSwap`); the record
100
+ * itself goes in whole, `profile` included. */
101
+ declare const ArkadeRfqSwapSchema: {
102
+ name: string;
103
+ primaryKey: string;
104
+ properties: {
105
+ rfqId: string;
106
+ state: string;
107
+ updatedAt: string;
108
+ data: string;
109
+ };
110
+ };
111
+ /**
112
+ * The v2 client's accept records, keyed by the client-minted quote id.
113
+ *
114
+ * `family` and `updatedAt` are mapped out for querying; the record itself goes
115
+ * in whole, which is what keeps a nested corridor `profile` from being lost the
116
+ * way a field-mapped schema could lose it.
117
+ */
118
+ declare const ArkadeSwapRecordSchema: {
119
+ name: string;
120
+ primaryKey: string;
121
+ properties: {
122
+ id: string;
123
+ family: string;
124
+ updatedAt: string;
125
+ data: string;
126
+ };
127
+ };
92
128
  declare const AssetSwapRealmSchemas: ({
93
129
  name: string;
94
130
  primaryKey: string;
@@ -120,6 +156,15 @@ declare const AssetSwapRealmSchemas: ({
120
156
  updatedAt: string;
121
157
  data: string;
122
158
  };
159
+ } | {
160
+ name: string;
161
+ primaryKey: string;
162
+ properties: {
163
+ id: string;
164
+ family: string;
165
+ updatedAt: string;
166
+ data: string;
167
+ };
123
168
  })[];
124
169
 
125
- export { ArkadeAssetSwapMarketsCacheSchema, ArkadeAssetSwapScannedTxidSchema, ArkadeAssetSwapSchema, AssetSwapRealmSchemas, RealmAssetSwapRepository };
170
+ export { ArkadeAssetSwapMarketsCacheSchema, ArkadeAssetSwapScannedTxidSchema, ArkadeAssetSwapSchema, ArkadeRfqSwapSchema, ArkadeSwapRecordSchema, AssetSwapRealmSchemas, RealmAssetSwapRepository };