@arkade-os/sdk 0.4.15 → 0.4.17

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 +60 -28
  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 +140 -77
  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 +60 -28
  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 +140 -77
  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 +39 -65
  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
@@ -39,6 +39,10 @@ const contractManager_1 = require("../contracts/contractManager");
39
39
  const handlers_1 = require("../contracts/handlers");
40
40
  const helpers_1 = require("../contracts/handlers/helpers");
41
41
  const syncCursors_1 = require("../utils/syncCursors");
42
+ // Hardcoded unilateral exit delay for mainnet (~7 days in seconds).
43
+ // Pinned here so that address derivation stays stable for existing mainnet
44
+ // wallets even after the server lowers the delay it advertises.
45
+ const MAINNET_UNILATERAL_EXIT_DELAY = 605184n;
42
46
  /**
43
47
  * Type guard function to check if an identity has a toReadonly method.
44
48
  */
@@ -113,12 +117,12 @@ class ReadonlyWallet {
113
117
  const serverIsMainnet = info.network === "bitcoin";
114
118
  if (identityIsMainnet && !serverIsMainnet) {
115
119
  throw new Error(`Network mismatch: identity uses mainnet derivation (coin type 0) ` +
116
- `but Ark server is on ${info.network}. ` +
120
+ `but the Arkade server is on ${info.network}. ` +
117
121
  `Create identity with { isMainnet: false } to use testnet derivation.`);
118
122
  }
119
123
  if (!identityIsMainnet && serverIsMainnet) {
120
124
  throw new Error(`Network mismatch: identity uses testnet derivation (coin type 1) ` +
121
- `but Ark server is on mainnet. ` +
125
+ `but the Arkade server is on mainnet. ` +
122
126
  `Create identity with { isMainnet: true } or omit isMainnet (defaults to mainnet).`);
123
127
  }
124
128
  }
@@ -134,10 +138,16 @@ class ReadonlyWallet {
134
138
  throw new Error("invalid exitTimelock");
135
139
  }
136
140
  }
141
+ // On mainnet, pin the unilateral exit delay to the historical value so
142
+ // that addresses derived by existing wallets remain stable even if the
143
+ // server starts advertising a shorter delay.
144
+ const unilateralExitDelay = info.network === "bitcoin"
145
+ ? MAINNET_UNILATERAL_EXIT_DELAY
146
+ : info.unilateralExitDelay;
137
147
  // create unilateral exit timelock
138
148
  const exitTimelock = config.exitTimelock ?? {
139
- value: info.unilateralExitDelay,
140
- type: info.unilateralExitDelay < 512n ? "blocks" : "seconds",
149
+ value: unilateralExitDelay,
150
+ type: unilateralExitDelay < 512n ? "blocks" : "seconds",
141
151
  };
142
152
  // validate boarding timelock passed in config if any
143
153
  if (config.boardingTimelock) {
@@ -190,6 +200,12 @@ class ReadonlyWallet {
190
200
  delegatorProvider: config.delegatorProvider,
191
201
  };
192
202
  }
203
+ /**
204
+ * Create a readonly wallet for querying balances, addresses, and history.
205
+ *
206
+ * @param config - Readonly wallet configuration
207
+ * @returns A readonly wallet instance
208
+ */
193
209
  static async create(config) {
194
210
  const pubkey = await config.identity.xOnlyPublicKey();
195
211
  if (!pubkey) {
@@ -208,12 +224,17 @@ class ReadonlyWallet {
208
224
  get defaultContractScript() {
209
225
  return base_1.hex.encode(this.offchainTapscript.pkScript);
210
226
  }
227
+ /** Returns the wallet's Arkade address. */
211
228
  async getAddress() {
212
229
  return this.arkAddress.encode();
213
230
  }
231
+ /** Returns the onchain boarding address used to move funds into Arkade. */
214
232
  async getBoardingAddress() {
215
233
  return this.boardingTapscript.onchainAddress(this.network);
216
234
  }
235
+ /**
236
+ * Return the wallet's combined onchain and offchain balances.
237
+ */
217
238
  async getBalance() {
218
239
  const [boardingUtxos, vtxos] = await Promise.all([
219
240
  this.getBoardingUtxos(),
@@ -245,7 +266,7 @@ class ReadonlyWallet {
245
266
  .reduce((sum, coin) => sum + coin.value, 0);
246
267
  const totalBoarding = confirmed + unconfirmed;
247
268
  const totalOffchain = settled + preconfirmed + recoverable;
248
- // aggregate asset balances from spendable vtxos
269
+ // aggregate asset balances from spendable virtual outputs
249
270
  const assetBalances = new Map();
250
271
  for (const vtxo of vtxos) {
251
272
  if (!(0, _1.isSpendable)(vtxo))
@@ -275,15 +296,16 @@ class ReadonlyWallet {
275
296
  assets,
276
297
  };
277
298
  }
299
+ /**
300
+ * Return virtual outputs tracked by the wallet.
301
+ *
302
+ * @param filter - Optional flags controlling whether recoverable or unrolled VTXOs are included
303
+ */
278
304
  async getVtxos(filter) {
279
- const { isDelta, fetchedExtended, address } = await this.syncVtxos();
280
305
  const f = filter ?? { withRecoverable: true, withUnrolled: false };
281
- // For delta syncs, read the full merged set from cache so old
282
- // VTXOs that weren't in the delta are still returned.
283
- const vtxos = isDelta
284
- ? await this.walletRepository.getVtxos(address)
285
- : fetchedExtended;
286
- return vtxos.filter((vtxo) => {
306
+ const contractManager = await this.getContractManager();
307
+ const contractsWithVtxos = await contractManager.getContractsWithVtxos();
308
+ return contractsWithVtxos.flatMap(({ vtxos }) => vtxos.filter((vtxo) => {
287
309
  if ((0, _1.isSpendable)(vtxo)) {
288
310
  if (!f.withRecoverable &&
289
311
  ((0, _1.isRecoverable)(vtxo) || (0, _1.isExpired)(vtxo))) {
@@ -292,10 +314,13 @@ class ReadonlyWallet {
292
314
  return true;
293
315
  }
294
316
  return !!(f.withUnrolled && vtxo.isUnrolled);
295
- });
317
+ }));
296
318
  }
319
+ /**
320
+ * Return wallet transaction history derived from Arkade state and boarding transactions.
321
+ */
297
322
  async getTransactionHistory() {
298
- // Delta-sync VTXOs into cache, then build history from the cache.
323
+ // Delta-sync virtual outputs into cache, then build history from the cache.
299
324
  const { isDelta, fetchedExtended, address } = await this.syncVtxos();
300
325
  const allVtxos = isDelta
301
326
  ? await this.walletRepository.getVtxos(address)
@@ -307,7 +332,7 @@ class ReadonlyWallet {
307
332
  return (0, transactionHistory_1.buildTransactionHistory)(allVtxos, boardingTxs, commitmentsToIgnore, getTxCreatedAt);
308
333
  }
309
334
  /**
310
- * Delta-sync wallet VTXOs: fetch only changed VTXOs since the last
335
+ * Delta-sync wallet virtual outputs: fetch only changed virtual outputs since the last
311
336
  * cursor, or do a full bootstrap when no cursor exists. Upserts
312
337
  * the result into the cache and advances the sync cursors.
313
338
  *
@@ -380,21 +405,21 @@ class ReadonlyWallet {
380
405
  allVtxos.push(...response.vtxos);
381
406
  }
382
407
  }
383
- // Extend every fetched VTXO and upsert into the cache.
408
+ // Extend every fetched virtual output and upsert into the cache.
384
409
  const fetchedExtended = [];
385
410
  for (const vtxo of allVtxos) {
386
411
  const extended = extendWithScript(vtxo);
387
412
  if (extended)
388
413
  fetchedExtended.push(extended);
389
414
  }
390
- // Save VTXOs first, then advance cursors only on success.
415
+ // Save virtual outputs first, then advance cursors only on success.
391
416
  const cutoff = (0, syncCursors_1.cursorCutoff)(requestStartedAt);
392
417
  await this.walletRepository.saveVtxos(address, fetchedExtended);
393
418
  await (0, syncCursors_1.advanceSyncCursors)(this.walletRepository, Object.fromEntries(allScripts.map((s) => [s, cutoff])));
394
419
  // Delta-sync reconciliation: full re-fetch for delta scripts.
395
420
  //
396
- // The delta fetch (above) only returns VTXOs changed after the
397
- // cursor, so it can miss preconfirmed VTXOs that were consumed
421
+ // The delta fetch (above) only returns virtual outputs changed after the
422
+ // cursor, so it can miss preconfirmed virtual outputs that were consumed
398
423
  // by a round between syncs. Rather than layering targeted
399
424
  // queries (pendingOnly, spendableOnly) with pagination guards
400
425
  // and set algebra, we perform a single unfiltered re-fetch for
@@ -402,8 +427,8 @@ class ReadonlyWallet {
402
427
  // gives us complete, authoritative state in one call and keeps
403
428
  // the reconciliation logic simple.
404
429
  //
405
- // Any cached non-spent VTXO that is absent from the full
406
- // result set is marked spent; any VTXO whose state changed
430
+ // Any cached non-spent virtual output that is absent from the full
431
+ // result set is marked spent; any virtual output whose state changed
407
432
  // (e.g. preconfirmed → settled) is updated in place.
408
433
  if (hasDelta) {
409
434
  const { vtxos: fullVtxos, page: fullPage } = await this.indexerProvider.getVtxos({
@@ -412,7 +437,7 @@ class ReadonlyWallet {
412
437
  // Reconciliation is best-effort: if the response is
413
438
  // paginated we don't have a complete picture, so we skip
414
439
  // rather than act on partial data. Wallets with enough
415
- // VTXOs to exceed a single page rely solely on the
440
+ // virtual outputs to exceed a single page rely solely on the
416
441
  // cursor-based delta mechanism for state updates.
417
442
  const fullSetComplete = !fullPage || fullPage.total <= 1;
418
443
  if (fullSetComplete) {
@@ -429,7 +454,7 @@ class ReadonlyWallet {
429
454
  const outpoint = `${cached.txid}:${cached.vout}`;
430
455
  const fresh = fullOutpoints.get(outpoint);
431
456
  if (!fresh) {
432
- // Server no longer knows about this VTXO
457
+ // Server no longer knows about this virtual output
433
458
  // it was spent between syncs.
434
459
  reconciledExtended.push({
435
460
  ...cached,
@@ -462,12 +487,15 @@ class ReadonlyWallet {
462
487
  };
463
488
  }
464
489
  /**
465
- * Clear all VTXO sync cursors, forcing a full re-bootstrap on next sync.
490
+ * Clear all virtual output sync cursors, forcing a full re-bootstrap on next sync.
466
491
  * Useful for recovery after indexer reprocessing or debugging.
467
492
  */
468
493
  async clearSyncCursors() {
469
494
  await (0, syncCursors_1.clearSyncCursors)(this.walletRepository);
470
495
  }
496
+ /**
497
+ * Build a transaction history view for the wallet's boarding address.
498
+ */
471
499
  async getBoardingTxs() {
472
500
  const utxos = [];
473
501
  const commitmentsToIgnore = new Set();
@@ -538,16 +566,25 @@ class ReadonlyWallet {
538
566
  commitmentsToIgnore,
539
567
  };
540
568
  }
569
+ /**
570
+ * Fetch and cache onchain inputs (UTXOs) received at the boarding address.
571
+ */
541
572
  async getBoardingUtxos() {
542
573
  const boardingAddress = await this.getBoardingAddress();
543
574
  const boardingUtxos = await this.onchainProvider.getCoins(boardingAddress);
544
575
  const utxos = boardingUtxos.map((utxo) => {
545
576
  return (0, utils_1.extendCoin)(this, utxo);
546
577
  });
547
- // Save boardingUtxos using unified repository
578
+ // Save boarding inputs using unified repository
548
579
  await this.walletRepository.saveUtxos(boardingAddress, utxos);
549
580
  return utxos;
550
581
  }
582
+ /**
583
+ * Subscribe to onchain and offchain notifications for newly received funds.
584
+ *
585
+ * @param eventCallback - Callback invoked when matching funds are detected
586
+ * @returns A function that stops the subscriptions
587
+ */
551
588
  async notifyIncomingFunds(eventCallback) {
552
589
  const arkAddress = await this.getAddress();
553
590
  const boardingAddress = await this.getBoardingAddress();
@@ -558,11 +595,11 @@ class ReadonlyWallet {
558
595
  return tx.vout.findIndex((v) => v.scriptpubkey_address === boardingAddress);
559
596
  };
560
597
  onchainStopFunc = await this.onchainProvider.watchAddresses([boardingAddress], (txs) => {
561
- // find all utxos belonging to our boarding address
598
+ // find all onchain outputs belonging to our boarding address
562
599
  const coins = txs
563
600
  // filter txs where address is in output
564
601
  .filter((tx) => findVoutOnTx(tx) !== -1)
565
- // return utxo as Coin
602
+ // return boarding input as Coin
566
603
  .map((tx) => {
567
604
  const { txid, status } = tx;
568
605
  const vout = findVoutOnTx(tx);
@@ -587,8 +624,8 @@ class ReadonlyWallet {
587
624
  };
588
625
  // Handle subscription updates asynchronously without blocking.
589
626
  // Note: subscription covers all wallet scripts (default + delegate),
590
- // but we can't determine which script each VTXO belongs to from the
591
- // subscription event. VTXOs are extended with the current offchainTapscript;
627
+ // but we can't determine which script each virtual output belongs to from the
628
+ // subscription event. Virtual outputs are extended with the current offchainTapscript;
592
629
  // this is for notification/display only — not for spending.
593
630
  // For correct extension metadata, use getVtxos() which queries per-script.
594
631
  (async () => {
@@ -615,8 +652,9 @@ class ReadonlyWallet {
615
652
  };
616
653
  return stopFunc;
617
654
  }
655
+ /** Fetch Arkade transaction ids that are still pending final settlement. */
618
656
  async fetchPendingTxs() {
619
- // get non-swept VTXOs, rely on the indexer only in case DB doesn't have the right state
657
+ // get non-swept virtual outputs, rely on the indexer only in case DB doesn't have the right state
620
658
  const scripts = await this.getWalletScripts();
621
659
  let { vtxos } = await this.indexerProvider.getVtxos({
622
660
  scripts,
@@ -657,7 +695,7 @@ class ReadonlyWallet {
657
695
  }
658
696
  /**
659
697
  * Build a map of scriptHex → VtxoScript for all wallet contracts,
660
- * so VTXOs can be extended with the correct tapscript per contract.
698
+ * so virtual outputs can be extended with the correct tapscript per contract.
661
699
  */
662
700
  async getScriptMap() {
663
701
  const map = new Map();
@@ -746,7 +784,6 @@ class ReadonlyWallet {
746
784
  indexerProvider: this.indexerProvider,
747
785
  contractRepository: this.contractRepository,
748
786
  walletRepository: this.walletRepository,
749
- getDefaultAddress: () => this.getAddress(),
750
787
  watcherConfig: this.watcherConfig,
751
788
  });
752
789
  // Register the wallet's current address as a contract
@@ -770,7 +807,7 @@ class ReadonlyWallet {
770
807
  address: await this.getAddress(),
771
808
  state: "active",
772
809
  });
773
- // Also register the non-delegate version so old VTXOs remain visible
810
+ // Also register the non-delegate version so old virtual outputs remain visible
774
811
  const nonDelegateScript = new default_1.DefaultVtxo.Script({
775
812
  pubKey: delegateScript.options.pubKey,
776
813
  serverPubKey: delegateScript.options.serverPubKey,
@@ -808,6 +845,7 @@ class ReadonlyWallet {
808
845
  }
809
846
  return manager;
810
847
  }
848
+ /** Dispose wallet-owned managers and release background resources. */
811
849
  async dispose() {
812
850
  const manager = this._contractManager ??
813
851
  (this._contractManagerInitializing
@@ -817,30 +855,31 @@ class ReadonlyWallet {
817
855
  this._contractManager = undefined;
818
856
  this._contractManagerInitializing = undefined;
819
857
  }
858
+ /** Async-dispose hook that forwards to `dispose()`. */
820
859
  async [Symbol.asyncDispose]() {
821
860
  await this.dispose();
822
861
  }
823
862
  }
824
863
  exports.ReadonlyWallet = ReadonlyWallet;
825
864
  /**
826
- * Main wallet implementation for Bitcoin transactions with Ark protocol support.
827
- * The wallet does not store any data locally and relies on Ark and onchain
828
- * providers to fetch UTXOs and VTXOs.
865
+ * Main wallet implementation for Bitcoin transactions with Arkade protocol support.
866
+ * The wallet does not store any data locally and relies on Arkade and onchain
867
+ * providers to fetch onchain and virtual outputs.
829
868
  *
830
869
  * @example
831
870
  * ```typescript
832
871
  * // Create a wallet with URL configuration
833
872
  * const wallet = await Wallet.create({
834
- * identity: SingleKey.fromHex('your_private_key'),
835
- * arkServerUrl: 'https://ark.example.com',
873
+ * identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
874
+ * arkServerUrl: 'https://arkade.computer',
836
875
  * esploraUrl: 'https://mempool.space/api'
837
876
  * });
838
877
  *
839
878
  * // Or with custom provider instances (e.g., for Expo/React Native)
840
879
  * const wallet = await Wallet.create({
841
- * identity: SingleKey.fromHex('your_private_key'),
842
- * arkProvider: new ExpoArkProvider('https://ark.example.com'),
843
- * indexerProvider: new ExpoIndexerProvider('https://ark.example.com'),
880
+ * identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
881
+ * arkProvider: new ExpoArkProvider('https://arkade.computer'),
882
+ * indexerProvider: new ExpoIndexerProvider('https://arkade.computer'),
844
883
  * esploraUrl: 'https://mempool.space/api'
845
884
  * });
846
885
  *
@@ -849,9 +888,9 @@ exports.ReadonlyWallet = ReadonlyWallet;
849
888
  * const boardingAddress = await wallet.getBoardingAddress();
850
889
  *
851
890
  * // Send bitcoin
852
- * const txid = await wallet.sendBitcoin({
853
- * address: 'tb1...',
854
- * amount: 50000
891
+ * const txid = await wallet.send({
892
+ * address: 'ark1q...',
893
+ * amount: 50000,
855
894
  * });
856
895
  * ```
857
896
  */
@@ -880,7 +919,7 @@ class Wallet extends ReadonlyWallet {
880
919
  this.forfeitOutputScript = forfeitOutputScript;
881
920
  this.forfeitPubkey = forfeitPubkey;
882
921
  /**
883
- * Async mutex that serializes all operations submitting VTXOs to the Ark
922
+ * Async mutex that serializes all operations submitting VTXOs to the Arkade
884
923
  * server (`settle`, `send`, `sendBitcoin`). This prevents VtxoManager's
885
924
  * background renewal from racing with user-initiated transactions for the
886
925
  * same VTXO inputs.
@@ -960,6 +999,19 @@ class Wallet extends ReadonlyWallet {
960
999
  await super.dispose();
961
1000
  }
962
1001
  }
1002
+ /**
1003
+ * Create a full wallet and initialize its background managers.
1004
+ *
1005
+ * @param config - Wallet configuration
1006
+ * @returns A wallet ready to query balances and send transactions
1007
+ * @example
1008
+ * ```typescript
1009
+ * const wallet = await Wallet.create({
1010
+ * identity,
1011
+ * arkServerUrl: 'https://arkade.computer',
1012
+ * });
1013
+ * ```
1014
+ */
963
1015
  static async create(config) {
964
1016
  const pubkey = await config.identity.xOnlyPublicKey();
965
1017
  if (!pubkey) {
@@ -991,7 +1043,7 @@ class Wallet extends ReadonlyWallet {
991
1043
  * @returns A readonly wallet with the same configuration but readonly identity
992
1044
  * @example
993
1045
  * ```typescript
994
- * const wallet = await Wallet.create({ identity: SingleKey.fromHex('...'), ... });
1046
+ * const wallet = await Wallet.create({ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'), ... });
995
1047
  * const readonlyWallet = await wallet.toReadonly();
996
1048
  *
997
1049
  * // Can query balance and addresses
@@ -999,7 +1051,7 @@ class Wallet extends ReadonlyWallet {
999
1051
  * const address = await readonlyWallet.getAddress();
1000
1052
  *
1001
1053
  * // But cannot send transactions (type error)
1002
- * // readonlyWallet.sendBitcoin(...); // TypeScript error
1054
+ * // readonlyWallet.send(...); // TypeScript error
1003
1055
  * ```
1004
1056
  */
1005
1057
  async toReadonly() {
@@ -1009,19 +1061,22 @@ class Wallet extends ReadonlyWallet {
1009
1061
  : this.identity; // Identity extends ReadonlyIdentity, so this is safe
1010
1062
  return new ReadonlyWallet(readonlyIdentity, this.network, this.onchainProvider, this.indexerProvider, this.arkServerPublicKey, this.offchainTapscript, this.boardingTapscript, this.dustAmount, this.walletRepository, this.contractRepository, this.delegatorProvider, this.watcherConfig);
1011
1063
  }
1064
+ /** Returns the delegator manager when delegation support is configured. */
1012
1065
  async getDelegatorManager() {
1013
1066
  return this._delegatorManager;
1014
1067
  }
1015
1068
  /**
1016
- * @deprecated Use `send`
1017
- * @param params
1069
+ * Send bitcoin to an Arkade address.
1070
+ *
1071
+ * @deprecated Use `send`.
1072
+ * @param params - Send parameters
1018
1073
  */
1019
1074
  async sendBitcoin(params) {
1020
1075
  if (params.amount <= 0) {
1021
1076
  throw new Error("Amount must be positive");
1022
1077
  }
1023
1078
  if (!(0, arkTransaction_1.isValidArkAddress)(params.address)) {
1024
- throw new Error("Invalid Ark address " + params.address);
1079
+ throw new Error("Invalid Arkade address " + params.address);
1025
1080
  }
1026
1081
  if (params.selectedVtxos && params.selectedVtxos.length > 0) {
1027
1082
  return this._withTxLock(async () => {
@@ -1066,6 +1121,13 @@ class Wallet extends ReadonlyWallet {
1066
1121
  amount: params.amount,
1067
1122
  });
1068
1123
  }
1124
+ /**
1125
+ * Settle boarding inputs and/or virtual outputs into a finalized mainnet transaction.
1126
+ *
1127
+ * @param params - Optional settlement inputs and outputs. When omitted, the wallet settles all eligible funds.
1128
+ * @param eventCallback - Optional callback invoked for settlement stream events.
1129
+ * @returns The finalized Arkade transaction id
1130
+ */
1069
1131
  async settle(params, eventCallback) {
1070
1132
  return this._withTxLock(() => this._settleImpl(params, eventCallback));
1071
1133
  }
@@ -1083,7 +1145,7 @@ class Wallet extends ReadonlyWallet {
1083
1145
  }
1084
1146
  }
1085
1147
  }
1086
- // if no params are provided, use all non expired boarding utxos and offchain vtxos as inputs
1148
+ // if no params are provided, use all non-expired boarding inputs and offchain virtual outputs as inputs
1087
1149
  // and send all to the offchain address
1088
1150
  if (!params) {
1089
1151
  const { fees } = await this.arkProvider.getInfo();
@@ -1104,7 +1166,7 @@ class Wallet extends ReadonlyWallet {
1104
1166
  amount: BigInt(utxo.value),
1105
1167
  });
1106
1168
  if (inputFee.value >= utxo.value) {
1107
- // skip if fees are greater than the utxo value
1169
+ // skip if fees are greater than the boarding input value
1108
1170
  continue;
1109
1171
  }
1110
1172
  filteredBoardingUtxos.push(utxo);
@@ -1125,7 +1187,7 @@ class Wallet extends ReadonlyWallet {
1125
1187
  : new Date(),
1126
1188
  });
1127
1189
  if (inputFee.value >= vtxo.value) {
1128
- // skip if fees are greater than the vtxo value
1190
+ // skip if fees are greater than the virtual output value
1129
1191
  continue;
1130
1192
  }
1131
1193
  filteredVtxos.push(vtxo);
@@ -1216,7 +1278,7 @@ class Wallet extends ReadonlyWallet {
1216
1278
  const assetPacket = (0, asset_1.createAssetPacket)(assetInputs, recipients);
1217
1279
  outputs.push(extension_1.Extension.create([assetPacket]).txOut());
1218
1280
  }
1219
- // session holds the state of the musig2 signing process of the vtxo tree
1281
+ // session holds the state of the musig2 signing process of the virtual output tree
1220
1282
  let session;
1221
1283
  const signingPublicKeys = [];
1222
1284
  if (hasOffchainOutputs) {
@@ -1267,7 +1329,7 @@ class Wallet extends ReadonlyWallet {
1267
1329
  for (const input of inputs) {
1268
1330
  // check if the input is an offchain "virtual" coin
1269
1331
  const vtxo = vtxos.find((vtxo) => vtxo.txid === input.txid && vtxo.vout === input.vout);
1270
- // boarding utxo, we need to sign the settlement tx
1332
+ // boarding input, we need to sign the settlement tx
1271
1333
  if (!vtxo) {
1272
1334
  for (let i = 0; i < settlementPsbt.inputsLength; i++) {
1273
1335
  const settlementInput = settlementPsbt.getInput(i);
@@ -1345,11 +1407,12 @@ class Wallet extends ReadonlyWallet {
1345
1407
  }
1346
1408
  }
1347
1409
  /**
1348
- * @implements Batch.Handler interface.
1410
+ * Create a batch event handler for settlement flows.
1411
+ *
1349
1412
  * @param intentId - The intent ID.
1350
- * @param inputs - The inputs of the intent.
1351
- * @param session - The musig2 signing session, if not provided, the signing will be skipped.
1352
- * @param expectedRecipients - Expected recipients to validate in the vtxo tree.
1413
+ * @param inputs - Inputs used by the intent.
1414
+ * @param expectedRecipients - Expected recipients to validate in the virtual output tree.
1415
+ * @param session - Optional musig2 signing session. When omitted, signing steps are skipped.
1353
1416
  */
1354
1417
  createBatchHandler(intentId, inputs, expectedRecipients, session) {
1355
1418
  let sweepTapTreeRoot;
@@ -1363,7 +1426,7 @@ class Wallet extends ReadonlyWallet {
1363
1426
  for (const idHash of event.intentIdHashes) {
1364
1427
  if (idHash === intentIdHashStr) {
1365
1428
  if (!this.arkProvider) {
1366
- throw new Error("Ark provider not configured");
1429
+ throw new Error("Arkade provider not configured");
1367
1430
  }
1368
1431
  await this.arkProvider.confirmRegistration(intentId);
1369
1432
  skip = false;
@@ -1396,10 +1459,10 @@ class Wallet extends ReadonlyWallet {
1396
1459
  // not a cosigner, skip the signing
1397
1460
  return { skip: true };
1398
1461
  }
1399
- // validate the unsigned vtxo tree
1462
+ // validate the unsigned virtual output tree
1400
1463
  const commitmentTx = btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(event.unsignedCommitmentTx));
1401
1464
  (0, validation_1.validateVtxoTxGraph)(vtxoTree, commitmentTx, sweepTapTreeRoot);
1402
- // validate that all expected receivers are in the vtxo tree with correct amounts and assets
1465
+ // validate that all expected receivers are in the virtual output tree with correct amounts and assets
1403
1466
  if (expectedRecipients && expectedRecipients.length > 0) {
1404
1467
  (0, validation_2.validateBatchRecipients)(commitmentTx, vtxoTree.leaves(), expectedRecipients, this.network);
1405
1468
  }
@@ -1500,7 +1563,7 @@ class Wallet extends ReadonlyWallet {
1500
1563
  /**
1501
1564
  * Finalizes pending transactions by retrieving them from the server and finalizing each one.
1502
1565
  * Skips the server check entirely when no send was interrupted (no pending tx flag set).
1503
- * @param vtxos - Optional list of VTXOs to use instead of retrieving them from the server
1566
+ * @param vtxos - Optional list of virtual outputs to use instead of retrieving them from the server
1504
1567
  * @returns Array of transaction IDs that were finalized
1505
1568
  */
1506
1569
  async finalizePendingTxs(vtxos) {
@@ -1599,13 +1662,13 @@ class Wallet extends ReadonlyWallet {
1599
1662
  /**
1600
1663
  * Send BTC and/or assets to one or more recipients.
1601
1664
  *
1602
- * @param recipients - Array of recipients with their addresses, BTC amounts, and assets
1603
- * @returns Promise resolving to the ark transaction ID
1665
+ * @param args - Recipients with their addresses, BTC amounts, and assets
1666
+ * @returns Promise resolving to the Arkade transaction ID
1604
1667
  *
1605
1668
  * @example
1606
1669
  * ```typescript
1607
1670
  * const txid = await wallet.send({
1608
- * address: 'ark1...',
1671
+ * address: 'ark1q...',
1609
1672
  * amount: 1000, // (optional, default to dust) btc amount to send to the output
1610
1673
  * assets: [{ assetId: 'abc123...', amount: 50 }] // (optional) list of assets to send
1611
1674
  * });
@@ -1753,8 +1816,8 @@ class Wallet extends ReadonlyWallet {
1753
1816
  }
1754
1817
  /**
1755
1818
  * Build an offchain transaction from the given inputs and outputs,
1756
- * sign it, submit to the ark provider, and finalize.
1757
- * @returns The ark transaction id and server-signed checkpoint PSBTs (for bookkeeping)
1819
+ * sign it, submit to the Arkade provider, and finalize.
1820
+ * @returns The Arkade transaction id and server-signed checkpoint PSBTs (for bookkeeping)
1758
1821
  */
1759
1822
  async buildAndSubmitOffchainTx(inputs, outputs) {
1760
1823
  const offchainTx = (0, arkTransaction_1.buildOffchainTx)(inputs.map((input) => {
@@ -1813,7 +1876,7 @@ class Wallet extends ReadonlyWallet {
1813
1876
  }
1814
1877
  return { arkTxid, signedCheckpointTxs };
1815
1878
  }
1816
- // mark vtxo spent and save change vtxo if any
1879
+ // mark virtual outputs as spent, save change outputs if any
1817
1880
  async updateDbAfterOffchainTx(inputs, arkTxid, signedCheckpointTxs, sentAmount, changeAmount, changeVout, changeAssets) {
1818
1881
  try {
1819
1882
  const spentVtxos = [];
@@ -1861,7 +1924,7 @@ class Wallet extends ReadonlyWallet {
1861
1924
  }
1862
1925
  const createdAt = Date.now();
1863
1926
  const addr = this.arkAddress.encode();
1864
- // Only save a change VTXO for preconfirmed coins (those with a batchExpiry).
1927
+ // Only save a change virtual output for preconfirmed coins (those with a batchExpiry).
1865
1928
  // Inputs without a batchExpiry are already settled/unrolled and don't need tracking.
1866
1929
  let changeVtxo;
1867
1930
  if (changeAmount > 0n && batchExpiry !== Number.MAX_SAFE_INTEGER) {
@@ -1905,7 +1968,7 @@ class Wallet extends ReadonlyWallet {
1905
1968
  console.warn("error saving offchain tx to repository", e);
1906
1969
  }
1907
1970
  }
1908
- // mark vtxo spent & settled, remove boarding utxo
1971
+ // mark virtual outputs as spent/settled, remove boarding inputs
1909
1972
  async updateDbAfterSettle(inputs, commitmentTxid) {
1910
1973
  try {
1911
1974
  const addr = this.arkAddress.encode();
@@ -1916,7 +1979,7 @@ class Wallet extends ReadonlyWallet {
1916
1979
  const isVtxo = (input) => "virtualStatus" in input;
1917
1980
  for (const input of inputs) {
1918
1981
  if (isVtxo(input)) {
1919
- // vtxo = mark it settled
1982
+ // virtual output = mark it settled
1920
1983
  const vtxo = (0, utils_1.extendVirtualCoin)(this, input);
1921
1984
  if (vtxo.arkTxId) {
1922
1985
  inputArkTxIds.add(vtxo.arkTxId);
@@ -1932,7 +1995,7 @@ class Wallet extends ReadonlyWallet {
1932
1995
  });
1933
1996
  }
1934
1997
  else {
1935
- // boarding utxo = remove it
1998
+ // boarding input = remove it
1936
1999
  boardingUtxoToRemove.add(`${input.txid}:${input.vout}`);
1937
2000
  }
1938
2001
  }
@@ -1957,13 +2020,13 @@ class Wallet extends ReadonlyWallet {
1957
2020
  exports.Wallet = Wallet;
1958
2021
  Wallet.MIN_FEE_RATE = 1; // sats/vbyte
1959
2022
  /**
1960
- * Select virtual coins to reach a target amount, prioritizing those closer to expiry
1961
- * @param coins List of virtual coins to select from
2023
+ * Select virtual outputs to reach a target amount, prioritizing those closer to expiry
2024
+ * @param coins List of virtual outputs to select from
1962
2025
  * @param targetAmount Target amount to reach in satoshis
1963
- * @returns Selected coins and change amount
2026
+ * @returns Selected virtual outputs and change amount
1964
2027
  */
1965
2028
  function selectVirtualCoins(coins, targetAmount) {
1966
- // Sort VTXOs by expiry (ascending) and amount (descending)
2029
+ // Sort virtual outputs by expiry (ascending) and amount (descending)
1967
2030
  const sortedCoins = [...coins].sort((a, b) => {
1968
2031
  // First sort by expiry if available
1969
2032
  const expiryA = a.virtualStatus.batchExpiry || Number.MAX_SAFE_INTEGER;
@@ -52,7 +52,7 @@ class AsyncStorageTaskQueue {
52
52
  // ── Config persistence (for background handler rehydration) ──────
53
53
  /**
54
54
  * Persist a config blob alongside the queue data.
55
- * Used by {@link ExpoWallet.setup} to store the wallet parameters
55
+ * Used by @see ExpoWallet.setup to store the wallet parameters
56
56
  * that the background handler needs to reconstruct providers.
57
57
  */
58
58
  async persistConfig(config) {
@@ -6,7 +6,7 @@ exports.CONTRACT_POLL_TASK_TYPE = "contract-poll";
6
6
  * Polls the indexer for the latest VTXO state of every contract and
7
7
  * persists the results to the wallet repository.
8
8
  *
9
- * Replicates the polling subset of {@link ContractManager.initialize}:
9
+ * Replicates the polling subset of @see ContractManager.initialize:
10
10
  * 1. Load all contracts from the contract repository.
11
11
  * 2. Mark expired active contracts as inactive.
12
12
  * 3. Paginated fetch of spendable VTXOs from the indexer.
@@ -29,7 +29,7 @@ exports.contractPollProcessor = {
29
29
  contract.state = "inactive";
30
30
  await contractRepository.saveContract(contract);
31
31
  }
32
- // Paginated fetch of spendable VTXOs
32
+ // Paginated fetch of spendable virtual outputs
33
33
  const pageSize = 100;
34
34
  let pageIndex = 0;
35
35
  let hasMore = true;
@@ -8,7 +8,7 @@ const utils_1 = require("../../wallet/utils");
8
8
  *
9
9
  * For each task in the inbox:
10
10
  * 1. Find the processor whose `taskType` matches `task.type`.
11
- * 2. Execute it, producing a {@link TaskResult}.
11
+ * 2. Execute it, producing a @see TaskResult.
12
12
  * 3. Push the result to the outbox and remove the task from the inbox.
13
13
  *
14
14
  * Tasks with no matching processor produce a `"noop"` result.
@@ -57,8 +57,8 @@ async function runTasks(queue, processors, deps) {
57
57
  return results;
58
58
  }
59
59
  /**
60
- * Build the {@link TaskDependencies} needed by task processors
61
- * (e.g. {@link import("./processors").contractPollProcessor}).
60
+ * Build the @see TaskDependencies needed by task processors
61
+ * (e.g. `src/worker/expo/processors/contractPollProcessor.ts`)
62
62
  *
63
63
  * This is the same construction that `defineExpoBackgroundTask` does
64
64
  * internally, extracted so that consumers with custom schedulers