@arkade-os/sdk 0.4.48-rc.0 → 0.4.48
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/adapters/expo.cjs +5 -5
- package/dist/adapters/expo.d.cts +2 -2
- package/dist/adapters/expo.d.ts +2 -2
- package/dist/adapters/expo.js +3 -3
- package/dist/adapters/indexedDB.cjs +5 -5
- package/dist/adapters/indexedDB.js +4 -4
- package/dist/{ark-CoJgwTi_.d.cts → ark-CjE0KkGp.d.cts} +405 -250
- package/dist/{ark-CoJgwTi_.d.ts → ark-CjE0KkGp.d.ts} +405 -250
- package/dist/{asyncStorageTaskQueue-CwknfM_j.d.cts → asyncStorageTaskQueue-CeLZhZFU.d.cts} +1 -1
- package/dist/{asyncStorageTaskQueue-D2Zl7yAB.d.ts → asyncStorageTaskQueue-D9SOPMPC.d.ts} +1 -1
- package/dist/{chunk-XN3554FT.js → chunk-4VVTRPH3.js} +4 -4
- package/dist/chunk-4VVTRPH3.js.map +1 -0
- package/dist/{chunk-RQSA7ADZ.cjs → chunk-5XMVTK5S.cjs} +37 -37
- package/dist/chunk-5XMVTK5S.cjs.map +1 -0
- package/dist/{chunk-L5ND2FJJ.cjs → chunk-7TXSPRN5.cjs} +161 -2
- package/dist/chunk-7TXSPRN5.cjs.map +1 -0
- package/dist/{chunk-GM6JRQP5.js → chunk-BHHLRZCS.js} +169 -42
- package/dist/chunk-BHHLRZCS.js.map +1 -0
- package/dist/{chunk-CFQO5MCM.cjs → chunk-EB3ALGTM.cjs} +178 -50
- package/dist/chunk-EB3ALGTM.cjs.map +1 -0
- package/dist/{chunk-3HUZAIKI.cjs → chunk-ENDNQPZA.cjs} +17 -44
- package/dist/chunk-ENDNQPZA.cjs.map +1 -0
- package/dist/{chunk-RJMFTTRJ.cjs → chunk-ENZ4YPR2.cjs} +614 -592
- package/dist/chunk-ENZ4YPR2.cjs.map +1 -0
- package/dist/{chunk-4AIHKC65.js → chunk-G6J6AEMH.js} +5 -4
- package/dist/chunk-G6J6AEMH.js.map +1 -0
- package/dist/{chunk-SV4PCGKM.js → chunk-NYR5H6GR.js} +348 -323
- package/dist/chunk-NYR5H6GR.js.map +1 -0
- package/dist/{chunk-EA3IWZ4W.cjs → chunk-SYDANBJI.cjs} +9 -8
- package/dist/chunk-SYDANBJI.cjs.map +1 -0
- package/dist/{chunk-ZRY2KSK5.js → chunk-XFMGIFBL.js} +4 -31
- package/dist/chunk-XFMGIFBL.js.map +1 -0
- package/dist/{chunk-C7TXXTMS.js → chunk-ZDDBTFVO.js} +146 -3
- package/dist/chunk-ZDDBTFVO.js.map +1 -0
- package/dist/contracts/handlers/index.cjs +8 -8
- package/dist/contracts/handlers/index.d.cts +3 -3
- package/dist/contracts/handlers/index.d.ts +3 -3
- package/dist/contracts/handlers/index.js +2 -2
- package/dist/{delegate-Dl87_zMA.d.cts → delegate-D3dY-2vS.d.cts} +1 -1
- package/dist/{delegate-CuaDqqQi.d.ts → delegate-DhGZk1r2.d.ts} +1 -1
- package/dist/{index-BC_G0VTh.d.cts → index-D6RQROds.d.cts} +2 -2
- package/dist/{index-CKwpZEpw.d.ts → index-DK4_iWYy.d.ts} +2 -2
- package/dist/index.cjs +208 -188
- package/dist/index.d.cts +35 -18
- package/dist/index.d.ts +35 -18
- package/dist/index.js +4 -4
- package/dist/repositories/realm/index.cjs +19 -19
- package/dist/repositories/realm/index.d.cts +2 -2
- package/dist/repositories/realm/index.d.ts +2 -2
- package/dist/repositories/realm/index.js +5 -5
- package/dist/repositories/sqlite/index.cjs +18 -18
- package/dist/repositories/sqlite/index.d.cts +2 -2
- package/dist/repositories/sqlite/index.d.ts +2 -2
- package/dist/repositories/sqlite/index.js +5 -5
- package/dist/{taskRunner-Df8YQpn1.d.ts → taskRunner-B-2MHCYG.d.ts} +1 -1
- package/dist/{taskRunner-RYihSj9E.d.cts → taskRunner-Brnak0Rc.d.cts} +1 -1
- package/dist/wallet/expo/background.cjs +14 -14
- package/dist/wallet/expo/background.d.cts +3 -3
- package/dist/wallet/expo/background.d.ts +3 -3
- package/dist/wallet/expo/background.js +6 -6
- package/dist/wallet/expo/index.cjs +14 -14
- package/dist/wallet/expo/index.cjs.map +1 -1
- package/dist/wallet/expo/index.d.cts +5 -5
- package/dist/wallet/expo/index.d.ts +5 -5
- package/dist/wallet/expo/index.js +5 -5
- package/dist/wallet/expo/index.js.map +1 -1
- package/dist/{wallet-B6s7_5bJ.d.cts → wallet-B5bwixQa.d.ts} +31 -31
- package/dist/{wallet-C61huH8i.d.ts → wallet-DiOrtYic.d.cts} +31 -31
- package/dist/worker/expo/index.cjs +9 -9
- package/dist/worker/expo/index.d.cts +4 -4
- package/dist/worker/expo/index.d.ts +4 -4
- package/dist/worker/expo/index.js +5 -5
- package/package.json +3 -2
- package/dist/chunk-3HUZAIKI.cjs.map +0 -1
- package/dist/chunk-4AIHKC65.js.map +0 -1
- package/dist/chunk-C7TXXTMS.js.map +0 -1
- package/dist/chunk-CFQO5MCM.cjs.map +0 -1
- package/dist/chunk-EA3IWZ4W.cjs.map +0 -1
- package/dist/chunk-GM6JRQP5.js.map +0 -1
- package/dist/chunk-L5ND2FJJ.cjs.map +0 -1
- package/dist/chunk-RJMFTTRJ.cjs.map +0 -1
- package/dist/chunk-RQSA7ADZ.cjs.map +0 -1
- package/dist/chunk-SV4PCGKM.js.map +0 -1
- package/dist/chunk-XN3554FT.js.map +0 -1
- package/dist/chunk-ZRY2KSK5.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Transaction, setArkPsbtField, PrevArkTxField, ConditionWitness, AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, Packet, craftToSpendTx, getArkPsbtFields, CosignerPublicKey, BufferReader, BufferWriter, OP_RETURN_EMPTY_PKSCRIPT, VtxoTaprootTree, baseFetch, Intent, maybeArkError, isArkError, ArkErrorName, ProviderUnavailableError, FetchError, isFetchTimeoutError, AssetRef, isEventSourceError, RestArkProvider, RestIndexerProvider, ArkError } from './chunk-
|
|
2
|
-
import { witnessRefToBytes, validateProgram, toASM, stringifyArtifact, serializeArkadeContractParams, resolveAsm, parseArtifact, getOpcodeValue, getOpcodeName, fromASM, deserializeArkadeContractParams, computeArkadeScriptPublicKey, bytesToASM, asmToBytes, arkadeWitnessHash, arkadeScriptHash, SUPPORTED_PROGRAM_VERSION, OPCODE_VALUES, OPCODE_NAMES, bignum_exports, ArkadeScript, ArkadeProgramScript, ARKADE_OPS, ARKADE_OPCODE_VALUES, ARKADE_OPCODE_NAMES, ARKADE_OPCODES, ARKADE_OP, inputName, contractHandlers, isMainnetDescriptor, descriptorIsOurs, DefaultVtxo, DEFAULT_PAGE_SIZE, DelegateVtxo, WALLET_RECEIVE_SOURCE, deriveDescriptorLeafPubKey, BoardingContractHandler } from './chunk-
|
|
3
|
-
import { VtxoScript, CSVMultisigTapscript, DEFAULT_NETWORK, ArkAddress, sequenceToTimelock, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, timelockToSequence, DEFAULT_NETWORK_NAME, getSequence, getNetwork, MultisigTapscript, networks as networks$1, DEFAULT_ARKADE_SERVER_URL } from './chunk-
|
|
1
|
+
import { Transaction, setArkPsbtField, PrevArkTxField, ConditionWitness, AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, Packet, craftToSpendTx, getArkPsbtFields, CosignerPublicKey, BufferReader, BufferWriter, OP_RETURN_EMPTY_PKSCRIPT, VtxoTaprootTree, baseFetch, Intent, rateGate, maybeArkError, isArkError, ArkErrorName, ProviderUnavailableError, FetchError, isFetchTimeoutError, AssetRef, isEventSourceError, RestArkProvider, RestIndexerProvider, ArkError } from './chunk-BHHLRZCS.js';
|
|
2
|
+
import { witnessRefToBytes, validateProgram, toASM, stringifyArtifact, serializeArkadeContractParams, resolveAsm, parseArtifact, getOpcodeValue, getOpcodeName, fromASM, deserializeArkadeContractParams, computeArkadeScriptPublicKey, bytesToASM, asmToBytes, arkadeWitnessHash, arkadeScriptHash, SUPPORTED_PROGRAM_VERSION, OPCODE_VALUES, OPCODE_NAMES, bignum_exports, ArkadeScript, ArkadeProgramScript, ARKADE_OPS, ARKADE_OPCODE_VALUES, ARKADE_OPCODE_NAMES, ARKADE_OPCODES, ARKADE_OP, inputName, contractHandlers, isMainnetDescriptor, descriptorIsOurs, DefaultVtxo, DEFAULT_PAGE_SIZE, DelegateVtxo, WALLET_RECEIVE_SOURCE, deriveDescriptorLeafPubKey, BoardingContractHandler } from './chunk-4VVTRPH3.js';
|
|
3
|
+
import { VtxoScript, isRecoverable, CSVMultisigTapscript, DEFAULT_NETWORK, hasTerminalSpend, getNormalizedVtxos, isVirtualCoin, ArkAddress, sequenceToTimelock, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, timelockToSequence, DEFAULT_NETWORK_NAME, normalizeVtxo, getSequence, toBatchExpiry, toOffchainInputFeeParams, canRecoverOnchain, getNetwork, MultisigTapscript, canSpendOffchain, toVirtualStatus, resolveTimeHeight, parseLegacyExpiry, networks as networks$1, isExpired, DEFAULT_ARKADE_SERVER_URL, isPastExpiry } from './chunk-ZDDBTFVO.js';
|
|
4
4
|
import { __export } from './chunk-NSBPE2FW.js';
|
|
5
5
|
import { sha256, equalBytes, hash160, sha256x2, concatBytes, randomPrivateKeyBytes, pubECDSA, pubSchnorr } from '@scure/btc-signer/utils.js';
|
|
6
6
|
import { SigHash, Script, OP, OutScript, Address, RawWitness, p2tr, p2wpkh, TaprootControlBlock, DEFAULT_SEQUENCE, Transaction as Transaction$2 } from '@scure/btc-signer';
|
|
@@ -991,7 +991,7 @@ var RestDelegateProvider = class {
|
|
|
991
991
|
*/
|
|
992
992
|
async getDelegateInfo() {
|
|
993
993
|
const url = `${this.url}/v1/delegator/info`;
|
|
994
|
-
const response = await baseFetch(url);
|
|
994
|
+
const response = await rateGate.runHttp(url, () => baseFetch(url));
|
|
995
995
|
if (!response.ok) {
|
|
996
996
|
const errorText2 = await response.text();
|
|
997
997
|
throw new Error(`Failed to get delegate info: ${errorText2}`);
|
|
@@ -2042,20 +2042,6 @@ var TxType = /* @__PURE__ */ ((TxType2) => {
|
|
|
2042
2042
|
TxType2["TxReceived"] = "RECEIVED";
|
|
2043
2043
|
return TxType2;
|
|
2044
2044
|
})(TxType || {});
|
|
2045
|
-
function isSpendable(vtxo) {
|
|
2046
|
-
return !vtxo.isSpent;
|
|
2047
|
-
}
|
|
2048
|
-
function isRecoverable(vtxo) {
|
|
2049
|
-
return vtxo.virtualStatus.state === "swept" && isSpendable(vtxo);
|
|
2050
|
-
}
|
|
2051
|
-
function isExpired(vtxo) {
|
|
2052
|
-
if (vtxo.virtualStatus.state === "swept") return true;
|
|
2053
|
-
const expiry = vtxo.virtualStatus.batchExpiry;
|
|
2054
|
-
if (!expiry) return false;
|
|
2055
|
-
const expireAt = new Date(expiry);
|
|
2056
|
-
if (expireAt.getFullYear() < 2025) return false;
|
|
2057
|
-
return expiry <= Date.now();
|
|
2058
|
-
}
|
|
2059
2045
|
function isSubdust(vtxo, dust) {
|
|
2060
2046
|
if (typeof vtxo === "bigint") return vtxo < dust;
|
|
2061
2047
|
return vtxo.value < dust;
|
|
@@ -2725,7 +2711,7 @@ function selectPendingRecoveryOutpoints(contractsWithVtxos, signerSet, nowSecond
|
|
|
2725
2711
|
continue;
|
|
2726
2712
|
}
|
|
2727
2713
|
for (const v of vtxos) {
|
|
2728
|
-
if (
|
|
2714
|
+
if (!hasTerminalSpend(v) && !v.isSwept) out.add(`${v.txid}:${v.vout}`);
|
|
2729
2715
|
}
|
|
2730
2716
|
}
|
|
2731
2717
|
return out;
|
|
@@ -2757,16 +2743,28 @@ var MAX_INPUTS_PER_INTENT = 20;
|
|
|
2757
2743
|
function byValueDescending(vtxos) {
|
|
2758
2744
|
return [...vtxos].sort((a, b) => b.value - a.value);
|
|
2759
2745
|
}
|
|
2760
|
-
function
|
|
2746
|
+
async function fetchTimeHeight(wallet) {
|
|
2747
|
+
return resolveTimeHeight(wallet.onchainProvider);
|
|
2748
|
+
}
|
|
2749
|
+
function canMigrateBySend(vtxo, now) {
|
|
2750
|
+
if (!canSpendOffchain(vtxo, now)) return false;
|
|
2751
|
+
return vtxo.expiresAt !== void 0 || vtxo.expiresAtHeight !== void 0;
|
|
2752
|
+
}
|
|
2753
|
+
function byExpiryAscending(vtxos, now) {
|
|
2761
2754
|
const expiryKey = (vtxo) => {
|
|
2762
|
-
if (
|
|
2763
|
-
|
|
2764
|
-
if (
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
return
|
|
2755
|
+
if (vtxo.isSwept) return -Infinity;
|
|
2756
|
+
if (vtxo.expiresAt !== void 0) return vtxo.expiresAt.getTime();
|
|
2757
|
+
if (vtxo.expiresAtHeight !== void 0) {
|
|
2758
|
+
return isPastExpiry(vtxo, now) ? -Infinity : Infinity;
|
|
2759
|
+
}
|
|
2760
|
+
return Infinity;
|
|
2768
2761
|
};
|
|
2769
|
-
return [...vtxos].sort((a, b) =>
|
|
2762
|
+
return [...vtxos].sort((a, b) => {
|
|
2763
|
+
const ka = expiryKey(a);
|
|
2764
|
+
const kb = expiryKey(b);
|
|
2765
|
+
if (ka === kb) return 0;
|
|
2766
|
+
return ka < kb ? -1 : 1;
|
|
2767
|
+
});
|
|
2770
2768
|
}
|
|
2771
2769
|
function capSettlementBatch(sorted, maxAmount) {
|
|
2772
2770
|
const batch = [];
|
|
@@ -2792,22 +2790,19 @@ var DEFAULT_SETTLEMENT_CONFIG = {
|
|
|
2792
2790
|
pollIntervalMs: 6e4,
|
|
2793
2791
|
deprecatedSignerMigration: true
|
|
2794
2792
|
};
|
|
2795
|
-
function getRecoverableVtxos(vtxos, dustAmount) {
|
|
2793
|
+
function getRecoverableVtxos(vtxos, dustAmount, now) {
|
|
2796
2794
|
return vtxos.filter((vtxo) => {
|
|
2797
|
-
if (
|
|
2798
|
-
return true;
|
|
2799
|
-
}
|
|
2800
|
-
if (isSpendable(vtxo) && isExpired(vtxo)) {
|
|
2795
|
+
if (canRecoverOnchain(vtxo, now)) {
|
|
2801
2796
|
return true;
|
|
2802
2797
|
}
|
|
2803
|
-
if (vtxo
|
|
2798
|
+
if (canSpendOffchain(vtxo, now) && vtxo.isPreconfirmed && isSubdust(vtxo, dustAmount)) {
|
|
2804
2799
|
return true;
|
|
2805
2800
|
}
|
|
2806
2801
|
return false;
|
|
2807
2802
|
});
|
|
2808
2803
|
}
|
|
2809
|
-
function getRecoverableWithSubdust(vtxos, dustAmount) {
|
|
2810
|
-
const recoverableVtxos = getRecoverableVtxos(vtxos, dustAmount);
|
|
2804
|
+
function getRecoverableWithSubdust(vtxos, dustAmount, now) {
|
|
2805
|
+
const recoverableVtxos = getRecoverableVtxos(vtxos, dustAmount, now);
|
|
2811
2806
|
const subdust = [];
|
|
2812
2807
|
const regular = [];
|
|
2813
2808
|
for (const vtxo of recoverableVtxos) {
|
|
@@ -2831,17 +2826,16 @@ function getRecoverableWithSubdust(vtxos, dustAmount) {
|
|
|
2831
2826
|
}
|
|
2832
2827
|
function isVtxoExpiringSoon(vtxo, thresholdMs) {
|
|
2833
2828
|
const realThresholdMs = thresholdMs <= 100 ? DEFAULT_THRESHOLD_MS : thresholdMs;
|
|
2834
|
-
const
|
|
2835
|
-
if (
|
|
2836
|
-
const expireAt = new Date(batchExpiry);
|
|
2837
|
-
if (expireAt.getFullYear() < 2025) return false;
|
|
2829
|
+
const expiresAt = normalizeVtxo(vtxo).expiresAt;
|
|
2830
|
+
if (expiresAt === void 0) return false;
|
|
2838
2831
|
const now = Date.now();
|
|
2832
|
+
const batchExpiry = expiresAt.getTime();
|
|
2839
2833
|
if (batchExpiry <= now) return false;
|
|
2840
2834
|
return batchExpiry - now <= realThresholdMs;
|
|
2841
2835
|
}
|
|
2842
|
-
function getExpiringAndRecoverableVtxos(vtxos, thresholdMs, dustAmount) {
|
|
2836
|
+
function getExpiringAndRecoverableVtxos(vtxos, thresholdMs, dustAmount, now) {
|
|
2843
2837
|
return vtxos.filter(
|
|
2844
|
-
(vtxo) => isVtxoExpiringSoon(vtxo, thresholdMs) ||
|
|
2838
|
+
(vtxo) => isVtxoExpiringSoon(vtxo, thresholdMs) || canRecoverOnchain(vtxo, now) || isSubdust(vtxo, dustAmount)
|
|
2845
2839
|
);
|
|
2846
2840
|
}
|
|
2847
2841
|
function isMigrationCapable(wallet) {
|
|
@@ -2990,7 +2984,8 @@ var VtxoManager = class _VtxoManager {
|
|
|
2990
2984
|
withUnrolled: false
|
|
2991
2985
|
});
|
|
2992
2986
|
const dustAmount = getDustAmount(this.wallet);
|
|
2993
|
-
|
|
2987
|
+
const now = await fetchTimeHeight(this.wallet);
|
|
2988
|
+
let { vtxosToRecover, totalAmount } = getRecoverableWithSubdust(allVtxos, dustAmount, now);
|
|
2994
2989
|
if (vtxosToRecover.length === 0) {
|
|
2995
2990
|
throw new Error("No recoverable VTXOs found");
|
|
2996
2991
|
}
|
|
@@ -2999,7 +2994,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
2999
2994
|
const capped = capSettlementBatch(byValueDescending(vtxosToRecover), vtxoMaxAmount);
|
|
3000
2995
|
if (capped.length < vtxosToRecover.length) {
|
|
3001
2996
|
const recoverableCount = vtxosToRecover.length;
|
|
3002
|
-
({ vtxosToRecover, totalAmount } = getRecoverableWithSubdust(capped, dustAmount));
|
|
2997
|
+
({ vtxosToRecover, totalAmount } = getRecoverableWithSubdust(capped, dustAmount, now));
|
|
3003
2998
|
if (vtxosToRecover.length === 0) {
|
|
3004
2999
|
throw new Error(
|
|
3005
3000
|
`Capped recovery batch (highest-value subset of ${recoverableCount} recoverable VTXOs within the ${MAX_VTXOS_PER_SETTLEMENT}-input and ${vtxoMaxAmount}-sat limits) is below the dust threshold ${dustAmount}`
|
|
@@ -3051,7 +3046,8 @@ var VtxoManager = class _VtxoManager {
|
|
|
3051
3046
|
const dustAmount = getDustAmount(this.wallet);
|
|
3052
3047
|
const { vtxosToRecover, includesSubdust, totalAmount } = getRecoverableWithSubdust(
|
|
3053
3048
|
allVtxos,
|
|
3054
|
-
dustAmount
|
|
3049
|
+
dustAmount,
|
|
3050
|
+
await fetchTimeHeight(this.wallet)
|
|
3055
3051
|
);
|
|
3056
3052
|
const subdustAmount = vtxosToRecover.filter((v) => BigInt(v.value) < dustAmount).reduce((sum, v) => sum + BigInt(v.value), 0n);
|
|
3057
3053
|
return {
|
|
@@ -3085,6 +3081,16 @@ var VtxoManager = class _VtxoManager {
|
|
|
3085
3081
|
* ```
|
|
3086
3082
|
*/
|
|
3087
3083
|
async getExpiringVtxos(thresholdMs) {
|
|
3084
|
+
return this.selectExpiringVtxos(thresholdMs);
|
|
3085
|
+
}
|
|
3086
|
+
/**
|
|
3087
|
+
* {@link getExpiringVtxos}, against a caller-supplied chain tip.
|
|
3088
|
+
*
|
|
3089
|
+
* The settle paths select, re-select after pre-flight, and sort by expiry within one pass;
|
|
3090
|
+
* each of those judges expiry, so they share one tip rather than fetching (and possibly
|
|
3091
|
+
* disagreeing on) one apiece. Fetches its own when `now` is omitted.
|
|
3092
|
+
*/
|
|
3093
|
+
async selectExpiringVtxos(thresholdMs, now) {
|
|
3088
3094
|
if (this.settlementConfig === false && thresholdMs === void 0) {
|
|
3089
3095
|
return [];
|
|
3090
3096
|
}
|
|
@@ -3097,7 +3103,12 @@ var VtxoManager = class _VtxoManager {
|
|
|
3097
3103
|
} else {
|
|
3098
3104
|
threshold = this.renewalConfig?.thresholdMs ?? DEFAULT_RENEWAL_CONFIG.thresholdMs;
|
|
3099
3105
|
}
|
|
3100
|
-
return getExpiringAndRecoverableVtxos(
|
|
3106
|
+
return getExpiringAndRecoverableVtxos(
|
|
3107
|
+
vtxos,
|
|
3108
|
+
threshold,
|
|
3109
|
+
getDustAmount(this.wallet),
|
|
3110
|
+
now ?? await fetchTimeHeight(this.wallet)
|
|
3111
|
+
);
|
|
3101
3112
|
}
|
|
3102
3113
|
/**
|
|
3103
3114
|
* Renew expiring virtual outputs by settling them back to the wallet's address
|
|
@@ -3150,17 +3161,18 @@ var VtxoManager = class _VtxoManager {
|
|
|
3150
3161
|
} else {
|
|
3151
3162
|
threshold = DEFAULT_RENEWAL_CONFIG.thresholdMs;
|
|
3152
3163
|
}
|
|
3153
|
-
|
|
3164
|
+
const now = await fetchTimeHeight(this.wallet);
|
|
3165
|
+
let vtxos = await this.selectExpiringVtxos(threshold, now);
|
|
3154
3166
|
if (vtxos.length === 0) {
|
|
3155
3167
|
throw new Error("No VTXOs available to renew");
|
|
3156
3168
|
}
|
|
3157
|
-
vtxos = await this.revalidateBeforeSettle(vtxos, threshold);
|
|
3169
|
+
vtxos = await this.revalidateBeforeSettle(vtxos, threshold, now);
|
|
3158
3170
|
if (vtxos.length === 0) {
|
|
3159
3171
|
throw new Error("No VTXOs available to renew");
|
|
3160
3172
|
}
|
|
3161
3173
|
const info = await this.getInfoProvider()?.getInfo();
|
|
3162
3174
|
const vtxoMaxAmount = info?.vtxoMaxAmount ?? -1n;
|
|
3163
|
-
const capped = capSettlementBatch(byExpiryAscending(vtxos), vtxoMaxAmount);
|
|
3175
|
+
const capped = capSettlementBatch(byExpiryAscending(vtxos, now), vtxoMaxAmount);
|
|
3164
3176
|
if (vtxoMaxAmount >= 0n) {
|
|
3165
3177
|
const oversized = vtxos.filter((vtxo) => BigInt(vtxo.value) > vtxoMaxAmount);
|
|
3166
3178
|
if (oversized.length > 0) {
|
|
@@ -3421,6 +3433,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
3421
3433
|
signers: reports
|
|
3422
3434
|
};
|
|
3423
3435
|
if (vtxoMigratable.length > 0) {
|
|
3436
|
+
const now = await fetchTimeHeight(this.wallet);
|
|
3424
3437
|
report.vtxos = await this.runMigrationLeg(
|
|
3425
3438
|
vtxoMigratable,
|
|
3426
3439
|
(c) => c.vtxo.value,
|
|
@@ -3428,7 +3441,11 @@ var VtxoManager = class _VtxoManager {
|
|
|
3428
3441
|
vtxoMaxAmount,
|
|
3429
3442
|
dustAmount,
|
|
3430
3443
|
"VTXO",
|
|
3431
|
-
(capped) => wallet.sendSelectedVtxosToSelf(
|
|
3444
|
+
(capped) => wallet.sendSelectedVtxosToSelf(
|
|
3445
|
+
capped.map((c) => c.vtxo),
|
|
3446
|
+
now
|
|
3447
|
+
),
|
|
3448
|
+
(c) => canMigrateBySend(c.vtxo, now)
|
|
3432
3449
|
);
|
|
3433
3450
|
}
|
|
3434
3451
|
if (boardingMigratable.length > 0) {
|
|
@@ -3468,10 +3485,22 @@ var VtxoManager = class _VtxoManager {
|
|
|
3468
3485
|
* the server ceiling by the cap). The dust floor guards the degenerate cases
|
|
3469
3486
|
* where every input was oversized or the whole holding sums below dust.
|
|
3470
3487
|
*/
|
|
3471
|
-
async runMigrationLeg(candidates, valueOf, toRef, vtxoMaxAmount, dustAmount, legName, submit) {
|
|
3488
|
+
async runMigrationLeg(candidates, valueOf, toRef, vtxoMaxAmount, dustAmount, legName, submit, eligible) {
|
|
3489
|
+
const notSpendableRefs = [];
|
|
3490
|
+
const migratable = eligible ? candidates.filter((c) => {
|
|
3491
|
+
if (eligible(c)) return true;
|
|
3492
|
+
notSpendableRefs.push(toRef(c));
|
|
3493
|
+
return false;
|
|
3494
|
+
}) : candidates;
|
|
3495
|
+
if (notSpendableRefs.length > 0) {
|
|
3496
|
+
console.warn(
|
|
3497
|
+
`Deprecated-signer migration (${legName}): ${notSpendableRefs.length} input(s) are no longer cooperatively spendable at the current chain tip and were excluded; they recover through the sweep/recovery path instead.`
|
|
3498
|
+
);
|
|
3499
|
+
}
|
|
3500
|
+
const notSpendableField = notSpendableRefs.length > 0 ? { notSpendableOffchain: notSpendableRefs } : {};
|
|
3472
3501
|
const oversizedRefs = [];
|
|
3473
3502
|
const sized = [];
|
|
3474
|
-
for (const c of
|
|
3503
|
+
for (const c of migratable) {
|
|
3475
3504
|
if (vtxoMaxAmount >= 0n && BigInt(valueOf(c)) > vtxoMaxAmount) {
|
|
3476
3505
|
oversizedRefs.push(toRef(c));
|
|
3477
3506
|
} else {
|
|
@@ -3491,11 +3520,12 @@ var VtxoManager = class _VtxoManager {
|
|
|
3491
3520
|
const deferred = sized.length - capped.length;
|
|
3492
3521
|
const totalAmount = capped.reduce((sum, c) => sum + BigInt(valueOf(c)), 0n);
|
|
3493
3522
|
if (totalAmount < dustAmount) {
|
|
3494
|
-
const
|
|
3523
|
+
const skipped = sized.length > 0 ? "below-dust" : oversizedRefs.length > 0 ? "oversized-only" : notSpendableRefs.length > 0 ? "not-spendable-only" : "below-dust";
|
|
3495
3524
|
return {
|
|
3496
3525
|
migrated: [],
|
|
3497
|
-
skipped
|
|
3498
|
-
...oversizedField
|
|
3526
|
+
skipped,
|
|
3527
|
+
...oversizedField,
|
|
3528
|
+
...notSpendableField
|
|
3499
3529
|
};
|
|
3500
3530
|
}
|
|
3501
3531
|
try {
|
|
@@ -3504,13 +3534,15 @@ var VtxoManager = class _VtxoManager {
|
|
|
3504
3534
|
txid,
|
|
3505
3535
|
migrated: capped.map(toRef),
|
|
3506
3536
|
...deferred > 0 ? { deferred } : {},
|
|
3507
|
-
...oversizedField
|
|
3537
|
+
...oversizedField,
|
|
3538
|
+
...notSpendableField
|
|
3508
3539
|
};
|
|
3509
3540
|
} catch (e) {
|
|
3510
3541
|
return {
|
|
3511
3542
|
migrated: [],
|
|
3512
3543
|
error: e instanceof Error ? e.message : String(e),
|
|
3513
|
-
...oversizedField
|
|
3544
|
+
...oversizedField,
|
|
3545
|
+
...notSpendableField
|
|
3514
3546
|
};
|
|
3515
3547
|
}
|
|
3516
3548
|
}
|
|
@@ -3538,8 +3570,8 @@ var VtxoManager = class _VtxoManager {
|
|
|
3538
3570
|
if (!serverPubKey) continue;
|
|
3539
3571
|
const cls = classifyAgainstSignerSet(serverPubKey, signerSet, nowSeconds);
|
|
3540
3572
|
if (cls.status === "CURRENT") continue;
|
|
3541
|
-
const recoverable = vtxos.filter((v) =>
|
|
3542
|
-
const spendable = vtxos.filter((v) =>
|
|
3573
|
+
const recoverable = vtxos.filter((v) => v.isSwept && !hasTerminalSpend(v));
|
|
3574
|
+
const spendable = vtxos.filter((v) => !hasTerminalSpend(v) && !v.isSwept);
|
|
3543
3575
|
const value = spendable.reduce((sum, v) => sum + v.value, 0);
|
|
3544
3576
|
let recoverableCount = 0;
|
|
3545
3577
|
let recoverableValue = 0;
|
|
@@ -3552,7 +3584,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
3552
3584
|
awaitingSweepCount = spendable.length;
|
|
3553
3585
|
awaitingSweepValue = value;
|
|
3554
3586
|
for (const v of spendable) {
|
|
3555
|
-
const exp = v
|
|
3587
|
+
const exp = toBatchExpiry(v);
|
|
3556
3588
|
if (exp !== void 0 && (nextSweepEta === void 0 || exp < nextSweepEta)) {
|
|
3557
3589
|
nextSweepEta = exp;
|
|
3558
3590
|
}
|
|
@@ -3588,7 +3620,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
3588
3620
|
}
|
|
3589
3621
|
if (isCooperativelyMigratable(cls.status)) {
|
|
3590
3622
|
for (const v of spendable) {
|
|
3591
|
-
if (
|
|
3623
|
+
if (v.expiresAt === void 0 && v.expiresAtHeight === void 0) continue;
|
|
3592
3624
|
migratable.push({ vtxo: v, classification: cls });
|
|
3593
3625
|
}
|
|
3594
3626
|
} else if (cls.status === "EXPIRED") {
|
|
@@ -3966,7 +3998,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
3966
3998
|
* candidates and lets the post-submit `VTXO_ALREADY_SPENT` recovery
|
|
3967
3999
|
* handle whatever slipped through.
|
|
3968
4000
|
*/
|
|
3969
|
-
async revalidateBeforeSettle(candidates, thresholdMs) {
|
|
4001
|
+
async revalidateBeforeSettle(candidates, thresholdMs, now) {
|
|
3970
4002
|
if (candidates.length === 0) return candidates;
|
|
3971
4003
|
try {
|
|
3972
4004
|
const cm = await this.wallet.getContractManager();
|
|
@@ -3976,7 +4008,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
3976
4008
|
return candidates;
|
|
3977
4009
|
}
|
|
3978
4010
|
try {
|
|
3979
|
-
const refreshed = await this.
|
|
4011
|
+
const refreshed = await this.selectExpiringVtxos(thresholdMs, now);
|
|
3980
4012
|
const candidateKeys = new Set(candidates.map((v) => `${v.txid}:${v.vout}`));
|
|
3981
4013
|
return refreshed.filter((v) => candidateKeys.has(`${v.txid}:${v.vout}`));
|
|
3982
4014
|
} catch (e) {
|
|
@@ -4094,10 +4126,12 @@ var VtxoManager = class _VtxoManager {
|
|
|
4094
4126
|
(u) => u.status.confirmed && !this.knownBoardingUtxos.has(`${u.txid}:${u.vout}`) && !expiredSet.has(`${u.txid}:${u.vout}`)
|
|
4095
4127
|
);
|
|
4096
4128
|
let expiringVtxos = [];
|
|
4129
|
+
let now;
|
|
4097
4130
|
if (!this.renewalInProgress) {
|
|
4098
4131
|
try {
|
|
4099
|
-
|
|
4100
|
-
expiringVtxos = await this.
|
|
4132
|
+
now = await fetchTimeHeight(this.wallet);
|
|
4133
|
+
expiringVtxos = await this.selectExpiringVtxos(void 0, now);
|
|
4134
|
+
expiringVtxos = await this.revalidateBeforeSettle(expiringVtxos, void 0, now);
|
|
4101
4135
|
} catch (e) {
|
|
4102
4136
|
console.error("Error fetching expiring VTXOs:", e);
|
|
4103
4137
|
}
|
|
@@ -4129,17 +4163,11 @@ var VtxoManager = class _VtxoManager {
|
|
|
4129
4163
|
totalAmount += BigInt(u.value) - BigInt(inputFee.satoshis);
|
|
4130
4164
|
}
|
|
4131
4165
|
const filteredVtxos = [];
|
|
4132
|
-
for (const v of byExpiryAscending(expiringVtxos)) {
|
|
4166
|
+
for (const v of byExpiryAscending(expiringVtxos, now ?? { timestamp: /* @__PURE__ */ new Date() })) {
|
|
4133
4167
|
if (filteredVtxos.length >= MAX_VTXOS_PER_SETTLEMENT) {
|
|
4134
4168
|
break;
|
|
4135
4169
|
}
|
|
4136
|
-
const inputFee = estimator.evalOffchainInput(
|
|
4137
|
-
amount: BigInt(v.value),
|
|
4138
|
-
type: v.virtualStatus.state === "swept" ? "recoverable" : "vtxo",
|
|
4139
|
-
weight: 0,
|
|
4140
|
-
birth: v.createdAt,
|
|
4141
|
-
expiry: v.virtualStatus.batchExpiry ? new Date(v.virtualStatus.batchExpiry) : void 0
|
|
4142
|
-
});
|
|
4170
|
+
const inputFee = estimator.evalOffchainInput(toOffchainInputFeeParams(v));
|
|
4143
4171
|
if (inputFee.satoshis >= v.value) {
|
|
4144
4172
|
continue;
|
|
4145
4173
|
}
|
|
@@ -4343,8 +4371,8 @@ function readUInt32BE(array, offset) {
|
|
|
4343
4371
|
function noteTapscript(preimageHash) {
|
|
4344
4372
|
return Script.encode(["SHA256", preimageHash, "EQUAL"]);
|
|
4345
4373
|
}
|
|
4346
|
-
var
|
|
4347
|
-
constructor(privateKey, serverPubKey, csvTimelock, hrp =
|
|
4374
|
+
var ArkadeCash = class _ArkadeCash {
|
|
4375
|
+
constructor(privateKey, serverPubKey, csvTimelock, hrp = _ArkadeCash.DefaultHRP) {
|
|
4348
4376
|
this.csvTimelock = csvTimelock;
|
|
4349
4377
|
this.hrp = hrp;
|
|
4350
4378
|
if (privateKey.length !== 32) {
|
|
@@ -4363,7 +4391,7 @@ var ArkCash = class _ArkCash {
|
|
|
4363
4391
|
}
|
|
4364
4392
|
csvTimelock;
|
|
4365
4393
|
hrp;
|
|
4366
|
-
static DefaultHRP = "
|
|
4394
|
+
static DefaultHRP = "arkadecash";
|
|
4367
4395
|
static Version = 0;
|
|
4368
4396
|
static PayloadLength = 1 + 32 + 32 + 4;
|
|
4369
4397
|
// 69 bytes
|
|
@@ -4386,32 +4414,32 @@ var ArkCash = class _ArkCash {
|
|
|
4386
4414
|
return this._publicKey.slice();
|
|
4387
4415
|
}
|
|
4388
4416
|
static generate(serverPubKey, csvTimelock, hrp) {
|
|
4389
|
-
return new
|
|
4417
|
+
return new _ArkadeCash(randomPrivateKeyBytes(), serverPubKey, csvTimelock, hrp);
|
|
4390
4418
|
}
|
|
4391
4419
|
static fromString(encoded) {
|
|
4392
4420
|
const decoded = bech32m.decodeUnsafe(encoded.trim().toLowerCase(), 1023);
|
|
4393
4421
|
if (!decoded) {
|
|
4394
|
-
throw new Error("Invalid
|
|
4422
|
+
throw new Error("Invalid arkadeCash string: failed to decode bech32m");
|
|
4395
4423
|
}
|
|
4396
4424
|
const data = new Uint8Array(bech32m.fromWords(decoded.words));
|
|
4397
|
-
if (data.length !==
|
|
4425
|
+
if (data.length !== _ArkadeCash.PayloadLength) {
|
|
4398
4426
|
throw new Error(
|
|
4399
|
-
`Invalid
|
|
4427
|
+
`Invalid arkadeCash data length: expected ${_ArkadeCash.PayloadLength} bytes, got ${data.length}`
|
|
4400
4428
|
);
|
|
4401
4429
|
}
|
|
4402
4430
|
const version = data[0];
|
|
4403
|
-
if (version !==
|
|
4404
|
-
throw new Error(`Unsupported
|
|
4431
|
+
if (version !== _ArkadeCash.Version) {
|
|
4432
|
+
throw new Error(`Unsupported arkadeCash version: ${version}`);
|
|
4405
4433
|
}
|
|
4406
4434
|
const privateKey = data.slice(1, 33);
|
|
4407
4435
|
const serverPubKey = data.slice(33, 65);
|
|
4408
4436
|
const sequence = new DataView(data.buffer, data.byteOffset + 65, 4).getUint32(0, false);
|
|
4409
4437
|
const csvTimelock = sequenceToTimelock(sequence);
|
|
4410
|
-
return new
|
|
4438
|
+
return new _ArkadeCash(privateKey, serverPubKey, csvTimelock, decoded.prefix);
|
|
4411
4439
|
}
|
|
4412
4440
|
toString() {
|
|
4413
|
-
const data = new Uint8Array(
|
|
4414
|
-
data[0] =
|
|
4441
|
+
const data = new Uint8Array(_ArkadeCash.PayloadLength);
|
|
4442
|
+
data[0] = _ArkadeCash.Version;
|
|
4415
4443
|
data.set(this._privateKey, 1);
|
|
4416
4444
|
data.set(this._serverPubKey, 33);
|
|
4417
4445
|
const sequence = timelockToSequence(this.csvTimelock);
|
|
@@ -5497,13 +5525,13 @@ function subtractAssets(spent, change) {
|
|
|
5497
5525
|
return Array.from(map, ([assetId, amount]) => ({ assetId, amount }));
|
|
5498
5526
|
}
|
|
5499
5527
|
async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnore, getTxCreatedAt) {
|
|
5500
|
-
const fromOldestVtxo =
|
|
5528
|
+
const fromOldestVtxo = vtxos.map(normalizeVtxo).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
|
|
5501
5529
|
const unmatchedSettledBoardingTxs = allBoardingTxs.filter(isSettledBoardingReceive).sort((a, b) => a.createdAt - b.createdAt);
|
|
5502
5530
|
const sent = [];
|
|
5503
5531
|
let received = [];
|
|
5504
5532
|
for (const vtxo of fromOldestVtxo) {
|
|
5505
5533
|
if (vtxo.status.isLeaf) {
|
|
5506
|
-
const commitmentTxid = vtxo.
|
|
5534
|
+
const commitmentTxid = vtxo.commitmentTxIds[0];
|
|
5507
5535
|
const vtxoCreatedAt = vtxo.createdAt.getTime();
|
|
5508
5536
|
const ignoredCommitment = commitmentsToIgnore.has(commitmentTxid) || !!vtxo.settledBy && commitmentsToIgnore.has(vtxo.settledBy);
|
|
5509
5537
|
if (ignoredCommitment) {
|
|
@@ -5511,7 +5539,7 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
|
|
|
5511
5539
|
unmatchedSettledBoardingTxs,
|
|
5512
5540
|
(tx) => tx.createdAt <= vtxoCreatedAt && (tx.key.commitmentTxid === commitmentTxid || tx.key.commitmentTxid === vtxo.settledBy)
|
|
5513
5541
|
);
|
|
5514
|
-
} else if (fromOldestVtxo.filter((v) => v.settledBy === vtxo.
|
|
5542
|
+
} else if (fromOldestVtxo.filter((v) => v.settledBy === vtxo.commitmentTxIds[0]).length === 0) {
|
|
5515
5543
|
const duplicateBoardingReceive = consumeBoardingReceive(
|
|
5516
5544
|
unmatchedSettledBoardingTxs,
|
|
5517
5545
|
(tx) => tx.amount === vtxo.value && tx.createdAt <= vtxoCreatedAt
|
|
@@ -5574,7 +5602,7 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
|
|
|
5574
5602
|
}
|
|
5575
5603
|
if (vtxo.settledBy && !commitmentsToIgnore.has(vtxo.settledBy) && !sent.some((s) => s.key.commitmentTxid === vtxo.settledBy)) {
|
|
5576
5604
|
const changes = fromOldestVtxo.filter(
|
|
5577
|
-
(v) => v.status.isLeaf && v.
|
|
5605
|
+
(v) => v.status.isLeaf && v.commitmentTxIds.length > 0 && v.commitmentTxIds.every((_) => vtxo.settledBy === _)
|
|
5578
5606
|
);
|
|
5579
5607
|
const forfeitVtxos = fromOldestVtxo.filter((v) => v.settledBy === vtxo.settledBy);
|
|
5580
5608
|
const forfeitAmount = forfeitVtxos.reduce((acc, v) => acc + v.value, 0);
|
|
@@ -5963,7 +5991,7 @@ var DelegateManagerImpl = class {
|
|
|
5963
5991
|
const destinationScript = ArkAddress.decode(destination).pkScript;
|
|
5964
5992
|
const arkInfo = await this.arkInfoProvider.getInfo();
|
|
5965
5993
|
const delegateInfo = await this.delegateProvider.getDelegateInfo();
|
|
5966
|
-
const eligible = vtxos.filter(
|
|
5994
|
+
const eligible = vtxos.map(normalizeVtxo).filter(
|
|
5967
5995
|
(v) => isAnnotated(v) && findDelegateTapLeaf(v, delegateInfo.pubkey) !== void 0
|
|
5968
5996
|
);
|
|
5969
5997
|
if (eligible.length === 0) {
|
|
@@ -5988,14 +6016,15 @@ var DelegateManagerImpl = class {
|
|
|
5988
6016
|
}
|
|
5989
6017
|
return { delegated: eligible, failed: [] };
|
|
5990
6018
|
}
|
|
6019
|
+
const now = { timestamp: /* @__PURE__ */ new Date() };
|
|
5991
6020
|
const groupByExpiry = /* @__PURE__ */ new Map();
|
|
5992
6021
|
let recoverableVtxos = [];
|
|
5993
6022
|
for (const vtxo of eligible) {
|
|
5994
|
-
if (
|
|
6023
|
+
if (canRecoverOnchain(vtxo, now)) {
|
|
5995
6024
|
recoverableVtxos.push(vtxo);
|
|
5996
6025
|
continue;
|
|
5997
6026
|
}
|
|
5998
|
-
const expiry = vtxo
|
|
6027
|
+
const expiry = toBatchExpiry(vtxo);
|
|
5999
6028
|
if (!expiry) continue;
|
|
6000
6029
|
const dayKey = getDayTimestamp(expiry);
|
|
6001
6030
|
groupByExpiry.set(dayKey, [...groupByExpiry.get(dayKey) ?? [], vtxo]);
|
|
@@ -6059,10 +6088,8 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
|
|
|
6059
6088
|
throw new Error("unable to delegate: delegate provider not configured");
|
|
6060
6089
|
}
|
|
6061
6090
|
if (!delegateAt) {
|
|
6062
|
-
const
|
|
6063
|
-
|
|
6064
|
-
Number.MAX_SAFE_INTEGER
|
|
6065
|
-
);
|
|
6091
|
+
const now = { timestamp: /* @__PURE__ */ new Date() };
|
|
6092
|
+
const expiryTimestamp = vtxos.filter((coin) => !canRecoverOnchain(coin, now) && toBatchExpiry(coin)).reduce((min, coin) => Math.min(min, toBatchExpiry(coin)), Number.MAX_SAFE_INTEGER);
|
|
6066
6093
|
if (!expiryTimestamp || expiryTimestamp === Number.MAX_SAFE_INTEGER) {
|
|
6067
6094
|
delegateAt = new Date(Date.now() + 1 * 60 * 1e3);
|
|
6068
6095
|
} else {
|
|
@@ -6091,11 +6118,8 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
|
|
|
6091
6118
|
let amount = 0n;
|
|
6092
6119
|
for (const coin of vtxos) {
|
|
6093
6120
|
const inputFee = estimator.evalOffchainInput({
|
|
6094
|
-
|
|
6095
|
-
type: "vtxo"
|
|
6096
|
-
weight: 0,
|
|
6097
|
-
birth: coin.createdAt,
|
|
6098
|
-
expiry: coin.virtualStatus.batchExpiry ? new Date(coin.virtualStatus.batchExpiry) : void 0
|
|
6121
|
+
...toOffchainInputFeeParams(coin),
|
|
6122
|
+
type: "vtxo"
|
|
6099
6123
|
});
|
|
6100
6124
|
if (inputFee.value >= coin.value) {
|
|
6101
6125
|
continue;
|
|
@@ -6144,7 +6168,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
|
|
|
6144
6168
|
Address(getNetwork(network)).decode(forfeitAddress)
|
|
6145
6169
|
);
|
|
6146
6170
|
const forfeits = await Promise.all(
|
|
6147
|
-
vtxos.filter((v) => !
|
|
6171
|
+
vtxos.filter((v) => !canRecoverOnchain(v, { timestamp: /* @__PURE__ */ new Date() })).map(async (coin) => {
|
|
6148
6172
|
const forfeit = await makeDelegateForfeitTx(
|
|
6149
6173
|
coin,
|
|
6150
6174
|
dust,
|
|
@@ -6932,7 +6956,8 @@ function validateVtxosForScript(vtxos, script, context) {
|
|
|
6932
6956
|
);
|
|
6933
6957
|
}
|
|
6934
6958
|
async function getVtxosForContract(repo, contract) {
|
|
6935
|
-
|
|
6959
|
+
const vtxos = repo.getVtxosForScript ? await repo.getVtxosForScript(contract.script) : filterVtxosForScript(await repo.getVtxos(contract.address), contract.script);
|
|
6960
|
+
return vtxos.map(normalizeVtxo);
|
|
6936
6961
|
}
|
|
6937
6962
|
async function saveVtxosForContract(repo, contract, vtxos) {
|
|
6938
6963
|
if (repo.saveVtxosForScript) {
|
|
@@ -7136,7 +7161,7 @@ var deserializeTapLeaf = (t) => {
|
|
|
7136
7161
|
const s = hex.decode(t.s);
|
|
7137
7162
|
return [cb, s];
|
|
7138
7163
|
};
|
|
7139
|
-
var deserializeVtxo = (o) => ({
|
|
7164
|
+
var deserializeVtxo = (o) => normalizeVtxo({
|
|
7140
7165
|
...o,
|
|
7141
7166
|
createdAt: new Date(o.createdAt),
|
|
7142
7167
|
tapTree: hex.decode(o.tapTree),
|
|
@@ -7735,50 +7760,12 @@ function getLifecycleWeight(v) {
|
|
|
7735
7760
|
if (v.arkTxId) weight += 2;
|
|
7736
7761
|
return weight;
|
|
7737
7762
|
}
|
|
7763
|
+
|
|
7764
|
+
// src/repositories/migrations/walletRepositoryImpl.ts
|
|
7738
7765
|
var getVtxosStorageKey = (address) => `vtxos:${address}`;
|
|
7739
7766
|
var getUtxosStorageKey = (address) => `utxos:${address}`;
|
|
7740
7767
|
var getTransactionsStorageKey = (address) => `tx:${address}`;
|
|
7741
7768
|
var walletStateStorageKey = "wallet:state";
|
|
7742
|
-
var serializeVtxo2 = (v) => ({
|
|
7743
|
-
...v,
|
|
7744
|
-
tapTree: hex.encode(v.tapTree),
|
|
7745
|
-
forfeitTapLeafScript: serializeTapLeaf2(v.forfeitTapLeafScript),
|
|
7746
|
-
intentTapLeafScript: serializeTapLeaf2(v.intentTapLeafScript),
|
|
7747
|
-
extraWitness: v.extraWitness?.map(hex.encode),
|
|
7748
|
-
assets: serializeAssets(v.assets)
|
|
7749
|
-
});
|
|
7750
|
-
var serializeUtxo2 = (u) => ({
|
|
7751
|
-
...u,
|
|
7752
|
-
tapTree: hex.encode(u.tapTree),
|
|
7753
|
-
forfeitTapLeafScript: serializeTapLeaf2(u.forfeitTapLeafScript),
|
|
7754
|
-
intentTapLeafScript: serializeTapLeaf2(u.intentTapLeafScript),
|
|
7755
|
-
extraWitness: u.extraWitness?.map(hex.encode)
|
|
7756
|
-
});
|
|
7757
|
-
var deserializeVtxo2 = (o) => ({
|
|
7758
|
-
...o,
|
|
7759
|
-
createdAt: new Date(o.createdAt),
|
|
7760
|
-
tapTree: hex.decode(o.tapTree),
|
|
7761
|
-
forfeitTapLeafScript: deserializeTapLeaf2(o.forfeitTapLeafScript),
|
|
7762
|
-
intentTapLeafScript: deserializeTapLeaf2(o.intentTapLeafScript),
|
|
7763
|
-
extraWitness: o.extraWitness?.map(hex.decode),
|
|
7764
|
-
assets: deserializeAssets(o.assets)
|
|
7765
|
-
});
|
|
7766
|
-
var deserializeUtxo2 = (o) => ({
|
|
7767
|
-
...o,
|
|
7768
|
-
tapTree: hex.decode(o.tapTree),
|
|
7769
|
-
forfeitTapLeafScript: deserializeTapLeaf2(o.forfeitTapLeafScript),
|
|
7770
|
-
intentTapLeafScript: deserializeTapLeaf2(o.intentTapLeafScript),
|
|
7771
|
-
extraWitness: o.extraWitness?.map(hex.decode)
|
|
7772
|
-
});
|
|
7773
|
-
var serializeTapLeaf2 = ([cb, s]) => ({
|
|
7774
|
-
cb: hex.encode(TaprootControlBlock.encode(cb)),
|
|
7775
|
-
s: hex.encode(s)
|
|
7776
|
-
});
|
|
7777
|
-
var deserializeTapLeaf2 = (t) => {
|
|
7778
|
-
const cb = TaprootControlBlock.decode(hex.decode(t.cb));
|
|
7779
|
-
const s = hex.decode(t.s);
|
|
7780
|
-
return [cb, s];
|
|
7781
|
-
};
|
|
7782
7769
|
var WalletRepositoryImpl = class {
|
|
7783
7770
|
version = 1;
|
|
7784
7771
|
storage;
|
|
@@ -7790,7 +7777,7 @@ var WalletRepositoryImpl = class {
|
|
|
7790
7777
|
if (!stored) return [];
|
|
7791
7778
|
try {
|
|
7792
7779
|
const parsed = JSON.parse(stored);
|
|
7793
|
-
return parsed.map(
|
|
7780
|
+
return parsed.map(deserializeVtxo);
|
|
7794
7781
|
} catch (error) {
|
|
7795
7782
|
console.error(`Failed to parse VTXOs for address ${address}:`, error);
|
|
7796
7783
|
return [];
|
|
@@ -7810,7 +7797,7 @@ var WalletRepositoryImpl = class {
|
|
|
7810
7797
|
}
|
|
7811
7798
|
await this.storage.setItem(
|
|
7812
7799
|
getVtxosStorageKey(address),
|
|
7813
|
-
JSON.stringify(storedVtxos.map(
|
|
7800
|
+
JSON.stringify(storedVtxos.map(serializeVtxo))
|
|
7814
7801
|
);
|
|
7815
7802
|
}
|
|
7816
7803
|
async clearVtxos(address) {
|
|
@@ -7824,7 +7811,7 @@ var WalletRepositoryImpl = class {
|
|
|
7824
7811
|
if (!stored) return [];
|
|
7825
7812
|
try {
|
|
7826
7813
|
const parsed = JSON.parse(stored);
|
|
7827
|
-
return parsed.map(
|
|
7814
|
+
return parsed.map(deserializeUtxo);
|
|
7828
7815
|
} catch (error) {
|
|
7829
7816
|
console.error(`Failed to parse UTXOs for address ${address}:`, error);
|
|
7830
7817
|
return [];
|
|
@@ -7844,7 +7831,7 @@ var WalletRepositoryImpl = class {
|
|
|
7844
7831
|
});
|
|
7845
7832
|
await this.storage.setItem(
|
|
7846
7833
|
getUtxosStorageKey(address),
|
|
7847
|
-
JSON.stringify(storedUtxos.map(
|
|
7834
|
+
JSON.stringify(storedUtxos.map(serializeUtxo))
|
|
7848
7835
|
);
|
|
7849
7836
|
}
|
|
7850
7837
|
async clearUtxos(address) {
|
|
@@ -8496,15 +8483,27 @@ var ContractWatcher = class {
|
|
|
8496
8483
|
}
|
|
8497
8484
|
/**
|
|
8498
8485
|
* Handle a subscription update.
|
|
8486
|
+
*
|
|
8487
|
+
* Normalization boundary: `getSubscription` is part of the public `IndexerProvider` interface,
|
|
8488
|
+
* so a consumer implementation may yield legacy-shaped VTXOs. Normalizing on ingest also fixes
|
|
8489
|
+
* the shape of the payloads emitted to external event consumers.
|
|
8499
8490
|
*/
|
|
8500
8491
|
handleSubscriptionUpdate(update) {
|
|
8501
8492
|
if (!this.eventCallback) return;
|
|
8502
8493
|
const timestamp = Date.now();
|
|
8503
8494
|
if (update.newVtxos?.length) {
|
|
8504
|
-
this.processSubscriptionVtxos(
|
|
8495
|
+
this.processSubscriptionVtxos(
|
|
8496
|
+
update.newVtxos.map(normalizeVtxo),
|
|
8497
|
+
"vtxo_received",
|
|
8498
|
+
timestamp
|
|
8499
|
+
);
|
|
8505
8500
|
}
|
|
8506
8501
|
if (update.spentVtxos?.length) {
|
|
8507
|
-
this.processSubscriptionVtxos(
|
|
8502
|
+
this.processSubscriptionVtxos(
|
|
8503
|
+
update.spentVtxos.map(normalizeVtxo),
|
|
8504
|
+
"vtxo_spent",
|
|
8505
|
+
timestamp
|
|
8506
|
+
);
|
|
8508
8507
|
}
|
|
8509
8508
|
}
|
|
8510
8509
|
/**
|
|
@@ -8634,7 +8633,7 @@ async function reconcileIntents(deps) {
|
|
|
8634
8633
|
let vtxosByOutpoint = /* @__PURE__ */ new Map();
|
|
8635
8634
|
if (outpoints.length > 0) {
|
|
8636
8635
|
try {
|
|
8637
|
-
const { vtxos } = await deps.indexerProvider
|
|
8636
|
+
const { vtxos } = await getNormalizedVtxos(deps.indexerProvider, { outpoints });
|
|
8638
8637
|
vtxosByOutpoint = new Map(vtxos.map((v) => [outpointKey(v), v]));
|
|
8639
8638
|
} catch (e) {
|
|
8640
8639
|
console.error("reconcileIntents: failed to fetch input VTXO state", e);
|
|
@@ -8887,9 +8886,10 @@ var ContractManager = class _ContractManager {
|
|
|
8887
8886
|
* Safety-critical invariants (spec §2.C / §4):
|
|
8888
8887
|
* - `opts.materialize(i)` throwing is structural/fatal: it is NOT
|
|
8889
8888
|
* wrapped — it propagates and aborts the scan.
|
|
8890
|
-
* - A `discoverAt` rejection is collected into `handlerErrors` and
|
|
8891
|
-
*
|
|
8892
|
-
*
|
|
8889
|
+
* - A `discoverAt` rejection is collected into `handlerErrors` and makes
|
|
8890
|
+
* its index *indeterminate*: it does NOT advance the gap counter, and
|
|
8891
|
+
* the scan stops verifying there, reporting `truncatedAt`. Only an index
|
|
8892
|
+
* every handler answered for can be a confirmed miss.
|
|
8893
8893
|
* - `persistAndWatchContract` rejecting is operational/fatal and
|
|
8894
8894
|
* propagates (only `discoverAt` is guarded).
|
|
8895
8895
|
* - Within an index the handler probes run concurrently (independent
|
|
@@ -8903,8 +8903,12 @@ var ContractManager = class _ContractManager {
|
|
|
8903
8903
|
* over-scanned, nothing is discarded, and `materialize`/`discoverAt` are
|
|
8904
8904
|
* invoked on exactly the same index set. The window's hits are still
|
|
8905
8905
|
* processed strictly in ascending index order, so the discovered set,
|
|
8906
|
-
* persisted rows, `
|
|
8907
|
-
* identical to the serial path — only the wall-clock
|
|
8906
|
+
* persisted rows, `highestConfirmedUsedIndex`, and `handlerErrors` are
|
|
8907
|
+
* byte-for-byte identical to the serial path — only the wall-clock
|
|
8908
|
+
* differs. Truncation is the one exception: a window's concurrent probes
|
|
8909
|
+
* can surface hits above the failed index that a serial scan would never
|
|
8910
|
+
* have reached, so a truncated batched scan discovers a superset — never
|
|
8911
|
+
* a subset — of the serial one.
|
|
8908
8912
|
*/
|
|
8909
8913
|
async scanContracts(opts) {
|
|
8910
8914
|
const gapLimit = opts.gapLimit ?? 20;
|
|
@@ -8926,7 +8930,8 @@ var ContractManager = class _ContractManager {
|
|
|
8926
8930
|
];
|
|
8927
8931
|
const maxIdx = opts.hd ? SCAN_MAX_INDEX : 0;
|
|
8928
8932
|
const handlerErrors = [];
|
|
8929
|
-
let
|
|
8933
|
+
let highestConfirmedUsedIndex = -1;
|
|
8934
|
+
let truncatedAt;
|
|
8930
8935
|
let unused = 0;
|
|
8931
8936
|
let i = 0;
|
|
8932
8937
|
const probeIndex = async (index) => {
|
|
@@ -8953,6 +8958,7 @@ var ContractManager = class _ContractManager {
|
|
|
8953
8958
|
const index = windowIndices[w];
|
|
8954
8959
|
const probes = windowProbes[w];
|
|
8955
8960
|
let hitAtThisIndex = false;
|
|
8961
|
+
let indeterminate = false;
|
|
8956
8962
|
for (let h = 0; h < discoverables.length; h++) {
|
|
8957
8963
|
const probe = probes[h];
|
|
8958
8964
|
if (!probe.ok) {
|
|
@@ -8961,6 +8967,7 @@ var ContractManager = class _ContractManager {
|
|
|
8961
8967
|
index,
|
|
8962
8968
|
error: probe.error
|
|
8963
8969
|
});
|
|
8970
|
+
indeterminate = true;
|
|
8964
8971
|
continue;
|
|
8965
8972
|
}
|
|
8966
8973
|
for (const c of probe.found) {
|
|
@@ -8968,21 +8975,26 @@ var ContractManager = class _ContractManager {
|
|
|
8968
8975
|
hitAtThisIndex = true;
|
|
8969
8976
|
}
|
|
8970
8977
|
}
|
|
8971
|
-
if (
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
}
|
|
8978
|
+
if (indeterminate && truncatedAt === void 0) truncatedAt = index;
|
|
8979
|
+
if (hitAtThisIndex) highestConfirmedUsedIndex = index;
|
|
8980
|
+
if (truncatedAt !== void 0) continue;
|
|
8981
|
+
if (hitAtThisIndex) unused = 0;
|
|
8982
|
+
else unused += 1;
|
|
8977
8983
|
}
|
|
8984
|
+
if (truncatedAt !== void 0) break;
|
|
8978
8985
|
i = windowEnd + 1;
|
|
8979
8986
|
}
|
|
8980
|
-
if (opts.hd && i > maxIdx && unused < gapLimit) {
|
|
8987
|
+
if (opts.hd && truncatedAt === void 0 && i > maxIdx && unused < gapLimit) {
|
|
8981
8988
|
throw new Error(
|
|
8982
8989
|
`scanContracts: reached SCAN_MAX_INDEX (${SCAN_MAX_INDEX}) without closing the ${gapLimit}-index gap window; a Discoverable handler may be returning unconditional hits`
|
|
8983
8990
|
);
|
|
8984
8991
|
}
|
|
8985
|
-
return {
|
|
8992
|
+
return {
|
|
8993
|
+
lastIndexUsed: highestConfirmedUsedIndex,
|
|
8994
|
+
highestConfirmedUsedIndex,
|
|
8995
|
+
...truncatedAt !== void 0 && { truncatedAt },
|
|
8996
|
+
handlerErrors
|
|
8997
|
+
};
|
|
8986
8998
|
}
|
|
8987
8999
|
/**
|
|
8988
9000
|
* Get contracts with optional filters.
|
|
@@ -9029,7 +9041,9 @@ var ContractManager = class _ContractManager {
|
|
|
9029
9041
|
byScript.set(contract.script, contract);
|
|
9030
9042
|
}
|
|
9031
9043
|
const tapscriptCache = /* @__PURE__ */ new Map();
|
|
9032
|
-
return vtxos.map(
|
|
9044
|
+
return vtxos.map(
|
|
9045
|
+
(vtxo) => extendVirtualCoinForContract(normalizeVtxo(vtxo), byScript, tapscriptCache)
|
|
9046
|
+
);
|
|
9033
9047
|
}
|
|
9034
9048
|
buildContractsDbFilter(filter) {
|
|
9035
9049
|
return {
|
|
@@ -9197,7 +9211,7 @@ var ContractManager = class _ContractManager {
|
|
|
9197
9211
|
}
|
|
9198
9212
|
async refreshOutpoints(outpoints) {
|
|
9199
9213
|
if (outpoints.length === 0) return;
|
|
9200
|
-
const { vtxos } = await this.config.indexerProvider
|
|
9214
|
+
const { vtxos } = await getNormalizedVtxos(this.config.indexerProvider, {
|
|
9201
9215
|
outpoints
|
|
9202
9216
|
});
|
|
9203
9217
|
if (vtxos.length === 0) return;
|
|
@@ -9325,7 +9339,7 @@ var ContractManager = class _ContractManager {
|
|
|
9325
9339
|
async reconcilePendingFrontier(contracts) {
|
|
9326
9340
|
const scripts = contracts.map((c) => c.script);
|
|
9327
9341
|
const scriptToContract = new Map(contracts.map((c) => [c.script, c]));
|
|
9328
|
-
const { vtxos } = await this.config.indexerProvider
|
|
9342
|
+
const { vtxos } = await getNormalizedVtxos(this.config.indexerProvider, {
|
|
9329
9343
|
scripts,
|
|
9330
9344
|
pendingOnly: true
|
|
9331
9345
|
});
|
|
@@ -9416,7 +9430,7 @@ var ContractManager = class _ContractManager {
|
|
|
9416
9430
|
let pageIndex = 0;
|
|
9417
9431
|
let hasMore = true;
|
|
9418
9432
|
while (hasMore) {
|
|
9419
|
-
const { vtxos, page } = await this.config.indexerProvider
|
|
9433
|
+
const { vtxos, page } = await getNormalizedVtxos(this.config.indexerProvider, {
|
|
9420
9434
|
scripts,
|
|
9421
9435
|
...windowOpts,
|
|
9422
9436
|
pageIndex,
|
|
@@ -10233,14 +10247,14 @@ var cashReport = (vtxo, reason) => ({
|
|
|
10233
10247
|
value: vtxo.value,
|
|
10234
10248
|
reason
|
|
10235
10249
|
});
|
|
10236
|
-
var
|
|
10250
|
+
var ArkadeCashCreateError = class extends Error {
|
|
10237
10251
|
constructor(cash, cause) {
|
|
10238
10252
|
super(
|
|
10239
|
-
`Failed to create
|
|
10253
|
+
`Failed to create ArkadeCash: send failed after the note may have been submitted. Recover with claimCash using the token on this error's \`cash\` field.`
|
|
10240
10254
|
);
|
|
10241
10255
|
this.cash = cash;
|
|
10242
10256
|
this.cause = cause;
|
|
10243
|
-
this.name = "
|
|
10257
|
+
this.name = "ArkadeCashCreateError";
|
|
10244
10258
|
}
|
|
10245
10259
|
cash;
|
|
10246
10260
|
cause;
|
|
@@ -10703,20 +10717,21 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
10703
10717
|
}
|
|
10704
10718
|
let recoverable = 0;
|
|
10705
10719
|
let pendingRecovery = 0;
|
|
10706
|
-
const
|
|
10707
|
-
const
|
|
10708
|
-
(coin) => coin
|
|
10720
|
+
const now = { timestamp: /* @__PURE__ */ new Date() };
|
|
10721
|
+
const settled = vtxos.filter(
|
|
10722
|
+
(coin) => canSpendOffchain(coin, now) && !coin.isPreconfirmed && !isPendingRecovery(coin)
|
|
10709
10723
|
).reduce((sum, coin) => sum + coin.value, 0);
|
|
10710
|
-
const
|
|
10711
|
-
(coin) => (coin
|
|
10724
|
+
const preconfirmed = vtxos.filter(
|
|
10725
|
+
(coin) => canSpendOffchain(coin, now) && coin.isPreconfirmed && !isPendingRecovery(coin)
|
|
10712
10726
|
).reduce((sum, coin) => sum + coin.value, 0);
|
|
10713
|
-
|
|
10727
|
+
const available = unlockedVtxos.filter((coin) => canSpendOffchain(coin, now) && !isPendingRecovery(coin)).reduce((sum, coin) => sum + coin.value, 0);
|
|
10728
|
+
recoverable = vtxos.filter((coin) => canRecoverOnchain(coin, now) && !isPendingRecovery(coin)).reduce((sum, coin) => sum + coin.value, 0);
|
|
10714
10729
|
pendingRecovery = vtxos.filter(isPendingRecovery).reduce((sum, coin) => sum + coin.value, 0);
|
|
10715
10730
|
const totalBoarding = confirmed + unconfirmed;
|
|
10716
10731
|
const totalOffchain = settled + preconfirmed + recoverable + pendingRecovery;
|
|
10717
10732
|
const assetBalances = /* @__PURE__ */ new Map();
|
|
10718
10733
|
for (const vtxo of vtxos) {
|
|
10719
|
-
if (
|
|
10734
|
+
if (hasTerminalSpend(vtxo)) continue;
|
|
10720
10735
|
if (vtxo.assets) {
|
|
10721
10736
|
for (const a of vtxo.assets) {
|
|
10722
10737
|
const current = assetBalances.get(a.assetId) ?? 0n;
|
|
@@ -10752,12 +10767,13 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
10752
10767
|
const f = filter ?? { withRecoverable: true, withUnrolled: false };
|
|
10753
10768
|
const contractManager = await this.getContractManager();
|
|
10754
10769
|
const vtxos = await contractManager.getContractsWithVtxos();
|
|
10770
|
+
const now = { timestamp: /* @__PURE__ */ new Date() };
|
|
10755
10771
|
return vtxos.flatMap((_) => _.vtxos).filter((vtxo) => {
|
|
10756
10772
|
if (this._pendingSpendOutpoints.has(`${vtxo.txid}:${vtxo.vout}`)) {
|
|
10757
10773
|
return false;
|
|
10758
10774
|
}
|
|
10759
|
-
if (
|
|
10760
|
-
if (!f.withRecoverable && (
|
|
10775
|
+
if (!hasTerminalSpend(vtxo)) {
|
|
10776
|
+
if (!f.withRecoverable && canRecoverOnchain(vtxo, now)) {
|
|
10761
10777
|
return false;
|
|
10762
10778
|
}
|
|
10763
10779
|
return true;
|
|
@@ -10790,7 +10806,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
10790
10806
|
const response = await contractManager.getContractsWithVtxos();
|
|
10791
10807
|
const allVtxos = response.flatMap((_) => _.vtxos);
|
|
10792
10808
|
const { boardingTxs, commitmentsToIgnore } = await this.getBoardingTxs();
|
|
10793
|
-
const getTxCreatedAt = (txid) => this.indexerProvider
|
|
10809
|
+
const getTxCreatedAt = (txid) => getNormalizedVtxos(this.indexerProvider, { outpoints: [{ txid, vout: 0 }] }).then((res) => res.vtxos[0]?.createdAt.getTime()).catch((err) => {
|
|
10794
10810
|
if (isRetryableProviderError(err)) return void 0;
|
|
10795
10811
|
throw err;
|
|
10796
10812
|
});
|
|
@@ -10866,6 +10882,12 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
10866
10882
|
if (spent && commitmentTxid) {
|
|
10867
10883
|
commitmentsToIgnore.add(commitmentTxid);
|
|
10868
10884
|
}
|
|
10885
|
+
const boardingFacts = {
|
|
10886
|
+
isSpent: spent,
|
|
10887
|
+
isSwept: false,
|
|
10888
|
+
isPreconfirmed: false,
|
|
10889
|
+
commitmentTxIds: spent && commitmentTxid ? [commitmentTxid] : []
|
|
10890
|
+
};
|
|
10869
10891
|
utxos.push({
|
|
10870
10892
|
txid: tx.txid,
|
|
10871
10893
|
vout: i,
|
|
@@ -10875,10 +10897,9 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
10875
10897
|
block_time: tx.status.block_time
|
|
10876
10898
|
},
|
|
10877
10899
|
isUnrolled: true,
|
|
10878
|
-
|
|
10879
|
-
|
|
10880
|
-
|
|
10881
|
-
},
|
|
10900
|
+
...boardingFacts,
|
|
10901
|
+
virtualStatus: toVirtualStatus(boardingFacts),
|
|
10902
|
+
spentBy: "",
|
|
10882
10903
|
createdAt: tx.status.confirmed ? new Date(tx.status.block_time * 1e3) : /* @__PURE__ */ new Date(0),
|
|
10883
10904
|
script: scriptHex
|
|
10884
10905
|
});
|
|
@@ -10892,12 +10913,12 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
10892
10913
|
const tx = {
|
|
10893
10914
|
key: {
|
|
10894
10915
|
boardingTxid: utxo.txid,
|
|
10895
|
-
commitmentTxid: utxo.
|
|
10916
|
+
commitmentTxid: utxo.commitmentTxIds[0] ?? "",
|
|
10896
10917
|
arkTxid: ""
|
|
10897
10918
|
},
|
|
10898
10919
|
amount: utxo.value,
|
|
10899
10920
|
type: "RECEIVED" /* TxReceived */,
|
|
10900
|
-
settled: utxo.
|
|
10921
|
+
settled: utxo.isSpent,
|
|
10901
10922
|
createdAt: utxo.status.block_time ? new Date(utxo.status.block_time * 1e3).getTime() : 0
|
|
10902
10923
|
};
|
|
10903
10924
|
if (!utxo.status.block_time) {
|
|
@@ -11121,11 +11142,11 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
11121
11142
|
/** Fetch Arkade transaction ids that are still pending final settlement. */
|
|
11122
11143
|
async fetchPendingTxs() {
|
|
11123
11144
|
const scripts = await this.getWalletScripts();
|
|
11124
|
-
let { vtxos } = await this.indexerProvider
|
|
11145
|
+
let { vtxos } = await getNormalizedVtxos(this.indexerProvider, {
|
|
11125
11146
|
scripts
|
|
11126
11147
|
});
|
|
11127
11148
|
return vtxos.filter(
|
|
11128
|
-
(vtxo) => vtxo.
|
|
11149
|
+
(vtxo) => (vtxo.isSpent || vtxo.isPreconfirmed && !vtxo.isSwept) && vtxo.arkTxId !== void 0
|
|
11129
11150
|
).map((_) => _.arkTxId);
|
|
11130
11151
|
}
|
|
11131
11152
|
// ========================================================================
|
|
@@ -11224,7 +11245,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
11224
11245
|
});
|
|
11225
11246
|
onVtxosPersisted = async (_contract, vtxos) => {
|
|
11226
11247
|
for (const v of vtxos) {
|
|
11227
|
-
if (v.
|
|
11248
|
+
if (v.isSpent) continue;
|
|
11228
11249
|
await captureExitBranch({
|
|
11229
11250
|
resolver,
|
|
11230
11251
|
repository: virtualTxRepository,
|
|
@@ -11701,14 +11722,14 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11701
11722
|
_restoreInFlight;
|
|
11702
11723
|
_addPendingSpends(inputs) {
|
|
11703
11724
|
for (const input of inputs) {
|
|
11704
|
-
if (
|
|
11725
|
+
if (isVirtualCoin(input)) {
|
|
11705
11726
|
this._pendingSpendOutpoints.add(`${input.txid}:${input.vout}`);
|
|
11706
11727
|
}
|
|
11707
11728
|
}
|
|
11708
11729
|
}
|
|
11709
11730
|
_removePendingSpends(inputs) {
|
|
11710
11731
|
for (const input of inputs) {
|
|
11711
|
-
if (
|
|
11732
|
+
if (isVirtualCoin(input)) {
|
|
11712
11733
|
this._pendingSpendOutpoints.delete(`${input.txid}:${input.vout}`);
|
|
11713
11734
|
}
|
|
11714
11735
|
}
|
|
@@ -11796,15 +11817,22 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11796
11817
|
materialize,
|
|
11797
11818
|
deps
|
|
11798
11819
|
});
|
|
11799
|
-
if (hd && result.
|
|
11800
|
-
await provider.advanceLastIndexUsed(result.
|
|
11820
|
+
if (hd && result.highestConfirmedUsedIndex >= 0) {
|
|
11821
|
+
await provider.advanceLastIndexUsed(result.highestConfirmedUsedIndex);
|
|
11801
11822
|
}
|
|
11802
11823
|
await manager.refreshVtxos({ includeInactive: true });
|
|
11824
|
+
const causes = result.handlerErrors.map(
|
|
11825
|
+
(e) => e.error instanceof Error ? e.error : new Error(String(e.error))
|
|
11826
|
+
);
|
|
11827
|
+
if (result.truncatedAt !== void 0) {
|
|
11828
|
+
throw new AggregateError(
|
|
11829
|
+
causes,
|
|
11830
|
+
`restore: scan truncated at index ${result.truncatedAt}; indices >= ${result.truncatedAt} are unverified (${result.handlerErrors.length} discovery handler failure(s)). Retry is safe (idempotent).`
|
|
11831
|
+
);
|
|
11832
|
+
}
|
|
11803
11833
|
if (result.handlerErrors.length > 0) {
|
|
11804
11834
|
throw new AggregateError(
|
|
11805
|
-
|
|
11806
|
-
(e) => e.error instanceof Error ? e.error : new Error(String(e.error))
|
|
11807
|
-
),
|
|
11835
|
+
causes,
|
|
11808
11836
|
`restore: ${result.handlerErrors.length} discovery handler(s) failed; the gap window may have closed early \u2014 retry is safe (idempotent).`
|
|
11809
11837
|
);
|
|
11810
11838
|
}
|
|
@@ -12116,13 +12144,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12116
12144
|
if (filteredVtxos.length >= MAX_VTXOS_PER_SETTLEMENT) {
|
|
12117
12145
|
break;
|
|
12118
12146
|
}
|
|
12119
|
-
const inputFee = estimator.evalOffchainInput(
|
|
12120
|
-
amount: BigInt(vtxo.value),
|
|
12121
|
-
type: vtxo.virtualStatus.state === "swept" ? "recoverable" : "vtxo",
|
|
12122
|
-
weight: 0,
|
|
12123
|
-
birth: vtxo.createdAt,
|
|
12124
|
-
expiry: vtxo.virtualStatus.batchExpiry ? new Date(vtxo.virtualStatus.batchExpiry) : void 0
|
|
12125
|
-
});
|
|
12147
|
+
const inputFee = estimator.evalOffchainInput(toOffchainInputFeeParams(vtxo));
|
|
12126
12148
|
if (inputFee.satoshis >= vtxo.value) {
|
|
12127
12149
|
continue;
|
|
12128
12150
|
}
|
|
@@ -12338,9 +12360,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12338
12360
|
* renewal / offboard) is not a board and leaves the boarding address
|
|
12339
12361
|
* untouched.
|
|
12340
12362
|
*
|
|
12341
|
-
* Boarding inputs are the non-VTXO coins (no `
|
|
12363
|
+
* Boarding inputs are the non-VTXO coins (no `script`), the same
|
|
12342
12364
|
* discriminator {@link handleSettlementFinalizationEvent} uses; the
|
|
12343
|
-
* `typeof` guard skips arknote
|
|
12365
|
+
* `typeof` guard skips the arknote strings settle also accepts.
|
|
12344
12366
|
*
|
|
12345
12367
|
* No-ops for static / `auto` wallets (no descriptor provider — boarding
|
|
12346
12368
|
* stays on its fixed index-0 address). Best-effort and non-fatal: the
|
|
@@ -12353,7 +12375,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12353
12375
|
async maybeRotateBoardingAfterBoard(inputs) {
|
|
12354
12376
|
if (!this._descriptorProvider) return;
|
|
12355
12377
|
const consumedBoarding = inputs.some(
|
|
12356
|
-
(input) => typeof input !== "string" && !(
|
|
12378
|
+
(input) => typeof input !== "string" && !isVirtualCoin(input)
|
|
12357
12379
|
);
|
|
12358
12380
|
if (!consumedBoarding) return;
|
|
12359
12381
|
try {
|
|
@@ -12364,13 +12386,12 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12364
12386
|
}
|
|
12365
12387
|
async handleSettlementFinalizationEvent(event, inputs, forfeitOutputScript, connectorsGraph) {
|
|
12366
12388
|
const signedForfeits = [];
|
|
12367
|
-
const isVtxo = (input) => "virtualStatus" in input;
|
|
12368
12389
|
let settlementPsbt = Transaction$2.fromPSBT(base64.decode(event.commitmentTx));
|
|
12369
12390
|
let hasBoardingUtxos = false;
|
|
12370
12391
|
let connectorIndex = 0;
|
|
12371
12392
|
const connectorsLeaves = connectorsGraph?.leaves() || [];
|
|
12372
12393
|
for (const input of inputs) {
|
|
12373
|
-
if (!
|
|
12394
|
+
if (!isVirtualCoin(input)) {
|
|
12374
12395
|
for (let i = 0; i < settlementPsbt.inputsLength; i++) {
|
|
12375
12396
|
const settlementInput = settlementPsbt.getInput(i);
|
|
12376
12397
|
if (!settlementInput.txid || settlementInput.index === void 0) {
|
|
@@ -12401,7 +12422,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12401
12422
|
}
|
|
12402
12423
|
continue;
|
|
12403
12424
|
}
|
|
12404
|
-
if (
|
|
12425
|
+
if (canRecoverOnchain(input, { timestamp: /* @__PURE__ */ new Date() }) || isSubdust({ value: input.value }, this.dustAmount)) {
|
|
12405
12426
|
continue;
|
|
12406
12427
|
}
|
|
12407
12428
|
if (connectorsLeaves.length === 0) {
|
|
@@ -12708,13 +12729,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12708
12729
|
const scriptMap = await this.getScriptMap();
|
|
12709
12730
|
const allExtended = [];
|
|
12710
12731
|
const allScripts = [...scriptMap.keys()];
|
|
12711
|
-
const { vtxos: fetchedVtxos } = await this.indexerProvider
|
|
12732
|
+
const { vtxos: fetchedVtxos } = await getNormalizedVtxos(this.indexerProvider, {
|
|
12712
12733
|
scripts: allScripts
|
|
12713
12734
|
});
|
|
12714
12735
|
for (const vtxo of fetchedVtxos) {
|
|
12715
12736
|
const vtxoScript = scriptMap.get(vtxo.script);
|
|
12716
12737
|
if (!vtxoScript) continue;
|
|
12717
|
-
if (vtxo.
|
|
12738
|
+
if (!vtxo.isSpent && !(vtxo.isPreconfirmed && !vtxo.isSwept)) {
|
|
12718
12739
|
continue;
|
|
12719
12740
|
}
|
|
12720
12741
|
allExtended.push({
|
|
@@ -12814,14 +12835,14 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12814
12835
|
}));
|
|
12815
12836
|
}
|
|
12816
12837
|
/**
|
|
12817
|
-
* Create an
|
|
12838
|
+
* Create an ArkadeCash bearer instrument.
|
|
12818
12839
|
*
|
|
12819
12840
|
* Generates a fresh keypair, sends the specified amount to a DefaultVtxo
|
|
12820
|
-
* controlled by the new key, and returns the encoded
|
|
12841
|
+
* controlled by the new key, and returns the encoded arkadeCash string.
|
|
12821
12842
|
* The receiver can claim the funds using `claimCash()` without ever
|
|
12822
12843
|
* sharing their address.
|
|
12823
12844
|
*
|
|
12824
|
-
*
|
|
12845
|
+
* ArkadeCash is a short-lived instrument: it carries a private key, so it is
|
|
12825
12846
|
* meant to be handed over and claimed promptly, not held. A note left
|
|
12826
12847
|
* unclaimed past its batch expiry is swept by the server and `claimCash`
|
|
12827
12848
|
* can only report it, not move it.
|
|
@@ -12829,16 +12850,16 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12829
12850
|
* @param amount - Amount in satoshis to send. Must be a whole number of
|
|
12830
12851
|
* sats at or above the dust threshold — a below-dust amount would mint an
|
|
12831
12852
|
* OP_RETURN output that is unspendable as cash.
|
|
12832
|
-
* @returns The encoded
|
|
12853
|
+
* @returns The encoded arkadeCash string (e.g., "arkadecash1...")
|
|
12833
12854
|
*/
|
|
12834
12855
|
async createCash(amount) {
|
|
12835
12856
|
if (!Number.isSafeInteger(amount) || amount < Number(this.dustAmount)) {
|
|
12836
12857
|
throw new Error(
|
|
12837
|
-
`Invalid
|
|
12858
|
+
`Invalid ArkadeCash amount ${amount}: must be a whole number of sats >= dust (${this.dustAmount})`
|
|
12838
12859
|
);
|
|
12839
12860
|
}
|
|
12840
|
-
const cashHrp = this.network.hrp.replace(/ark$/, "
|
|
12841
|
-
const cash =
|
|
12861
|
+
const cashHrp = this.network.hrp.replace(/ark$/, "arkadecash");
|
|
12862
|
+
const cash = ArkadeCash.generate(
|
|
12842
12863
|
this.arkServerPublicKey,
|
|
12843
12864
|
this.offchainTapscript.options.csvTimelock,
|
|
12844
12865
|
cashHrp
|
|
@@ -12848,37 +12869,37 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12848
12869
|
try {
|
|
12849
12870
|
await this.send({ address, amount });
|
|
12850
12871
|
} catch (error) {
|
|
12851
|
-
throw new
|
|
12872
|
+
throw new ArkadeCashCreateError(cashStr, error);
|
|
12852
12873
|
}
|
|
12853
12874
|
return cashStr;
|
|
12854
12875
|
}
|
|
12855
12876
|
/**
|
|
12856
|
-
* Claim an
|
|
12877
|
+
* Claim an ArkadeCash bearer instrument: sweep what can be swept, report the
|
|
12857
12878
|
* rest.
|
|
12858
12879
|
*
|
|
12859
|
-
* Every spendable VTXO at the
|
|
12860
|
-
* its own offchain transaction, signed with the key carried by the
|
|
12880
|
+
* Every spendable VTXO at the arkadeCash address is swept to this wallet in
|
|
12881
|
+
* its own offchain transaction, signed with the key carried by the arkadeCash
|
|
12861
12882
|
* string. Nothing is ever persisted: no contract is imported, and the
|
|
12862
|
-
*
|
|
12883
|
+
* arkadeCash key is not stored. Anything that cannot be swept — server-swept,
|
|
12863
12884
|
* subdust, already claimed, or asset-bearing — is returned in `unclaimed`
|
|
12864
12885
|
* with a per-VTXO reason and otherwise ignored.
|
|
12865
12886
|
*
|
|
12866
|
-
* The
|
|
12887
|
+
* The arkadeCash string is the recovery token: a claim interrupted between
|
|
12867
12888
|
* submit and finalize is completed by simply re-running `claimCash`, which
|
|
12868
|
-
* drains any pending
|
|
12889
|
+
* drains any pending arkadeCash transaction on the server before sweeping.
|
|
12869
12890
|
*
|
|
12870
|
-
* @param cashStr - The encoded
|
|
12891
|
+
* @param cashStr - The encoded arkadeCash string (e.g., "arkadecash1...")
|
|
12871
12892
|
* @returns The swept total and the report of what was left behind. The
|
|
12872
12893
|
* shape is open: further buckets may be added alongside `unclaimed`.
|
|
12873
12894
|
*/
|
|
12874
12895
|
async claimCash(cashStr) {
|
|
12875
|
-
const cash =
|
|
12896
|
+
const cash = ArkadeCash.fromString(cashStr);
|
|
12876
12897
|
const cashScript = cash.vtxoScript;
|
|
12877
12898
|
const cashPkScript = hex.encode(cashScript.pkScript);
|
|
12878
12899
|
const scripts = [cashPkScript];
|
|
12879
12900
|
let vtxos = await this.fetchAllVtxos(scripts);
|
|
12880
12901
|
if (vtxos.length === 0) {
|
|
12881
|
-
throw new Error("No VTXOs found for this
|
|
12902
|
+
throw new Error("No VTXOs found for this arkadeCash");
|
|
12882
12903
|
}
|
|
12883
12904
|
const myPkScript = ArkAddress.decode(await this.getAddress()).pkScript;
|
|
12884
12905
|
let { spendable, unclaimed } = this.classifyCashVtxos(vtxos);
|
|
@@ -12894,7 +12915,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12894
12915
|
myPkScript
|
|
12895
12916
|
);
|
|
12896
12917
|
} catch (error) {
|
|
12897
|
-
console.error("Failed to drain pending
|
|
12918
|
+
console.error("Failed to drain pending arkadeCash txs:", error);
|
|
12898
12919
|
}
|
|
12899
12920
|
if (drained.count > 0) {
|
|
12900
12921
|
vtxos = await this.fetchAllVtxos(scripts);
|
|
@@ -12929,7 +12950,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12929
12950
|
});
|
|
12930
12951
|
swept += vtxo.value;
|
|
12931
12952
|
} catch (error) {
|
|
12932
|
-
console.error(
|
|
12953
|
+
console.error(
|
|
12954
|
+
`Failed to sweep arkadeCash VTXO ${vtxo.txid}:${vtxo.vout}:`,
|
|
12955
|
+
error
|
|
12956
|
+
);
|
|
12933
12957
|
unclaimed.push(cashReport(vtxo, "sweep-failed"));
|
|
12934
12958
|
}
|
|
12935
12959
|
}
|
|
@@ -12943,18 +12967,18 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12943
12967
|
};
|
|
12944
12968
|
}
|
|
12945
12969
|
/**
|
|
12946
|
-
* Split the VTXOs at an
|
|
12970
|
+
* Split the VTXOs at an arkadeCash address into the ones the thin sweep can
|
|
12947
12971
|
* move and the ones it can only report.
|
|
12948
12972
|
*/
|
|
12949
12973
|
classifyCashVtxos(vtxos) {
|
|
12950
12974
|
const spendable = [];
|
|
12951
12975
|
const unclaimed = [];
|
|
12952
12976
|
for (const vtxo of vtxos) {
|
|
12953
|
-
if (
|
|
12977
|
+
if (hasTerminalSpend(vtxo)) {
|
|
12954
12978
|
unclaimed.push(cashReport(vtxo, "already-spent"));
|
|
12955
12979
|
} else if (isSubdust(vtxo, this.dustAmount)) {
|
|
12956
12980
|
unclaimed.push(cashReport(vtxo, "subdust"));
|
|
12957
|
-
} else if (
|
|
12981
|
+
} else if (vtxo.isSwept) {
|
|
12958
12982
|
unclaimed.push(cashReport(vtxo, "swept"));
|
|
12959
12983
|
} else if (vtxo.assets && vtxo.assets.length > 0) {
|
|
12960
12984
|
unclaimed.push(cashReport(vtxo, "has-assets"));
|
|
@@ -12970,7 +12994,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12970
12994
|
const all = [];
|
|
12971
12995
|
const seen = /* @__PURE__ */ new Set();
|
|
12972
12996
|
for (let pageIndex = 0; ; pageIndex++) {
|
|
12973
|
-
const { vtxos, page } = await this.indexerProvider
|
|
12997
|
+
const { vtxos, page } = await getNormalizedVtxos(this.indexerProvider, {
|
|
12974
12998
|
scripts,
|
|
12975
12999
|
pageIndex,
|
|
12976
13000
|
pageSize
|
|
@@ -12986,7 +13010,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12986
13010
|
}
|
|
12987
13011
|
/**
|
|
12988
13012
|
* Complete any sweep a previous `claimCash` registered but never finalized.
|
|
12989
|
-
* A thin variant of {@link finalizePendingTxs}, scoped to the
|
|
13013
|
+
* A thin variant of {@link finalizePendingTxs}, scoped to the arkadeCash key:
|
|
12990
13014
|
* the intent is signed with it, and so are the returned checkpoints.
|
|
12991
13015
|
*
|
|
12992
13016
|
* A drained sweep is not automatically *ours*. Whoever registered it chose
|
|
@@ -12995,7 +13019,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
12995
13019
|
* completing it unsticks the funds), but only the value it actually pays to
|
|
12996
13020
|
* `myPkScript` may be counted as claimed here.
|
|
12997
13021
|
*
|
|
12998
|
-
* @param vtxos - VTXOs at the
|
|
13022
|
+
* @param vtxos - VTXOs at the arkadeCash contract's own pkScript, spent ones
|
|
12999
13023
|
* included (a registered sweep marks its input spent). Any other outpoint —
|
|
13000
13024
|
* subdust above all — would make the proof invalid, since it describes every
|
|
13001
13025
|
* input by that pkScript.
|
|
@@ -13056,7 +13080,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13056
13080
|
}
|
|
13057
13081
|
}
|
|
13058
13082
|
} catch (error) {
|
|
13059
|
-
console.error(
|
|
13083
|
+
console.error(
|
|
13084
|
+
`Failed to finalize pending arkadeCash tx ${pendingTx.arkTxid}:`,
|
|
13085
|
+
error
|
|
13086
|
+
);
|
|
13060
13087
|
}
|
|
13061
13088
|
}
|
|
13062
13089
|
return result;
|
|
@@ -13300,7 +13327,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13300
13327
|
* there is no separate change output. It records no `TxSent` history — the
|
|
13301
13328
|
* funds never leave the wallet.
|
|
13302
13329
|
*/
|
|
13303
|
-
async sendSelectedVtxosToSelf(inputs) {
|
|
13330
|
+
async sendSelectedVtxosToSelf(inputs, now) {
|
|
13304
13331
|
if (inputs.length === 0) {
|
|
13305
13332
|
throw new Error("sendSelectedVtxosToSelf: no inputs");
|
|
13306
13333
|
}
|
|
@@ -13309,26 +13336,28 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13309
13336
|
const serverPubKey = this.arkServerPublicKey;
|
|
13310
13337
|
const serverUnrollScript = this.serverUnrollScript;
|
|
13311
13338
|
const arkAddress = offchainTapscript.address(this.network.hrp, serverPubKey);
|
|
13312
|
-
|
|
13313
|
-
|
|
13339
|
+
const normalizedInputs = inputs.map(normalizeVtxo);
|
|
13340
|
+
const at = now ?? await resolveTimeHeight(this.onchainProvider);
|
|
13341
|
+
for (const input of normalizedInputs) {
|
|
13342
|
+
if (!canSpendOffchain(input, at)) {
|
|
13314
13343
|
throw new Error(
|
|
13315
13344
|
`sendSelectedVtxosToSelf: input ${input.txid}:${input.vout} is not cooperatively spendable`
|
|
13316
13345
|
);
|
|
13317
13346
|
}
|
|
13318
|
-
if (
|
|
13347
|
+
if (input.expiresAt === void 0 && input.expiresAtHeight === void 0) {
|
|
13319
13348
|
throw new Error(
|
|
13320
|
-
`sendSelectedVtxosToSelf: input ${input.txid}:${input.vout} has no
|
|
13349
|
+
`sendSelectedVtxosToSelf: input ${input.txid}:${input.vout} has no batch expiry`
|
|
13321
13350
|
);
|
|
13322
13351
|
}
|
|
13323
13352
|
}
|
|
13324
|
-
const total =
|
|
13353
|
+
const total = normalizedInputs.reduce((sum, c) => sum + BigInt(c.value), 0n);
|
|
13325
13354
|
const outputs = [
|
|
13326
13355
|
{
|
|
13327
13356
|
script: total < this.dustAmount ? arkAddress.subdustPkScript : arkAddress.pkScript,
|
|
13328
13357
|
amount: total
|
|
13329
13358
|
}
|
|
13330
13359
|
];
|
|
13331
|
-
const assetInputs = selectedCoinsToAssetInputs(
|
|
13360
|
+
const assetInputs = selectedCoinsToAssetInputs(normalizedInputs);
|
|
13332
13361
|
let selfAssets;
|
|
13333
13362
|
if (assetInputs.size > 0) {
|
|
13334
13363
|
const totals = /* @__PURE__ */ new Map();
|
|
@@ -13345,7 +13374,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13345
13374
|
const packet = createAssetPacket(assetInputs, [], selfReceiver);
|
|
13346
13375
|
outputs.push(Extension.create([packet]).txOut());
|
|
13347
13376
|
}
|
|
13348
|
-
return this._submitOffchainSpend(
|
|
13377
|
+
return this._submitOffchainSpend(normalizedInputs, outputs, {
|
|
13349
13378
|
sentAmount: 0,
|
|
13350
13379
|
changeAmount: total,
|
|
13351
13380
|
changeVout: 0,
|
|
@@ -13446,43 +13475,42 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13446
13475
|
const cm = await this.getContractManager();
|
|
13447
13476
|
const annotatedInputs = await cm.annotateVtxos(inputs);
|
|
13448
13477
|
for (const [inputIndex, vtxo] of annotatedInputs.entries()) {
|
|
13478
|
+
const spentFacts = { ...vtxo, isSpent: true };
|
|
13449
13479
|
if (inputIndex < safeLength && signedCheckpointTxs[inputIndex]) {
|
|
13450
13480
|
const checkpoint = Transaction$2.fromPSBT(
|
|
13451
13481
|
base64.decode(signedCheckpointTxs[inputIndex])
|
|
13452
13482
|
);
|
|
13453
13483
|
spentVtxos.push({
|
|
13454
|
-
...
|
|
13455
|
-
virtualStatus:
|
|
13456
|
-
...vtxo.virtualStatus,
|
|
13457
|
-
state: "spent"
|
|
13458
|
-
},
|
|
13484
|
+
...spentFacts,
|
|
13485
|
+
virtualStatus: toVirtualStatus(spentFacts),
|
|
13459
13486
|
spentBy: checkpoint.id,
|
|
13460
|
-
arkTxId: arkTxid
|
|
13461
|
-
isSpent: true
|
|
13487
|
+
arkTxId: arkTxid
|
|
13462
13488
|
});
|
|
13463
13489
|
} else {
|
|
13464
13490
|
spentVtxos.push({
|
|
13465
|
-
...
|
|
13466
|
-
virtualStatus:
|
|
13467
|
-
|
|
13468
|
-
state: "spent"
|
|
13469
|
-
},
|
|
13470
|
-
arkTxId: arkTxid,
|
|
13471
|
-
isSpent: true
|
|
13491
|
+
...spentFacts,
|
|
13492
|
+
virtualStatus: toVirtualStatus(spentFacts),
|
|
13493
|
+
arkTxId: arkTxid
|
|
13472
13494
|
});
|
|
13473
13495
|
}
|
|
13474
|
-
|
|
13475
|
-
|
|
13476
|
-
commitmentTxIds.add(id);
|
|
13477
|
-
}
|
|
13496
|
+
for (const id of vtxo.commitmentTxIds) {
|
|
13497
|
+
commitmentTxIds.add(id);
|
|
13478
13498
|
}
|
|
13479
|
-
|
|
13480
|
-
|
|
13499
|
+
const vtxoExpiry = toBatchExpiry(vtxo);
|
|
13500
|
+
if (vtxoExpiry) {
|
|
13501
|
+
batchExpiry = Math.min(batchExpiry, vtxoExpiry);
|
|
13481
13502
|
}
|
|
13482
13503
|
}
|
|
13483
13504
|
const createdAt = Date.now();
|
|
13484
13505
|
let changeVtxo;
|
|
13485
13506
|
if (changeAmount > 0n && batchExpiry !== Number.MAX_SAFE_INTEGER) {
|
|
13507
|
+
const changeFacts = {
|
|
13508
|
+
isSpent: false,
|
|
13509
|
+
isSwept: false,
|
|
13510
|
+
isPreconfirmed: true,
|
|
13511
|
+
commitmentTxIds: Array.from(commitmentTxIds),
|
|
13512
|
+
...parseLegacyExpiry(batchExpiry)
|
|
13513
|
+
};
|
|
13486
13514
|
changeVtxo = {
|
|
13487
13515
|
txid: arkTxid,
|
|
13488
13516
|
vout: changeVout,
|
|
@@ -13490,14 +13518,11 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13490
13518
|
forfeitTapLeafScript: offchainTapscript.forfeit(),
|
|
13491
13519
|
intentTapLeafScript: offchainTapscript.forfeit(),
|
|
13492
13520
|
isUnrolled: false,
|
|
13493
|
-
isSpent: false,
|
|
13494
13521
|
tapTree: offchainTapscript.encode(),
|
|
13495
13522
|
value: Number(changeAmount),
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
|
|
13499
|
-
batchExpiry
|
|
13500
|
-
},
|
|
13523
|
+
...changeFacts,
|
|
13524
|
+
virtualStatus: toVirtualStatus(changeFacts),
|
|
13525
|
+
spentBy: "",
|
|
13501
13526
|
status: {
|
|
13502
13527
|
confirmed: false
|
|
13503
13528
|
},
|
|
@@ -13565,25 +13590,25 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13565
13590
|
const spentVtxos = [];
|
|
13566
13591
|
const inputArkTxIds = /* @__PURE__ */ new Set();
|
|
13567
13592
|
const boardingRemovalsByAddress = /* @__PURE__ */ new Map();
|
|
13568
|
-
const
|
|
13569
|
-
const vtxoInputs = inputs.filter(isVtxo);
|
|
13593
|
+
const vtxoInputs = inputs.filter(isVirtualCoin);
|
|
13570
13594
|
const cm = await this.getContractManager();
|
|
13571
13595
|
const annotatedVtxos = await cm.annotateVtxos(vtxoInputs);
|
|
13572
13596
|
const annotatedByKey = new Map(annotatedVtxos.map((v) => [`${v.txid}:${v.vout}`, v]));
|
|
13573
13597
|
for (const input of inputs) {
|
|
13574
|
-
if (
|
|
13575
|
-
const
|
|
13598
|
+
if (isVirtualCoin(input)) {
|
|
13599
|
+
const outpoint = `${input.txid}:${input.vout}`;
|
|
13600
|
+
const vtxo = annotatedByKey.get(outpoint);
|
|
13601
|
+
if (!vtxo) {
|
|
13602
|
+
throw new Error(`missing annotation for virtual coin ${outpoint}`);
|
|
13603
|
+
}
|
|
13576
13604
|
if (vtxo.arkTxId) {
|
|
13577
13605
|
inputArkTxIds.add(vtxo.arkTxId);
|
|
13578
13606
|
}
|
|
13607
|
+
const settledFacts = { ...vtxo, isSpent: true };
|
|
13579
13608
|
spentVtxos.push({
|
|
13580
|
-
...
|
|
13581
|
-
virtualStatus:
|
|
13582
|
-
|
|
13583
|
-
state: "settled"
|
|
13584
|
-
},
|
|
13585
|
-
settledBy: commitmentTxid,
|
|
13586
|
-
isSpent: true
|
|
13609
|
+
...settledFacts,
|
|
13610
|
+
virtualStatus: toVirtualStatus(settledFacts),
|
|
13611
|
+
settledBy: commitmentTxid
|
|
13587
13612
|
});
|
|
13588
13613
|
} else {
|
|
13589
13614
|
let sourceAddress;
|
|
@@ -13646,9 +13671,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13646
13671
|
}
|
|
13647
13672
|
};
|
|
13648
13673
|
function selectVirtualCoins(coins, targetAmount) {
|
|
13649
|
-
const sortedCoins =
|
|
13650
|
-
const expiryA = a
|
|
13651
|
-
const expiryB = b
|
|
13674
|
+
const sortedCoins = coins.map(normalizeVtxo).sort((a, b) => {
|
|
13675
|
+
const expiryA = toBatchExpiry(a) || Number.MAX_SAFE_INTEGER;
|
|
13676
|
+
const expiryB = toBatchExpiry(b) || Number.MAX_SAFE_INTEGER;
|
|
13652
13677
|
if (expiryA !== expiryB) {
|
|
13653
13678
|
return expiryA - expiryB;
|
|
13654
13679
|
}
|
|
@@ -14342,13 +14367,7 @@ var Ramps = class {
|
|
|
14342
14367
|
const filteredVtxos = [];
|
|
14343
14368
|
let totalAmount = 0n;
|
|
14344
14369
|
for (const vtxo of vtxos) {
|
|
14345
|
-
const inputFee = estimator.evalOffchainInput(
|
|
14346
|
-
amount: BigInt(vtxo.value),
|
|
14347
|
-
type: vtxo.virtualStatus.state === "swept" ? "recoverable" : "vtxo",
|
|
14348
|
-
weight: 0,
|
|
14349
|
-
birth: vtxo.createdAt,
|
|
14350
|
-
expiry: vtxo.virtualStatus.batchExpiry ? new Date(vtxo.virtualStatus.batchExpiry) : void 0
|
|
14351
|
-
});
|
|
14370
|
+
const inputFee = estimator.evalOffchainInput(toOffchainInputFeeParams(vtxo));
|
|
14352
14371
|
if (inputFee.satoshis >= vtxo.value) {
|
|
14353
14372
|
continue;
|
|
14354
14373
|
}
|
|
@@ -15083,30 +15102,30 @@ var WalletMessageHandler = class {
|
|
|
15083
15102
|
unconfirmed += utxo.value;
|
|
15084
15103
|
}
|
|
15085
15104
|
}
|
|
15086
|
-
const
|
|
15087
|
-
const sweptVtxos = allVtxos.filter((vtxo) => vtxo.virtualStatus.state === "swept");
|
|
15105
|
+
const now = { timestamp: /* @__PURE__ */ new Date() };
|
|
15088
15106
|
let settled = 0;
|
|
15089
15107
|
let preconfirmed = 0;
|
|
15090
15108
|
let recoverable = 0;
|
|
15091
15109
|
let pendingRecovery = 0;
|
|
15092
|
-
for (const vtxo of
|
|
15110
|
+
for (const vtxo of allVtxos) {
|
|
15111
|
+
if (hasTerminalSpend(vtxo)) continue;
|
|
15093
15112
|
if (pendingOutpoints.has(`${vtxo.txid}:${vtxo.vout}`)) {
|
|
15094
15113
|
pendingRecovery += vtxo.value;
|
|
15095
|
-
} else if (vtxo
|
|
15096
|
-
settled += vtxo.value;
|
|
15097
|
-
} else if (vtxo.virtualStatus.state === "preconfirmed") {
|
|
15098
|
-
preconfirmed += vtxo.value;
|
|
15099
|
-
}
|
|
15100
|
-
}
|
|
15101
|
-
for (const vtxo of sweptVtxos) {
|
|
15102
|
-
if (isSpendable(vtxo)) {
|
|
15114
|
+
} else if (canRecoverOnchain(vtxo, now)) {
|
|
15103
15115
|
recoverable += vtxo.value;
|
|
15116
|
+
} else if (canSpendOffchain(vtxo, now)) {
|
|
15117
|
+
if (vtxo.isPreconfirmed) {
|
|
15118
|
+
preconfirmed += vtxo.value;
|
|
15119
|
+
} else {
|
|
15120
|
+
settled += vtxo.value;
|
|
15121
|
+
}
|
|
15104
15122
|
}
|
|
15105
15123
|
}
|
|
15106
15124
|
const totalBoarding = confirmed + unconfirmed;
|
|
15107
15125
|
const totalOffchain = settled + preconfirmed + recoverable + pendingRecovery;
|
|
15108
15126
|
const assetBalances = /* @__PURE__ */ new Map();
|
|
15109
|
-
for (const vtxo of
|
|
15127
|
+
for (const vtxo of allVtxos) {
|
|
15128
|
+
if (hasTerminalSpend(vtxo)) continue;
|
|
15110
15129
|
if (vtxo.assets) {
|
|
15111
15130
|
for (const a of vtxo.assets) {
|
|
15112
15131
|
const current = assetBalances.get(a.assetId) ?? 0n;
|
|
@@ -15142,7 +15161,7 @@ var WalletMessageHandler = class {
|
|
|
15142
15161
|
*/
|
|
15143
15162
|
async getSpendableVtxos() {
|
|
15144
15163
|
const vtxos = await this.getVtxosFromRepo();
|
|
15145
|
-
return vtxos.filter(
|
|
15164
|
+
return vtxos.filter((v) => !hasTerminalSpend(v));
|
|
15146
15165
|
}
|
|
15147
15166
|
async onWalletInitialized() {
|
|
15148
15167
|
if (!this.readonlyWallet || !this.arkProvider || !this.indexerProvider || !this.walletRepository) {
|
|
@@ -15154,9 +15173,7 @@ var WalletMessageHandler = class {
|
|
|
15154
15173
|
try {
|
|
15155
15174
|
const vtxos = await this.getVtxosFromRepo();
|
|
15156
15175
|
const { pending, finalized } = await this.wallet.finalizePendingTxs(
|
|
15157
|
-
vtxos.filter(
|
|
15158
|
-
(vtxo) => vtxo.virtualStatus.state !== "swept" && vtxo.virtualStatus.state !== "settled"
|
|
15159
|
-
)
|
|
15176
|
+
vtxos.filter((vtxo) => vtxo.isSpent || vtxo.isPreconfirmed && !vtxo.isSwept)
|
|
15160
15177
|
);
|
|
15161
15178
|
console.info(
|
|
15162
15179
|
`Recovered ${finalized.length}/${pending.length} pending transactions: ${finalized.join(", ")}`
|
|
@@ -15415,8 +15432,12 @@ var WalletMessageHandler = class {
|
|
|
15415
15432
|
`WalletMessageHandler.getVtxosFromRepo: failed to derive script from wallet address ${walletAddress}: ${e instanceof Error ? e.message : String(e)}`
|
|
15416
15433
|
);
|
|
15417
15434
|
}
|
|
15418
|
-
|
|
15419
|
-
|
|
15435
|
+
addVtxos(
|
|
15436
|
+
await getVtxosForContract(this.walletRepository, {
|
|
15437
|
+
script: walletScript,
|
|
15438
|
+
address: walletAddress
|
|
15439
|
+
})
|
|
15440
|
+
);
|
|
15420
15441
|
return allVtxos;
|
|
15421
15442
|
}
|
|
15422
15443
|
/**
|
|
@@ -15448,7 +15469,7 @@ var WalletMessageHandler = class {
|
|
|
15448
15469
|
}));
|
|
15449
15470
|
const BATCH_SIZE = 100;
|
|
15450
15471
|
for (let i = 0; i < outpoints.length; i += BATCH_SIZE) {
|
|
15451
|
-
const res = await this.indexerProvider
|
|
15472
|
+
const res = await getNormalizedVtxos(this.indexerProvider, {
|
|
15452
15473
|
outpoints: outpoints.slice(i, i + BATCH_SIZE)
|
|
15453
15474
|
});
|
|
15454
15475
|
for (const v of res.vtxos) {
|
|
@@ -16150,7 +16171,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
16150
16171
|
};
|
|
16151
16172
|
try {
|
|
16152
16173
|
const response = await this.sendMessage(message);
|
|
16153
|
-
return response.payload.vtxos;
|
|
16174
|
+
return response.payload.vtxos.map(normalizeVtxo);
|
|
16154
16175
|
} catch (error) {
|
|
16155
16176
|
throw new Error(`Failed to get vtxos: ${error}`);
|
|
16156
16177
|
}
|
|
@@ -16263,7 +16284,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
16263
16284
|
};
|
|
16264
16285
|
try {
|
|
16265
16286
|
const response = await sendContractMessage(message);
|
|
16266
|
-
return response.payload.vtxos;
|
|
16287
|
+
return response.payload.vtxos.map(normalizeVtxo);
|
|
16267
16288
|
} catch (e) {
|
|
16268
16289
|
throw new Error("Failed to annotate vtxos");
|
|
16269
16290
|
}
|
|
@@ -16708,7 +16729,7 @@ var ServiceWorkerWallet = class _ServiceWorkerWallet extends ServiceWorkerReadon
|
|
|
16708
16729
|
};
|
|
16709
16730
|
try {
|
|
16710
16731
|
const response = await wallet.sendMessage(message);
|
|
16711
|
-
return response.payload.vtxos;
|
|
16732
|
+
return response.payload.vtxos.map(normalizeVtxo);
|
|
16712
16733
|
} catch (e) {
|
|
16713
16734
|
throw new Error(`Failed to get expiring vtxos: ${e}`);
|
|
16714
16735
|
}
|
|
@@ -18448,7 +18469,7 @@ async function resolveFeeRate(opts) {
|
|
|
18448
18469
|
}
|
|
18449
18470
|
async function selectExitVtxos(opts) {
|
|
18450
18471
|
if (!opts.vtxos) return opts.wallet.getVtxos();
|
|
18451
|
-
const res = await opts.wallet.indexerProvider
|
|
18472
|
+
const res = await getNormalizedVtxos(opts.wallet.indexerProvider, { outpoints: opts.vtxos });
|
|
18452
18473
|
const tapTrees = /* @__PURE__ */ new Map();
|
|
18453
18474
|
const out = [];
|
|
18454
18475
|
for (const vtxo of res.vtxos) {
|
|
@@ -19117,7 +19138,7 @@ __export(arkade_exports, {
|
|
|
19117
19138
|
validateProgram: () => validateProgram,
|
|
19118
19139
|
witnessRefToBytes: () => witnessRefToBytes
|
|
19119
19140
|
});
|
|
19120
|
-
var isVtxoCoin = (input) =>
|
|
19141
|
+
var isVtxoCoin = (input) => isVirtualCoin(input);
|
|
19121
19142
|
function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message, session, arkProvider, emulator, network, recipients) {
|
|
19122
19143
|
let batchId;
|
|
19123
19144
|
let sweepTapTreeRoot;
|
|
@@ -19194,7 +19215,11 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
|
|
|
19194
19215
|
break;
|
|
19195
19216
|
}
|
|
19196
19217
|
}
|
|
19197
|
-
if (boardingIdx === null)
|
|
19218
|
+
if (boardingIdx === null) {
|
|
19219
|
+
throw new Error(
|
|
19220
|
+
`input ${input.txid}:${input.vout} is neither a virtual output nor an input of the commitment tx; a virtual output must carry its \`script\``
|
|
19221
|
+
);
|
|
19222
|
+
}
|
|
19198
19223
|
commitmentPsbt.updateInput(boardingIdx, {
|
|
19199
19224
|
tapLeafScript: [input.forfeitTapLeafScript]
|
|
19200
19225
|
});
|
|
@@ -19474,13 +19499,13 @@ var ArkadeContract = class _ArkadeContract {
|
|
|
19474
19499
|
const [registered] = await manager.getContracts({ script: scriptHex });
|
|
19475
19500
|
if (registered) {
|
|
19476
19501
|
const [withVtxos] = await manager.getContractsWithVtxos({ script: scriptHex });
|
|
19477
|
-
return (withVtxos?.vtxos ?? []).filter(
|
|
19502
|
+
return (withVtxos?.vtxos ?? []).filter((v) => !hasTerminalSpend(v));
|
|
19478
19503
|
}
|
|
19479
19504
|
}
|
|
19480
19505
|
if (!this.client.indexer) {
|
|
19481
19506
|
throw new Error("ArkadeContract.getUtxos: an indexer is required");
|
|
19482
19507
|
}
|
|
19483
|
-
const { vtxos } = await this.client.indexer
|
|
19508
|
+
const { vtxos } = await getNormalizedVtxos(this.client.indexer, {
|
|
19484
19509
|
scripts: [scriptHex],
|
|
19485
19510
|
spendableOnly: true
|
|
19486
19511
|
});
|
|
@@ -19788,6 +19813,6 @@ function isArkContract(str) {
|
|
|
19788
19813
|
return str.startsWith(ARKCONTRACT_PREFIX + "=");
|
|
19789
19814
|
}
|
|
19790
19815
|
|
|
19791
|
-
export { ARKADE_MAGIC, ActivityRegistry,
|
|
19792
|
-
//# sourceMappingURL=chunk-
|
|
19793
|
-
//# sourceMappingURL=chunk-
|
|
19816
|
+
export { ARKADE_MAGIC, ActivityRegistry, ArkNote, ArkadeCash, ArkadeCashCreateError, AssetManager, BIP322, Batch, ChainedTxType, ContractManager, ContractRepositoryImpl, ContractWatcher, DB_VERSION, DEFAULT_MESSAGE_TIMEOUTS, DelegateManagerImpl, DelegateNotConfiguredError, DelegatorManagerImpl, DelegatorNotConfiguredError, DescriptorSigningProviderMissingError, DustChangeError, ELECTRUM_TCP_HOST, ELECTRUM_WS_URL, ESPLORA_URL, ElectrumOnchainProvider, EmulatorPacket, EsploraProvider, Estimator, Extension, ExtensionNotFoundError, HDDescriptorProvider, INTENT_TERMINAL_STATES, InMemoryContractRepository, InMemoryIntentRepository, InMemoryVirtualTxRepository, InMemoryWalletRepository, IndexedDBContractRepository, IndexedDBIntentRepository, IndexedDBVirtualTxRepository, IndexedDBWalletRepository, MESSAGE_BUS_INITIALIZING, MESSAGE_BUS_NOT_INITIALIZED, MIGRATION_KEY, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, P2A, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestDelegatorProvider, RestEmulatorProvider, SeedIdentity, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, TxTree, TxType, TxWeightEstimator, UnilateralExit, UnknownPacket, Unroll, VtxoManager, Wallet2 as Wallet, WalletMessageHandler, WalletNotInitializedError, WalletRepositoryImpl, WsElectrumChainSource, arkade_exports, assertIntentIdUnique, boardingResolver, buildForfeitTx, buildOffchainTx, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, combineTapscriptSigs, contractFromArkContract, contractFromArkContractWithAddress, createAssetPacket, createDefaultActivityRegistry, createExitChainResolver, decodeArkContract, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, extendVirtualCoinForContract, getMigrationStatus, getRandomId, hasBoardingTxExpired, intentMatchesFilter, intentPageBounds, isArkContract, isBatchSignable, isCooperativelyMigratable, isDiscoverable, isRetryableProviderError, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, isVtxoForScript, mergeChainedTxType, migrateWalletRepository, openDatabase, requiresMigration, rollbackMigration, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signerSetFromInfo, toXOnlySignerHex, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, warnAndFilterVtxosForScript };
|
|
19817
|
+
//# sourceMappingURL=chunk-NYR5H6GR.js.map
|
|
19818
|
+
//# sourceMappingURL=chunk-NYR5H6GR.js.map
|