@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.
- package/README.md +102 -96
- package/dist/cjs/arkfee/estimator.js +1 -1
- package/dist/cjs/arkfee/types.js +2 -1
- package/dist/cjs/arknote/index.js +43 -4
- package/dist/cjs/bip322/index.js +1 -1
- package/dist/cjs/contracts/arkcontract.js +1 -1
- package/dist/cjs/contracts/contractManager.js +40 -24
- package/dist/cjs/contracts/contractWatcher.js +29 -22
- package/dist/cjs/contracts/handlers/default.js +1 -1
- package/dist/cjs/contracts/handlers/delegate.js +1 -1
- package/dist/cjs/contracts/handlers/helpers.js +1 -1
- package/dist/cjs/extension/asset/assetGroup.js +92 -5
- package/dist/cjs/extension/asset/assetId.js +67 -3
- package/dist/cjs/extension/asset/assetInput.js +18 -0
- package/dist/cjs/extension/asset/assetOutput.js +15 -0
- package/dist/cjs/extension/asset/assetRef.js +66 -0
- package/dist/cjs/extension/asset/metadata.js +15 -0
- package/dist/cjs/extension/asset/packet.js +4 -1
- package/dist/cjs/extension/index.js +1 -1
- package/dist/cjs/forfeit.js +14 -0
- package/dist/cjs/identity/seedIdentity.js +2 -2
- package/dist/cjs/identity/singleKey.js +4 -0
- package/dist/cjs/intent/index.js +28 -12
- package/dist/cjs/providers/ark.js +3 -2
- package/dist/cjs/providers/delegator.js +20 -1
- package/dist/cjs/providers/expoArk.js +2 -2
- package/dist/cjs/providers/indexer.js +2 -2
- package/dist/cjs/providers/onchain.js +2 -1
- package/dist/cjs/repositories/realm/schemas.js +2 -2
- package/dist/cjs/repositories/realm/types.js +1 -1
- package/dist/cjs/script/address.js +37 -6
- package/dist/cjs/script/base.js +70 -1
- package/dist/cjs/script/default.js +3 -0
- package/dist/cjs/script/delegate.js +4 -0
- package/dist/cjs/script/tapscript.js +17 -2
- package/dist/cjs/script/vhtlc.js +35 -27
- package/dist/cjs/storage/fileSystem.js +1 -1
- package/dist/cjs/storage/inMemory.js +1 -1
- package/dist/cjs/storage/indexedDB.js +1 -1
- package/dist/cjs/storage/localStorage.js +1 -1
- package/dist/cjs/tree/validation.js +1 -1
- package/dist/cjs/utils/arkTransaction.js +5 -5
- package/dist/cjs/utils/bip21.js +16 -3
- package/dist/cjs/utils/syncCursors.js +4 -4
- package/dist/cjs/utils/transaction.js +1 -1
- package/dist/cjs/utils/transactionHistory.js +11 -11
- package/dist/cjs/utils/unknownFields.js +3 -3
- package/dist/cjs/wallet/asset-manager.js +4 -4
- package/dist/cjs/wallet/batch.js +5 -5
- package/dist/cjs/wallet/delegator.js +9 -8
- package/dist/cjs/wallet/expo/background.js +3 -3
- package/dist/cjs/wallet/expo/wallet.js +7 -7
- package/dist/cjs/wallet/index.js +43 -0
- package/dist/cjs/wallet/onchain.js +43 -5
- package/dist/cjs/wallet/ramps.js +44 -14
- package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +22 -22
- package/dist/cjs/wallet/serviceWorker/wallet.js +28 -24
- package/dist/cjs/wallet/unroll.js +12 -8
- package/dist/cjs/wallet/utils.js +1 -1
- package/dist/cjs/wallet/vtxo-manager.js +122 -82
- package/dist/cjs/wallet/wallet.js +125 -67
- package/dist/cjs/worker/expo/asyncStorageTaskQueue.js +1 -1
- package/dist/cjs/worker/expo/processors/contractPollProcessor.js +2 -2
- package/dist/cjs/worker/expo/taskRunner.js +3 -3
- package/dist/cjs/worker/messageBus.js +3 -0
- package/dist/esm/arkfee/estimator.js +1 -1
- package/dist/esm/arkfee/types.js +2 -1
- package/dist/esm/arknote/index.js +43 -4
- package/dist/esm/bip322/index.js +1 -1
- package/dist/esm/contracts/arkcontract.js +1 -1
- package/dist/esm/contracts/contractManager.js +40 -24
- package/dist/esm/contracts/contractWatcher.js +29 -22
- package/dist/esm/contracts/handlers/default.js +1 -1
- package/dist/esm/contracts/handlers/delegate.js +1 -1
- package/dist/esm/contracts/handlers/helpers.js +1 -1
- package/dist/esm/extension/asset/assetGroup.js +92 -5
- package/dist/esm/extension/asset/assetId.js +67 -3
- package/dist/esm/extension/asset/assetInput.js +18 -0
- package/dist/esm/extension/asset/assetOutput.js +15 -0
- package/dist/esm/extension/asset/assetRef.js +66 -0
- package/dist/esm/extension/asset/metadata.js +15 -0
- package/dist/esm/extension/asset/packet.js +4 -1
- package/dist/esm/extension/index.js +1 -1
- package/dist/esm/forfeit.js +14 -0
- package/dist/esm/identity/seedIdentity.js +2 -2
- package/dist/esm/identity/singleKey.js +4 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/intent/index.js +28 -12
- package/dist/esm/providers/ark.js +3 -2
- package/dist/esm/providers/delegator.js +20 -1
- package/dist/esm/providers/expoArk.js +2 -2
- package/dist/esm/providers/indexer.js +2 -2
- package/dist/esm/providers/onchain.js +2 -1
- package/dist/esm/repositories/realm/schemas.js +2 -2
- package/dist/esm/repositories/realm/types.js +1 -1
- package/dist/esm/script/address.js +37 -6
- package/dist/esm/script/base.js +70 -1
- package/dist/esm/script/default.js +3 -0
- package/dist/esm/script/delegate.js +4 -0
- package/dist/esm/script/tapscript.js +17 -2
- package/dist/esm/script/vhtlc.js +35 -27
- package/dist/esm/storage/fileSystem.js +1 -1
- package/dist/esm/storage/inMemory.js +1 -1
- package/dist/esm/storage/indexedDB.js +1 -1
- package/dist/esm/storage/localStorage.js +1 -1
- package/dist/esm/tree/validation.js +1 -1
- package/dist/esm/utils/arkTransaction.js +5 -5
- package/dist/esm/utils/bip21.js +16 -3
- package/dist/esm/utils/syncCursors.js +4 -4
- package/dist/esm/utils/transaction.js +1 -1
- package/dist/esm/utils/transactionHistory.js +11 -11
- package/dist/esm/utils/unknownFields.js +3 -3
- package/dist/esm/wallet/asset-manager.js +4 -4
- package/dist/esm/wallet/batch.js +5 -5
- package/dist/esm/wallet/delegator.js +9 -8
- package/dist/esm/wallet/expo/background.js +3 -3
- package/dist/esm/wallet/expo/wallet.js +7 -7
- package/dist/esm/wallet/index.js +43 -0
- package/dist/esm/wallet/onchain.js +43 -5
- package/dist/esm/wallet/ramps.js +44 -14
- package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +22 -22
- package/dist/esm/wallet/serviceWorker/wallet.js +28 -24
- package/dist/esm/wallet/unroll.js +12 -8
- package/dist/esm/wallet/utils.js +1 -1
- package/dist/esm/wallet/vtxo-manager.js +121 -81
- package/dist/esm/wallet/wallet.js +125 -67
- package/dist/esm/worker/expo/asyncStorageTaskQueue.js +1 -1
- package/dist/esm/worker/expo/processors/contractPollProcessor.js +2 -2
- package/dist/esm/worker/expo/taskRunner.js +3 -3
- package/dist/esm/worker/messageBus.js +3 -0
- package/dist/types/arkfee/estimator.d.ts +1 -1
- package/dist/types/arkfee/types.d.ts +2 -1
- package/dist/types/arknote/index.d.ts +44 -4
- package/dist/types/bip322/index.d.ts +1 -1
- package/dist/types/contracts/arkcontract.d.ts +1 -1
- package/dist/types/contracts/contractManager.d.ts +40 -63
- package/dist/types/contracts/contractWatcher.d.ts +39 -18
- package/dist/types/contracts/handlers/default.d.ts +1 -1
- package/dist/types/contracts/handlers/delegate.d.ts +1 -1
- package/dist/types/contracts/handlers/helpers.d.ts +1 -1
- package/dist/types/contracts/types.d.ts +36 -26
- package/dist/types/extension/asset/assetGroup.d.ts +92 -1
- package/dist/types/extension/asset/assetId.d.ts +67 -3
- package/dist/types/extension/asset/assetInput.d.ts +18 -0
- package/dist/types/extension/asset/assetOutput.d.ts +15 -0
- package/dist/types/extension/asset/assetRef.d.ts +66 -0
- package/dist/types/extension/asset/metadata.d.ts +15 -0
- package/dist/types/extension/asset/packet.d.ts +4 -1
- package/dist/types/extension/index.d.ts +1 -1
- package/dist/types/forfeit.d.ts +14 -0
- package/dist/types/identity/index.d.ts +16 -0
- package/dist/types/identity/seedIdentity.d.ts +8 -6
- package/dist/types/identity/singleKey.d.ts +4 -0
- package/dist/types/intent/index.d.ts +19 -6
- package/dist/types/providers/ark.d.ts +40 -2
- package/dist/types/providers/delegator.d.ts +54 -1
- package/dist/types/providers/expoArk.d.ts +2 -2
- package/dist/types/providers/indexer.d.ts +105 -2
- package/dist/types/providers/onchain.d.ts +62 -1
- package/dist/types/repositories/realm/schemas.d.ts +2 -2
- package/dist/types/repositories/realm/types.d.ts +2 -2
- package/dist/types/repositories/walletRepository.d.ts +16 -0
- package/dist/types/script/address.d.ts +35 -2
- package/dist/types/script/base.d.ts +66 -1
- package/dist/types/script/default.d.ts +3 -0
- package/dist/types/script/delegate.d.ts +4 -0
- package/dist/types/script/tapscript.d.ts +17 -2
- package/dist/types/script/vhtlc.d.ts +35 -27
- package/dist/types/storage/fileSystem.d.ts +1 -1
- package/dist/types/storage/inMemory.d.ts +1 -1
- package/dist/types/storage/index.d.ts +1 -1
- package/dist/types/storage/indexedDB.d.ts +1 -1
- package/dist/types/storage/localStorage.d.ts +1 -1
- package/dist/types/utils/arkTransaction.d.ts +3 -3
- package/dist/types/utils/bip21.d.ts +17 -0
- package/dist/types/utils/syncCursors.d.ts +4 -4
- package/dist/types/utils/transaction.d.ts +1 -1
- package/dist/types/utils/transactionHistory.d.ts +3 -3
- package/dist/types/utils/unknownFields.d.ts +5 -5
- package/dist/types/wallet/asset-manager.d.ts +3 -3
- package/dist/types/wallet/batch.d.ts +27 -7
- package/dist/types/wallet/delegator.d.ts +10 -0
- package/dist/types/wallet/expo/background.d.ts +4 -4
- package/dist/types/wallet/expo/wallet.d.ts +10 -10
- package/dist/types/wallet/index.d.ts +457 -25
- package/dist/types/wallet/onchain.d.ts +42 -4
- package/dist/types/wallet/ramps.d.ts +40 -10
- package/dist/types/wallet/serviceWorker/wallet-message-handler.d.ts +4 -4
- package/dist/types/wallet/serviceWorker/wallet.d.ts +71 -33
- package/dist/types/wallet/unroll.d.ts +8 -6
- package/dist/types/wallet/vtxo-manager.d.ts +146 -93
- package/dist/types/wallet/wallet.d.ts +91 -33
- package/dist/types/worker/expo/asyncStorageTaskQueue.d.ts +1 -1
- package/dist/types/worker/expo/processors/contractPollProcessor.d.ts +1 -1
- package/dist/types/worker/expo/taskRunner.d.ts +6 -6
- package/dist/types/worker/messageBus.d.ts +5 -3
- package/package.json +1 -1
|
@@ -108,12 +108,12 @@ export class ReadonlyWallet {
|
|
|
108
108
|
const serverIsMainnet = info.network === "bitcoin";
|
|
109
109
|
if (identityIsMainnet && !serverIsMainnet) {
|
|
110
110
|
throw new Error(`Network mismatch: identity uses mainnet derivation (coin type 0) ` +
|
|
111
|
-
`but
|
|
111
|
+
`but the Arkade server is on ${info.network}. ` +
|
|
112
112
|
`Create identity with { isMainnet: false } to use testnet derivation.`);
|
|
113
113
|
}
|
|
114
114
|
if (!identityIsMainnet && serverIsMainnet) {
|
|
115
115
|
throw new Error(`Network mismatch: identity uses testnet derivation (coin type 1) ` +
|
|
116
|
-
`but
|
|
116
|
+
`but the Arkade server is on mainnet. ` +
|
|
117
117
|
`Create identity with { isMainnet: true } or omit isMainnet (defaults to mainnet).`);
|
|
118
118
|
}
|
|
119
119
|
}
|
|
@@ -185,6 +185,12 @@ export class ReadonlyWallet {
|
|
|
185
185
|
delegatorProvider: config.delegatorProvider,
|
|
186
186
|
};
|
|
187
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Create a readonly wallet for querying balances, addresses, and history.
|
|
190
|
+
*
|
|
191
|
+
* @param config - Readonly wallet configuration
|
|
192
|
+
* @returns A readonly wallet instance
|
|
193
|
+
*/
|
|
188
194
|
static async create(config) {
|
|
189
195
|
const pubkey = await config.identity.xOnlyPublicKey();
|
|
190
196
|
if (!pubkey) {
|
|
@@ -203,12 +209,17 @@ export class ReadonlyWallet {
|
|
|
203
209
|
get defaultContractScript() {
|
|
204
210
|
return hex.encode(this.offchainTapscript.pkScript);
|
|
205
211
|
}
|
|
212
|
+
/** Returns the wallet's Arkade address. */
|
|
206
213
|
async getAddress() {
|
|
207
214
|
return this.arkAddress.encode();
|
|
208
215
|
}
|
|
216
|
+
/** Returns the onchain boarding address used to move funds into Arkade. */
|
|
209
217
|
async getBoardingAddress() {
|
|
210
218
|
return this.boardingTapscript.onchainAddress(this.network);
|
|
211
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Return the wallet's combined onchain and offchain balances.
|
|
222
|
+
*/
|
|
212
223
|
async getBalance() {
|
|
213
224
|
const [boardingUtxos, vtxos] = await Promise.all([
|
|
214
225
|
this.getBoardingUtxos(),
|
|
@@ -240,7 +251,7 @@ export class ReadonlyWallet {
|
|
|
240
251
|
.reduce((sum, coin) => sum + coin.value, 0);
|
|
241
252
|
const totalBoarding = confirmed + unconfirmed;
|
|
242
253
|
const totalOffchain = settled + preconfirmed + recoverable;
|
|
243
|
-
// aggregate asset balances from spendable
|
|
254
|
+
// aggregate asset balances from spendable virtual outputs
|
|
244
255
|
const assetBalances = new Map();
|
|
245
256
|
for (const vtxo of vtxos) {
|
|
246
257
|
if (!isSpendable(vtxo))
|
|
@@ -270,11 +281,16 @@ export class ReadonlyWallet {
|
|
|
270
281
|
assets,
|
|
271
282
|
};
|
|
272
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Return virtual outputs tracked by the wallet.
|
|
286
|
+
*
|
|
287
|
+
* @param filter - Optional flags controlling whether recoverable or unrolled VTXOs are included
|
|
288
|
+
*/
|
|
273
289
|
async getVtxos(filter) {
|
|
274
290
|
const { isDelta, fetchedExtended, address } = await this.syncVtxos();
|
|
275
291
|
const f = filter ?? { withRecoverable: true, withUnrolled: false };
|
|
276
292
|
// For delta syncs, read the full merged set from cache so old
|
|
277
|
-
//
|
|
293
|
+
// Virtual outputs that weren't in the delta are still returned.
|
|
278
294
|
const vtxos = isDelta
|
|
279
295
|
? await this.walletRepository.getVtxos(address)
|
|
280
296
|
: fetchedExtended;
|
|
@@ -289,8 +305,11 @@ export class ReadonlyWallet {
|
|
|
289
305
|
return !!(f.withUnrolled && vtxo.isUnrolled);
|
|
290
306
|
});
|
|
291
307
|
}
|
|
308
|
+
/**
|
|
309
|
+
* Return wallet transaction history derived from Arkade state and boarding transactions.
|
|
310
|
+
*/
|
|
292
311
|
async getTransactionHistory() {
|
|
293
|
-
// Delta-sync
|
|
312
|
+
// Delta-sync virtual outputs into cache, then build history from the cache.
|
|
294
313
|
const { isDelta, fetchedExtended, address } = await this.syncVtxos();
|
|
295
314
|
const allVtxos = isDelta
|
|
296
315
|
? await this.walletRepository.getVtxos(address)
|
|
@@ -302,7 +321,7 @@ export class ReadonlyWallet {
|
|
|
302
321
|
return buildTransactionHistory(allVtxos, boardingTxs, commitmentsToIgnore, getTxCreatedAt);
|
|
303
322
|
}
|
|
304
323
|
/**
|
|
305
|
-
* Delta-sync wallet
|
|
324
|
+
* Delta-sync wallet virtual outputs: fetch only changed virtual outputs since the last
|
|
306
325
|
* cursor, or do a full bootstrap when no cursor exists. Upserts
|
|
307
326
|
* the result into the cache and advances the sync cursors.
|
|
308
327
|
*
|
|
@@ -375,21 +394,21 @@ export class ReadonlyWallet {
|
|
|
375
394
|
allVtxos.push(...response.vtxos);
|
|
376
395
|
}
|
|
377
396
|
}
|
|
378
|
-
// Extend every fetched
|
|
397
|
+
// Extend every fetched virtual output and upsert into the cache.
|
|
379
398
|
const fetchedExtended = [];
|
|
380
399
|
for (const vtxo of allVtxos) {
|
|
381
400
|
const extended = extendWithScript(vtxo);
|
|
382
401
|
if (extended)
|
|
383
402
|
fetchedExtended.push(extended);
|
|
384
403
|
}
|
|
385
|
-
// Save
|
|
404
|
+
// Save virtual outputs first, then advance cursors only on success.
|
|
386
405
|
const cutoff = cursorCutoff(requestStartedAt);
|
|
387
406
|
await this.walletRepository.saveVtxos(address, fetchedExtended);
|
|
388
407
|
await advanceSyncCursors(this.walletRepository, Object.fromEntries(allScripts.map((s) => [s, cutoff])));
|
|
389
408
|
// Delta-sync reconciliation: full re-fetch for delta scripts.
|
|
390
409
|
//
|
|
391
|
-
// The delta fetch (above) only returns
|
|
392
|
-
// cursor, so it can miss preconfirmed
|
|
410
|
+
// The delta fetch (above) only returns virtual outputs changed after the
|
|
411
|
+
// cursor, so it can miss preconfirmed virtual outputs that were consumed
|
|
393
412
|
// by a round between syncs. Rather than layering targeted
|
|
394
413
|
// queries (pendingOnly, spendableOnly) with pagination guards
|
|
395
414
|
// and set algebra, we perform a single unfiltered re-fetch for
|
|
@@ -397,8 +416,8 @@ export class ReadonlyWallet {
|
|
|
397
416
|
// gives us complete, authoritative state in one call and keeps
|
|
398
417
|
// the reconciliation logic simple.
|
|
399
418
|
//
|
|
400
|
-
// Any cached non-spent
|
|
401
|
-
// result set is marked spent; any
|
|
419
|
+
// Any cached non-spent virtual output that is absent from the full
|
|
420
|
+
// result set is marked spent; any virtual output whose state changed
|
|
402
421
|
// (e.g. preconfirmed → settled) is updated in place.
|
|
403
422
|
if (hasDelta) {
|
|
404
423
|
const { vtxos: fullVtxos, page: fullPage } = await this.indexerProvider.getVtxos({
|
|
@@ -407,7 +426,7 @@ export class ReadonlyWallet {
|
|
|
407
426
|
// Reconciliation is best-effort: if the response is
|
|
408
427
|
// paginated we don't have a complete picture, so we skip
|
|
409
428
|
// rather than act on partial data. Wallets with enough
|
|
410
|
-
//
|
|
429
|
+
// virtual outputs to exceed a single page rely solely on the
|
|
411
430
|
// cursor-based delta mechanism for state updates.
|
|
412
431
|
const fullSetComplete = !fullPage || fullPage.total <= 1;
|
|
413
432
|
if (fullSetComplete) {
|
|
@@ -424,7 +443,7 @@ export class ReadonlyWallet {
|
|
|
424
443
|
const outpoint = `${cached.txid}:${cached.vout}`;
|
|
425
444
|
const fresh = fullOutpoints.get(outpoint);
|
|
426
445
|
if (!fresh) {
|
|
427
|
-
// Server no longer knows about this
|
|
446
|
+
// Server no longer knows about this virtual output —
|
|
428
447
|
// it was spent between syncs.
|
|
429
448
|
reconciledExtended.push({
|
|
430
449
|
...cached,
|
|
@@ -457,12 +476,15 @@ export class ReadonlyWallet {
|
|
|
457
476
|
};
|
|
458
477
|
}
|
|
459
478
|
/**
|
|
460
|
-
* Clear all
|
|
479
|
+
* Clear all virtual output sync cursors, forcing a full re-bootstrap on next sync.
|
|
461
480
|
* Useful for recovery after indexer reprocessing or debugging.
|
|
462
481
|
*/
|
|
463
482
|
async clearSyncCursors() {
|
|
464
483
|
await clearSyncCursors(this.walletRepository);
|
|
465
484
|
}
|
|
485
|
+
/**
|
|
486
|
+
* Build a transaction history view for the wallet's boarding address.
|
|
487
|
+
*/
|
|
466
488
|
async getBoardingTxs() {
|
|
467
489
|
const utxos = [];
|
|
468
490
|
const commitmentsToIgnore = new Set();
|
|
@@ -533,16 +555,25 @@ export class ReadonlyWallet {
|
|
|
533
555
|
commitmentsToIgnore,
|
|
534
556
|
};
|
|
535
557
|
}
|
|
558
|
+
/**
|
|
559
|
+
* Fetch and cache onchain inputs (UTXOs) received at the boarding address.
|
|
560
|
+
*/
|
|
536
561
|
async getBoardingUtxos() {
|
|
537
562
|
const boardingAddress = await this.getBoardingAddress();
|
|
538
563
|
const boardingUtxos = await this.onchainProvider.getCoins(boardingAddress);
|
|
539
564
|
const utxos = boardingUtxos.map((utxo) => {
|
|
540
565
|
return extendCoin(this, utxo);
|
|
541
566
|
});
|
|
542
|
-
// Save
|
|
567
|
+
// Save boarding inputs using unified repository
|
|
543
568
|
await this.walletRepository.saveUtxos(boardingAddress, utxos);
|
|
544
569
|
return utxos;
|
|
545
570
|
}
|
|
571
|
+
/**
|
|
572
|
+
* Subscribe to onchain and offchain notifications for newly received funds.
|
|
573
|
+
*
|
|
574
|
+
* @param eventCallback - Callback invoked when matching funds are detected
|
|
575
|
+
* @returns A function that stops the subscriptions
|
|
576
|
+
*/
|
|
546
577
|
async notifyIncomingFunds(eventCallback) {
|
|
547
578
|
const arkAddress = await this.getAddress();
|
|
548
579
|
const boardingAddress = await this.getBoardingAddress();
|
|
@@ -553,11 +584,11 @@ export class ReadonlyWallet {
|
|
|
553
584
|
return tx.vout.findIndex((v) => v.scriptpubkey_address === boardingAddress);
|
|
554
585
|
};
|
|
555
586
|
onchainStopFunc = await this.onchainProvider.watchAddresses([boardingAddress], (txs) => {
|
|
556
|
-
// find all
|
|
587
|
+
// find all onchain outputs belonging to our boarding address
|
|
557
588
|
const coins = txs
|
|
558
589
|
// filter txs where address is in output
|
|
559
590
|
.filter((tx) => findVoutOnTx(tx) !== -1)
|
|
560
|
-
// return
|
|
591
|
+
// return boarding input as Coin
|
|
561
592
|
.map((tx) => {
|
|
562
593
|
const { txid, status } = tx;
|
|
563
594
|
const vout = findVoutOnTx(tx);
|
|
@@ -582,8 +613,8 @@ export class ReadonlyWallet {
|
|
|
582
613
|
};
|
|
583
614
|
// Handle subscription updates asynchronously without blocking.
|
|
584
615
|
// Note: subscription covers all wallet scripts (default + delegate),
|
|
585
|
-
// but we can't determine which script each
|
|
586
|
-
// subscription event.
|
|
616
|
+
// but we can't determine which script each virtual output belongs to from the
|
|
617
|
+
// subscription event. Virtual outputs are extended with the current offchainTapscript;
|
|
587
618
|
// this is for notification/display only — not for spending.
|
|
588
619
|
// For correct extension metadata, use getVtxos() which queries per-script.
|
|
589
620
|
(async () => {
|
|
@@ -610,8 +641,9 @@ export class ReadonlyWallet {
|
|
|
610
641
|
};
|
|
611
642
|
return stopFunc;
|
|
612
643
|
}
|
|
644
|
+
/** Fetch Arkade transaction ids that are still pending final settlement. */
|
|
613
645
|
async fetchPendingTxs() {
|
|
614
|
-
// get non-swept
|
|
646
|
+
// get non-swept virtual outputs, rely on the indexer only in case DB doesn't have the right state
|
|
615
647
|
const scripts = await this.getWalletScripts();
|
|
616
648
|
let { vtxos } = await this.indexerProvider.getVtxos({
|
|
617
649
|
scripts,
|
|
@@ -652,7 +684,7 @@ export class ReadonlyWallet {
|
|
|
652
684
|
}
|
|
653
685
|
/**
|
|
654
686
|
* Build a map of scriptHex → VtxoScript for all wallet contracts,
|
|
655
|
-
* so
|
|
687
|
+
* so virtual outputs can be extended with the correct tapscript per contract.
|
|
656
688
|
*/
|
|
657
689
|
async getScriptMap() {
|
|
658
690
|
const map = new Map();
|
|
@@ -765,7 +797,7 @@ export class ReadonlyWallet {
|
|
|
765
797
|
address: await this.getAddress(),
|
|
766
798
|
state: "active",
|
|
767
799
|
});
|
|
768
|
-
// Also register the non-delegate version so old
|
|
800
|
+
// Also register the non-delegate version so old virtual outputs remain visible
|
|
769
801
|
const nonDelegateScript = new DefaultVtxo.Script({
|
|
770
802
|
pubKey: delegateScript.options.pubKey,
|
|
771
803
|
serverPubKey: delegateScript.options.serverPubKey,
|
|
@@ -803,6 +835,7 @@ export class ReadonlyWallet {
|
|
|
803
835
|
}
|
|
804
836
|
return manager;
|
|
805
837
|
}
|
|
838
|
+
/** Dispose wallet-owned managers and release background resources. */
|
|
806
839
|
async dispose() {
|
|
807
840
|
const manager = this._contractManager ??
|
|
808
841
|
(this._contractManagerInitializing
|
|
@@ -812,29 +845,30 @@ export class ReadonlyWallet {
|
|
|
812
845
|
this._contractManager = undefined;
|
|
813
846
|
this._contractManagerInitializing = undefined;
|
|
814
847
|
}
|
|
848
|
+
/** Async-dispose hook that forwards to `dispose()`. */
|
|
815
849
|
async [Symbol.asyncDispose]() {
|
|
816
850
|
await this.dispose();
|
|
817
851
|
}
|
|
818
852
|
}
|
|
819
853
|
/**
|
|
820
|
-
* Main wallet implementation for Bitcoin transactions with
|
|
821
|
-
* The wallet does not store any data locally and relies on
|
|
822
|
-
* providers to fetch
|
|
854
|
+
* Main wallet implementation for Bitcoin transactions with Arkade protocol support.
|
|
855
|
+
* The wallet does not store any data locally and relies on Arkade and onchain
|
|
856
|
+
* providers to fetch onchain and virtual outputs.
|
|
823
857
|
*
|
|
824
858
|
* @example
|
|
825
859
|
* ```typescript
|
|
826
860
|
* // Create a wallet with URL configuration
|
|
827
861
|
* const wallet = await Wallet.create({
|
|
828
|
-
* identity:
|
|
829
|
-
* arkServerUrl: 'https://
|
|
862
|
+
* identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
|
|
863
|
+
* arkServerUrl: 'https://arkade.computer',
|
|
830
864
|
* esploraUrl: 'https://mempool.space/api'
|
|
831
865
|
* });
|
|
832
866
|
*
|
|
833
867
|
* // Or with custom provider instances (e.g., for Expo/React Native)
|
|
834
868
|
* const wallet = await Wallet.create({
|
|
835
|
-
* identity:
|
|
836
|
-
* arkProvider: new ExpoArkProvider('https://
|
|
837
|
-
* indexerProvider: new ExpoIndexerProvider('https://
|
|
869
|
+
* identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
|
|
870
|
+
* arkProvider: new ExpoArkProvider('https://arkade.computer'),
|
|
871
|
+
* indexerProvider: new ExpoIndexerProvider('https://arkade.computer'),
|
|
838
872
|
* esploraUrl: 'https://mempool.space/api'
|
|
839
873
|
* });
|
|
840
874
|
*
|
|
@@ -843,9 +877,9 @@ export class ReadonlyWallet {
|
|
|
843
877
|
* const boardingAddress = await wallet.getBoardingAddress();
|
|
844
878
|
*
|
|
845
879
|
* // Send bitcoin
|
|
846
|
-
* const txid = await wallet.
|
|
847
|
-
* address: '
|
|
848
|
-
* amount: 50000
|
|
880
|
+
* const txid = await wallet.send({
|
|
881
|
+
* address: 'ark1q...',
|
|
882
|
+
* amount: 50000,
|
|
849
883
|
* });
|
|
850
884
|
* ```
|
|
851
885
|
*/
|
|
@@ -874,7 +908,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
874
908
|
this.forfeitOutputScript = forfeitOutputScript;
|
|
875
909
|
this.forfeitPubkey = forfeitPubkey;
|
|
876
910
|
/**
|
|
877
|
-
* Async mutex that serializes all operations submitting VTXOs to the
|
|
911
|
+
* Async mutex that serializes all operations submitting VTXOs to the Arkade
|
|
878
912
|
* server (`settle`, `send`, `sendBitcoin`). This prevents VtxoManager's
|
|
879
913
|
* background renewal from racing with user-initiated transactions for the
|
|
880
914
|
* same VTXO inputs.
|
|
@@ -954,6 +988,19 @@ export class Wallet extends ReadonlyWallet {
|
|
|
954
988
|
await super.dispose();
|
|
955
989
|
}
|
|
956
990
|
}
|
|
991
|
+
/**
|
|
992
|
+
* Create a full wallet and initialize its background managers.
|
|
993
|
+
*
|
|
994
|
+
* @param config - Wallet configuration
|
|
995
|
+
* @returns A wallet ready to query balances and send transactions
|
|
996
|
+
* @example
|
|
997
|
+
* ```typescript
|
|
998
|
+
* const wallet = await Wallet.create({
|
|
999
|
+
* identity,
|
|
1000
|
+
* arkServerUrl: 'https://arkade.computer',
|
|
1001
|
+
* });
|
|
1002
|
+
* ```
|
|
1003
|
+
*/
|
|
957
1004
|
static async create(config) {
|
|
958
1005
|
const pubkey = await config.identity.xOnlyPublicKey();
|
|
959
1006
|
if (!pubkey) {
|
|
@@ -985,7 +1032,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
985
1032
|
* @returns A readonly wallet with the same configuration but readonly identity
|
|
986
1033
|
* @example
|
|
987
1034
|
* ```typescript
|
|
988
|
-
* const wallet = await Wallet.create({ identity:
|
|
1035
|
+
* const wallet = await Wallet.create({ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'), ... });
|
|
989
1036
|
* const readonlyWallet = await wallet.toReadonly();
|
|
990
1037
|
*
|
|
991
1038
|
* // Can query balance and addresses
|
|
@@ -993,7 +1040,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
993
1040
|
* const address = await readonlyWallet.getAddress();
|
|
994
1041
|
*
|
|
995
1042
|
* // But cannot send transactions (type error)
|
|
996
|
-
* // readonlyWallet.
|
|
1043
|
+
* // readonlyWallet.send(...); // TypeScript error
|
|
997
1044
|
* ```
|
|
998
1045
|
*/
|
|
999
1046
|
async toReadonly() {
|
|
@@ -1003,19 +1050,22 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1003
1050
|
: this.identity; // Identity extends ReadonlyIdentity, so this is safe
|
|
1004
1051
|
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);
|
|
1005
1052
|
}
|
|
1053
|
+
/** Returns the delegator manager when delegation support is configured. */
|
|
1006
1054
|
async getDelegatorManager() {
|
|
1007
1055
|
return this._delegatorManager;
|
|
1008
1056
|
}
|
|
1009
1057
|
/**
|
|
1010
|
-
*
|
|
1011
|
-
*
|
|
1058
|
+
* Send bitcoin to an Arkade address.
|
|
1059
|
+
*
|
|
1060
|
+
* @deprecated Use `send`.
|
|
1061
|
+
* @param params - Send parameters
|
|
1012
1062
|
*/
|
|
1013
1063
|
async sendBitcoin(params) {
|
|
1014
1064
|
if (params.amount <= 0) {
|
|
1015
1065
|
throw new Error("Amount must be positive");
|
|
1016
1066
|
}
|
|
1017
1067
|
if (!isValidArkAddress(params.address)) {
|
|
1018
|
-
throw new Error("Invalid
|
|
1068
|
+
throw new Error("Invalid Arkade address " + params.address);
|
|
1019
1069
|
}
|
|
1020
1070
|
if (params.selectedVtxos && params.selectedVtxos.length > 0) {
|
|
1021
1071
|
return this._withTxLock(async () => {
|
|
@@ -1060,6 +1110,13 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1060
1110
|
amount: params.amount,
|
|
1061
1111
|
});
|
|
1062
1112
|
}
|
|
1113
|
+
/**
|
|
1114
|
+
* Settle boarding inputs and/or virtual outputs into a finalized mainnet transaction.
|
|
1115
|
+
*
|
|
1116
|
+
* @param params - Optional settlement inputs and outputs. When omitted, the wallet settles all eligible funds.
|
|
1117
|
+
* @param eventCallback - Optional callback invoked for settlement stream events.
|
|
1118
|
+
* @returns The finalized Arkade transaction id
|
|
1119
|
+
*/
|
|
1063
1120
|
async settle(params, eventCallback) {
|
|
1064
1121
|
return this._withTxLock(() => this._settleImpl(params, eventCallback));
|
|
1065
1122
|
}
|
|
@@ -1077,7 +1134,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1077
1134
|
}
|
|
1078
1135
|
}
|
|
1079
1136
|
}
|
|
1080
|
-
// if no params are provided, use all non
|
|
1137
|
+
// if no params are provided, use all non-expired boarding inputs and offchain virtual outputs as inputs
|
|
1081
1138
|
// and send all to the offchain address
|
|
1082
1139
|
if (!params) {
|
|
1083
1140
|
const { fees } = await this.arkProvider.getInfo();
|
|
@@ -1098,7 +1155,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1098
1155
|
amount: BigInt(utxo.value),
|
|
1099
1156
|
});
|
|
1100
1157
|
if (inputFee.value >= utxo.value) {
|
|
1101
|
-
// skip if fees are greater than the
|
|
1158
|
+
// skip if fees are greater than the boarding input value
|
|
1102
1159
|
continue;
|
|
1103
1160
|
}
|
|
1104
1161
|
filteredBoardingUtxos.push(utxo);
|
|
@@ -1119,7 +1176,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1119
1176
|
: new Date(),
|
|
1120
1177
|
});
|
|
1121
1178
|
if (inputFee.value >= vtxo.value) {
|
|
1122
|
-
// skip if fees are greater than the
|
|
1179
|
+
// skip if fees are greater than the virtual output value
|
|
1123
1180
|
continue;
|
|
1124
1181
|
}
|
|
1125
1182
|
filteredVtxos.push(vtxo);
|
|
@@ -1210,7 +1267,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1210
1267
|
const assetPacket = createAssetPacket(assetInputs, recipients);
|
|
1211
1268
|
outputs.push(Extension.create([assetPacket]).txOut());
|
|
1212
1269
|
}
|
|
1213
|
-
// session holds the state of the musig2 signing process of the
|
|
1270
|
+
// session holds the state of the musig2 signing process of the virtual output tree
|
|
1214
1271
|
let session;
|
|
1215
1272
|
const signingPublicKeys = [];
|
|
1216
1273
|
if (hasOffchainOutputs) {
|
|
@@ -1261,7 +1318,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1261
1318
|
for (const input of inputs) {
|
|
1262
1319
|
// check if the input is an offchain "virtual" coin
|
|
1263
1320
|
const vtxo = vtxos.find((vtxo) => vtxo.txid === input.txid && vtxo.vout === input.vout);
|
|
1264
|
-
// boarding
|
|
1321
|
+
// boarding input, we need to sign the settlement tx
|
|
1265
1322
|
if (!vtxo) {
|
|
1266
1323
|
for (let i = 0; i < settlementPsbt.inputsLength; i++) {
|
|
1267
1324
|
const settlementInput = settlementPsbt.getInput(i);
|
|
@@ -1339,11 +1396,12 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1339
1396
|
}
|
|
1340
1397
|
}
|
|
1341
1398
|
/**
|
|
1342
|
-
*
|
|
1399
|
+
* Create a batch event handler for settlement flows.
|
|
1400
|
+
*
|
|
1343
1401
|
* @param intentId - The intent ID.
|
|
1344
|
-
* @param inputs -
|
|
1345
|
-
* @param
|
|
1346
|
-
* @param
|
|
1402
|
+
* @param inputs - Inputs used by the intent.
|
|
1403
|
+
* @param expectedRecipients - Expected recipients to validate in the virtual output tree.
|
|
1404
|
+
* @param session - Optional musig2 signing session. When omitted, signing steps are skipped.
|
|
1347
1405
|
*/
|
|
1348
1406
|
createBatchHandler(intentId, inputs, expectedRecipients, session) {
|
|
1349
1407
|
let sweepTapTreeRoot;
|
|
@@ -1357,7 +1415,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1357
1415
|
for (const idHash of event.intentIdHashes) {
|
|
1358
1416
|
if (idHash === intentIdHashStr) {
|
|
1359
1417
|
if (!this.arkProvider) {
|
|
1360
|
-
throw new Error("
|
|
1418
|
+
throw new Error("Arkade provider not configured");
|
|
1361
1419
|
}
|
|
1362
1420
|
await this.arkProvider.confirmRegistration(intentId);
|
|
1363
1421
|
skip = false;
|
|
@@ -1390,10 +1448,10 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1390
1448
|
// not a cosigner, skip the signing
|
|
1391
1449
|
return { skip: true };
|
|
1392
1450
|
}
|
|
1393
|
-
// validate the unsigned
|
|
1451
|
+
// validate the unsigned virtual output tree
|
|
1394
1452
|
const commitmentTx = Transaction.fromPSBT(base64.decode(event.unsignedCommitmentTx));
|
|
1395
1453
|
validateVtxoTxGraph(vtxoTree, commitmentTx, sweepTapTreeRoot);
|
|
1396
|
-
// validate that all expected receivers are in the
|
|
1454
|
+
// validate that all expected receivers are in the virtual output tree with correct amounts and assets
|
|
1397
1455
|
if (expectedRecipients && expectedRecipients.length > 0) {
|
|
1398
1456
|
validateBatchRecipients(commitmentTx, vtxoTree.leaves(), expectedRecipients, this.network);
|
|
1399
1457
|
}
|
|
@@ -1494,7 +1552,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1494
1552
|
/**
|
|
1495
1553
|
* Finalizes pending transactions by retrieving them from the server and finalizing each one.
|
|
1496
1554
|
* Skips the server check entirely when no send was interrupted (no pending tx flag set).
|
|
1497
|
-
* @param vtxos - Optional list of
|
|
1555
|
+
* @param vtxos - Optional list of virtual outputs to use instead of retrieving them from the server
|
|
1498
1556
|
* @returns Array of transaction IDs that were finalized
|
|
1499
1557
|
*/
|
|
1500
1558
|
async finalizePendingTxs(vtxos) {
|
|
@@ -1593,13 +1651,13 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1593
1651
|
/**
|
|
1594
1652
|
* Send BTC and/or assets to one or more recipients.
|
|
1595
1653
|
*
|
|
1596
|
-
* @param
|
|
1597
|
-
* @returns Promise resolving to the
|
|
1654
|
+
* @param args - Recipients with their addresses, BTC amounts, and assets
|
|
1655
|
+
* @returns Promise resolving to the Arkade transaction ID
|
|
1598
1656
|
*
|
|
1599
1657
|
* @example
|
|
1600
1658
|
* ```typescript
|
|
1601
1659
|
* const txid = await wallet.send({
|
|
1602
|
-
* address: '
|
|
1660
|
+
* address: 'ark1q...',
|
|
1603
1661
|
* amount: 1000, // (optional, default to dust) btc amount to send to the output
|
|
1604
1662
|
* assets: [{ assetId: 'abc123...', amount: 50 }] // (optional) list of assets to send
|
|
1605
1663
|
* });
|
|
@@ -1747,8 +1805,8 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1747
1805
|
}
|
|
1748
1806
|
/**
|
|
1749
1807
|
* Build an offchain transaction from the given inputs and outputs,
|
|
1750
|
-
* sign it, submit to the
|
|
1751
|
-
* @returns The
|
|
1808
|
+
* sign it, submit to the Arkade provider, and finalize.
|
|
1809
|
+
* @returns The Arkade transaction id and server-signed checkpoint PSBTs (for bookkeeping)
|
|
1752
1810
|
*/
|
|
1753
1811
|
async buildAndSubmitOffchainTx(inputs, outputs) {
|
|
1754
1812
|
const offchainTx = buildOffchainTx(inputs.map((input) => {
|
|
@@ -1807,7 +1865,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1807
1865
|
}
|
|
1808
1866
|
return { arkTxid, signedCheckpointTxs };
|
|
1809
1867
|
}
|
|
1810
|
-
// mark
|
|
1868
|
+
// mark virtual outputs as spent, save change outputs if any
|
|
1811
1869
|
async updateDbAfterOffchainTx(inputs, arkTxid, signedCheckpointTxs, sentAmount, changeAmount, changeVout, changeAssets) {
|
|
1812
1870
|
try {
|
|
1813
1871
|
const spentVtxos = [];
|
|
@@ -1855,7 +1913,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1855
1913
|
}
|
|
1856
1914
|
const createdAt = Date.now();
|
|
1857
1915
|
const addr = this.arkAddress.encode();
|
|
1858
|
-
// Only save a change
|
|
1916
|
+
// Only save a change virtual output for preconfirmed coins (those with a batchExpiry).
|
|
1859
1917
|
// Inputs without a batchExpiry are already settled/unrolled and don't need tracking.
|
|
1860
1918
|
let changeVtxo;
|
|
1861
1919
|
if (changeAmount > 0n && batchExpiry !== Number.MAX_SAFE_INTEGER) {
|
|
@@ -1899,7 +1957,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1899
1957
|
console.warn("error saving offchain tx to repository", e);
|
|
1900
1958
|
}
|
|
1901
1959
|
}
|
|
1902
|
-
// mark
|
|
1960
|
+
// mark virtual outputs as spent/settled, remove boarding inputs
|
|
1903
1961
|
async updateDbAfterSettle(inputs, commitmentTxid) {
|
|
1904
1962
|
try {
|
|
1905
1963
|
const addr = this.arkAddress.encode();
|
|
@@ -1910,7 +1968,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1910
1968
|
const isVtxo = (input) => "virtualStatus" in input;
|
|
1911
1969
|
for (const input of inputs) {
|
|
1912
1970
|
if (isVtxo(input)) {
|
|
1913
|
-
//
|
|
1971
|
+
// virtual output = mark it settled
|
|
1914
1972
|
const vtxo = extendVirtualCoin(this, input);
|
|
1915
1973
|
if (vtxo.arkTxId) {
|
|
1916
1974
|
inputArkTxIds.add(vtxo.arkTxId);
|
|
@@ -1926,7 +1984,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1926
1984
|
});
|
|
1927
1985
|
}
|
|
1928
1986
|
else {
|
|
1929
|
-
// boarding
|
|
1987
|
+
// boarding input = remove it
|
|
1930
1988
|
boardingUtxoToRemove.add(`${input.txid}:${input.vout}`);
|
|
1931
1989
|
}
|
|
1932
1990
|
}
|
|
@@ -1950,13 +2008,13 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1950
2008
|
}
|
|
1951
2009
|
Wallet.MIN_FEE_RATE = 1; // sats/vbyte
|
|
1952
2010
|
/**
|
|
1953
|
-
* Select virtual
|
|
1954
|
-
* @param coins List of virtual
|
|
2011
|
+
* Select virtual outputs to reach a target amount, prioritizing those closer to expiry
|
|
2012
|
+
* @param coins List of virtual outputs to select from
|
|
1955
2013
|
* @param targetAmount Target amount to reach in satoshis
|
|
1956
|
-
* @returns Selected
|
|
2014
|
+
* @returns Selected virtual outputs and change amount
|
|
1957
2015
|
*/
|
|
1958
2016
|
export function selectVirtualCoins(coins, targetAmount) {
|
|
1959
|
-
// Sort
|
|
2017
|
+
// Sort virtual outputs by expiry (ascending) and amount (descending)
|
|
1960
2018
|
const sortedCoins = [...coins].sort((a, b) => {
|
|
1961
2019
|
// First sort by expiry if available
|
|
1962
2020
|
const expiryA = a.virtualStatus.batchExpiry || Number.MAX_SAFE_INTEGER;
|
|
@@ -49,7 +49,7 @@ export class AsyncStorageTaskQueue {
|
|
|
49
49
|
// ── Config persistence (for background handler rehydration) ──────
|
|
50
50
|
/**
|
|
51
51
|
* Persist a config blob alongside the queue data.
|
|
52
|
-
* Used by
|
|
52
|
+
* Used by @see ExpoWallet.setup to store the wallet parameters
|
|
53
53
|
* that the background handler needs to reconstruct providers.
|
|
54
54
|
*/
|
|
55
55
|
async persistConfig(config) {
|
|
@@ -3,7 +3,7 @@ export const CONTRACT_POLL_TASK_TYPE = "contract-poll";
|
|
|
3
3
|
* Polls the indexer for the latest VTXO state of every contract and
|
|
4
4
|
* persists the results to the wallet repository.
|
|
5
5
|
*
|
|
6
|
-
* Replicates the polling subset of
|
|
6
|
+
* Replicates the polling subset of @see ContractManager.initialize:
|
|
7
7
|
* 1. Load all contracts from the contract repository.
|
|
8
8
|
* 2. Mark expired active contracts as inactive.
|
|
9
9
|
* 3. Paginated fetch of spendable VTXOs from the indexer.
|
|
@@ -26,7 +26,7 @@ export const contractPollProcessor = {
|
|
|
26
26
|
contract.state = "inactive";
|
|
27
27
|
await contractRepository.saveContract(contract);
|
|
28
28
|
}
|
|
29
|
-
// Paginated fetch of spendable
|
|
29
|
+
// Paginated fetch of spendable virtual outputs
|
|
30
30
|
const pageSize = 100;
|
|
31
31
|
let pageIndex = 0;
|
|
32
32
|
let hasMore = true;
|
|
@@ -4,7 +4,7 @@ import { getRandomId, extendVirtualCoin, extendVtxoFromContract, } from '../../w
|
|
|
4
4
|
*
|
|
5
5
|
* For each task in the inbox:
|
|
6
6
|
* 1. Find the processor whose `taskType` matches `task.type`.
|
|
7
|
-
* 2. Execute it, producing a
|
|
7
|
+
* 2. Execute it, producing a @see TaskResult.
|
|
8
8
|
* 3. Push the result to the outbox and remove the task from the inbox.
|
|
9
9
|
*
|
|
10
10
|
* Tasks with no matching processor produce a `"noop"` result.
|
|
@@ -53,8 +53,8 @@ export async function runTasks(queue, processors, deps) {
|
|
|
53
53
|
return results;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* Build the
|
|
57
|
-
* (e.g.
|
|
56
|
+
* Build the @see TaskDependencies needed by task processors
|
|
57
|
+
* (e.g. `src/worker/expo/processors/contractPollProcessor.ts`)
|
|
58
58
|
*
|
|
59
59
|
* This is the same construction that `defineExpoBackgroundTask` does
|
|
60
60
|
* internally, extracted so that consumers with custom schedulers
|
|
@@ -7,6 +7,7 @@ import { ReadonlyWallet, Wallet } from '../wallet/wallet.js';
|
|
|
7
7
|
import { hex } from "@scure/base";
|
|
8
8
|
import { MessageBusNotInitializedError, ServiceWorkerTimeoutError, } from './errors.js';
|
|
9
9
|
export class MessageBus {
|
|
10
|
+
/** Create the service-worker message bus with repositories and handler configuration. */
|
|
10
11
|
constructor(walletRepository, contractRepository, { messageHandlers, tickIntervalMs = 10000, messageTimeoutMs = 30000, debug = false, buildServices, }) {
|
|
11
12
|
this.walletRepository = walletRepository;
|
|
12
13
|
this.contractRepository = contractRepository;
|
|
@@ -22,6 +23,7 @@ export class MessageBus {
|
|
|
22
23
|
this.debug = debug;
|
|
23
24
|
this.buildServicesFn = buildServices ?? this.buildServices.bind(this);
|
|
24
25
|
}
|
|
26
|
+
/** Start the message bus and attach service-worker event listeners. */
|
|
25
27
|
async start() {
|
|
26
28
|
if (this.running)
|
|
27
29
|
return;
|
|
@@ -42,6 +44,7 @@ export class MessageBus {
|
|
|
42
44
|
}
|
|
43
45
|
});
|
|
44
46
|
}
|
|
47
|
+
/** Stop the message bus, cancel ticks, and stop all registered handlers. */
|
|
45
48
|
async stop() {
|
|
46
49
|
if (this.debug)
|
|
47
50
|
console.log("MessageBus stopping");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IntentFeeConfig, OffchainInput, OnchainInput, FeeOutput, FeeAmount } from "./types.js";
|
|
2
2
|
/**
|
|
3
|
-
* Estimator evaluates CEL expressions to calculate fees for
|
|
3
|
+
* Estimator evaluates CEL expressions to calculate fees for Arkade intents
|
|
4
4
|
*/
|
|
5
5
|
export declare class Estimator {
|
|
6
6
|
readonly config: IntentFeeConfig;
|