@arkade-os/sdk 0.4.14 → 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 (203) hide show
  1. package/README.md +287 -215
  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 +25 -1
  12. package/dist/cjs/contracts/handlers/vhtlc.js +2 -4
  13. package/dist/cjs/extension/asset/assetGroup.js +92 -5
  14. package/dist/cjs/extension/asset/assetId.js +67 -3
  15. package/dist/cjs/extension/asset/assetInput.js +18 -0
  16. package/dist/cjs/extension/asset/assetOutput.js +15 -0
  17. package/dist/cjs/extension/asset/assetRef.js +66 -0
  18. package/dist/cjs/extension/asset/metadata.js +15 -0
  19. package/dist/cjs/extension/asset/packet.js +4 -1
  20. package/dist/cjs/extension/index.js +1 -1
  21. package/dist/cjs/forfeit.js +14 -0
  22. package/dist/cjs/identity/index.js +6 -0
  23. package/dist/cjs/identity/seedIdentity.js +5 -5
  24. package/dist/cjs/identity/singleKey.js +4 -0
  25. package/dist/cjs/index.js +5 -3
  26. package/dist/cjs/intent/index.js +28 -12
  27. package/dist/cjs/providers/ark.js +3 -2
  28. package/dist/cjs/providers/delegator.js +20 -1
  29. package/dist/cjs/providers/expoArk.js +2 -2
  30. package/dist/cjs/providers/indexer.js +2 -2
  31. package/dist/cjs/providers/onchain.js +2 -1
  32. package/dist/cjs/repositories/realm/schemas.js +2 -2
  33. package/dist/cjs/repositories/realm/types.js +1 -1
  34. package/dist/cjs/script/address.js +37 -6
  35. package/dist/cjs/script/base.js +70 -1
  36. package/dist/cjs/script/default.js +3 -0
  37. package/dist/cjs/script/delegate.js +4 -0
  38. package/dist/cjs/script/tapscript.js +25 -4
  39. package/dist/cjs/script/vhtlc.js +35 -27
  40. package/dist/cjs/storage/fileSystem.js +1 -1
  41. package/dist/cjs/storage/inMemory.js +1 -1
  42. package/dist/cjs/storage/indexedDB.js +1 -1
  43. package/dist/cjs/storage/localStorage.js +1 -1
  44. package/dist/cjs/tree/validation.js +1 -1
  45. package/dist/cjs/utils/arkTransaction.js +5 -5
  46. package/dist/cjs/utils/bip21.js +16 -3
  47. package/dist/cjs/utils/syncCursors.js +4 -4
  48. package/dist/cjs/utils/transaction.js +1 -1
  49. package/dist/cjs/utils/transactionHistory.js +11 -11
  50. package/dist/cjs/utils/unknownFields.js +3 -3
  51. package/dist/cjs/wallet/asset-manager.js +4 -4
  52. package/dist/cjs/wallet/batch.js +5 -5
  53. package/dist/cjs/wallet/delegator.js +9 -8
  54. package/dist/cjs/wallet/expo/background.js +3 -3
  55. package/dist/cjs/wallet/expo/wallet.js +7 -7
  56. package/dist/cjs/wallet/index.js +43 -0
  57. package/dist/cjs/wallet/onchain.js +43 -5
  58. package/dist/cjs/wallet/ramps.js +44 -14
  59. package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +22 -22
  60. package/dist/cjs/wallet/serviceWorker/wallet.js +28 -24
  61. package/dist/cjs/wallet/unroll.js +12 -8
  62. package/dist/cjs/wallet/utils.js +1 -1
  63. package/dist/cjs/wallet/vtxo-manager.js +123 -82
  64. package/dist/cjs/wallet/wallet.js +231 -98
  65. package/dist/cjs/worker/expo/asyncStorageTaskQueue.js +1 -1
  66. package/dist/cjs/worker/expo/processors/contractPollProcessor.js +2 -2
  67. package/dist/cjs/worker/expo/taskRunner.js +3 -3
  68. package/dist/cjs/worker/messageBus.js +3 -0
  69. package/dist/esm/arkfee/estimator.js +1 -1
  70. package/dist/esm/arkfee/types.js +2 -1
  71. package/dist/esm/arknote/index.js +43 -4
  72. package/dist/esm/bip322/index.js +1 -1
  73. package/dist/esm/contracts/arkcontract.js +1 -1
  74. package/dist/esm/contracts/contractManager.js +40 -24
  75. package/dist/esm/contracts/contractWatcher.js +29 -22
  76. package/dist/esm/contracts/handlers/default.js +1 -1
  77. package/dist/esm/contracts/handlers/delegate.js +1 -1
  78. package/dist/esm/contracts/handlers/helpers.js +24 -1
  79. package/dist/esm/contracts/handlers/vhtlc.js +3 -5
  80. package/dist/esm/extension/asset/assetGroup.js +92 -5
  81. package/dist/esm/extension/asset/assetId.js +67 -3
  82. package/dist/esm/extension/asset/assetInput.js +18 -0
  83. package/dist/esm/extension/asset/assetOutput.js +15 -0
  84. package/dist/esm/extension/asset/assetRef.js +66 -0
  85. package/dist/esm/extension/asset/metadata.js +15 -0
  86. package/dist/esm/extension/asset/packet.js +4 -1
  87. package/dist/esm/extension/index.js +1 -1
  88. package/dist/esm/forfeit.js +14 -0
  89. package/dist/esm/identity/index.js +5 -0
  90. package/dist/esm/identity/seedIdentity.js +5 -5
  91. package/dist/esm/identity/singleKey.js +4 -0
  92. package/dist/esm/index.js +3 -2
  93. package/dist/esm/intent/index.js +28 -12
  94. package/dist/esm/providers/ark.js +3 -2
  95. package/dist/esm/providers/delegator.js +20 -1
  96. package/dist/esm/providers/expoArk.js +2 -2
  97. package/dist/esm/providers/indexer.js +2 -2
  98. package/dist/esm/providers/onchain.js +2 -1
  99. package/dist/esm/repositories/realm/schemas.js +2 -2
  100. package/dist/esm/repositories/realm/types.js +1 -1
  101. package/dist/esm/script/address.js +37 -6
  102. package/dist/esm/script/base.js +70 -1
  103. package/dist/esm/script/default.js +3 -0
  104. package/dist/esm/script/delegate.js +4 -0
  105. package/dist/esm/script/tapscript.js +25 -4
  106. package/dist/esm/script/vhtlc.js +35 -27
  107. package/dist/esm/storage/fileSystem.js +1 -1
  108. package/dist/esm/storage/inMemory.js +1 -1
  109. package/dist/esm/storage/indexedDB.js +1 -1
  110. package/dist/esm/storage/localStorage.js +1 -1
  111. package/dist/esm/tree/validation.js +1 -1
  112. package/dist/esm/utils/arkTransaction.js +5 -5
  113. package/dist/esm/utils/bip21.js +16 -3
  114. package/dist/esm/utils/syncCursors.js +4 -4
  115. package/dist/esm/utils/transaction.js +1 -1
  116. package/dist/esm/utils/transactionHistory.js +11 -11
  117. package/dist/esm/utils/unknownFields.js +3 -3
  118. package/dist/esm/wallet/asset-manager.js +4 -4
  119. package/dist/esm/wallet/batch.js +5 -5
  120. package/dist/esm/wallet/delegator.js +9 -8
  121. package/dist/esm/wallet/expo/background.js +3 -3
  122. package/dist/esm/wallet/expo/wallet.js +7 -7
  123. package/dist/esm/wallet/index.js +43 -0
  124. package/dist/esm/wallet/onchain.js +43 -5
  125. package/dist/esm/wallet/ramps.js +44 -14
  126. package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +22 -22
  127. package/dist/esm/wallet/serviceWorker/wallet.js +28 -24
  128. package/dist/esm/wallet/unroll.js +12 -8
  129. package/dist/esm/wallet/utils.js +1 -1
  130. package/dist/esm/wallet/vtxo-manager.js +122 -81
  131. package/dist/esm/wallet/wallet.js +232 -99
  132. package/dist/esm/worker/expo/asyncStorageTaskQueue.js +1 -1
  133. package/dist/esm/worker/expo/processors/contractPollProcessor.js +2 -2
  134. package/dist/esm/worker/expo/taskRunner.js +3 -3
  135. package/dist/esm/worker/messageBus.js +3 -0
  136. package/dist/types/arkfee/estimator.d.ts +1 -1
  137. package/dist/types/arkfee/types.d.ts +2 -1
  138. package/dist/types/arknote/index.d.ts +44 -4
  139. package/dist/types/bip322/index.d.ts +1 -1
  140. package/dist/types/contracts/arkcontract.d.ts +1 -1
  141. package/dist/types/contracts/contractManager.d.ts +40 -63
  142. package/dist/types/contracts/contractWatcher.d.ts +39 -18
  143. package/dist/types/contracts/handlers/default.d.ts +1 -1
  144. package/dist/types/contracts/handlers/delegate.d.ts +1 -1
  145. package/dist/types/contracts/handlers/helpers.d.ts +11 -1
  146. package/dist/types/contracts/types.d.ts +36 -26
  147. package/dist/types/extension/asset/assetGroup.d.ts +92 -1
  148. package/dist/types/extension/asset/assetId.d.ts +67 -3
  149. package/dist/types/extension/asset/assetInput.d.ts +18 -0
  150. package/dist/types/extension/asset/assetOutput.d.ts +15 -0
  151. package/dist/types/extension/asset/assetRef.d.ts +66 -0
  152. package/dist/types/extension/asset/metadata.d.ts +15 -0
  153. package/dist/types/extension/asset/packet.d.ts +4 -1
  154. package/dist/types/extension/index.d.ts +1 -1
  155. package/dist/types/forfeit.d.ts +14 -0
  156. package/dist/types/identity/index.d.ts +36 -0
  157. package/dist/types/identity/seedIdentity.d.ts +10 -8
  158. package/dist/types/identity/singleKey.d.ts +4 -0
  159. package/dist/types/index.d.ts +3 -3
  160. package/dist/types/intent/index.d.ts +19 -6
  161. package/dist/types/providers/ark.d.ts +40 -2
  162. package/dist/types/providers/delegator.d.ts +54 -1
  163. package/dist/types/providers/expoArk.d.ts +2 -2
  164. package/dist/types/providers/indexer.d.ts +105 -2
  165. package/dist/types/providers/onchain.d.ts +62 -1
  166. package/dist/types/repositories/realm/schemas.d.ts +2 -2
  167. package/dist/types/repositories/realm/types.d.ts +2 -2
  168. package/dist/types/repositories/walletRepository.d.ts +16 -0
  169. package/dist/types/script/address.d.ts +35 -2
  170. package/dist/types/script/base.d.ts +66 -1
  171. package/dist/types/script/default.d.ts +3 -0
  172. package/dist/types/script/delegate.d.ts +4 -0
  173. package/dist/types/script/tapscript.d.ts +17 -2
  174. package/dist/types/script/vhtlc.d.ts +35 -27
  175. package/dist/types/storage/fileSystem.d.ts +1 -1
  176. package/dist/types/storage/inMemory.d.ts +1 -1
  177. package/dist/types/storage/index.d.ts +1 -1
  178. package/dist/types/storage/indexedDB.d.ts +1 -1
  179. package/dist/types/storage/localStorage.d.ts +1 -1
  180. package/dist/types/utils/arkTransaction.d.ts +3 -3
  181. package/dist/types/utils/bip21.d.ts +17 -0
  182. package/dist/types/utils/syncCursors.d.ts +4 -4
  183. package/dist/types/utils/transaction.d.ts +1 -1
  184. package/dist/types/utils/transactionHistory.d.ts +3 -3
  185. package/dist/types/utils/unknownFields.d.ts +5 -5
  186. package/dist/types/wallet/asset-manager.d.ts +3 -3
  187. package/dist/types/wallet/batch.d.ts +27 -7
  188. package/dist/types/wallet/delegator.d.ts +10 -0
  189. package/dist/types/wallet/expo/background.d.ts +4 -4
  190. package/dist/types/wallet/expo/wallet.d.ts +10 -10
  191. package/dist/types/wallet/index.d.ts +457 -25
  192. package/dist/types/wallet/onchain.d.ts +42 -4
  193. package/dist/types/wallet/ramps.d.ts +40 -10
  194. package/dist/types/wallet/serviceWorker/wallet-message-handler.d.ts +4 -4
  195. package/dist/types/wallet/serviceWorker/wallet.d.ts +71 -33
  196. package/dist/types/wallet/unroll.d.ts +8 -6
  197. package/dist/types/wallet/vtxo-manager.d.ts +146 -93
  198. package/dist/types/wallet/wallet.d.ts +91 -33
  199. package/dist/types/worker/expo/asyncStorageTaskQueue.d.ts +1 -1
  200. package/dist/types/worker/expo/processors/contractPollProcessor.d.ts +1 -1
  201. package/dist/types/worker/expo/taskRunner.d.ts +6 -6
  202. package/dist/types/worker/messageBus.d.ts +5 -3
  203. package/package.json +18 -10
@@ -2,7 +2,7 @@ import * as bip68 from "bip68";
2
2
  import { RawWitness, ScriptNum } from "@scure/btc-signer";
3
3
  import { hex } from "@scure/base";
4
4
  /**
5
- * ArkPsbtFieldKey is the key values for ark psbt fields.
5
+ * ArkPsbtFieldKey are the available key names for the Arkade PSBT custom fields.
6
6
  */
7
7
  export var ArkPsbtFieldKey;
8
8
  (function (ArkPsbtFieldKey) {
@@ -12,8 +12,8 @@ export var ArkPsbtFieldKey;
12
12
  ArkPsbtFieldKey["ConditionWitness"] = "condition";
13
13
  })(ArkPsbtFieldKey || (ArkPsbtFieldKey = {}));
14
14
  /**
15
- * ArkPsbtFieldKeyType is the type of the ark psbt field key.
16
- * Every ark psbt field has key type 222.
15
+ * ArkPsbtFieldKeyType is the key type of the Arkade PSBT custom field.
16
+ * Every Arkade PSBT field has key type 222.
17
17
  */
18
18
  export const ArkPsbtFieldKeyType = 222;
19
19
  /**
@@ -23,7 +23,7 @@ export class AssetManager extends ReadonlyAssetManager {
23
23
  * @param params.amount - Amount of asset units to issue
24
24
  * @param params.controlAssetId - Optional control asset ID (for reissuable assets)
25
25
  * @param params.metadata - Optional metadata to attach to the asset
26
- * @returns Promise resolving to the ark transaction ID and asset ID
26
+ * @returns Promise resolving to the Arkade transaction ID and asset ID
27
27
  *
28
28
  * @example
29
29
  * ```typescript
@@ -108,7 +108,7 @@ export class AssetManager extends ReadonlyAssetManager {
108
108
  * @param params - Parameters for asset reissuance
109
109
  * @param params.assetId - The asset ID to reissue (control asset ID is resolved via getAssetDetails)
110
110
  * @param params.amount - Amount of additional units to issue
111
- * @returns Promise resolving to the ark transaction ID
111
+ * @returns Promise resolving to the Arkade transaction ID
112
112
  *
113
113
  * @example
114
114
  * ```typescript
@@ -215,7 +215,7 @@ export class AssetManager extends ReadonlyAssetManager {
215
215
  * @param params - Parameters for burning
216
216
  * @param params.assetId - The asset ID to burn
217
217
  * @param params.amount - Amount of units to burn
218
- * @returns Promise resolving to the ark transaction ID
218
+ * @returns Promise resolving to the Arkade transaction ID
219
219
  *
220
220
  * @example
221
221
  * ```typescript
@@ -233,7 +233,7 @@ export class AssetManager extends ReadonlyAssetManager {
233
233
  withRecoverable: false,
234
234
  });
235
235
  const assetChanges = new Map();
236
- // select vtxos with the asset to burn
236
+ // select virtual outputs with the asset to burn
237
237
  const { selected: assetCoins } = selectCoinsWithAsset(virtualCoins, params.assetId, BigInt(params.amount));
238
238
  const selectedCoins = [...assetCoins];
239
239
  let totalBtcSelected = 0;
@@ -11,7 +11,7 @@ import { hex } from "@scure/base";
11
11
  * const handler = wallet.createBatchHandler(intentId, inputs, expectedRecipients, musig2session);
12
12
  *
13
13
  * const abortController = new AbortController();
14
- * // Get event stream from Ark provider
14
+ * // Get event stream from the Arkade provider
15
15
  * const eventStream = arkProvider.getEventStream(
16
16
  * abortController.signal,
17
17
  * ['your-topic-1', 'your-topic-2']
@@ -96,7 +96,7 @@ export var Batch;
96
96
  step !== Step.TreeNoncesAggregated) {
97
97
  continue;
98
98
  }
99
- // batchIndex 0 = vtxo tree, batchIndex 1 = connector tree
99
+ // batchIndex 0 = virtual output tree, batchIndex 1 = connector tree
100
100
  if (event.batchIndex === 0) {
101
101
  flatVtxoTree.push(event.chunk);
102
102
  }
@@ -115,7 +115,7 @@ export var Batch;
115
115
  if (!vtxoTree) {
116
116
  throw new Error("vtxo tree not initialized");
117
117
  }
118
- // push signature to the vtxo tree
118
+ // push signature to the virtual output tree
119
119
  const tapKeySig = hex.decode(event.signature);
120
120
  vtxoTree.update(event.txid, (tx) => {
121
121
  tx.updateInput(0, {
@@ -131,7 +131,7 @@ export var Batch;
131
131
  if (step !== Step.BatchStarted) {
132
132
  continue;
133
133
  }
134
- // create vtxo tree from collected chunks
134
+ // create virtual output tree from collected chunks
135
135
  vtxoTree = TxTree.create(flatVtxoTree);
136
136
  const { skip } = await handler.onTreeSigningStarted(event, vtxoTree);
137
137
  if (!skip) {
@@ -153,7 +153,7 @@ export var Batch;
153
153
  if (step !== Step.TreeNoncesAggregated) {
154
154
  continue;
155
155
  }
156
- // Build vtxo tree if it hasn't been built yet
156
+ // Build virtual output tree if it hasn't been built yet
157
157
  if (!vtxoTree && flatVtxoTree.length > 0) {
158
158
  vtxoTree = TxTree.create(flatVtxoTree);
159
159
  }
@@ -8,6 +8,7 @@ import { getNetwork } from '../networks.js';
8
8
  import { createAssetPacket } from './asset.js';
9
9
  import { Extension } from '../extension/index.js';
10
10
  export class DelegatorManagerImpl {
11
+ /** Create a delegator manager from the configured provider, Arkade info source, and wallet identity. */
11
12
  constructor(delegatorProvider, arkInfoProvider, identity) {
12
13
  this.delegatorProvider = delegatorProvider;
13
14
  this.arkInfoProvider = arkInfoProvider;
@@ -24,7 +25,7 @@ export class DelegatorManagerImpl {
24
25
  // fetch server and delegator info once, shared across all groups
25
26
  const arkInfo = await this.arkInfoProvider.getInfo();
26
27
  const delegateInfo = await this.delegatorProvider.getDelegateInfo();
27
- // if explicit delegateAt is provided, delegate all vtxos at once without sorting
28
+ // if explicit delegateAt is provided, delegate all virtual outputs at once without sorting
28
29
  if (delegateAt) {
29
30
  try {
30
31
  await delegate(this.identity, this.delegatorProvider, arkInfo, delegateInfo, vtxos, destinationScript, delegateAt);
@@ -34,7 +35,7 @@ export class DelegatorManagerImpl {
34
35
  }
35
36
  return { delegated: vtxos, failed: [] };
36
37
  }
37
- // if no explicit delegateAt is provided, sort vtxos by expiry and delegate in groups of the same expiry day
38
+ // if no explicit delegateAt is provided, sort virtual outputs by expiry and delegate in groups of the same expiry day
38
39
  const groupByExpiry = new Map();
39
40
  let recoverableVtxos = [];
40
41
  for (const vtxo of vtxos) {
@@ -51,7 +52,7 @@ export class DelegatorManagerImpl {
51
52
  vtxo,
52
53
  ]);
53
54
  }
54
- // if no groups, it means we only need to delegate the recoverable vtxos
55
+ // if no groups, it means we only need to delegate the recoverable virtual outputs
55
56
  if (groupByExpiry.size === 0) {
56
57
  try {
57
58
  await delegate(this.identity, this.delegatorProvider, arkInfo, delegateInfo, recoverableVtxos, destinationScript, delegateAt);
@@ -64,7 +65,7 @@ export class DelegatorManagerImpl {
64
65
  }
65
66
  return { delegated: recoverableVtxos, failed: [] };
66
67
  }
67
- // search for the earliest group, include recoverable vtxos into it
68
+ // search for the earliest group, include recoverable virtual outputs into it
68
69
  const earliestGroup = Math.min(...groupByExpiry.keys());
69
70
  groupByExpiry.set(earliestGroup, [
70
71
  ...(groupByExpiry.get(earliestGroup) ?? []),
@@ -86,9 +87,9 @@ export class DelegatorManagerImpl {
86
87
  }
87
88
  }
88
89
  /**
89
- * Delegates virtual coins to a delegator provider, allowing them to manage the coins renewal
90
- * on behalf of the wallet.
91
- * @param vtxos - Array of extended virtual coins to delegate. Must not be empty.
90
+ * Delegates virtual outputs to a delegation service, allowing them to manage their renewal
91
+ * on behalf of the wallet owner.
92
+ * @param vtxos - Array of extended virtual outputs to delegate. Must not be empty.
92
93
  * @param delegateAt - Optional Date specifying when the delegation
93
94
  * should occur. If not provided, defaults to 12 hours before the earliest
94
95
  * expiry time of the provided vtxos.
@@ -105,7 +106,7 @@ async function delegate(identity, delegatorProvider, arkInfo, delegateInfo, vtxo
105
106
  .filter((coin) => !isRecoverable(coin) && coin.virtualStatus.batchExpiry)
106
107
  .reduce((min, coin) => Math.min(min, coin.virtualStatus.batchExpiry), Number.MAX_SAFE_INTEGER);
107
108
  if (!expiryTimestamp || expiryTimestamp === Number.MAX_SAFE_INTEGER) {
108
- // if no expiry (recoverable vtxos), delegate 1 minute from now
109
+ // if no expiry (recoverable virtual outputs), delegate 1 minute from now
109
110
  delegateAt = new Date(Date.now() + 1 * 60 * 1000);
110
111
  }
111
112
  else {
@@ -60,7 +60,7 @@ export function defineExpoBackgroundTask(taskName, options) {
60
60
  const indexerProvider = new ExpoIndexerProvider(config.arkServerUrl);
61
61
  const arkProvider = new ExpoArkProvider(config.arkServerUrl);
62
62
  // Reconstruct default offchainTapscript as fallback
63
- // for VTXOs not associated with a contract.
63
+ // for virtual outputs not associated with a contract.
64
64
  const offchainTapscript = new DefaultVtxo.Script({
65
65
  pubKey: hex.decode(config.pubkeyHex),
66
66
  serverPubKey: hex.decode(config.serverPubKeyHex),
@@ -104,8 +104,8 @@ export function defineExpoBackgroundTask(taskName, options) {
104
104
  /**
105
105
  * Activate the OS-level background task scheduler.
106
106
  *
107
- * Call this after {@link defineExpoBackgroundTask} (typically inside
108
- * {@link ExpoWallet.setup} or in a React component after wallet init).
107
+ * Call this after @see defineExpoBackgroundTask (typically inside
108
+ * @see ExpoWallet.setup or in a React component after wallet init).
109
109
  *
110
110
  * @param minimumInterval - Minimum interval in minutes (default 15).
111
111
  */
@@ -8,7 +8,7 @@ import { DefaultVtxo } from '../../script/default.js';
8
8
  /**
9
9
  * Expo/React Native wallet with built-in background task processing.
10
10
  *
11
- * Wraps a standard {@link Wallet} and adds a lightweight task queue
11
+ * Wraps a standard @see Wallet and adds a lightweight task queue
12
12
  * for keeping contract/VTXO state fresh while the app is active and
13
13
  * across Expo BackgroundTask wakes.
14
14
  *
@@ -18,10 +18,10 @@ import { DefaultVtxo } from '../../script/default.js';
18
18
  * import { AsyncStorageTaskQueue } from "@arkade-os/sdk/worker/expo";
19
19
  *
20
20
  * const wallet = await ExpoWallet.setup({
21
- * identity: SingleKey.fromHex(privateKey),
22
- * arkServerUrl,
23
- * esploraUrl,
24
- * storage: { walletRepository, contractRepository },
21
+ * identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
22
+ * arkServerUrl: 'https://arkade.computer',
23
+ * esploraUrl: 'https://mempool.space/api',
24
+ * storage: { ... },
25
25
  * background: {
26
26
  * taskName: "ark-background-poll",
27
27
  * taskQueue: new AsyncStorageTaskQueue(AsyncStorage),
@@ -50,8 +50,8 @@ export class ExpoWallet {
50
50
  /**
51
51
  * Create an ExpoWallet with background task support.
52
52
  *
53
- * 1. Creates the inner {@link Wallet} via `Wallet.create()`.
54
- * 2. Wires up processors (defaults to {@link contractPollProcessor}).
53
+ * 1. Creates the inner @see Wallet via `Wallet.create()`.
54
+ * 2. Wires up processors (defaults to @see contractPollProcessor).
55
55
  * 3. Persists background config for the background handler (if the queue supports it).
56
56
  * 4. Seeds the task queue with a `contract-poll` task.
57
57
  * 5. Registers the background task with the OS scheduler (if `minimumBackgroundInterval` is set).
@@ -1,14 +1,48 @@
1
+ /** Wallet transaction direction. */
1
2
  export var TxType;
2
3
  (function (TxType) {
3
4
  TxType["TxSent"] = "SENT";
4
5
  TxType["TxReceived"] = "RECEIVED";
5
6
  })(TxType || (TxType = {}));
7
+ /**
8
+ * Return whether a virtual output is still spendable.
9
+ *
10
+ * @param vtxo - virtual output to inspect
11
+ * @returns `true` when the virtual output is not marked as spent
12
+ *
13
+ * @see isRecoverable
14
+ * @see isExpired
15
+ */
6
16
  export function isSpendable(vtxo) {
7
17
  return !vtxo.isSpent;
8
18
  }
19
+ /**
20
+ * Return whether a virtual output is recoverable.
21
+ *
22
+ * @param vtxo - virtual output to inspect
23
+ * @returns `true` when the virtual output is swept but still spendable
24
+ *
25
+ * @remarks
26
+ * Recoverable virtual outputs are typically re-settled into fresh virtual outputs by the virtual output manager.
27
+ *
28
+ * @see isSpendable
29
+ * @see isExpired
30
+ */
9
31
  export function isRecoverable(vtxo) {
10
32
  return vtxo.virtualStatus.state === "swept" && isSpendable(vtxo);
11
33
  }
34
+ /**
35
+ * Return whether a virtual output should be treated as expired.
36
+ *
37
+ * @param vtxo - virtual output to inspect
38
+ * @returns `true` when the virtual output is swept or its batch expiry has passed
39
+ * @remarks
40
+ * On regtest-like environments the upstream expiry value may be expressed as a block
41
+ * height instead of a timestamp. This helper intentionally ignores obviously non-time
42
+ * values to avoid false positives.
43
+ *
44
+ * @see VirtualStatus.batchExpiry
45
+ */
12
46
  export function isExpired(vtxo) {
13
47
  if (vtxo.virtualStatus.state === "swept")
14
48
  return true; // swept by server = expired
@@ -23,6 +57,15 @@ export function isExpired(vtxo) {
23
57
  return false;
24
58
  return expiry <= Date.now();
25
59
  }
60
+ /**
61
+ * Return whether a virtual output is below the dust threshold.
62
+ *
63
+ * @param vtxo - virtual output to inspect
64
+ * @param dust - dust threshold in satoshis
65
+ * @returns `true` when the virtual output value is below `dust`
66
+ *
67
+ * @see isRecoverable
68
+ */
26
69
  export function isSubdust(vtxo, dust) {
27
70
  return vtxo.value < dust;
28
71
  }
@@ -9,7 +9,7 @@ import { DUST_AMOUNT } from './utils.js';
9
9
  * Onchain Bitcoin wallet implementation for traditional Bitcoin transactions.
10
10
  *
11
11
  * This wallet handles regular Bitcoin transactions on the blockchain without
12
- * using the Ark protocol. It supports P2TR (Pay-to-Taproot) addresses and
12
+ * using the Arkade protocol. It supports P2TR (Pay-to-Taproot) addresses and
13
13
  * provides basic Bitcoin wallet functionality.
14
14
  *
15
15
  * @example
@@ -29,6 +29,16 @@ export class OnchainWallet {
29
29
  this.onchainP2TR = onchainP2TR;
30
30
  this.provider = provider;
31
31
  }
32
+ /**
33
+ * Create an onchain wallet for the given identity and Bitcoin network.
34
+ *
35
+ * @param identity - Identity used to derive the Taproot key and sign transactions
36
+ * @param networkName - Bitcoin network name, @see NetworkName
37
+ * @param provider - Optional onchain provider override, @see OnchainProvider
38
+ * @returns Configured onchain wallet
39
+ * @defaultValue `provider = new EsploraProvider('https://mempool.space/api')`
40
+ * @throws Error if the configured identity cannot produce a valid x-only public key
41
+ */
32
42
  static async create(identity, networkName, provider) {
33
43
  const pubkey = await identity.xOnlyPublicKey();
34
44
  if (!pubkey) {
@@ -42,9 +52,21 @@ export class OnchainWallet {
42
52
  get address() {
43
53
  return this.onchainP2TR.address || "";
44
54
  }
55
+ /**
56
+ * Fetch spendable onchain outputs for the wallet address.
57
+ *
58
+ * @returns Spendable onchain outputs for the wallet address
59
+ * @see getBalance
60
+ */
45
61
  async getCoins() {
46
62
  return this.provider.getCoins(this.address);
47
63
  }
64
+ /**
65
+ * Return the wallet's total onchain balance in satoshis.
66
+ *
67
+ * @returns Confirmed plus unconfirmed onchain balance
68
+ * @see getCoins
69
+ */
48
70
  async getBalance() {
49
71
  const coins = await this.getCoins();
50
72
  const onchainConfirmed = coins
@@ -59,9 +81,9 @@ export class OnchainWallet {
59
81
  /**
60
82
  * Iteratively selects coins and estimates transaction fees until convergence.
61
83
  *
62
- * This method handles the circular dependency between coin selection and fee
84
+ * This method handles the circular dependency between output selection and fee
63
85
  * estimation: the fee depends on transaction size, which depends on the number
64
- * of inputs (selected coins) and whether a change output is needed.
86
+ * of inputs (selected outputs) and whether a change output is needed.
65
87
  *
66
88
  * The algorithm iterates up to 10 times, refining the fee estimate based on
67
89
  * the actual transaction structure. It resolves dust oscillation loops that
@@ -70,7 +92,7 @@ export class OnchainWallet {
70
92
  * When a lower fee is computed (indicating the change output was dropped),
71
93
  * the function accepts this state to guarantee termination.
72
94
  *
73
- * @param coins - Available coins to select from
95
+ * @param coins - Available onchain outputs to select from
74
96
  * @param amount - Target send amount in satoshis
75
97
  * @param feeRate - Fee rate in sat/vbyte
76
98
  * @param recipientAddress - Destination address for size estimation
@@ -103,6 +125,14 @@ export class OnchainWallet {
103
125
  }
104
126
  throw new Error("Fee estimation failed: could not converge");
105
127
  }
128
+ /**
129
+ * Send bitcoin to a single onchain address.
130
+ *
131
+ * @param params - destination `address`, `amount` (in satoshis), and optional `feeRate` override (other fields ignored)
132
+ * @returns Broadcast transaction id
133
+ * @throws Error if the amount is non-positive, below dust, or cannot be funded
134
+ * @see SendBitcoinParams
135
+ */
106
136
  async send(params) {
107
137
  if (params.amount <= 0) {
108
138
  throw new Error("Amount must be positive");
@@ -148,6 +178,14 @@ export class OnchainWallet {
148
178
  const txid = await this.provider.broadcastTransaction(tx.hex);
149
179
  return txid;
150
180
  }
181
+ /**
182
+ * CPFP-bump a parent transaction that contains a pay-to-anchor output.
183
+ *
184
+ * @param parent - Parent transaction containing a pay-to-anchor output
185
+ * @returns Tuple of parent transaction id and child transaction id
186
+ * @throws Error if the parent transaction has no pay-to-anchor output or bumping cannot be funded
187
+ * @see send
188
+ */
151
189
  async bumpP2A(parent) {
152
190
  const parentVsize = parent.vsize;
153
191
  let child = new Transaction({
@@ -169,7 +207,7 @@ export class OnchainWallet {
169
207
  if (!fee) {
170
208
  throw new Error(`invalid fee, got ${fee} with vsize ${packageVSize}, feeRate ${feeRate}`);
171
209
  }
172
- // Select coins
210
+ // Select onchain outputs
173
211
  const coins = await this.getCoins();
174
212
  const selected = selectCoins(coins, fee, true);
175
213
  for (const input of selected.inputs) {
@@ -4,30 +4,50 @@ import { hex } from "@scure/base";
4
4
  import { networks } from '../networks.js';
5
5
  import { ArkAddress } from '../script/address.js';
6
6
  /**
7
- * Ramps is a class wrapping IWallet.settle method to provide a more convenient interface for onboarding and offboarding operations.
7
+ * Ramps is a class wrapping `settle` method to provide a more convenient interface for onboarding and offboarding operations.
8
+ *
9
+ * @see IWallet.settle
10
+ * @see onboard
11
+ * @see offboard
8
12
  *
9
13
  * @example
10
14
  * ```typescript
11
15
  * const ramps = new Ramps(wallet);
12
- * await ramps.onboard(); // onboard all boarding utxos
13
- * await ramps.offboard(myOnchainAddress); // collaborative exit all vtxos to onchain address
16
+ * const feeInfo = { intentFee: {}, txFeeRate: '1' };
17
+ * await ramps.onboard(feeInfo); // onboard all boarding inputs
18
+ * await ramps.offboard('bc1q...', feeInfo); // collaboratively exit all virtual outputs to an onchain address
14
19
  * ```
15
20
  */
16
21
  export class Ramps {
22
+ /**
23
+ * Create convenience wrappers for onboarding and offboarding flows.
24
+ *
25
+ * @param wallet - Wallet used to query funds and execute settlement transactions
26
+ */
17
27
  constructor(wallet) {
18
28
  this.wallet = wallet;
19
29
  }
20
30
  /**
21
- * Onboard boarding utxos.
31
+ * Onboard boarding inputs.
22
32
  *
23
33
  * @param feeInfo - The fee info to deduct from the onboard amount.
24
- * @param boardingUtxos - The boarding utxos to onboard. If not provided, all boarding utxos will be used.
25
- * @param amount - The amount to onboard. If not provided, the total amount of boarding utxos will be onboarded.
26
- * @param eventCallback - The callback to receive settlement events. optional.
34
+ * @param boardingUtxos - Specific boarding inputs to onboard. If not provided, all boarding inputs will be used.
35
+ * @param amount - Amount to onboard. If not provided, the total amount of boarding inputs will be onboarded.
36
+ * @param eventCallback - Optional callback that receives settlement events
37
+ * @returns The Arkade transaction id created by settlement
38
+ * @throws Error if no boarding inputs remain after fee deduction or if `amount` exceeds available value
39
+ * @see IWallet.getBoardingUtxos
40
+ * @see IWallet.settle
41
+ * @example
42
+ * ```typescript
43
+ * const feeInfo = { intentFee: {}, txFeeRate: '1' };
44
+ * const ramps = new Ramps(wallet);
45
+ * await ramps.onboard(feeInfo);
46
+ * ```
27
47
  */
28
48
  async onboard(feeInfo, boardingUtxos, amount, eventCallback) {
29
49
  boardingUtxos = boardingUtxos ?? (await this.wallet.getBoardingUtxos());
30
- // Calculate input fees and filter out utxos where fee >= value
50
+ // Calculate input fees and filter out boarding inputs where fee >= value.
31
51
  const estimator = new Estimator(feeInfo?.intentFee ?? {});
32
52
  const filteredBoardingUtxos = [];
33
53
  let totalAmount = 0n;
@@ -36,7 +56,7 @@ export class Ramps {
36
56
  amount: BigInt(utxo.value),
37
57
  });
38
58
  if (inputFee.satoshis >= utxo.value) {
39
- // skip if fees are greater than or equal to the utxo value
59
+ // Skip boarding inputs where spending fees are greater than or equal to the input value.
40
60
  continue;
41
61
  }
42
62
  filteredBoardingUtxos.push(utxo);
@@ -84,19 +104,29 @@ export class Ramps {
84
104
  }, eventCallback);
85
105
  }
86
106
  /**
87
- * Offboard vtxos, or "collaborative exit" vtxos to onchain address.
107
+ * Offboard virtual outputs, or collaboratively exit them to an onchain address.
88
108
  *
89
109
  * @param destinationAddress - The destination address to offboard to.
90
110
  * @param feeInfo - The fee info to deduct from the offboard amount.
91
- * @param amount - The amount to offboard. If not provided, the total amount of vtxos will be offboarded.
92
- * @param eventCallback - The callback to receive settlement events. optional.
111
+ * @param amount - The amount to offboard. If not provided, the total amount of virtual outputs will be offboarded.
112
+ * @param eventCallback - Optional callback that receives settlement events
113
+ * @returns The Arkade transaction id created by settlement
114
+ * @throws Error if no virtual outputs remain after fee deduction or the destination address cannot be decoded
115
+ * @see IWallet.getVtxos
116
+ * @see IWallet.settle
117
+ * @example
118
+ * ```typescript
119
+ * const feeInfo = { intentFee: {}, txFeeRate: '1' };
120
+ * const ramps = new Ramps(wallet);
121
+ * await ramps.offboard('bc1q...', feeInfo);
122
+ * ```
93
123
  */
94
124
  async offboard(destinationAddress, feeInfo, amount, eventCallback) {
95
125
  const vtxos = await this.wallet.getVtxos({
96
126
  withRecoverable: true,
97
127
  withUnrolled: false,
98
128
  });
99
- // Calculate input fees and filter out vtxos where fee >= value
129
+ // Calculate input fees and filter out virtual outputs where fee >= value.
100
130
  const estimator = new Estimator(feeInfo?.intentFee ?? {});
101
131
  const filteredVtxos = [];
102
132
  let totalAmount = 0n;
@@ -113,7 +143,7 @@ export class Ramps {
113
143
  : undefined,
114
144
  });
115
145
  if (inputFee.satoshis >= vtxo.value) {
116
- // skip if fees are greater than or equal to the vtxo value
146
+ // Skip virtual outputs where spending fees are greater than or equal to the output value.
117
147
  continue;
118
148
  }
119
149
  filteredVtxos.push(vtxo);
@@ -49,7 +49,7 @@ export class WalletMessageHandler {
49
49
  this.contractEventsSubscription = undefined;
50
50
  }
51
51
  // Dispose the wallet to stop VtxoManager background tasks
52
- // (auto-renewal, boarding UTXO polling) and ContractWatcher.
52
+ // (auto-renewal, boarding input polling) and ContractWatcher.
53
53
  try {
54
54
  if (this.wallet) {
55
55
  await this.wallet.dispose();
@@ -484,7 +484,7 @@ export class WalletMessageHandler {
484
484
  }
485
485
  const totalBoarding = confirmed + unconfirmed;
486
486
  const totalOffchain = settled + preconfirmed + recoverable;
487
- // aggregate asset balances from spendable vtxos
487
+ // aggregate asset balances from spendable virtual outputs
488
488
  const assetBalances = new Map();
489
489
  for (const vtxo of spendableVtxos) {
490
490
  if (vtxo.assets) {
@@ -529,9 +529,9 @@ export class WalletMessageHandler {
529
529
  return;
530
530
  }
531
531
  // Initialize contract manager FIRST — this populates the repository
532
- // with full VTXO history for all contracts (one indexer call per contract)
532
+ // with full virtual output history for all contracts (one indexer call per contract)
533
533
  await this.ensureContractEventBroadcasting();
534
- // Refresh cached data (VTXOs, boarding UTXOs, tx history)
534
+ // Refresh cached data (virtual outputs, boarding inputs, tx history)
535
535
  await this.refreshCachedData();
536
536
  // Recover pending transactions (init-only, not on reload).
537
537
  // Pending txs only exist if a send was interrupted mid-finalization.
@@ -562,12 +562,12 @@ export class WalletMessageHandler {
562
562
  : [];
563
563
  if ([...newVtxos, ...spentVtxos].length === 0)
564
564
  return;
565
- // save vtxos using unified repository
565
+ // save virtual outputs using unified repository
566
566
  await this.walletRepository?.saveVtxos(address, [
567
567
  ...newVtxos,
568
568
  ...spentVtxos,
569
569
  ]);
570
- // notify all clients about the vtxo update
570
+ // notify all clients about the virtual output state update
571
571
  this.scheduleForNextTick(() => this.tagged({
572
572
  type: "VTXO_UPDATE",
573
573
  broadcast: true,
@@ -577,11 +577,11 @@ export class WalletMessageHandler {
577
577
  if (funds.type === "utxo") {
578
578
  const utxos = funds.coins.map((utxo) => extendCoin(this.readonlyWallet, utxo));
579
579
  const boardingAddress = await this.readonlyWallet.getBoardingAddress();
580
- // save utxos using unified repository
581
- // TODO: remove UTXOS by address
580
+ // save boarding inputs using unified repository
581
+ // TODO: remove UTXOs by address
582
582
  // await this.walletRepository.clearUtxos(boardingAddress);
583
583
  await this.walletRepository?.saveUtxos(boardingAddress, utxos);
584
- // notify all clients about the utxo update
584
+ // notify all clients about the boarding input state update
585
585
  this.scheduleForNextTick(() => this.tagged({
586
586
  type: "UTXO_UPDATE",
587
587
  broadcast: true,
@@ -590,8 +590,8 @@ export class WalletMessageHandler {
590
590
  }
591
591
  });
592
592
  // Eagerly start the VtxoManager so its background tasks (auto-renewal,
593
- // boarding UTXO polling/sweep) run inside the service worker without
594
- // waiting for a client to send a vtxo-manager message first.
593
+ // boarding input polling/sweep) run inside the service worker without
594
+ // waiting for a client to send a VtxoManager message first.
595
595
  if (this.wallet) {
596
596
  try {
597
597
  await this.wallet.getVtxoManager();
@@ -602,7 +602,7 @@ export class WalletMessageHandler {
602
602
  }
603
603
  }
604
604
  /**
605
- * Refresh VTXOs, boarding UTXOs, and transaction history from cache.
605
+ * Refresh virtual outputs, boarding inputs, and transaction history from cache.
606
606
  * Shared by onWalletInitialized (full bootstrap) and reloadWallet
607
607
  * (post-refresh), avoiding duplicate subscriptions and VtxoManager restarts.
608
608
  */
@@ -610,14 +610,14 @@ export class WalletMessageHandler {
610
610
  if (!this.readonlyWallet || !this.walletRepository) {
611
611
  return;
612
612
  }
613
- // Read VTXOs from repository (now populated by contract manager)
613
+ // Read virtual outputs from repository (now populated by contract manager)
614
614
  const vtxos = await this.getVtxosFromRepo();
615
- // Fetch boarding utxos and save using unified repository
615
+ // Fetch boarding inputs and save using unified repository
616
616
  const boardingAddress = await this.readonlyWallet.getBoardingAddress();
617
617
  const coins = await this.readonlyWallet.onchainProvider.getCoins(boardingAddress);
618
618
  await this.walletRepository.deleteUtxos(boardingAddress);
619
619
  await this.walletRepository.saveUtxos(boardingAddress, coins.map((utxo) => extendCoin(this.readonlyWallet, utxo)));
620
- // Build transaction history from cached VTXOs (no indexer call)
620
+ // Build transaction history from cached virtual outputs (no indexer call)
621
621
  const address = await this.readonlyWallet.getAddress();
622
622
  const txs = await this.buildTransactionHistoryFromCache(vtxos);
623
623
  if (txs)
@@ -759,7 +759,7 @@ export class WalletMessageHandler {
759
759
  this.indexerProvider = undefined;
760
760
  }
761
761
  /**
762
- * Read all VTXOs from the repository, aggregated across all contract
762
+ * Read all virtual outputs from the repository, aggregated across all contract
763
763
  * addresses and the wallet's primary address, with deduplication.
764
764
  */
765
765
  async getVtxosFromRepo() {
@@ -776,7 +776,7 @@ export class WalletMessageHandler {
776
776
  }
777
777
  }
778
778
  };
779
- // Aggregate VTXOs from all contract addresses
779
+ // Aggregate virtual outputs from all contract addresses
780
780
  const manager = await this.readonlyWallet.getContractManager();
781
781
  const contracts = await manager.getContracts();
782
782
  for (const contract of contracts) {
@@ -790,15 +790,15 @@ export class WalletMessageHandler {
790
790
  return allVtxos;
791
791
  }
792
792
  /**
793
- * Build transaction history from cached VTXOs without hitting the indexer.
793
+ * Build transaction history from cached virtual outputs without hitting the indexer.
794
794
  * Falls back to indexer only for uncached transaction timestamps.
795
795
  */
796
796
  async buildTransactionHistoryFromCache(vtxos) {
797
797
  if (!this.readonlyWallet)
798
798
  return null;
799
799
  const { boardingTxs, commitmentsToIgnore } = await this.readonlyWallet.getBoardingTxs();
800
- // Build a lookup for cached VTXO timestamps, keyed by txid.
801
- // Multiple VTXOs can share a txid (different vouts) — we keep the
800
+ // Build a lookup for cached virtual output timestamps, keyed by txid.
801
+ // Multiple virtual outputs can share a txid (different vouts) — we keep the
802
802
  // earliest createdAt so the history ordering is stable.
803
803
  const vtxoCreatedAt = new Map();
804
804
  for (const vtxo of vtxos) {
@@ -809,8 +809,8 @@ export class WalletMessageHandler {
809
809
  }
810
810
  }
811
811
  // Pre-fetch uncached timestamps in a single batched indexer call.
812
- // buildTransactionHistory needs these for spent-offchain VTXOs with
813
- // no change outputs (i.e. arkTxId is set but no VTXO has txid === arkTxId).
812
+ // buildTransactionHistory needs these for spent-offchain virtual outputs with
813
+ // no change outputs (i.e. arkTxId is set but no virtual output has txid === arkTxId).
814
814
  if (this.indexerProvider) {
815
815
  const uncachedTxids = new Set();
816
816
  for (const vtxo of vtxos) {