@arkade-os/sdk 0.4.24 → 0.4.26
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/dist/cjs/contracts/contractManager.js +44 -8
- package/dist/cjs/contracts/contractWatcher.js +2 -2
- package/dist/cjs/contracts/vtxoOwnership.js +18 -0
- package/dist/cjs/repositories/inMemory/walletRepository.js +35 -0
- package/dist/cjs/repositories/indexedDB/walletRepository.js +117 -0
- package/dist/cjs/repositories/realm/walletRepository.js +28 -0
- package/dist/cjs/repositories/sqlite/walletRepository.js +23 -0
- package/dist/cjs/script/address.js +2 -2
- package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +14 -3
- package/dist/cjs/wallet/serviceWorker/wallet.js +10 -0
- package/dist/cjs/wallet/vtxo-manager.js +112 -16
- package/dist/cjs/wallet/wallet.js +3 -17
- package/dist/cjs/worker/expo/processors/contractPollProcessor.js +1 -1
- package/dist/esm/adapters/asyncStorage.js +1 -1
- package/dist/esm/adapters/expo.js +2 -2
- package/dist/esm/adapters/fileSystem.js +1 -1
- package/dist/esm/adapters/indexedDB.js +1 -1
- package/dist/esm/adapters/localStorage.js +1 -1
- package/dist/esm/arkfee/index.js +1 -1
- package/dist/esm/arknote/index.js +1 -1
- package/dist/esm/bip322/index.js +2 -2
- package/dist/esm/contracts/arkcontract.js +2 -2
- package/dist/esm/contracts/contractManager.js +49 -13
- package/dist/esm/contracts/contractWatcher.js +5 -5
- package/dist/esm/contracts/handlers/default.js +4 -4
- package/dist/esm/contracts/handlers/delegate.js +4 -4
- package/dist/esm/contracts/handlers/helpers.js +2 -2
- package/dist/esm/contracts/handlers/index.js +8 -8
- package/dist/esm/contracts/handlers/vhtlc.js +3 -3
- package/dist/esm/contracts/index.js +8 -8
- package/dist/esm/contracts/vtxoOwnership.js +16 -0
- package/dist/esm/extension/asset/assetGroup.js +7 -7
- package/dist/esm/extension/asset/assetId.js +2 -2
- package/dist/esm/extension/asset/assetInput.js +2 -2
- package/dist/esm/extension/asset/assetOutput.js +1 -1
- package/dist/esm/extension/asset/assetRef.js +3 -3
- package/dist/esm/extension/asset/index.js +8 -8
- package/dist/esm/extension/asset/metadata.js +1 -1
- package/dist/esm/extension/asset/packet.js +3 -3
- package/dist/esm/extension/index.js +4 -4
- package/dist/esm/forfeit.js +2 -2
- package/dist/esm/identity/index.js +5 -5
- package/dist/esm/identity/seedIdentity.js +2 -2
- package/dist/esm/identity/serialize.js +2 -2
- package/dist/esm/identity/singleKey.js +1 -1
- package/dist/esm/identity/staticDescriptorProvider.js +2 -2
- package/dist/esm/index.js +47 -47
- package/dist/esm/intent/index.js +3 -3
- package/dist/esm/musig2/index.js +3 -3
- package/dist/esm/musig2/sign.js +1 -1
- package/dist/esm/providers/ark.js +3 -3
- package/dist/esm/providers/delegator.js +1 -1
- package/dist/esm/providers/electrum.js +2 -2
- package/dist/esm/providers/expoArk.js +2 -2
- package/dist/esm/providers/expoIndexer.js +3 -3
- package/dist/esm/providers/indexer.js +3 -3
- package/dist/esm/repositories/inMemory/walletRepository.js +35 -0
- package/dist/esm/repositories/index.js +9 -9
- package/dist/esm/repositories/indexedDB/contractRepository.js +4 -4
- package/dist/esm/repositories/indexedDB/db.js +2 -2
- package/dist/esm/repositories/indexedDB/schema.js +1 -1
- package/dist/esm/repositories/indexedDB/walletRepository.js +122 -5
- package/dist/esm/repositories/migrations/fromStorageAdapter.js +1 -1
- package/dist/esm/repositories/migrations/walletRepositoryImpl.js +1 -1
- package/dist/esm/repositories/realm/index.js +3 -3
- package/dist/esm/repositories/realm/schemas.js +1 -1
- package/dist/esm/repositories/realm/walletRepository.js +30 -2
- package/dist/esm/repositories/scriptFromAddress.js +1 -1
- package/dist/esm/repositories/sqlite/index.js +2 -2
- package/dist/esm/repositories/sqlite/walletRepository.js +25 -2
- package/dist/esm/script/address.js +3 -3
- package/dist/esm/script/base.js +3 -3
- package/dist/esm/script/default.js +2 -2
- package/dist/esm/script/delegate.js +3 -3
- package/dist/esm/script/tapscript.js +1 -1
- package/dist/esm/script/vhtlc.js +2 -2
- package/dist/esm/storage/indexedDB.js +1 -1
- package/dist/esm/tree/signingSession.js +2 -2
- package/dist/esm/tree/validation.js +2 -2
- package/dist/esm/utils/arkTransaction.js +7 -7
- package/dist/esm/utils/transactionHistory.js +1 -1
- package/dist/esm/utils/unknownFields.js +1 -1
- package/dist/esm/wallet/asset-manager.js +5 -5
- package/dist/esm/wallet/asset.js +1 -1
- package/dist/esm/wallet/batch.js +2 -2
- package/dist/esm/wallet/delegator.js +6 -6
- package/dist/esm/wallet/expo/background.js +5 -5
- package/dist/esm/wallet/expo/index.js +2 -2
- package/dist/esm/wallet/expo/wallet.js +8 -8
- package/dist/esm/wallet/hdDescriptorProvider.js +2 -2
- package/dist/esm/wallet/onchain.js +7 -7
- package/dist/esm/wallet/ramps.js +3 -3
- package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +20 -9
- package/dist/esm/wallet/serviceWorker/wallet.js +17 -7
- package/dist/esm/wallet/unroll.js +7 -7
- package/dist/esm/wallet/utils.js +2 -2
- package/dist/esm/wallet/validation.js +2 -2
- package/dist/esm/wallet/vtxo-manager.js +120 -24
- package/dist/esm/wallet/wallet.js +36 -50
- package/dist/esm/worker/expo/index.js +4 -4
- package/dist/esm/worker/expo/processors/contractPollProcessor.js +2 -2
- package/dist/esm/worker/expo/processors/index.js +1 -1
- package/dist/esm/worker/expo/taskRunner.js +1 -1
- package/dist/esm/worker/messageBus.js +6 -6
- package/dist/types/adapters/asyncStorage.d.ts +2 -2
- package/dist/types/adapters/expo.d.ts +4 -4
- package/dist/types/adapters/fileSystem.d.ts +2 -2
- package/dist/types/adapters/indexedDB.d.ts +2 -2
- package/dist/types/adapters/localStorage.d.ts +2 -2
- package/dist/types/arkfee/index.d.ts +2 -2
- package/dist/types/arknote/index.d.ts +2 -2
- 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 +22 -6
- package/dist/types/contracts/contractWatcher.d.ts +3 -3
- package/dist/types/contracts/handlers/default.d.ts +3 -3
- package/dist/types/contracts/handlers/delegate.d.ts +3 -3
- package/dist/types/contracts/handlers/helpers.d.ts +1 -1
- package/dist/types/contracts/handlers/index.d.ts +7 -7
- package/dist/types/contracts/handlers/registry.d.ts +1 -1
- package/dist/types/contracts/handlers/vhtlc.d.ts +3 -3
- package/dist/types/contracts/index.d.ts +14 -14
- package/dist/types/contracts/types.d.ts +3 -3
- package/dist/types/contracts/vtxoOwnership.d.ts +9 -1
- package/dist/types/extension/asset/assetGroup.d.ts +6 -6
- package/dist/types/extension/asset/assetId.d.ts +1 -1
- package/dist/types/extension/asset/assetInput.d.ts +2 -2
- package/dist/types/extension/asset/assetOutput.d.ts +1 -1
- package/dist/types/extension/asset/assetRef.d.ts +3 -3
- package/dist/types/extension/asset/index.d.ts +8 -8
- package/dist/types/extension/asset/metadata.d.ts +1 -1
- package/dist/types/extension/asset/packet.d.ts +2 -2
- package/dist/types/extension/index.d.ts +6 -6
- package/dist/types/forfeit.d.ts +1 -1
- package/dist/types/identity/descriptorProvider.d.ts +1 -1
- package/dist/types/identity/hdCapableIdentity.d.ts +3 -3
- package/dist/types/identity/index.d.ts +11 -11
- package/dist/types/identity/seedIdentity.d.ts +5 -5
- package/dist/types/identity/serialize.d.ts +1 -1
- package/dist/types/identity/singleKey.d.ts +3 -3
- package/dist/types/identity/staticDescriptorProvider.d.ts +3 -3
- package/dist/types/index.d.ts +57 -57
- package/dist/types/intent/index.d.ts +2 -2
- package/dist/types/musig2/index.d.ts +4 -4
- package/dist/types/providers/ark.d.ts +5 -5
- package/dist/types/providers/delegator.d.ts +2 -2
- package/dist/types/providers/electrum.d.ts +5 -5
- package/dist/types/providers/expoArk.d.ts +1 -1
- package/dist/types/providers/expoIndexer.d.ts +1 -1
- package/dist/types/providers/indexer.d.ts +1 -1
- package/dist/types/providers/onchain.d.ts +2 -2
- package/dist/types/repositories/contractRepository.d.ts +1 -1
- package/dist/types/repositories/inMemory/contractRepository.d.ts +2 -2
- package/dist/types/repositories/inMemory/walletRepository.d.ts +5 -2
- package/dist/types/repositories/index.d.ts +9 -9
- package/dist/types/repositories/indexedDB/contractRepository.d.ts +2 -2
- package/dist/types/repositories/indexedDB/db.d.ts +3 -3
- package/dist/types/repositories/indexedDB/walletRepository.d.ts +5 -2
- package/dist/types/repositories/migrations/contractRepositoryImpl.d.ts +3 -3
- package/dist/types/repositories/migrations/fromStorageAdapter.d.ts +2 -2
- package/dist/types/repositories/migrations/walletRepositoryImpl.d.ts +3 -3
- package/dist/types/repositories/realm/contractRepository.d.ts +3 -3
- package/dist/types/repositories/realm/index.d.ts +4 -4
- package/dist/types/repositories/realm/walletRepository.d.ts +6 -3
- package/dist/types/repositories/serialization.d.ts +11 -11
- package/dist/types/repositories/sqlite/contractRepository.d.ts +3 -3
- package/dist/types/repositories/sqlite/index.d.ts +3 -3
- package/dist/types/repositories/sqlite/walletRepository.d.ts +6 -3
- package/dist/types/repositories/walletRepository.d.ts +22 -1
- package/dist/types/script/address.d.ts +2 -2
- package/dist/types/script/base.d.ts +2 -2
- package/dist/types/script/default.d.ts +2 -2
- package/dist/types/script/delegate.d.ts +3 -3
- package/dist/types/script/vhtlc.d.ts +2 -2
- package/dist/types/storage/asyncStorage.d.ts +1 -1
- package/dist/types/storage/fileSystem.d.ts +1 -1
- package/dist/types/storage/inMemory.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/tree/signingSession.d.ts +2 -2
- package/dist/types/tree/validation.d.ts +1 -1
- package/dist/types/utils/arkTransaction.d.ts +5 -5
- package/dist/types/utils/syncCursors.d.ts +1 -1
- package/dist/types/utils/timelock.d.ts +1 -1
- package/dist/types/utils/transaction.d.ts +2 -2
- package/dist/types/utils/transactionHistory.d.ts +1 -1
- package/dist/types/utils/txSizeEstimator.d.ts +1 -1
- package/dist/types/wallet/asset-manager.d.ts +3 -3
- package/dist/types/wallet/asset.d.ts +2 -2
- package/dist/types/wallet/batch.d.ts +2 -2
- package/dist/types/wallet/delegator.d.ts +5 -5
- package/dist/types/wallet/expo/background.d.ts +4 -4
- package/dist/types/wallet/expo/index.d.ts +4 -4
- package/dist/types/wallet/expo/wallet.d.ts +8 -8
- package/dist/types/wallet/hdDescriptorProvider.d.ts +4 -4
- package/dist/types/wallet/index.d.ts +29 -26
- package/dist/types/wallet/onchain.d.ts +6 -6
- package/dist/types/wallet/ramps.d.ts +2 -2
- package/dist/types/wallet/serviceWorker/wallet-message-handler.d.ts +21 -9
- package/dist/types/wallet/serviceWorker/wallet.d.ts +10 -10
- package/dist/types/wallet/unroll.d.ts +6 -6
- package/dist/types/wallet/utils.d.ts +5 -5
- package/dist/types/wallet/validation.d.ts +3 -3
- package/dist/types/wallet/vtxo-manager.d.ts +34 -7
- package/dist/types/wallet/wallet.d.ts +20 -20
- package/dist/types/worker/expo/asyncStorageTaskQueue.d.ts +1 -1
- package/dist/types/worker/expo/index.d.ts +7 -7
- package/dist/types/worker/expo/processors/contractPollProcessor.d.ts +1 -1
- package/dist/types/worker/expo/processors/index.d.ts +1 -1
- package/dist/types/worker/expo/taskRunner.d.ts +7 -7
- package/dist/types/worker/messageBus.d.ts +6 -6
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DefaultVtxo } from
|
|
2
|
-
import { MultisigTapscript } from
|
|
3
|
-
import { VtxoScript } from
|
|
1
|
+
import { DefaultVtxo } from "./default.js";
|
|
2
|
+
import { MultisigTapscript } from "./tapscript.js";
|
|
3
|
+
import { VtxoScript } from "./base.js";
|
|
4
4
|
import { hex } from "@scure/base";
|
|
5
5
|
/**
|
|
6
6
|
* DelegateVtxo extends DefaultVtxo with an extra delegator path
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Script, ScriptNum, p2tr_ms } from "@scure/btc-signer";
|
|
2
2
|
import { hex } from "@scure/base";
|
|
3
|
-
import { sequenceToTimelock, timelockToSequence } from
|
|
3
|
+
import { sequenceToTimelock, timelockToSequence } from "../utils/timelock.js";
|
|
4
4
|
const MinimalScriptNum = ScriptNum(undefined, true);
|
|
5
5
|
export var TapscriptType;
|
|
6
6
|
(function (TapscriptType) {
|
package/dist/esm/script/vhtlc.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Script } from "@scure/btc-signer";
|
|
2
|
-
import { CLTVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CSVMultisigTapscript, MultisigTapscript, } from
|
|
2
|
+
import { CLTVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CSVMultisigTapscript, MultisigTapscript, } from "./tapscript.js";
|
|
3
3
|
import { hex } from "@scure/base";
|
|
4
|
-
import { VtxoScript } from
|
|
4
|
+
import { VtxoScript } from "./base.js";
|
|
5
5
|
/** Virtual Hash Time Lock Contract (VHTLC) namespace. */
|
|
6
6
|
export var VHTLC;
|
|
7
7
|
(function (VHTLC) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as musig2 from
|
|
1
|
+
import * as musig2 from "../musig2/index.js";
|
|
2
2
|
import { Script } from "@scure/btc-signer/script.js";
|
|
3
3
|
import { SigHash } from "@scure/btc-signer/transaction.js";
|
|
4
4
|
import { hex } from "@scure/base";
|
|
5
5
|
import { schnorr, secp256k1 } from "@noble/curves/secp256k1.js";
|
|
6
6
|
import { randomPrivateKeyBytes } from "@scure/btc-signer/utils.js";
|
|
7
|
-
import { CosignerPublicKey, getArkPsbtFields } from
|
|
7
|
+
import { CosignerPublicKey, getArkPsbtFields } from "../utils/unknownFields.js";
|
|
8
8
|
export const ErrMissingVtxoGraph = new Error("missing vtxo graph");
|
|
9
9
|
export const ErrMissingAggregateKey = new Error("missing aggregate key");
|
|
10
10
|
export class TreeSignerSession {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { hex } from "@scure/base";
|
|
2
2
|
import { Transaction } from "@scure/btc-signer/transaction.js";
|
|
3
3
|
import { base64 } from "@scure/base";
|
|
4
|
-
import { aggregateKeys } from
|
|
5
|
-
import { CosignerPublicKey, getArkPsbtFields } from
|
|
4
|
+
import { aggregateKeys } from "../musig2/index.js";
|
|
5
|
+
import { CosignerPublicKey, getArkPsbtFields } from "../utils/unknownFields.js";
|
|
6
6
|
export const ErrInvalidSettlementTx = (tx) => new Error(`invalid settlement transaction: ${tx}`);
|
|
7
7
|
export const ErrInvalidSettlementTxOutputs = new Error("invalid settlement transaction outputs");
|
|
8
8
|
export const ErrEmptyTree = new Error("empty tree");
|
|
@@ -2,13 +2,13 @@ import { schnorr } from "@noble/curves/secp256k1.js";
|
|
|
2
2
|
import { hex } from "@scure/base";
|
|
3
3
|
import { DEFAULT_SEQUENCE, Script, SigHash } from "@scure/btc-signer";
|
|
4
4
|
import { tapLeafHash } from "@scure/btc-signer/payment.js";
|
|
5
|
-
import { CLTVMultisigTapscript, decodeTapscript, } from
|
|
6
|
-
import { scriptFromTapLeafScript, VtxoScript, } from
|
|
7
|
-
import { P2A } from
|
|
8
|
-
import { setArkPsbtField, VtxoTaprootTree } from
|
|
9
|
-
import { Transaction } from
|
|
10
|
-
import { ArkAddress } from
|
|
11
|
-
import { Extension } from
|
|
5
|
+
import { CLTVMultisigTapscript, decodeTapscript, } from "../script/tapscript.js";
|
|
6
|
+
import { scriptFromTapLeafScript, VtxoScript, } from "../script/base.js";
|
|
7
|
+
import { P2A } from "./anchor.js";
|
|
8
|
+
import { setArkPsbtField, VtxoTaprootTree } from "./unknownFields.js";
|
|
9
|
+
import { Transaction } from "./transaction.js";
|
|
10
|
+
import { ArkAddress } from "../script/address.js";
|
|
11
|
+
import { Extension } from "../extension/index.js";
|
|
12
12
|
/**
|
|
13
13
|
* Builds an offchain transaction with checkpoint transactions.
|
|
14
14
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RawWitness, ScriptNum } from "@scure/btc-signer";
|
|
2
2
|
import { hex } from "@scure/base";
|
|
3
|
-
import { sequenceToTimelock } from
|
|
3
|
+
import { sequenceToTimelock } from "./timelock.js";
|
|
4
4
|
/**
|
|
5
5
|
* ArkPsbtFieldKey are the available key names for the Arkade PSBT custom fields.
|
|
6
6
|
*/
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { AssetGroup, AssetId, AssetInput, AssetOutput, AssetRef, Metadata, Packet, } from
|
|
2
|
-
import { ArkAddress } from
|
|
3
|
-
import { selectedCoinsToAssetInputs, selectCoinsWithAsset } from
|
|
4
|
-
import { Extension } from
|
|
5
|
-
import { selectVirtualCoins } from
|
|
1
|
+
import { AssetGroup, AssetId, AssetInput, AssetOutput, AssetRef, Metadata, Packet, } from "../extension/asset/index.js";
|
|
2
|
+
import { ArkAddress } from "../script/address.js";
|
|
3
|
+
import { selectedCoinsToAssetInputs, selectCoinsWithAsset } from "./asset.js";
|
|
4
|
+
import { Extension } from "../extension/index.js";
|
|
5
|
+
import { selectVirtualCoins } from "./wallet.js";
|
|
6
6
|
export class ReadonlyAssetManager {
|
|
7
7
|
constructor(indexer) {
|
|
8
8
|
this.indexer = indexer;
|
package/dist/esm/wallet/asset.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AssetGroup, AssetId, AssetInput, AssetOutput, Packet, } from
|
|
1
|
+
import { AssetGroup, AssetId, AssetInput, AssetOutput, Packet, } from "../extension/asset/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Creates an asset packet from asset inputs and receivers.
|
|
4
4
|
* Groups inputs and outputs by asset ID and creates the Packet object
|
package/dist/esm/wallet/batch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SettlementEventType } from
|
|
2
|
-
import { TxTree } from
|
|
1
|
+
import { SettlementEventType } from "../providers/ark.js";
|
|
2
|
+
import { TxTree } from "../tree/txTree.js";
|
|
3
3
|
import { hex } from "@scure/base";
|
|
4
4
|
/**
|
|
5
5
|
* Batch namespace provides utilities for joining and processing batch session.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { ArkAddress, decodeTapscript, Estimator, Intent, isRecoverable, MultisigTapscript, VtxoScript, } from
|
|
1
|
+
import { ArkAddress, decodeTapscript, Estimator, Intent, isRecoverable, MultisigTapscript, VtxoScript, } from "../index.js";
|
|
2
2
|
import { base64, hex } from "@scure/base";
|
|
3
|
-
import { scriptFromTapLeafScript } from
|
|
4
|
-
import { buildForfeitTxWithOutput } from
|
|
3
|
+
import { scriptFromTapLeafScript } from "../script/base.js";
|
|
4
|
+
import { buildForfeitTxWithOutput } from "../forfeit.js";
|
|
5
5
|
import { Address, OutScript, SigHash } from "@scure/btc-signer";
|
|
6
6
|
import { equalBytes } from "@scure/btc-signer/utils.js";
|
|
7
|
-
import { getNetwork } from
|
|
8
|
-
import { createAssetPacket } from
|
|
9
|
-
import { Extension } from
|
|
7
|
+
import { getNetwork } from "../networks.js";
|
|
8
|
+
import { createAssetPacket } from "./asset.js";
|
|
9
|
+
import { Extension } from "../extension/index.js";
|
|
10
10
|
export class DelegatorManagerImpl {
|
|
11
11
|
/** Create a delegator manager from the configured provider, Arkade info source, and wallet identity. */
|
|
12
12
|
constructor(delegatorProvider, arkInfoProvider, identity) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { runTasks, createTaskDependencies } from
|
|
2
|
-
import { contractPollProcessor, CONTRACT_POLL_TASK_TYPE, } from
|
|
3
|
-
import { ExpoArkProvider } from
|
|
4
|
-
import { ExpoIndexerProvider } from
|
|
5
|
-
import { getRandomId } from
|
|
1
|
+
import { runTasks, createTaskDependencies } from "../../worker/expo/taskRunner.js";
|
|
2
|
+
import { contractPollProcessor, CONTRACT_POLL_TASK_TYPE, } from "../../worker/expo/processors/index.js";
|
|
3
|
+
import { ExpoArkProvider } from "../../providers/expoArk.js";
|
|
4
|
+
import { ExpoIndexerProvider } from "../../providers/expoIndexer.js";
|
|
5
|
+
import { getRandomId } from "../utils.js";
|
|
6
6
|
function requireTaskManager() {
|
|
7
7
|
try {
|
|
8
8
|
return require("expo-task-manager");
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { ExpoWallet } from
|
|
2
|
-
export { defineExpoBackgroundTask, registerExpoBackgroundTask, unregisterExpoBackgroundTask, } from
|
|
1
|
+
export { ExpoWallet } from "./wallet.js";
|
|
2
|
+
export { defineExpoBackgroundTask, registerExpoBackgroundTask, unregisterExpoBackgroundTask, } from "./background.js";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { hex } from "@scure/base";
|
|
2
|
-
import { Wallet } from
|
|
3
|
-
import { RestArkProvider } from
|
|
4
|
-
import { runTasks } from
|
|
5
|
-
import { contractPollProcessor, CONTRACT_POLL_TASK_TYPE, } from
|
|
6
|
-
import { extendVirtualCoinForContract, getRandomId } from
|
|
7
|
-
import { DefaultVtxo } from
|
|
2
|
+
import { Wallet } from "../wallet.js";
|
|
3
|
+
import { RestArkProvider } from "../../providers/ark.js";
|
|
4
|
+
import { runTasks } from "../../worker/expo/taskRunner.js";
|
|
5
|
+
import { contractPollProcessor, CONTRACT_POLL_TASK_TYPE, } from "../../worker/expo/processors/index.js";
|
|
6
|
+
import { extendVirtualCoinForContract, getRandomId } from "../utils.js";
|
|
7
|
+
import { DefaultVtxo } from "../../script/default.js";
|
|
8
8
|
/**
|
|
9
9
|
* Expo/React Native wallet with built-in background task processing.
|
|
10
10
|
*
|
|
@@ -96,7 +96,7 @@ export class ExpoWallet {
|
|
|
96
96
|
// Activate OS-level background scheduling
|
|
97
97
|
if (config.background.minimumBackgroundInterval) {
|
|
98
98
|
try {
|
|
99
|
-
const { registerExpoBackgroundTask } = await import("./background");
|
|
99
|
+
const { registerExpoBackgroundTask } = await import("./background.js");
|
|
100
100
|
await registerExpoBackgroundTask(config.background.taskName, {
|
|
101
101
|
minimumInterval: config.background.minimumBackgroundInterval,
|
|
102
102
|
});
|
|
@@ -145,7 +145,7 @@ export class ExpoWallet {
|
|
|
145
145
|
this.foregroundIntervalId = undefined;
|
|
146
146
|
}
|
|
147
147
|
try {
|
|
148
|
-
const { unregisterExpoBackgroundTask } = await import("./background");
|
|
148
|
+
const { unregisterExpoBackgroundTask } = await import("./background.js");
|
|
149
149
|
await unregisterExpoBackgroundTask(this.taskName);
|
|
150
150
|
}
|
|
151
151
|
catch {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { expand, networks } from "@bitcoinerlab/descriptors-scure";
|
|
2
|
-
import { isMainnetDescriptor } from
|
|
3
|
-
import { updateWalletState } from
|
|
2
|
+
import { isMainnetDescriptor } from "../identity/descriptor.js";
|
|
3
|
+
import { updateWalletState } from "../utils/syncCursors.js";
|
|
4
4
|
/** Settings key under {@link WalletState.settings} where HD state lives. */
|
|
5
5
|
const HD_SETTINGS_KEY = "hd";
|
|
6
6
|
/**
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { p2tr } from "@scure/btc-signer";
|
|
2
|
-
import { DEFAULT_NETWORK_NAME } from
|
|
3
|
-
import { getNetwork } from
|
|
4
|
-
import { ESPLORA_URL, EsploraProvider, } from
|
|
5
|
-
import { findP2AOutput, P2A } from
|
|
6
|
-
import { TxWeightEstimator } from
|
|
7
|
-
import { Transaction } from
|
|
8
|
-
import { DUST_AMOUNT } from
|
|
2
|
+
import { DEFAULT_NETWORK_NAME } from "./index.js";
|
|
3
|
+
import { getNetwork } from "../networks.js";
|
|
4
|
+
import { ESPLORA_URL, EsploraProvider, } from "../providers/onchain.js";
|
|
5
|
+
import { findP2AOutput, P2A } from "../utils/anchor.js";
|
|
6
|
+
import { TxWeightEstimator } from "../utils/txSizeEstimator.js";
|
|
7
|
+
import { Transaction } from "../utils/transaction.js";
|
|
8
|
+
import { DUST_AMOUNT } from "./utils.js";
|
|
9
9
|
/**
|
|
10
10
|
* Onchain Bitcoin wallet implementation for traditional Bitcoin transactions.
|
|
11
11
|
*
|
package/dist/esm/wallet/ramps.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Estimator } from
|
|
1
|
+
import { Estimator } from "../arkfee/index.js";
|
|
2
2
|
import { Address, OutScript } from "@scure/btc-signer";
|
|
3
3
|
import { hex } from "@scure/base";
|
|
4
|
-
import { networks } from
|
|
5
|
-
import { ArkAddress } from
|
|
4
|
+
import { networks } from "../networks.js";
|
|
5
|
+
import { ArkAddress } from "../script/address.js";
|
|
6
6
|
/**
|
|
7
7
|
* Ramps is a class wrapping `settle` method to provide a more convenient interface for onboarding and offboarding operations.
|
|
8
8
|
*
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { RestIndexerProvider } from
|
|
2
|
-
import { isExpired, isRecoverable, isSpendable, isSubdust, } from
|
|
3
|
-
import { extendCoin } from
|
|
4
|
-
import { buildTransactionHistory } from
|
|
5
|
-
import { filterVtxosForScript, warnAndFilterVtxosForScript, } from
|
|
6
|
-
import { scriptFromArkAddress } from
|
|
1
|
+
import { RestIndexerProvider } from "../../providers/indexer.js";
|
|
2
|
+
import { isExpired, isRecoverable, isSpendable, isSubdust, } from "../index.js";
|
|
3
|
+
import { extendCoin } from "../utils.js";
|
|
4
|
+
import { buildTransactionHistory } from "../../utils/transactionHistory.js";
|
|
5
|
+
import { filterVtxosForScript, getVtxosForContract, saveVtxosForContract, warnAndFilterVtxosForScript, } from "../../contracts/vtxoOwnership.js";
|
|
6
|
+
import { scriptFromArkAddress } from "../../repositories/scriptFromAddress.js";
|
|
7
7
|
export class WalletNotInitializedError extends Error {
|
|
8
8
|
constructor() {
|
|
9
9
|
super("Wallet handler not initialized");
|
|
@@ -313,6 +313,16 @@ export class WalletMessageHandler {
|
|
|
313
313
|
type: "REFRESH_VTXOS_SUCCESS",
|
|
314
314
|
});
|
|
315
315
|
}
|
|
316
|
+
case "REFRESH_OUTPOINTS": {
|
|
317
|
+
const manager = await this.readonlyWallet.getContractManager();
|
|
318
|
+
const { outpoints } = message
|
|
319
|
+
.payload;
|
|
320
|
+
await manager.refreshOutpoints(outpoints);
|
|
321
|
+
return this.tagged({
|
|
322
|
+
id,
|
|
323
|
+
type: "REFRESH_OUTPOINTS_SUCCESS",
|
|
324
|
+
});
|
|
325
|
+
}
|
|
316
326
|
case "SEND": {
|
|
317
327
|
const { recipients } = message.payload;
|
|
318
328
|
const txid = await this.wallet.send(...recipients);
|
|
@@ -620,7 +630,9 @@ export class WalletMessageHandler {
|
|
|
620
630
|
: addrByScript.get(script);
|
|
621
631
|
if (!targetAddress)
|
|
622
632
|
continue;
|
|
623
|
-
|
|
633
|
+
if (this.walletRepository) {
|
|
634
|
+
await saveVtxosForContract(this.walletRepository, { script, address: targetAddress }, filtered);
|
|
635
|
+
}
|
|
624
636
|
}
|
|
625
637
|
// notify all clients about the virtual output state update
|
|
626
638
|
this.scheduleForNextTick(() => this.tagged({
|
|
@@ -840,8 +852,7 @@ export class WalletMessageHandler {
|
|
|
840
852
|
const manager = await this.readonlyWallet.getContractManager();
|
|
841
853
|
const contracts = await manager.getContracts();
|
|
842
854
|
for (const contract of contracts) {
|
|
843
|
-
|
|
844
|
-
addVtxos(filterVtxosForScript(vtxos, contract.script));
|
|
855
|
+
addVtxos(await getVtxosForContract(this.walletRepository, contract));
|
|
845
856
|
}
|
|
846
857
|
// Also check the wallet's primary address. Decode it to its script
|
|
847
858
|
// and apply the same script gate. Failing to decode the wallet's own
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { hex } from "@scure/base";
|
|
2
|
-
import { serializeReadonlyIdentity, serializeSigningIdentity, } from
|
|
3
|
-
import { setupServiceWorker } from
|
|
4
|
-
import { IndexedDBContractRepository, IndexedDBWalletRepository, } from
|
|
5
|
-
import { DEFAULT_MESSAGE_TAG, } from
|
|
6
|
-
import { getRandomId } from
|
|
7
|
-
import { MESSAGE_BUS_NOT_INITIALIZED, ServiceWorkerTimeoutError, } from
|
|
8
|
-
import { getArkadeServerUrl } from
|
|
2
|
+
import { serializeReadonlyIdentity, serializeSigningIdentity, } from "../../identity/index.js";
|
|
3
|
+
import { setupServiceWorker } from "../../worker/browser/utils.js";
|
|
4
|
+
import { IndexedDBContractRepository, IndexedDBWalletRepository, } from "../../repositories/index.js";
|
|
5
|
+
import { DEFAULT_MESSAGE_TAG, } from "./wallet-message-handler.js";
|
|
6
|
+
import { getRandomId } from "../utils.js";
|
|
7
|
+
import { MESSAGE_BUS_NOT_INITIALIZED, ServiceWorkerTimeoutError, } from "../../worker/errors.js";
|
|
8
|
+
import { getArkadeServerUrl } from "../wallet.js";
|
|
9
9
|
// Check by error message content instead of instanceof because postMessage uses the
|
|
10
10
|
// structured clone algorithm which strips the prototype chain — the page
|
|
11
11
|
// receives a plain Error, not the original MessageBusNotInitializedError.
|
|
@@ -57,6 +57,7 @@ export const DEFAULT_MESSAGE_TIMEOUTS = {
|
|
|
57
57
|
UPDATE_CONTRACT: 30000,
|
|
58
58
|
DELETE_CONTRACT: 10000,
|
|
59
59
|
REFRESH_VTXOS: 30000,
|
|
60
|
+
REFRESH_OUTPOINTS: 30000,
|
|
60
61
|
};
|
|
61
62
|
const DEDUPABLE_REQUEST_TYPES = new Set([
|
|
62
63
|
"GET_ADDRESS",
|
|
@@ -821,6 +822,15 @@ export class ServiceWorkerReadonlyWallet {
|
|
|
821
822
|
};
|
|
822
823
|
await sendContractMessage(message);
|
|
823
824
|
},
|
|
825
|
+
async refreshOutpoints(outpoints) {
|
|
826
|
+
const message = {
|
|
827
|
+
type: "REFRESH_OUTPOINTS",
|
|
828
|
+
id: getRandomId(),
|
|
829
|
+
tag: messageTag,
|
|
830
|
+
payload: { outpoints },
|
|
831
|
+
};
|
|
832
|
+
await sendContractMessage(message);
|
|
833
|
+
},
|
|
824
834
|
async isWatching() {
|
|
825
835
|
const message = {
|
|
826
836
|
type: "IS_CONTRACT_MANAGER_WATCHING",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { base64, hex } from "@scure/base";
|
|
2
2
|
import { SigHash, TaprootControlBlock } from "@scure/btc-signer";
|
|
3
|
-
import { timelockToSequence } from
|
|
4
|
-
import { ChainTxType } from
|
|
5
|
-
import { VtxoScript } from
|
|
6
|
-
import { TxWeightEstimator } from
|
|
7
|
-
import { Wallet } from
|
|
8
|
-
import { Transaction } from
|
|
9
|
-
import { DUST_AMOUNT } from
|
|
3
|
+
import { timelockToSequence } from "../utils/timelock.js";
|
|
4
|
+
import { ChainTxType } from "../providers/indexer.js";
|
|
5
|
+
import { VtxoScript } from "../script/base.js";
|
|
6
|
+
import { TxWeightEstimator } from "../utils/txSizeEstimator.js";
|
|
7
|
+
import { Wallet } from "./wallet.js";
|
|
8
|
+
import { Transaction } from "../utils/transaction.js";
|
|
9
|
+
import { DUST_AMOUNT } from "./utils.js";
|
|
10
10
|
export var Unroll;
|
|
11
11
|
(function (Unroll) {
|
|
12
12
|
let StepType;
|
package/dist/esm/wallet/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ArkAddress, } from
|
|
2
|
-
import { contractHandlers } from
|
|
1
|
+
import { ArkAddress, } from "../index.js";
|
|
2
|
+
import { contractHandlers } from "../contracts/handlers/index.js";
|
|
3
3
|
import { hex } from "@scure/base";
|
|
4
4
|
export const DUST_AMOUNT = 546; // sats
|
|
5
5
|
export function extendCoin(wallet, utxo) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { equalBytes } from "@scure/btc-signer/utils.js";
|
|
2
|
-
import { ArkAddress } from
|
|
3
|
-
import { Extension } from
|
|
2
|
+
import { ArkAddress } from "../script/address.js";
|
|
3
|
+
import { Extension } from "../extension/index.js";
|
|
4
4
|
import { Address, OutScript } from "@scure/btc-signer";
|
|
5
5
|
export const ErrOffchainOutputNotFound = (address) => new Error(`offchain send output not found: ${address}`);
|
|
6
6
|
export const ErrInvalidAssetOutputAmount = (got, want, assetId) => new Error(`invalid asset output amount for ${assetId}: got ${got}, want ${want}`);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { isExpired, isRecoverable, isSpendable, isSubdust, } from
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { isExpired, isRecoverable, isSpendable, isSubdust, } from "./index.js";
|
|
2
|
+
import { maybeArkError } from "../providers/errors.js";
|
|
3
|
+
import { hasBoardingTxExpired } from "../utils/arkTransaction.js";
|
|
4
|
+
import { CSVMultisigTapscript } from "../script/tapscript.js";
|
|
4
5
|
import { hex } from "@scure/base";
|
|
5
|
-
import { getSequence } from
|
|
6
|
-
import { Transaction } from
|
|
7
|
-
import { TxWeightEstimator } from
|
|
8
|
-
import { Estimator } from
|
|
9
|
-
import { ArkAddress } from
|
|
6
|
+
import { getSequence } from "../script/base.js";
|
|
7
|
+
import { Transaction } from "../utils/transaction.js";
|
|
8
|
+
import { TxWeightEstimator } from "../utils/txSizeEstimator.js";
|
|
9
|
+
import { Estimator } from "../arkfee/index.js";
|
|
10
|
+
import { ArkAddress } from "../script/address.js";
|
|
10
11
|
/**
|
|
11
12
|
* Return whether a wallet exposes the properties required for boarding input sweep operations.
|
|
12
13
|
*
|
|
@@ -432,10 +433,22 @@ export class VtxoManager {
|
|
|
432
433
|
try {
|
|
433
434
|
// Get all virtual outputs (including recoverable ones)
|
|
434
435
|
// Use default threshold to bypass settlementConfig gate (manual API should always work)
|
|
435
|
-
const
|
|
436
|
+
const threshold = this.settlementConfig !== false &&
|
|
436
437
|
this.settlementConfig?.vtxoThreshold !== undefined
|
|
437
438
|
? this.settlementConfig.vtxoThreshold * 1000
|
|
438
|
-
: DEFAULT_RENEWAL_CONFIG.thresholdMs
|
|
439
|
+
: DEFAULT_RENEWAL_CONFIG.thresholdMs;
|
|
440
|
+
let vtxos = await this.getExpiringVtxos(threshold);
|
|
441
|
+
if (vtxos.length === 0) {
|
|
442
|
+
throw new Error("No VTXOs available to renew");
|
|
443
|
+
}
|
|
444
|
+
// Pre-flight: validate the chosen inputs against the indexer's
|
|
445
|
+
// authoritative state before submitting. The cursor-derived
|
|
446
|
+
// delta sync filters by `created_at`, so a VTXO created
|
|
447
|
+
// before the cursor and spent recently can sit in the local
|
|
448
|
+
// cache forever; settling against it yields a guaranteed
|
|
449
|
+
// VTXO_ALREADY_SPENT 400. Refreshing the candidates here
|
|
450
|
+
// catches that BEFORE the network round-trip.
|
|
451
|
+
vtxos = await this.revalidateBeforeSettle(vtxos, threshold);
|
|
439
452
|
if (vtxos.length === 0) {
|
|
440
453
|
throw new Error("No VTXOs available to renew");
|
|
441
454
|
}
|
|
@@ -684,9 +697,11 @@ export class VtxoManager {
|
|
|
684
697
|
if (e.message.includes("VTXO_ALREADY_SPENT")) {
|
|
685
698
|
// Our local VTXO cache is stale vs. the
|
|
686
699
|
// server's authoritative view. Trigger a
|
|
687
|
-
// throttled refresh
|
|
688
|
-
//
|
|
689
|
-
|
|
700
|
+
// throttled, targeted refresh on the
|
|
701
|
+
// offending outpoint (if the server told
|
|
702
|
+
// us which one), then skip — the next
|
|
703
|
+
// cycle will see fresh data.
|
|
704
|
+
void this.maybeRefreshAfterVtxoSpent(this.extractSpentOutpoint(e));
|
|
690
705
|
return;
|
|
691
706
|
}
|
|
692
707
|
}
|
|
@@ -711,13 +726,20 @@ export class VtxoManager {
|
|
|
711
726
|
/**
|
|
712
727
|
* VTXO_ALREADY_SPENT means the server's authoritative view of VTXO state
|
|
713
728
|
* is ahead of ours — cross-instance race, pre-lock snapshot drift, or an
|
|
714
|
-
* SSE gap left stale data in the local cache. Silent-swallowing
|
|
715
|
-
* the same error on the next cycle because nothing
|
|
716
|
-
*
|
|
717
|
-
*
|
|
718
|
-
*
|
|
729
|
+
* SSE gap left stale data in the local cache. Silent-swallowing
|
|
730
|
+
* guarantees the same error on the next cycle because nothing
|
|
731
|
+
* reconciles the cache.
|
|
732
|
+
*
|
|
733
|
+
* The cursor-derived delta sync filters by `created_at`, so a VTXO that
|
|
734
|
+
* was created before the cursor but spent recently can never be
|
|
735
|
+
* reconciled by `refreshVtxos()`. Use `refreshOutpoints` for surgical
|
|
736
|
+
* recovery: query the indexer for the specific stale outpoint and
|
|
737
|
+
* upsert its authoritative state into the wallet repository.
|
|
738
|
+
*
|
|
739
|
+
* Throttled because the same VTXO can fire repeatedly before the
|
|
740
|
+
* upsert observably propagates through the renewal selector.
|
|
719
741
|
*/
|
|
720
|
-
maybeRefreshAfterVtxoSpent() {
|
|
742
|
+
maybeRefreshAfterVtxoSpent(spentOutpoint) {
|
|
721
743
|
if (this.vtxoSpentRefreshPromise) {
|
|
722
744
|
return this.vtxoSpentRefreshPromise;
|
|
723
745
|
}
|
|
@@ -730,7 +752,13 @@ export class VtxoManager {
|
|
|
730
752
|
this.vtxoSpentRefreshPromise = (async () => {
|
|
731
753
|
try {
|
|
732
754
|
const contractManager = await this.wallet.getContractManager();
|
|
733
|
-
|
|
755
|
+
if (spentOutpoint) {
|
|
756
|
+
await contractManager.refreshOutpoints([spentOutpoint]);
|
|
757
|
+
}
|
|
758
|
+
else {
|
|
759
|
+
// No outpoint metadata — fall back to the broader refresh.
|
|
760
|
+
await contractManager.refreshVtxos();
|
|
761
|
+
}
|
|
734
762
|
}
|
|
735
763
|
catch (e) {
|
|
736
764
|
console.error("Error refreshing VTXOs after VTXO_ALREADY_SPENT:", e);
|
|
@@ -741,6 +769,66 @@ export class VtxoManager {
|
|
|
741
769
|
})();
|
|
742
770
|
return this.vtxoSpentRefreshPromise;
|
|
743
771
|
}
|
|
772
|
+
/**
|
|
773
|
+
* Extract the offending VTXO outpoint from a `VTXO_ALREADY_SPENT` error,
|
|
774
|
+
* if the server attached one in `metadata.vtxo_outpoint`. Returns
|
|
775
|
+
* `undefined` when the error isn't a parsed ArkError, isn't this code,
|
|
776
|
+
* or doesn't carry the metadata.
|
|
777
|
+
*/
|
|
778
|
+
extractSpentOutpoint(error) {
|
|
779
|
+
const ark = maybeArkError(error);
|
|
780
|
+
if (!ark || ark.name !== "VTXO_ALREADY_SPENT")
|
|
781
|
+
return undefined;
|
|
782
|
+
const raw = ark.metadata?.vtxo_outpoint;
|
|
783
|
+
if (typeof raw !== "string")
|
|
784
|
+
return undefined;
|
|
785
|
+
const [txid, voutStr] = raw.split(":");
|
|
786
|
+
if (!txid || !voutStr)
|
|
787
|
+
return undefined;
|
|
788
|
+
const vout = Number(voutStr);
|
|
789
|
+
if (!Number.isInteger(vout) || vout < 0)
|
|
790
|
+
return undefined;
|
|
791
|
+
return { txid, vout };
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Reconcile the chosen VTXOs with the indexer's authoritative state
|
|
795
|
+
* before submitting a settle intent. Pulls the canonical record for
|
|
796
|
+
* each candidate outpoint via {@link IContractManager.refreshOutpoints}
|
|
797
|
+
* (which upserts the result into the wallet repository), then
|
|
798
|
+
* re-selects through the standard expiring-vtxo filter so anything
|
|
799
|
+
* the refresh flagged as spent is dropped.
|
|
800
|
+
*
|
|
801
|
+
* Best-effort: a failed refresh just falls back to the original
|
|
802
|
+
* candidates and lets the post-submit `VTXO_ALREADY_SPENT` recovery
|
|
803
|
+
* handle whatever slipped through.
|
|
804
|
+
*/
|
|
805
|
+
async revalidateBeforeSettle(candidates, thresholdMs) {
|
|
806
|
+
if (candidates.length === 0)
|
|
807
|
+
return candidates;
|
|
808
|
+
try {
|
|
809
|
+
const cm = await this.wallet.getContractManager();
|
|
810
|
+
await cm.refreshOutpoints(candidates.map((v) => ({ txid: v.txid, vout: v.vout })));
|
|
811
|
+
}
|
|
812
|
+
catch (e) {
|
|
813
|
+
console.error("Error pre-validating VTXOs before settle:", e);
|
|
814
|
+
return candidates;
|
|
815
|
+
}
|
|
816
|
+
// Re-select from the now-fresh local cache. Anything previously
|
|
817
|
+
// selected but spent gets filtered out by the standard
|
|
818
|
+
// `isSpendable`/`isSpent` checks inside getVtxos / getExpiringVtxos.
|
|
819
|
+
try {
|
|
820
|
+
const refreshed = await this.getExpiringVtxos(thresholdMs);
|
|
821
|
+
const candidateKeys = new Set(candidates.map((v) => `${v.txid}:${v.vout}`));
|
|
822
|
+
// Restrict to vtxos that were also in the original candidate set
|
|
823
|
+
// — `getExpiringVtxos` may surface NEW vtxos and we don't want
|
|
824
|
+
// pre-flight to silently expand the input set.
|
|
825
|
+
return refreshed.filter((v) => candidateKeys.has(`${v.txid}:${v.vout}`));
|
|
826
|
+
}
|
|
827
|
+
catch (e) {
|
|
828
|
+
console.error("Error re-selecting VTXOs after pre-validate:", e);
|
|
829
|
+
return candidates;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
744
832
|
/** Computes the next poll delay, applying exponential backoff on failures. */
|
|
745
833
|
getNextPollDelay() {
|
|
746
834
|
if (this.settlementConfig === false)
|
|
@@ -882,6 +970,13 @@ export class VtxoManager {
|
|
|
882
970
|
if (!this.renewalInProgress) {
|
|
883
971
|
try {
|
|
884
972
|
expiringVtxos = await this.getExpiringVtxos();
|
|
973
|
+
// Pre-flight validation: see comment in `renewVtxos`. The
|
|
974
|
+
// local cache may carry vtxos that the indexer already
|
|
975
|
+
// marks spent because the cursor-derived delta sync only
|
|
976
|
+
// catches `created_at`-recent updates, not status changes
|
|
977
|
+
// for older VTXOs.
|
|
978
|
+
expiringVtxos =
|
|
979
|
+
await this.revalidateBeforeSettle(expiringVtxos);
|
|
885
980
|
}
|
|
886
981
|
catch (e) {
|
|
887
982
|
// Non-fatal: fall back to boarding-only settle.
|
|
@@ -973,11 +1068,12 @@ export class VtxoManager {
|
|
|
973
1068
|
e.message.includes("VTXO_ALREADY_SPENT")) {
|
|
974
1069
|
// Local VTXO cache is stale vs. the server's
|
|
975
1070
|
// authoritative view — not a transient failure.
|
|
976
|
-
// Trigger a throttled refresh
|
|
977
|
-
//
|
|
978
|
-
//
|
|
1071
|
+
// Trigger a throttled, targeted refresh on the
|
|
1072
|
+
// offending outpoint and skip this cycle without
|
|
1073
|
+
// bumping the failure counter, so the next poll
|
|
1074
|
+
// can retry once the cache reconciles.
|
|
979
1075
|
staleCacheSkip = true;
|
|
980
|
-
void this.maybeRefreshAfterVtxoSpent();
|
|
1076
|
+
void this.maybeRefreshAfterVtxoSpent(this.extractSpentOutpoint(e));
|
|
981
1077
|
}
|
|
982
1078
|
else {
|
|
983
1079
|
throw e;
|