@arkade-os/sdk 0.4.31 → 0.4.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/adapters/expo.cjs +4 -4
  2. package/dist/adapters/expo.d.cts +2 -2
  3. package/dist/adapters/expo.d.ts +2 -2
  4. package/dist/adapters/expo.js +2 -2
  5. package/dist/adapters/indexedDB.cjs +4 -4
  6. package/dist/adapters/indexedDB.js +3 -3
  7. package/dist/{ark-ibLW4Hte.d.cts → ark-DEsDMYGv.d.cts} +17 -4
  8. package/dist/{ark-ibLW4Hte.d.ts → ark-DEsDMYGv.d.ts} +17 -4
  9. package/dist/{asyncStorageTaskQueue-BEOFPNc0.d.ts → asyncStorageTaskQueue-CMrTYlKG.d.ts} +1 -1
  10. package/dist/{asyncStorageTaskQueue-VGHXWR9F.d.cts → asyncStorageTaskQueue-D8T1VXEx.d.cts} +1 -1
  11. package/dist/{chunk-GIGILVVP.cjs → chunk-5CCRRL5S.cjs} +8 -8
  12. package/dist/{chunk-GIGILVVP.cjs.map → chunk-5CCRRL5S.cjs.map} +1 -1
  13. package/dist/{chunk-GPZH5QNA.cjs → chunk-7K3ROJF6.cjs} +315 -146
  14. package/dist/chunk-7K3ROJF6.cjs.map +1 -0
  15. package/dist/{chunk-YA4G7RFB.js → chunk-AOJUURHM.js} +30 -6
  16. package/dist/chunk-AOJUURHM.js.map +1 -0
  17. package/dist/{chunk-AXGVYRAL.js → chunk-BU3BU6XK.js} +3 -3
  18. package/dist/{chunk-AXGVYRAL.js.map → chunk-BU3BU6XK.js.map} +1 -1
  19. package/dist/{chunk-HJM6JPG4.js → chunk-DSS2GQUG.js} +224 -55
  20. package/dist/chunk-DSS2GQUG.js.map +1 -0
  21. package/dist/{chunk-6NWNOLL3.js → chunk-E22HEKLN.js} +3 -3
  22. package/dist/chunk-E22HEKLN.js.map +1 -0
  23. package/dist/{chunk-IEO3XDKI.cjs → chunk-GYSK5R57.cjs} +32 -5
  24. package/dist/chunk-GYSK5R57.cjs.map +1 -0
  25. package/dist/{chunk-RN2OFLC3.cjs → chunk-HAVA4XB7.cjs} +7 -7
  26. package/dist/{chunk-RN2OFLC3.cjs.map → chunk-HAVA4XB7.cjs.map} +1 -1
  27. package/dist/{chunk-ABWRLTX5.js → chunk-L6ZETTX3.js} +3 -3
  28. package/dist/{chunk-ABWRLTX5.js.map → chunk-L6ZETTX3.js.map} +1 -1
  29. package/dist/{chunk-6FLL2Q36.cjs → chunk-SPDNHPM4.cjs} +3 -3
  30. package/dist/chunk-SPDNHPM4.cjs.map +1 -0
  31. package/dist/contracts/handlers/index.cjs +9 -5
  32. package/dist/contracts/handlers/index.d.cts +3 -3
  33. package/dist/contracts/handlers/index.d.ts +3 -3
  34. package/dist/contracts/handlers/index.js +1 -1
  35. package/dist/{delegate-BvNTw44a.d.cts → delegate-BJeBNP5a.d.cts} +10 -2
  36. package/dist/{delegate-BXaR1RNG.d.ts → delegate-EXN2mfkb.d.ts} +10 -2
  37. package/dist/{index-BusKawmy.d.ts → index-BG2ooYKO.d.ts} +57 -3
  38. package/dist/{index-C-5Tw7VA.d.cts → index-DHjEeHEp.d.cts} +57 -3
  39. package/dist/index.cjs +125 -113
  40. package/dist/index.d.cts +33 -9
  41. package/dist/index.d.ts +33 -9
  42. package/dist/index.js +3 -3
  43. package/dist/repositories/realm/index.cjs +12 -12
  44. package/dist/repositories/realm/index.d.cts +1 -1
  45. package/dist/repositories/realm/index.d.ts +1 -1
  46. package/dist/repositories/realm/index.js +3 -3
  47. package/dist/repositories/sqlite/index.cjs +12 -12
  48. package/dist/repositories/sqlite/index.d.cts +1 -1
  49. package/dist/repositories/sqlite/index.d.ts +1 -1
  50. package/dist/repositories/sqlite/index.js +3 -3
  51. package/dist/{taskRunner-B1igKGAo.d.ts → taskRunner-B7lBU45X.d.ts} +1 -1
  52. package/dist/{taskRunner-By92TQ1m.d.cts → taskRunner-pIGyarFG.d.cts} +1 -1
  53. package/dist/wallet/expo/background.cjs +13 -13
  54. package/dist/wallet/expo/background.d.cts +3 -3
  55. package/dist/wallet/expo/background.d.ts +3 -3
  56. package/dist/wallet/expo/background.js +5 -5
  57. package/dist/wallet/expo/index.cjs +13 -13
  58. package/dist/wallet/expo/index.cjs.map +1 -1
  59. package/dist/wallet/expo/index.d.cts +4 -4
  60. package/dist/wallet/expo/index.d.ts +4 -4
  61. package/dist/wallet/expo/index.js +5 -5
  62. package/dist/wallet/expo/index.js.map +1 -1
  63. package/dist/{wallet-CyM4F7Bs.d.ts → wallet-C4L_X0i6.d.ts} +2 -2
  64. package/dist/{wallet-B_rxgQTu.d.cts → wallet-D4Dll5Gu.d.cts} +2 -2
  65. package/dist/worker/expo/index.cjs +8 -8
  66. package/dist/worker/expo/index.d.cts +4 -4
  67. package/dist/worker/expo/index.d.ts +4 -4
  68. package/dist/worker/expo/index.js +4 -4
  69. package/package.json +1 -1
  70. package/dist/chunk-6FLL2Q36.cjs.map +0 -1
  71. package/dist/chunk-6NWNOLL3.js.map +0 -1
  72. package/dist/chunk-GPZH5QNA.cjs.map +0 -1
  73. package/dist/chunk-HJM6JPG4.js.map +0 -1
  74. package/dist/chunk-IEO3XDKI.cjs.map +0 -1
  75. package/dist/chunk-YA4G7RFB.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { craftToSpendTx, Transaction, OP_RETURN_EMPTY_PKSCRIPT, Intent, getArkPsbtFields, CosignerPublicKey, setArkPsbtField, VtxoTaprootTree, maybeArkError, AssetRef, AssetId, AssetOutput, AssetGroup, AssetInput, Packet, Metadata, isEventSourceError, RestArkProvider, RestIndexerProvider, ArkError, BufferReader } from './chunk-6NWNOLL3.js';
2
- import { isMainnetDescriptor, descriptorIsOurs, contractHandlers, DelegateVtxo, DefaultVtxo, WALLET_RECEIVE_SOURCE, deriveDescriptorLeafPubKey } from './chunk-YA4G7RFB.js';
1
+ import { craftToSpendTx, Transaction, OP_RETURN_EMPTY_PKSCRIPT, Intent, getArkPsbtFields, CosignerPublicKey, setArkPsbtField, VtxoTaprootTree, maybeArkError, AssetRef, AssetId, AssetOutput, AssetGroup, AssetInput, Packet, Metadata, isEventSourceError, RestArkProvider, RestIndexerProvider, ArkError, BufferReader } from './chunk-E22HEKLN.js';
2
+ import { isMainnetDescriptor, descriptorIsOurs, contractHandlers, DelegateVtxo, WALLET_RECEIVE_SOURCE, deriveDescriptorLeafPubKey, DefaultVtxo, BoardingContractHandler } from './chunk-AOJUURHM.js';
3
3
  import { VtxoScript, timelockToSequence, DEFAULT_NETWORK, DEFAULT_NETWORK_NAME, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, ArkAddress, getSequence, CSVMultisigTapscript, getNetwork, MultisigTapscript, networks as networks$1, DEFAULT_ARKADE_SERVER_URL } from './chunk-TU3LVAPX.js';
4
4
  import { sha256, hash160, sha256x2, concatBytes, randomPrivateKeyBytes, pubECDSA, pubSchnorr, equalBytes as equalBytes$1 } from '@scure/btc-signer/utils.js';
5
5
  import { SigHash, Script, p2tr, RawWitness, Address, OutScript, p2wpkh, TaprootControlBlock, DEFAULT_SEQUENCE, Transaction as Transaction$2 } from '@scure/btc-signer';
@@ -1966,12 +1966,22 @@ function verifyTapscriptSignatures(tx, inputIndex, requiredSigners, excludePubke
1966
1966
  }
1967
1967
  }
1968
1968
  function combineTapscriptSigs(signedTx, originalTx) {
1969
+ if (signedTx.inputsLength !== originalTx.inputsLength) {
1970
+ throw new Error(
1971
+ `combineTapscriptSigs: input count mismatch (signedTx ${signedTx.inputsLength}, originalTx ${originalTx.inputsLength})`
1972
+ );
1973
+ }
1969
1974
  for (let i = 0; i < signedTx.inputsLength; i++) {
1970
1975
  const input = originalTx.getInput(i);
1971
1976
  const signedInput = signedTx.getInput(i);
1972
- if (!input.tapScriptSig) throw new Error("No tapScriptSig");
1977
+ if (!input.tapScriptSig) {
1978
+ throw new Error(`combineTapscriptSigs: originalTx input ${i} has no tapScriptSig`);
1979
+ }
1980
+ if (!signedInput.tapScriptSig) {
1981
+ throw new Error(`combineTapscriptSigs: signedTx input ${i} has no tapScriptSig`);
1982
+ }
1973
1983
  originalTx.updateInput(i, {
1974
- tapScriptSig: input.tapScriptSig?.concat(signedInput.tapScriptSig)
1984
+ tapScriptSig: input.tapScriptSig.concat(signedInput.tapScriptSig)
1975
1985
  });
1976
1986
  }
1977
1987
  return originalTx;
@@ -3657,6 +3667,15 @@ var txKey = {
3657
3667
  boardingTxid: "",
3658
3668
  arkTxid: ""
3659
3669
  };
3670
+ function consumeBoardingReceive(boardingTxs, predicate) {
3671
+ const index = boardingTxs.findIndex(predicate);
3672
+ if (index === -1) return false;
3673
+ boardingTxs.splice(index, 1);
3674
+ return true;
3675
+ }
3676
+ function isSettledBoardingReceive(tx) {
3677
+ return tx.type === "RECEIVED" /* TxReceived */ && tx.settled && tx.key.boardingTxid !== "";
3678
+ }
3660
3679
  function collectAssets(vtxos) {
3661
3680
  const map = /* @__PURE__ */ new Map();
3662
3681
  for (const vtxo of vtxos) {
@@ -3696,24 +3715,39 @@ function subtractAssets(spent, change) {
3696
3715
  }
3697
3716
  async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnore, getTxCreatedAt) {
3698
3717
  const fromOldestVtxo = [...vtxos].sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
3718
+ const unmatchedSettledBoardingTxs = allBoardingTxs.filter(isSettledBoardingReceive).sort((a, b) => a.createdAt - b.createdAt);
3699
3719
  const sent = [];
3700
3720
  let received = [];
3701
3721
  for (const vtxo of fromOldestVtxo) {
3702
3722
  if (vtxo.status.isLeaf) {
3703
- if (!commitmentsToIgnore.has(vtxo.virtualStatus.commitmentTxIds[0]) && fromOldestVtxo.filter((v) => v.settledBy === vtxo.virtualStatus.commitmentTxIds[0]).length === 0) {
3704
- const assets = collectAssets([vtxo]);
3705
- received.push({
3706
- key: {
3707
- ...txKey,
3708
- commitmentTxid: vtxo.virtualStatus.commitmentTxIds[0]
3709
- },
3710
- tag: "batch",
3711
- type: "RECEIVED" /* TxReceived */,
3712
- amount: vtxo.value,
3713
- settled: vtxo.status.isLeaf || vtxo.isSpent,
3714
- createdAt: vtxo.createdAt.getTime(),
3715
- ...assets && { assets }
3716
- });
3723
+ const commitmentTxid = vtxo.virtualStatus.commitmentTxIds[0];
3724
+ const vtxoCreatedAt = vtxo.createdAt.getTime();
3725
+ const ignoredCommitment = commitmentsToIgnore.has(commitmentTxid) || !!vtxo.settledBy && commitmentsToIgnore.has(vtxo.settledBy);
3726
+ if (ignoredCommitment) {
3727
+ consumeBoardingReceive(
3728
+ unmatchedSettledBoardingTxs,
3729
+ (tx) => tx.createdAt <= vtxoCreatedAt && (tx.key.commitmentTxid === commitmentTxid || tx.key.commitmentTxid === vtxo.settledBy)
3730
+ );
3731
+ } else if (fromOldestVtxo.filter((v) => v.settledBy === vtxo.virtualStatus.commitmentTxIds[0]).length === 0) {
3732
+ const duplicateBoardingReceive = consumeBoardingReceive(
3733
+ unmatchedSettledBoardingTxs,
3734
+ (tx) => tx.amount === vtxo.value && tx.createdAt <= vtxoCreatedAt
3735
+ );
3736
+ if (!duplicateBoardingReceive) {
3737
+ const assets = collectAssets([vtxo]);
3738
+ received.push({
3739
+ key: {
3740
+ ...txKey,
3741
+ commitmentTxid
3742
+ },
3743
+ tag: "batch",
3744
+ type: "RECEIVED" /* TxReceived */,
3745
+ amount: vtxo.value,
3746
+ settled: vtxo.status.isLeaf || vtxo.isSpent,
3747
+ createdAt: vtxoCreatedAt,
3748
+ ...assets && { assets }
3749
+ });
3750
+ }
3717
3751
  }
3718
3752
  } else if (fromOldestVtxo.filter((v) => v.arkTxId === vtxo.txid).length === 0) {
3719
3753
  const assets = collectAssets([vtxo]);
@@ -7535,7 +7569,7 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
7535
7569
  const newScript = hex.encode(newTapscript.pkScript);
7536
7570
  const newAddress = newTapscript.address(wallet.network.hrp, wallet.arkServerPublicKey).encode();
7537
7571
  const manager = await wallet.getContractManager();
7538
- const csvTimelock = newTapscript.options.csvTimelock ?? DefaultVtxo.Script.DEFAULT_TIMELOCK;
7572
+ const csvTimelock = newTapscript.options.csvTimelock;
7539
7573
  const csvTimelockStr = timelockToSequence(csvTimelock).toString();
7540
7574
  const serverPubKeyHex = hex.encode(newTapscript.options.serverPubKey);
7541
7575
  const baseParams = {
@@ -7668,8 +7702,24 @@ var InputSignerRouter = class {
7668
7702
  constructor(deps) {
7669
7703
  this.deps = deps;
7670
7704
  }
7671
- async sign(tx, jobs) {
7672
- if (jobs.length === 0) return tx;
7705
+ /**
7706
+ * Resolve each job to its target signer without invoking signing. The
7707
+ * returned plan is the single source of truth for both {@link sign} and
7708
+ * the batch-eligibility predicate {@link canBatch} — callers that want
7709
+ * to pre-flight a batch path call {@link canBatch} (which delegates
7710
+ * here) so the routing rules never live in two places.
7711
+ *
7712
+ * Throws {@link MissingSigningDescriptorError} for a non-baseline
7713
+ * default/delegate contract whose `metadata.signingDescriptor` is
7714
+ * missing — the same condition that would later abort signing. Failing
7715
+ * here moves the failure earlier, before any PSBT is mutated.
7716
+ */
7717
+ async classify(jobs) {
7718
+ const identityIndexes = [];
7719
+ const descriptorGroups = /* @__PURE__ */ new Map();
7720
+ if (jobs.length === 0) {
7721
+ return { identityIndexes, descriptorGroups };
7722
+ }
7673
7723
  const distinctScripts = Array.from(new Set(jobs.map((j) => hex.encode(j.lookupScript))));
7674
7724
  const contracts = await this.deps.contractRepository.getContracts({
7675
7725
  script: distinctScripts
@@ -7682,8 +7732,6 @@ var InputSignerRouter = class {
7682
7732
  }
7683
7733
  const baselinePubKeyHex = hex.encode(await this.deps.identity.xOnlyPublicKey());
7684
7734
  const boardingScriptHex = hex.encode(this.deps.boardingPkScript);
7685
- const identityIndexes = [];
7686
- const descriptorGroups = /* @__PURE__ */ new Map();
7687
7735
  for (const job of jobs) {
7688
7736
  const scriptHex = hex.encode(job.lookupScript);
7689
7737
  const contract = scriptToContract.get(scriptHex);
@@ -7716,6 +7764,31 @@ var InputSignerRouter = class {
7716
7764
  descriptorGroups.set(descriptor, [job.index]);
7717
7765
  }
7718
7766
  }
7767
+ return { identityIndexes, descriptorGroups };
7768
+ }
7769
+ /**
7770
+ * Returns `true` when every signable input across all `jobSets` resolves
7771
+ * to the baseline {@link Identity} key — i.e. the descriptor provider
7772
+ * would not be invoked. Used by the wallet's send/recovery paths to
7773
+ * pre-flight the {@link BatchSignableIdentity.signMultiple} fast path,
7774
+ * which can only fold work a single identity key can sign.
7775
+ *
7776
+ * Accepts several job sets (e.g. an arkTx's jobs plus one set per
7777
+ * checkpoint) and classifies their union in a single pass. Eligibility
7778
+ * is monotonic — the union routes entirely to the baseline key iff every
7779
+ * set does — so this returns the same answer as ANDing the per-set
7780
+ * results, but with one {@link classify} (one repo round-trip + one
7781
+ * `xOnlyPublicKey` call) instead of one per set. Only the routing buckets
7782
+ * matter here, so the input-index collisions produced by flattening jobs
7783
+ * from different transactions are irrelevant.
7784
+ */
7785
+ async canBatch(...jobSets) {
7786
+ const plan = await this.classify(jobSets.flat());
7787
+ return plan.descriptorGroups.size === 0;
7788
+ }
7789
+ async sign(tx, jobs) {
7790
+ if (jobs.length === 0) return tx;
7791
+ const { identityIndexes, descriptorGroups } = await this.classify(jobs);
7719
7792
  let signed = tx;
7720
7793
  if (identityIndexes.length > 0) {
7721
7794
  signed = await this.deps.identity.sign(signed, identityIndexes);
@@ -7773,6 +7846,20 @@ function dedupeTimelocks(timelocks) {
7773
7846
  }
7774
7847
  return deduped;
7775
7848
  }
7849
+ function areSameScriptBaselineTypesCompatible(existingType, requestedType) {
7850
+ if (existingType === requestedType) return true;
7851
+ return existingType === "default" && requestedType === "boarding" || existingType === "boarding" && requestedType === "default";
7852
+ }
7853
+ async function ensureWalletContract(manager, params) {
7854
+ const [existing] = await manager.getContracts({ script: params.script });
7855
+ if (existing && existing.type !== params.type && areSameScriptBaselineTypesCompatible(existing.type, params.type)) {
7856
+ if (params.type === "default" && existing.type === "boarding") {
7857
+ await manager.updateContract(params.script, { type: "default" });
7858
+ }
7859
+ return;
7860
+ }
7861
+ await manager.createContract(params);
7862
+ }
7776
7863
  function hasToReadonly(identity) {
7777
7864
  return typeof identity === "object" && identity !== null && "toReadonly" in identity && typeof identity.toReadonly === "function";
7778
7865
  }
@@ -7801,9 +7888,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
7801
7888
  this._offchainTapscript = offchainTapscript;
7802
7889
  this.watcherConfig = watcherConfig;
7803
7890
  this._assetManager = new ReadonlyAssetManager(this.indexerProvider);
7804
- this.walletContractTimelocks = walletContractTimelocks && walletContractTimelocks.length > 0 ? dedupeTimelocks(walletContractTimelocks) : [
7805
- this.offchainTapscript.options.csvTimelock ?? DefaultVtxo.Script.DEFAULT_TIMELOCK
7806
- ];
7891
+ this.walletContractTimelocks = walletContractTimelocks && walletContractTimelocks.length > 0 ? dedupeTimelocks(walletContractTimelocks) : [this.offchainTapscript.options.csvTimelock];
7807
7892
  }
7808
7893
  _contractManager;
7809
7894
  _contractManagerInitializing;
@@ -7909,9 +7994,10 @@ var ReadonlyWallet = class _ReadonlyWallet {
7909
7994
  csvTimelock: exitTimelock
7910
7995
  };
7911
7996
  const offchainTapscript = !delegatePubKey ? new DefaultVtxo.Script(offchainOptions) : new DelegateVtxo.Script({ ...offchainOptions, delegatePubKey });
7912
- const boardingTapscript = new DefaultVtxo.Script({
7913
- ...offchainOptions,
7914
- csvTimelock: boardingTimelock
7997
+ const boardingTapscript = BoardingContractHandler.createScript({
7998
+ pubKey: hex.encode(pubKey),
7999
+ serverPubKey: hex.encode(serverPubKey),
8000
+ csvTimelock: timelockToSequence(boardingTimelock).toString()
7915
8001
  });
7916
8002
  const walletRepository = config.storage?.walletRepository ?? new IndexedDBWalletRepository();
7917
8003
  const contractRepository = config.storage?.contractRepository ?? new IndexedDBContractRepository();
@@ -8120,7 +8206,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
8120
8206
  const tx = {
8121
8207
  key: {
8122
8208
  boardingTxid: utxo.txid,
8123
- commitmentTxid: "",
8209
+ commitmentTxid: utxo.virtualStatus.commitmentTxIds?.[0] ?? "",
8124
8210
  arkTxid: ""
8125
8211
  },
8126
8212
  amount: utxo.value,
@@ -8324,7 +8410,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
8324
8410
  csvTimelock
8325
8411
  });
8326
8412
  const defaultScriptHex = hex.encode(defaultScript.pkScript);
8327
- await manager.createContract({
8413
+ await ensureWalletContract(manager, {
8328
8414
  type: "default",
8329
8415
  params: {
8330
8416
  pubKey: hex.encode(defaultScript.options.pubKey),
@@ -8357,6 +8443,19 @@ var ReadonlyWallet = class _ReadonlyWallet {
8357
8443
  });
8358
8444
  }
8359
8445
  }
8446
+ const boardingScriptHex = hex.encode(this.boardingTapscript.pkScript);
8447
+ const boardingCsvTimelock = this.boardingTapscript.options.csvTimelock ?? DefaultVtxo.Script.DEFAULT_TIMELOCK;
8448
+ await ensureWalletContract(manager, {
8449
+ type: "boarding",
8450
+ params: {
8451
+ pubKey: hex.encode(this.boardingTapscript.options.pubKey),
8452
+ serverPubKey: hex.encode(this.boardingTapscript.options.serverPubKey),
8453
+ csvTimelock: timelockToSequence(boardingCsvTimelock).toString()
8454
+ },
8455
+ script: boardingScriptHex,
8456
+ address: this.boardingTapscript.address(this.network.hrp, this.arkServerPublicKey).encode(),
8457
+ state: "active"
8458
+ });
8360
8459
  return manager;
8361
8460
  }
8362
8461
  /** Dispose wallet-owned managers and release background resources. */
@@ -9306,16 +9405,38 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
9306
9405
  seen.add(pendingTx.arkTxid);
9307
9406
  batchPending.push(pendingTx.arkTxid);
9308
9407
  try {
9309
- const finalCheckpoints = await Promise.all(
9310
- pendingTx.signedCheckpointTxs.map(async (c) => {
9311
- const tx = Transaction$2.fromPSBT(base64.decode(c));
9312
- const signedCheckpoint = await this._signerRouter.sign(
9313
- tx,
9314
- this.inputSigningJobsFromWitnessUtxos(tx)
9315
- );
9316
- return base64.encode(signedCheckpoint.toPSBT());
9317
- })
9408
+ const checkpointTxs = pendingTx.signedCheckpointTxs.map(
9409
+ (c) => Transaction$2.fromPSBT(base64.decode(c))
9410
+ );
9411
+ const checkpointJobs = checkpointTxs.map(
9412
+ (tx) => this.inputSigningJobsFromWitnessUtxos(tx)
9318
9413
  );
9414
+ const identity = this.identity;
9415
+ const batchEligible = isBatchSignable(identity) && await this._signerRouter.canBatch(...checkpointJobs);
9416
+ let finalCheckpoints;
9417
+ if (batchEligible) {
9418
+ const requests = checkpointTxs.map((tx, i) => ({
9419
+ tx,
9420
+ inputIndexes: checkpointJobs[i].map((j) => j.index)
9421
+ }));
9422
+ const signed = await identity.signMultiple(requests);
9423
+ if (signed.length !== requests.length) {
9424
+ throw new Error(
9425
+ `signMultiple returned ${signed.length} transactions, expected ${requests.length}`
9426
+ );
9427
+ }
9428
+ finalCheckpoints = signed.map((tx) => base64.encode(tx.toPSBT()));
9429
+ } else {
9430
+ finalCheckpoints = await Promise.all(
9431
+ checkpointTxs.map(async (tx, i) => {
9432
+ const signedCheckpoint = await this._signerRouter.sign(
9433
+ tx,
9434
+ checkpointJobs[i]
9435
+ );
9436
+ return base64.encode(signedCheckpoint.toPSBT());
9437
+ })
9438
+ );
9439
+ }
9319
9440
  await this.arkProvider.finalizeTx(pendingTx.arkTxid, finalCheckpoints);
9320
9441
  batchFinalized.push(pendingTx.arkTxid);
9321
9442
  } catch (error) {
@@ -9543,22 +9664,65 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
9543
9664
  index,
9544
9665
  lookupScript: VtxoScript.decode(input.tapTree).pkScript
9545
9666
  }));
9546
- const signedVirtualTx = await this._signerRouter.sign(offchainTx.arkTx, arkTxJobs);
9667
+ const checkpointJobs = offchainTx.checkpoints.map(
9668
+ (c) => this.inputSigningJobsFromWitnessUtxos(c)
9669
+ );
9670
+ let signedVirtualTx;
9671
+ let userSignedCheckpoints;
9672
+ const identity = this.identity;
9673
+ const batchEligible = isBatchSignable(identity) && await this._signerRouter.canBatch(arkTxJobs, ...checkpointJobs);
9674
+ if (batchEligible) {
9675
+ const requests = [
9676
+ {
9677
+ tx: offchainTx.arkTx.clone(),
9678
+ inputIndexes: arkTxJobs.map((j) => j.index)
9679
+ },
9680
+ ...offchainTx.checkpoints.map((c, i) => ({
9681
+ tx: c.clone(),
9682
+ inputIndexes: checkpointJobs[i].map((j) => j.index)
9683
+ }))
9684
+ ];
9685
+ const signed = await identity.signMultiple(requests);
9686
+ if (signed.length !== requests.length) {
9687
+ throw new Error(
9688
+ `signMultiple returned ${signed.length} transactions, expected ${requests.length}`
9689
+ );
9690
+ }
9691
+ const [firstSignedTx, ...signedCheckpoints] = signed;
9692
+ signedVirtualTx = firstSignedTx;
9693
+ userSignedCheckpoints = signedCheckpoints;
9694
+ } else {
9695
+ signedVirtualTx = await this._signerRouter.sign(offchainTx.arkTx, arkTxJobs);
9696
+ }
9547
9697
  await this.setPendingTxFlag(true);
9548
9698
  const { arkTxid, signedCheckpointTxs } = await this.arkProvider.submitTx(
9549
9699
  base64.encode(signedVirtualTx.toPSBT()),
9550
9700
  offchainTx.checkpoints.map((c) => base64.encode(c.toPSBT()))
9551
9701
  );
9552
- const finalCheckpoints = await Promise.all(
9553
- signedCheckpointTxs.map(async (c) => {
9554
- const tx = Transaction$2.fromPSBT(base64.decode(c));
9555
- const signedCheckpoint = await this._signerRouter.sign(
9556
- tx,
9557
- this.inputSigningJobsFromWitnessUtxos(tx)
9702
+ let finalCheckpoints;
9703
+ if (userSignedCheckpoints) {
9704
+ if (signedCheckpointTxs.length !== userSignedCheckpoints.length) {
9705
+ throw new Error(
9706
+ `submitTx returned ${signedCheckpointTxs.length} checkpoints, expected ${userSignedCheckpoints.length}`
9558
9707
  );
9559
- return base64.encode(signedCheckpoint.toPSBT());
9560
- })
9561
- );
9708
+ }
9709
+ finalCheckpoints = signedCheckpointTxs.map((c, i) => {
9710
+ const serverSigned = Transaction$2.fromPSBT(base64.decode(c));
9711
+ combineTapscriptSigs(userSignedCheckpoints[i], serverSigned);
9712
+ return base64.encode(serverSigned.toPSBT());
9713
+ });
9714
+ } else {
9715
+ finalCheckpoints = await Promise.all(
9716
+ signedCheckpointTxs.map(async (c) => {
9717
+ const tx = Transaction$2.fromPSBT(base64.decode(c));
9718
+ const signedCheckpoint = await this._signerRouter.sign(
9719
+ tx,
9720
+ this.inputSigningJobsFromWitnessUtxos(tx)
9721
+ );
9722
+ return base64.encode(signedCheckpoint.toPSBT());
9723
+ })
9724
+ );
9725
+ }
9562
9726
  await this.arkProvider.finalizeTx(arkTxid, finalCheckpoints);
9563
9727
  try {
9564
9728
  await this.setPendingTxFlag(false);
@@ -9808,12 +9972,17 @@ function selectVirtualCoins(coins, targetAmount) {
9808
9972
  }
9809
9973
  async function waitForIncomingFunds(wallet) {
9810
9974
  let stopFunc;
9975
+ let settled = false;
9811
9976
  return new Promise((resolve) => {
9812
- wallet.notifyIncomingFunds((coins) => {
9813
- resolve(coins);
9814
- if (stopFunc) stopFunc();
9977
+ wallet.notifyIncomingFunds((funds) => {
9978
+ const hasFunds = funds.type === "utxo" ? funds.coins.length > 0 : funds.newVtxos.length > 0;
9979
+ if (settled || !hasFunds) return;
9980
+ settled = true;
9981
+ resolve(funds);
9982
+ stopFunc?.();
9815
9983
  }).then((stop) => {
9816
9984
  stopFunc = stop;
9985
+ if (settled) stop();
9817
9986
  });
9818
9987
  });
9819
9988
  }
@@ -13990,5 +14159,5 @@ function isArkContract(str) {
13990
14159
  }
13991
14160
 
13992
14161
  export { ArkNote, AssetManager, BIP322, Batch, ContractManager, ContractRepositoryImpl, ContractWatcher, DB_VERSION, DEFAULT_MESSAGE_TIMEOUTS, DelegateManagerImpl, DelegateNotConfiguredError, DelegatorManagerImpl, DelegatorNotConfiguredError, DescriptorSigningProviderMissingError, DustChangeError, ELECTRUM_TCP_HOST, ELECTRUM_WS_URL, ESPLORA_URL, ElectrumOnchainProvider, EsploraProvider, Estimator, HDDescriptorProvider, InMemoryContractRepository, InMemoryWalletRepository, IndexedDBContractRepository, IndexedDBWalletRepository, MESSAGE_BUS_NOT_INITIALIZED, MIGRATION_KEY, MessageBus, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, P2A, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestDelegatorProvider, SeedIdentity, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, TxTree, TxType, TxWeightEstimator, Unroll, VtxoManager, Wallet2 as Wallet, WalletMessageHandler, WalletNotInitializedError, WalletRepositoryImpl, WsElectrumChainSource, buildForfeitTx, buildOffchainTx, closeDatabase, combineTapscriptSigs, contractFromArkContract, contractFromArkContractWithAddress, decodeArkContract, deserializeAssets, deserializeUtxo, deserializeVtxo, encodeArkContract, extendVirtualCoinForContract, getMigrationStatus, getRandomId, hasBoardingTxExpired, isArkContract, isBatchSignable, isDiscoverable, isExpired, isRecoverable, isSpendable, isSubdust, isValidArkAddress, isVtxoExpiringSoon, isVtxoForScript, migrateWalletRepository, openDatabase, requiresMigration, rollbackMigration, saveVtxosForContract, scriptFromArkAddress, serializeAssets, serializeUtxo, serializeVtxo, setupServiceWorker, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, warnAndFilterVtxosForScript };
13993
- //# sourceMappingURL=chunk-HJM6JPG4.js.map
13994
- //# sourceMappingURL=chunk-HJM6JPG4.js.map
14162
+ //# sourceMappingURL=chunk-DSS2GQUG.js.map
14163
+ //# sourceMappingURL=chunk-DSS2GQUG.js.map