@arkade-os/sdk 0.5.3 → 0.5.4

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 (88) hide show
  1. package/README.md +36 -34
  2. package/dist/adapters/expo.cjs +9 -5
  3. package/dist/adapters/expo.d.cts +11 -7
  4. package/dist/adapters/expo.d.ts +11 -7
  5. package/dist/adapters/expo.js +3 -3
  6. package/dist/{asyncStorageTaskQueue-B3U5gQ-i.d.ts → asyncStorageTaskQueue-DHMIxY04.d.ts} +2 -2
  7. package/dist/{asyncStorageTaskQueue-C9PkPcW_.d.cts → asyncStorageTaskQueue-DTBa8EH7.d.cts} +2 -2
  8. package/dist/{chunk-P7B4LQ3H.js → chunk-6CUP6ZIF.js} +4 -4
  9. package/dist/{chunk-P7B4LQ3H.js.map → chunk-6CUP6ZIF.js.map} +1 -1
  10. package/dist/{chunk-OPX2HRWM.js → chunk-AG4TFD6F.js} +137 -59
  11. package/dist/chunk-AG4TFD6F.js.map +1 -0
  12. package/dist/{chunk-5WRA66RV.cjs → chunk-B6VNKGIH.cjs} +10 -10
  13. package/dist/chunk-B6VNKGIH.cjs.map +1 -0
  14. package/dist/{chunk-6FL4N4S2.js → chunk-BTRCN4JJ.js} +22 -19
  15. package/dist/chunk-BTRCN4JJ.js.map +1 -0
  16. package/dist/{chunk-ZPF4I3K2.cjs → chunk-DNITZVNG.cjs} +28 -47
  17. package/dist/chunk-DNITZVNG.cjs.map +1 -0
  18. package/dist/{chunk-BYPBVHVA.cjs → chunk-E6OOJEHL.cjs} +49 -49
  19. package/dist/{chunk-BYPBVHVA.cjs.map → chunk-E6OOJEHL.cjs.map} +1 -1
  20. package/dist/{chunk-OUTWUYJ4.cjs → chunk-F3FAE7VJ.cjs} +769 -619
  21. package/dist/chunk-F3FAE7VJ.cjs.map +1 -0
  22. package/dist/{chunk-KW7ZEWYS.cjs → chunk-GHUUT54D.cjs} +140 -58
  23. package/dist/chunk-GHUUT54D.cjs.map +1 -0
  24. package/dist/{chunk-Y4BL3YYX.js → chunk-MWVAWFX6.js} +4 -4
  25. package/dist/chunk-MWVAWFX6.js.map +1 -0
  26. package/dist/{chunk-T7C3E2HL.js → chunk-TUOLZBNC.js} +19 -39
  27. package/dist/chunk-TUOLZBNC.js.map +1 -0
  28. package/dist/{chunk-ZMSM3NOH.cjs → chunk-WXNSISXK.cjs} +37 -34
  29. package/dist/chunk-WXNSISXK.cjs.map +1 -0
  30. package/dist/{chunk-HAQAWBYG.js → chunk-ZJHLLDBP.js} +283 -136
  31. package/dist/chunk-ZJHLLDBP.js.map +1 -0
  32. package/dist/contracts/handlers/index.cjs +9 -9
  33. package/dist/contracts/handlers/index.d.cts +3 -3
  34. package/dist/contracts/handlers/index.d.ts +3 -3
  35. package/dist/contracts/handlers/index.js +2 -2
  36. package/dist/{delegate-ByfKszb6.d.cts → delegate-f4_t864Z.d.cts} +1 -1
  37. package/dist/{delegate-Cd28gxpM.d.ts → delegate-xrSBNybC.d.ts} +1 -1
  38. package/dist/{index-DgH_0j14.d.cts → index-BJDz15ms.d.ts} +5 -5
  39. package/dist/{index-B6X2E7W_.d.ts → index-BjiVGtp8.d.cts} +5 -5
  40. package/dist/{index-BURzbRup.d.ts → index-DRwe0UDN.d.cts} +182 -114
  41. package/dist/{index-BURzbRup.d.cts → index-DRwe0UDN.d.ts} +182 -114
  42. package/dist/index.cjs +333 -313
  43. package/dist/index.d.cts +66 -44
  44. package/dist/index.d.ts +66 -44
  45. package/dist/index.js +4 -4
  46. package/dist/repositories/realm/index.cjs +65 -36
  47. package/dist/repositories/realm/index.cjs.map +1 -1
  48. package/dist/repositories/realm/index.d.cts +7 -3
  49. package/dist/repositories/realm/index.d.ts +7 -3
  50. package/dist/repositories/realm/index.js +35 -6
  51. package/dist/repositories/realm/index.js.map +1 -1
  52. package/dist/repositories/sqlite/index.cjs +176 -110
  53. package/dist/repositories/sqlite/index.cjs.map +1 -1
  54. package/dist/repositories/sqlite/index.d.cts +23 -13
  55. package/dist/repositories/sqlite/index.d.ts +23 -13
  56. package/dist/repositories/sqlite/index.js +148 -83
  57. package/dist/repositories/sqlite/index.js.map +1 -1
  58. package/dist/{taskRunner-i56-drQV.d.cts → taskRunner-BPPU-YHG.d.cts} +4 -4
  59. package/dist/{taskRunner-BaNCSxqK.d.ts → taskRunner-CDlNeth0.d.ts} +4 -4
  60. package/dist/wallet/expo/background.cjs +14 -14
  61. package/dist/wallet/expo/background.cjs.map +1 -1
  62. package/dist/wallet/expo/background.d.cts +3 -3
  63. package/dist/wallet/expo/background.d.ts +3 -3
  64. package/dist/wallet/expo/background.js +7 -7
  65. package/dist/wallet/expo/background.js.map +1 -1
  66. package/dist/wallet/expo/index.cjs +15 -15
  67. package/dist/wallet/expo/index.cjs.map +1 -1
  68. package/dist/wallet/expo/index.d.cts +6 -6
  69. package/dist/wallet/expo/index.d.ts +6 -6
  70. package/dist/wallet/expo/index.js +6 -6
  71. package/dist/wallet/expo/index.js.map +1 -1
  72. package/dist/{wallet-BjQugVUt.d.cts → wallet-Oc3Wd5gv.d.ts} +22 -18
  73. package/dist/{wallet-BnmhohgZ.d.ts → wallet-jVBDQl6R.d.cts} +22 -18
  74. package/dist/worker/expo/index.cjs +9 -9
  75. package/dist/worker/expo/index.d.cts +4 -4
  76. package/dist/worker/expo/index.d.ts +4 -4
  77. package/dist/worker/expo/index.js +5 -5
  78. package/package.json +1 -1
  79. package/dist/chunk-5WRA66RV.cjs.map +0 -1
  80. package/dist/chunk-6FL4N4S2.js.map +0 -1
  81. package/dist/chunk-HAQAWBYG.js.map +0 -1
  82. package/dist/chunk-KW7ZEWYS.cjs.map +0 -1
  83. package/dist/chunk-OPX2HRWM.js.map +0 -1
  84. package/dist/chunk-OUTWUYJ4.cjs.map +0 -1
  85. package/dist/chunk-T7C3E2HL.js.map +0 -1
  86. package/dist/chunk-Y4BL3YYX.js.map +0 -1
  87. package/dist/chunk-ZMSM3NOH.cjs.map +0 -1
  88. package/dist/chunk-ZPF4I3K2.cjs.map +0 -1
@@ -1,15 +1,15 @@
1
- import { Packet, AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, RestIndexerProvider, BufferReader, BufferWriter, AssetRef } from './chunk-6FL4N4S2.js';
2
- import { witnessRefToBytes, validateProgram, toASM, stringifyArtifact, serializeArkadeContractParams, resolveAsm, parseArtifact, getOpcodeValue, getOpcodeName, fromASM, deserializeArkadeContractParams, computeArkadeScriptPublicKey, bytesToASM, asmToBytes, arkadeWitnessHash, arkadeScriptHash, UnsupportedProgramVersionError, SUPPORTED_PROGRAM_VERSION, OPCODE_VALUES, OPCODE_NAMES, bignum_exports, ArkadeScript, ArkadeProgramScript, ARKADE_OPS, ARKADE_OPCODE_VALUES, ARKADE_OPCODE_NAMES, ARKADE_OPCODES, ARKADE_OP, toXOnly, ARKADE_TYPE_ENCODINGS, validateParamValue, contractHandlers, speculativeReceiveMetadata, isMainnetDescriptor, descriptorIsOurs, deriveDescriptorLeafPubKey, deriveDescriptorLeafCompressedPubKey, normalizeToDescriptor, extractPubKey, parseHDDescriptor, identityDescriptor, DefaultVtxo, DelegateVtxo, WALLET_RECEIVE_SOURCE, BoardingContractHandler } from './chunk-P7B4LQ3H.js';
3
- import { VtxoScript, __export, Transaction, requiresForfeit, CSVMultisigTapscript, networks, getNetwork, DEFAULT_NETWORK, resolveEmulatorPubkey, timelockToSequence, isVtxoSpent, getNormalizedVtxos, setArkPsbtField, PrevArkTxField, ConditionWitness, craftToSpendTx, RestArkProvider, ArkAddress, isVirtualCoin, getArkPsbtFields, CosignerPublicKey, ServerResponseMismatchError, assertNonNegativeMs, isRetryableProviderError, getAllNormalizedVtxos, DEFAULT_PAGE_SIZE, assertAllowedSighashTypes, OP_RETURN_EMPTY_PKSCRIPT, canSweepOnchain, sequenceToTimelock, DEFAULT_ARKADE_SERVER_URL, baseFetch, DEFAULT_NETWORK_NAME, sequenceToCanonicalTimelock, assertTimerMs, isEventSourceError, isEventSourceUnavailableError, normalizeVtxo, isPastExpiry, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, VtxoTaprootTree, formatSighash, isArkError, ArkErrorName, Intent, rateGate, getSequence, maybeArkError, toOffchainInputFeeParams, canRecoverOnchain, MultisigTapscript, DEFAULT_ARKADE_EMULATOR_URL, networkFromArkadeInfo, ArkError, toBIP371TapTree, resolveTimeHeight, canSpendOffchain, INFO_FETCH_TIMEOUT_MS, PrevoutTxField, fetchVtxoCreatedAtByTxid, EXPIRY_MIN_PLAUSIBLE_MS, ProviderUnavailableError } from './chunk-OPX2HRWM.js';
4
- import { sha256, equalBytes, hash160, sha256x2, concatBytes, randomPrivateKeyBytes, pubECDSA, pubSchnorr } from '@scure/btc-signer/utils.js';
5
- import { SigHash, Script, OP, OutScript, Address, RawWitness, p2tr, p2wpkh, TaprootControlBlock, DEFAULT_SEQUENCE, Transaction as Transaction$1 } from '@scure/btc-signer';
6
- import { hex, base58, base64, bech32m } from '@scure/base';
1
+ import { Packet, AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, RestIndexerProvider, BufferReader, BufferWriter, AssetRef } from './chunk-BTRCN4JJ.js';
2
+ import { witnessRefToBytes, validateProgram, toASM, stringifyArtifact, serializeArkadeContractParams, resolveAsm, parseArtifact, getOpcodeValue, getOpcodeName, fromASM, deserializeArkadeContractParams, computeArkadeScriptPublicKey, bytesToASM, asmToBytes, arkadeWitnessHash, arkadeScriptHash, UnsupportedProgramVersionError, SUPPORTED_PROGRAM_VERSION, OPCODE_VALUES, OPCODE_NAMES, bignum_exports, ArkadeScript, ArkadeProgramScript, ARKADE_OPS, ARKADE_OPCODE_VALUES, ARKADE_OPCODE_NAMES, ARKADE_OPCODES, ARKADE_OP, toXOnly, ARKADE_TYPE_ENCODINGS, validateParamValue, contractHandlers, speculativeReceiveMetadata, isMainnetDescriptor, descriptorIsOurs, deriveDescriptorLeafPubKey, deriveDescriptorLeafCompressedPubKey, normalizeToDescriptor, extractPubKey, parseHDDescriptor, identityDescriptor, DefaultVtxo, DelegateVtxo, WALLET_RECEIVE_SOURCE, BoardingContractHandler } from './chunk-6CUP6ZIF.js';
3
+ import { VtxoScript, __export, Transaction, requiresForfeit, CSVMultisigTapscript, networks, getNetwork, DEFAULT_NETWORK, resolveEmulatorPubkey, timelockToSequence, isVtxoSpent, getNormalizedVtxos, setArkPsbtField, PrevArkTxField, ConditionWitness, craftToSpendTx, RestOperatorProvider, ArkAddress, isVirtualCoin, getArkPsbtFields, CosignerPublicKey, ServerResponseMismatchError, assertNonNegativeMs, isRetryableProviderError, getAllNormalizedVtxos, DEFAULT_PAGE_SIZE, assertAllowedSighashTypes, OP_RETURN_EMPTY_PKSCRIPT, canSweepOnchain, sequenceToTimelock, DEFAULT_ARKADE_SERVER_URL, baseFetch, DEFAULT_NETWORK_NAME, sequenceToCanonicalTimelock, assertTimerMs, isEventSourceError, isEventSourceUnavailableError, normalizeVtxo, isPastExpiry, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, VtxoTaprootTree, formatSighash, isArkError, ArkErrorName, Proof, rateGate, getSequence, maybeArkError, toOffchainInputFeeParams, canRecoverOnchain, MultisigTapscript, DEFAULT_ARKADE_EMULATOR_URL, networkFromArkadeInfo, Intent, ArkError, toBIP371TapTree, resolveTimeHeight, canSpendOffchain, INFO_FETCH_TIMEOUT_MS, PrevoutTxField, fetchVtxoCreatedAtByTxid, EXPIRY_MIN_PLAUSIBLE_MS, ProviderUnavailableError } from './chunk-AG4TFD6F.js';
7
4
  import * as musig2 from '@scure/btc-signer/musig2.js';
5
+ import { hex, base58, base64, bech32m } from '@scure/base';
8
6
  import { equalBytes as equalBytes$1, randomBytes, bytesToNumberBE } from '@noble/curves/utils.js';
9
7
  import { signAsync, schnorr as schnorr$1, Point } from '@noble/secp256k1';
10
8
  import { secp256k1, schnorr } from '@noble/curves/secp256k1.js';
11
9
  import { Script as Script$1 } from '@scure/btc-signer/script.js';
12
10
  import { SigHash as SigHash$1 } from '@scure/btc-signer/transaction.js';
11
+ import { sha256, equalBytes, hash160, sha256x2, concatBytes, randomPrivateKeyBytes, pubECDSA, pubSchnorr } from '@scure/btc-signer/utils.js';
12
+ import { SigHash, Script, OP, OutScript, Address, RawWitness, p2tr, p2wpkh, TaprootControlBlock, DEFAULT_SEQUENCE, Transaction as Transaction$1 } from '@scure/btc-signer';
13
13
  import { mnemonicToSeedSync, validateMnemonic } from '@scure/bip39';
14
14
  import { wordlist } from '@scure/bip39/wordlists/english.js';
15
15
  import { networks as networks$1, scriptExpressions, HDKey, expand } from '@bitcoinerlab/descriptors-scure';
@@ -123,6 +123,7 @@ var TreeSignerSession = class _TreeSignerSession {
123
123
  graph = null;
124
124
  scriptRoot = null;
125
125
  rootSharedOutputAmount = null;
126
+ /** Use a fresh key/session per signing attempt; never reuse sessions or their nonces. */
126
127
  static random() {
127
128
  const secretKey = randomPrivateKeyBytes();
128
129
  return new _TreeSignerSession(secretKey);
@@ -891,9 +892,14 @@ var OVERLAP_MS = 24 * 60 * 60 * 1e3;
891
892
  var walletStateLocks = /* @__PURE__ */ new WeakMap();
892
893
  var WALLET_STATE_LOCK_NAME = "arkade-wallet-state";
893
894
  async function updateWalletState(repo, updater) {
895
+ const atomic = repo.atomicWalletState;
894
896
  const prev = walletStateLocks.get(repo) ?? Promise.resolve();
895
897
  const op = prev.then(
896
898
  () => withWebLock(WALLET_STATE_LOCK_NAME, async () => {
899
+ if (atomic !== void 0) {
900
+ await atomic.update(updater);
901
+ return;
902
+ }
897
903
  const state = await repo.getWalletState() ?? {};
898
904
  await repo.saveWalletState(updater(state));
899
905
  })
@@ -1603,7 +1609,7 @@ var RestDelegateProvider = class {
1603
1609
  },
1604
1610
  body: JSON.stringify({
1605
1611
  intent: {
1606
- message: Intent.encodeMessage(intent.message),
1612
+ message: Proof.encodeMessage(intent.message),
1607
1613
  proof: intent.proof
1608
1614
  },
1609
1615
  forfeit_txs: forfeitTxs,
@@ -1700,6 +1706,15 @@ function assertHistoryPageFilter(filter) {
1700
1706
  throw new RangeError("history since must be non-negative Unix milliseconds");
1701
1707
  }
1702
1708
  }
1709
+ function applyWalletStateUpdate(state, updater) {
1710
+ const updated = updater(state);
1711
+ if (updated && typeof updated.then === "function") {
1712
+ if (updated instanceof Promise) void updated.catch(() => {
1713
+ });
1714
+ throw new TypeError("wallet-state updater must be synchronous");
1715
+ }
1716
+ return updated;
1717
+ }
1703
1718
  function compareScriptVtxoCursors(a, b) {
1704
1719
  return a.address < b.address ? -1 : a.address > b.address ? 1 : compareOutpoints(a, b);
1705
1720
  }
@@ -2862,10 +2877,10 @@ var ErrUnvalidatedOffchainOutput = (address) => new ServerResponseMismatchError(
2862
2877
  `offchain output ${address} cannot be validated: virtual output tree signing did not run`
2863
2878
  );
2864
2879
  var ErrIntentOutputNotFound = (index, kind) => new ServerResponseMismatchError(
2865
- `${kind} output ${index} of the intent proof is not present in what the server built`
2880
+ `${kind} output ${index} of the proof is not present in what the server built`
2866
2881
  );
2867
2882
  var ErrUnvalidatedIntentOutput = (index) => new ServerResponseMismatchError(
2868
- `offchain output ${index} of the intent proof cannot be validated: virtual output tree signing did not run`
2883
+ `offchain output ${index} of the proof cannot be validated: virtual output tree signing did not run`
2869
2884
  );
2870
2885
  var ErrInvalidOnchainOutputAmount = (address) => new Error(`invalid onchain output amount: ${address}`);
2871
2886
  var ErrInvalidOnchainOutputAssets = (address) => new Error(`onchain output ${address} cannot have assets`);
@@ -4404,7 +4419,7 @@ async function runWithCrossInstanceLock(name, fn) {
4404
4419
  });
4405
4420
  }
4406
4421
  var MAX_VTXOS_PER_SETTLEMENT = 50;
4407
- var MAX_INPUTS_PER_INTENT = 20;
4422
+ var MAX_INPUTS_PER_PROOF = 20;
4408
4423
  function byValueDescending(vtxos) {
4409
4424
  return [...vtxos].sort((a, b) => b.value - a.value);
4410
4425
  }
@@ -4988,7 +5003,7 @@ var VtxoManager = class _VtxoManager {
4988
5003
  * ```typescript
4989
5004
  * const wallet = await Wallet.create({
4990
5005
  * identity,
4991
- * arkProvider: new RestArkProvider(),
5006
+ * operatorProvider: new RestOperatorProvider(),
4992
5007
  * settlementConfig: {
4993
5008
  * vtxoThreshold: 86_400 // 24 hours
4994
5009
  * },
@@ -5216,7 +5231,7 @@ var VtxoManager = class _VtxoManager {
5216
5231
  * ```typescript
5217
5232
  * const wallet = await Wallet.create({
5218
5233
  * identity,
5219
- * arkProvider: new RestArkProvider(),
5234
+ * operatorProvider: new RestOperatorProvider(),
5220
5235
  * settlementConfig: {
5221
5236
  * boardingUtxoSweep: true,
5222
5237
  * },
@@ -5759,11 +5774,11 @@ var VtxoManager = class _VtxoManager {
5759
5774
  getOnchainProvider() {
5760
5775
  return this.getSweepWallet().onchainProvider;
5761
5776
  }
5762
- getArkProvider() {
5777
+ getOperatorProvider() {
5763
5778
  return this.getSweepWallet().arkProvider;
5764
5779
  }
5765
5780
  /**
5766
- * Unlike {@link getArkProvider}, doesn't require boarding-sweep capability. Undefined when no
5781
+ * Unlike {@link getOperatorProvider}, doesn't require boarding-sweep capability. Undefined when no
5767
5782
  * provider is wired, which callers treat as "no limit".
5768
5783
  */
5769
5784
  getInfoProvider() {
@@ -6014,7 +6029,7 @@ var VtxoManager = class _VtxoManager {
6014
6029
  return;
6015
6030
  }
6016
6031
  const dustAmount = getDustAmount(this.wallet);
6017
- const info = await this.getArkProvider().getInfo();
6032
+ const info = await this.getOperatorProvider().getInfo();
6018
6033
  const { fees, vtxoMaxAmount } = info;
6019
6034
  const estimator = new Estimator(fees.intentFee);
6020
6035
  let totalAmount = 0n;
@@ -7407,6 +7422,16 @@ function gatedTouchpoints(gated) {
7407
7422
  }
7408
7423
  return { paidIn, paidOut };
7409
7424
  }
7425
+ function groupBy(items, key) {
7426
+ const groups = /* @__PURE__ */ new Map();
7427
+ for (const item of items) {
7428
+ const k = key(item);
7429
+ const group = groups.get(k);
7430
+ if (group) group.push(item);
7431
+ else groups.set(k, [item]);
7432
+ }
7433
+ return groups;
7434
+ }
7410
7435
  var txKey = {
7411
7436
  commitmentTxid: "",
7412
7437
  boardingTxid: "",
@@ -7464,6 +7489,15 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
7464
7489
  const txidsNeedingCreatedAt = resolveTxCreatedAt ? collectArkTxidsNeedingCreatedAt(ownVtxos, localCreatedAt) : [];
7465
7490
  const resolvedCreatedAt = resolveTxCreatedAt && txidsNeedingCreatedAt.length > 0 ? await resolveTxCreatedAt(txidsNeedingCreatedAt) : /* @__PURE__ */ new Map();
7466
7491
  const unmatchedSettledBoardingTxs = allBoardingTxs.filter(isSettledBoardingReceive).sort((a, b) => a.createdAt - b.createdAt);
7492
+ const bySettledBy = groupBy(ownVtxos, (v) => v.settledBy);
7493
+ const byArkTxId = groupBy(ownVtxos, (v) => v.arkTxId);
7494
+ const byTxid = groupBy(ownVtxos, (v) => v.txid);
7495
+ const leavesBySoleCommitment = groupBy(
7496
+ ownVtxos,
7497
+ (v) => v.status.isLeaf && v.commitmentTxIds.length > 0 && v.commitmentTxIds.every((c) => c === v.commitmentTxIds[0]) ? v.commitmentTxIds[0] : void 0
7498
+ );
7499
+ const handledArkTxids = /* @__PURE__ */ new Set();
7500
+ const handledCommitments = /* @__PURE__ */ new Set();
7467
7501
  const sent = [];
7468
7502
  let received = [];
7469
7503
  for (const vtxo of ownVtxos) {
@@ -7476,7 +7510,7 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
7476
7510
  unmatchedSettledBoardingTxs,
7477
7511
  (tx) => tx.createdAt <= vtxoCreatedAt && (tx.key.commitmentTxid === commitmentTxid || tx.key.commitmentTxid === vtxo.settledBy)
7478
7512
  );
7479
- } else if (ownVtxos.filter((v) => v.settledBy === vtxo.commitmentTxIds[0]).length === 0) {
7513
+ } else if (!bySettledBy.has(vtxo.commitmentTxIds[0])) {
7480
7514
  const duplicateBoardingReceive = consumeBoardingReceive(
7481
7515
  unmatchedSettledBoardingTxs,
7482
7516
  (tx) => tx.amount === vtxo.value && tx.createdAt <= vtxoCreatedAt
@@ -7497,7 +7531,7 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
7497
7531
  });
7498
7532
  }
7499
7533
  }
7500
- } else if (ownVtxos.filter((v) => v.arkTxId === vtxo.txid).length === 0) {
7534
+ } else if (!byArkTxId.has(vtxo.txid)) {
7501
7535
  const assets = subtractAssets([], [vtxo]);
7502
7536
  received.push({
7503
7537
  key: { ...txKey, arkTxid: vtxo.txid },
@@ -7513,9 +7547,10 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
7513
7547
  });
7514
7548
  }
7515
7549
  if (vtxo.isSpent) {
7516
- if (vtxo.arkTxId && !sent.some((s) => s.key.arkTxid === vtxo.arkTxId)) {
7517
- const changes = ownVtxos.filter((_) => _.txid === vtxo.arkTxId);
7518
- const allSpent = ownVtxos.filter((v) => v.arkTxId === vtxo.arkTxId);
7550
+ if (vtxo.arkTxId && !handledArkTxids.has(vtxo.arkTxId)) {
7551
+ handledArkTxids.add(vtxo.arkTxId);
7552
+ const changes = byTxid.get(vtxo.arkTxId) ?? [];
7553
+ const allSpent = byArkTxId.get(vtxo.arkTxId);
7519
7554
  const spentAmount = allSpent.reduce((acc, v) => acc + v.value, 0);
7520
7555
  let txAmount = 0;
7521
7556
  let txTime = 0;
@@ -7543,11 +7578,10 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
7543
7578
  });
7544
7579
  }
7545
7580
  }
7546
- if (vtxo.settledBy && !commitmentsToIgnore.has(vtxo.settledBy) && !sent.some((s) => s.key.commitmentTxid === vtxo.settledBy)) {
7547
- const changes = ownVtxos.filter(
7548
- (v) => v.status.isLeaf && v.commitmentTxIds.length > 0 && v.commitmentTxIds.every((_) => vtxo.settledBy === _)
7549
- );
7550
- const forfeitVtxos = ownVtxos.filter((v) => v.settledBy === vtxo.settledBy);
7581
+ if (vtxo.settledBy && !commitmentsToIgnore.has(vtxo.settledBy) && !handledCommitments.has(vtxo.settledBy)) {
7582
+ handledCommitments.add(vtxo.settledBy);
7583
+ const changes = leavesBySoleCommitment.get(vtxo.settledBy) ?? [];
7584
+ const forfeitVtxos = bySettledBy.get(vtxo.settledBy);
7551
7585
  const forfeitAmount = forfeitVtxos.reduce((acc, v) => acc + v.value, 0);
7552
7586
  if (changes.length > 0) {
7553
7587
  const settledAmount = changes.reduce((acc, v) => acc + v.value, 0);
@@ -8154,7 +8188,7 @@ async function makeSignedDelegateIntent(identity, coins, outputs, onchainOutputs
8154
8188
  expire_at: 0,
8155
8189
  cosigners_public_keys: cosignerPubKeys
8156
8190
  };
8157
- const proof = Intent.create(message, coins, outputs);
8191
+ const proof = Proof.create(message, coins, outputs);
8158
8192
  const signedProof = await identity.sign(proof);
8159
8193
  return {
8160
8194
  proof: base64.encode(signedProof.toPSBT()),
@@ -8826,6 +8860,21 @@ var InMemoryWalletRepository = class {
8826
8860
  utxosByAddress = /* @__PURE__ */ new Map();
8827
8861
  txsByAddress = /* @__PURE__ */ new Map();
8828
8862
  walletState = null;
8863
+ atomicWalletState;
8864
+ constructor() {
8865
+ const clone2 = typeof globalThis.structuredClone === "function" ? globalThis.structuredClone.bind(globalThis) : void 0;
8866
+ if (clone2) {
8867
+ this.atomicWalletState = {
8868
+ version: 1,
8869
+ update: async (updater) => {
8870
+ this.walletState = applyWalletStateUpdate(
8871
+ clone2(this.walletState ?? {}),
8872
+ updater
8873
+ );
8874
+ }
8875
+ };
8876
+ }
8877
+ }
8829
8878
  async getVtxosPage(address, page) {
8830
8879
  return pageOutpoints(this.vtxosByAddress.get(address) ?? [], page);
8831
8880
  }
@@ -11799,8 +11848,12 @@ var deserializeUtxo = (o) => ({
11799
11848
  var IndexedDBWalletRepository = class {
11800
11849
  version = 2;
11801
11850
  connection;
11802
- constructor(dbName = DEFAULT_DB_NAME) {
11851
+ /** persistentWalletState asserts persistence beyond this process; it cannot detect browser eviction. */
11852
+ constructor(dbName = DEFAULT_DB_NAME, options) {
11803
11853
  this.connection = createManagedConnection(dbName, DB_VERSION, initDatabase);
11854
+ if (options?.persistentWalletState === true) {
11855
+ this.atomicWalletState = { ...this.atomicWalletState, persistent: true };
11856
+ }
11804
11857
  }
11805
11858
  async clear() {
11806
11859
  try {
@@ -12069,6 +12122,47 @@ var IndexedDBWalletRepository = class {
12069
12122
  throw error;
12070
12123
  }
12071
12124
  }
12125
+ atomicWalletState = {
12126
+ version: 1,
12127
+ update: async (updater) => {
12128
+ const db = await this.getDB();
12129
+ const transaction = db.transaction([STORE_WALLET_STATE], "readwrite");
12130
+ const completion = awaitTransaction(transaction);
12131
+ let failed = false;
12132
+ let failure;
12133
+ try {
12134
+ const store = transaction.objectStore(STORE_WALLET_STATE);
12135
+ const request = store.get("state");
12136
+ request.onerror = () => {
12137
+ failed = true;
12138
+ failure = request.error;
12139
+ };
12140
+ request.onsuccess = () => {
12141
+ try {
12142
+ const state = applyWalletStateUpdate(request.result?.data ?? {}, updater);
12143
+ const write = store.put({ key: "state", data: state });
12144
+ write.onerror = () => {
12145
+ failed = true;
12146
+ failure = write.error;
12147
+ };
12148
+ } catch (error) {
12149
+ failed = true;
12150
+ failure = error;
12151
+ transaction.abort();
12152
+ }
12153
+ };
12154
+ } catch (error) {
12155
+ failed = true;
12156
+ failure = error;
12157
+ transaction.abort();
12158
+ }
12159
+ try {
12160
+ await completion;
12161
+ } catch (error) {
12162
+ throw failed ? failure : error;
12163
+ }
12164
+ }
12165
+ };
12072
12166
  async getWalletState() {
12073
12167
  try {
12074
12168
  const db = await this.getDB();
@@ -12079,7 +12173,7 @@ var IndexedDBWalletRepository = class {
12079
12173
  return result?.data ?? null;
12080
12174
  } catch (error) {
12081
12175
  console.error("Failed to get wallet state:", error);
12082
- return null;
12176
+ throw error;
12083
12177
  }
12084
12178
  }
12085
12179
  async saveWalletState(state) {
@@ -12257,7 +12351,7 @@ function arkadeServiceUrl(service) {
12257
12351
  }
12258
12352
  async function resolveArkadeService(service, opts = {}) {
12259
12353
  const operatorUrl = arkadeServiceUrl(service);
12260
- const arkProvider = opts.arkProvider ?? new RestArkProvider(operatorUrl);
12354
+ const arkProvider = opts.arkProvider ?? new RestOperatorProvider(operatorUrl);
12261
12355
  const info = opts.info ?? await arkProvider.getInfo();
12262
12356
  if ("network" in service && service.network !== info.network) {
12263
12357
  throw new Error(
@@ -12994,7 +13088,7 @@ function asSendParams(args) {
12994
13088
  }
12995
13089
  return { recipients: args };
12996
13090
  }
12997
- function extractArkProviderUrl(provider) {
13091
+ function extractOperatorProviderUrl(provider) {
12998
13092
  const serverUrl = provider.serverUrl;
12999
13093
  return typeof serverUrl === "string" && serverUrl.length > 0 ? serverUrl : void 0;
13000
13094
  }
@@ -13424,18 +13518,22 @@ var ReadonlyWallet = class _ReadonlyWallet {
13424
13518
  }
13425
13519
  /** Shared setup for ReadonlyWallet.create() and Wallet.create(). */
13426
13520
  static async setupWalletConfig(config, pubKey) {
13427
- if (config.service && (config.arkProvider || config.indexerProvider || config.onchainProvider)) {
13521
+ if (config.operatorProvider && config.arkProvider) {
13522
+ throw new Error("Pass either `operatorProvider` or `arkProvider`, not both");
13523
+ }
13524
+ const callerProvider = config.operatorProvider ?? config.arkProvider;
13525
+ if (config.service && (callerProvider || config.indexerProvider || config.onchainProvider)) {
13428
13526
  throw new Error(
13429
- "Pass either `service` or `arkProvider`/`indexerProvider`/`onchainProvider`, not both"
13527
+ "Pass either `service` or `operatorProvider`/`indexerProvider`/`onchainProvider`, not both"
13430
13528
  );
13431
13529
  }
13432
- const arkProvider = config.arkProvider || new RestArkProvider(config.service ? arkadeServiceUrl(config.service) : void 0);
13530
+ const arkProvider = callerProvider || new RestOperatorProvider(config.service ? arkadeServiceUrl(config.service) : void 0);
13433
13531
  let indexerProvider = config.indexerProvider;
13434
13532
  if (!indexerProvider && !config.service) {
13435
- const derived = extractArkProviderUrl(arkProvider);
13436
- if (!derived && config.arkProvider) {
13533
+ const derived = extractOperatorProviderUrl(arkProvider);
13534
+ if (!derived && callerProvider) {
13437
13535
  throw new Error(
13438
- "indexerProvider is required when arkProvider is provided without a discoverable serverUrl"
13536
+ "indexerProvider is required when operatorProvider is provided without a discoverable serverUrl"
13439
13537
  );
13440
13538
  }
13441
13539
  indexerProvider = new RestIndexerProvider(derived ?? DEFAULT_ARKADE_SERVER_URL);
@@ -14360,85 +14458,90 @@ var ReadonlyWallet = class _ReadonlyWallet {
14360
14458
  return { height, time };
14361
14459
  }
14362
14460
  });
14363
- const baselinePubkey = await baselinePubkeyPromise;
14364
- const delegatePubKey = this.offchainTapscript instanceof DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
14365
- const baselineSigners = [
14366
- this.offchainTapscript.options.serverPubKey,
14367
- ...[...this._deprecatedSigners.keys()].map((h) => hex.decode(h))
14368
- ];
14369
- const seenBaselineScripts = /* @__PURE__ */ new Set();
14370
- const baseline = [];
14371
- for (const serverPubKey of baselineSigners) {
14372
- for (const csvTimelock2 of this.walletContractTimelocks) {
14373
- const csvTimelockStr = timelockToSequence(csvTimelock2).toString();
14374
- const defaultScript = new DefaultVtxo.Script({
14375
- pubKey: baselinePubkey,
14376
- serverPubKey,
14377
- csvTimelock: csvTimelock2
14378
- });
14379
- const defaultScriptHex = hex.encode(defaultScript.pkScript);
14380
- if (!seenBaselineScripts.has(defaultScriptHex)) {
14381
- seenBaselineScripts.add(defaultScriptHex);
14382
- baseline.push({
14383
- type: "default",
14384
- params: {
14385
- pubKey: hex.encode(defaultScript.options.pubKey),
14386
- serverPubKey: hex.encode(serverPubKey),
14387
- csvTimelock: csvTimelockStr
14388
- },
14389
- script: defaultScriptHex,
14390
- address: defaultScript.address(this.network.hrp, serverPubKey).encode(),
14391
- state: "active"
14392
- });
14393
- }
14394
- if (delegatePubKey) {
14395
- const delegateScript = new DelegateVtxo.Script({
14461
+ try {
14462
+ const baselinePubkey = await baselinePubkeyPromise;
14463
+ const delegatePubKey = this.offchainTapscript instanceof DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
14464
+ const baselineSigners = [
14465
+ this.offchainTapscript.options.serverPubKey,
14466
+ ...[...this._deprecatedSigners.keys()].map((h) => hex.decode(h))
14467
+ ];
14468
+ const seenBaselineScripts = /* @__PURE__ */ new Set();
14469
+ const baseline = [];
14470
+ for (const serverPubKey of baselineSigners) {
14471
+ for (const csvTimelock2 of this.walletContractTimelocks) {
14472
+ const csvTimelockStr = timelockToSequence(csvTimelock2).toString();
14473
+ const defaultScript = new DefaultVtxo.Script({
14396
14474
  pubKey: baselinePubkey,
14397
14475
  serverPubKey,
14398
- delegatePubKey,
14399
14476
  csvTimelock: csvTimelock2
14400
14477
  });
14401
- const delegateScriptHex = hex.encode(delegateScript.pkScript);
14402
- if (seenBaselineScripts.has(delegateScriptHex)) continue;
14403
- seenBaselineScripts.add(delegateScriptHex);
14404
- baseline.push({
14405
- type: "delegate",
14406
- params: {
14407
- pubKey: hex.encode(delegateScript.options.pubKey),
14408
- serverPubKey: hex.encode(serverPubKey),
14409
- delegatePubKey: hex.encode(delegateScript.options.delegatePubKey),
14410
- csvTimelock: csvTimelockStr
14411
- },
14412
- script: delegateScriptHex,
14413
- address: delegateScript.address(this.network.hrp, serverPubKey).encode(),
14414
- state: "active"
14415
- });
14478
+ const defaultScriptHex = hex.encode(defaultScript.pkScript);
14479
+ if (!seenBaselineScripts.has(defaultScriptHex)) {
14480
+ seenBaselineScripts.add(defaultScriptHex);
14481
+ baseline.push({
14482
+ type: "default",
14483
+ params: {
14484
+ pubKey: hex.encode(defaultScript.options.pubKey),
14485
+ serverPubKey: hex.encode(serverPubKey),
14486
+ csvTimelock: csvTimelockStr
14487
+ },
14488
+ script: defaultScriptHex,
14489
+ address: defaultScript.address(this.network.hrp, serverPubKey).encode(),
14490
+ state: "active"
14491
+ });
14492
+ }
14493
+ if (delegatePubKey) {
14494
+ const delegateScript = new DelegateVtxo.Script({
14495
+ pubKey: baselinePubkey,
14496
+ serverPubKey,
14497
+ delegatePubKey,
14498
+ csvTimelock: csvTimelock2
14499
+ });
14500
+ const delegateScriptHex = hex.encode(delegateScript.pkScript);
14501
+ if (seenBaselineScripts.has(delegateScriptHex)) continue;
14502
+ seenBaselineScripts.add(delegateScriptHex);
14503
+ baseline.push({
14504
+ type: "delegate",
14505
+ params: {
14506
+ pubKey: hex.encode(delegateScript.options.pubKey),
14507
+ serverPubKey: hex.encode(serverPubKey),
14508
+ delegatePubKey: hex.encode(delegateScript.options.delegatePubKey),
14509
+ csvTimelock: csvTimelockStr
14510
+ },
14511
+ script: delegateScriptHex,
14512
+ address: delegateScript.address(this.network.hrp, serverPubKey).encode(),
14513
+ state: "active"
14514
+ });
14515
+ }
14416
14516
  }
14417
14517
  }
14518
+ const boardingCsvTimelock = this.boardingTapscript.options.csvTimelock ?? DefaultVtxo.Script.DEFAULT_TIMELOCK;
14519
+ for (const serverPubKey of baselineSigners) {
14520
+ const baselineBoarding = new DefaultVtxo.Script({
14521
+ pubKey: baselinePubkey,
14522
+ serverPubKey,
14523
+ csvTimelock: boardingCsvTimelock
14524
+ });
14525
+ const boardingScriptHex = hex.encode(baselineBoarding.pkScript);
14526
+ if (seenBaselineScripts.has(boardingScriptHex)) continue;
14527
+ seenBaselineScripts.add(boardingScriptHex);
14528
+ baseline.push({
14529
+ type: "boarding",
14530
+ params: {
14531
+ pubKey: hex.encode(baselineBoarding.options.pubKey),
14532
+ serverPubKey: hex.encode(serverPubKey),
14533
+ csvTimelock: timelockToSequence(boardingCsvTimelock).toString()
14534
+ },
14535
+ script: boardingScriptHex,
14536
+ address: baselineBoarding.address(this.network.hrp, serverPubKey).encode(),
14537
+ state: "active"
14538
+ });
14539
+ }
14540
+ await manager.createContracts(baseline);
14541
+ } catch (error) {
14542
+ await manager.dispose().catch(() => void 0);
14543
+ throw error;
14418
14544
  }
14419
- const boardingCsvTimelock = this.boardingTapscript.options.csvTimelock ?? DefaultVtxo.Script.DEFAULT_TIMELOCK;
14420
- for (const serverPubKey of baselineSigners) {
14421
- const baselineBoarding = new DefaultVtxo.Script({
14422
- pubKey: baselinePubkey,
14423
- serverPubKey,
14424
- csvTimelock: boardingCsvTimelock
14425
- });
14426
- const boardingScriptHex = hex.encode(baselineBoarding.pkScript);
14427
- if (seenBaselineScripts.has(boardingScriptHex)) continue;
14428
- seenBaselineScripts.add(boardingScriptHex);
14429
- baseline.push({
14430
- type: "boarding",
14431
- params: {
14432
- pubKey: hex.encode(baselineBoarding.options.pubKey),
14433
- serverPubKey: hex.encode(serverPubKey),
14434
- csvTimelock: timelockToSequence(boardingCsvTimelock).toString()
14435
- },
14436
- script: boardingScriptHex,
14437
- address: baselineBoarding.address(this.network.hrp, serverPubKey).encode(),
14438
- state: "active"
14439
- });
14440
- }
14441
- await manager.createContracts(baseline);
14442
14545
  return manager;
14443
14546
  }
14444
14547
  /** Dispose wallet-owned managers and release background resources. */
@@ -15917,7 +16020,7 @@ var Wallet2 = class extends ReadonlyWallet {
15917
16020
  return { skip };
15918
16021
  }
15919
16022
  if (!this.arkProvider) {
15920
- throw new Error("Arkade provider not configured");
16023
+ throw new Error("Operator provider not configured");
15921
16024
  }
15922
16025
  const timelock = assertValidBatchExpiry(
15923
16026
  event.batchExpiry,
@@ -16028,7 +16131,7 @@ var Wallet2 = class extends ReadonlyWallet {
16028
16131
  ...existing ?? {},
16029
16132
  intentTxId,
16030
16133
  registerProof: intent.proof,
16031
- registerProofMessage: Intent.encodeMessage(intent.message),
16134
+ registerProofMessage: Proof.encodeMessage(intent.message),
16032
16135
  deleteProof: deleteIntent.proof,
16033
16136
  deleteProofMessage: Intent.encodeMessage(deleteIntent.message),
16034
16137
  intentVtxos: inputs.map((i) => ({
@@ -16079,7 +16182,7 @@ var Wallet2 = class extends ReadonlyWallet {
16079
16182
  expire_at: 0,
16080
16183
  cosigners_public_keys: cosignerPubKeys
16081
16184
  };
16082
- const proof = Intent.create(message, coins, outputs);
16185
+ const proof = Proof.create(message, coins, outputs);
16083
16186
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
16084
16187
  return {
16085
16188
  proof: base64.encode(signedProof.toPSBT()),
@@ -16091,7 +16194,7 @@ var Wallet2 = class extends ReadonlyWallet {
16091
16194
  type: "delete",
16092
16195
  expire_at: 0
16093
16196
  };
16094
- const proof = Intent.create(message, coins, []);
16197
+ const proof = Proof.create(message, coins, []);
16095
16198
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
16096
16199
  return {
16097
16200
  proof: base64.encode(signedProof.toPSBT()),
@@ -16103,7 +16206,7 @@ var Wallet2 = class extends ReadonlyWallet {
16103
16206
  type: "get-pending-tx",
16104
16207
  expire_at: 0
16105
16208
  };
16106
- const proof = Intent.create(message, coins, []);
16209
+ const proof = Proof.create(message, coins, []);
16107
16210
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
16108
16211
  return {
16109
16212
  proof: base64.encode(signedProof.toPSBT()),
@@ -16146,8 +16249,8 @@ var Wallet2 = class extends ReadonlyWallet {
16146
16249
  vtxos = allExtended;
16147
16250
  }
16148
16251
  const batches = [];
16149
- for (let i = 0; i < vtxos.length; i += MAX_INPUTS_PER_INTENT) {
16150
- batches.push(vtxos.slice(i, i + MAX_INPUTS_PER_INTENT));
16252
+ for (let i = 0; i < vtxos.length; i += MAX_INPUTS_PER_PROOF) {
16253
+ batches.push(vtxos.slice(i, i + MAX_INPUTS_PER_PROOF));
16151
16254
  }
16152
16255
  const unrollCandidates = this.checkpointUnrollCandidates(await this.arkProvider.getInfo());
16153
16256
  const checkpointInputs = vtxos.map((vtxo) => ({
@@ -16602,10 +16705,10 @@ var Wallet2 = class extends ReadonlyWallet {
16602
16705
  const identity = cash.identity;
16603
16706
  const seenTxids = /* @__PURE__ */ new Set();
16604
16707
  const pendingTxs = [];
16605
- for (let i = 0; i < inputs.length; i += MAX_INPUTS_PER_INTENT) {
16606
- const batch = inputs.slice(i, i + MAX_INPUTS_PER_INTENT);
16708
+ for (let i = 0; i < inputs.length; i += MAX_INPUTS_PER_PROOF) {
16709
+ const batch = inputs.slice(i, i + MAX_INPUTS_PER_PROOF);
16607
16710
  const message = { type: "get-pending-tx", expire_at: 0 };
16608
- const proof = Intent.create(message, batch, []);
16711
+ const proof = Proof.create(message, batch, []);
16609
16712
  const signedProof = await identity.sign(
16610
16713
  proof,
16611
16714
  Array.from({ length: batch.length + 1 }, (_, j) => j)
@@ -17110,7 +17213,7 @@ var Wallet2 = class extends ReadonlyWallet {
17110
17213
  }
17111
17214
  /**
17112
17215
  * Build an offchain transaction from the given inputs and outputs,
17113
- * sign it, submit to the Arkade provider, and finalize.
17216
+ * sign it, submit to the operator provider, and finalize.
17114
17217
  *
17115
17218
  * Signs whatever it is handed, ungated — see {@link settle} for the trade.
17116
17219
  *
@@ -17851,7 +17954,7 @@ var MessageBus = class {
17851
17954
  this.initialized = true;
17852
17955
  }
17853
17956
  async buildServices(config) {
17854
- const arkProvider = new RestArkProvider(config.arkServer.url);
17957
+ const arkProvider = new RestOperatorProvider(config.arkServer.url);
17855
17958
  const storage = {
17856
17959
  walletRepository: this.walletRepository,
17857
17960
  contractRepository: this.contractRepository,
@@ -22668,7 +22771,7 @@ function childTxidFromHex(txHex) {
22668
22771
 
22669
22772
  // src/providers/cachingArk.ts
22670
22773
  var DEFAULT_TTL_MS = 6e4;
22671
- var CachingArkProvider = class {
22774
+ var CachingOperatorProvider = class {
22672
22775
  constructor(inner, ttlMs = DEFAULT_TTL_MS) {
22673
22776
  this.inner = inner;
22674
22777
  this.ttlMs = ttlMs;
@@ -22749,6 +22852,7 @@ var CachingArkProvider = class {
22749
22852
  });
22750
22853
  }
22751
22854
  };
22855
+ var CachingArkProvider = CachingOperatorProvider;
22752
22856
  var PrevTxUnavailableError = class extends Error {
22753
22857
  constructor(message, txids = []) {
22754
22858
  super(message);
@@ -24975,6 +25079,7 @@ var Arkade = class _Arkade {
24975
25079
  *
24976
25080
  * Declared `server`/`user` params default to the client's keys. Compiler
24977
25081
  * artifacts reserve the server key and exit delay to the connected server.
25082
+ * Struct and array params are passed whole by name (see {@link ArkadeNestedValue}).
24978
25083
  */
24979
25084
  contract(program, args = {}) {
24980
25085
  const declared = (program.params ?? []).map((p) => p.name);
@@ -25018,19 +25123,19 @@ var ArkadeContract = class _ArkadeContract {
25018
25123
  constructor(client, program, args = {}, keys) {
25019
25124
  this.client = client;
25020
25125
  this.program = program;
25021
- this.args = args;
25126
+ this.args = /* @__PURE__ */ Object.create(null);
25127
+ for (const [name, value] of Object.entries(args)) flattenValue(name, value, this.args);
25022
25128
  this.keys = keys ?? {
25023
25129
  serverKey: client.serverKey,
25024
25130
  userKey: client.userKey,
25025
25131
  emulatorKey: client.emulatorKey
25026
25132
  };
25027
- this.vtxoScript = new ArkadeProgramScript(program, args, this.keys);
25133
+ this.vtxoScript = new ArkadeProgramScript(program, this.args, this.keys);
25028
25134
  this.tapTree = this.vtxoScript.encode();
25029
25135
  this.compiled = this.vtxoScript.compiled;
25030
25136
  }
25031
25137
  client;
25032
25138
  program;
25033
- args;
25034
25139
  /** The compiled taproot tree of spending-path leaves. */
25035
25140
  vtxoScript;
25036
25141
  /** Encoded taproot tree (shared spend context for every path). */
@@ -25039,6 +25144,8 @@ var ArkadeContract = class _ArkadeContract {
25039
25144
  keys;
25040
25145
  /** Spending paths in declaration order. */
25041
25146
  compiled;
25147
+ /** Constructor bindings by flattened name (`owners.0.key`), as persisted. */
25148
+ args;
25042
25149
  /**
25043
25150
  * Rebuild a callable contract from a persisted `"arkade"` row. Compiles with the stored keys,
25044
25151
  * not the client's current ones, so script and address survive a server signer rotation.
@@ -25468,7 +25575,7 @@ var ArkadeTransactionBuilder = class {
25468
25575
  );
25469
25576
  return {
25470
25577
  txid: res.arkTxid,
25471
- // Required by ArkadeBroadcaster; RestArkProvider.submitTx rejects a response without it.
25578
+ // Required by ArkadeBroadcaster; RestOperatorProvider.submitTx rejects a response without it.
25472
25579
  signedArkTx: res.finalArkTx,
25473
25580
  signedCheckpointTxs: res.signedCheckpointTxs
25474
25581
  };
@@ -25536,20 +25643,60 @@ function unspendable(coin, now) {
25536
25643
  function witnessBytes({ contract, args }, ref) {
25537
25644
  return witnessRefToBytes(ref, args, contract.args);
25538
25645
  }
25646
+ function flattenValue(name, value, out, ancestors = /* @__PURE__ */ new Set()) {
25647
+ if (typeof value !== "object" || value === null || ArrayBuffer.isView(value)) {
25648
+ if (Object.hasOwn(out, name)) throw new Error(`duplicate argument '${name}'`);
25649
+ out[name] = value;
25650
+ return;
25651
+ }
25652
+ if (ancestors.has(value)) throw new Error(`argument '${name}' must not be cyclic`);
25653
+ if (Array.isArray(value)) {
25654
+ for (let i = 0; i < value.length; i++) {
25655
+ if (!Object.hasOwn(value, i))
25656
+ throw new Error(`argument '${name}.${i}' is a sparse array element`);
25657
+ }
25658
+ }
25659
+ const entries = Object.entries(value);
25660
+ if (entries.length === 0) {
25661
+ const proto = Object.getPrototypeOf(value);
25662
+ if (proto !== Object.prototype && proto !== Array.prototype && proto !== null)
25663
+ throw new Error(`argument '${name}' must be bytes, a number, a struct or an array`);
25664
+ throw new Error(`argument '${name}' must not be an empty struct or array`);
25665
+ }
25666
+ ancestors.add(value);
25667
+ for (const [key, item] of entries) flattenValue(`${name}.${key}`, item, out, ancestors);
25668
+ ancestors.delete(value);
25669
+ }
25539
25670
  function bindInputs(fn, callArgs) {
25540
25671
  const inputs = fn.def.inputs ?? [];
25541
- if (callArgs.length !== inputs.length) {
25672
+ const declared = /* @__PURE__ */ new Set();
25673
+ for (const def of inputs) {
25674
+ if (declared.has(def.name)) throw new Error(`${fn.name}: duplicate input '${def.name}'`);
25675
+ declared.add(def.name);
25676
+ }
25677
+ const params = [
25678
+ ...new Map(
25679
+ inputs.map(({ name }) => {
25680
+ const root = name.split(".")[0];
25681
+ return [name.includes(".") ? `${root}.` : root, root];
25682
+ })
25683
+ ).values()
25684
+ ];
25685
+ if (callArgs.length !== params.length) {
25542
25686
  throw new Error(
25543
- `${fn.name}: expected ${inputs.length} argument(s), got ${callArgs.length}`
25687
+ `${fn.name}: expected ${params.length} argument(s), got ${callArgs.length}`
25544
25688
  );
25545
25689
  }
25546
25690
  const bound = /* @__PURE__ */ Object.create(null);
25547
- inputs.forEach((def, i) => {
25548
- if (Object.hasOwn(bound, def.name))
25549
- throw new Error(`${fn.name}: duplicate input '${def.name}'`);
25550
- validateParamValue(def, callArgs[i]);
25551
- bound[def.name] = callArgs[i];
25552
- });
25691
+ params.forEach((param, i) => flattenValue(param, callArgs[i], bound));
25692
+ for (const name of Object.keys(bound)) {
25693
+ if (!declared.has(name)) throw new Error(`${fn.name}: unexpected input '${name}'`);
25694
+ }
25695
+ for (const def of inputs) {
25696
+ if (bound[def.name] === void 0)
25697
+ throw new Error(`${fn.name}: missing input '${def.name}'`);
25698
+ validateParamValue(def, bound[def.name]);
25699
+ }
25553
25700
  return bound;
25554
25701
  }
25555
25702
  function attachExtension(tx, newPackets) {
@@ -26034,6 +26181,6 @@ function createDefaultPaymentRouter(wallet) {
26034
26181
  }).use(arkRail()).use(arkAssetRail()).use(onchainRail({ feeInfo: walletFeeSource(wallet) }));
26035
26182
  }
26036
26183
 
26037
- export { ARKADE_MAGIC, ARKADE_SALTED_PREIMAGE_TAG, ARKADE_SWAP_PREIMAGE_TAG, ASSET_CARRIER_SATS, AbortError, ActivityRegistry, AmbiguousRouteError, ArkNote, Arkade, ArkadeCash, ArkadeCashCreateError, ArkadeCashOperatorMismatchError, AssetManager, BIP21, BIP21Error, BIP322, BLOCKED_UPGRADE_TIMEOUT_MS, Batch, CachingArkProvider, ChainedTxType, ConnectionDisposedError, ContractManager, ContractWatcher, DEFAULT_MESSAGE_TIMEOUTS, DEFAULT_MIN_BATCH_EXPIRY_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, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, OversizedChangeError, P2A, PaymentRouter, PrevTxUnavailableError, REGTEST_MIN_BATCH_EXPIRY_SECONDS, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestEmulatorProvider, SeedIdentity, SendDeadlineExceededError, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, StaticDescriptorProvider, TxTree, TxType, TxWeightEstimator, UnannotatableInputError, UnilateralExit, UnknownPacket, Unroll, VtxoManager, VtxoReservedError, 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, 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, resolveDescriptorSigner, resolvePrevTxs, resolveSendAmount, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, selectionOf, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signAndSubmitOffchainTx, signerSetFromInfo, signingDescriptorIndex, strictSigningDescriptorIndex, submitViaEmulator, toXOnlySignerHex, tryResolveSendAmount, utxoEntries, validateBatchRecipients, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, walletFeeSource, warnAndFilterVtxosForScript, withPrevTxs };
26038
- //# sourceMappingURL=chunk-HAQAWBYG.js.map
26039
- //# sourceMappingURL=chunk-HAQAWBYG.js.map
26184
+ export { ARKADE_MAGIC, ARKADE_SALTED_PREIMAGE_TAG, ARKADE_SWAP_PREIMAGE_TAG, ASSET_CARRIER_SATS, AbortError, ActivityRegistry, AmbiguousRouteError, ArkNote, Arkade, ArkadeCash, ArkadeCashCreateError, ArkadeCashOperatorMismatchError, AssetManager, BIP21, BIP21Error, BIP322, BLOCKED_UPGRADE_TIMEOUT_MS, Batch, CachingArkProvider, CachingOperatorProvider, ChainedTxType, ConnectionDisposedError, ContractManager, ContractWatcher, DEFAULT_MESSAGE_TIMEOUTS, DEFAULT_MIN_BATCH_EXPIRY_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, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, OversizedChangeError, P2A, PaymentRouter, PrevTxUnavailableError, REGTEST_MIN_BATCH_EXPIRY_SECONDS, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestEmulatorProvider, SeedIdentity, SendDeadlineExceededError, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, StaticDescriptorProvider, TreeSignerSession, TxTree, TxType, TxWeightEstimator, UnannotatableInputError, UnilateralExit, UnknownPacket, Unroll, VtxoManager, VtxoReservedError, Wallet2 as Wallet, WalletCannotAllocateAddressError, WalletCannotSignError, WalletMessageHandler, WalletNotInitializedError, WsElectrumChainSource, adoptContractDescriptor, applyWalletStateUpdate, 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, deleteByIndex, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, exitObserverFor, extendVirtualCoinForContract, extractOperatorProviderUrl, 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, resolveDescriptorSigner, resolvePrevTxs, resolveSendAmount, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, selectionOf, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signAndSubmitOffchainTx, signerSetFromInfo, signingDescriptorIndex, strictSigningDescriptorIndex, submitViaEmulator, toXOnlySignerHex, tryResolveSendAmount, utxoEntries, validateBatchRecipients, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, walletFeeSource, warnAndFilterVtxosForScript, withPrevTxs };
26185
+ //# sourceMappingURL=chunk-ZJHLLDBP.js.map
26186
+ //# sourceMappingURL=chunk-ZJHLLDBP.js.map