@arkade-os/sdk 0.5.0-rc.11 → 0.5.0-rc.13

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 (94) hide show
  1. package/README.md +43 -12
  2. package/dist/adapters/expo.cjs +5 -5
  3. package/dist/adapters/expo.d.cts +2 -2
  4. package/dist/adapters/expo.d.ts +2 -2
  5. package/dist/adapters/expo.js +3 -3
  6. package/dist/{asyncStorageTaskQueue-DBaZsltv.d.cts → asyncStorageTaskQueue-0EeSeCAt.d.cts} +1 -1
  7. package/dist/{asyncStorageTaskQueue-uAG3XLyg.d.ts → asyncStorageTaskQueue-DV94jhwq.d.ts} +1 -1
  8. package/dist/{chunk-WSQAWSEH.js → chunk-3JLYJ5KZ.js} +75 -237
  9. package/dist/chunk-3JLYJ5KZ.js.map +1 -0
  10. package/dist/{chunk-VMLLYEYM.js → chunk-4EU2Q6YT.js} +12 -14
  11. package/dist/chunk-4EU2Q6YT.js.map +1 -0
  12. package/dist/{chunk-IA32YGLH.cjs → chunk-7BACS4XK.cjs} +10 -10
  13. package/dist/chunk-7BACS4XK.cjs.map +1 -0
  14. package/dist/{chunk-5OBGYL6U.cjs → chunk-7NK6XFC3.cjs} +120 -194
  15. package/dist/chunk-7NK6XFC3.cjs.map +1 -0
  16. package/dist/{chunk-CQPQ7D4U.cjs → chunk-BFQX2KS3.cjs} +87 -248
  17. package/dist/chunk-BFQX2KS3.cjs.map +1 -0
  18. package/dist/{chunk-DD6MTNAS.js → chunk-D7JLTHSZ.js} +5 -5
  19. package/dist/chunk-D7JLTHSZ.js.map +1 -0
  20. package/dist/{chunk-CMLSTGOC.js → chunk-EJYWGTZ7.js} +119 -194
  21. package/dist/chunk-EJYWGTZ7.js.map +1 -0
  22. package/dist/{chunk-T2ILYGWE.cjs → chunk-FDQQOF3F.cjs} +327 -1080
  23. package/dist/chunk-FDQQOF3F.cjs.map +1 -0
  24. package/dist/{chunk-MGDXN74N.cjs → chunk-I4YBVHAK.cjs} +2357 -3374
  25. package/dist/chunk-I4YBVHAK.cjs.map +1 -0
  26. package/dist/{chunk-M2ZUPLKQ.js → chunk-IV2252XM.js} +1946 -2977
  27. package/dist/chunk-IV2252XM.js.map +1 -0
  28. package/dist/{chunk-OMJRW2D5.js → chunk-JOUPIZ32.js} +263 -1036
  29. package/dist/chunk-JOUPIZ32.js.map +1 -0
  30. package/dist/{chunk-PWEBQNIE.cjs → chunk-RDQSVIXD.cjs} +22 -24
  31. package/dist/chunk-RDQSVIXD.cjs.map +1 -0
  32. package/dist/contracts/handlers/index.cjs +9 -9
  33. package/dist/contracts/handlers/index.d.cts +3 -3
  34. package/dist/contracts/handlers/index.d.ts +3 -3
  35. package/dist/contracts/handlers/index.js +2 -2
  36. package/dist/{delegate-DFwlkVYR.d.cts → delegate-BgpUJW5B.d.cts} +1 -1
  37. package/dist/{delegate-D3YHDERL.d.ts → delegate-BuagcGnG.d.ts} +1 -1
  38. package/dist/{index-DTvUv5lD.d.cts → index-CKmB14Yu.d.cts} +1145 -2263
  39. package/dist/{index-DTvUv5lD.d.ts → index-CKmB14Yu.d.ts} +1145 -2263
  40. package/dist/index-D0BuYwhF.d.cts +637 -0
  41. package/dist/index-DbzyrqK7.d.ts +637 -0
  42. package/dist/index.cjs +341 -297
  43. package/dist/index.d.cts +379 -788
  44. package/dist/index.d.ts +379 -788
  45. package/dist/index.js +4 -4
  46. package/dist/repositories/realm/index.cjs +142 -101
  47. package/dist/repositories/realm/index.cjs.map +1 -1
  48. package/dist/repositories/realm/index.d.cts +13 -11
  49. package/dist/repositories/realm/index.d.ts +13 -11
  50. package/dist/repositories/realm/index.js +130 -89
  51. package/dist/repositories/realm/index.js.map +1 -1
  52. package/dist/repositories/sqlite/index.cjs +158 -118
  53. package/dist/repositories/sqlite/index.cjs.map +1 -1
  54. package/dist/repositories/sqlite/index.d.cts +14 -13
  55. package/dist/repositories/sqlite/index.d.ts +14 -13
  56. package/dist/repositories/sqlite/index.js +147 -107
  57. package/dist/repositories/sqlite/index.js.map +1 -1
  58. package/dist/{taskRunner-B5bl0YRt.d.ts → taskRunner-BX-pB0sv.d.ts} +1 -1
  59. package/dist/{taskRunner--sKy9Inv.d.cts → taskRunner-DJrFFyus.d.cts} +1 -1
  60. package/dist/wallet/expo/background.cjs +14 -14
  61. package/dist/wallet/expo/background.cjs.map +1 -1
  62. package/dist/wallet/expo/background.d.cts +8 -14
  63. package/dist/wallet/expo/background.d.ts +8 -14
  64. package/dist/wallet/expo/background.js +6 -6
  65. package/dist/wallet/expo/background.js.map +1 -1
  66. package/dist/wallet/expo/index.cjs +14 -14
  67. package/dist/wallet/expo/index.cjs.map +1 -1
  68. package/dist/wallet/expo/index.d.cts +5 -5
  69. package/dist/wallet/expo/index.d.ts +5 -5
  70. package/dist/wallet/expo/index.js +5 -5
  71. package/dist/wallet/expo/index.js.map +1 -1
  72. package/dist/wallet-BsL2G3Qb.d.cts +1542 -0
  73. package/dist/wallet-DXNiCmq8.d.ts +1542 -0
  74. package/dist/worker/expo/index.cjs +9 -9
  75. package/dist/worker/expo/index.d.cts +4 -4
  76. package/dist/worker/expo/index.d.ts +4 -4
  77. package/dist/worker/expo/index.js +5 -5
  78. package/package.json +3 -2
  79. package/dist/chunk-5OBGYL6U.cjs.map +0 -1
  80. package/dist/chunk-CMLSTGOC.js.map +0 -1
  81. package/dist/chunk-CQPQ7D4U.cjs.map +0 -1
  82. package/dist/chunk-DD6MTNAS.js.map +0 -1
  83. package/dist/chunk-IA32YGLH.cjs.map +0 -1
  84. package/dist/chunk-M2ZUPLKQ.js.map +0 -1
  85. package/dist/chunk-MGDXN74N.cjs.map +0 -1
  86. package/dist/chunk-OMJRW2D5.js.map +0 -1
  87. package/dist/chunk-PWEBQNIE.cjs.map +0 -1
  88. package/dist/chunk-T2ILYGWE.cjs.map +0 -1
  89. package/dist/chunk-VMLLYEYM.js.map +0 -1
  90. package/dist/chunk-WSQAWSEH.js.map +0 -1
  91. package/dist/hdWalletCapable-C350s3bP.d.ts +0 -2206
  92. package/dist/hdWalletCapable-rrOmXcbT.d.cts +0 -2206
  93. package/dist/index-C0ZyGoyP.d.cts +0 -850
  94. package/dist/index-DASN1cVk.d.ts +0 -850
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var chunkMGDXN74N_cjs = require('../../chunk-MGDXN74N.cjs');
4
- require('../../chunk-CQPQ7D4U.cjs');
5
- require('../../chunk-T2ILYGWE.cjs');
6
- require('../../chunk-5OBGYL6U.cjs');
3
+ var chunkI4YBVHAK_cjs = require('../../chunk-I4YBVHAK.cjs');
4
+ require('../../chunk-BFQX2KS3.cjs');
5
+ require('../../chunk-FDQQOF3F.cjs');
6
+ var chunk7NK6XFC3_cjs = require('../../chunk-7NK6XFC3.cjs');
7
7
 
8
8
  // src/repositories/sqlite/transaction.ts
9
9
  var writeChains = /* @__PURE__ */ new WeakMap();
@@ -30,11 +30,18 @@ function runInTransaction(db, fn) {
30
30
  return run;
31
31
  }
32
32
 
33
+ // src/repositories/sqlite/prefix.ts
34
+ var SAFE_PREFIX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
35
+ function sanitizeTablePrefix(p) {
36
+ if (!SAFE_PREFIX.test(p)) throw new Error(`Invalid table prefix "${p}"`);
37
+ return p;
38
+ }
39
+
33
40
  // src/repositories/sqlite/walletRepository.ts
34
41
  var SQLiteWalletRepository = class {
35
42
  constructor(db, options) {
36
43
  this.db = db;
37
- this.prefix = sanitizePrefix(options?.prefix ?? "ark_");
44
+ this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
38
45
  this.tables = {
39
46
  vtxos: `${this.prefix}vtxos`,
40
47
  utxos: `${this.prefix}utxos`,
@@ -43,7 +50,7 @@ var SQLiteWalletRepository = class {
43
50
  };
44
51
  }
45
52
  db;
46
- version = 1;
53
+ version = 2;
47
54
  initPromise = null;
48
55
  prefix;
49
56
  tables;
@@ -99,23 +106,42 @@ var SQLiteWalletRepository = class {
99
106
  await this.db.run(
100
107
  `CREATE INDEX IF NOT EXISTS idx_${this.prefix}vtxos_script ON ${this.tables.vtxos} (script)`
101
108
  );
109
+ await this.db.run(
110
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}vtxos_script_page ON ${this.tables.vtxos} (script, address, txid, vout)`
111
+ );
112
+ await this.db.run(
113
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}vtxos_address_page ON ${this.tables.vtxos} (address, txid, vout)`
114
+ );
115
+ await this.db.run(`DROP INDEX IF EXISTS idx_${this.prefix}vtxos_live_script`);
116
+ await this.db.run(
117
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}vtxos_live_script_page ON ${this.tables.vtxos} (script, address, txid, vout)
118
+ WHERE ${UNSPENT_VTXO_PREDICATE}`
119
+ );
102
120
  await this.db.run(
103
121
  `CREATE INDEX IF NOT EXISTS idx_${this.prefix}utxos_address ON ${this.tables.utxos} (address)`
104
122
  );
123
+ await this.db.run(
124
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}utxos_address_page ON ${this.tables.utxos} (address, txid, vout)`
125
+ );
105
126
  await this.db.run(
106
127
  `CREATE INDEX IF NOT EXISTS idx_${this.prefix}transactions_address ON ${this.tables.transactions} (address)`
107
128
  );
129
+ await this.db.run(
130
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}transactions_history ON ${this.tables.transactions} (address, created_at, boarding_txid, commitment_txid, ark_txid)`
131
+ );
108
132
  }
109
133
  /**
110
134
  * Bring the `vtxos` table to the current schema (v1 = `script` NOT NULL).
111
135
  *
112
- * Three cases:
136
+ * Four cases:
113
137
  * - Fresh install: create the v1 schema directly.
114
138
  * - Legacy install without a `script` column: add it, backfill from
115
139
  * `address`, then rebuild the table with NOT NULL (SQLite cannot add
116
140
  * the NOT NULL constraint in place).
117
141
  * - Legacy install with a nullable `script` column: backfill the NULLs
118
142
  * and rebuild.
143
+ * - 0.4.x install: `script` is already NOT NULL but `virtual_status_json
144
+ * NOT NULL` is still there, and `saveVtxos` no longer writes it.
119
145
  *
120
146
  * The backfill derives `script` from the Ark address, matching what the
121
147
  * indexer would have returned — new rows from the indexer always carry a
@@ -159,10 +185,11 @@ var SQLiteWalletRepository = class {
159
185
  addedCanonicalColumns = true;
160
186
  }
161
187
  }
162
- if (addedCanonicalColumns && cols.some((c) => c.name === "virtual_status_json")) {
188
+ const hasLegacyBlob = cols.some((c) => c.name === "virtual_status_json");
189
+ if (addedCanonicalColumns && hasLegacyBlob) {
163
190
  await this.backfillCanonicalVtxoColumns();
164
191
  }
165
- if (scriptCol && scriptCol.notnull === 1) {
192
+ if (scriptCol && scriptCol.notnull === 1 && !hasLegacyBlob) {
166
193
  return;
167
194
  }
168
195
  if (!scriptCol) {
@@ -172,7 +199,7 @@ var SQLiteWalletRepository = class {
172
199
  for (const row of nullRows) {
173
200
  await this.db.run(
174
201
  `UPDATE ${this.tables.vtxos} SET script = ? WHERE txid = ? AND vout = ?`,
175
- [chunkMGDXN74N_cjs.scriptFromArkAddress(row.address), row.txid, row.vout]
202
+ [chunkI4YBVHAK_cjs.scriptFromArkAddress(row.address), row.txid, row.vout]
176
203
  );
177
204
  }
178
205
  const tempName = `${this.tables.vtxos}__migrate_tmp`;
@@ -213,7 +240,7 @@ var SQLiteWalletRepository = class {
213
240
  WHERE virtual_status_json IS NOT NULL AND is_swept IS NULL`
214
241
  );
215
242
  for (const row of rows) {
216
- const facts = chunkMGDXN74N_cjs.legacyVtxoFacts(row.virtual_status_json);
243
+ const facts = chunkI4YBVHAK_cjs.legacyVtxoFacts(row.virtual_status_json);
217
244
  if (!facts) continue;
218
245
  await this.db.run(
219
246
  `UPDATE ${this.tables.vtxos}
@@ -274,18 +301,13 @@ var SQLiteWalletRepository = class {
274
301
  await this.db.run(`DELETE FROM ${this.tables.walletState}`);
275
302
  }
276
303
  // ── VTXO management ────────────────────────────────────────────────
277
- async getVtxos(address) {
278
- await this.ensureInit();
279
- const rows = await this.db.all(
280
- `SELECT * FROM ${this.tables.vtxos} WHERE address = ?`,
281
- [address]
282
- );
283
- return rows.map(vtxoRowToDomain);
304
+ async getVtxosPage(address, page) {
305
+ return this.pageByAddress(this.tables.vtxos, address, page, vtxoRowToDomain);
284
306
  }
285
307
  async saveVtxos(address, vtxos) {
286
308
  await this.ensureInit();
287
309
  for (const vtxo of vtxos) {
288
- const s = chunkMGDXN74N_cjs.serializeVtxo(vtxo);
310
+ const s = chunkI4YBVHAK_cjs.serializeVtxo(vtxo);
289
311
  await this.db.run(
290
312
  `INSERT OR REPLACE INTO ${this.tables.vtxos}
291
313
  (txid, vout, value, address,
@@ -311,13 +333,13 @@ var SQLiteWalletRepository = class {
311
333
  s.intentTapLeafScript.cb,
312
334
  s.intentTapLeafScript.s,
313
335
  JSON.stringify(s.status),
314
- typeof s.createdAt === "string" ? s.createdAt : s.createdAt instanceof Date ? s.createdAt.toISOString() : new Date(s.createdAt).toISOString(),
336
+ chunkI4YBVHAK_cjs.createdAtToIso(s.createdAt),
315
337
  s.isUnrolled ? 1 : 0,
316
338
  s.isSpent === void 0 ? null : s.isSpent ? 1 : 0,
317
339
  s.isSwept === void 0 ? null : s.isSwept ? 1 : 0,
318
340
  s.isPreconfirmed === void 0 ? null : s.isPreconfirmed ? 1 : 0,
319
341
  s.commitmentTxIds ? JSON.stringify(s.commitmentTxIds) : null,
320
- s.expiresAt === void 0 ? null : s.expiresAt instanceof Date ? s.expiresAt.toISOString() : new Date(s.expiresAt).toISOString(),
342
+ s.expiresAt === void 0 ? null : new Date(s.expiresAt).toISOString(),
321
343
  s.expiresAtHeight ?? null,
322
344
  s.spentBy ?? null,
323
345
  s.settledBy ?? null,
@@ -333,44 +355,58 @@ var SQLiteWalletRepository = class {
333
355
  await this.ensureInit();
334
356
  await this.db.run(`DELETE FROM ${this.tables.vtxos} WHERE address = ?`, [address]);
335
357
  }
336
- async getVtxosForScript(script) {
358
+ async getVtxosForScriptPage(script, page, options) {
359
+ chunkI4YBVHAK_cjs.assertPageRequest(page);
337
360
  await this.ensureInit();
361
+ const after = page.after;
338
362
  const rows = await this.db.all(
339
- `SELECT * FROM ${this.tables.vtxos} WHERE script = ?`,
340
- [script]
363
+ `SELECT * FROM ${this.tables.vtxos} WHERE script = ?
364
+ ${options?.unspentOnly ? `AND ${UNSPENT_VTXO_PREDICATE}` : ""}
365
+ ${after ? "AND (address > ? OR (address = ? AND (txid > ? OR (txid = ? AND vout > ?))))" : ""}
366
+ ORDER BY address, txid, vout LIMIT ?`,
367
+ after ? [
368
+ script,
369
+ after.address,
370
+ after.address,
371
+ after.txid,
372
+ after.txid,
373
+ after.vout,
374
+ page.limit + 1
375
+ ] : [script, page.limit + 1]
341
376
  );
342
- return rows.map(vtxoRowToDomain);
377
+ const result = chunkI4YBVHAK_cjs.pageResult(
378
+ rows.map((row) => ({ address: row.address, vtxo: vtxoRowToDomain(row) })),
379
+ page.limit,
380
+ (row) => ({ address: row.address, txid: row.vtxo.txid, vout: row.vtxo.vout })
381
+ );
382
+ return options?.unspentOnly ? { ...result, items: result.items.filter((row) => !chunk7NK6XFC3_cjs.isVtxoSpent(row.vtxo)) } : result;
343
383
  }
344
384
  async saveVtxosForScript(key, vtxos) {
345
- if (!key.address) {
346
- throw new Error("SQLiteWalletRepository requires an address");
347
- }
348
- for (const vtxo of vtxos) {
349
- if (!chunkMGDXN74N_cjs.isVtxoForScript(vtxo, key.script)) {
350
- throw new Error(
351
- `VTXO ${vtxo.txid}:${vtxo.vout} script mismatch: expected ${key.script}, got ${vtxo.script}`
352
- );
353
- }
354
- }
355
- return this.saveVtxos(key.address, vtxos);
385
+ return this.saveVtxos(chunkI4YBVHAK_cjs.checkSaveVtxosForScript("SQLiteWalletRepository", key, vtxos), vtxos);
356
386
  }
357
387
  async deleteVtxosForScript(script) {
358
388
  await this.ensureInit();
359
389
  await this.db.run(`DELETE FROM ${this.tables.vtxos} WHERE script = ?`, [script]);
360
390
  }
361
391
  // ── UTXO management ────────────────────────────────────────────────
362
- async getUtxos(address) {
392
+ async getUtxosPage(address, page) {
393
+ return this.pageByAddress(this.tables.utxos, address, page, utxoRowToDomain);
394
+ }
395
+ async pageByAddress(table, address, page, deserialize) {
396
+ chunkI4YBVHAK_cjs.assertPageRequest(page);
363
397
  await this.ensureInit();
364
398
  const rows = await this.db.all(
365
- `SELECT * FROM ${this.tables.utxos} WHERE address = ?`,
366
- [address]
399
+ `SELECT * FROM ${table} WHERE address = ? AND (txid, vout) > (?, ?)
400
+ ORDER BY txid, vout LIMIT ?`,
401
+ [address, page.after?.txid ?? "", page.after?.vout ?? -1, page.limit + 1]
367
402
  );
368
- return rows.map(utxoRowToDomain);
403
+ const result = chunkI4YBVHAK_cjs.pageResult(rows, page.limit, ({ txid, vout }) => ({ txid, vout }));
404
+ return { items: result.items.map(deserialize), nextCursor: result.nextCursor };
369
405
  }
370
406
  async saveUtxos(address, utxos) {
371
407
  await this.ensureInit();
372
408
  for (const utxo of utxos) {
373
- const s = chunkMGDXN74N_cjs.serializeUtxo(utxo);
409
+ const s = chunkI4YBVHAK_cjs.serializeUtxo(utxo);
374
410
  await this.db.run(
375
411
  `INSERT OR REPLACE INTO ${this.tables.utxos}
376
412
  (txid, vout, value, address,
@@ -400,13 +436,36 @@ var SQLiteWalletRepository = class {
400
436
  await this.db.run(`DELETE FROM ${this.tables.utxos} WHERE address = ?`, [address]);
401
437
  }
402
438
  // ── Transaction history ────────────────────────────────────────────
403
- async getTransactionHistory(address) {
439
+ async getTransactionHistoryPage(filter, page) {
440
+ chunkI4YBVHAK_cjs.assertPageRequest(page);
441
+ chunkI4YBVHAK_cjs.assertHistoryPageFilter(filter);
404
442
  await this.ensureInit();
443
+ const conditions = ["address = ?"];
444
+ const params = [filter.address];
445
+ if (filter.since !== void 0) {
446
+ conditions.push("created_at >= ?");
447
+ params.push(filter.since);
448
+ }
449
+ if (page.after !== void 0) {
450
+ conditions.push(
451
+ "(created_at, boarding_txid, commitment_txid, ark_txid) > (?, ?, ?, ?)"
452
+ );
453
+ params.push(
454
+ page.after.createdAt,
455
+ page.after.key.boardingTxid,
456
+ page.after.key.commitmentTxid,
457
+ page.after.key.arkTxid
458
+ );
459
+ }
405
460
  const rows = await this.db.all(
406
- `SELECT * FROM ${this.tables.transactions} WHERE address = ? ORDER BY created_at ASC`,
407
- [address]
461
+ `SELECT * FROM ${this.tables.transactions} WHERE ${conditions.join(" AND ")}
462
+ ORDER BY created_at, boarding_txid, commitment_txid, ark_txid LIMIT ?`,
463
+ [...params, page.limit + 1]
408
464
  );
409
- return rows.map(txRowToDomain);
465
+ return chunkI4YBVHAK_cjs.pageResult(rows.map(txRowToDomain), page.limit, (tx) => ({
466
+ createdAt: tx.createdAt,
467
+ key: tx.key
468
+ }));
410
469
  }
411
470
  async saveTransactions(address, txs) {
412
471
  await this.ensureInit();
@@ -426,7 +485,7 @@ var SQLiteWalletRepository = class {
426
485
  tx.amount,
427
486
  tx.settled ? 1 : 0,
428
487
  tx.createdAt,
429
- tx.assets ? JSON.stringify(chunkMGDXN74N_cjs.serializeAssets(tx.assets)) : null
488
+ tx.assets ? JSON.stringify(chunkI4YBVHAK_cjs.serializeAssets(tx.assets)) : null
430
489
  ]
431
490
  );
432
491
  }
@@ -464,15 +523,7 @@ var SQLiteWalletRepository = class {
464
523
  );
465
524
  }
466
525
  };
467
- var SAFE_PREFIX = /^[a-zA-Z0-9_]+$/;
468
- function sanitizePrefix(prefix) {
469
- if (!SAFE_PREFIX.test(prefix)) {
470
- throw new Error(
471
- `Invalid table prefix "${prefix}": only letters, digits, and underscores are allowed`
472
- );
473
- }
474
- return prefix;
475
- }
526
+ var UNSPENT_VTXO_PREDICATE = "(is_spent IS NULL OR is_spent = 0) AND (spent_by IS NULL OR spent_by = '') AND (settled_by IS NULL OR settled_by = '')";
476
527
  function vtxoRowToDomain(row) {
477
528
  const serialized = {
478
529
  txid: row.txid,
@@ -504,9 +555,9 @@ function vtxoRowToDomain(row) {
504
555
  // Post-migration every row has `script`, but the backfill is
505
556
  // idempotent: derive from `address` if the legacy column is still
506
557
  // null (e.g. the migration hasn't run yet on this handle).
507
- script: row.script ?? chunkMGDXN74N_cjs.scriptFromArkAddress(row.address)
558
+ script: row.script ?? chunkI4YBVHAK_cjs.scriptFromArkAddress(row.address)
508
559
  };
509
- return chunkMGDXN74N_cjs.deserializeVtxo(serialized);
560
+ return chunkI4YBVHAK_cjs.deserializeVtxo(serialized);
510
561
  }
511
562
  function utxoRowToDomain(row) {
512
563
  const serialized = {
@@ -525,7 +576,7 @@ function utxoRowToDomain(row) {
525
576
  status: JSON.parse(row.status_json),
526
577
  extraWitness: row.extra_witness_json ? JSON.parse(row.extra_witness_json) : void 0
527
578
  };
528
- return chunkMGDXN74N_cjs.deserializeUtxo(serialized);
579
+ return chunkI4YBVHAK_cjs.deserializeUtxo(serialized);
529
580
  }
530
581
  function txRowToDomain(row) {
531
582
  const tx = {
@@ -540,7 +591,7 @@ function txRowToDomain(row) {
540
591
  createdAt: row.created_at
541
592
  };
542
593
  if (row.assets_json) {
543
- tx.assets = chunkMGDXN74N_cjs.deserializeAssets(JSON.parse(row.assets_json));
594
+ tx.assets = chunkI4YBVHAK_cjs.deserializeAssets(JSON.parse(row.assets_json));
544
595
  }
545
596
  return tx;
546
597
  }
@@ -549,11 +600,11 @@ function txRowToDomain(row) {
549
600
  var SQLiteContractRepository = class {
550
601
  constructor(db, options) {
551
602
  this.db = db;
552
- this.prefix = sanitizePrefix2(options?.prefix ?? "ark_");
603
+ this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
553
604
  this.table = `${this.prefix}contracts`;
554
605
  }
555
606
  db;
556
- version = 2;
607
+ version = 3;
557
608
  initPromise = null;
558
609
  prefix;
559
610
  table;
@@ -600,8 +651,10 @@ var SQLiteContractRepository = class {
600
651
  await this.db.run(`DELETE FROM ${this.table}`);
601
652
  }
602
653
  // ── Contract management ────────────────────────────────────────────
603
- async getContracts(filter) {
654
+ async getContractsPage(filter, page) {
655
+ chunkI4YBVHAK_cjs.assertPageRequest(page);
604
656
  await this.ensureInit();
657
+ if (chunkI4YBVHAK_cjs.contractFilterMatchesNothing(filter)) return { items: [] };
605
658
  const conditions = [];
606
659
  const params = [];
607
660
  if (filter) {
@@ -610,12 +663,16 @@ var SQLiteContractRepository = class {
610
663
  this.addFilterCondition(conditions, params, "type", filter.type);
611
664
  this.addWatchCondition(conditions, params, filter.watch);
612
665
  }
613
- let sql = `SELECT * FROM ${this.table}`;
614
- if (conditions.length > 0) {
615
- sql += ` WHERE ${conditions.join(" AND ")}`;
666
+ if (page.after !== void 0) {
667
+ conditions.push("script > ?");
668
+ params.push(page.after);
616
669
  }
617
- const rows = await this.db.all(sql, params);
618
- return rows.map(contractRowToDomain);
670
+ const where = conditions.length ? ` WHERE ${conditions.join(" AND ")}` : "";
671
+ const rows = await this.db.all(
672
+ `SELECT * FROM ${this.table}${where} ORDER BY script LIMIT ?`,
673
+ [...params, page.limit + 1]
674
+ );
675
+ return chunkI4YBVHAK_cjs.pageResult(rows.map(contractRowToDomain), page.limit, (contract) => contract.script);
619
676
  }
620
677
  async saveContract(contract) {
621
678
  await this.ensureInit();
@@ -669,15 +726,6 @@ var SQLiteContractRepository = class {
669
726
  params.push(...wanted);
670
727
  }
671
728
  };
672
- var SAFE_PREFIX2 = /^[a-zA-Z0-9_]+$/;
673
- function sanitizePrefix2(prefix) {
674
- if (!SAFE_PREFIX2.test(prefix)) {
675
- throw new Error(
676
- `Invalid table prefix "${prefix}": only letters, digits, and underscores are allowed`
677
- );
678
- }
679
- return prefix;
680
- }
681
729
  function contractRowToDomain(row) {
682
730
  const contract = {
683
731
  script: row.script,
@@ -700,15 +748,10 @@ function contractRowToDomain(row) {
700
748
  }
701
749
 
702
750
  // src/repositories/sqlite/intentRepository.ts
703
- var SAFE_PREFIX3 = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
704
- function sanitizePrefix3(p) {
705
- if (!SAFE_PREFIX3.test(p)) throw new Error(`Invalid table prefix "${p}"`);
706
- return p;
707
- }
708
751
  var SQLiteIntentRepository = class {
709
752
  constructor(db, options) {
710
753
  this.db = db;
711
- this.prefix = sanitizePrefix3(options?.prefix ?? "ark_");
754
+ this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
712
755
  this.t = `${this.prefix}intents`;
713
756
  }
714
757
  db;
@@ -747,19 +790,16 @@ var SQLiteIntentRepository = class {
747
790
  `CREATE INDEX IF NOT EXISTS idx_${this.prefix}intent_state ON ${this.t} (state)`
748
791
  );
749
792
  }
750
- withTx(fn) {
751
- return runInTransaction(this.db, fn);
752
- }
753
793
  async clear() {
754
794
  await this.ensureInit();
755
- await this.withTx(async () => {
795
+ await runInTransaction(this.db, async () => {
756
796
  await this.db.run(`DELETE FROM ${this.t}`);
757
797
  });
758
798
  }
759
799
  async saveIntent(intent) {
760
800
  await this.ensureInit();
761
801
  const now = Date.now();
762
- await this.withTx(async () => {
802
+ await runInTransaction(this.db, async () => {
763
803
  await this.db.run(
764
804
  `INSERT INTO ${this.t}
765
805
  (intent_tx_id, intent_id, state, valid_from, valid_until,
@@ -807,22 +847,37 @@ var SQLiteIntentRepository = class {
807
847
  );
808
848
  });
809
849
  }
810
- async getIntents(filter) {
850
+ async getIntentsPage(filter, page) {
851
+ chunkI4YBVHAK_cjs.assertPageRequest(page);
811
852
  await this.ensureInit();
812
- const rows = await this.db.all(
813
- `SELECT * FROM ${this.t} ORDER BY created_at ASC, intent_tx_id ASC`
814
- );
815
- let out = rows.map(rowToIntent);
816
- if (filter) out = out.filter((i) => chunkMGDXN74N_cjs.intentMatchesFilter(i, filter));
817
- const { skip, end } = chunkMGDXN74N_cjs.intentPageBounds(filter, out.length);
818
- return out.slice(skip, end);
853
+ if (filter?.states?.length === 0) return { items: [] };
854
+ const stateSql = filter?.states ? ` AND state IN (${filter.states.map(() => "?").join(", ")})` : "";
855
+ const stateParams = filter?.states ?? [];
856
+ const batchSize = Math.max(64, page.limit + 1);
857
+ const rows = [];
858
+ let after = page.after;
859
+ while (rows.length <= page.limit) {
860
+ const batch = await this.db.all(
861
+ `SELECT * FROM ${this.t} WHERE intent_tx_id > ?${stateSql} ORDER BY intent_tx_id LIMIT ?`,
862
+ [after ?? "", ...stateParams, batchSize]
863
+ );
864
+ if (batch.length === 0) break;
865
+ for (const row of batch) {
866
+ after = row.intent_tx_id;
867
+ const intent = rowToIntent(row);
868
+ if (!filter || chunkI4YBVHAK_cjs.intentMatchesFilter(intent, filter)) rows.push(intent);
869
+ if (rows.length > page.limit) break;
870
+ }
871
+ if (batch.length < batchSize) break;
872
+ }
873
+ return chunkI4YBVHAK_cjs.pageResult(rows, page.limit, (intent) => intent.intentTxId);
819
874
  }
820
875
  async getLockedVtxoOutpoints() {
821
876
  await this.ensureInit();
822
877
  const rows = await this.db.all(`SELECT * FROM ${this.t}`);
823
878
  const out = [];
824
879
  for (const r of rows) {
825
- if (chunkMGDXN74N_cjs.isTerminalIntentState(r.state)) continue;
880
+ if (chunkI4YBVHAK_cjs.isTerminalIntentState(r.state)) continue;
826
881
  for (const o of JSON.parse(r.intent_vtxos_json)) out.push(o);
827
882
  }
828
883
  return out;
@@ -853,15 +908,10 @@ function rowToIntent(r) {
853
908
  }
854
909
 
855
910
  // src/repositories/sqlite/virtualTxRepository.ts
856
- var SAFE_PREFIX4 = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
857
- function sanitizePrefix4(p) {
858
- if (!SAFE_PREFIX4.test(p)) throw new Error(`Invalid table prefix "${p}"`);
859
- return p;
860
- }
861
911
  var SQLiteVirtualTxRepository = class {
862
912
  constructor(db, options) {
863
913
  this.db = db;
864
- this.prefix = sanitizePrefix4(options?.prefix ?? "ark_");
914
+ this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
865
915
  this.tTx = `${this.prefix}virtual_txs`;
866
916
  this.tBranch = `${this.prefix}vtxo_branches`;
867
917
  }
@@ -893,12 +943,9 @@ var SQLiteVirtualTxRepository = class {
893
943
  `CREATE INDEX IF NOT EXISTS idx_${this.prefix}branch_vtxid ON ${this.tBranch} (virtual_txid)`
894
944
  );
895
945
  }
896
- tx(fn) {
897
- return runInTransaction(this.db, fn);
898
- }
899
946
  async clear() {
900
947
  await this.ensureInit();
901
- await this.tx(async () => {
948
+ await runInTransaction(this.db, async () => {
902
949
  await this.db.run(`DELETE FROM ${this.tTx}`);
903
950
  await this.db.run(`DELETE FROM ${this.tBranch}`);
904
951
  });
@@ -906,7 +953,7 @@ var SQLiteVirtualTxRepository = class {
906
953
  async upsertVirtualTxs(txs) {
907
954
  if (txs.length === 0) return;
908
955
  await this.ensureInit();
909
- await this.tx(async () => {
956
+ await runInTransaction(this.db, async () => {
910
957
  const placeholders = txs.map(() => "?").join(", ");
911
958
  const existing = await this.db.all(
912
959
  `SELECT * FROM ${this.tTx} WHERE txid IN (${placeholders})`,
@@ -917,7 +964,7 @@ var SQLiteVirtualTxRepository = class {
917
964
  const prev = prevByTxid.get(t.txid);
918
965
  const psbt = t.psbt ?? prev?.psbt ?? null;
919
966
  const expires = t.expiresAt ?? prev?.expires_at ?? null;
920
- const type = chunkMGDXN74N_cjs.mergeChainedTxType(t.type, prev?.type);
967
+ const type = chunkI4YBVHAK_cjs.mergeChainedTxType(t.type, prev?.type);
921
968
  await this.db.run(
922
969
  `INSERT OR REPLACE INTO ${this.tTx} (txid, psbt, expires_at, type) VALUES (?, ?, ?, ?)`,
923
970
  [t.txid, psbt, expires, type]
@@ -933,7 +980,7 @@ var SQLiteVirtualTxRepository = class {
933
980
  }
934
981
  async setBranch(vtxo, branch) {
935
982
  await this.ensureInit();
936
- await this.tx(async () => {
983
+ await runInTransaction(this.db, async () => {
937
984
  await this.db.run(`DELETE FROM ${this.tBranch} WHERE vtxo_txid = ? AND vtxo_vout = ?`, [
938
985
  vtxo.txid,
939
986
  vtxo.vout
@@ -968,7 +1015,7 @@ var SQLiteVirtualTxRepository = class {
968
1015
  }
969
1016
  async pruneForSpentVtxo(vtxo) {
970
1017
  await this.ensureInit();
971
- await this.tx(async () => {
1018
+ await runInTransaction(this.db, async () => {
972
1019
  const removed = await this.db.all(
973
1020
  `SELECT DISTINCT virtual_txid FROM ${this.tBranch} WHERE vtxo_txid = ? AND vtxo_vout = ?`,
974
1021
  [vtxo.txid, vtxo.vout]
@@ -1001,16 +1048,9 @@ function rowToTx(r) {
1001
1048
  };
1002
1049
  }
1003
1050
 
1004
- // src/repositories/sqlite/prefix.ts
1005
- var SAFE_PREFIX5 = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
1006
- function sanitizeTablePrefix(p) {
1007
- if (!SAFE_PREFIX5.test(p)) throw new Error(`Invalid table prefix "${p}"`);
1008
- return p;
1009
- }
1010
-
1011
1051
  Object.defineProperty(exports, "ChainedTxType", {
1012
1052
  enumerable: true,
1013
- get: function () { return chunkMGDXN74N_cjs.ChainedTxType; }
1053
+ get: function () { return chunkI4YBVHAK_cjs.ChainedTxType; }
1014
1054
  });
1015
1055
  exports.SQLiteContractRepository = SQLiteContractRepository;
1016
1056
  exports.SQLiteIntentRepository = SQLiteIntentRepository;