@arkade-os/sdk 0.5.0-rc.22 → 0.5.0-rc.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- 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/{asyncStorageTaskQueue-C9Ab5DyR.d.cts → asyncStorageTaskQueue-DUu3VwBE.d.cts} +1 -1
- package/dist/{asyncStorageTaskQueue-CbQryNK9.d.ts → asyncStorageTaskQueue-Dm71_6ID.d.ts} +1 -1
- package/dist/{chunk-OACS4QUR.js → chunk-B4CZLBE6.js} +4 -4
- package/dist/{chunk-OACS4QUR.js.map → chunk-B4CZLBE6.js.map} +1 -1
- package/dist/{chunk-MN22OMVC.js → chunk-ENGV6VZF.js} +502 -83
- package/dist/chunk-ENGV6VZF.js.map +1 -0
- package/dist/{chunk-4X3ZGHWW.cjs → chunk-H7W2KLN2.cjs} +981 -559
- package/dist/chunk-H7W2KLN2.cjs.map +1 -0
- package/dist/{chunk-W4TZBRG3.cjs → chunk-JETDFDWV.cjs} +10 -10
- package/dist/{chunk-W4TZBRG3.cjs.map → chunk-JETDFDWV.cjs.map} +1 -1
- package/dist/{chunk-OJ5W7L6Q.cjs → chunk-KR6FLFIH.cjs} +3 -3
- package/dist/{chunk-OJ5W7L6Q.cjs.map → chunk-KR6FLFIH.cjs.map} +1 -1
- package/dist/{chunk-OSRXKF7B.cjs → chunk-QLJXXVRO.cjs} +48 -48
- package/dist/{chunk-OSRXKF7B.cjs.map → chunk-QLJXXVRO.cjs.map} +1 -1
- package/dist/{chunk-W27URLQ5.js → chunk-SPJA7XMU.js} +3 -3
- package/dist/{chunk-W27URLQ5.js.map → chunk-SPJA7XMU.js.map} +1 -1
- package/dist/{chunk-WJKVNBUN.js → chunk-UDQ3QE4C.js} +3 -3
- package/dist/{chunk-WJKVNBUN.js.map → chunk-UDQ3QE4C.js.map} +1 -1
- package/dist/{chunk-EBUSHD43.js → chunk-W2VYRZLB.js} +4 -4
- package/dist/{chunk-EBUSHD43.js.map → chunk-W2VYRZLB.js.map} +1 -1
- package/dist/{chunk-QUR5ENRP.js → chunk-XZEQV5FE.js} +3 -3
- package/dist/{chunk-QUR5ENRP.js.map → chunk-XZEQV5FE.js.map} +1 -1
- package/dist/{chunk-XWUJBHYW.cjs → chunk-YFHGGSII.cjs} +18 -18
- package/dist/{chunk-XWUJBHYW.cjs.map → chunk-YFHGGSII.cjs.map} +1 -1
- package/dist/{chunk-QFT7X26G.cjs → chunk-ZDLFQ7ZH.cjs} +15 -15
- package/dist/{chunk-QFT7X26G.cjs.map → chunk-ZDLFQ7ZH.cjs.map} +1 -1
- package/dist/contracts/handlers/index.cjs +9 -9
- 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-BT5iON1T.d.ts → delegate-DATx5c2o.d.ts} +1 -1
- package/dist/{delegate-u6kXTtWY.d.cts → delegate-DRoyCz4n.d.cts} +1 -1
- package/dist/{index-CK5QbTmZ.d.ts → index-BKBoBSKX.d.cts} +83 -9
- package/dist/{index-CK5QbTmZ.d.cts → index-BKBoBSKX.d.ts} +83 -9
- package/dist/{index-D1D4cR-G.d.ts → index-BjDUwnH-.d.ts} +2 -2
- package/dist/{index-BCnhItOQ.d.cts → index-CLgF0km0.d.cts} +2 -2
- package/dist/index.cjs +321 -309
- package/dist/index.d.cts +78 -16
- package/dist/index.d.ts +78 -16
- package/dist/index.js +4 -4
- package/dist/repositories/realm/index.cjs +35 -35
- 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 +33 -33
- 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-BDAZSNyd.d.ts → taskRunner-B78rNRXB.d.ts} +1 -1
- package/dist/{taskRunner-D5ObtxWZ.d.cts → taskRunner-CoGRmz1U.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 +15 -15
- package/dist/wallet/expo/index.d.cts +4 -4
- package/dist/wallet/expo/index.d.ts +4 -4
- package/dist/wallet/expo/index.js +5 -5
- package/dist/{wallet-DG3Qmbmt.d.cts → wallet-CdUjdg15.d.cts} +23 -5
- package/dist/{wallet-DzSLMxBZ.d.ts → wallet-yKzfCUfY.d.ts} +23 -5
- 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 +1 -1
- package/dist/chunk-4X3ZGHWW.cjs.map +0 -1
- package/dist/chunk-MN22OMVC.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, Packet, BufferReader, BufferWriter, AssetRef, RestIndexerProvider } 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, toXOnly, inputName, contractHandlers, isMainnetDescriptor, descriptorIsOurs, deriveDescriptorLeafPubKey, deriveDescriptorLeafCompressedPubKey, normalizeToDescriptor, extractPubKey, parseHDDescriptor, identityDescriptor, DefaultVtxo, speculativeReceiveMetadata, DelegateVtxo, WALLET_RECEIVE_SOURCE, BoardingContractHandler } from './chunk-
|
|
3
|
-
import { VtxoScript, __export, Transaction, requiresForfeit, CSVMultisigTapscript, networks, getNetwork, DEFAULT_NETWORK, resolveEmulatorPubkey, isVtxoSpent, getNormalizedVtxos, setArkPsbtField, PrevArkTxField, ConditionWitness, craftToSpendTx, ArkAddress, isVirtualCoin, getArkPsbtFields, CosignerPublicKey, ServerResponseMismatchError, OP_RETURN_EMPTY_PKSCRIPT, canSweepOnchain, sequenceToTimelock, sequenceToCanonicalTimelock, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, VtxoTaprootTree, timelockToSequence, assertAllowedSighashTypes, baseFetch, Intent, rateGate, DEFAULT_NETWORK_NAME, formatSighash, normalizeVtxo, assertTimerMs, getSequence, maybeArkError, isArkError, ArkErrorName, toOffchainInputFeeParams, canRecoverOnchain, MultisigTapscript, isEventSourceError, isEventSourceUnavailableError, getAllNormalizedVtxos, isPastExpiry, assertNonNegativeMs, isRetryableProviderError, DEFAULT_PAGE_SIZE, RestArkProvider, DEFAULT_ARKADE_SERVER_URL, networkFromArkadeInfo, ArkError, toBIP371TapTree, resolveTimeHeight, canSpendOffchain, INFO_FETCH_TIMEOUT_MS, PrevoutTxField, fetchVtxoCreatedAtByTxid, EXPIRY_MIN_PLAUSIBLE_MS, ProviderUnavailableError } from './chunk-
|
|
1
|
+
import { AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, Packet, BufferReader, BufferWriter, AssetRef, RestIndexerProvider } from './chunk-SPJA7XMU.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, toXOnly, inputName, contractHandlers, isMainnetDescriptor, descriptorIsOurs, deriveDescriptorLeafPubKey, deriveDescriptorLeafCompressedPubKey, normalizeToDescriptor, extractPubKey, parseHDDescriptor, identityDescriptor, DefaultVtxo, speculativeReceiveMetadata, DelegateVtxo, WALLET_RECEIVE_SOURCE, BoardingContractHandler } from './chunk-UDQ3QE4C.js';
|
|
3
|
+
import { VtxoScript, __export, Transaction, requiresForfeit, CSVMultisigTapscript, networks, getNetwork, DEFAULT_NETWORK, resolveEmulatorPubkey, isVtxoSpent, getNormalizedVtxos, setArkPsbtField, PrevArkTxField, ConditionWitness, craftToSpendTx, ArkAddress, isVirtualCoin, getArkPsbtFields, CosignerPublicKey, ServerResponseMismatchError, OP_RETURN_EMPTY_PKSCRIPT, canSweepOnchain, sequenceToTimelock, sequenceToCanonicalTimelock, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, VtxoTaprootTree, timelockToSequence, assertAllowedSighashTypes, baseFetch, Intent, rateGate, DEFAULT_NETWORK_NAME, formatSighash, normalizeVtxo, assertTimerMs, getSequence, maybeArkError, isArkError, ArkErrorName, toOffchainInputFeeParams, canRecoverOnchain, MultisigTapscript, isEventSourceError, isEventSourceUnavailableError, getAllNormalizedVtxos, isPastExpiry, assertNonNegativeMs, isRetryableProviderError, DEFAULT_PAGE_SIZE, RestArkProvider, DEFAULT_ARKADE_SERVER_URL, networkFromArkadeInfo, ArkError, toBIP371TapTree, resolveTimeHeight, canSpendOffchain, INFO_FETCH_TIMEOUT_MS, PrevoutTxField, fetchVtxoCreatedAtByTxid, EXPIRY_MIN_PLAUSIBLE_MS, ProviderUnavailableError } from './chunk-XZEQV5FE.js';
|
|
4
4
|
import { sha256, equalBytes, hash160, sha256x2, concatBytes, randomPrivateKeyBytes, pubECDSA, pubSchnorr } from '@scure/btc-signer/utils.js';
|
|
5
5
|
import { SigHash, Script, OP, OutScript, Address, RawWitness, p2tr, p2wpkh, TaprootControlBlock, DEFAULT_SEQUENCE, Transaction as Transaction$1 } from '@scure/btc-signer';
|
|
6
6
|
import { hex, base58, base64, bech32m } from '@scure/base';
|
|
@@ -3337,6 +3337,53 @@ function selectedCoinsToAssetInputs(selectedCoins) {
|
|
|
3337
3337
|
}
|
|
3338
3338
|
return assetInputs;
|
|
3339
3339
|
}
|
|
3340
|
+
|
|
3341
|
+
// src/wallet/sendDeadline.ts
|
|
3342
|
+
var SendDeadlineExceededError = class extends Error {
|
|
3343
|
+
constructor(validUntil) {
|
|
3344
|
+
super(`Send deadline ${validUntil} expired before provider submission`);
|
|
3345
|
+
this.name = "SendDeadlineExceededError";
|
|
3346
|
+
}
|
|
3347
|
+
};
|
|
3348
|
+
function captureSendDeadline(value, required = false) {
|
|
3349
|
+
if (value === void 0 && !required) return void 0;
|
|
3350
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0) {
|
|
3351
|
+
throw new TypeError("validUntil must be a positive safe integer UNIX timestamp in seconds");
|
|
3352
|
+
}
|
|
3353
|
+
return value;
|
|
3354
|
+
}
|
|
3355
|
+
function assertSendDeadline(validUntil) {
|
|
3356
|
+
if (validUntil !== void 0 && Date.now() / 1e3 >= validUntil) {
|
|
3357
|
+
throw new SendDeadlineExceededError(validUntil);
|
|
3358
|
+
}
|
|
3359
|
+
}
|
|
3360
|
+
|
|
3361
|
+
// src/wallet/sendInputExpiry.ts
|
|
3362
|
+
function captureInputExpiryFloor(value, required = false) {
|
|
3363
|
+
if (value === void 0 && !required) return void 0;
|
|
3364
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3365
|
+
throw new TypeError(
|
|
3366
|
+
"inputExpiryFloor must specify a time or height and positive bigint value"
|
|
3367
|
+
);
|
|
3368
|
+
}
|
|
3369
|
+
const { kind, value: floor } = value;
|
|
3370
|
+
if (kind !== "time" && kind !== "height" || typeof floor !== "bigint" || floor <= 0n) {
|
|
3371
|
+
throw new TypeError(
|
|
3372
|
+
"inputExpiryFloor must specify a time or height and positive bigint value"
|
|
3373
|
+
);
|
|
3374
|
+
}
|
|
3375
|
+
return Object.freeze({ kind, value: floor });
|
|
3376
|
+
}
|
|
3377
|
+
function meetsInputExpiryFloor(coin, floor) {
|
|
3378
|
+
if (coin.expiresAt === void 0 === (coin.expiresAtHeight === void 0)) return false;
|
|
3379
|
+
if (floor.kind === "height") {
|
|
3380
|
+
const height = coin.expiresAtHeight;
|
|
3381
|
+
return typeof height === "number" && Number.isSafeInteger(height) && height > 0 && BigInt(height) >= floor.value;
|
|
3382
|
+
}
|
|
3383
|
+
if (!(coin.expiresAt instanceof Date)) return false;
|
|
3384
|
+
const milliseconds = coin.expiresAt.getTime();
|
|
3385
|
+
return Number.isSafeInteger(milliseconds) && milliseconds > 0 && BigInt(milliseconds) >= floor.value * 1000n;
|
|
3386
|
+
}
|
|
3340
3387
|
function toXOnlySignerHex(pubkeyHex) {
|
|
3341
3388
|
const bytes = hex.decode(pubkeyHex);
|
|
3342
3389
|
if (bytes.length === 32 || bytes.length === 33) return hex.encode(toXOnly(bytes, "signer key"));
|
|
@@ -9550,11 +9597,18 @@ var ContractManager = class _ContractManager {
|
|
|
9550
9597
|
initialized = false;
|
|
9551
9598
|
eventCallbacks = /* @__PURE__ */ new Set();
|
|
9552
9599
|
stopWatcherFn;
|
|
9600
|
+
/** Watcher events still being handled. They write VTXO rows, so {@link dispose} waits for them. */
|
|
9601
|
+
inFlightEvents = /* @__PURE__ */ new Set();
|
|
9553
9602
|
/** `undefined` while online; the failure reason once a sync degrades. */
|
|
9554
9603
|
syncDegradedReason;
|
|
9555
9604
|
/** Epoch-ms of the last successful provider sync, if any. */
|
|
9556
9605
|
lastSyncedAt;
|
|
9557
9606
|
syncedAtByScript = /* @__PURE__ */ new Map();
|
|
9607
|
+
syncsInFlight = 0;
|
|
9608
|
+
/** The off-critical-path boot sequence, if one is running. @see runBootSequence */
|
|
9609
|
+
bootTask;
|
|
9610
|
+
/** A catch-up sync requested behind a stored read. @see requestCatchUpSync */
|
|
9611
|
+
catchUpSync;
|
|
9558
9612
|
/** Last chain tip read, with the epoch-ms it was read at. @see currentChainTip */
|
|
9559
9613
|
chainTipCache;
|
|
9560
9614
|
/** In-flight chain tip read, so concurrent cache misses share one. */
|
|
@@ -9595,12 +9649,18 @@ var ContractManager = class _ContractManager {
|
|
|
9595
9649
|
* {@link initialize}, {@link getContractsWithVtxos} and {@link createContract}.
|
|
9596
9650
|
*/
|
|
9597
9651
|
getSyncState() {
|
|
9598
|
-
|
|
9652
|
+
const syncing = this.syncsInFlight > 0;
|
|
9653
|
+
return this.syncDegradedReason === void 0 ? { mode: "online", syncing, lastSyncedAt: this.lastSyncedAt } : {
|
|
9599
9654
|
mode: "degraded",
|
|
9655
|
+
syncing,
|
|
9600
9656
|
reason: this.syncDegradedReason,
|
|
9601
9657
|
lastSyncedAt: this.lastSyncedAt
|
|
9602
9658
|
};
|
|
9603
9659
|
}
|
|
9660
|
+
/** @inheritdoc */
|
|
9661
|
+
whenBooted() {
|
|
9662
|
+
return this.bootTask ?? Promise.resolve();
|
|
9663
|
+
}
|
|
9604
9664
|
/** @see ContractManagerConfig.vtxoSyncMaxAgeMs — for factory-built managers. */
|
|
9605
9665
|
setVtxoSyncMaxAge(maxAgeMs) {
|
|
9606
9666
|
assertNonNegativeMs("vtxoSyncMaxAgeMs", maxAgeMs);
|
|
@@ -9623,9 +9683,14 @@ var ContractManager = class _ContractManager {
|
|
|
9623
9683
|
syncGapReason() {
|
|
9624
9684
|
const annotations = this.annotationDegradedReason();
|
|
9625
9685
|
const owedRefill = this.lookAheadRefillOwed ? "the look-ahead band is behind the allocation watermark, so a funded address inside it is not being watched yet" : void 0;
|
|
9626
|
-
const
|
|
9686
|
+
const watcher = this.watcherStartFailure === void 0 ? void 0 : `the contract watcher failed to start, so incoming funds are not being observed \u2014 ${this.watcherStartFailure}`;
|
|
9687
|
+
const reasons = [annotations, owedRefill, watcher].filter(
|
|
9688
|
+
(r) => r !== void 0
|
|
9689
|
+
);
|
|
9627
9690
|
return reasons.length === 0 ? void 0 : reasons.join("; ");
|
|
9628
9691
|
}
|
|
9692
|
+
/** Why the lazy boot's watcher start failed; nothing retries it, so no sync may clear it. */
|
|
9693
|
+
watcherStartFailure;
|
|
9629
9694
|
/** Contracts a sync could not annotate, as `script → reason`. */
|
|
9630
9695
|
annotationFailures = /* @__PURE__ */ new Map();
|
|
9631
9696
|
annotationDegradedReason() {
|
|
@@ -9670,20 +9735,74 @@ var ContractManager = class _ContractManager {
|
|
|
9670
9735
|
for (const contract of contracts) {
|
|
9671
9736
|
await this.watcher.addContract(contract);
|
|
9672
9737
|
}
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9738
|
+
if (!this.config.lazyInitialization) {
|
|
9739
|
+
try {
|
|
9740
|
+
await this.scheduleLookAheadDrain();
|
|
9741
|
+
} catch (err) {
|
|
9742
|
+
if (!isRetryableProviderError(err)) throw err;
|
|
9743
|
+
this.lookAheadRefillOwed = true;
|
|
9744
|
+
this.markSyncDegraded(err);
|
|
9745
|
+
}
|
|
9746
|
+
await this.trySync(() => this.reconcileWatched());
|
|
9747
|
+
this.initialized = true;
|
|
9748
|
+
this.stopWatcherFn = await this.watcher.startWatching(
|
|
9749
|
+
(event) => this.onWatcherEvent(event)
|
|
9750
|
+
);
|
|
9751
|
+
return;
|
|
9679
9752
|
}
|
|
9680
|
-
await this.trySync(() => this.reconcileWatched());
|
|
9681
9753
|
this.initialized = true;
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9754
|
+
const boot = this.runBootSequence();
|
|
9755
|
+
this.bootTask = boot;
|
|
9756
|
+
void boot.catch(() => {
|
|
9757
|
+
}).finally(() => {
|
|
9758
|
+
if (this.bootTask === boot) this.bootTask = void 0;
|
|
9759
|
+
});
|
|
9760
|
+
}
|
|
9761
|
+
async runBootSequence() {
|
|
9762
|
+
this.syncsInFlight++;
|
|
9763
|
+
this.watcherStartFailure = void 0;
|
|
9764
|
+
try {
|
|
9765
|
+
try {
|
|
9766
|
+
await this.scheduleLookAheadDrain();
|
|
9767
|
+
} catch (err) {
|
|
9768
|
+
this.lookAheadRefillOwed = true;
|
|
9769
|
+
this.reportBackgroundFailure("look-ahead drain", err);
|
|
9770
|
+
}
|
|
9771
|
+
try {
|
|
9772
|
+
await this.reconcileWatched();
|
|
9773
|
+
this.markSyncOnline();
|
|
9774
|
+
} catch (err) {
|
|
9775
|
+
this.reportBackgroundFailure("boot sync", err);
|
|
9776
|
+
}
|
|
9777
|
+
if (this.disposed) return;
|
|
9778
|
+
try {
|
|
9779
|
+
const stopWatching = await this.watcher.startWatching(
|
|
9780
|
+
(event) => this.onWatcherEvent(event)
|
|
9781
|
+
);
|
|
9782
|
+
if (this.disposed) stopWatching();
|
|
9783
|
+
else this.stopWatcherFn = stopWatching;
|
|
9784
|
+
} catch (err) {
|
|
9785
|
+
this.watcherStartFailure = err instanceof Error ? err.message : String(err);
|
|
9786
|
+
this.reportBackgroundFailure("watcher start", err);
|
|
9787
|
+
}
|
|
9788
|
+
} finally {
|
|
9789
|
+
this.syncsInFlight--;
|
|
9790
|
+
}
|
|
9791
|
+
}
|
|
9792
|
+
/** Tracked so {@link dispose} can wait for handlers still writing. */
|
|
9793
|
+
onWatcherEvent(event) {
|
|
9794
|
+
const handled = this.handleContractEvent(event).catch((error) => {
|
|
9795
|
+
console.error("Error handling contract event:", error);
|
|
9686
9796
|
});
|
|
9797
|
+
this.inFlightEvents.add(handled);
|
|
9798
|
+
void handled.finally(() => this.inFlightEvents.delete(handled));
|
|
9799
|
+
}
|
|
9800
|
+
/** No throw: construction returned long ago, so the state is the channel. */
|
|
9801
|
+
reportBackgroundFailure(stage, err) {
|
|
9802
|
+
this.markSyncDegraded(err);
|
|
9803
|
+
if (!isRetryableProviderError(err)) {
|
|
9804
|
+
console.error(`[contracts] background ${stage} failed`, err);
|
|
9805
|
+
}
|
|
9687
9806
|
}
|
|
9688
9807
|
/**
|
|
9689
9808
|
* Delta-sync the watched set (boot and reconnect), then reconcile the pending frontier, which
|
|
@@ -10165,6 +10284,32 @@ var ContractManager = class _ContractManager {
|
|
|
10165
10284
|
vtxos: vtxosByScript.get(contract.script)?.slice() ?? []
|
|
10166
10285
|
}));
|
|
10167
10286
|
}
|
|
10287
|
+
async getStoredContractsWithVtxos(filter) {
|
|
10288
|
+
const contracts = await this.getContracts(filter);
|
|
10289
|
+
if (!this.syncedWithin(contracts, this.config.vtxoSyncMaxAgeMs ?? 0)) {
|
|
10290
|
+
this.requestCatchUpSync(contracts);
|
|
10291
|
+
}
|
|
10292
|
+
const vtxos = await this.getVtxosForContracts(contracts);
|
|
10293
|
+
return contracts.map((contract) => ({
|
|
10294
|
+
contract,
|
|
10295
|
+
vtxos: vtxos.filter((vtxo) => vtxo.contractScript === contract.script)
|
|
10296
|
+
}));
|
|
10297
|
+
}
|
|
10298
|
+
requestCatchUpSync(contracts) {
|
|
10299
|
+
if (this.disposed || this.bootTask || this.catchUpSync || contracts.length === 0) return;
|
|
10300
|
+
const run = (async () => {
|
|
10301
|
+
try {
|
|
10302
|
+
await this.syncContracts({ contracts });
|
|
10303
|
+
this.markSyncOnline();
|
|
10304
|
+
} catch (err) {
|
|
10305
|
+
this.reportBackgroundFailure("catch-up sync", err);
|
|
10306
|
+
}
|
|
10307
|
+
})();
|
|
10308
|
+
this.catchUpSync = run;
|
|
10309
|
+
void run.finally(() => {
|
|
10310
|
+
if (this.catchUpSync === run) this.catchUpSync = void 0;
|
|
10311
|
+
});
|
|
10312
|
+
}
|
|
10168
10313
|
async annotateVtxos(vtxos, tapscripts) {
|
|
10169
10314
|
if (vtxos.length === 0) return [];
|
|
10170
10315
|
const scripts = Array.from(new Set(vtxos.map((v) => v.script)));
|
|
@@ -10481,6 +10626,7 @@ var ContractManager = class _ContractManager {
|
|
|
10481
10626
|
}
|
|
10482
10627
|
}
|
|
10483
10628
|
async handleContractEvent(event) {
|
|
10629
|
+
if (this.disposed) return;
|
|
10484
10630
|
if (this.lookAheadRefillOwed) this.requestLookAheadDrain();
|
|
10485
10631
|
try {
|
|
10486
10632
|
switch (event.type) {
|
|
@@ -10534,6 +10680,14 @@ var ContractManager = class _ContractManager {
|
|
|
10534
10680
|
}
|
|
10535
10681
|
/** Sync virtual outputs for the given contracts (default: the watched set). */
|
|
10536
10682
|
async syncContracts(options) {
|
|
10683
|
+
this.syncsInFlight++;
|
|
10684
|
+
try {
|
|
10685
|
+
return await this.performContractSync(options);
|
|
10686
|
+
} finally {
|
|
10687
|
+
this.syncsInFlight--;
|
|
10688
|
+
}
|
|
10689
|
+
}
|
|
10690
|
+
async performContractSync(options) {
|
|
10537
10691
|
const cursor = await getSyncCursor(this.config.walletRepository);
|
|
10538
10692
|
const window2 = options.window ?? computeSyncWindow(cursor, this.config.vtxoSyncOverlapMs);
|
|
10539
10693
|
const mustUpdateCursor = options.contracts === void 0 && options.window === void 0 && (window2.after ?? 0) <= cursor;
|
|
@@ -10702,34 +10856,49 @@ var ContractManager = class _ContractManager {
|
|
|
10702
10856
|
}
|
|
10703
10857
|
return { vtxosByScript: result, promoted };
|
|
10704
10858
|
}
|
|
10705
|
-
/**
|
|
10859
|
+
/**
|
|
10860
|
+
* Stop the watcher, clear callbacks, and mark the manager uninitialized.
|
|
10861
|
+
*
|
|
10862
|
+
* Teardown is synchronous. The returned promise settles once watcher events already being
|
|
10863
|
+
* handled, any look-ahead drain, and any lazy boot sequence finish; after that nothing more is written to the
|
|
10864
|
+
* repositories.
|
|
10865
|
+
*/
|
|
10706
10866
|
dispose() {
|
|
10707
10867
|
this.disposed = true;
|
|
10708
10868
|
const pendingDrain = this.lookAheadDrain;
|
|
10869
|
+
const pendingBoot = this.bootTask;
|
|
10709
10870
|
this.stopWatcherFn?.();
|
|
10710
10871
|
this.stopWatcherFn = void 0;
|
|
10711
10872
|
this.eventCallbacks.clear();
|
|
10712
10873
|
this.lookAheadEntries.clear();
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
});
|
|
10718
|
-
}
|
|
10874
|
+
const drainUnwound = pendingDrain?.catch(() => {
|
|
10875
|
+
}).then(() => {
|
|
10876
|
+
if (this.disposed) this.lookAheadEntries.clear();
|
|
10877
|
+
});
|
|
10719
10878
|
this.initialized = false;
|
|
10879
|
+
return Promise.all([...this.inFlightEvents, drainUnwound, pendingBoot]).then(
|
|
10880
|
+
() => void 0
|
|
10881
|
+
);
|
|
10882
|
+
}
|
|
10883
|
+
/**
|
|
10884
|
+
* Symbol.dispose implementation for the `using` keyword. Teardown is immediate, but it does
|
|
10885
|
+
* not wait for in-flight work; use `await using` for that.
|
|
10886
|
+
*/
|
|
10887
|
+
[Symbol.dispose]() {
|
|
10888
|
+
void this.dispose();
|
|
10720
10889
|
}
|
|
10721
10890
|
/**
|
|
10722
|
-
* Symbol.
|
|
10891
|
+
* Symbol.asyncDispose implementation for the `await using` keyword; waits like {@link dispose}.
|
|
10723
10892
|
* @example
|
|
10724
10893
|
* ```typescript
|
|
10725
10894
|
* {
|
|
10726
|
-
* using manager = await wallet.getContractManager();
|
|
10895
|
+
* await using manager = await wallet.getContractManager();
|
|
10727
10896
|
* // ... use manager
|
|
10728
|
-
* } //
|
|
10897
|
+
* } // disposed, with in-flight events finished
|
|
10729
10898
|
* ```
|
|
10730
10899
|
*/
|
|
10731
|
-
[Symbol.
|
|
10732
|
-
this.dispose();
|
|
10900
|
+
async [Symbol.asyncDispose]() {
|
|
10901
|
+
await this.dispose();
|
|
10733
10902
|
}
|
|
10734
10903
|
};
|
|
10735
10904
|
|
|
@@ -12473,6 +12642,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12473
12642
|
walletRepository;
|
|
12474
12643
|
contractRepository;
|
|
12475
12644
|
delegateProvider;
|
|
12645
|
+
lazyInitialization = false;
|
|
12646
|
+
boardingLoaded = false;
|
|
12476
12647
|
_contractManager;
|
|
12477
12648
|
_contractManagerInitializing;
|
|
12478
12649
|
watcherConfig;
|
|
@@ -12535,9 +12706,11 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12535
12706
|
* construct, so it is safe for readonly callers.
|
|
12536
12707
|
*/
|
|
12537
12708
|
getProviderConnectionState() {
|
|
12709
|
+
const syncing = this._contractManager?.getSyncState().syncing ?? false;
|
|
12538
12710
|
if (this._serverInfoSource === "cache") {
|
|
12539
12711
|
return {
|
|
12540
12712
|
mode: "degraded",
|
|
12713
|
+
syncing,
|
|
12541
12714
|
source: "cache",
|
|
12542
12715
|
provider: "arkade",
|
|
12543
12716
|
reason: "constructed from cached server-info; operator was unreachable at boot",
|
|
@@ -12548,6 +12721,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12548
12721
|
if (sync?.mode === "degraded") {
|
|
12549
12722
|
return {
|
|
12550
12723
|
mode: "degraded",
|
|
12724
|
+
syncing,
|
|
12551
12725
|
source: "repository",
|
|
12552
12726
|
provider: "indexer",
|
|
12553
12727
|
reason: sync.reason,
|
|
@@ -12556,6 +12730,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12556
12730
|
}
|
|
12557
12731
|
return {
|
|
12558
12732
|
mode: "online",
|
|
12733
|
+
syncing,
|
|
12559
12734
|
source: "live",
|
|
12560
12735
|
lastOnlineAt: sync?.lastSyncedAt ?? this._serverInfoLastOnlineAt ?? 0
|
|
12561
12736
|
};
|
|
@@ -12802,6 +12977,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12802
12977
|
);
|
|
12803
12978
|
wallet.vtxoSyncOverlapMs = config.vtxoSyncOverlapMs;
|
|
12804
12979
|
wallet.intentRepository = config.storage?.intentRepository;
|
|
12980
|
+
wallet.lazyInitialization = config.lazyInitialization ?? false;
|
|
12805
12981
|
wallet.virtualTxRepository = config.storage?.virtualTxRepository;
|
|
12806
12982
|
wallet.exitDataCapture = config.storage?.exitDataCapture;
|
|
12807
12983
|
wallet._serverInfoSource = setup.serverInfoSource;
|
|
@@ -12842,6 +13018,19 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12842
13018
|
// The bucketer drops every spent coin and the gate reads contracts only.
|
|
12843
13019
|
this.contractSnapshot(void 0, { unspentOnly: true })
|
|
12844
13020
|
]);
|
|
13021
|
+
return this.balanceFromSnapshot(boardingUtxos, snapshot);
|
|
13022
|
+
}
|
|
13023
|
+
/** Cached balance; inspect connection state and boarding.loaded before displaying zeros. */
|
|
13024
|
+
async getStoredBalance() {
|
|
13025
|
+
const [boardingUtxos, snapshot] = await Promise.all([
|
|
13026
|
+
this.getStoredBoardingUtxos(),
|
|
13027
|
+
this.contractSnapshotStored()
|
|
13028
|
+
]);
|
|
13029
|
+
const balance = await this.balanceFromSnapshot(boardingUtxos, snapshot);
|
|
13030
|
+
balance.boarding.loaded = this.boardingLoaded;
|
|
13031
|
+
return balance;
|
|
13032
|
+
}
|
|
13033
|
+
async balanceFromSnapshot(boardingUtxos, snapshot) {
|
|
12845
13034
|
const vtxos = filterSnapshotVtxos(
|
|
12846
13035
|
snapshot,
|
|
12847
13036
|
{ withRecoverable: true, withUnrolled: true },
|
|
@@ -12868,6 +13057,14 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12868
13057
|
this._pendingSpendOutpoints
|
|
12869
13058
|
);
|
|
12870
13059
|
}
|
|
13060
|
+
/** Cached VTXOs; may be empty before the first sync. Never use for coin selection. */
|
|
13061
|
+
async getStoredVtxos(filter) {
|
|
13062
|
+
return filterSnapshotVtxos(
|
|
13063
|
+
await this.contractSnapshotStored(),
|
|
13064
|
+
filter,
|
|
13065
|
+
this._pendingSpendOutpoints
|
|
13066
|
+
);
|
|
13067
|
+
}
|
|
12871
13068
|
/** @inheritdoc */
|
|
12872
13069
|
async getSpendableVtxos(filter) {
|
|
12873
13070
|
const snapshot = await this.contractSnapshot(filter, {
|
|
@@ -12972,6 +13169,10 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12972
13169
|
requireSynced: filter?.requireSynced
|
|
12973
13170
|
});
|
|
12974
13171
|
}
|
|
13172
|
+
async contractSnapshotStored() {
|
|
13173
|
+
const contractManager = await this.getContractManager();
|
|
13174
|
+
return contractManager.getStoredContractsWithVtxos ? contractManager.getStoredContractsWithVtxos() : contractManager.getContractsWithVtxos();
|
|
13175
|
+
}
|
|
12975
13176
|
/**
|
|
12976
13177
|
* The two exclusion sets the gate is made of, derived from one snapshot so
|
|
12977
13178
|
* {@link getSpendableVtxos} and the balance answer about the same instant.
|
|
@@ -13236,6 +13437,14 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
13236
13437
|
await this.walletRepository.saveUtxos(
|
|
13237
13438
|
new Map(groups.map((group, i) => [addresses[i], group.coins]))
|
|
13238
13439
|
);
|
|
13440
|
+
for (const [i, group] of groups.entries()) {
|
|
13441
|
+
const fresh = new Set(group.coins.map((coin) => `${coin.txid}:${coin.vout}`));
|
|
13442
|
+
const cached = await collectUtxos(this.walletRepository, addresses[i]);
|
|
13443
|
+
const kept = cached.filter((coin) => fresh.has(`${coin.txid}:${coin.vout}`));
|
|
13444
|
+
if (kept.length === cached.length) continue;
|
|
13445
|
+
await this.walletRepository.deleteUtxos(addresses[i]);
|
|
13446
|
+
if (kept.length > 0) await this.walletRepository.saveUtxos(addresses[i], kept);
|
|
13447
|
+
}
|
|
13239
13448
|
return groups;
|
|
13240
13449
|
}
|
|
13241
13450
|
/**
|
|
@@ -13249,8 +13458,21 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
13249
13458
|
toXOnlySignerHex(hex.encode(this.boardingTapscript.options.serverPubKey))
|
|
13250
13459
|
]);
|
|
13251
13460
|
const groups = await this.getBoardingUtxosForSigners(currentOnly);
|
|
13461
|
+
this.boardingLoaded = true;
|
|
13252
13462
|
return groups.flatMap((g) => g.coins);
|
|
13253
13463
|
}
|
|
13464
|
+
async getStoredBoardingUtxos() {
|
|
13465
|
+
const currentOnly = /* @__PURE__ */ new Set([
|
|
13466
|
+
toXOnlySignerHex(hex.encode(this.boardingTapscript.options.serverPubKey))
|
|
13467
|
+
]);
|
|
13468
|
+
const tapscripts = await this.getBoardingTapscripts(currentOnly);
|
|
13469
|
+
const perAddress = await Promise.all(
|
|
13470
|
+
tapscripts.map(
|
|
13471
|
+
(tapscript) => collectUtxos(this.walletRepository, tapscript.onchainAddress(this.network))
|
|
13472
|
+
)
|
|
13473
|
+
);
|
|
13474
|
+
return perAddress.flat();
|
|
13475
|
+
}
|
|
13254
13476
|
/**
|
|
13255
13477
|
* Subscribe to onchain and offchain notifications for newly received funds.
|
|
13256
13478
|
*
|
|
@@ -13477,6 +13699,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
13477
13699
|
onVtxosSpent = (vtxos) => pruneExitBranches(virtualTxRepository, vtxos);
|
|
13478
13700
|
}
|
|
13479
13701
|
const manager = await ContractManager.create({
|
|
13702
|
+
lazyInitialization: this.lazyInitialization,
|
|
13480
13703
|
indexerProvider: this.indexerProvider,
|
|
13481
13704
|
contractRepository: this.contractRepository,
|
|
13482
13705
|
walletRepository: this.walletRepository,
|
|
@@ -13576,7 +13799,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
13576
13799
|
/** Dispose wallet-owned managers and release background resources. */
|
|
13577
13800
|
async dispose() {
|
|
13578
13801
|
const manager = this._contractManager ?? (this._contractManagerInitializing ? await this._contractManagerInitializing.catch(() => void 0) : void 0);
|
|
13579
|
-
manager?.dispose();
|
|
13802
|
+
await manager?.dispose();
|
|
13580
13803
|
this._contractManager = void 0;
|
|
13581
13804
|
this._contractManagerInitializing = void 0;
|
|
13582
13805
|
}
|
|
@@ -14419,6 +14642,7 @@ var Wallet2 = class extends ReadonlyWallet {
|
|
|
14419
14642
|
},
|
|
14420
14643
|
checkpointExitDelayOverrides
|
|
14421
14644
|
);
|
|
14645
|
+
wallet.lazyInitialization = config.lazyInitialization ?? false;
|
|
14422
14646
|
wallet._serverInfoSource = setup.serverInfoSource;
|
|
14423
14647
|
if (setup.serverInfoSource === "live") {
|
|
14424
14648
|
const now = Date.now();
|
|
@@ -14505,12 +14729,17 @@ var Wallet2 = class extends ReadonlyWallet {
|
|
|
14505
14729
|
*
|
|
14506
14730
|
* @param params - Optional settlement inputs and outputs. When omitted, the wallet settles all eligible funds.
|
|
14507
14731
|
* @param eventCallback - Optional callback invoked for settlement stream events.
|
|
14732
|
+
* @param hooks - Optional phases for preparation and intent registration.
|
|
14508
14733
|
* @returns The finalized Arkade transaction id
|
|
14509
14734
|
*/
|
|
14510
|
-
async settle(params, eventCallback) {
|
|
14511
|
-
return this._withTxLock(() =>
|
|
14735
|
+
async settle(params, eventCallback, hooks) {
|
|
14736
|
+
return this._withTxLock(() => {
|
|
14737
|
+
hooks?.onPhase?.("preparing");
|
|
14738
|
+
const onRegistrationAttempt = hooks?.onPhase ? () => hooks.onPhase?.("registration_attempt") : void 0;
|
|
14739
|
+
return this._settleImpl(params, eventCallback, onRegistrationAttempt);
|
|
14740
|
+
});
|
|
14512
14741
|
}
|
|
14513
|
-
async _settleImpl(params, eventCallback) {
|
|
14742
|
+
async _settleImpl(params, eventCallback, onRegistrationAttempt) {
|
|
14514
14743
|
if (params?.inputs) {
|
|
14515
14744
|
for (const input of params.inputs) {
|
|
14516
14745
|
if (typeof input === "string") {
|
|
@@ -14725,6 +14954,7 @@ var Wallet2 = class extends ReadonlyWallet {
|
|
|
14725
14954
|
}
|
|
14726
14955
|
yield* stream;
|
|
14727
14956
|
})();
|
|
14957
|
+
onRegistrationAttempt?.();
|
|
14728
14958
|
const intentId = await this.safeRegisterIntent(intent, params.inputs);
|
|
14729
14959
|
await this.persistIntentSnapshot(
|
|
14730
14960
|
intentTxId,
|
|
@@ -15736,13 +15966,13 @@ var Wallet2 = class extends ReadonlyWallet {
|
|
|
15736
15966
|
*/
|
|
15737
15967
|
async send(...args) {
|
|
15738
15968
|
const params = asSendParams(args);
|
|
15739
|
-
|
|
15969
|
+
const validUntil = captureSendDeadline(params.validUntil);
|
|
15970
|
+
const inputExpiryFloor = captureInputExpiryFloor(params.inputExpiryFloor);
|
|
15971
|
+
assertSendDeadline(validUntil);
|
|
15972
|
+
return this._withTxLock(() => this._sendImpl(params, validUntil, inputExpiryFloor));
|
|
15740
15973
|
}
|
|
15741
|
-
async _sendImpl({
|
|
15742
|
-
|
|
15743
|
-
selectedVtxos,
|
|
15744
|
-
maxChangeFee
|
|
15745
|
-
}) {
|
|
15974
|
+
async _sendImpl({ recipients: args, selectedVtxos, maxChangeFee }, validUntil, inputExpiryFloor) {
|
|
15975
|
+
assertSendDeadline(validUntil);
|
|
15746
15976
|
if (args.length === 0) {
|
|
15747
15977
|
throw new Error("At least one receiver is required");
|
|
15748
15978
|
}
|
|
@@ -15753,6 +15983,10 @@ var Wallet2 = class extends ReadonlyWallet {
|
|
|
15753
15983
|
throw new Error("send({ maxChangeFee }): expected a non-negative safe integer");
|
|
15754
15984
|
}
|
|
15755
15985
|
if (selectedVtxos) {
|
|
15986
|
+
if (inputExpiryFloor) selectedVtxos = selectedVtxos.map(normalizeVtxo);
|
|
15987
|
+
if (inputExpiryFloor && selectedVtxos.some((coin) => !meetsInputExpiryFloor(coin, inputExpiryFloor))) {
|
|
15988
|
+
throw new Error("send({ selectedVtxos }): input expiry floor not met");
|
|
15989
|
+
}
|
|
15756
15990
|
void this.logUngatedInputs("send({ selectedVtxos })", selectedVtxos);
|
|
15757
15991
|
}
|
|
15758
15992
|
const offchainTapscript = this.offchainTapscript;
|
|
@@ -15771,6 +16005,11 @@ var Wallet2 = class extends ReadonlyWallet {
|
|
|
15771
16005
|
withRecoverable: false,
|
|
15772
16006
|
genericallySpendableOnly: true
|
|
15773
16007
|
});
|
|
16008
|
+
if (inputExpiryFloor) {
|
|
16009
|
+
virtualCoins = virtualCoins.filter(
|
|
16010
|
+
(coin) => meetsInputExpiryFloor(coin, inputExpiryFloor)
|
|
16011
|
+
);
|
|
16012
|
+
}
|
|
15774
16013
|
}
|
|
15775
16014
|
const assetChanges = /* @__PURE__ */ new Map();
|
|
15776
16015
|
let selectedCoins = selectedVtxos ? [...selectedVtxos] : [];
|
|
@@ -16005,27 +16244,33 @@ var Wallet2 = class extends ReadonlyWallet {
|
|
|
16005
16244
|
outputs.push(Extension.create(allExtPackets).txOut());
|
|
16006
16245
|
}
|
|
16007
16246
|
const sentAmount = recipients.reduce((sum, r) => sum + r.amount, 0);
|
|
16008
|
-
return this._submitOffchainSpend(
|
|
16009
|
-
|
|
16010
|
-
|
|
16011
|
-
|
|
16012
|
-
|
|
16013
|
-
|
|
16014
|
-
|
|
16015
|
-
|
|
16016
|
-
|
|
16247
|
+
return this._submitOffchainSpend(
|
|
16248
|
+
selectedCoins,
|
|
16249
|
+
outputs,
|
|
16250
|
+
{
|
|
16251
|
+
sentAmount,
|
|
16252
|
+
changeAmount: BigInt(changeAmount),
|
|
16253
|
+
changeVout: changeReceiver ? changeIndex : 0,
|
|
16254
|
+
offchainTapscript,
|
|
16255
|
+
serverPubKey,
|
|
16256
|
+
serverUnrollScript,
|
|
16257
|
+
changeAssets: changeReceiver?.assets
|
|
16258
|
+
},
|
|
16259
|
+
{ validUntil }
|
|
16260
|
+
);
|
|
16017
16261
|
}
|
|
16018
16262
|
/**
|
|
16019
16263
|
* Shared submit/persist tail of `send` and {@link sendSelectedVtxosToSelf}; callers own coin
|
|
16020
16264
|
* selection, outputs and the synchronous epoch snapshot.
|
|
16021
16265
|
*/
|
|
16022
|
-
async _submitOffchainSpend(inputs, outputs, persist) {
|
|
16266
|
+
async _submitOffchainSpend(inputs, outputs, persist, options) {
|
|
16023
16267
|
this._addPendingSpends(inputs);
|
|
16024
16268
|
try {
|
|
16025
|
-
const { arkTxid, signedCheckpointTxs } = await this.
|
|
16269
|
+
const { arkTxid, signedCheckpointTxs } = await this._buildAndSubmitOffchainTx(
|
|
16026
16270
|
inputs,
|
|
16027
16271
|
outputs,
|
|
16028
|
-
persist.serverUnrollScript
|
|
16272
|
+
persist.serverUnrollScript,
|
|
16273
|
+
options
|
|
16029
16274
|
);
|
|
16030
16275
|
await this.updateDbAfterOffchainTx(
|
|
16031
16276
|
inputs,
|
|
@@ -16118,7 +16363,16 @@ var Wallet2 = class extends ReadonlyWallet {
|
|
|
16118
16363
|
*
|
|
16119
16364
|
* @returns The Arkade transaction id and server-signed checkpoint PSBTs (for bookkeeping)
|
|
16120
16365
|
*/
|
|
16121
|
-
async buildAndSubmitOffchainTx(inputs, outputs, serverUnrollScript = this.serverUnrollScript) {
|
|
16366
|
+
async buildAndSubmitOffchainTx(inputs, outputs, serverUnrollScript = this.serverUnrollScript, options) {
|
|
16367
|
+
const validUntil = captureSendDeadline(options?.validUntil);
|
|
16368
|
+
assertSendDeadline(validUntil);
|
|
16369
|
+
return this._withTxLock(
|
|
16370
|
+
() => this._buildAndSubmitOffchainTx(inputs, outputs, serverUnrollScript, { validUntil })
|
|
16371
|
+
);
|
|
16372
|
+
}
|
|
16373
|
+
async _buildAndSubmitOffchainTx(inputs, outputs, serverUnrollScript, options) {
|
|
16374
|
+
const validUntil = captureSendDeadline(options?.validUntil);
|
|
16375
|
+
assertSendDeadline(validUntil);
|
|
16122
16376
|
void this.logUngatedInputs("buildAndSubmitOffchainTx", inputs);
|
|
16123
16377
|
await (await this.getContractManager()).assertAnnotatable(inputs);
|
|
16124
16378
|
const offchainTx = buildOffchainTx(
|
|
@@ -16176,7 +16430,25 @@ var Wallet2 = class extends ReadonlyWallet {
|
|
|
16176
16430
|
{
|
|
16177
16431
|
// Mark pending before submitting — if we crash between submit and
|
|
16178
16432
|
// finalize, the next init recovers via finalizePendingTxs.
|
|
16179
|
-
beforeSubmit: () =>
|
|
16433
|
+
beforeSubmit: async () => {
|
|
16434
|
+
const ownsPendingFlag = validUntil !== void 0 && !await this.hasPendingTxFlag();
|
|
16435
|
+
await this.setPendingTxFlag(true);
|
|
16436
|
+
try {
|
|
16437
|
+
assertSendDeadline(validUntil);
|
|
16438
|
+
} catch (error) {
|
|
16439
|
+
if (ownsPendingFlag) {
|
|
16440
|
+
try {
|
|
16441
|
+
await this.setPendingTxFlag(false);
|
|
16442
|
+
} catch (clearError) {
|
|
16443
|
+
console.error(
|
|
16444
|
+
"Failed to clear pending tx flag after deadline expiry:",
|
|
16445
|
+
clearError
|
|
16446
|
+
);
|
|
16447
|
+
}
|
|
16448
|
+
}
|
|
16449
|
+
throw error;
|
|
16450
|
+
}
|
|
16451
|
+
},
|
|
16180
16452
|
afterFinalize: async () => {
|
|
16181
16453
|
try {
|
|
16182
16454
|
await this.setPendingTxFlag(false);
|
|
@@ -16811,6 +17083,7 @@ var MessageBus = class {
|
|
|
16811
17083
|
delegateProvider,
|
|
16812
17084
|
settlementConfig: config.settlementConfig,
|
|
16813
17085
|
walletMode: config.walletMode,
|
|
17086
|
+
lazyInitialization: config.lazyInitialization,
|
|
16814
17087
|
watcherConfig: config.watcherConfig,
|
|
16815
17088
|
lookAheadWindow: config.lookAheadWindow,
|
|
16816
17089
|
minBatchExpirySeconds: config.minBatchExpirySeconds,
|
|
@@ -16820,6 +17093,7 @@ var MessageBus = class {
|
|
|
16820
17093
|
}
|
|
16821
17094
|
const identity = hydrateIdentity(serialized);
|
|
16822
17095
|
const readonlyWallet = await ReadonlyWallet.create({
|
|
17096
|
+
lazyInitialization: config.lazyInitialization,
|
|
16823
17097
|
identity,
|
|
16824
17098
|
arkProvider,
|
|
16825
17099
|
arkServerPublicKey: config.arkServer.publicKey,
|
|
@@ -17548,9 +17822,11 @@ var WalletMessageHandler = class {
|
|
|
17548
17822
|
// `onWalletInitialized` re-subscribes incoming funds while
|
|
17549
17823
|
// `ensureContractEventBroadcasting` deliberately keeps its subscription, so
|
|
17550
17824
|
// a shared bump would leave the live contract-event emitter permanently
|
|
17551
|
-
// stale,
|
|
17825
|
+
// stale, folding requests in would truncate an in-flight settle, and
|
|
17826
|
+
// sharing with boarding would kill every lazy refresh (see `boardingEpoch`).
|
|
17552
17827
|
incomingFundsEpoch = 0;
|
|
17553
17828
|
contractEventsEpoch = 0;
|
|
17829
|
+
boardingEpoch = 0;
|
|
17554
17830
|
/** Per-request progress callbacks: ends with the handler, not with a re-init. */
|
|
17555
17831
|
requestEpoch = 0;
|
|
17556
17832
|
/**
|
|
@@ -17575,6 +17851,7 @@ var WalletMessageHandler = class {
|
|
|
17575
17851
|
this.requestEpoch++;
|
|
17576
17852
|
this.incomingFundsEpoch++;
|
|
17577
17853
|
this.contractEventsEpoch++;
|
|
17854
|
+
this.boardingEpoch++;
|
|
17578
17855
|
this.channel = void 0;
|
|
17579
17856
|
this.onNextTick = [];
|
|
17580
17857
|
if (this.incomingFundsSubscription) {
|
|
@@ -17616,6 +17893,8 @@ var WalletMessageHandler = class {
|
|
|
17616
17893
|
return this.incomingFundsEpoch;
|
|
17617
17894
|
case "contractEvents":
|
|
17618
17895
|
return this.contractEventsEpoch;
|
|
17896
|
+
case "boarding":
|
|
17897
|
+
return this.boardingEpoch;
|
|
17619
17898
|
case "request":
|
|
17620
17899
|
return this.requestEpoch;
|
|
17621
17900
|
default: {
|
|
@@ -17788,7 +18067,10 @@ var WalletMessageHandler = class {
|
|
|
17788
18067
|
});
|
|
17789
18068
|
}
|
|
17790
18069
|
case "GET_BOARDING_UTXOS": {
|
|
17791
|
-
|
|
18070
|
+
if (!this.readonlyWallet) {
|
|
18071
|
+
throw new WalletNotInitializedError();
|
|
18072
|
+
}
|
|
18073
|
+
const utxos = await this.readonlyWallet.getBoardingUtxos();
|
|
17792
18074
|
return this.tagged({
|
|
17793
18075
|
id,
|
|
17794
18076
|
type: "BOARDING_UTXOS",
|
|
@@ -18064,6 +18346,43 @@ var WalletMessageHandler = class {
|
|
|
18064
18346
|
payload: { txid }
|
|
18065
18347
|
});
|
|
18066
18348
|
}
|
|
18349
|
+
case "SEND_WITH_DEADLINE":
|
|
18350
|
+
case "SEND_WITH_INPUT_EXPIRY_FLOOR": {
|
|
18351
|
+
const wallet = this.requireWallet();
|
|
18352
|
+
const {
|
|
18353
|
+
recipients,
|
|
18354
|
+
selectedVtxos,
|
|
18355
|
+
maxChangeFee,
|
|
18356
|
+
validUntil: wireDeadline
|
|
18357
|
+
} = message.payload;
|
|
18358
|
+
const inputExpiryFloor = message.type === "SEND_WITH_INPUT_EXPIRY_FLOOR" ? captureInputExpiryFloor(
|
|
18359
|
+
message.payload.inputExpiryFloor,
|
|
18360
|
+
true
|
|
18361
|
+
) : void 0;
|
|
18362
|
+
const validUntil = captureSendDeadline(
|
|
18363
|
+
wireDeadline,
|
|
18364
|
+
message.type === "SEND_WITH_DEADLINE"
|
|
18365
|
+
);
|
|
18366
|
+
try {
|
|
18367
|
+
const txid = await wallet.send({
|
|
18368
|
+
recipients,
|
|
18369
|
+
...selectedVtxos ? { selectedVtxos } : {},
|
|
18370
|
+
...maxChangeFee !== void 0 ? { maxChangeFee } : {},
|
|
18371
|
+
validUntil,
|
|
18372
|
+
...inputExpiryFloor ? { inputExpiryFloor } : {}
|
|
18373
|
+
});
|
|
18374
|
+
return this.tagged({ id, type: "SEND_SUCCESS", payload: { txid } });
|
|
18375
|
+
} catch (error) {
|
|
18376
|
+
if (validUntil === void 0 || !(error instanceof SendDeadlineExceededError))
|
|
18377
|
+
throw error;
|
|
18378
|
+
return this.tagged({
|
|
18379
|
+
id,
|
|
18380
|
+
type: "SEND_DEADLINE_EXCEEDED",
|
|
18381
|
+
error,
|
|
18382
|
+
payload: { validUntil }
|
|
18383
|
+
});
|
|
18384
|
+
}
|
|
18385
|
+
}
|
|
18067
18386
|
case "GET_ASSET_DETAILS": {
|
|
18068
18387
|
const { assetId } = message.payload;
|
|
18069
18388
|
const assetDetails = await this.readonlyWallet.assetManager.getAssetDetails(assetId);
|
|
@@ -18259,9 +18578,16 @@ var WalletMessageHandler = class {
|
|
|
18259
18578
|
// Wallet methods
|
|
18260
18579
|
async handleInitWallet({ payload }) {
|
|
18261
18580
|
const { arkServerUrl } = payload;
|
|
18581
|
+
this.lazyBoardingInit = payload.lazyBoarding ?? false;
|
|
18582
|
+
this.boardingEpoch++;
|
|
18583
|
+
this.boardingLoaded = false;
|
|
18262
18584
|
this.indexerProvider = new RestIndexerProvider(arkServerUrl);
|
|
18263
18585
|
await this.onWalletInitialized();
|
|
18264
18586
|
}
|
|
18587
|
+
/** @see RequestInitWallet.payload.lazyBoarding */
|
|
18588
|
+
lazyBoardingInit = false;
|
|
18589
|
+
/** Set once this session has actually fetched the boarding addresses. */
|
|
18590
|
+
boardingLoaded = false;
|
|
18265
18591
|
/**
|
|
18266
18592
|
* The worker's own balance. Same bucketing rules as `Wallet.getBalance` —
|
|
18267
18593
|
* both call {@link computeOffchainBalance} — but deliberately a different
|
|
@@ -18272,7 +18598,7 @@ var WalletMessageHandler = class {
|
|
|
18272
18598
|
*/
|
|
18273
18599
|
async handleGetBalance() {
|
|
18274
18600
|
const [boardingUtxos, { snapshot, vtxos: allVtxos }] = await Promise.all([
|
|
18275
|
-
this.
|
|
18601
|
+
this.getBoardingUtxosForBalance(),
|
|
18276
18602
|
// The bucketer drops every spent coin and the gate reads contracts only.
|
|
18277
18603
|
this.repoSnapshot({ unspentOnly: true })
|
|
18278
18604
|
]);
|
|
@@ -18288,11 +18614,14 @@ var WalletMessageHandler = class {
|
|
|
18288
18614
|
isUnlocked: (vtxo) => unlocked.has(`${vtxo.txid}:${vtxo.vout}`),
|
|
18289
18615
|
dustCarrier: getDustAmount(this.readonlyWallet)
|
|
18290
18616
|
});
|
|
18291
|
-
|
|
18617
|
+
const balance = toWalletBalance(boardingUtxos, offchain);
|
|
18618
|
+
balance.boarding.loaded = this.boardingLoaded;
|
|
18619
|
+
return balance;
|
|
18292
18620
|
}
|
|
18293
|
-
async
|
|
18621
|
+
async getBoardingUtxosForBalance() {
|
|
18294
18622
|
if (!this.readonlyWallet) return [];
|
|
18295
|
-
return this.readonlyWallet.getBoardingUtxos();
|
|
18623
|
+
if (!this.lazyBoardingInit) return this.readonlyWallet.getBoardingUtxos();
|
|
18624
|
+
return this.readonlyWallet.getStoredBoardingUtxos ? this.readonlyWallet.getStoredBoardingUtxos() : this.readonlyWallet.getBoardingUtxos();
|
|
18296
18625
|
}
|
|
18297
18626
|
async onWalletInitialized() {
|
|
18298
18627
|
const wallet = this.readonlyWallet;
|
|
@@ -18302,7 +18631,7 @@ var WalletMessageHandler = class {
|
|
|
18302
18631
|
const init = this.newGeneration("incomingFunds");
|
|
18303
18632
|
await this.ensureContractEventBroadcasting();
|
|
18304
18633
|
if (init.stale) return;
|
|
18305
|
-
await this.refreshCachedData();
|
|
18634
|
+
await this.refreshCachedData({ lazyBoarding: this.lazyBoardingInit });
|
|
18306
18635
|
if (init.stale) return;
|
|
18307
18636
|
if (this.wallet) {
|
|
18308
18637
|
try {
|
|
@@ -18400,32 +18729,75 @@ var WalletMessageHandler = class {
|
|
|
18400
18729
|
}
|
|
18401
18730
|
}
|
|
18402
18731
|
/**
|
|
18403
|
-
* Refresh
|
|
18404
|
-
*
|
|
18405
|
-
* (post-refresh),
|
|
18732
|
+
* Refresh boarding inputs and transaction history. The virtual outputs come
|
|
18733
|
+
* from the contract manager, which runs before this. Shared by
|
|
18734
|
+
* onWalletInitialized (full bootstrap) and reloadWallet (post-refresh),
|
|
18735
|
+
* avoiding duplicate subscriptions and VtxoManager restarts.
|
|
18736
|
+
*
|
|
18737
|
+
* Both legs reach the onchain provider, so `lazyBoarding` moves them both
|
|
18738
|
+
* off the caller's path. @see RequestInitWallet.payload.lazyBoarding
|
|
18406
18739
|
*/
|
|
18407
|
-
async refreshCachedData() {
|
|
18740
|
+
async refreshCachedData(opts) {
|
|
18408
18741
|
if (!this.readonlyWallet || !this.walletRepository) {
|
|
18409
18742
|
return;
|
|
18410
18743
|
}
|
|
18744
|
+
if (opts?.lazyBoarding) {
|
|
18745
|
+
const emitter = this.newEmitter("boarding");
|
|
18746
|
+
void (async () => {
|
|
18747
|
+
await this.refreshBoardingCache(emitter);
|
|
18748
|
+
if (emitter.stale) return;
|
|
18749
|
+
this.boardingLoaded = true;
|
|
18750
|
+
const coins = await this.readonlyWallet?.getStoredBoardingUtxos?.() ?? [];
|
|
18751
|
+
emitter.emit(
|
|
18752
|
+
this.tagged({
|
|
18753
|
+
type: "UTXO_UPDATE",
|
|
18754
|
+
broadcast: true,
|
|
18755
|
+
payload: { coins }
|
|
18756
|
+
})
|
|
18757
|
+
);
|
|
18758
|
+
await this.refreshHistoryCache(emitter);
|
|
18759
|
+
})().catch((error) => {
|
|
18760
|
+
console.warn("[wallet] background refresh failed", error);
|
|
18761
|
+
});
|
|
18762
|
+
return;
|
|
18763
|
+
}
|
|
18764
|
+
await this.refreshBoardingCache();
|
|
18765
|
+
this.boardingLoaded = true;
|
|
18766
|
+
await this.refreshHistoryCache();
|
|
18767
|
+
}
|
|
18768
|
+
/** @param gen - set by a background caller; each write is skipped once it goes stale. */
|
|
18769
|
+
async refreshHistoryCache(gen) {
|
|
18411
18770
|
const wallet = this.readonlyWallet;
|
|
18412
18771
|
const repository = this.walletRepository;
|
|
18772
|
+
if (!wallet || !repository) return;
|
|
18773
|
+
const address = await wallet.getAddress();
|
|
18774
|
+
const txs = await this.buildTransactionHistoryFromCache();
|
|
18775
|
+
if (txs && !gen?.stale) await repository.saveTransactions(address, txs);
|
|
18776
|
+
}
|
|
18777
|
+
/**
|
|
18778
|
+
* @param gen - set by a background caller; each write here is skipped once it goes stale.
|
|
18779
|
+
* The fetch saves the fetched rows itself, before control returns, so that one write is
|
|
18780
|
+
* outside this check.
|
|
18781
|
+
*/
|
|
18782
|
+
async refreshBoardingCache(gen) {
|
|
18783
|
+
const wallet = this.readonlyWallet;
|
|
18784
|
+
const repository = this.walletRepository;
|
|
18785
|
+
if (!wallet || !repository) return;
|
|
18413
18786
|
const currentSigner = toXOnlySignerHex(
|
|
18414
18787
|
hex.encode(wallet.boardingTapscript.options.serverPubKey)
|
|
18415
18788
|
);
|
|
18416
18789
|
const groups = await wallet.getBoardingUtxosForSigners(/* @__PURE__ */ new Set([currentSigner]));
|
|
18417
18790
|
for (const { tapscript, coins } of groups) {
|
|
18418
|
-
|
|
18791
|
+
if (gen?.stale) return;
|
|
18792
|
+
const address = tapscript.onchainAddress(wallet.network);
|
|
18419
18793
|
const freshKeys = new Set(coins.map((coin) => `${coin.txid}:${coin.vout}`));
|
|
18420
|
-
const cached = await collectUtxos(repository,
|
|
18794
|
+
const cached = await collectUtxos(repository, address);
|
|
18421
18795
|
const kept = cached.filter((coin) => freshKeys.has(`${coin.txid}:${coin.vout}`));
|
|
18422
18796
|
if (kept.length === cached.length) continue;
|
|
18423
|
-
|
|
18424
|
-
|
|
18797
|
+
if (gen?.stale) return;
|
|
18798
|
+
await repository.deleteUtxos(address);
|
|
18799
|
+
if (kept.length > 0) await repository.saveUtxos(address, kept);
|
|
18425
18800
|
}
|
|
18426
|
-
const address = await this.readonlyWallet.getAddress();
|
|
18427
|
-
const txs = await this.buildTransactionHistoryFromCache();
|
|
18428
|
-
if (txs) await this.walletRepository.saveTransactions(address, txs);
|
|
18429
18801
|
}
|
|
18430
18802
|
/**
|
|
18431
18803
|
* Force a full VTXO refresh from the indexer, then refresh cached data.
|
|
@@ -18519,6 +18891,8 @@ var WalletMessageHandler = class {
|
|
|
18519
18891
|
this.requestEpoch++;
|
|
18520
18892
|
this.incomingFundsEpoch++;
|
|
18521
18893
|
this.contractEventsEpoch++;
|
|
18894
|
+
this.boardingEpoch++;
|
|
18895
|
+
this.boardingLoaded = false;
|
|
18522
18896
|
this.onNextTick = [];
|
|
18523
18897
|
if (this.incomingFundsSubscription) {
|
|
18524
18898
|
this.incomingFundsSubscription();
|
|
@@ -18722,6 +19096,8 @@ var DEFAULT_MESSAGE_TIMEOUTS = {
|
|
|
18722
19096
|
// are treated as long-running on both sides of the bus: the values below
|
|
18723
19097
|
// are retained only for type completeness and are never enforced.
|
|
18724
19098
|
SEND: 5e4,
|
|
19099
|
+
SEND_WITH_DEADLINE: 5e4,
|
|
19100
|
+
SEND_WITH_INPUT_EXPIRY_FLOOR: 5e4,
|
|
18725
19101
|
SETTLE: 5e4,
|
|
18726
19102
|
// Broadcast: the server round-trip a spend ends in, so it belongs
|
|
18727
19103
|
// with the writes rather than the reads above.
|
|
@@ -18919,6 +19295,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
18919
19295
|
const serializedWallet = await serializeReadonlyIdentity(options.identity);
|
|
18920
19296
|
return _ServiceWorkerReadonlyWallet.bootstrap(wallet, options, serializedWallet, {
|
|
18921
19297
|
delegateUrl: options.delegateUrl,
|
|
19298
|
+
lazyInitialization: options.lazyInitialization,
|
|
18922
19299
|
watcherConfig: options.watcherConfig
|
|
18923
19300
|
});
|
|
18924
19301
|
}
|
|
@@ -18926,6 +19303,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
18926
19303
|
static async bootstrap(wallet, options, serializedWallet, busConfig) {
|
|
18927
19304
|
const arkServer = options.arkServer ?? { url: DEFAULT_ARKADE_SERVER_URL };
|
|
18928
19305
|
const initWalletPayload = {
|
|
19306
|
+
lazyBoarding: options.lazyBoarding,
|
|
18929
19307
|
arkServerUrl: arkServer.url,
|
|
18930
19308
|
arkServerPublicKey: arkServer.publicKey
|
|
18931
19309
|
};
|
|
@@ -19008,6 +19386,16 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
19008
19386
|
if (request.id !== response.id) {
|
|
19009
19387
|
return;
|
|
19010
19388
|
}
|
|
19389
|
+
if (response.type === "SEND_DEADLINE_EXCEEDED") {
|
|
19390
|
+
if (event.source !== this.serviceWorker || response.tag !== request.tag) return;
|
|
19391
|
+
cleanup();
|
|
19392
|
+
if ((request.type === "SEND_WITH_DEADLINE" || request.type === "SEND_WITH_INPUT_EXPIRY_FLOOR") && response.error instanceof Error && (response.broadcast === void 0 || response.broadcast === false) && Number.isSafeInteger(response.payload?.validUntil) && response.payload.validUntil > 0 && response.payload.validUntil === request.payload.validUntil) {
|
|
19393
|
+
reject(new SendDeadlineExceededError(request.payload.validUntil));
|
|
19394
|
+
} else {
|
|
19395
|
+
reject(new Error("Invalid timed-send refusal response"));
|
|
19396
|
+
}
|
|
19397
|
+
return;
|
|
19398
|
+
}
|
|
19011
19399
|
cleanup();
|
|
19012
19400
|
if (response.error) {
|
|
19013
19401
|
reject(restoreErrorName(response));
|
|
@@ -19750,8 +20138,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
19750
20138
|
});
|
|
19751
20139
|
}
|
|
19752
20140
|
},
|
|
19753
|
-
dispose() {
|
|
19754
|
-
return;
|
|
20141
|
+
async dispose() {
|
|
19755
20142
|
},
|
|
19756
20143
|
[Symbol.dispose]() {
|
|
19757
20144
|
return;
|
|
@@ -19811,6 +20198,7 @@ var ServiceWorkerWallet = class _ServiceWorkerWallet extends ServiceWorkerReadon
|
|
|
19811
20198
|
delegateUrl: options.delegateUrl,
|
|
19812
20199
|
settlementConfig: options.settlementConfig,
|
|
19813
20200
|
walletMode: options.walletMode,
|
|
20201
|
+
lazyInitialization: options.lazyInitialization,
|
|
19814
20202
|
watcherConfig: options.watcherConfig,
|
|
19815
20203
|
lookAheadWindow: options.lookAheadWindow,
|
|
19816
20204
|
minBatchExpirySeconds: options.minBatchExpirySeconds,
|
|
@@ -20048,27 +20436,51 @@ var ServiceWorkerWallet = class _ServiceWorkerWallet extends ServiceWorkerReadon
|
|
|
20048
20436
|
}
|
|
20049
20437
|
async send(...args) {
|
|
20050
20438
|
const [first] = args;
|
|
20051
|
-
const {
|
|
20439
|
+
const {
|
|
20440
|
+
recipients,
|
|
20441
|
+
selectedVtxos,
|
|
20442
|
+
maxChangeFee,
|
|
20443
|
+
validUntil: wireDeadline,
|
|
20444
|
+
inputExpiryFloor: wireInputExpiryFloor
|
|
20445
|
+
} = args.length === 1 && first && "recipients" in first ? first : {
|
|
20052
20446
|
recipients: args,
|
|
20053
20447
|
selectedVtxos: void 0,
|
|
20054
|
-
maxChangeFee: void 0
|
|
20448
|
+
maxChangeFee: void 0,
|
|
20449
|
+
validUntil: void 0,
|
|
20450
|
+
inputExpiryFloor: void 0
|
|
20055
20451
|
};
|
|
20056
|
-
const
|
|
20452
|
+
const validUntil = captureSendDeadline(wireDeadline);
|
|
20453
|
+
const inputExpiryFloor = captureInputExpiryFloor(wireInputExpiryFloor);
|
|
20454
|
+
const options = {
|
|
20455
|
+
...selectedVtxos ? { selectedVtxos } : {},
|
|
20456
|
+
...maxChangeFee !== void 0 ? { maxChangeFee } : {}
|
|
20457
|
+
};
|
|
20458
|
+
const message = inputExpiryFloor !== void 0 ? {
|
|
20057
20459
|
tag: this.messageTag,
|
|
20058
|
-
type: "
|
|
20460
|
+
type: "SEND_WITH_INPUT_EXPIRY_FLOOR",
|
|
20059
20461
|
id: getRandomId(),
|
|
20060
|
-
// Omitted rather than sent as `undefined`, so an older worker sees
|
|
20061
|
-
// exactly the payload it saw before.
|
|
20062
20462
|
payload: {
|
|
20063
20463
|
recipients,
|
|
20064
|
-
...
|
|
20065
|
-
|
|
20464
|
+
...options,
|
|
20465
|
+
inputExpiryFloor,
|
|
20466
|
+
...validUntil === void 0 ? {} : { validUntil }
|
|
20066
20467
|
}
|
|
20468
|
+
} : validUntil === void 0 ? {
|
|
20469
|
+
tag: this.messageTag,
|
|
20470
|
+
type: "SEND",
|
|
20471
|
+
id: getRandomId(),
|
|
20472
|
+
payload: { recipients, ...options }
|
|
20473
|
+
} : {
|
|
20474
|
+
tag: this.messageTag,
|
|
20475
|
+
type: "SEND_WITH_DEADLINE",
|
|
20476
|
+
id: getRandomId(),
|
|
20477
|
+
payload: { recipients, ...options, validUntil }
|
|
20067
20478
|
};
|
|
20068
20479
|
try {
|
|
20069
20480
|
const response = await this.sendMessage(message);
|
|
20070
20481
|
return response.payload.txid;
|
|
20071
20482
|
} catch (error) {
|
|
20483
|
+
if (error instanceof SendDeadlineExceededError) throw error;
|
|
20072
20484
|
throw new Error(`Send failed: ${error}`);
|
|
20073
20485
|
}
|
|
20074
20486
|
}
|
|
@@ -23618,6 +24030,7 @@ var ArkadeTransactionBuilder = class {
|
|
|
23618
24030
|
outputs = [];
|
|
23619
24031
|
fundingCoins = [];
|
|
23620
24032
|
assetSpecs = [];
|
|
24033
|
+
extraPackets = [];
|
|
23621
24034
|
coin;
|
|
23622
24035
|
changeScript;
|
|
23623
24036
|
from(coin) {
|
|
@@ -23637,6 +24050,11 @@ var ArkadeTransactionBuilder = class {
|
|
|
23637
24050
|
this.assetSpecs.push(spec);
|
|
23638
24051
|
return this;
|
|
23639
24052
|
}
|
|
24053
|
+
/** Add an extension packet; reusing the asset or emulator packet's type fails at build. */
|
|
24054
|
+
withPacket(packet) {
|
|
24055
|
+
this.extraPackets.push(packet);
|
|
24056
|
+
return this;
|
|
24057
|
+
}
|
|
23640
24058
|
/** Destination for any surplus (inputs − outputs). Required when the spend is not exact. */
|
|
23641
24059
|
change(script) {
|
|
23642
24060
|
this.changeScript = script;
|
|
@@ -23728,6 +24146,7 @@ var ArkadeTransactionBuilder = class {
|
|
|
23728
24146
|
])
|
|
23729
24147
|
);
|
|
23730
24148
|
}
|
|
24149
|
+
packets.push(...this.extraPackets);
|
|
23731
24150
|
if (packets.length > 0) {
|
|
23732
24151
|
attachExtension(arkTx, packets);
|
|
23733
24152
|
}
|
|
@@ -24323,6 +24742,6 @@ function createDefaultPaymentRouter(wallet) {
|
|
|
24323
24742
|
}).use(arkRail()).use(arkAssetRail()).use(onchainRail({ feeInfo: walletFeeSource(wallet) }));
|
|
24324
24743
|
}
|
|
24325
24744
|
|
|
24326
|
-
export { ARKADE_MAGIC, ARKADE_SALTED_PREIMAGE_TAG, ARKADE_SWAP_PREIMAGE_TAG, ASSET_CARRIER_SATS, AbortError, ActivityRegistry, AmbiguousRouteError, ArkNote, ArkadeCash, ArkadeCashCreateError, AssetManager, BIP21, BIP21Error, BIP322, BLOCKED_UPGRADE_TIMEOUT_MS, Batch, CachingArkProvider, ChainedTxType, ConnectionDisposedError, ContractManager, ContractWatcher, DEFAULT_MESSAGE_TIMEOUTS, DEFAULT_MIN_BATCH_EXPIRY_SECONDS, DEFAULT_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, DatabaseUpgradeBlockedError, DelegateManagerImpl, DelegateNotConfiguredError, DescriptorIdentity, DescriptorSigningProviderMissingError, DustChangeError, ELECTRUM_TCP_HOST, ELECTRUM_WS_URL, ESPLORA_URL, ElectrumOnchainProvider, EmulatorPacket, EsploraProvider, Estimator, Extension, ExtensionNotFoundError, ForeignDescriptorError, HDDescriptorProvider, INTENT_TERMINAL_STATES, InMemoryContractRepository, InMemoryIntentRepository, InMemoryVirtualTxRepository, InMemoryWalletRepository, IndexedDBContractRepository, IndexedDBIntentRepository, IndexedDBVirtualTxRepository, IndexedDBWalletRepository, KeyringDescriptorProvider, MAX_PAGE_SIZE, MAX_USED_SIGNING_DESCRIPTORS_LOOK_AHEAD, MESSAGE_BUS_INITIALIZING, MESSAGE_BUS_NOT_INITIALIZED, MUTINYNET_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, OversizedChangeError, P2A, PaymentRouter, PrevTxUnavailableError, REGTEST_MIN_BATCH_EXPIRY_SECONDS, REGTEST_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestEmulatorProvider, SIGNET_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, SeedIdentity, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, StaticDescriptorProvider, TxTree, TxType, TxWeightEstimator, UnannotatableInputError, UnilateralExit, UnknownPacket, Unroll, VtxoManager, Wallet2 as Wallet, WalletCannotAllocateAddressError, WalletCannotSignError, WalletMessageHandler, WalletNotInitializedError, WsElectrumChainSource, adoptContractDescriptor, arkAssetRail, arkRail, arkTarget, arkade_exports, assertFinalCommitmentMatchesValidated, assertHistoryPageFilter, assertIntentIdUnique, assertNoAssets, assertNoSelection, assertPageRequest, assertRecipientArkadeAddress, assertSendableAmount, assertSubmittedArkTxid, assertValidBatchExpiry, assertValidServerUnrollScript, assetMintResolver, assetsOf, attachPrevArkTxs, attachPrevoutTxs, awaitTransaction, boardingResolver, btcTarget, buildForfeitTx, buildOffchainTx, buildPreimageMessage, buildSaltedPreimageMessage, checkSaveVtxosForScript, claimWithPreimageIdentity, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, collabExitResolver, collectContracts, collectIntents, collectPages, collectScriptVtxos, collectTransactionHistory, collectUtxos, collectVtxos, combineTapscriptSigs, compareHistoryCursors, contractFilterMatchesNothing, contractFromArkContract, contractFromArkContractWithAddress, contractPreimage, contractSigner, createAssetPacket, createDefaultActivityRegistry, createDefaultPaymentRouter, createExitChainResolver, createManagedConnection, createdAtToIso, decodeArkContract, defaultBatchExpiryPolicy, defaultCheckpointExitDelayPolicy, deleteByIndex, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, exitObserverFor, extendVirtualCoinForContract, extractArkProviderUrl, gateExclusion, gatedContracts, getAllByIndexValues, getRandomId, hasBoardingTxExpired, hasCandidates, intentMatchesFilter, invoiceTarget, isAddressAllocationCapable, isArkContract, isBatchSignable, isBtcAddress, isContractGenericallySpendable, isContractVtxoEvent, isCooperativelyMigratable, isDeterministicSigner, isDiscoverable, isHDAllocationCapable, isHDDeterministicSignCapable, isHDWalletCapable, isLightningInvoice, isLnurl, isMessageBusInitializingError, isMessageBusNotInitializedError, isPerArtifactDescriptor, isSigningIdentity, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, iteratePages, legacyVtxoFacts, logExcludedVtxos, makeHandle, matchServerCheckpoints, mergeChainedTxType, notifyExitObserved, onchainRail, openDatabase, outpointExclusion, outpointReasons, pageResult, promisifyRequest, provisionClaimSecret, provisionRefundKey, registerWalletRestoreHook, resolveAssetAmount, resolveBatchExpiryPolicy, resolveCheckpointExitDelayPolicy, resolveDescriptorSigner, resolvePrevTxs, resolveSendAmount, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, selectionOf, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signAndSubmitOffchainTx, signerSetFromInfo, signingDescriptorIndex, strictSigningDescriptorIndex, toXOnlySignerHex, tryResolveSendAmount, utxoEntries, validateBatchRecipients, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, walletFeeSource, warnAndFilterVtxosForScript, withPrevTxs };
|
|
24327
|
-
//# sourceMappingURL=chunk-
|
|
24328
|
-
//# sourceMappingURL=chunk-
|
|
24745
|
+
export { ARKADE_MAGIC, ARKADE_SALTED_PREIMAGE_TAG, ARKADE_SWAP_PREIMAGE_TAG, ASSET_CARRIER_SATS, AbortError, ActivityRegistry, AmbiguousRouteError, ArkNote, ArkadeCash, ArkadeCashCreateError, AssetManager, BIP21, BIP21Error, BIP322, BLOCKED_UPGRADE_TIMEOUT_MS, Batch, CachingArkProvider, ChainedTxType, ConnectionDisposedError, ContractManager, ContractWatcher, DEFAULT_MESSAGE_TIMEOUTS, DEFAULT_MIN_BATCH_EXPIRY_SECONDS, DEFAULT_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, DatabaseUpgradeBlockedError, DelegateManagerImpl, DelegateNotConfiguredError, DescriptorIdentity, DescriptorSigningProviderMissingError, DustChangeError, ELECTRUM_TCP_HOST, ELECTRUM_WS_URL, ESPLORA_URL, ElectrumOnchainProvider, EmulatorPacket, EsploraProvider, Estimator, Extension, ExtensionNotFoundError, ForeignDescriptorError, HDDescriptorProvider, INTENT_TERMINAL_STATES, InMemoryContractRepository, InMemoryIntentRepository, InMemoryVirtualTxRepository, InMemoryWalletRepository, IndexedDBContractRepository, IndexedDBIntentRepository, IndexedDBVirtualTxRepository, IndexedDBWalletRepository, KeyringDescriptorProvider, MAX_PAGE_SIZE, MAX_USED_SIGNING_DESCRIPTORS_LOOK_AHEAD, MESSAGE_BUS_INITIALIZING, MESSAGE_BUS_NOT_INITIALIZED, MUTINYNET_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, OversizedChangeError, P2A, PaymentRouter, PrevTxUnavailableError, REGTEST_MIN_BATCH_EXPIRY_SECONDS, REGTEST_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestEmulatorProvider, SIGNET_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, SeedIdentity, SendDeadlineExceededError, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, StaticDescriptorProvider, TxTree, TxType, TxWeightEstimator, UnannotatableInputError, UnilateralExit, UnknownPacket, Unroll, VtxoManager, Wallet2 as Wallet, WalletCannotAllocateAddressError, WalletCannotSignError, WalletMessageHandler, WalletNotInitializedError, WsElectrumChainSource, adoptContractDescriptor, arkAssetRail, arkRail, arkTarget, arkade_exports, assertFinalCommitmentMatchesValidated, assertHistoryPageFilter, assertIntentIdUnique, assertNoAssets, assertNoSelection, assertPageRequest, assertRecipientArkadeAddress, assertSendDeadline, assertSendableAmount, assertSubmittedArkTxid, assertValidBatchExpiry, assertValidServerUnrollScript, assetMintResolver, assetsOf, attachPrevArkTxs, attachPrevoutTxs, awaitTransaction, boardingResolver, btcTarget, buildForfeitTx, buildOffchainTx, buildPreimageMessage, buildSaltedPreimageMessage, captureSendDeadline, checkSaveVtxosForScript, claimWithPreimageIdentity, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, collabExitResolver, collectContracts, collectIntents, collectPages, collectScriptVtxos, collectTransactionHistory, collectUtxos, collectVtxos, combineTapscriptSigs, compareHistoryCursors, contractFilterMatchesNothing, contractFromArkContract, contractFromArkContractWithAddress, contractPreimage, contractSigner, createAssetPacket, createDefaultActivityRegistry, createDefaultPaymentRouter, createExitChainResolver, createManagedConnection, createdAtToIso, decodeArkContract, defaultBatchExpiryPolicy, defaultCheckpointExitDelayPolicy, deleteByIndex, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, exitObserverFor, extendVirtualCoinForContract, extractArkProviderUrl, gateExclusion, gatedContracts, getAllByIndexValues, getRandomId, hasBoardingTxExpired, hasCandidates, intentMatchesFilter, invoiceTarget, isAddressAllocationCapable, isArkContract, isBatchSignable, isBtcAddress, isContractGenericallySpendable, isContractVtxoEvent, isCooperativelyMigratable, isDeterministicSigner, isDiscoverable, isHDAllocationCapable, isHDDeterministicSignCapable, isHDWalletCapable, isLightningInvoice, isLnurl, isMessageBusInitializingError, isMessageBusNotInitializedError, isPerArtifactDescriptor, isSigningIdentity, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, iteratePages, legacyVtxoFacts, logExcludedVtxos, makeHandle, matchServerCheckpoints, mergeChainedTxType, notifyExitObserved, onchainRail, openDatabase, outpointExclusion, outpointReasons, pageResult, promisifyRequest, provisionClaimSecret, provisionRefundKey, registerWalletRestoreHook, resolveAssetAmount, resolveBatchExpiryPolicy, resolveCheckpointExitDelayPolicy, resolveDescriptorSigner, resolvePrevTxs, resolveSendAmount, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, selectionOf, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signAndSubmitOffchainTx, signerSetFromInfo, signingDescriptorIndex, strictSigningDescriptorIndex, toXOnlySignerHex, tryResolveSendAmount, utxoEntries, validateBatchRecipients, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, walletFeeSource, warnAndFilterVtxosForScript, withPrevTxs };
|
|
24746
|
+
//# sourceMappingURL=chunk-ENGV6VZF.js.map
|
|
24747
|
+
//# sourceMappingURL=chunk-ENGV6VZF.js.map
|