@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,8 +1,8 @@
1
- import { scriptFromArkAddress, legacyVtxoFacts, serializeVtxo, isVtxoForScript, serializeUtxo, serializeAssets, deserializeVtxo, deserializeUtxo, deserializeAssets, intentMatchesFilter, intentPageBounds, isTerminalIntentState, mergeChainedTxType } from '../../chunk-M2ZUPLKQ.js';
2
- export { ChainedTxType } from '../../chunk-M2ZUPLKQ.js';
3
- import '../../chunk-WSQAWSEH.js';
4
- import '../../chunk-OMJRW2D5.js';
5
- import '../../chunk-CMLSTGOC.js';
1
+ import { scriptFromArkAddress, legacyVtxoFacts, serializeVtxo, createdAtToIso, assertPageRequest, pageResult, checkSaveVtxosForScript, serializeUtxo, assertHistoryPageFilter, serializeAssets, deserializeVtxo, deserializeUtxo, deserializeAssets, contractFilterMatchesNothing, intentMatchesFilter, isTerminalIntentState, mergeChainedTxType } from '../../chunk-IV2252XM.js';
2
+ export { ChainedTxType } from '../../chunk-IV2252XM.js';
3
+ import '../../chunk-3JLYJ5KZ.js';
4
+ import '../../chunk-JOUPIZ32.js';
5
+ import { isVtxoSpent } from '../../chunk-EJYWGTZ7.js';
6
6
 
7
7
  // src/repositories/sqlite/transaction.ts
8
8
  var writeChains = /* @__PURE__ */ new WeakMap();
@@ -29,11 +29,18 @@ function runInTransaction(db, fn) {
29
29
  return run;
30
30
  }
31
31
 
32
+ // src/repositories/sqlite/prefix.ts
33
+ var SAFE_PREFIX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
34
+ function sanitizeTablePrefix(p) {
35
+ if (!SAFE_PREFIX.test(p)) throw new Error(`Invalid table prefix "${p}"`);
36
+ return p;
37
+ }
38
+
32
39
  // src/repositories/sqlite/walletRepository.ts
33
40
  var SQLiteWalletRepository = class {
34
41
  constructor(db, options) {
35
42
  this.db = db;
36
- this.prefix = sanitizePrefix(options?.prefix ?? "ark_");
43
+ this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
37
44
  this.tables = {
38
45
  vtxos: `${this.prefix}vtxos`,
39
46
  utxos: `${this.prefix}utxos`,
@@ -42,7 +49,7 @@ var SQLiteWalletRepository = class {
42
49
  };
43
50
  }
44
51
  db;
45
- version = 1;
52
+ version = 2;
46
53
  initPromise = null;
47
54
  prefix;
48
55
  tables;
@@ -98,23 +105,42 @@ var SQLiteWalletRepository = class {
98
105
  await this.db.run(
99
106
  `CREATE INDEX IF NOT EXISTS idx_${this.prefix}vtxos_script ON ${this.tables.vtxos} (script)`
100
107
  );
108
+ await this.db.run(
109
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}vtxos_script_page ON ${this.tables.vtxos} (script, address, txid, vout)`
110
+ );
111
+ await this.db.run(
112
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}vtxos_address_page ON ${this.tables.vtxos} (address, txid, vout)`
113
+ );
114
+ await this.db.run(`DROP INDEX IF EXISTS idx_${this.prefix}vtxos_live_script`);
115
+ await this.db.run(
116
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}vtxos_live_script_page ON ${this.tables.vtxos} (script, address, txid, vout)
117
+ WHERE ${UNSPENT_VTXO_PREDICATE}`
118
+ );
101
119
  await this.db.run(
102
120
  `CREATE INDEX IF NOT EXISTS idx_${this.prefix}utxos_address ON ${this.tables.utxos} (address)`
103
121
  );
122
+ await this.db.run(
123
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}utxos_address_page ON ${this.tables.utxos} (address, txid, vout)`
124
+ );
104
125
  await this.db.run(
105
126
  `CREATE INDEX IF NOT EXISTS idx_${this.prefix}transactions_address ON ${this.tables.transactions} (address)`
106
127
  );
128
+ await this.db.run(
129
+ `CREATE INDEX IF NOT EXISTS idx_${this.prefix}transactions_history ON ${this.tables.transactions} (address, created_at, boarding_txid, commitment_txid, ark_txid)`
130
+ );
107
131
  }
108
132
  /**
109
133
  * Bring the `vtxos` table to the current schema (v1 = `script` NOT NULL).
110
134
  *
111
- * Three cases:
135
+ * Four cases:
112
136
  * - Fresh install: create the v1 schema directly.
113
137
  * - Legacy install without a `script` column: add it, backfill from
114
138
  * `address`, then rebuild the table with NOT NULL (SQLite cannot add
115
139
  * the NOT NULL constraint in place).
116
140
  * - Legacy install with a nullable `script` column: backfill the NULLs
117
141
  * and rebuild.
142
+ * - 0.4.x install: `script` is already NOT NULL but `virtual_status_json
143
+ * NOT NULL` is still there, and `saveVtxos` no longer writes it.
118
144
  *
119
145
  * The backfill derives `script` from the Ark address, matching what the
120
146
  * indexer would have returned — new rows from the indexer always carry a
@@ -158,10 +184,11 @@ var SQLiteWalletRepository = class {
158
184
  addedCanonicalColumns = true;
159
185
  }
160
186
  }
161
- if (addedCanonicalColumns && cols.some((c) => c.name === "virtual_status_json")) {
187
+ const hasLegacyBlob = cols.some((c) => c.name === "virtual_status_json");
188
+ if (addedCanonicalColumns && hasLegacyBlob) {
162
189
  await this.backfillCanonicalVtxoColumns();
163
190
  }
164
- if (scriptCol && scriptCol.notnull === 1) {
191
+ if (scriptCol && scriptCol.notnull === 1 && !hasLegacyBlob) {
165
192
  return;
166
193
  }
167
194
  if (!scriptCol) {
@@ -273,13 +300,8 @@ var SQLiteWalletRepository = class {
273
300
  await this.db.run(`DELETE FROM ${this.tables.walletState}`);
274
301
  }
275
302
  // ── VTXO management ────────────────────────────────────────────────
276
- async getVtxos(address) {
277
- await this.ensureInit();
278
- const rows = await this.db.all(
279
- `SELECT * FROM ${this.tables.vtxos} WHERE address = ?`,
280
- [address]
281
- );
282
- return rows.map(vtxoRowToDomain);
303
+ async getVtxosPage(address, page) {
304
+ return this.pageByAddress(this.tables.vtxos, address, page, vtxoRowToDomain);
283
305
  }
284
306
  async saveVtxos(address, vtxos) {
285
307
  await this.ensureInit();
@@ -310,13 +332,13 @@ var SQLiteWalletRepository = class {
310
332
  s.intentTapLeafScript.cb,
311
333
  s.intentTapLeafScript.s,
312
334
  JSON.stringify(s.status),
313
- typeof s.createdAt === "string" ? s.createdAt : s.createdAt instanceof Date ? s.createdAt.toISOString() : new Date(s.createdAt).toISOString(),
335
+ createdAtToIso(s.createdAt),
314
336
  s.isUnrolled ? 1 : 0,
315
337
  s.isSpent === void 0 ? null : s.isSpent ? 1 : 0,
316
338
  s.isSwept === void 0 ? null : s.isSwept ? 1 : 0,
317
339
  s.isPreconfirmed === void 0 ? null : s.isPreconfirmed ? 1 : 0,
318
340
  s.commitmentTxIds ? JSON.stringify(s.commitmentTxIds) : null,
319
- s.expiresAt === void 0 ? null : s.expiresAt instanceof Date ? s.expiresAt.toISOString() : new Date(s.expiresAt).toISOString(),
341
+ s.expiresAt === void 0 ? null : new Date(s.expiresAt).toISOString(),
320
342
  s.expiresAtHeight ?? null,
321
343
  s.spentBy ?? null,
322
344
  s.settledBy ?? null,
@@ -332,39 +354,53 @@ var SQLiteWalletRepository = class {
332
354
  await this.ensureInit();
333
355
  await this.db.run(`DELETE FROM ${this.tables.vtxos} WHERE address = ?`, [address]);
334
356
  }
335
- async getVtxosForScript(script) {
357
+ async getVtxosForScriptPage(script, page, options) {
358
+ assertPageRequest(page);
336
359
  await this.ensureInit();
360
+ const after = page.after;
337
361
  const rows = await this.db.all(
338
- `SELECT * FROM ${this.tables.vtxos} WHERE script = ?`,
339
- [script]
362
+ `SELECT * FROM ${this.tables.vtxos} WHERE script = ?
363
+ ${options?.unspentOnly ? `AND ${UNSPENT_VTXO_PREDICATE}` : ""}
364
+ ${after ? "AND (address > ? OR (address = ? AND (txid > ? OR (txid = ? AND vout > ?))))" : ""}
365
+ ORDER BY address, txid, vout LIMIT ?`,
366
+ after ? [
367
+ script,
368
+ after.address,
369
+ after.address,
370
+ after.txid,
371
+ after.txid,
372
+ after.vout,
373
+ page.limit + 1
374
+ ] : [script, page.limit + 1]
340
375
  );
341
- return rows.map(vtxoRowToDomain);
376
+ const result = pageResult(
377
+ rows.map((row) => ({ address: row.address, vtxo: vtxoRowToDomain(row) })),
378
+ page.limit,
379
+ (row) => ({ address: row.address, txid: row.vtxo.txid, vout: row.vtxo.vout })
380
+ );
381
+ return options?.unspentOnly ? { ...result, items: result.items.filter((row) => !isVtxoSpent(row.vtxo)) } : result;
342
382
  }
343
383
  async saveVtxosForScript(key, vtxos) {
344
- if (!key.address) {
345
- throw new Error("SQLiteWalletRepository requires an address");
346
- }
347
- for (const vtxo of vtxos) {
348
- if (!isVtxoForScript(vtxo, key.script)) {
349
- throw new Error(
350
- `VTXO ${vtxo.txid}:${vtxo.vout} script mismatch: expected ${key.script}, got ${vtxo.script}`
351
- );
352
- }
353
- }
354
- return this.saveVtxos(key.address, vtxos);
384
+ return this.saveVtxos(checkSaveVtxosForScript("SQLiteWalletRepository", key, vtxos), vtxos);
355
385
  }
356
386
  async deleteVtxosForScript(script) {
357
387
  await this.ensureInit();
358
388
  await this.db.run(`DELETE FROM ${this.tables.vtxos} WHERE script = ?`, [script]);
359
389
  }
360
390
  // ── UTXO management ────────────────────────────────────────────────
361
- async getUtxos(address) {
391
+ async getUtxosPage(address, page) {
392
+ return this.pageByAddress(this.tables.utxos, address, page, utxoRowToDomain);
393
+ }
394
+ async pageByAddress(table, address, page, deserialize) {
395
+ assertPageRequest(page);
362
396
  await this.ensureInit();
363
397
  const rows = await this.db.all(
364
- `SELECT * FROM ${this.tables.utxos} WHERE address = ?`,
365
- [address]
398
+ `SELECT * FROM ${table} WHERE address = ? AND (txid, vout) > (?, ?)
399
+ ORDER BY txid, vout LIMIT ?`,
400
+ [address, page.after?.txid ?? "", page.after?.vout ?? -1, page.limit + 1]
366
401
  );
367
- return rows.map(utxoRowToDomain);
402
+ const result = pageResult(rows, page.limit, ({ txid, vout }) => ({ txid, vout }));
403
+ return { items: result.items.map(deserialize), nextCursor: result.nextCursor };
368
404
  }
369
405
  async saveUtxos(address, utxos) {
370
406
  await this.ensureInit();
@@ -399,13 +435,36 @@ var SQLiteWalletRepository = class {
399
435
  await this.db.run(`DELETE FROM ${this.tables.utxos} WHERE address = ?`, [address]);
400
436
  }
401
437
  // ── Transaction history ────────────────────────────────────────────
402
- async getTransactionHistory(address) {
438
+ async getTransactionHistoryPage(filter, page) {
439
+ assertPageRequest(page);
440
+ assertHistoryPageFilter(filter);
403
441
  await this.ensureInit();
442
+ const conditions = ["address = ?"];
443
+ const params = [filter.address];
444
+ if (filter.since !== void 0) {
445
+ conditions.push("created_at >= ?");
446
+ params.push(filter.since);
447
+ }
448
+ if (page.after !== void 0) {
449
+ conditions.push(
450
+ "(created_at, boarding_txid, commitment_txid, ark_txid) > (?, ?, ?, ?)"
451
+ );
452
+ params.push(
453
+ page.after.createdAt,
454
+ page.after.key.boardingTxid,
455
+ page.after.key.commitmentTxid,
456
+ page.after.key.arkTxid
457
+ );
458
+ }
404
459
  const rows = await this.db.all(
405
- `SELECT * FROM ${this.tables.transactions} WHERE address = ? ORDER BY created_at ASC`,
406
- [address]
460
+ `SELECT * FROM ${this.tables.transactions} WHERE ${conditions.join(" AND ")}
461
+ ORDER BY created_at, boarding_txid, commitment_txid, ark_txid LIMIT ?`,
462
+ [...params, page.limit + 1]
407
463
  );
408
- return rows.map(txRowToDomain);
464
+ return pageResult(rows.map(txRowToDomain), page.limit, (tx) => ({
465
+ createdAt: tx.createdAt,
466
+ key: tx.key
467
+ }));
409
468
  }
410
469
  async saveTransactions(address, txs) {
411
470
  await this.ensureInit();
@@ -463,15 +522,7 @@ var SQLiteWalletRepository = class {
463
522
  );
464
523
  }
465
524
  };
466
- var SAFE_PREFIX = /^[a-zA-Z0-9_]+$/;
467
- function sanitizePrefix(prefix) {
468
- if (!SAFE_PREFIX.test(prefix)) {
469
- throw new Error(
470
- `Invalid table prefix "${prefix}": only letters, digits, and underscores are allowed`
471
- );
472
- }
473
- return prefix;
474
- }
525
+ 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 = '')";
475
526
  function vtxoRowToDomain(row) {
476
527
  const serialized = {
477
528
  txid: row.txid,
@@ -548,11 +599,11 @@ function txRowToDomain(row) {
548
599
  var SQLiteContractRepository = class {
549
600
  constructor(db, options) {
550
601
  this.db = db;
551
- this.prefix = sanitizePrefix2(options?.prefix ?? "ark_");
602
+ this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
552
603
  this.table = `${this.prefix}contracts`;
553
604
  }
554
605
  db;
555
- version = 2;
606
+ version = 3;
556
607
  initPromise = null;
557
608
  prefix;
558
609
  table;
@@ -599,8 +650,10 @@ var SQLiteContractRepository = class {
599
650
  await this.db.run(`DELETE FROM ${this.table}`);
600
651
  }
601
652
  // ── Contract management ────────────────────────────────────────────
602
- async getContracts(filter) {
653
+ async getContractsPage(filter, page) {
654
+ assertPageRequest(page);
603
655
  await this.ensureInit();
656
+ if (contractFilterMatchesNothing(filter)) return { items: [] };
604
657
  const conditions = [];
605
658
  const params = [];
606
659
  if (filter) {
@@ -609,12 +662,16 @@ var SQLiteContractRepository = class {
609
662
  this.addFilterCondition(conditions, params, "type", filter.type);
610
663
  this.addWatchCondition(conditions, params, filter.watch);
611
664
  }
612
- let sql = `SELECT * FROM ${this.table}`;
613
- if (conditions.length > 0) {
614
- sql += ` WHERE ${conditions.join(" AND ")}`;
665
+ if (page.after !== void 0) {
666
+ conditions.push("script > ?");
667
+ params.push(page.after);
615
668
  }
616
- const rows = await this.db.all(sql, params);
617
- return rows.map(contractRowToDomain);
669
+ const where = conditions.length ? ` WHERE ${conditions.join(" AND ")}` : "";
670
+ const rows = await this.db.all(
671
+ `SELECT * FROM ${this.table}${where} ORDER BY script LIMIT ?`,
672
+ [...params, page.limit + 1]
673
+ );
674
+ return pageResult(rows.map(contractRowToDomain), page.limit, (contract) => contract.script);
618
675
  }
619
676
  async saveContract(contract) {
620
677
  await this.ensureInit();
@@ -668,15 +725,6 @@ var SQLiteContractRepository = class {
668
725
  params.push(...wanted);
669
726
  }
670
727
  };
671
- var SAFE_PREFIX2 = /^[a-zA-Z0-9_]+$/;
672
- function sanitizePrefix2(prefix) {
673
- if (!SAFE_PREFIX2.test(prefix)) {
674
- throw new Error(
675
- `Invalid table prefix "${prefix}": only letters, digits, and underscores are allowed`
676
- );
677
- }
678
- return prefix;
679
- }
680
728
  function contractRowToDomain(row) {
681
729
  const contract = {
682
730
  script: row.script,
@@ -699,15 +747,10 @@ function contractRowToDomain(row) {
699
747
  }
700
748
 
701
749
  // src/repositories/sqlite/intentRepository.ts
702
- var SAFE_PREFIX3 = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
703
- function sanitizePrefix3(p) {
704
- if (!SAFE_PREFIX3.test(p)) throw new Error(`Invalid table prefix "${p}"`);
705
- return p;
706
- }
707
750
  var SQLiteIntentRepository = class {
708
751
  constructor(db, options) {
709
752
  this.db = db;
710
- this.prefix = sanitizePrefix3(options?.prefix ?? "ark_");
753
+ this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
711
754
  this.t = `${this.prefix}intents`;
712
755
  }
713
756
  db;
@@ -746,19 +789,16 @@ var SQLiteIntentRepository = class {
746
789
  `CREATE INDEX IF NOT EXISTS idx_${this.prefix}intent_state ON ${this.t} (state)`
747
790
  );
748
791
  }
749
- withTx(fn) {
750
- return runInTransaction(this.db, fn);
751
- }
752
792
  async clear() {
753
793
  await this.ensureInit();
754
- await this.withTx(async () => {
794
+ await runInTransaction(this.db, async () => {
755
795
  await this.db.run(`DELETE FROM ${this.t}`);
756
796
  });
757
797
  }
758
798
  async saveIntent(intent) {
759
799
  await this.ensureInit();
760
800
  const now = Date.now();
761
- await this.withTx(async () => {
801
+ await runInTransaction(this.db, async () => {
762
802
  await this.db.run(
763
803
  `INSERT INTO ${this.t}
764
804
  (intent_tx_id, intent_id, state, valid_from, valid_until,
@@ -806,15 +846,30 @@ var SQLiteIntentRepository = class {
806
846
  );
807
847
  });
808
848
  }
809
- async getIntents(filter) {
849
+ async getIntentsPage(filter, page) {
850
+ assertPageRequest(page);
810
851
  await this.ensureInit();
811
- const rows = await this.db.all(
812
- `SELECT * FROM ${this.t} ORDER BY created_at ASC, intent_tx_id ASC`
813
- );
814
- let out = rows.map(rowToIntent);
815
- if (filter) out = out.filter((i) => intentMatchesFilter(i, filter));
816
- const { skip, end } = intentPageBounds(filter, out.length);
817
- return out.slice(skip, end);
852
+ if (filter?.states?.length === 0) return { items: [] };
853
+ const stateSql = filter?.states ? ` AND state IN (${filter.states.map(() => "?").join(", ")})` : "";
854
+ const stateParams = filter?.states ?? [];
855
+ const batchSize = Math.max(64, page.limit + 1);
856
+ const rows = [];
857
+ let after = page.after;
858
+ while (rows.length <= page.limit) {
859
+ const batch = await this.db.all(
860
+ `SELECT * FROM ${this.t} WHERE intent_tx_id > ?${stateSql} ORDER BY intent_tx_id LIMIT ?`,
861
+ [after ?? "", ...stateParams, batchSize]
862
+ );
863
+ if (batch.length === 0) break;
864
+ for (const row of batch) {
865
+ after = row.intent_tx_id;
866
+ const intent = rowToIntent(row);
867
+ if (!filter || intentMatchesFilter(intent, filter)) rows.push(intent);
868
+ if (rows.length > page.limit) break;
869
+ }
870
+ if (batch.length < batchSize) break;
871
+ }
872
+ return pageResult(rows, page.limit, (intent) => intent.intentTxId);
818
873
  }
819
874
  async getLockedVtxoOutpoints() {
820
875
  await this.ensureInit();
@@ -852,15 +907,10 @@ function rowToIntent(r) {
852
907
  }
853
908
 
854
909
  // src/repositories/sqlite/virtualTxRepository.ts
855
- var SAFE_PREFIX4 = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
856
- function sanitizePrefix4(p) {
857
- if (!SAFE_PREFIX4.test(p)) throw new Error(`Invalid table prefix "${p}"`);
858
- return p;
859
- }
860
910
  var SQLiteVirtualTxRepository = class {
861
911
  constructor(db, options) {
862
912
  this.db = db;
863
- this.prefix = sanitizePrefix4(options?.prefix ?? "ark_");
913
+ this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
864
914
  this.tTx = `${this.prefix}virtual_txs`;
865
915
  this.tBranch = `${this.prefix}vtxo_branches`;
866
916
  }
@@ -892,12 +942,9 @@ var SQLiteVirtualTxRepository = class {
892
942
  `CREATE INDEX IF NOT EXISTS idx_${this.prefix}branch_vtxid ON ${this.tBranch} (virtual_txid)`
893
943
  );
894
944
  }
895
- tx(fn) {
896
- return runInTransaction(this.db, fn);
897
- }
898
945
  async clear() {
899
946
  await this.ensureInit();
900
- await this.tx(async () => {
947
+ await runInTransaction(this.db, async () => {
901
948
  await this.db.run(`DELETE FROM ${this.tTx}`);
902
949
  await this.db.run(`DELETE FROM ${this.tBranch}`);
903
950
  });
@@ -905,7 +952,7 @@ var SQLiteVirtualTxRepository = class {
905
952
  async upsertVirtualTxs(txs) {
906
953
  if (txs.length === 0) return;
907
954
  await this.ensureInit();
908
- await this.tx(async () => {
955
+ await runInTransaction(this.db, async () => {
909
956
  const placeholders = txs.map(() => "?").join(", ");
910
957
  const existing = await this.db.all(
911
958
  `SELECT * FROM ${this.tTx} WHERE txid IN (${placeholders})`,
@@ -932,7 +979,7 @@ var SQLiteVirtualTxRepository = class {
932
979
  }
933
980
  async setBranch(vtxo, branch) {
934
981
  await this.ensureInit();
935
- await this.tx(async () => {
982
+ await runInTransaction(this.db, async () => {
936
983
  await this.db.run(`DELETE FROM ${this.tBranch} WHERE vtxo_txid = ? AND vtxo_vout = ?`, [
937
984
  vtxo.txid,
938
985
  vtxo.vout
@@ -967,7 +1014,7 @@ var SQLiteVirtualTxRepository = class {
967
1014
  }
968
1015
  async pruneForSpentVtxo(vtxo) {
969
1016
  await this.ensureInit();
970
- await this.tx(async () => {
1017
+ await runInTransaction(this.db, async () => {
971
1018
  const removed = await this.db.all(
972
1019
  `SELECT DISTINCT virtual_txid FROM ${this.tBranch} WHERE vtxo_txid = ? AND vtxo_vout = ?`,
973
1020
  [vtxo.txid, vtxo.vout]
@@ -1000,13 +1047,6 @@ function rowToTx(r) {
1000
1047
  };
1001
1048
  }
1002
1049
 
1003
- // src/repositories/sqlite/prefix.ts
1004
- var SAFE_PREFIX5 = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
1005
- function sanitizeTablePrefix(p) {
1006
- if (!SAFE_PREFIX5.test(p)) throw new Error(`Invalid table prefix "${p}"`);
1007
- return p;
1008
- }
1009
-
1010
1050
  export { SQLiteContractRepository, SQLiteIntentRepository, SQLiteVirtualTxRepository, SQLiteWalletRepository, runInTransaction, sanitizeTablePrefix };
1011
1051
  //# sourceMappingURL=index.js.map
1012
1052
  //# sourceMappingURL=index.js.map