@arkade-os/sdk 0.4.15 → 0.4.16

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 (197) hide show
  1. package/README.md +102 -96
  2. package/dist/cjs/arkfee/estimator.js +1 -1
  3. package/dist/cjs/arkfee/types.js +2 -1
  4. package/dist/cjs/arknote/index.js +43 -4
  5. package/dist/cjs/bip322/index.js +1 -1
  6. package/dist/cjs/contracts/arkcontract.js +1 -1
  7. package/dist/cjs/contracts/contractManager.js +40 -24
  8. package/dist/cjs/contracts/contractWatcher.js +29 -22
  9. package/dist/cjs/contracts/handlers/default.js +1 -1
  10. package/dist/cjs/contracts/handlers/delegate.js +1 -1
  11. package/dist/cjs/contracts/handlers/helpers.js +1 -1
  12. package/dist/cjs/extension/asset/assetGroup.js +92 -5
  13. package/dist/cjs/extension/asset/assetId.js +67 -3
  14. package/dist/cjs/extension/asset/assetInput.js +18 -0
  15. package/dist/cjs/extension/asset/assetOutput.js +15 -0
  16. package/dist/cjs/extension/asset/assetRef.js +66 -0
  17. package/dist/cjs/extension/asset/metadata.js +15 -0
  18. package/dist/cjs/extension/asset/packet.js +4 -1
  19. package/dist/cjs/extension/index.js +1 -1
  20. package/dist/cjs/forfeit.js +14 -0
  21. package/dist/cjs/identity/seedIdentity.js +2 -2
  22. package/dist/cjs/identity/singleKey.js +4 -0
  23. package/dist/cjs/intent/index.js +28 -12
  24. package/dist/cjs/providers/ark.js +3 -2
  25. package/dist/cjs/providers/delegator.js +20 -1
  26. package/dist/cjs/providers/expoArk.js +2 -2
  27. package/dist/cjs/providers/indexer.js +2 -2
  28. package/dist/cjs/providers/onchain.js +2 -1
  29. package/dist/cjs/repositories/realm/schemas.js +2 -2
  30. package/dist/cjs/repositories/realm/types.js +1 -1
  31. package/dist/cjs/script/address.js +37 -6
  32. package/dist/cjs/script/base.js +70 -1
  33. package/dist/cjs/script/default.js +3 -0
  34. package/dist/cjs/script/delegate.js +4 -0
  35. package/dist/cjs/script/tapscript.js +17 -2
  36. package/dist/cjs/script/vhtlc.js +35 -27
  37. package/dist/cjs/storage/fileSystem.js +1 -1
  38. package/dist/cjs/storage/inMemory.js +1 -1
  39. package/dist/cjs/storage/indexedDB.js +1 -1
  40. package/dist/cjs/storage/localStorage.js +1 -1
  41. package/dist/cjs/tree/validation.js +1 -1
  42. package/dist/cjs/utils/arkTransaction.js +5 -5
  43. package/dist/cjs/utils/bip21.js +16 -3
  44. package/dist/cjs/utils/syncCursors.js +4 -4
  45. package/dist/cjs/utils/transaction.js +1 -1
  46. package/dist/cjs/utils/transactionHistory.js +11 -11
  47. package/dist/cjs/utils/unknownFields.js +3 -3
  48. package/dist/cjs/wallet/asset-manager.js +4 -4
  49. package/dist/cjs/wallet/batch.js +5 -5
  50. package/dist/cjs/wallet/delegator.js +9 -8
  51. package/dist/cjs/wallet/expo/background.js +3 -3
  52. package/dist/cjs/wallet/expo/wallet.js +7 -7
  53. package/dist/cjs/wallet/index.js +43 -0
  54. package/dist/cjs/wallet/onchain.js +43 -5
  55. package/dist/cjs/wallet/ramps.js +44 -14
  56. package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +22 -22
  57. package/dist/cjs/wallet/serviceWorker/wallet.js +28 -24
  58. package/dist/cjs/wallet/unroll.js +12 -8
  59. package/dist/cjs/wallet/utils.js +1 -1
  60. package/dist/cjs/wallet/vtxo-manager.js +122 -82
  61. package/dist/cjs/wallet/wallet.js +125 -67
  62. package/dist/cjs/worker/expo/asyncStorageTaskQueue.js +1 -1
  63. package/dist/cjs/worker/expo/processors/contractPollProcessor.js +2 -2
  64. package/dist/cjs/worker/expo/taskRunner.js +3 -3
  65. package/dist/cjs/worker/messageBus.js +3 -0
  66. package/dist/esm/arkfee/estimator.js +1 -1
  67. package/dist/esm/arkfee/types.js +2 -1
  68. package/dist/esm/arknote/index.js +43 -4
  69. package/dist/esm/bip322/index.js +1 -1
  70. package/dist/esm/contracts/arkcontract.js +1 -1
  71. package/dist/esm/contracts/contractManager.js +40 -24
  72. package/dist/esm/contracts/contractWatcher.js +29 -22
  73. package/dist/esm/contracts/handlers/default.js +1 -1
  74. package/dist/esm/contracts/handlers/delegate.js +1 -1
  75. package/dist/esm/contracts/handlers/helpers.js +1 -1
  76. package/dist/esm/extension/asset/assetGroup.js +92 -5
  77. package/dist/esm/extension/asset/assetId.js +67 -3
  78. package/dist/esm/extension/asset/assetInput.js +18 -0
  79. package/dist/esm/extension/asset/assetOutput.js +15 -0
  80. package/dist/esm/extension/asset/assetRef.js +66 -0
  81. package/dist/esm/extension/asset/metadata.js +15 -0
  82. package/dist/esm/extension/asset/packet.js +4 -1
  83. package/dist/esm/extension/index.js +1 -1
  84. package/dist/esm/forfeit.js +14 -0
  85. package/dist/esm/identity/seedIdentity.js +2 -2
  86. package/dist/esm/identity/singleKey.js +4 -0
  87. package/dist/esm/index.js +1 -1
  88. package/dist/esm/intent/index.js +28 -12
  89. package/dist/esm/providers/ark.js +3 -2
  90. package/dist/esm/providers/delegator.js +20 -1
  91. package/dist/esm/providers/expoArk.js +2 -2
  92. package/dist/esm/providers/indexer.js +2 -2
  93. package/dist/esm/providers/onchain.js +2 -1
  94. package/dist/esm/repositories/realm/schemas.js +2 -2
  95. package/dist/esm/repositories/realm/types.js +1 -1
  96. package/dist/esm/script/address.js +37 -6
  97. package/dist/esm/script/base.js +70 -1
  98. package/dist/esm/script/default.js +3 -0
  99. package/dist/esm/script/delegate.js +4 -0
  100. package/dist/esm/script/tapscript.js +17 -2
  101. package/dist/esm/script/vhtlc.js +35 -27
  102. package/dist/esm/storage/fileSystem.js +1 -1
  103. package/dist/esm/storage/inMemory.js +1 -1
  104. package/dist/esm/storage/indexedDB.js +1 -1
  105. package/dist/esm/storage/localStorage.js +1 -1
  106. package/dist/esm/tree/validation.js +1 -1
  107. package/dist/esm/utils/arkTransaction.js +5 -5
  108. package/dist/esm/utils/bip21.js +16 -3
  109. package/dist/esm/utils/syncCursors.js +4 -4
  110. package/dist/esm/utils/transaction.js +1 -1
  111. package/dist/esm/utils/transactionHistory.js +11 -11
  112. package/dist/esm/utils/unknownFields.js +3 -3
  113. package/dist/esm/wallet/asset-manager.js +4 -4
  114. package/dist/esm/wallet/batch.js +5 -5
  115. package/dist/esm/wallet/delegator.js +9 -8
  116. package/dist/esm/wallet/expo/background.js +3 -3
  117. package/dist/esm/wallet/expo/wallet.js +7 -7
  118. package/dist/esm/wallet/index.js +43 -0
  119. package/dist/esm/wallet/onchain.js +43 -5
  120. package/dist/esm/wallet/ramps.js +44 -14
  121. package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +22 -22
  122. package/dist/esm/wallet/serviceWorker/wallet.js +28 -24
  123. package/dist/esm/wallet/unroll.js +12 -8
  124. package/dist/esm/wallet/utils.js +1 -1
  125. package/dist/esm/wallet/vtxo-manager.js +121 -81
  126. package/dist/esm/wallet/wallet.js +125 -67
  127. package/dist/esm/worker/expo/asyncStorageTaskQueue.js +1 -1
  128. package/dist/esm/worker/expo/processors/contractPollProcessor.js +2 -2
  129. package/dist/esm/worker/expo/taskRunner.js +3 -3
  130. package/dist/esm/worker/messageBus.js +3 -0
  131. package/dist/types/arkfee/estimator.d.ts +1 -1
  132. package/dist/types/arkfee/types.d.ts +2 -1
  133. package/dist/types/arknote/index.d.ts +44 -4
  134. package/dist/types/bip322/index.d.ts +1 -1
  135. package/dist/types/contracts/arkcontract.d.ts +1 -1
  136. package/dist/types/contracts/contractManager.d.ts +40 -63
  137. package/dist/types/contracts/contractWatcher.d.ts +39 -18
  138. package/dist/types/contracts/handlers/default.d.ts +1 -1
  139. package/dist/types/contracts/handlers/delegate.d.ts +1 -1
  140. package/dist/types/contracts/handlers/helpers.d.ts +1 -1
  141. package/dist/types/contracts/types.d.ts +36 -26
  142. package/dist/types/extension/asset/assetGroup.d.ts +92 -1
  143. package/dist/types/extension/asset/assetId.d.ts +67 -3
  144. package/dist/types/extension/asset/assetInput.d.ts +18 -0
  145. package/dist/types/extension/asset/assetOutput.d.ts +15 -0
  146. package/dist/types/extension/asset/assetRef.d.ts +66 -0
  147. package/dist/types/extension/asset/metadata.d.ts +15 -0
  148. package/dist/types/extension/asset/packet.d.ts +4 -1
  149. package/dist/types/extension/index.d.ts +1 -1
  150. package/dist/types/forfeit.d.ts +14 -0
  151. package/dist/types/identity/index.d.ts +16 -0
  152. package/dist/types/identity/seedIdentity.d.ts +8 -6
  153. package/dist/types/identity/singleKey.d.ts +4 -0
  154. package/dist/types/intent/index.d.ts +19 -6
  155. package/dist/types/providers/ark.d.ts +40 -2
  156. package/dist/types/providers/delegator.d.ts +54 -1
  157. package/dist/types/providers/expoArk.d.ts +2 -2
  158. package/dist/types/providers/indexer.d.ts +105 -2
  159. package/dist/types/providers/onchain.d.ts +62 -1
  160. package/dist/types/repositories/realm/schemas.d.ts +2 -2
  161. package/dist/types/repositories/realm/types.d.ts +2 -2
  162. package/dist/types/repositories/walletRepository.d.ts +16 -0
  163. package/dist/types/script/address.d.ts +35 -2
  164. package/dist/types/script/base.d.ts +66 -1
  165. package/dist/types/script/default.d.ts +3 -0
  166. package/dist/types/script/delegate.d.ts +4 -0
  167. package/dist/types/script/tapscript.d.ts +17 -2
  168. package/dist/types/script/vhtlc.d.ts +35 -27
  169. package/dist/types/storage/fileSystem.d.ts +1 -1
  170. package/dist/types/storage/inMemory.d.ts +1 -1
  171. package/dist/types/storage/index.d.ts +1 -1
  172. package/dist/types/storage/indexedDB.d.ts +1 -1
  173. package/dist/types/storage/localStorage.d.ts +1 -1
  174. package/dist/types/utils/arkTransaction.d.ts +3 -3
  175. package/dist/types/utils/bip21.d.ts +17 -0
  176. package/dist/types/utils/syncCursors.d.ts +4 -4
  177. package/dist/types/utils/transaction.d.ts +1 -1
  178. package/dist/types/utils/transactionHistory.d.ts +3 -3
  179. package/dist/types/utils/unknownFields.d.ts +5 -5
  180. package/dist/types/wallet/asset-manager.d.ts +3 -3
  181. package/dist/types/wallet/batch.d.ts +27 -7
  182. package/dist/types/wallet/delegator.d.ts +10 -0
  183. package/dist/types/wallet/expo/background.d.ts +4 -4
  184. package/dist/types/wallet/expo/wallet.d.ts +10 -10
  185. package/dist/types/wallet/index.d.ts +457 -25
  186. package/dist/types/wallet/onchain.d.ts +42 -4
  187. package/dist/types/wallet/ramps.d.ts +40 -10
  188. package/dist/types/wallet/serviceWorker/wallet-message-handler.d.ts +4 -4
  189. package/dist/types/wallet/serviceWorker/wallet.d.ts +71 -33
  190. package/dist/types/wallet/unroll.d.ts +8 -6
  191. package/dist/types/wallet/vtxo-manager.d.ts +146 -93
  192. package/dist/types/wallet/wallet.d.ts +91 -33
  193. package/dist/types/worker/expo/asyncStorageTaskQueue.d.ts +1 -1
  194. package/dist/types/worker/expo/processors/contractPollProcessor.d.ts +1 -1
  195. package/dist/types/worker/expo/taskRunner.d.ts +6 -6
  196. package/dist/types/worker/messageBus.d.ts +5 -3
  197. package/package.json +1 -1
@@ -10,38 +10,50 @@ const DEFAULT_PAGE_SIZE = 500;
10
10
  /**
11
11
  * Central manager for contract lifecycle and operations.
12
12
  *
13
- * The ContractManager orchestrates:
14
- * - Contract registration and persistence
15
- * - Multi-contract watching via ContractWatcher
16
- * - VTXO queries across contracts
13
+ * Responsibilities:
14
+ * - Create and persist contracts
15
+ * - Query stored contracts (optionally with their virtual outputs)
16
+ * - Provide spendable path selection for a contract
17
+ * - Emit contract-related events (virtual output received/spent/expired, connection reset)
18
+ *
19
+ * Notes:
20
+ * - Implementations typically start watching automatically during initialization
21
+ * (so `onContractEvent()` is just for subscribing).
17
22
  *
18
23
  * @example
19
24
  * ```typescript
20
- * const manager = new ContractManager({
25
+ * const manager = await ContractManager.create({
21
26
  * indexerProvider: wallet.indexerProvider,
22
27
  * contractRepository: wallet.contractRepository,
28
+ * walletRepository: wallet.walletRepository,
23
29
  * getDefaultAddress: () => wallet.getAddress(),
24
30
  * });
25
31
  *
26
- * // Initialize (loads persisted contracts)
27
- * await manager.initialize();
28
- *
29
32
  * // Create a new VHTLC contract
30
33
  * const contract = await manager.createContract({
31
34
  * label: "Lightning Receive",
32
35
  * type: "vhtlc",
33
- * params: { sender: "ab12...", receiver: "cd34...", ... },
36
+ * params: { sender: "ark1q...", receiver: "ark1q...", ... },
34
37
  * script: "5120...",
35
- * address: "tark1...",
38
+ * address: "ark1q...",
36
39
  * });
37
40
  *
38
41
  * // Start watching for events
39
- * const stop = await manager.startWatching((event) => {
42
+ * const unsubscribe = manager.onContractEvent((event) => {
40
43
  * console.log(`${event.type} on ${event.contractScript}`);
41
44
  * });
42
45
  *
46
+ * // Query contracts together with their current virtual outputs
47
+ * const contractsWithVtxos = await manager.getContractsWithVtxos();
48
+ *
43
49
  * // Get balance across all contracts
44
- * const balances = await manager.getAllBalances();
50
+ * const balances = contractsWithVtxos.flatMap(({vtxos}) => vtxos).reduce((acc, vtxo) => acc + vtxo.value, 0)
51
+ *
52
+ * // Later: unsubscribe from events
53
+ * unsubscribe();
54
+ *
55
+ * // Clean up
56
+ * manager.dispose();
45
57
  * ```
46
58
  */
47
59
  class ContractManager {
@@ -49,7 +61,7 @@ class ContractManager {
49
61
  this.initialized = false;
50
62
  this.eventCallbacks = new Set();
51
63
  this.config = config;
52
- // Create watcher with wallet repository for VTXO caching
64
+ // Create watcher with wallet repository for virtual output caching
53
65
  this.watcher = new contractWatcher_1.ContractWatcher({
54
66
  indexerProvider: config.indexerProvider,
55
67
  walletRepository: config.walletRepository,
@@ -61,7 +73,7 @@ class ContractManager {
61
73
  * Initialize the manager by loading persisted contracts and starting to watch.
62
74
  *
63
75
  * After initialization, the manager automatically watches all active contracts
64
- * and contracts with VTXOs. Use `onContractEvent()` to register event callbacks.
76
+ * and contracts with virtual outputs. Use `onContractEvent()` to register event callbacks.
65
77
  *
66
78
  * @param config ContractManagerConfig
67
79
  */
@@ -76,10 +88,10 @@ class ContractManager {
76
88
  }
77
89
  // Load persisted contracts
78
90
  const contracts = await this.config.contractRepository.getContracts();
79
- // Delta-sync: fetch only VTXOs that changed since the last cursor,
91
+ // Delta-sync: fetch only virtual outputs that changed since the last cursor,
80
92
  // falling back to a full bootstrap for scripts seen for the first time.
81
93
  await this.deltaSyncContracts(contracts);
82
- // Reconcile the pending frontier: fetch all not-yet-finalized VTXOs
94
+ // Reconcile the pending frontier: fetch all not-yet-finalized virtual outputs
83
95
  // to catch any that the delta window may have missed.
84
96
  if (contracts.length > 0) {
85
97
  await this.reconcilePendingFrontier(contracts);
@@ -148,7 +160,7 @@ class ContractManager {
148
160
  };
149
161
  // Persist
150
162
  await this.config.contractRepository.saveContract(contract);
151
- // fetch all VTXOs (including spent/swept) for this contract
163
+ // fetch all virtual outputs (including spent/swept) for this contract
152
164
  const requestStartedAt = Date.now();
153
165
  await this.fetchContractVxosFromIndexer([contract], true);
154
166
  // Advance the sync cursor so that the watcher's vtxo_received
@@ -261,7 +273,6 @@ class ContractManager {
261
273
  /**
262
274
  * Get currently spendable paths for a contract.
263
275
  *
264
- * @param contractScript - The contract script
265
276
  * @param options - Options for getting spendable paths
266
277
  */
267
278
  async getSpendablePaths(options) {
@@ -281,6 +292,11 @@ class ContractManager {
281
292
  };
282
293
  return handler.getSpendablePaths(script, contract, context);
283
294
  }
295
+ /**
296
+ * Get every currently valid spending path for a contract.
297
+ *
298
+ * @param options - Options for getting spending paths
299
+ */
284
300
  async getAllSpendingPaths(options) {
285
301
  const { contractScript, collaborative = true, walletPubKey } = options;
286
302
  const [contract] = await this.getContracts({ script: contractScript });
@@ -323,7 +339,7 @@ class ContractManager {
323
339
  };
324
340
  }
325
341
  /**
326
- * Force a VTXO refresh from the indexer.
342
+ * Force refresh virtual outputs from the indexer.
327
343
  *
328
344
  * Without options, clears all sync cursors and re-fetches every contract.
329
345
  * With options, narrows the refresh to specific scripts and/or a time window.
@@ -385,7 +401,7 @@ class ContractManager {
385
401
  */
386
402
  async handleContractEvent(event) {
387
403
  switch (event.type) {
388
- // Delta-sync only the changed VTXOs for this contract.
404
+ // Delta-sync only the changed virtual outputs for this contract.
389
405
  case "vtxo_received":
390
406
  case "vtxo_spent":
391
407
  await this.deltaSyncContracts([event.contract]);
@@ -410,7 +426,7 @@ class ContractManager {
410
426
  return await this.fetchContractVxosFromIndexer(contracts, false, pageSize);
411
427
  }
412
428
  /**
413
- * Incrementally sync VTXOs for the given contracts.
429
+ * Incrementally sync virtual outputs for the given contracts.
414
430
  * Uses per-script cursors to fetch only what changed since the last sync.
415
431
  * Scripts without a cursor are bootstrapped with a full fetch.
416
432
  */
@@ -462,8 +478,8 @@ class ContractManager {
462
478
  return result;
463
479
  }
464
480
  /**
465
- * Fetch all pending (not-yet-finalized) VTXOs and upsert them into the
466
- * repository. This catches VTXOs whose state changed outside the delta
481
+ * Fetch all pending (unfinalized) virtual outputs and upsert them into the
482
+ * repository. This catches virtual outputs whose state changed outside the delta
467
483
  * window (e.g. a spend that hasn't settled yet).
468
484
  */
469
485
  async reconcilePendingFrontier(contracts) {
@@ -545,7 +561,7 @@ class ContractManager {
545
561
  pageSize,
546
562
  });
547
563
  for (const vtxo of vtxos) {
548
- // Match the VTXO back to its contract via the script field
564
+ // Match the virtual output back to its contract via the script field
549
565
  // populated by the indexer.
550
566
  if (!vtxo.script)
551
567
  continue;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ContractWatcher = void 0;
4
4
  /**
5
- * Watches multiple contracts for VTXO changes with resilient connection handling.
5
+ * Watches multiple contracts for virtual output state changes with resilient connection handling.
6
6
  *
7
7
  * Features:
8
8
  * - Automatic reconnection with exponential backoff
@@ -32,6 +32,12 @@ exports.ContractWatcher = void 0;
32
32
  * ```
33
33
  */
34
34
  class ContractWatcher {
35
+ /**
36
+ * Create a contract watcher with the given providers and polling settings.
37
+ *
38
+ * @param config - Contract watcher configuration
39
+ * @see ContractWatcherConfig
40
+ */
35
41
  constructor(config) {
36
42
  this.contracts = new Map();
37
43
  this.isWatching = false;
@@ -48,9 +54,10 @@ class ContractWatcher {
48
54
  /**
49
55
  * Add a contract to be watched.
50
56
  *
51
- * Active contracts are immediately subscribed. All contracts are polled
52
- * to discover any existing VTXOs (which may cause them to be watched
53
- * even if inactive).
57
+ * Active contracts are immediately subscribed.
58
+ *
59
+ * All contracts are polled to discover any existing virtual outputs
60
+ * (which may cause them to be watched even if inactive).
54
61
  */
55
62
  async addContract(contract) {
56
63
  const state = {
@@ -58,11 +65,11 @@ class ContractWatcher {
58
65
  lastKnownVtxos: new Map(),
59
66
  };
60
67
  this.contracts.set(contract.script, state);
61
- // If we're already watching, poll to discover VTXOs and update subscription
68
+ // If we're already watching, poll to discover virtual outputs and update subscription
62
69
  if (this.isWatching) {
63
- // Poll first to discover VTXOs (may affect whether we watch this contract)
70
+ // Poll first to discover virtual outputs (may affect whether we watch this contract).
64
71
  await this.pollContracts([contract.script]);
65
- // Update subscription based on active state and VTXOs
72
+ // Update subscription based on active state and virtual outputs.
66
73
  await this.tryUpdateSubscription();
67
74
  }
68
75
  }
@@ -108,10 +115,10 @@ class ContractWatcher {
108
115
  *
109
116
  * Returns scripts for:
110
117
  * - All active contracts
111
- * - All contracts with known VTXOs (regardless of state)
118
+ * - All contracts with known virtual outputs (regardless of state)
112
119
  *
113
120
  * This ensures we continue monitoring contracts even after they're
114
- * deactivated, as long as they have unspent VTXOs.
121
+ * deactivated, as long as they have unspent virtual outputs.
115
122
  */
116
123
  getScriptsToWatch() {
117
124
  const scripts = new Set();
@@ -121,7 +128,7 @@ class ContractWatcher {
121
128
  scripts.add(state.contract.script);
122
129
  continue;
123
130
  }
124
- // Also watch inactive/expired contracts that have VTXOs
131
+ // Also watch inactive/expired contracts that have virtual outputs.
125
132
  if (state.lastKnownVtxos.size > 0) {
126
133
  scripts.add(state.contract.script);
127
134
  }
@@ -129,8 +136,8 @@ class ContractWatcher {
129
136
  return Array.from(scripts);
130
137
  }
131
138
  /**
132
- * Get VTXOs for contracts, grouped by contract script.
133
- * Uses Repository.
139
+ * Get virtual outputs for contracts, grouped by contract script.
140
+ * @see WalletRepository for `repo`
134
141
  */
135
142
  async getContractVtxos(options) {
136
143
  const { contractScripts, includeSpent } = options;
@@ -163,7 +170,7 @@ class ContractWatcher {
163
170
  return new Map(results.flat(1));
164
171
  }
165
172
  /**
166
- * Start watching for VTXO events across all active contracts.
173
+ * Start watching for virtual output events across all active contracts.
167
174
  */
168
175
  async startWatching(callback) {
169
176
  if (this.isWatching) {
@@ -342,7 +349,7 @@ class ContractWatcher {
342
349
  return;
343
350
  const now = Date.now();
344
351
  try {
345
- // Load all the VTXOs for these contracts, from DB
352
+ // Load all the virtual outputs for these contracts, from DB
346
353
  const vtxosMap = await this.getContractVtxos({
347
354
  contractScripts,
348
355
  includeSpent: false, // only spendable ones!
@@ -353,7 +360,7 @@ class ContractWatcher {
353
360
  continue;
354
361
  const currentVtxos = vtxosMap.get(contractScript) || [];
355
362
  const currentKeys = new Set(currentVtxos.map((v) => `${v.txid}:${v.vout}`));
356
- // Find new VTXOs and add them to the contract's state
363
+ // Find new virtual outputs and add them to the contract's state
357
364
  const newVtxos = [];
358
365
  for (const vtxo of currentVtxos) {
359
366
  const key = `${vtxo.txid}:${vtxo.vout}`;
@@ -362,7 +369,7 @@ class ContractWatcher {
362
369
  state.lastKnownVtxos.set(key, vtxo);
363
370
  }
364
371
  }
365
- // Find spent VTXOs and remove them from the contract's state
372
+ // Find spent virtual outputs and remove them from the contract's state
366
373
  const spentVtxos = [];
367
374
  for (const [key, vtxo] of state.lastKnownVtxos) {
368
375
  if (!currentKeys.has(key)) {
@@ -397,7 +404,7 @@ class ContractWatcher {
397
404
  /**
398
405
  * Update the subscription with scripts that should be watched.
399
406
  *
400
- * Watches both active contracts and contracts with VTXOs.
407
+ * Watches both active contracts and contracts with virtual outputs.
401
408
  */
402
409
  async updateSubscription() {
403
410
  const scriptsToWatch = this.getScriptsToWatch();
@@ -474,11 +481,11 @@ class ContractWatcher {
474
481
  }
475
482
  }
476
483
  /**
477
- * Process VTXOs from subscription and route to correct contracts.
484
+ * Process virtual outputs from subscription and route to correct contracts.
478
485
  * Uses the scripts from the subscription response to determine contract ownership.
479
486
  */
480
487
  processSubscriptionVtxos(vtxos, scripts, eventType, timestamp) {
481
- // If we have exactly one script, all VTXOs belong to that contract
488
+ // If we have exactly one script, all virtual outputs belong to that contract
482
489
  // Otherwise, we can't reliably determine ownership without script in VirtualCoin
483
490
  if (scripts.length === 1) {
484
491
  const contractScript = scripts[0];
@@ -500,8 +507,8 @@ class ContractWatcher {
500
507
  }
501
508
  return;
502
509
  }
503
- // Multiple scripts - assign VTXOs to all matching contracts
504
- // This is a limitation: we can't know which VTXO belongs to which script
510
+ // Multiple scripts - assign virtual outputs to all matching contracts
511
+ // This is a limitation: we can't know which virtual output belongs to which script
505
512
  // In practice, subscription events usually come with a single script context
506
513
  for (const script of scripts) {
507
514
  const contractScript = script;
@@ -523,7 +530,7 @@ class ContractWatcher {
523
530
  }
524
531
  }
525
532
  /**
526
- * Emit a VTXO event for a contract.
533
+ * Emit a virtual output event for a contract.
527
534
  */
528
535
  emitVtxoEvent(contractScript, vtxos, eventType, timestamp) {
529
536
  if (!this.eventCallback)
@@ -5,7 +5,7 @@ const base_1 = require("@scure/base");
5
5
  const default_1 = require("../../script/default");
6
6
  const helpers_1 = require("./helpers");
7
7
  /**
8
- * Handler for default wallet VTXOs.
8
+ * Handler for default wallet virtual outputs.
9
9
  *
10
10
  * Default contracts use the standard forfeit + exit tapscript:
11
11
  * - forfeit: (Alice + Server) multisig for collaborative spending
@@ -6,7 +6,7 @@ const delegate_1 = require("../../script/delegate");
6
6
  const default_1 = require("../../script/default");
7
7
  const helpers_1 = require("./helpers");
8
8
  /**
9
- * Handler for delegate wallet VTXOs.
9
+ * Handler for delegate wallet virtual outputs.
10
10
  *
11
11
  * Delegate contracts extend the default tapscript with an additional delegate path:
12
12
  * - forfeit: (Alice + Server) multisig for collaborative spending
@@ -103,7 +103,7 @@ function isCltvSatisfied(context, locktime) {
103
103
  return currentTimeSec >= locktime;
104
104
  }
105
105
  /**
106
- * Check if a CSV timelock is currently satisfied for the given context/VTXO.
106
+ * Check if a CSV timelock is currently satisfied for the given context/virtual output.
107
107
  */
108
108
  function isCsvSpendable(context, sequence) {
109
109
  if (sequence === undefined)
@@ -10,9 +10,25 @@ const assetOutput_1 = require("./assetOutput");
10
10
  const metadata_1 = require("./metadata");
11
11
  const utils_1 = require("./utils");
12
12
  /**
13
- * An asset group contains inputs/outputs and all data related to a given asset id.
13
+ * An asset group contains inputs, outputs, and all data related to a given asset id.
14
+ *
15
+ * @see Packet
16
+ * @see AssetId
17
+ * @see AssetRef
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const group = AssetGroup.create(
22
+ * null, // asset ID: null for new issuance
23
+ * null, // control asset ID: null when reissuance not needed
24
+ * [], // asset inputs: empty for new issuance
25
+ * [AssetOutput.create(0, 1000)], // asset outputs: 1000 units at vout index 0
26
+ * [] // metadata: can be empty
27
+ * )
28
+ * ```
14
29
  */
15
30
  class AssetGroup {
31
+ /** @see create */
16
32
  constructor(assetId, controlAsset, inputs, outputs, metadata) {
17
33
  this.assetId = assetId;
18
34
  this.controlAsset = controlAsset;
@@ -20,12 +36,31 @@ class AssetGroup {
20
36
  this.outputs = outputs;
21
37
  this.metadataList = new metadata_1.MetadataList(metadata);
22
38
  }
39
+ /**
40
+ * Create and validate an asset group.
41
+ *
42
+ * @param assetId - Asset id for this group, or `null` for fresh issuance
43
+ * @param controlAsset - Optional control asset reference for (re) issuance
44
+ * @param inputs - Asset inputs in the group
45
+ * @param outputs - Asset outputs in the group
46
+ * @param metadata - Metadata entries associated with the group
47
+ * @returns A validated asset group
48
+ * @throws Error if the group fails validation
49
+ * @see validate
50
+ */
23
51
  static create(assetId, controlAsset, inputs, outputs, metadata) {
24
52
  const ag = new AssetGroup(assetId, controlAsset, inputs, outputs, metadata);
25
53
  ag.validate();
26
54
  return ag;
27
55
  }
28
- // from hex encoded
56
+ /**
57
+ * Decode an asset group from its hex string form.
58
+ *
59
+ * @param s - Hex-encoded asset group
60
+ * @returns Decoded asset group
61
+ * @throws Error if the string is not valid hex or does not encode a valid asset group
62
+ * @see toString
63
+ */
29
64
  static fromString(s) {
30
65
  let buf;
31
66
  try {
@@ -36,6 +71,13 @@ class AssetGroup {
36
71
  }
37
72
  return AssetGroup.fromBytes(buf);
38
73
  }
74
+ /**
75
+ * Decode an asset group from its serialized bytes.
76
+ *
77
+ * @param buf - Serialized asset group bytes
78
+ * @returns Decoded asset group
79
+ * @throws Error if the buffer is empty or malformed
80
+ */
39
81
  static fromBytes(buf) {
40
82
  if (!buf || buf.length === 0) {
41
83
  throw new Error("missing asset group");
@@ -43,12 +85,21 @@ class AssetGroup {
43
85
  const reader = new utils_1.BufferReader(buf);
44
86
  return AssetGroup.fromReader(reader);
45
87
  }
46
- // an issuance is a group with null assetId
88
+ /**
89
+ * Return true when the group represents an issuance.
90
+ *
91
+ * @returns `true` when the group has no asset id
92
+ */
47
93
  isIssuance() {
48
94
  return this.assetId === null;
49
95
  }
50
- // a reissuance is a group that is not an issuance
51
- // but where the sum of the outputs is greater than the sum of the inputs
96
+ /**
97
+ * Return true when the group represents a reissuance.
98
+ *
99
+ * @returns `true` when the group has an asset id and outputs exceed local inputs
100
+ * @remarks
101
+ * Only local inputs contribute to the comparison; intent-backed inputs contribute `0` here.
102
+ */
52
103
  isReissuance() {
53
104
  const sumReducer = (s, { amount }) => s + amount;
54
105
  const sumOutputs = this.outputs.reduce(sumReducer, 0n);
@@ -59,12 +110,23 @@ class AssetGroup {
59
110
  .reduce(sumReducer, 0n);
60
111
  return !this.isIssuance() && sumInputs < sumOutputs;
61
112
  }
113
+ /**
114
+ * Serialize the asset group to raw bytes.
115
+ *
116
+ * @returns Serialized asset group bytes
117
+ * @see fromBytes
118
+ */
62
119
  serialize() {
63
120
  this.validate();
64
121
  const writer = new utils_1.BufferWriter();
65
122
  this.serializeTo(writer);
66
123
  return writer.toBytes();
67
124
  }
125
+ /**
126
+ * Validate the asset group and its child structures.
127
+ *
128
+ * @throws Error if the group is empty or violates issuance invariants
129
+ */
68
130
  validate() {
69
131
  if (this.inputs.length === 0 && this.outputs.length === 0) {
70
132
  throw new Error("empty asset group");
@@ -80,13 +142,33 @@ class AssetGroup {
80
142
  }
81
143
  }
82
144
  }
145
+ /**
146
+ * Convert the group into its batch-leaf representation for the given intent txid.
147
+ *
148
+ * @param intentTxid - Intent transaction id used to build the leaf input reference
149
+ * @returns Batch-leaf asset group
150
+ * @see AssetInput.createIntent
151
+ */
83
152
  toBatchLeafAssetGroup(intentTxid) {
84
153
  const leafInput = assetInput_1.AssetInput.createIntent(base_1.hex.encode(intentTxid), 0, 0);
85
154
  return new AssetGroup(this.assetId, this.controlAsset, [leafInput], this.outputs, this.metadataList.items);
86
155
  }
156
+ /**
157
+ * Encode the asset group to a hex string.
158
+ *
159
+ * @returns Hex-encoded asset group
160
+ * @see fromString
161
+ */
87
162
  toString() {
88
163
  return base_1.hex.encode(this.serialize());
89
164
  }
165
+ /**
166
+ * Decode an asset group from a binary reader.
167
+ *
168
+ * @param reader - Reader positioned at an asset group
169
+ * @returns Decoded asset group
170
+ * @throws Error if the encoded group is malformed
171
+ */
90
172
  static fromReader(reader) {
91
173
  const presence = reader.readByte();
92
174
  let assetId = null;
@@ -107,6 +189,11 @@ class AssetGroup {
107
189
  ag.validate();
108
190
  return ag;
109
191
  }
192
+ /**
193
+ * Serialize the asset group into an existing binary writer.
194
+ *
195
+ * @param writer - Writer to append the asset group to
196
+ */
110
197
  serializeTo(writer) {
111
198
  let presence = 0;
112
199
  if (this.assetId !== null) {
@@ -5,15 +5,34 @@ const base_1 = require("@scure/base");
5
5
  const types_1 = require("./types");
6
6
  const utils_1 = require("./utils");
7
7
  /**
8
- * AssetId represents the id of an asset.
9
- * @param txid - the genesis transaction id (decoded from hex)
10
- * @param groupIndex - the asset group index in the genesis transaction
8
+ * AssetId identifies a specific asset.
9
+ *
10
+ * @remarks
11
+ * Asset ids are derived from the genesis transaction id plus the asset group index.
12
+ *
13
+ * @see AssetRef
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const assetId = AssetId.create('00'.repeat(32), 0)
18
+ * const encoded = assetId.toString()
19
+ * const decoded = AssetId.fromString(encoded)
20
+ * ```
11
21
  */
12
22
  class AssetId {
13
23
  constructor(txid, groupIndex) {
14
24
  this.txid = txid;
15
25
  this.groupIndex = groupIndex;
16
26
  }
27
+ /**
28
+ * Create an asset id from a genesis transaction id and group index.
29
+ *
30
+ * @param txid - Hex-encoded genesis transaction id
31
+ * @param groupIndex - Asset group index within the genesis transaction
32
+ * @returns A validated asset id
33
+ * @throws Error if the txid is missing, malformed, or not 32 bytes long
34
+ * @see fromString
35
+ */
17
36
  static create(txid, groupIndex) {
18
37
  if (!txid) {
19
38
  throw new Error("missing txid");
@@ -32,6 +51,14 @@ class AssetId {
32
51
  assetId.validate();
33
52
  return assetId;
34
53
  }
54
+ /**
55
+ * Decode an asset id from its hex string representation.
56
+ *
57
+ * @param s - Hex-encoded asset id
58
+ * @returns Decoded asset id
59
+ * @throws Error if the string is not valid hex or does not encode a valid asset id
60
+ * @see toString
61
+ */
35
62
  static fromString(s) {
36
63
  let buf;
37
64
  try {
@@ -42,6 +69,13 @@ class AssetId {
42
69
  }
43
70
  return AssetId.fromBytes(buf);
44
71
  }
72
+ /**
73
+ * Decode an asset id from its serialized bytes.
74
+ *
75
+ * @param buf - Serialized asset id bytes
76
+ * @returns Decoded asset id
77
+ * @throws Error if the buffer length is invalid
78
+ */
45
79
  static fromBytes(buf) {
46
80
  if (!buf || buf.length === 0) {
47
81
  throw new Error("missing asset id");
@@ -52,14 +86,31 @@ class AssetId {
52
86
  const reader = new utils_1.BufferReader(buf);
53
87
  return AssetId.fromReader(reader);
54
88
  }
89
+ /**
90
+ * Serialize the asset id to raw bytes.
91
+ *
92
+ * @returns Serialized asset id bytes
93
+ * @see fromBytes
94
+ */
55
95
  serialize() {
56
96
  const writer = new utils_1.BufferWriter();
57
97
  this.serializeTo(writer);
58
98
  return writer.toBytes();
59
99
  }
100
+ /**
101
+ * Encode the asset id to a hex string.
102
+ *
103
+ * @returns Hex-encoded asset id
104
+ * @see fromString
105
+ */
60
106
  toString() {
61
107
  return base_1.hex.encode(this.serialize());
62
108
  }
109
+ /**
110
+ * Validate the asset id fields.
111
+ *
112
+ * @throws Error if the txid is empty or the group index is out of range
113
+ */
63
114
  validate() {
64
115
  if ((0, utils_1.isZeroBytes)(this.txid)) {
65
116
  throw new Error("empty txid");
@@ -70,6 +121,13 @@ class AssetId {
70
121
  throw new Error(`invalid group index: ${this.groupIndex}, must be in range [0, 65535]`);
71
122
  }
72
123
  }
124
+ /**
125
+ * Decode an asset id from a binary reader.
126
+ *
127
+ * @param reader - Reader positioned at an asset id
128
+ * @returns Decoded asset id
129
+ * @throws Error if the reader does not contain enough bytes
130
+ */
73
131
  static fromReader(reader) {
74
132
  if (reader.remaining() < types_1.ASSET_ID_SIZE) {
75
133
  throw new Error(`invalid asset id length: got ${reader.remaining()}, want ${types_1.ASSET_ID_SIZE}`);
@@ -80,6 +138,12 @@ class AssetId {
80
138
  assetId.validate();
81
139
  return assetId;
82
140
  }
141
+ /**
142
+ * Serialize the asset id into an existing binary writer.
143
+ *
144
+ * @param writer - Writer to append the asset id to
145
+ * @see serialize
146
+ */
83
147
  serializeTo(writer) {
84
148
  writer.write(this.txid);
85
149
  writer.writeUint16LE(this.groupIndex);