@arkade-os/sdk 0.4.47 → 0.4.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/adapters/expo.cjs +5 -5
  2. package/dist/adapters/expo.d.cts +2 -2
  3. package/dist/adapters/expo.d.ts +2 -2
  4. package/dist/adapters/expo.js +3 -3
  5. package/dist/adapters/indexedDB.cjs +5 -5
  6. package/dist/adapters/indexedDB.js +4 -4
  7. package/dist/{ark-CoJgwTi_.d.cts → ark-CjE0KkGp.d.cts} +405 -250
  8. package/dist/{ark-CoJgwTi_.d.ts → ark-CjE0KkGp.d.ts} +405 -250
  9. package/dist/{asyncStorageTaskQueue-Dowyo59a.d.cts → asyncStorageTaskQueue-CeLZhZFU.d.cts} +2 -2
  10. package/dist/{asyncStorageTaskQueue-Z3aFoXCl.d.ts → asyncStorageTaskQueue-D9SOPMPC.d.ts} +2 -2
  11. package/dist/{chunk-XN3554FT.js → chunk-4VVTRPH3.js} +4 -4
  12. package/dist/chunk-4VVTRPH3.js.map +1 -0
  13. package/dist/{chunk-RQSA7ADZ.cjs → chunk-5XMVTK5S.cjs} +37 -37
  14. package/dist/chunk-5XMVTK5S.cjs.map +1 -0
  15. package/dist/{chunk-L5ND2FJJ.cjs → chunk-7TXSPRN5.cjs} +161 -2
  16. package/dist/chunk-7TXSPRN5.cjs.map +1 -0
  17. package/dist/{chunk-CDDWXBEM.js → chunk-BHHLRZCS.js} +169 -42
  18. package/dist/chunk-BHHLRZCS.js.map +1 -0
  19. package/dist/{chunk-HHV5FPC6.cjs → chunk-EB3ALGTM.cjs} +178 -50
  20. package/dist/chunk-EB3ALGTM.cjs.map +1 -0
  21. package/dist/{chunk-JAYOXOLT.cjs → chunk-ENDNQPZA.cjs} +17 -44
  22. package/dist/chunk-ENDNQPZA.cjs.map +1 -0
  23. package/dist/{chunk-WTTLIFS7.cjs → chunk-ENZ4YPR2.cjs} +944 -544
  24. package/dist/chunk-ENZ4YPR2.cjs.map +1 -0
  25. package/dist/{chunk-3N5I6GT6.js → chunk-G6J6AEMH.js} +5 -4
  26. package/dist/chunk-G6J6AEMH.js.map +1 -0
  27. package/dist/{chunk-OCS5S3L3.js → chunk-NYR5H6GR.js} +685 -284
  28. package/dist/chunk-NYR5H6GR.js.map +1 -0
  29. package/dist/{chunk-VE67GMGM.cjs → chunk-SYDANBJI.cjs} +9 -8
  30. package/dist/chunk-SYDANBJI.cjs.map +1 -0
  31. package/dist/{chunk-AJQ4AOT3.js → chunk-XFMGIFBL.js} +4 -31
  32. package/dist/chunk-XFMGIFBL.js.map +1 -0
  33. package/dist/{chunk-C7TXXTMS.js → chunk-ZDDBTFVO.js} +146 -3
  34. package/dist/chunk-ZDDBTFVO.js.map +1 -0
  35. package/dist/contracts/handlers/index.cjs +8 -8
  36. package/dist/contracts/handlers/index.d.cts +3 -3
  37. package/dist/contracts/handlers/index.d.ts +3 -3
  38. package/dist/contracts/handlers/index.js +2 -2
  39. package/dist/{delegate-Dl87_zMA.d.cts → delegate-D3dY-2vS.d.cts} +1 -1
  40. package/dist/{delegate-CuaDqqQi.d.ts → delegate-DhGZk1r2.d.ts} +1 -1
  41. package/dist/{index-BC_G0VTh.d.cts → index-D6RQROds.d.cts} +2 -2
  42. package/dist/{index-CKwpZEpw.d.ts → index-DK4_iWYy.d.ts} +2 -2
  43. package/dist/index.cjs +211 -183
  44. package/dist/index.d.cts +61 -11
  45. package/dist/index.d.ts +61 -11
  46. package/dist/index.js +4 -4
  47. package/dist/repositories/realm/index.cjs +19 -19
  48. package/dist/repositories/realm/index.d.cts +2 -2
  49. package/dist/repositories/realm/index.d.ts +2 -2
  50. package/dist/repositories/realm/index.js +5 -5
  51. package/dist/repositories/sqlite/index.cjs +18 -18
  52. package/dist/repositories/sqlite/index.d.cts +2 -2
  53. package/dist/repositories/sqlite/index.d.ts +2 -2
  54. package/dist/repositories/sqlite/index.js +5 -5
  55. package/dist/{taskRunner-Dz-TI4Rb.d.ts → taskRunner-B-2MHCYG.d.ts} +2 -2
  56. package/dist/{taskRunner-Dz47k0lp.d.cts → taskRunner-Brnak0Rc.d.cts} +2 -2
  57. package/dist/wallet/expo/background.cjs +14 -14
  58. package/dist/wallet/expo/background.d.cts +3 -3
  59. package/dist/wallet/expo/background.d.ts +3 -3
  60. package/dist/wallet/expo/background.js +6 -6
  61. package/dist/wallet/expo/index.cjs +14 -14
  62. package/dist/wallet/expo/index.cjs.map +1 -1
  63. package/dist/wallet/expo/index.d.cts +5 -5
  64. package/dist/wallet/expo/index.d.ts +5 -5
  65. package/dist/wallet/expo/index.js +5 -5
  66. package/dist/wallet/expo/index.js.map +1 -1
  67. package/dist/{wallet-Oxz_wLxo.d.cts → wallet-B5bwixQa.d.ts} +130 -7
  68. package/dist/{wallet-x7egmXq6.d.ts → wallet-DiOrtYic.d.cts} +130 -7
  69. package/dist/worker/expo/index.cjs +9 -9
  70. package/dist/worker/expo/index.d.cts +4 -4
  71. package/dist/worker/expo/index.d.ts +4 -4
  72. package/dist/worker/expo/index.js +5 -5
  73. package/package.json +3 -2
  74. package/dist/chunk-3N5I6GT6.js.map +0 -1
  75. package/dist/chunk-AJQ4AOT3.js.map +0 -1
  76. package/dist/chunk-C7TXXTMS.js.map +0 -1
  77. package/dist/chunk-CDDWXBEM.js.map +0 -1
  78. package/dist/chunk-HHV5FPC6.cjs.map +0 -1
  79. package/dist/chunk-JAYOXOLT.cjs.map +0 -1
  80. package/dist/chunk-L5ND2FJJ.cjs.map +0 -1
  81. package/dist/chunk-OCS5S3L3.js.map +0 -1
  82. package/dist/chunk-RQSA7ADZ.cjs.map +0 -1
  83. package/dist/chunk-VE67GMGM.cjs.map +0 -1
  84. package/dist/chunk-WTTLIFS7.cjs.map +0 -1
  85. package/dist/chunk-XN3554FT.js.map +0 -1
@@ -824,6 +824,149 @@ function getSequence(tapLeafScript) {
824
824
  return sequence;
825
825
  }
826
826
 
827
+ // src/wallet/vtxo.ts
828
+ var EXPIRY_MIN_PLAUSIBLE_MS = Date.UTC(2025, 0, 1);
829
+ async function resolveTimeHeight(provider) {
830
+ const timestamp = /* @__PURE__ */ new Date();
831
+ if (!provider) return { timestamp };
832
+ try {
833
+ const tip = await provider.getChainTip();
834
+ return { timestamp, height: tip.height };
835
+ } catch (e) {
836
+ console.warn("Failed to fetch chain tip; height-based expiry will not be evaluated", e);
837
+ return { timestamp };
838
+ }
839
+ }
840
+ function parseWireExpiry(raw) {
841
+ if (raw === null || raw === void 0 || raw === "") return {};
842
+ const n = Number(raw);
843
+ if (!Number.isFinite(n) || n <= 0) return {};
844
+ const ms = n * 1e3;
845
+ if (ms >= EXPIRY_MIN_PLAUSIBLE_MS) return { expiresAt: new Date(ms) };
846
+ return { expiresAtHeight: n };
847
+ }
848
+ function toBatchExpiry(c) {
849
+ if (c.expiresAt !== void 0) return c.expiresAt.getTime();
850
+ if (c.expiresAtHeight !== void 0) return c.expiresAtHeight * 1e3;
851
+ return void 0;
852
+ }
853
+ function parseLegacyExpiry(batchExpiry) {
854
+ if (batchExpiry === void 0 || batchExpiry <= 0) return {};
855
+ if (batchExpiry >= EXPIRY_MIN_PLAUSIBLE_MS) return { expiresAt: new Date(batchExpiry) };
856
+ return { expiresAtHeight: batchExpiry / 1e3 };
857
+ }
858
+ function toVirtualStatus(c) {
859
+ return {
860
+ // Precedence is load-bearing: consumers bucket on this label, so any other order silently
861
+ // moves VTXOs between buckets.
862
+ state: c.isSpent ? "spent" : c.isSwept ? "swept" : c.isPreconfirmed ? "preconfirmed" : "settled",
863
+ commitmentTxIds: c.commitmentTxIds,
864
+ batchExpiry: toBatchExpiry(c)
865
+ };
866
+ }
867
+ function normalizeVtxo(v) {
868
+ const state = v.virtualStatus?.state;
869
+ const canonicalExpiry = v.expiresAt !== void 0 || v.expiresAtHeight !== void 0;
870
+ const expiry = canonicalExpiry ? (
871
+ // Coerce: a backend that persists through JSON hands back an ISO string, which typechecks
872
+ // as `Date` but returns NaN from `.getTime()` — comparing false against everything.
873
+ {
874
+ expiresAt: v.expiresAt === void 0 ? void 0 : new Date(v.expiresAt),
875
+ expiresAtHeight: v.expiresAtHeight
876
+ }
877
+ ) : parseLegacyExpiry(v.virtualStatus?.batchExpiry);
878
+ const isSpent = v.isSpent ?? state === "spent";
879
+ const isSwept = v.isSwept ?? state === "swept";
880
+ const isPreconfirmed = v.isPreconfirmed ?? state === "preconfirmed";
881
+ const commitmentTxIds = v.commitmentTxIds ?? v.virtualStatus?.commitmentTxIds ?? [];
882
+ return {
883
+ ...v,
884
+ isSpent,
885
+ isSwept,
886
+ isPreconfirmed,
887
+ spentBy: v.spentBy ?? "",
888
+ commitmentTxIds,
889
+ ...expiry,
890
+ virtualStatus: v.virtualStatus ?? toVirtualStatus({ isSpent, isSwept, isPreconfirmed, commitmentTxIds, ...expiry })
891
+ };
892
+ }
893
+ function convertVtxo(vtxo) {
894
+ const expiry = parseWireExpiry(vtxo.expiresAt);
895
+ const facts = {
896
+ isSpent: vtxo.isSpent,
897
+ isSwept: vtxo.isSwept,
898
+ isPreconfirmed: vtxo.isPreconfirmed,
899
+ commitmentTxIds: vtxo.commitmentTxids,
900
+ ...expiry
901
+ };
902
+ return {
903
+ txid: vtxo.outpoint.txid,
904
+ vout: vtxo.outpoint.vout,
905
+ value: Number(vtxo.amount),
906
+ status: {
907
+ confirmed: !vtxo.isSwept && !vtxo.isPreconfirmed,
908
+ isLeaf: !vtxo.isPreconfirmed
909
+ },
910
+ ...facts,
911
+ virtualStatus: toVirtualStatus(facts),
912
+ spentBy: vtxo.spentBy ?? "",
913
+ settledBy: vtxo.settledBy,
914
+ arkTxId: vtxo.arkTxid,
915
+ createdAt: new Date(Number(vtxo.createdAt) * 1e3),
916
+ isUnrolled: vtxo.isUnrolled,
917
+ script: vtxo.script,
918
+ assets: vtxo.assets?.map((a) => ({
919
+ assetId: a.assetId,
920
+ amount: BigInt(a.amount)
921
+ }))
922
+ };
923
+ }
924
+ async function getNormalizedVtxos(provider, opts) {
925
+ const { vtxos, page } = await provider.getVtxos(opts);
926
+ return { vtxos: vtxos.map(normalizeVtxo), page };
927
+ }
928
+ function hasTerminalSpend(vtxo) {
929
+ const n = normalizeVtxo(vtxo);
930
+ return !!n.isSpent || !!n.spentBy || !!n.settledBy;
931
+ }
932
+ function isPastExpiry(vtxo, now) {
933
+ const n = normalizeVtxo(vtxo);
934
+ if (n.expiresAt !== void 0 && now.timestamp.getTime() >= n.expiresAt.getTime()) return true;
935
+ return n.expiresAtHeight !== void 0 && now.height !== void 0 && now.height >= n.expiresAtHeight;
936
+ }
937
+ function canSpendOffchain(vtxo, now) {
938
+ const n = normalizeVtxo(vtxo);
939
+ return !hasTerminalSpend(n) && !(n.isSwept || isPastExpiry(n, now));
940
+ }
941
+ function canRecoverOnchain(vtxo, now) {
942
+ const n = normalizeVtxo(vtxo);
943
+ return !hasTerminalSpend(n) && (n.isSwept || isPastExpiry(n, now));
944
+ }
945
+ function toOffchainInputFeeParams(vtxo) {
946
+ const batchExpiry = toBatchExpiry(vtxo);
947
+ return {
948
+ amount: BigInt(vtxo.value),
949
+ type: vtxo.isSwept ? "recoverable" : "vtxo",
950
+ weight: 0,
951
+ birth: vtxo.createdAt,
952
+ expiry: batchExpiry ? new Date(batchExpiry) : void 0
953
+ };
954
+ }
955
+ function isVirtualCoin(input) {
956
+ return typeof input === "object" && input !== null && typeof input.script === "string";
957
+ }
958
+ function isSpendable(vtxo) {
959
+ return !hasTerminalSpend(vtxo);
960
+ }
961
+ function isRecoverable(vtxo) {
962
+ const n = normalizeVtxo(vtxo);
963
+ return n.isSwept && !hasTerminalSpend(n);
964
+ }
965
+ function isExpired(vtxo) {
966
+ const n = normalizeVtxo(vtxo);
967
+ return n.isSwept || n.expiresAt !== void 0 && n.expiresAt.getTime() <= Date.now();
968
+ }
969
+
827
970
  exports.ArkAddress = ArkAddress;
828
971
  exports.DEFAULT_ARKADE_SERVER_URL = DEFAULT_ARKADE_SERVER_URL;
829
972
  exports.DEFAULT_NETWORK = DEFAULT_NETWORK;
@@ -831,12 +974,28 @@ exports.DEFAULT_NETWORK_NAME = DEFAULT_NETWORK_NAME;
831
974
  exports.TapTreeCoder = TapTreeCoder;
832
975
  exports.VtxoScript = VtxoScript;
833
976
  exports.assembleBtcdTaprootTree = assembleBtcdTaprootTree;
977
+ exports.canRecoverOnchain = canRecoverOnchain;
978
+ exports.canSpendOffchain = canSpendOffchain;
979
+ exports.convertVtxo = convertVtxo;
834
980
  exports.decodeTapscript = decodeTapscript;
835
981
  exports.getNetwork = getNetwork;
982
+ exports.getNormalizedVtxos = getNormalizedVtxos;
836
983
  exports.getSequence = getSequence;
984
+ exports.hasTerminalSpend = hasTerminalSpend;
985
+ exports.isExpired = isExpired;
986
+ exports.isPastExpiry = isPastExpiry;
987
+ exports.isRecoverable = isRecoverable;
988
+ exports.isSpendable = isSpendable;
989
+ exports.isVirtualCoin = isVirtualCoin;
837
990
  exports.networks = networks;
991
+ exports.normalizeVtxo = normalizeVtxo;
992
+ exports.parseLegacyExpiry = parseLegacyExpiry;
993
+ exports.resolveTimeHeight = resolveTimeHeight;
838
994
  exports.scriptFromTapLeafScript = scriptFromTapLeafScript;
839
995
  exports.sequenceToTimelock = sequenceToTimelock;
840
996
  exports.timelockToSequence = timelockToSequence;
841
- //# sourceMappingURL=chunk-L5ND2FJJ.cjs.map
842
- //# sourceMappingURL=chunk-L5ND2FJJ.cjs.map
997
+ exports.toBatchExpiry = toBatchExpiry;
998
+ exports.toOffchainInputFeeParams = toOffchainInputFeeParams;
999
+ exports.toVirtualStatus = toVirtualStatus;
1000
+ //# sourceMappingURL=chunk-7TXSPRN5.cjs.map
1001
+ //# sourceMappingURL=chunk-7TXSPRN5.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/timelock.ts","../src/networks.ts","../src/script/address.ts","../src/script/tapscript.ts","../src/script/taprootTree.ts","../src/script/base.ts","../src/wallet/vtxo.ts"],"names":["bip68","NETWORK","TEST_NETWORK","bech32m","Script","ScriptNum","MultisigTapscript","CSVMultisigTapscript","ConditionCSVMultisigTapscript","ConditionMultisigTapscript","CLTVMultisigTapscript","hex","MultisigType","encode","p2tr_ms","decode","TAP_LEAF_VERSION","PSBTOutput","p2tr","TAPROOT_UNSPENDABLE_KEY","Address","leaf"],"mappings":"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","file":"chunk-7TXSPRN5.cjs","sourcesContent":["import * as bip68 from \"bip68\";\nimport type { RelativeTimelock } from \"../script/tapscript\";\n\n/**\n * Convert RelativeTimelock to BIP68 sequence number.\n */\nexport function timelockToSequence(timelock: RelativeTimelock): number {\n return bip68.encode(\n timelock.type === \"blocks\"\n ? { blocks: Number(timelock.value) }\n : { seconds: Number(timelock.value) },\n );\n}\n\n/**\n * Convert BIP68 sequence number back to RelativeTimelock.\n */\nexport function sequenceToTimelock(sequence: number): RelativeTimelock {\n const decoded = bip68.decode(sequence);\n if (\"blocks\" in decoded && decoded.blocks !== undefined) {\n return { type: \"blocks\", value: BigInt(decoded.blocks) };\n }\n if (\"seconds\" in decoded && decoded.seconds !== undefined) {\n return { type: \"seconds\", value: BigInt(decoded.seconds) };\n }\n throw new Error(`Invalid BIP68 sequence: ${sequence}`);\n}\n","import { NETWORK, TEST_NETWORK } from \"@scure/btc-signer/utils.js\";\n\nexport type NetworkName = \"bitcoin\" | \"testnet\" | \"signet\" | \"mutinynet\" | \"regtest\";\n\nexport interface Network {\n hrp: string;\n bech32: string;\n pubKeyHash: number;\n scriptHash: number;\n wif: number;\n}\nexport const getNetwork = (network: NetworkName): Network => {\n const found = networks[network];\n // Fail closed: an unknown network must never silently fall through to\n // mainnet params (e.g. via Address()'s default) when validating addresses.\n if (!found) throw new Error(`Unsupported network: ${network}`);\n return found;\n};\n\nexport const networks = {\n bitcoin: withArkPrefix(NETWORK, \"ark\"),\n testnet: withArkPrefix(TEST_NETWORK, \"tark\"),\n signet: withArkPrefix(TEST_NETWORK, \"tark\"),\n mutinynet: withArkPrefix(TEST_NETWORK, \"tark\"),\n regtest: withArkPrefix(\n {\n ...TEST_NETWORK,\n bech32: \"bcrt\",\n pubKeyHash: 0x6f,\n scriptHash: 0xc4,\n },\n \"tark\",\n ),\n};\n\nfunction withArkPrefix(network: Omit<Network, \"hrp\">, prefix: string): Network {\n return {\n ...network,\n hrp: prefix,\n };\n}\n\nexport const DEFAULT_ARKADE_SERVER_URL = \"https://arkade.computer\" as const;\nexport const DEFAULT_NETWORK = networks.bitcoin;\nexport const DEFAULT_NETWORK_NAME = \"bitcoin\" as const satisfies NetworkName;\n","import { bech32m } from \"@scure/base\";\nimport { Bytes } from \"@scure/btc-signer/utils.js\";\nimport { Script } from \"@scure/btc-signer/script.js\";\nimport { DEFAULT_NETWORK } from \"../networks\";\n\n/**\n * ArkAddress allows creating and decoding bech32m-encoded Arkade addresses.\n *\n * An Arkade address is composed of:\n * - a human readable prefix (hrp)\n * - a version byte (1 byte)\n * - a server public key (32 bytes)\n * - a vtxo taproot public key (32 bytes)\n *\n * @remarks\n * This is an Arkade-specific address format.\n * It is distinct from the Taproot onchain address returned by `VtxoScript.onchainAddress`.\n *\n * @see VtxoScript\n *\n * @example\n * ```typescript\n * const address = new ArkAddress(\n * new Uint8Array(32), // server public key\n * new Uint8Array(32), // vtxo taproot public key\n * \"ark\"\n * );\n *\n * const encoded = address.encode();\n * console.log(\"address: \", encoded);\n *\n * const decoded = ArkAddress.decode(encoded);\n * ```\n */\nexport class ArkAddress {\n /**\n * Create an Arkade address from its server public key, Taproot output key, and prefix.\n *\n * @param serverPubKey - 32-byte Arkade server public key\n * @param vtxoTaprootKey - 32-byte Taproot output key (a.k.a. tweaked public key)\n * @param hrp - Bech32 human-readable prefix\n * @param version - Address version byte\n * @defaultValue `version = 0`\n * @throws Error if either public key is not 32 bytes long\n */\n constructor(\n readonly serverPubKey: Bytes,\n readonly vtxoTaprootKey: Bytes,\n readonly hrp: string = DEFAULT_NETWORK.hrp,\n readonly version: number = 0,\n ) {\n if (serverPubKey.length !== 32) {\n throw new Error(\n \"Invalid server public key length, expected 32 bytes, got \" + serverPubKey.length,\n );\n }\n if (vtxoTaprootKey.length !== 32) {\n throw new Error(\n \"Invalid vtxo taproot public key length, expected 32 bytes, got \" +\n vtxoTaprootKey.length,\n );\n }\n }\n\n /**\n * Decode an Arkade address from its bech32m string form.\n *\n * @param address - Bech32m-encoded Arkade address\n * @returns Decoded Arkade address\n * @throws Error if the address is malformed or has an invalid payload length\n * @see encode\n */\n static decode(address: string): ArkAddress {\n const decoded = bech32m.decodeUnsafe(address, 1023);\n if (!decoded) {\n throw new Error(\"Invalid address\");\n }\n const data = new Uint8Array(bech32m.fromWords(decoded.words));\n\n // First the version byte, then 32 bytes server pubkey, then 32 bytes vtxo taproot public key.\n if (data.length !== 1 + 32 + 32) {\n throw new Error(\"Invalid data length, expected 65 bytes, got \" + data.length);\n }\n\n const version = data[0];\n const serverPubKey = data.slice(1, 33);\n const vtxoTaprootPubKey = data.slice(33, 65);\n\n return new ArkAddress(serverPubKey, vtxoTaprootPubKey, decoded.prefix, version);\n }\n\n /**\n * Encode the address to its bech32m string form.\n *\n * @returns Bech32m-encoded Arkade address\n * @see decode\n */\n encode(): string {\n // Combine version byte, server pubkey, and vtxo taproot public key.\n const data = new Uint8Array(1 + 32 + 32);\n data[0] = this.version;\n data.set(this.serverPubKey, 1);\n data.set(this.vtxoTaprootKey, 33);\n\n const words = bech32m.toWords(data);\n return bech32m.encode(this.hrp, words, 1023);\n }\n\n /** ScriptPubKey used to send non-dust funds to the address. */\n get pkScript(): Bytes {\n return Script.encode([\"OP_1\", this.vtxoTaprootKey]);\n }\n\n /** ScriptPubKey used to send sub-dust funds to the address. */\n get subdustPkScript(): Bytes {\n return Script.encode([\"RETURN\", this.vtxoTaprootKey]);\n }\n}\n","import { Script, ScriptNum, ScriptType, p2tr_ms } from \"@scure/btc-signer\";\nimport { Bytes } from \"@scure/btc-signer/utils.js\";\nimport { hex } from \"@scure/base\";\nimport { sequenceToTimelock, timelockToSequence } from \"../utils/timelock\";\n\nconst MinimalScriptNum = ScriptNum(undefined, true);\n\n/**\n * RelativeTimelock lets to create timelocked with CHECKSEQUENCEVERIFY script.\n *\n * @example\n * ```typescript\n * const timelock = { value: 144n, type: \"blocks\" }; // 1 day in blocks\n * const timelock = { value: 512n, type: \"seconds\" }; // 8 minutes in seconds\n * ```\n */\nexport type RelativeTimelock = {\n value: bigint;\n type: \"seconds\" | \"blocks\";\n};\n\nexport enum TapscriptType {\n Multisig = \"multisig\",\n CSVMultisig = \"csv-multisig\",\n ConditionCSVMultisig = \"condition-csv-multisig\",\n ConditionMultisig = \"condition-multisig\",\n CLTVMultisig = \"cltv-multisig\",\n}\n\n/**\n * ArkTapscript is the base element of vtxo scripts.\n * It is used to encode and decode the different types of vtxo scripts.\n */\nexport interface ArkTapscript<T extends TapscriptType, Params> {\n type: T;\n params: Params;\n script: Uint8Array;\n}\n\n/**\n * decodeTapscript is a function that decodes an Arkade tapscript from a raw script.\n *\n * @throws {Error} if the script is not a valid Arkade tapscript\n * @example\n * ```typescript\n * const arkTapscript = decodeTapscript(new Uint8Array(32));\n * console.log(\"type:\", arkTapscript.type);\n * ```\n */\nexport function decodeTapscript(script: Uint8Array): ArkTapscript<TapscriptType, any> {\n const types = [\n MultisigTapscript,\n CSVMultisigTapscript,\n ConditionCSVMultisigTapscript,\n ConditionMultisigTapscript,\n CLTVMultisigTapscript,\n ];\n\n for (const type of types) {\n try {\n return type.decode(script);\n } catch (error) {\n continue;\n }\n }\n\n throw new Error(`Failed to decode: script ${hex.encode(script)} is not a valid tapscript`);\n}\n\n/**\n * Implements a multi-signature tapscript.\n *\n * <pubkey> CHECKSIGVERIFY <pubkey> CHECKSIG\n *\n * @example\n * ```typescript\n * const multisigTapscript = MultisigTapscript.encode({ pubkeys: [new Uint8Array(32), new Uint8Array(32)] });\n * ```\n */\nexport namespace MultisigTapscript {\n export type Type = ArkTapscript<TapscriptType.Multisig, Params>;\n\n export enum MultisigType {\n CHECKSIG,\n CHECKSIGADD,\n }\n\n export type Params = {\n pubkeys: Bytes[];\n type?: MultisigType;\n };\n\n /** Encode a plain multisig tapscript. */\n export function encode(params: Params): Type {\n if (params.pubkeys.length === 0) {\n throw new Error(\"At least 1 pubkey is required\");\n }\n\n for (const pubkey of params.pubkeys) {\n if (pubkey.length !== 32) {\n throw new Error(`Invalid pubkey length: expected 32, got ${pubkey.length}`);\n }\n }\n\n if (!params.type) {\n params.type = MultisigType.CHECKSIG;\n }\n\n if (params.type === MultisigType.CHECKSIGADD) {\n return {\n type: TapscriptType.Multisig,\n params,\n script: p2tr_ms(params.pubkeys.length, params.pubkeys).script,\n };\n }\n\n const asm: ScriptType = [];\n for (let i = 0; i < params.pubkeys.length; i++) {\n asm.push(params.pubkeys[i]);\n\n // CHECKSIGVERIFY except the last pubkey\n if (i < params.pubkeys.length - 1) {\n asm.push(\"CHECKSIGVERIFY\");\n } else {\n asm.push(\"CHECKSIG\");\n }\n }\n\n return {\n type: TapscriptType.Multisig,\n params,\n script: Script.encode(asm),\n };\n }\n\n /** Decode a plain multisig tapscript from raw script bytes. */\n export function decode(script: Uint8Array): Type {\n if (script.length === 0) {\n throw new Error(\"Failed to decode: script is empty\");\n }\n\n try {\n // Try decoding as checksigAdd first\n return decodeChecksigAdd(script);\n } catch (error) {\n // If checksigAdd fails, try regular checksig\n try {\n return decodeChecksig(script);\n } catch (error2) {\n throw new Error(\n `Failed to decode script: ${error2 instanceof Error ? error2.message : String(error2)}`,\n );\n }\n }\n }\n\n // <pubkey> CHECKSIG <pubkey> CHECKSIGADD <len_keys> NUMEQUAL\n function decodeChecksigAdd(script: Uint8Array): Type {\n const asm = Script.decode(script);\n const pubkeys: Bytes[] = [];\n let foundNumEqual = false;\n\n // Parse through ASM operations\n for (let i = 0; i < asm.length; i++) {\n const op = asm[i];\n\n // If it's a data push, it should be a 32-byte pubkey\n if (typeof op !== \"string\" && typeof op !== \"number\") {\n if (op.length !== 32) {\n throw new Error(`Invalid pubkey length: expected 32, got ${op.length}`);\n }\n pubkeys.push(op);\n\n // Check next operation is CHECKSIGADD or CHECKSIG\n if (\n i + 1 >= asm.length ||\n (asm[i + 1] !== \"CHECKSIGADD\" && asm[i + 1] !== \"CHECKSIG\")\n ) {\n throw new Error(\"Expected CHECKSIGADD or CHECKSIG after pubkey\");\n }\n i++; // Skip the CHECKSIGADD op\n continue;\n }\n\n // Last operation should be NUMEQUAL\n if (i === asm.length - 1) {\n if (op !== \"NUMEQUAL\") {\n throw new Error(\"Expected NUMEQUAL at end of script\");\n }\n foundNumEqual = true;\n }\n }\n\n if (!foundNumEqual) {\n throw new Error(\"Missing NUMEQUAL operation\");\n }\n\n if (pubkeys.length === 0) {\n throw new Error(\"Invalid script: must have at least 1 pubkey\");\n }\n\n // Verify the script by re-encoding and comparing\n const reconstructed = encode({\n pubkeys,\n type: MultisigType.CHECKSIGADD,\n });\n if (hex.encode(reconstructed.script) !== hex.encode(script)) {\n throw new Error(\"Invalid script format: script reconstruction mismatch\");\n }\n\n return {\n type: TapscriptType.Multisig,\n params: { pubkeys, type: MultisigType.CHECKSIGADD },\n script,\n };\n }\n\n // <pubkey> CHECKSIGVERIFY <pubkey> CHECKSIG\n function decodeChecksig(script: Uint8Array): Type {\n const asm = Script.decode(script);\n const pubkeys: Bytes[] = [];\n\n // Parse through ASM operations\n for (let i = 0; i < asm.length; i++) {\n const op = asm[i];\n\n // If it's a data push, it should be a 32-byte pubkey\n if (typeof op !== \"string\" && typeof op !== \"number\") {\n if (op.length !== 32) {\n throw new Error(`Invalid pubkey length: expected 32, got ${op.length}`);\n }\n pubkeys.push(op);\n\n // Check next operation\n if (i + 1 >= asm.length) {\n throw new Error(\"Unexpected end of script\");\n }\n\n const nextOp = asm[i + 1];\n if (nextOp !== \"CHECKSIGVERIFY\" && nextOp !== \"CHECKSIG\") {\n throw new Error(\"Expected CHECKSIGVERIFY or CHECKSIG after pubkey\");\n }\n\n // Last operation must be CHECKSIG, not CHECKSIGVERIFY\n if (i === asm.length - 2 && nextOp !== \"CHECKSIG\") {\n throw new Error(\"Last operation must be CHECKSIG\");\n }\n\n i++; // Skip the CHECKSIG/CHECKSIGVERIFY op\n continue;\n }\n }\n\n if (pubkeys.length === 0) {\n throw new Error(\"Invalid script: must have at least 1 pubkey\");\n }\n\n // Verify the script by re-encoding and comparing\n const reconstructed = encode({ pubkeys, type: MultisigType.CHECKSIG });\n if (hex.encode(reconstructed.script) !== hex.encode(script)) {\n throw new Error(\"Invalid script format: script reconstruction mismatch\");\n }\n\n return {\n type: TapscriptType.Multisig,\n params: { pubkeys, type: MultisigType.CHECKSIG },\n script,\n };\n }\n\n /** Return true when the tapscript is a plain multisig tapscript. */\n export function is(tapscript: ArkTapscript<any, any>): tapscript is Type {\n return tapscript.type === TapscriptType.Multisig;\n }\n}\n\n/**\n * Implements a relative timelock script that requires all specified pubkeys to sign\n * after the relative timelock has expired. The timelock can be specified in blocks or seconds.\n *\n * This is the standard exit closure and it is also used for the sweep closure in vtxo trees.\n *\n * <sequence> CHECKSEQUENCEVERIFY DROP <pubkey> CHECKSIG\n *\n * @example\n * ```typescript\n * const csvMultisigTapscript = CSVMultisigTapscript.encode({ timelock: { type: \"blocks\", value: 144 }, pubkeys: [new Uint8Array(32), new Uint8Array(32)] });\n * ```\n */\nexport namespace CSVMultisigTapscript {\n export type Type = ArkTapscript<TapscriptType.CSVMultisig, Params>;\n\n export type Params = {\n timelock: RelativeTimelock;\n } & MultisigTapscript.Params;\n\n /** Encode a CSV multisig tapscript. */\n export function encode(params: Params): Type {\n for (const pubkey of params.pubkeys) {\n if (pubkey.length !== 32) {\n throw new Error(`Invalid pubkey length: expected 32, got ${pubkey.length}`);\n }\n }\n\n const sequence = MinimalScriptNum.encode(BigInt(timelockToSequence(params.timelock)));\n\n const asm: ScriptType = [\n sequence.length === 1 ? sequence[0] : sequence,\n \"CHECKSEQUENCEVERIFY\",\n \"DROP\",\n ];\n const multisigScript = MultisigTapscript.encode(params);\n const script = new Uint8Array([...Script.encode(asm), ...multisigScript.script]);\n\n return {\n type: TapscriptType.CSVMultisig,\n params,\n script,\n };\n }\n\n /** Decode a CSV multisig tapscript from raw script bytes. */\n export function decode(script: Uint8Array): Type {\n if (script.length === 0) {\n throw new Error(\"Failed to decode: script is empty\");\n }\n\n const isValid = isScriptValid(script);\n if (isValid instanceof Error) {\n throw isValid;\n }\n\n const asm = Script.decode(script);\n\n const sequence = asm[0];\n const multisigScript = new Uint8Array(Script.encode(asm.slice(3)));\n let multisig: MultisigTapscript.Type;\n\n try {\n multisig = MultisigTapscript.decode(multisigScript);\n } catch (error) {\n throw new Error(\n `Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n let sequenceNum: number;\n if (typeof sequence === \"number\") {\n sequenceNum = sequence;\n } else {\n sequenceNum = Number(MinimalScriptNum.decode(sequence as Uint8Array));\n }\n const timelock = sequenceToTimelock(sequenceNum);\n\n const reconstructed = encode({\n timelock,\n ...multisig.params,\n });\n\n if (hex.encode(reconstructed.script) !== hex.encode(script)) {\n throw new Error(\"Invalid script format: script reconstruction mismatch\");\n }\n\n return {\n type: TapscriptType.CSVMultisig,\n params: {\n timelock,\n ...multisig.params,\n },\n script,\n };\n }\n\n /** Return true when the tapscript is a CSV multisig tapscript. */\n export function is(tapscript: ArkTapscript<any, any>): tapscript is Type {\n return tapscript.type === TapscriptType.CSVMultisig;\n }\n\n export function isScriptValid(script: Uint8Array): true | Error {\n const asm = Script.decode(script);\n\n if (asm.length < 3) {\n return new Error(`Invalid script: too short (expected at least 3)`);\n }\n\n const sequence = asm[0];\n if (typeof sequence === \"string\") {\n return new Error(\"Invalid script: expected sequence number\");\n }\n\n if (asm[1] !== \"CHECKSEQUENCEVERIFY\" || asm[2] !== \"DROP\") {\n return new Error(\"Invalid script: expected CHECKSEQUENCEVERIFY DROP\");\n }\n\n return true;\n }\n}\n\n/**\n * Combines a condition script with an exit closure. The resulting script requires\n * the condition to be met, followed by the standard exit closure requirements\n * (timelock and signatures).\n *\n * <conditionScript> VERIFY <sequence> CHECKSEQUENCEVERIFY DROP <pubkey> CHECKSIGVERIFY <pubkey> CHECKSIG\n *\n * @example\n * ```typescript\n * const conditionCSVMultisigTapscript = ConditionCSVMultisigTapscript.encode({ conditionScript: new Uint8Array(32), pubkeys: [new Uint8Array(32), new Uint8Array(32)] });\n * ```\n */\nexport namespace ConditionCSVMultisigTapscript {\n export type Type = ArkTapscript<TapscriptType.ConditionCSVMultisig, Params>;\n\n export type Params = {\n conditionScript: Bytes;\n } & CSVMultisigTapscript.Params;\n\n /** Encode a condition + CSV multisig tapscript. */\n export function encode(params: Params): Type {\n const script = new Uint8Array([\n ...params.conditionScript,\n ...Script.encode([\"VERIFY\"]),\n ...CSVMultisigTapscript.encode(params).script,\n ]);\n\n return {\n type: TapscriptType.ConditionCSVMultisig,\n params,\n script,\n };\n }\n\n /** Decode a condition + CSV multisig tapscript from raw script bytes. */\n export function decode(script: Uint8Array): Type {\n if (script.length === 0) {\n throw new Error(\"Failed to decode: script is empty\");\n }\n\n const isValid = isScriptValid(script);\n if (isValid instanceof Error) {\n throw isValid;\n }\n\n const asm = Script.decode(script);\n\n let verifyIndex = getVerifyIndex(asm);\n\n if (verifyIndex === -1) {\n throw Error(\"Invalid script: missing VERIFY operation\");\n }\n\n const conditionScript = new Uint8Array(Script.encode(asm.slice(0, verifyIndex)));\n const csvMultisigScript = new Uint8Array(Script.encode(asm.slice(verifyIndex + 1)));\n\n let csvMultisig: CSVMultisigTapscript.Type;\n try {\n csvMultisig = CSVMultisigTapscript.decode(csvMultisigScript);\n } catch (error) {\n throw new Error(\n `Invalid CSV multisig script: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n const reconstructed = encode({\n conditionScript,\n ...csvMultisig.params,\n });\n\n if (hex.encode(reconstructed.script) !== hex.encode(script)) {\n throw new Error(\"Invalid script format: script reconstruction mismatch\");\n }\n\n return {\n type: TapscriptType.ConditionCSVMultisig,\n params: {\n conditionScript,\n ...csvMultisig.params,\n },\n script,\n };\n }\n\n /** Return true when the tapscript is a condition + CSV multisig tapscript. */\n export function is(tapscript: ArkTapscript<any, any>): tapscript is Type {\n return tapscript.type === TapscriptType.ConditionCSVMultisig;\n }\n\n function getVerifyIndex(asm: ScriptType) {\n let verifyIndex = -1;\n for (let i = asm.length - 1; i >= 0; i--) {\n if (asm[i] === \"VERIFY\") {\n verifyIndex = i;\n return verifyIndex;\n }\n }\n return verifyIndex;\n }\n\n export function isScriptValid(script: Uint8Array): true | Error {\n const asm = Script.decode(script);\n\n if (asm.length < 1) {\n return new Error(`Invalid script: too short (expected at least 1)`);\n }\n\n let verifyIndex = getVerifyIndex(asm);\n\n if (verifyIndex === -1) {\n return new Error(\"Invalid script: missing VERIFY operation\");\n }\n\n return true;\n }\n}\n\n/**\n * Combines a condition script with a forfeit closure. The resulting script requires\n * the condition to be met, followed by the standard forfeit closure requirements\n * (multi-signature).\n *\n * <conditionScript> VERIFY <pubkey> CHECKSIGVERIFY <pubkey> CHECKSIG\n *\n * @example\n * ```typescript\n * const conditionMultisigTapscript = ConditionMultisigTapscript.encode({ conditionScript: new Uint8Array(32), pubkeys: [new Uint8Array(32), new Uint8Array(32)] });\n * ```\n */\nexport namespace ConditionMultisigTapscript {\n export type Type = ArkTapscript<TapscriptType.ConditionMultisig, Params>;\n\n export type Params = {\n conditionScript: Bytes;\n } & MultisigTapscript.Params;\n\n /** Encode a condition + multisig tapscript. */\n export function encode(params: Params): Type {\n const script = new Uint8Array([\n ...params.conditionScript,\n ...Script.encode([\"VERIFY\"]),\n ...MultisigTapscript.encode(params).script,\n ]);\n\n return {\n type: TapscriptType.ConditionMultisig,\n params,\n script,\n };\n }\n\n /** Decode a condition + multisig tapscript from raw script bytes. */\n export function decode(script: Uint8Array): Type {\n if (script.length === 0) {\n throw new Error(\"Failed to decode: script is empty\");\n }\n\n const isValid = isScriptValid(script);\n if (isValid instanceof Error) {\n throw isValid;\n }\n\n const asm = Script.decode(script);\n\n let verifyIndex = getVerifyIndex(asm);\n\n if (verifyIndex === -1) {\n throw Error(\"Invalid script: missing VERIFY operation\");\n }\n\n const conditionScript = new Uint8Array(Script.encode(asm.slice(0, verifyIndex)));\n const multisigScript = new Uint8Array(Script.encode(asm.slice(verifyIndex + 1)));\n\n let multisig: MultisigTapscript.Type;\n try {\n multisig = MultisigTapscript.decode(multisigScript);\n } catch (error) {\n throw new Error(\n `Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n const reconstructed = encode({\n conditionScript,\n ...multisig.params,\n });\n\n if (hex.encode(reconstructed.script) !== hex.encode(script)) {\n throw new Error(\"Invalid script format: script reconstruction mismatch\");\n }\n\n return {\n type: TapscriptType.ConditionMultisig,\n params: {\n conditionScript,\n ...multisig.params,\n },\n script,\n };\n }\n\n /** Return true when the tapscript is a condition + multisig tapscript. */\n export function is(tapscript: ArkTapscript<any, any>): tapscript is Type {\n return tapscript.type === TapscriptType.ConditionMultisig;\n }\n\n function getVerifyIndex(asm: ScriptType) {\n let verifyIndex = -1;\n for (let i = asm.length - 1; i >= 0; i--) {\n if (asm[i] === \"VERIFY\") {\n verifyIndex = i;\n return verifyIndex;\n }\n }\n return verifyIndex;\n }\n\n export function isScriptValid(script: Uint8Array): true | Error {\n const asm = Script.decode(script);\n\n if (asm.length < 1) {\n return new Error(`Invalid script: too short (expected at least 1)`);\n }\n\n let verifyIndex = getVerifyIndex(asm);\n\n if (verifyIndex === -1) {\n return new Error(\"Invalid script: missing VERIFY operation\");\n }\n\n return true;\n }\n}\n\n/**\n * Implements an absolute timelock (CLTV) script combined with a forfeit closure.\n * The script requires waiting until a specific block height/timestamp before the\n * forfeit closure conditions can be met.\n *\n * <locktime> CHECKLOCKTIMEVERIFY DROP <pubkey> CHECKSIGVERIFY <pubkey> CHECKSIG\n *\n * @example\n * ```typescript\n * const cltvMultisigTapscript = CLTVMultisigTapscript.encode({ absoluteTimelock: 144, pubkeys: [new Uint8Array(32), new Uint8Array(32)] });\n * ```\n */\nexport namespace CLTVMultisigTapscript {\n export type Type = ArkTapscript<TapscriptType.CLTVMultisig, Params>;\n\n export type Params = {\n absoluteTimelock: bigint;\n } & MultisigTapscript.Params;\n\n /** Encode a CLTV multisig tapscript. */\n export function encode(params: Params): Type {\n const locktime = MinimalScriptNum.encode(params.absoluteTimelock);\n const asm: ScriptType = [\n locktime.length === 1 ? locktime[0] : locktime,\n \"CHECKLOCKTIMEVERIFY\",\n \"DROP\",\n ];\n const timelockedScript = Script.encode(asm);\n\n const script = new Uint8Array([\n ...timelockedScript,\n ...MultisigTapscript.encode(params).script,\n ]);\n\n return {\n type: TapscriptType.CLTVMultisig,\n params,\n script,\n };\n }\n\n /** Decode a CLTV multisig tapscript from raw script bytes. */\n export function decode(script: Uint8Array): Type {\n if (script.length === 0) {\n throw new Error(\"Failed to decode: script is empty\");\n }\n\n const isValid = isScriptValid(script);\n if (isValid instanceof Error) {\n throw isValid;\n }\n\n const asm = Script.decode(script);\n\n const locktime = asm[0];\n if (typeof locktime === \"string\") {\n throw new Error(\"Invalid script: expected locktime number\");\n }\n\n if (asm[1] !== \"CHECKLOCKTIMEVERIFY\" || asm[2] !== \"DROP\") {\n throw new Error(\"Invalid script: expected CHECKLOCKTIMEVERIFY DROP\");\n }\n\n const multisigScript = new Uint8Array(Script.encode(asm.slice(3)));\n let multisig: MultisigTapscript.Type;\n\n try {\n multisig = MultisigTapscript.decode(multisigScript);\n } catch (error) {\n throw new Error(\n `Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n let absoluteTimelock: bigint;\n if (typeof locktime === \"number\") {\n absoluteTimelock = BigInt(locktime);\n } else {\n absoluteTimelock = MinimalScriptNum.decode(locktime as Bytes);\n }\n\n const reconstructed = encode({\n absoluteTimelock,\n ...multisig.params,\n });\n\n if (hex.encode(reconstructed.script) !== hex.encode(script)) {\n throw new Error(\"Invalid script format: script reconstruction mismatch\");\n }\n\n return {\n type: TapscriptType.CLTVMultisig,\n params: {\n absoluteTimelock,\n ...multisig.params,\n },\n script,\n };\n }\n\n /** Return true when the tapscript is a CLTV multisig tapscript. */\n export function is(tapscript: ArkTapscript<any, any>): tapscript is Type {\n return tapscript.type === TapscriptType.CLTVMultisig;\n }\n\n export function isScriptValid(script: Uint8Array): true | Error {\n const asm = Script.decode(script);\n\n if (asm.length < 3) {\n return new Error(`Invalid script: too short (expected at least 3)`);\n }\n\n const locktime = asm[0];\n if (typeof locktime === \"string\") {\n return new Error(\"Invalid script: expected locktime as number or bytes\");\n }\n\n if (asm[1] !== \"CHECKLOCKTIMEVERIFY\" || asm[2] !== \"DROP\") {\n return new Error(\"Invalid script: expected CHECKLOCKTIMEVERIFY DROP\");\n }\n\n return true;\n }\n}\n","import { TAP_LEAF_VERSION } from \"@scure/btc-signer/payment.js\";\nimport { Bytes } from \"@scure/btc-signer/utils.js\";\n\n/**\n * A leaf node in the Taproot script tree, as consumed by\n * `@scure/btc-signer`'s `p2tr(internalKey, tree, ...)`.\n */\nexport interface TaprootLeaf {\n script: Bytes;\n leafVersion: number;\n}\n\n/**\n * Internal tree node shape consumed by `@scure/btc-signer`'s `p2tr`:\n * - A leaf is `{ script, leafVersion }`\n * - A branch is a 2-element tuple `[leftNode, rightNode]` of nodes\n */\nexport type TaprootTreeNode = TaprootLeaf | [TaprootTreeNode, TaprootTreeNode];\n\n/**\n * Assemble a Taproot script tree from a flat list of scripts using the\n * exact algorithm arkd's btcd dependency uses\n * (`txscript.AssembleTaprootScriptTree`, see\n * https://github.com/btcsuite/btcd/blob/master/txscript/taproot.go).\n *\n * The algorithm:\n *\n * Phase 1 — pair leaves left-to-right:\n * for i := 0; i < len(leaves); i += 2:\n * if i is the last index (odd leaf at end):\n * merge with the LAST branch built so far (do NOT pair as a fresh leaf)\n * else:\n * create a new branch from (leaves[i], leaves[i+1])\n *\n * Phase 2 — FIFO-queue merge branches:\n * while branches has ≥ 2 items:\n * take front two, combine into a new branch, push to back of queue\n *\n * This matters because `@scure/btc-signer`'s `taprootListToTree` builds a\n * Huffman tree (weight-1 leaves combine by smallest-weight pairs). For\n * power-of-2 leaf counts both algorithms happen to produce the same\n * perfectly-balanced binary tree and agree. For any other count they\n * produce DIFFERENT shapes → different merkle roots → different taproot\n * output keys → arkd rejects spends with `INVALID_PSBT_INPUT`.\n *\n * Reproducing btcd's algorithm here lets the SDK construct taptrees that\n * arkd accepts for arbitrary leaf counts.\n *\n * @param scripts - Raw tapscript bytes for each leaf, in the order they\n * should be encoded in the TapTree PSBT field.\n * @returns The nested-tuple form `p2tr` accepts.\n */\nexport function assembleBtcdTaprootTree(scripts: Bytes[]): TaprootTreeNode {\n if (scripts.length === 0) {\n throw new Error(\"assembleBtcdTaprootTree: empty scripts list\");\n }\n\n const leaves: TaprootLeaf[] = scripts.map((script) => ({\n script,\n leafVersion: TAP_LEAF_VERSION,\n }));\n\n if (leaves.length === 1) {\n return leaves[0];\n }\n\n // ── Phase 1: pair leaves left-to-right ─────────────────────────────\n const branches: TaprootTreeNode[] = [];\n for (let i = 0; i < leaves.length; i += 2) {\n if (i === leaves.length - 1) {\n // Odd leaf at end: merge into the LAST branch built so far.\n // Mirrors btcd's\n // branches[len(branches)-1] = NewTapBranch(branchToMerge, leaf)\n const last = branches.pop();\n if (last === undefined) {\n // Defensive — caller should have provided ≥ 2 leaves.\n throw new Error(\n `assembleBtcdTaprootTree: unexpected odd leaf at i=${i} with no prior branch`,\n );\n }\n branches.push([last, leaves[i]]);\n } else {\n // Pair two consecutive leaves into a new branch.\n branches.push([leaves[i], leaves[i + 1]]);\n }\n }\n\n // ── Phase 2: FIFO-queue merge branches ─────────────────────────────\n // Take front two, combine, push to back. Stops when one branch remains.\n while (branches.length >= 2) {\n const left = branches.shift()!;\n const right = branches.shift()!;\n branches.push([left, right]);\n }\n\n return branches[0];\n}\n","import { Address, p2tr, TAPROOT_UNSPENDABLE_KEY, NETWORK } from \"@scure/btc-signer\";\nimport { TAP_LEAF_VERSION } from \"@scure/btc-signer/payment.js\";\nimport { PSBTOutput } from \"@scure/btc-signer/psbt.js\";\nimport { Bytes } from \"@scure/btc-signer/utils.js\";\nimport { hex } from \"@scure/base\";\nimport { ArkAddress } from \"./address\";\nimport { timelockToSequence } from \"../utils/timelock\";\nimport {\n CLTVMultisigTapscript,\n ConditionCSVMultisigTapscript,\n CSVMultisigTapscript,\n} from \"./tapscript\";\nimport { assembleBtcdTaprootTree } from \"./taprootTree\";\nimport { DEFAULT_NETWORK } from \"../networks\";\n\nexport type TapLeafScript = [\n {\n version: number;\n internalKey: Bytes;\n merklePath: Bytes[];\n },\n Bytes,\n];\n\nexport const TapTreeCoder: (typeof PSBTOutput.tapTree)[2] = PSBTOutput.tapTree[2];\n\nexport function scriptFromTapLeafScript(leaf: TapLeafScript): Bytes {\n return leaf[1].subarray(0, leaf[1].length - 1); // remove the version byte\n}\n\n/**\n * VtxoScript is a script that contains a list of tapleaf scripts.\n * It is used to create virtual output scripts.\n *\n * @see ArkAddress\n *\n * @example\n * ```typescript\n * const vtxoScript = new VtxoScript([new Uint8Array(32), new Uint8Array(32)]);\n * ```\n */\nexport class VtxoScript {\n readonly leaves: TapLeafScript[];\n readonly tweakedPublicKey: Bytes;\n readonly pkScript: Bytes;\n\n /**\n * Decode a virtual output script from an encoded TapTree.\n *\n * @param tapTree - Encoded TapTree bytes\n * @returns Decoded virtual output script\n * @throws Error if the TapTree cannot be decoded into a valid script set\n * @see encode\n */\n static decode(tapTree: Bytes): VtxoScript {\n const leaves = TapTreeCoder.decode(tapTree);\n const scripts = leaves.map((leaf) => leaf.script);\n return new VtxoScript(scripts);\n }\n\n /**\n * Create a virtual output script from its tapleaf scripts.\n *\n * The Taproot script tree is assembled using btcd's algorithm\n * (`txscript.AssembleTaprootScriptTree`) so the derived taproot output\n * key agrees with arkd for any leaf count. `@scure/btc-signer`'s\n * default `taprootListToTree` is a Huffman builder that only agrees\n * with arkd for power-of-2 leaf counts.\n *\n * @param scripts - Raw tapscript bytes for each leaf\n * @throws Error if the provided leaves cannot produce a valid Taproot tree\n */\n constructor(readonly scripts: Bytes[]) {\n const tapTree = assembleBtcdTaprootTree(scripts);\n\n const payment = p2tr(TAPROOT_UNSPENDABLE_KEY, tapTree, undefined, true);\n\n if (!payment.tapLeafScript || payment.tapLeafScript.length !== scripts.length) {\n throw new Error(\"invalid scripts\");\n }\n\n this.leaves = payment.tapLeafScript;\n this.tweakedPublicKey = payment.tweakedPubkey;\n this.pkScript = payment.script;\n }\n\n /**\n * Encode the virtual output script to a TapTree byte representation.\n *\n * @returns Encoded TapTree bytes\n * @see decode\n */\n encode(): Bytes {\n const tapTree = TapTreeCoder.encode(\n this.scripts.map((script) => ({\n depth: 1,\n version: TAP_LEAF_VERSION,\n script,\n })),\n );\n return tapTree;\n }\n\n /**\n * Build the Arkade address corresponding to this virtual output script.\n *\n * @param prefix - Bech32 human-readable prefix\n * @param serverPubKey - 32-byte Arkade server public key\n * @returns Arkade address for this script\n * @see ArkAddress\n */\n address(prefix: string = DEFAULT_NETWORK.hrp, serverPubKey: Bytes): ArkAddress {\n return new ArkAddress(serverPubKey, this.tweakedPublicKey, prefix);\n }\n\n /**\n * Build the Taproot onchain address corresponding to this virtual output script.\n *\n * @param network - Bitcoin network descriptor\n * @returns Taproot onchain address\n * @see address\n */\n onchainAddress(network: typeof NETWORK = DEFAULT_NETWORK): string {\n return Address(network).encode({\n type: \"tr\",\n pubkey: this.tweakedPublicKey,\n });\n }\n\n /**\n * Look up a tapleaf script by its hex-encoded tapscript body.\n *\n * @param scriptHex - Hex-encoded tapscript body without the leaf version byte\n * @returns Matching tapleaf script\n * @throws Error if no matching leaf exists\n */\n findLeaf(scriptHex: string): TapLeafScript {\n const leaf = this.leaves.find(\n (leaf) => hex.encode(scriptFromTapLeafScript(leaf)) === scriptHex,\n )!;\n if (!leaf) {\n throw new Error(`leaf '${scriptHex}' not found`);\n }\n return leaf;\n }\n\n /**\n * Return all unilateral exit paths embedded in the virtual output script.\n *\n * @returns CSV-based exit paths found in the leaves\n * @see getSequence\n */\n exitPaths(): Array<CSVMultisigTapscript.Type | ConditionCSVMultisigTapscript.Type> {\n const paths: Array<CSVMultisigTapscript.Type | ConditionCSVMultisigTapscript.Type> = [];\n for (const leaf of this.leaves) {\n try {\n const script = scriptFromTapLeafScript(leaf);\n if (CSVMultisigTapscript.isScriptValid(script) === true) {\n const tapScript = CSVMultisigTapscript.decode(script);\n paths.push(tapScript);\n } else if (ConditionCSVMultisigTapscript.isScriptValid(script) === true) {\n const tapScript = ConditionCSVMultisigTapscript.decode(script);\n paths.push(tapScript);\n }\n } catch (e) {\n console.debug(\"Failed to decode script\", e);\n }\n }\n return paths;\n }\n}\n\nexport type EncodedVtxoScript = { tapTree: Bytes };\n\n/**\n * Extract the timelock value encoded in a timelocked tapleaf, if any.\n *\n * The return value is unit-ambiguous: for a CSV leaf it is a BIP-68\n * nSequence (relative timelock); for a CLTV leaf it is an absolute\n * nLockTime. Callers must know which leaf shape they are inspecting to\n * interpret the number correctly, and must not copy a CSV result into\n * `Transaction.lockTime` (or vice versa).\n *\n * @param tapLeafScript - Tapleaf script to inspect\n * @returns The encoded timelock value, or `undefined` when neither a CSV\n * nor CLTV path is present\n * @see VtxoScript.exitPaths\n */\n// TODO(next-major): return a discriminated union\n// (`{ kind: \"relative\", nSequence } | { kind: \"absolute\", lockTime }`)\n// so callers can't conflate the two. Deferred because changing the\n// return type is a breaking change.\nexport function getSequence(tapLeafScript: TapLeafScript): number | undefined {\n let sequence: number | undefined = undefined;\n\n try {\n const scriptWithLeafVersion = tapLeafScript[1];\n const script = scriptWithLeafVersion.subarray(0, scriptWithLeafVersion.length - 1);\n try {\n const params = CSVMultisigTapscript.decode(script).params;\n sequence = timelockToSequence(params.timelock);\n } catch {\n const params = CLTVMultisigTapscript.decode(script).params;\n sequence = Number(params.absoluteTimelock);\n }\n } catch {}\n\n return sequence;\n}\n","import type { GetVtxosOptions, IndexerProvider, PageResponse, Vtxo } from \"../providers/indexer\";\nimport type { OnchainProvider } from \"../providers/onchain\";\nimport type { ExtendedVirtualCoin, VirtualCoin, VirtualStatus } from \"./index\";\n\n/**\n * Canonical VTXO facts, the conversions between them and the legacy `virtualStatus` projection,\n * and the capability predicates behavior is expected to read.\n *\n * Three directions are owned here:\n *\n * 1. wire `Vtxo` -> canonical ({@link convertVtxo})\n * 2. canonical -> legacy `virtualStatus` ({@link toVirtualStatus})\n * 3. legacy `virtualStatus` -> canonical ({@link normalizeVtxo})\n *\n * Direction 3 is not just for old persisted rows: `IndexerProvider` and `WalletRepository` are\n * public interfaces, so consumer implementations may hand back legacy-shaped coins through the\n * front door. Normalization therefore runs where the SDK *consumes* an interface, never inside an\n * implementation of one.\n */\n\n/**\n * Below this, a millisecond value is too small to be a real batch expiry and is read as a block\n * height instead. The server returns one scalar for both units.\n *\n * A UTC constant rather than `getFullYear()`, which reads local time and would make the\n * classification depend on the runtime's timezone.\n */\nexport const EXPIRY_MIN_PLAUSIBLE_MS = Date.UTC(2025, 0, 1);\n\n/**\n * The current moment, as the expiry predicates need it.\n *\n * `height` is optional: offline-first paths have no chain tip at hand. When it is absent,\n * height-based expiry cannot be evaluated and reads as not expired.\n */\nexport type TimeHeight = { timestamp: Date; height?: number };\n\n/**\n * Resolve the {@link TimeHeight} for one expiry-driven pass.\n *\n * @remarks\n * Fetch the tip once per pass and reuse the result for every VTXO in it, so the pass judges them\n * all against the same height.\n *\n * A tip-fetch failure **degrades to timestamp-only rather than blocking**: height-encoded expiry\n * then reads as not expired, which is what the whole SDK did before heights were evaluated at all.\n * Recovery and deprecated-signer migration must not become unavailable because the onchain provider\n * is down.\n *\n * Pass no provider to opt out of height entirely — the offline-first paths (balance, coin\n * selection) do this deliberately.\n */\nexport async function resolveTimeHeight(\n provider?: Pick<OnchainProvider, \"getChainTip\">,\n): Promise<TimeHeight> {\n const timestamp = new Date();\n if (!provider) return { timestamp };\n try {\n const tip = await provider.getChainTip();\n return { timestamp, height: tip.height };\n } catch (e) {\n console.warn(\"Failed to fetch chain tip; height-based expiry will not be evaluated\", e);\n return { timestamp };\n }\n}\n\n/**\n * A {@link VirtualCoin} that has passed through {@link normalizeVtxo}: every fact the capability\n * predicates read is present.\n *\n * Internal signatures take this rather than `VirtualCoin` so the compiler rejects un-normalized\n * input — on the public shape these facts are optional, and `undefined` is falsy, so a legacy coin\n * would silently read as \"not swept\", \"not spent\", and drop out of the wrong bucket.\n *\n * It is deliberately a *subtype* of `VirtualCoin`, so normalized coins are returned to consumers\n * directly and no egress projection exists.\n */\nexport type NormalizedVirtualCoin = Omit<\n VirtualCoin,\n \"isSwept\" | \"isPreconfirmed\" | \"isSpent\" | \"spentBy\" | \"commitmentTxIds\"\n> & {\n isSwept: boolean;\n isPreconfirmed: boolean;\n isSpent: boolean;\n spentBy: string;\n commitmentTxIds: string[];\n};\n\nexport type NormalizedExtendedVirtualCoin = ExtendedVirtualCoin & NormalizedVirtualCoin;\n\n// --- expiry ------------------------------------------------------------------------------------\n\n/** The wire's single `expiresAt` scalar -> canonical, disambiguating seconds from height. */\nexport function parseWireExpiry(raw: string | null | undefined): {\n expiresAt?: Date;\n expiresAtHeight?: number;\n} {\n if (raw === null || raw === undefined || raw === \"\") return {};\n const n = Number(raw);\n // `n <= 0` would otherwise yield `expiresAtHeight: 0`, which every chain tip is past — a VTXO\n // with no expiry would read as permanently expired.\n if (!Number.isFinite(n) || n <= 0) return {};\n const ms = n * 1000;\n if (ms >= EXPIRY_MIN_PLAUSIBLE_MS) return { expiresAt: new Date(ms) };\n return { expiresAtHeight: n };\n}\n\n/** Canonical -> legacy `batchExpiry`. */\nexport function toBatchExpiry(c: {\n expiresAt?: Date;\n expiresAtHeight?: number;\n}): number | undefined {\n if (c.expiresAt !== undefined) return c.expiresAt.getTime();\n // Multiplying a block height by 1000 is dimensionally meaningless, but it is what the legacy\n // converter did and what consumers already receive. Preserved deliberately.\n if (c.expiresAtHeight !== undefined) return c.expiresAtHeight * 1000;\n return undefined;\n}\n\n/** Legacy `batchExpiry` -> canonical, inverting {@link toBatchExpiry} on its domain. */\nexport function parseLegacyExpiry(batchExpiry: number | undefined): {\n expiresAt?: Date;\n expiresAtHeight?: number;\n} {\n // Same `<= 0` guard as `parseWireExpiry`.\n if (batchExpiry === undefined || batchExpiry <= 0) return {};\n if (batchExpiry >= EXPIRY_MIN_PLAUSIBLE_MS) return { expiresAt: new Date(batchExpiry) };\n return { expiresAtHeight: batchExpiry / 1000 };\n}\n\n// --- normalization -----------------------------------------------------------------------------\n\n/** Synthesize the legacy projection from canonical facts. */\nexport function toVirtualStatus(c: {\n isSpent?: boolean;\n isSwept?: boolean;\n isPreconfirmed?: boolean;\n commitmentTxIds?: string[];\n expiresAt?: Date;\n expiresAtHeight?: number;\n}): VirtualStatus {\n return {\n // Precedence is load-bearing: consumers bucket on this label, so any other order silently\n // moves VTXOs between buckets.\n state: c.isSpent\n ? \"spent\"\n : c.isSwept\n ? \"swept\"\n : c.isPreconfirmed\n ? \"preconfirmed\"\n : \"settled\",\n commitmentTxIds: c.commitmentTxIds,\n batchExpiry: toBatchExpiry(c),\n };\n}\n\n/**\n * Fill in every canonical fact, deriving from `virtualStatus` when a coin carries only the legacy\n * shape. Idempotent.\n *\n * Facts are derived with `??` so a coin that already carries its own authoritative value keeps it\n * rather than having it re-derived from the lossy projection.\n */\nexport function normalizeVtxo<T extends VirtualCoin>(v: T): T & NormalizedVirtualCoin {\n const state = v.virtualStatus?.state;\n const canonicalExpiry = v.expiresAt !== undefined || v.expiresAtHeight !== undefined;\n const expiry = canonicalExpiry\n ? // Coerce: a backend that persists through JSON hands back an ISO string, which typechecks\n // as `Date` but returns NaN from `.getTime()` — comparing false against everything.\n {\n expiresAt: v.expiresAt === undefined ? undefined : new Date(v.expiresAt),\n expiresAtHeight: v.expiresAtHeight,\n }\n : parseLegacyExpiry(v.virtualStatus?.batchExpiry);\n\n // `state === \"spent\"` cannot tell us whether the coin was *also* swept or preconfirmed — the\n // collapse destroyed that. Reading them as false matches today's behavior: a spent coin already\n // fails every spendability check.\n const isSpent = v.isSpent ?? state === \"spent\";\n const isSwept = v.isSwept ?? state === \"swept\";\n const isPreconfirmed = v.isPreconfirmed ?? state === \"preconfirmed\";\n const commitmentTxIds = v.commitmentTxIds ?? v.virtualStatus?.commitmentTxIds ?? [];\n\n return {\n ...v,\n isSpent,\n isSwept,\n isPreconfirmed,\n spentBy: v.spentBy ?? \"\",\n commitmentTxIds,\n ...expiry,\n virtualStatus:\n v.virtualStatus ??\n toVirtualStatus({ isSpent, isSwept, isPreconfirmed, commitmentTxIds, ...expiry }),\n };\n}\n\n/** Wire `Vtxo` -> canonical `VirtualCoin`. Shared by every indexer provider. */\nexport function convertVtxo(vtxo: Vtxo): NormalizedVirtualCoin {\n const expiry = parseWireExpiry(vtxo.expiresAt);\n const facts = {\n isSpent: vtxo.isSpent,\n isSwept: vtxo.isSwept,\n isPreconfirmed: vtxo.isPreconfirmed,\n commitmentTxIds: vtxo.commitmentTxids,\n ...expiry,\n };\n return {\n txid: vtxo.outpoint.txid,\n vout: vtxo.outpoint.vout,\n value: Number(vtxo.amount),\n status: {\n confirmed: !vtxo.isSwept && !vtxo.isPreconfirmed,\n isLeaf: !vtxo.isPreconfirmed,\n },\n ...facts,\n virtualStatus: toVirtualStatus(facts),\n spentBy: vtxo.spentBy ?? \"\",\n settledBy: vtxo.settledBy,\n arkTxId: vtxo.arkTxid,\n createdAt: new Date(Number(vtxo.createdAt) * 1000),\n isUnrolled: vtxo.isUnrolled,\n script: vtxo.script,\n assets: vtxo.assets?.map((a) => ({\n assetId: a.assetId,\n amount: BigInt(a.amount),\n })),\n };\n}\n\n// --- provider boundary -------------------------------------------------------------------------\n\n/**\n * The only sanctioned way for SDK logic to read VTXOs from an `IndexerProvider`: a drop-in for\n * `provider.getVtxos()` that normalizes whatever came back. A cheap pass-through for the built-in\n * providers, which already populate the facts.\n */\nexport async function getNormalizedVtxos(\n provider: Pick<IndexerProvider, \"getVtxos\">,\n opts?: GetVtxosOptions,\n): Promise<{ vtxos: NormalizedVirtualCoin[]; page?: PageResponse }> {\n const { vtxos, page } = await provider.getVtxos(opts);\n return { vtxos: vtxos.map(normalizeVtxo), page };\n}\n\n// --- capabilities ------------------------------------------------------------------------------\n\n/**\n * Whether a virtual output has been consumed and can never be spent again.\n *\n * @remarks\n * Unions all three spend facts rather than trusting any one of them. The wire contract permits\n * `isSpent: true` with an empty `spentBy` (settlement inputs needing no forfeit are written that\n * way), so a `spentBy || settledBy` definition would classify a spent VTXO as spendable — inflating\n * balance and selecting it for a send that must fail.\n */\nexport function hasTerminalSpend(vtxo: VirtualCoin): boolean {\n const n = normalizeVtxo(vtxo);\n return !!n.isSpent || !!n.spentBy || !!n.settledBy;\n}\n\n/**\n * Whether a virtual output's batch expiry has passed. Pure expiry — swept is a separate fact, ORed\n * in explicitly by {@link canSpendOffchain} / {@link canRecoverOnchain}.\n *\n * @remarks\n * Not named `isExpired`: the deprecated {@link isExpired} also returns `true` for a swept VTXO, and\n * two same-named predicates with different truth conditions is how a call site gets silently\n * rewired.\n *\n * Height-based expiry is only evaluated when `now.height` is supplied.\n */\nexport function isPastExpiry(vtxo: VirtualCoin, now: TimeHeight): boolean {\n const n = normalizeVtxo(vtxo);\n if (n.expiresAt !== undefined && now.timestamp.getTime() >= n.expiresAt.getTime()) return true;\n return (\n n.expiresAtHeight !== undefined &&\n now.height !== undefined &&\n now.height >= n.expiresAtHeight\n );\n}\n\n/** Whether a virtual output can be spent in an offchain transaction. The send/coin-selection test. */\nexport function canSpendOffchain(vtxo: VirtualCoin, now: TimeHeight): boolean {\n const n = normalizeVtxo(vtxo);\n return !hasTerminalSpend(n) && !(n.isSwept || isPastExpiry(n, now));\n}\n\n/**\n * Whether a virtual output must be recovered into a fresh batch rather than spent offchain. The\n * recovery/renewal test and the `recoverable` balance bucket.\n */\nexport function canRecoverOnchain(vtxo: VirtualCoin, now: TimeHeight): boolean {\n const n = normalizeVtxo(vtxo);\n return !hasTerminalSpend(n) && (n.isSwept || isPastExpiry(n, now));\n}\n\n// --- fee estimation ----------------------------------------------------------------------------\n\n/**\n * The `OffchainInput` fields that come from the VTXO itself, shared by every offchain fee estimate.\n *\n * @remarks\n * `expiry` goes through {@link toBatchExpiry} so the estimator keeps seeing exactly what the legacy\n * `batchExpiry` path fed it. Correcting the height case here would move fees, which is out of\n * scope.\n */\nexport function toOffchainInputFeeParams(vtxo: NormalizedVirtualCoin): {\n amount: bigint;\n type: \"recoverable\" | \"vtxo\";\n weight: number;\n birth: Date;\n expiry: Date | undefined;\n} {\n const batchExpiry = toBatchExpiry(vtxo);\n return {\n amount: BigInt(vtxo.value),\n type: vtxo.isSwept ? \"recoverable\" : \"vtxo\",\n weight: 0,\n birth: vtxo.createdAt,\n expiry: batchExpiry ? new Date(batchExpiry) : undefined,\n };\n}\n\n// --- discrimination ----------------------------------------------------------------------------\n\n/**\n * Narrow a settle input to a virtual output.\n *\n * @remarks\n * Keyed on `script`: it is required on `VirtualCoin` (so legacy and canonical shapes both have it)\n * and absent from `ExtendedCoin`, which the optional canonical facts cannot claim.\n *\n * The `typeof` guard is load-bearing — `settle` accepts arknote strings, and `in` throws a\n * `TypeError` on a primitive rather than returning false.\n */\nexport function isVirtualCoin<T>(input: T): input is T & VirtualCoin {\n return (\n typeof input === \"object\" &&\n input !== null &&\n typeof (input as { script?: unknown }).script === \"string\"\n );\n}\n\n// --- deprecated compatibility wrappers ---------------------------------------------------------\n\n/**\n * Return whether a virtual output is still spendable.\n *\n * @param vtxo - virtual output to inspect\n * @returns `true` when the virtual output has not been consumed\n *\n * @deprecated Ambiguous: `true` for swept or expired virtual outputs, which cannot in fact be spent\n * offchain. Use {@link canSpendOffchain}.\n */\nexport function isSpendable(vtxo: VirtualCoin): boolean {\n return !hasTerminalSpend(vtxo);\n}\n\n/**\n * Return whether a virtual output is recoverable.\n *\n * @param vtxo - virtual output to inspect\n * @returns `true` when the virtual output is swept but not yet consumed\n *\n * @deprecated Swept-only: ignores virtual outputs that are past expiry but not yet swept, which are\n * equally recoverable. Use {@link canRecoverOnchain}.\n */\nexport function isRecoverable(vtxo: VirtualCoin): boolean {\n const n = normalizeVtxo(vtxo);\n return n.isSwept && !hasTerminalSpend(n);\n}\n\n/**\n * Return whether a virtual output should be treated as expired.\n *\n * @param vtxo - virtual output to inspect\n * @returns `true` when the virtual output is swept or its wall-clock batch expiry has passed\n *\n * @deprecated Conflates swept with expired, and cannot evaluate height-based expiry — being\n * synchronous, it has no source for the current chain tip, so it ignores `expiresAtHeight` exactly\n * as it always has. For the recovery decision use {@link canRecoverOnchain}; to reproduce this\n * truth condition use `v.isSwept || isPastExpiry(v, now)`.\n */\nexport function isExpired(vtxo: VirtualCoin): boolean {\n const n = normalizeVtxo(vtxo);\n return n.isSwept || (n.expiresAt !== undefined && n.expiresAt.getTime() <= Date.now());\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { VtxoScript, getSequence, sequenceToTimelock, DEFAULT_ARKADE_SERVER_URL } from './chunk-C7TXXTMS.js';
1
+ import { VtxoScript, getSequence, sequenceToTimelock, DEFAULT_ARKADE_SERVER_URL, convertVtxo } from './chunk-ZDDBTFVO.js';
2
2
  import { __export } from './chunk-NSBPE2FW.js';
3
3
  import { OP, Script, SigHash, RawWitness, Transaction as Transaction$1, ScriptNum } from '@scure/btc-signer';
4
4
  import { schnorr } from '@noble/curves/secp256k1.js';
@@ -159,7 +159,7 @@ function checkKeyMatch(key, arkPsbtFieldKey, prefixOnly = false) {
159
159
  }
160
160
 
161
161
  // package.json
162
- var version = "0.4.47";
162
+ var version = "0.4.48";
163
163
 
164
164
  // src/utils/fetch.ts
165
165
  var buildVersion = "0.9.9";
@@ -582,6 +582,138 @@ function isEventSourceError(error) {
582
582
  return error instanceof Error && error.name === "EventSourceError";
583
583
  }
584
584
 
585
+ // src/providers/rateGate.ts
586
+ var DEFAULT_MAX_CONCURRENT = 6;
587
+ var DEFAULT_COOLDOWN_MS = 5e3;
588
+ var MAX_COOLDOWN_MS = 6e4;
589
+ var DEFAULT_JITTER_MS = 500;
590
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
591
+ function parseRetryAfterMs(header) {
592
+ if (header === null || header === void 0) return void 0;
593
+ const trimmed = header.trim();
594
+ if (trimmed === "") return void 0;
595
+ const seconds = Number(trimmed);
596
+ if (Number.isFinite(seconds)) return seconds < 0 ? void 0 : seconds * 1e3;
597
+ const at = Date.parse(trimmed);
598
+ if (!Number.isNaN(at)) return Math.max(0, at - Date.now());
599
+ return void 0;
600
+ }
601
+ function requestOrigin(input) {
602
+ let url;
603
+ if (typeof input === "string") {
604
+ url = input;
605
+ } else if (input instanceof URL) {
606
+ url = input.href;
607
+ } else {
608
+ url = input.url;
609
+ }
610
+ try {
611
+ return new URL(url).origin;
612
+ } catch {
613
+ return url;
614
+ }
615
+ }
616
+ var OriginRateGate = class {
617
+ states = /* @__PURE__ */ new Map();
618
+ maxConcurrent;
619
+ defaultCooldownMs;
620
+ maxCooldownMs;
621
+ jitterMs;
622
+ constructor(options) {
623
+ this.maxConcurrent = options?.maxConcurrent ?? DEFAULT_MAX_CONCURRENT;
624
+ this.defaultCooldownMs = options?.defaultCooldownMs ?? DEFAULT_COOLDOWN_MS;
625
+ this.maxCooldownMs = options?.maxCooldownMs ?? MAX_COOLDOWN_MS;
626
+ this.jitterMs = options?.jitterMs ?? DEFAULT_JITTER_MS;
627
+ }
628
+ /**
629
+ * Run `fn` under the origin's concurrency cap and behind any active
630
+ * cooldown. Put only the request in `fn`: the slot is released as soon as
631
+ * it settles, so body parsing doesn't hold one.
632
+ */
633
+ async run(input, fn) {
634
+ const state = this.stateFor(requestOrigin(input));
635
+ await this.acquire(state);
636
+ try {
637
+ for (; ; ) {
638
+ const remaining = state.blockedUntil - Date.now();
639
+ if (remaining <= 0) break;
640
+ await sleep(remaining + Math.random() * this.jitterMs);
641
+ }
642
+ return await fn();
643
+ } finally {
644
+ this.release(state);
645
+ }
646
+ }
647
+ /**
648
+ * {@link run} for a request whose response the gate should inspect: a `429`
649
+ * is recorded *before* the slot is released. Reporting after `run()` resolves
650
+ * is too late — `release()` hands the slot to the next queued waiter, which
651
+ * resumes, sees no cooldown, and sends into the limiter that just refused us.
652
+ *
653
+ * Prefer this over `run` for anything returning a `Response`.
654
+ */
655
+ runHttp(input, fn) {
656
+ return this.run(input, async () => {
657
+ const response = await fn();
658
+ if (response.status === 429) {
659
+ this.reportRateLimited(input, response.headers?.get("retry-after"));
660
+ }
661
+ return response;
662
+ });
663
+ }
664
+ /**
665
+ * Record an observed `429`, pausing every gated request to that origin.
666
+ * Monotonic: a shorter cooldown never shortens one already in effect.
667
+ */
668
+ reportRateLimited(input, retryAfterHeader) {
669
+ const cooldown = Math.min(
670
+ parseRetryAfterMs(retryAfterHeader) ?? this.defaultCooldownMs,
671
+ this.maxCooldownMs
672
+ );
673
+ const state = this.stateFor(requestOrigin(input));
674
+ state.blockedUntil = Math.max(state.blockedUntil, Date.now() + cooldown);
675
+ }
676
+ /** Milliseconds left on `input` origin's cooldown; `0` when not cooling down. */
677
+ cooldownRemainingMs(input) {
678
+ const state = this.states.get(requestOrigin(input));
679
+ if (!state) return 0;
680
+ return Math.max(0, state.blockedUntil - Date.now());
681
+ }
682
+ /**
683
+ * Drop all per-origin state, so test suites don't inherit each other's
684
+ * cooldowns. Waiters queued on the discarded state still drain normally.
685
+ */
686
+ reset() {
687
+ this.states.clear();
688
+ }
689
+ stateFor(origin) {
690
+ let state = this.states.get(origin);
691
+ if (!state) {
692
+ state = { blockedUntil: 0, active: 0, queue: [] };
693
+ this.states.set(origin, state);
694
+ }
695
+ return state;
696
+ }
697
+ acquire(state) {
698
+ if (state.active < this.maxConcurrent) {
699
+ state.active += 1;
700
+ return Promise.resolve();
701
+ }
702
+ return new Promise((resolve) => {
703
+ state.queue.push(() => {
704
+ state.active += 1;
705
+ resolve();
706
+ });
707
+ });
708
+ }
709
+ release(state) {
710
+ state.active -= 1;
711
+ const next = state.queue.shift();
712
+ if (next) next();
713
+ }
714
+ };
715
+ var rateGate = new OriginRateGate();
716
+
585
717
  // src/providers/ark.ts
586
718
  var DigestMismatchError = class extends Error {
587
719
  constructor(message) {
@@ -657,6 +789,9 @@ var RestArkProvider = class {
657
789
  throw toProviderUnavailable(err, "arkade");
658
790
  }
659
791
  if (response.ok) return response;
792
+ if (response.status === 429) {
793
+ rateGate.reportRateLimited(url, response.headers?.get("retry-after"));
794
+ }
660
795
  let body;
661
796
  try {
662
797
  body = await response.clone().text();
@@ -677,7 +812,7 @@ var RestArkProvider = class {
677
812
  }
678
813
  async getInfo() {
679
814
  const url = `${this.serverUrl}/v1/info`;
680
- const response = await fetch(url);
815
+ const response = await rateGate.runHttp(url, () => fetch(url));
681
816
  if (!response.ok) {
682
817
  const errorText = await response.text();
683
818
  throwIfHttpUnavailable(response, "arkade", errorText);
@@ -2455,24 +2590,43 @@ var Packet = class _Packet {
2455
2590
  return packet;
2456
2591
  }
2457
2592
  };
2593
+ var INDEXER_MAX_ATTEMPTS = 3;
2594
+ var INDEXER_RETRY_BASE_MS = 250;
2458
2595
  async function indexerFetch(input, init) {
2459
- let res;
2460
- try {
2461
- res = await baseFetch(input, init);
2462
- } catch (err) {
2463
- throw toProviderUnavailable(err, "indexer");
2464
- }
2465
- if (!res.ok) {
2596
+ const method = (init?.method ?? "GET").toUpperCase();
2597
+ const maxAttempts = method === "GET" || method === "HEAD" ? INDEXER_MAX_ATTEMPTS : 1;
2598
+ for (let attempt = 1; ; attempt++) {
2599
+ const lastAttempt = attempt >= maxAttempts;
2600
+ let res;
2601
+ try {
2602
+ res = await rateGate.runHttp(input, () => baseFetch(input, init));
2603
+ } catch (err) {
2604
+ const mapped = toProviderUnavailable(err, "indexer");
2605
+ if (lastAttempt || !(mapped instanceof ProviderUnavailableError)) throw mapped;
2606
+ await sleep2(retryDelayMs(attempt));
2607
+ continue;
2608
+ }
2609
+ if (res.ok) return res;
2466
2610
  let body;
2467
2611
  try {
2468
2612
  body = await res.clone().text();
2469
2613
  } catch {
2470
2614
  body = void 0;
2471
2615
  }
2472
- throwIfHttpUnavailable(res, "indexer", body);
2616
+ try {
2617
+ throwIfHttpUnavailable(res, "indexer", body);
2618
+ } catch (err) {
2619
+ if (lastAttempt) throw err;
2620
+ await sleep2(retryDelayMs(attempt));
2621
+ continue;
2622
+ }
2623
+ return res;
2473
2624
  }
2474
- return res;
2475
2625
  }
2626
+ function retryDelayMs(attempt) {
2627
+ return INDEXER_RETRY_BASE_MS * 2 ** (attempt - 1);
2628
+ }
2629
+ var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2476
2630
  var IndexerTxType = /* @__PURE__ */ ((IndexerTxType2) => {
2477
2631
  IndexerTxType2[IndexerTxType2["INDEXER_TX_TYPE_UNSPECIFIED"] = 0] = "INDEXER_TX_TYPE_UNSPECIFIED";
2478
2632
  IndexerTxType2[IndexerTxType2["INDEXER_TX_TYPE_RECEIVED"] = 1] = "INDEXER_TX_TYPE_RECEIVED";
@@ -2855,33 +3009,6 @@ function parseAssetMetadata(metadata) {
2855
3009
  }
2856
3010
  return out;
2857
3011
  }
2858
- function convertVtxo(vtxo) {
2859
- return {
2860
- txid: vtxo.outpoint.txid,
2861
- vout: vtxo.outpoint.vout,
2862
- value: Number(vtxo.amount),
2863
- status: {
2864
- confirmed: !vtxo.isSwept && !vtxo.isPreconfirmed,
2865
- isLeaf: !vtxo.isPreconfirmed
2866
- },
2867
- virtualStatus: {
2868
- state: vtxo.isSpent ? "spent" : vtxo.isSwept ? "swept" : vtxo.isPreconfirmed ? "preconfirmed" : "settled",
2869
- commitmentTxIds: vtxo.commitmentTxids,
2870
- batchExpiry: vtxo.expiresAt ? Number(vtxo.expiresAt) * 1e3 : void 0
2871
- },
2872
- spentBy: vtxo.spentBy ?? "",
2873
- settledBy: vtxo.settledBy,
2874
- arkTxId: vtxo.arkTxid,
2875
- createdAt: new Date(Number(vtxo.createdAt) * 1e3),
2876
- isUnrolled: vtxo.isUnrolled,
2877
- isSpent: vtxo.isSpent,
2878
- script: vtxo.script,
2879
- assets: vtxo.assets?.map((a) => ({
2880
- assetId: a.assetId,
2881
- amount: BigInt(a.amount)
2882
- }))
2883
- };
2884
- }
2885
3012
  var Response;
2886
3013
  ((Response2) => {
2887
3014
  function isBatchInfo(data) {
@@ -2974,6 +3101,6 @@ var Response;
2974
3101
  Response2.isGetAssetResponse = isGetAssetResponse;
2975
3102
  })(Response || (Response = {}));
2976
3103
 
2977
- export { ArkError, ArkErrorName, ArkPsbtFieldKey, ArkPsbtFieldKeyType, AssetGroup, AssetId, AssetInput, AssetOutput, AssetRef, BufferReader, BufferWriter, ChainTxType, ConditionWitness, CosignerPublicKey, DigestMismatchError, FetchError, IndexerTxType, Intent, Metadata, OP_RETURN_EMPTY_PKSCRIPT, Packet, PrevArkTxField, PrevoutTxField, ProviderUnavailableError, RestArkProvider, RestIndexerProvider, SettlementEventType, Transaction, VtxoTaprootTree, VtxoTreeExpiry, asset_exports, baseFetch, buildVersion, craftToSpendTx, fetch, getArkPsbtFields, isArkError, isEventSourceError, isFetchTimeoutError, maybeArkError, sdkVersion, setArkPsbtField };
2978
- //# sourceMappingURL=chunk-CDDWXBEM.js.map
2979
- //# sourceMappingURL=chunk-CDDWXBEM.js.map
3104
+ export { ArkError, ArkErrorName, ArkPsbtFieldKey, ArkPsbtFieldKeyType, AssetGroup, AssetId, AssetInput, AssetOutput, AssetRef, BufferReader, BufferWriter, ChainTxType, ConditionWitness, CosignerPublicKey, DigestMismatchError, FetchError, IndexerTxType, Intent, Metadata, OP_RETURN_EMPTY_PKSCRIPT, Packet, PrevArkTxField, PrevoutTxField, ProviderUnavailableError, RestArkProvider, RestIndexerProvider, SettlementEventType, Transaction, VtxoTaprootTree, VtxoTreeExpiry, asset_exports, baseFetch, buildVersion, craftToSpendTx, fetch, getArkPsbtFields, isArkError, isEventSourceError, isFetchTimeoutError, maybeArkError, rateGate, sdkVersion, setArkPsbtField };
3105
+ //# sourceMappingURL=chunk-BHHLRZCS.js.map
3106
+ //# sourceMappingURL=chunk-BHHLRZCS.js.map