@arkade-os/sdk 0.5.0-rc.8 → 0.5.0

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 (94) hide show
  1. package/README.md +231 -50
  2. package/dist/adapters/expo.cjs +5 -5
  3. package/dist/adapters/expo.d.cts +5 -5
  4. package/dist/adapters/expo.d.ts +5 -5
  5. package/dist/adapters/expo.js +3 -3
  6. package/dist/{asyncStorageTaskQueue-CeYTmuGU.d.ts → asyncStorageTaskQueue-BFv2O1y1.d.ts} +1 -1
  7. package/dist/{asyncStorageTaskQueue-Bn3FoNkc.d.cts → asyncStorageTaskQueue-qRRQUOE8.d.cts} +1 -1
  8. package/dist/{chunk-ZTCDT7KB.cjs → chunk-AU77RYOC.cjs} +6304 -4613
  9. package/dist/chunk-AU77RYOC.cjs.map +1 -0
  10. package/dist/{chunk-K5RED5VE.cjs → chunk-GN2K4WBP.cjs} +494 -1122
  11. package/dist/chunk-GN2K4WBP.cjs.map +1 -0
  12. package/dist/{chunk-BMPGUGYZ.cjs → chunk-GOM26K6H.cjs} +12 -10
  13. package/dist/chunk-GOM26K6H.cjs.map +1 -0
  14. package/dist/{chunk-LN4ZJZK4.js → chunk-GWJWXVUB.js} +5906 -4235
  15. package/dist/chunk-GWJWXVUB.js.map +1 -0
  16. package/dist/{chunk-G6S4XSFI.js → chunk-HABGVRLF.js} +112 -243
  17. package/dist/chunk-HABGVRLF.js.map +1 -0
  18. package/dist/{chunk-2AWDPVZI.cjs → chunk-IQWLFYT2.cjs} +124 -254
  19. package/dist/chunk-IQWLFYT2.cjs.map +1 -0
  20. package/dist/{chunk-56RCBKNF.cjs → chunk-JT5YVMCJ.cjs} +39 -46
  21. package/dist/chunk-JT5YVMCJ.cjs.map +1 -0
  22. package/dist/{chunk-INTEA7D3.js → chunk-K2E6X6JT.js} +32 -39
  23. package/dist/chunk-K2E6X6JT.js.map +1 -0
  24. package/dist/{chunk-XCNAGBFR.js → chunk-K352GMVL.js} +427 -1078
  25. package/dist/chunk-K352GMVL.js.map +1 -0
  26. package/dist/{chunk-BIRUBLP3.js → chunk-TZSKLERU.js} +7 -5
  27. package/dist/chunk-TZSKLERU.js.map +1 -0
  28. package/dist/{chunk-NY5FN4VV.cjs → chunk-UUSKJOSX.cjs} +548 -399
  29. package/dist/chunk-UUSKJOSX.cjs.map +1 -0
  30. package/dist/{chunk-MTYQXZ2T.js → chunk-ZOEB53NQ.js} +541 -400
  31. package/dist/chunk-ZOEB53NQ.js.map +1 -0
  32. package/dist/contracts/handlers/index.cjs +9 -9
  33. package/dist/contracts/handlers/index.d.cts +5 -5
  34. package/dist/contracts/handlers/index.d.ts +5 -5
  35. package/dist/contracts/handlers/index.js +2 -2
  36. package/dist/{delegate-Cyv2suFd.d.cts → delegate-B5BmYkEY.d.cts} +1 -1
  37. package/dist/{delegate-CyBnNY9v.d.ts → delegate-DNbiUgy8.d.ts} +1 -1
  38. package/dist/index-B4QuO9sH.d.cts +645 -0
  39. package/dist/index-CYeyT3kn.d.ts +645 -0
  40. package/dist/{index-BIL9boGL.d.cts → index-CZw-MMfY.d.cts} +1644 -2291
  41. package/dist/{index-BIL9boGL.d.ts → index-CZw-MMfY.d.ts} +1644 -2291
  42. package/dist/index.cjs +399 -311
  43. package/dist/index.d.cts +953 -1124
  44. package/dist/index.d.ts +953 -1124
  45. package/dist/index.js +4 -4
  46. package/dist/repositories/realm/index.cjs +165 -103
  47. package/dist/repositories/realm/index.cjs.map +1 -1
  48. package/dist/repositories/realm/index.d.cts +18 -14
  49. package/dist/repositories/realm/index.d.ts +18 -14
  50. package/dist/repositories/realm/index.js +153 -91
  51. package/dist/repositories/realm/index.js.map +1 -1
  52. package/dist/repositories/sqlite/index.cjs +226 -184
  53. package/dist/repositories/sqlite/index.cjs.map +1 -1
  54. package/dist/repositories/sqlite/index.d.cts +22 -21
  55. package/dist/repositories/sqlite/index.d.ts +22 -21
  56. package/dist/repositories/sqlite/index.js +218 -176
  57. package/dist/repositories/sqlite/index.js.map +1 -1
  58. package/dist/{taskRunner-z_BGID85.d.cts → taskRunner-B3SLvUfL.d.cts} +1 -1
  59. package/dist/{taskRunner-CRbuzUXR.d.ts → taskRunner-wm1bhmtP.d.ts} +1 -1
  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 +10 -16
  63. package/dist/wallet/expo/background.d.ts +10 -16
  64. package/dist/wallet/expo/background.js +6 -6
  65. package/dist/wallet/expo/background.js.map +1 -1
  66. package/dist/wallet/expo/index.cjs +19 -14
  67. package/dist/wallet/expo/index.cjs.map +1 -1
  68. package/dist/wallet/expo/index.d.cts +8 -6
  69. package/dist/wallet/expo/index.d.ts +8 -6
  70. package/dist/wallet/expo/index.js +10 -5
  71. package/dist/wallet/expo/index.js.map +1 -1
  72. package/dist/wallet-DCZ2-Bea.d.cts +1874 -0
  73. package/dist/wallet-DGLXuwXT.d.ts +1874 -0
  74. package/dist/worker/expo/index.cjs +9 -9
  75. package/dist/worker/expo/index.d.cts +6 -6
  76. package/dist/worker/expo/index.d.ts +6 -6
  77. package/dist/worker/expo/index.js +5 -5
  78. package/package.json +10 -11
  79. package/dist/chunk-2AWDPVZI.cjs.map +0 -1
  80. package/dist/chunk-56RCBKNF.cjs.map +0 -1
  81. package/dist/chunk-BIRUBLP3.js.map +0 -1
  82. package/dist/chunk-BMPGUGYZ.cjs.map +0 -1
  83. package/dist/chunk-G6S4XSFI.js.map +0 -1
  84. package/dist/chunk-INTEA7D3.js.map +0 -1
  85. package/dist/chunk-K5RED5VE.cjs.map +0 -1
  86. package/dist/chunk-LN4ZJZK4.js.map +0 -1
  87. package/dist/chunk-MTYQXZ2T.js.map +0 -1
  88. package/dist/chunk-NY5FN4VV.cjs.map +0 -1
  89. package/dist/chunk-XCNAGBFR.js.map +0 -1
  90. package/dist/chunk-ZTCDT7KB.cjs.map +0 -1
  91. package/dist/hdWalletCapable-D1ImQqlu.d.cts +0 -2214
  92. package/dist/hdWalletCapable-DvumVrKW.d.ts +0 -2214
  93. package/dist/index-DleNQcz5.d.cts +0 -850
  94. package/dist/index-QVhQgYvU.d.ts +0 -850
@@ -1,9 +1,10 @@
1
- import { ScriptNum, OP, p2tr_ms, Script, SigHash, p2tr, TAPROOT_UNSPENDABLE_KEY, Address, RawWitness, Transaction as Transaction$1 } from '@scure/btc-signer';
2
- import * as bip68 from 'bip68';
3
- import { TEST_NETWORK, NETWORK } from '@scure/btc-signer/utils.js';
1
+ import { TEST_NETWORK, NETWORK, concatBytes } from '@scure/btc-signer/utils.js';
4
2
  import { hex, bech32m } from '@scure/base';
5
- import { Script as Script$1 } from '@scure/btc-signer/script.js';
3
+ import { VarBytes, Script as Script$1 } from '@scure/btc-signer/script.js';
4
+ import * as bip68 from 'bip68';
5
+ import { ScriptNum, OP, p2tr_ms, Script, SigHash, p2tr, taprootNumsKey, Address, RawWitness, Transaction as Transaction$1, RawTx } from '@scure/btc-signer';
6
6
  import { TAP_LEAF_VERSION } from '@scure/btc-signer/payment.js';
7
+ import * as P from 'micro-packed';
7
8
  import { PSBTOutput } from '@scure/btc-signer/psbt.js';
8
9
  import { schnorr } from '@noble/curves/secp256k1.js';
9
10
 
@@ -12,185 +13,6 @@ var __export = (target, all) => {
12
13
  for (var name in all)
13
14
  __defProp(target, name, { get: all[name], enumerable: true });
14
15
  };
15
- var Transaction = class extends Transaction$1 {
16
- static ARK_TX_OPTS = {
17
- allowUnknown: true,
18
- allowUnknownOutputs: true,
19
- allowUnknownInputs: true
20
- };
21
- constructor(opts) {
22
- super(withArkOpts(opts));
23
- }
24
- static fromPSBT(psbt_, opts) {
25
- return Transaction$1.fromPSBT(psbt_, withArkOpts(opts));
26
- }
27
- static fromRaw(raw, opts) {
28
- return Transaction$1.fromRaw(raw, withArkOpts(opts));
29
- }
30
- };
31
- function withArkOpts(opts) {
32
- return { ...Transaction.ARK_TX_OPTS, ...opts };
33
- }
34
- function formatSighash(type) {
35
- return `0x${type.toString(16).padStart(2, "0")}`;
36
- }
37
- function assertAllowedSighashTypes(tx, allowedSighashTypes = [SigHash.DEFAULT]) {
38
- for (let i = 0; i < tx.inputsLength; i++) {
39
- const declared = tx.getInput(i).sighashType;
40
- if (declared === void 0) continue;
41
- if (!allowedSighashTypes.includes(declared)) {
42
- throw new Error(`Unallowed sighash type ${formatSighash(declared)} for input ${i}.`);
43
- }
44
- }
45
- }
46
- function timelockToSequence(timelock) {
47
- return bip68.encode(
48
- timelock.type === "blocks" ? { blocks: Number(timelock.value) } : { seconds: Number(timelock.value) }
49
- );
50
- }
51
- function sequenceToTimelock(sequence) {
52
- const decoded = bip68.decode(sequence);
53
- if ("blocks" in decoded && decoded.blocks !== void 0) {
54
- return { type: "blocks", value: BigInt(decoded.blocks) };
55
- }
56
- if ("seconds" in decoded && decoded.seconds !== void 0) {
57
- return { type: "seconds", value: BigInt(decoded.seconds) };
58
- }
59
- throw new Error(`Invalid BIP68 sequence: ${sequence}`);
60
- }
61
- var ArkPsbtFieldKey = /* @__PURE__ */ ((ArkPsbtFieldKey2) => {
62
- ArkPsbtFieldKey2["VtxoTaprootTree"] = "taptree";
63
- ArkPsbtFieldKey2["VtxoTreeExpiry"] = "expiry";
64
- ArkPsbtFieldKey2["Cosigner"] = "cosigner";
65
- ArkPsbtFieldKey2["ConditionWitness"] = "condition";
66
- ArkPsbtFieldKey2["PrevArkTx"] = "prevarktx";
67
- ArkPsbtFieldKey2["PrevoutTx"] = "prevouttx";
68
- return ArkPsbtFieldKey2;
69
- })(ArkPsbtFieldKey || {});
70
- var ArkPsbtFieldKeyType = 222;
71
- function setArkPsbtField(tx, inputIndex, coder, value) {
72
- tx.updateInput(inputIndex, {
73
- unknown: [...tx.getInput(inputIndex)?.unknown ?? [], coder.encode(value)]
74
- });
75
- }
76
- function getArkPsbtFields(tx, inputIndex, coder) {
77
- const unknown = tx.getInput(inputIndex)?.unknown ?? [];
78
- const fields = [];
79
- for (const u of unknown) {
80
- const v = coder.decode(u);
81
- if (v !== null) fields.push(v);
82
- }
83
- return fields;
84
- }
85
- var VtxoTaprootTree = {
86
- key: "taptree" /* VtxoTaprootTree */,
87
- encode: (value) => [
88
- {
89
- type: ArkPsbtFieldKeyType,
90
- key: encodedPsbtFieldKey["taptree" /* VtxoTaprootTree */]
91
- },
92
- value
93
- ],
94
- decode: (value) => nullIfCatch(() => {
95
- if (!checkKeyMatch(value[0], "taptree" /* VtxoTaprootTree */)) return null;
96
- return value[1];
97
- })
98
- };
99
- var ConditionWitness = {
100
- key: "condition" /* ConditionWitness */,
101
- encode: (value) => [
102
- {
103
- type: ArkPsbtFieldKeyType,
104
- key: encodedPsbtFieldKey["condition" /* ConditionWitness */]
105
- },
106
- RawWitness.encode(value)
107
- ],
108
- decode: (value) => nullIfCatch(() => {
109
- if (!checkKeyMatch(value[0], "condition" /* ConditionWitness */)) return null;
110
- return RawWitness.decode(value[1]);
111
- })
112
- };
113
- var PrevArkTxField = {
114
- key: "prevarktx" /* PrevArkTx */,
115
- encode: (value) => [
116
- {
117
- type: ArkPsbtFieldKeyType,
118
- key: encodedPsbtFieldKey["prevarktx" /* PrevArkTx */]
119
- },
120
- value
121
- ],
122
- decode: (value) => nullIfCatch(() => {
123
- if (!checkKeyMatch(value[0], "prevarktx" /* PrevArkTx */)) return null;
124
- return value[1];
125
- })
126
- };
127
- var PrevoutTxField = {
128
- key: "prevouttx" /* PrevoutTx */,
129
- encode: (value) => [
130
- {
131
- type: ArkPsbtFieldKeyType,
132
- key: encodedPsbtFieldKey["prevouttx" /* PrevoutTx */]
133
- },
134
- value
135
- ],
136
- decode: (value) => nullIfCatch(() => {
137
- if (!checkKeyMatch(value[0], "prevouttx" /* PrevoutTx */)) return null;
138
- return value[1];
139
- })
140
- };
141
- var CosignerPublicKey = {
142
- key: "cosigner" /* Cosigner */,
143
- encode: (value) => [
144
- {
145
- type: ArkPsbtFieldKeyType,
146
- key: new Uint8Array([...encodedPsbtFieldKey["cosigner" /* Cosigner */], value.index])
147
- },
148
- value.key
149
- ],
150
- decode: (unknown) => nullIfCatch(() => {
151
- if (!checkKeyMatch(unknown[0], "cosigner" /* Cosigner */, true)) return null;
152
- return {
153
- index: unknown[0].key[unknown[0].key.length - 1],
154
- key: unknown[1]
155
- };
156
- })
157
- };
158
- var VtxoTreeExpiry = {
159
- key: "expiry" /* VtxoTreeExpiry */,
160
- encode: (value) => [
161
- {
162
- type: ArkPsbtFieldKeyType,
163
- key: encodedPsbtFieldKey["expiry" /* VtxoTreeExpiry */]
164
- },
165
- ScriptNum(6, true).encode(value.value === 0n ? 0n : value.value)
166
- ],
167
- decode: (unknown) => nullIfCatch(() => {
168
- if (!checkKeyMatch(unknown[0], "expiry" /* VtxoTreeExpiry */)) return null;
169
- const v = ScriptNum(6, true).decode(unknown[1]);
170
- if (!v) return null;
171
- return sequenceToTimelock(Number(v));
172
- })
173
- };
174
- var encodedPsbtFieldKey = Object.fromEntries(
175
- Object.values(ArkPsbtFieldKey).map((key) => [key, new TextEncoder().encode(key)])
176
- );
177
- var nullIfCatch = (fn) => {
178
- try {
179
- return fn();
180
- } catch {
181
- return null;
182
- }
183
- };
184
- function checkKeyMatch(key, arkPsbtFieldKey, prefixOnly = false) {
185
- if (key.type !== ArkPsbtFieldKeyType) return false;
186
- const expected = encodedPsbtFieldKey[arkPsbtFieldKey];
187
- if (key.key.length < expected.length) return false;
188
- if (!prefixOnly && key.key.length !== expected.length) return false;
189
- for (let i = 0; i < expected.length; i++) {
190
- if (key.key[i] !== expected[i]) return false;
191
- }
192
- return true;
193
- }
194
16
  var getNetwork = (network) => {
195
17
  const found = networks[network];
196
18
  if (!found) throw new Error(`Unsupported network: ${network}`);
@@ -221,6 +43,7 @@ function withArkPrefix(network, prefix, name) {
221
43
  };
222
44
  }
223
45
  var DEFAULT_ARKADE_SERVER_URL = "https://arkade.computer";
46
+ var DEFAULT_ARKADE_EMULATOR_URL = "https://emulator.arkade.computer";
224
47
  var DEFAULT_NETWORK = networks.bitcoin;
225
48
  var DEFAULT_NETWORK_NAME = "bitcoin";
226
49
  var COMPRESSED_PUBKEY = /^0[23][0-9a-f]{64}$/;
@@ -327,6 +150,26 @@ var ArkAddress = class _ArkAddress {
327
150
  return Script$1.encode(["RETURN", this.vtxoTaprootKey]);
328
151
  }
329
152
  };
153
+ function timelockToSequence(timelock) {
154
+ return bip68.encode(
155
+ timelock.type === "blocks" ? { blocks: Number(timelock.value) } : { seconds: Number(timelock.value) }
156
+ );
157
+ }
158
+ function sequenceToTimelock(sequence) {
159
+ const decoded = bip68.decode(sequence);
160
+ if ("blocks" in decoded && decoded.blocks !== void 0) {
161
+ return { type: "blocks", value: BigInt(decoded.blocks) };
162
+ }
163
+ if ("seconds" in decoded && decoded.seconds !== void 0) {
164
+ return { type: "seconds", value: BigInt(decoded.seconds) };
165
+ }
166
+ throw new Error(`Invalid BIP68 sequence: ${sequence}`);
167
+ }
168
+ function sequenceToCanonicalTimelock(sequence) {
169
+ if (sequence < 0n || sequence >= 0x80000000n) return void 0;
170
+ const timelock = sequenceToTimelock(Number(sequence));
171
+ return BigInt(timelockToSequence(timelock)) === sequence ? timelock : void 0;
172
+ }
330
173
  var MinimalScriptNum = ScriptNum(void 0, true);
331
174
  function decodeTapscript(script) {
332
175
  const types = [
@@ -574,6 +417,16 @@ var CSVMultisigTapscript;
574
417
  }
575
418
  CSVMultisigTapscript2.isScriptValid = isScriptValid;
576
419
  })(CSVMultisigTapscript || (CSVMultisigTapscript = {}));
420
+ function isConditionScriptValid(script) {
421
+ const asm = Script.decode(script);
422
+ if (asm.length < 1) {
423
+ return new Error(`Invalid script: too short (expected at least 1)`);
424
+ }
425
+ if (asm.lastIndexOf("VERIFY") === -1) {
426
+ return new Error("Invalid script: missing VERIFY operation");
427
+ }
428
+ return true;
429
+ }
577
430
  var ConditionCSVMultisigTapscript;
578
431
  ((ConditionCSVMultisigTapscript2) => {
579
432
  function encode2(params) {
@@ -598,7 +451,7 @@ var ConditionCSVMultisigTapscript;
598
451
  throw isValid;
599
452
  }
600
453
  const asm = Script.decode(script);
601
- let verifyIndex = getVerifyIndex(asm);
454
+ const verifyIndex = asm.lastIndexOf("VERIFY");
602
455
  if (verifyIndex === -1) {
603
456
  throw Error("Invalid script: missing VERIFY operation");
604
457
  }
@@ -633,26 +486,8 @@ var ConditionCSVMultisigTapscript;
633
486
  return tapscript.type === "condition-csv-multisig" /* ConditionCSVMultisig */;
634
487
  }
635
488
  ConditionCSVMultisigTapscript2.is = is;
636
- function getVerifyIndex(asm) {
637
- let verifyIndex = -1;
638
- for (let i = asm.length - 1; i >= 0; i--) {
639
- if (asm[i] === "VERIFY") {
640
- verifyIndex = i;
641
- return verifyIndex;
642
- }
643
- }
644
- return verifyIndex;
645
- }
646
489
  function isScriptValid(script) {
647
- const asm = Script.decode(script);
648
- if (asm.length < 1) {
649
- return new Error(`Invalid script: too short (expected at least 1)`);
650
- }
651
- let verifyIndex = getVerifyIndex(asm);
652
- if (verifyIndex === -1) {
653
- return new Error("Invalid script: missing VERIFY operation");
654
- }
655
- return true;
490
+ return isConditionScriptValid(script);
656
491
  }
657
492
  ConditionCSVMultisigTapscript2.isScriptValid = isScriptValid;
658
493
  })(ConditionCSVMultisigTapscript || (ConditionCSVMultisigTapscript = {}));
@@ -680,7 +515,7 @@ var ConditionMultisigTapscript;
680
515
  throw isValid;
681
516
  }
682
517
  const asm = Script.decode(script);
683
- let verifyIndex = getVerifyIndex(asm);
518
+ const verifyIndex = asm.lastIndexOf("VERIFY");
684
519
  if (verifyIndex === -1) {
685
520
  throw Error("Invalid script: missing VERIFY operation");
686
521
  }
@@ -715,26 +550,8 @@ var ConditionMultisigTapscript;
715
550
  return tapscript.type === "condition-multisig" /* ConditionMultisig */;
716
551
  }
717
552
  ConditionMultisigTapscript2.is = is;
718
- function getVerifyIndex(asm) {
719
- let verifyIndex = -1;
720
- for (let i = asm.length - 1; i >= 0; i--) {
721
- if (asm[i] === "VERIFY") {
722
- verifyIndex = i;
723
- return verifyIndex;
724
- }
725
- }
726
- return verifyIndex;
727
- }
728
553
  function isScriptValid(script) {
729
- const asm = Script.decode(script);
730
- if (asm.length < 1) {
731
- return new Error(`Invalid script: too short (expected at least 1)`);
732
- }
733
- let verifyIndex = getVerifyIndex(asm);
734
- if (verifyIndex === -1) {
735
- return new Error("Invalid script: missing VERIFY operation");
736
- }
737
- return true;
554
+ return isConditionScriptValid(script);
738
555
  }
739
556
  ConditionMultisigTapscript2.isScriptValid = isScriptValid;
740
557
  })(ConditionMultisigTapscript || (ConditionMultisigTapscript = {}));
@@ -859,7 +676,25 @@ function assembleBtcdTaprootTree(scripts) {
859
676
  }
860
677
  return branches[0];
861
678
  }
862
- var TapTreeCoder = PSBTOutput.tapTree[2];
679
+ function btcdLeafLayout(count) {
680
+ const placeholders = Array.from({ length: count }, () => new Uint8Array());
681
+ const indexOf = new Map(placeholders.map((script, index) => [script, index]));
682
+ const layout = [];
683
+ const walk = (node, depth) => {
684
+ if (Array.isArray(node)) {
685
+ walk(node[0], depth + 1);
686
+ walk(node[1], depth + 1);
687
+ } else {
688
+ layout.push({ index: indexOf.get(node.script), depth });
689
+ }
690
+ };
691
+ walk(assembleBtcdTaprootTree(placeholders), 0);
692
+ return layout;
693
+ }
694
+ var TapTreeCoder = P.array(
695
+ null,
696
+ P.struct({ depth: P.U8, version: P.U8, script: VarBytes })
697
+ );
863
698
  function scriptFromTapLeafScript(leaf) {
864
699
  return leaf[1].subarray(0, leaf[1].length - 1);
865
700
  }
@@ -879,7 +714,7 @@ var VtxoScript = class _VtxoScript {
879
714
  constructor(scripts) {
880
715
  this.scripts = scripts;
881
716
  const tapTree = assembleBtcdTaprootTree(scripts);
882
- const payment = p2tr(TAPROOT_UNSPENDABLE_KEY, tapTree, void 0, true);
717
+ const payment = p2tr(taprootNumsKey(), tapTree, void 0, true);
883
718
  if (!payment.tapLeafScript || payment.tapLeafScript.length !== scripts.length) {
884
719
  throw new Error("invalid scripts");
885
720
  }
@@ -894,15 +729,46 @@ var VtxoScript = class _VtxoScript {
894
729
  /**
895
730
  * Decode a virtual output script from an encoded TapTree.
896
731
  *
732
+ * Leaves are normally read in construction order and their depths
733
+ * ignored: that covers the {@link encode} form (every depth 1) and the
734
+ * placeholder depths other writers use, such as arkd's. The exception is
735
+ * the BIP-371 form {@link toBIP371TapTree} writes, whose leaves are in the
736
+ * tree's DFS order: for some leaf counts (6, 7, 10, ...) that differs from
737
+ * construction order. A tree whose depths are exactly the shape
738
+ * `assembleBtcdTaprootTree` builds is that form, so its leaves are mapped
739
+ * back to construction order first. No construction-order writer produces
740
+ * that depth sequence when the two orders differ, so this never reorders
741
+ * a tree that decoded correctly before.
742
+ *
743
+ * Every leaf must carry the base tapscript version: the tree is rebuilt
744
+ * with {@link TAP_LEAF_VERSION} leaves, so any other version would
745
+ * silently derive a different taproot key.
746
+ *
897
747
  * @param tapTree - Encoded TapTree bytes
898
748
  * @returns Decoded virtual output script
899
749
  * @throws Error if the TapTree cannot be decoded into a valid script set
750
+ * or a leaf carries a version other than {@link TAP_LEAF_VERSION}
900
751
  * @see encode
901
752
  */
902
753
  static decode(tapTree) {
903
754
  const leaves = TapTreeCoder.decode(tapTree);
755
+ const foreign = leaves.find((leaf) => leaf.version !== TAP_LEAF_VERSION);
756
+ if (foreign) {
757
+ throw new Error(`unsupported tap leaf version 0x${foreign.version.toString(16)}`);
758
+ }
904
759
  const scripts = leaves.map((leaf) => leaf.script);
905
- return new _VtxoScript(scripts);
760
+ if (leaves.every((leaf) => leaf.depth === 1)) {
761
+ return new _VtxoScript(scripts);
762
+ }
763
+ const layout = btcdLeafLayout(leaves.length);
764
+ if (layout.some((slot, i) => slot.depth !== leaves[i].depth)) {
765
+ return new _VtxoScript(scripts);
766
+ }
767
+ const ordered = new Array(leaves.length);
768
+ layout.forEach((slot, i) => {
769
+ ordered[slot.index] = scripts[i];
770
+ });
771
+ return new _VtxoScript(ordered);
906
772
  }
907
773
  /**
908
774
  * Encode the virtual output script to a TapTree byte representation.
@@ -985,21 +851,323 @@ var VtxoScript = class _VtxoScript {
985
851
  return paths;
986
852
  }
987
853
  };
988
- function getSequence(tapLeafScript) {
989
- let sequence = void 0;
854
+ function toBIP371TapTree(tapTree) {
855
+ const scripts = TapTreeCoder.decode(tapTree).map((leaf) => leaf.script);
856
+ const vtxoScript = new VtxoScript(scripts);
857
+ return vtxoScript.leaves.map((leaf) => ({
858
+ depth: leaf[0].merklePath.length,
859
+ version: TAP_LEAF_VERSION,
860
+ script: scriptFromTapLeafScript(leaf)
861
+ }));
862
+ }
863
+ function getSequence(tapLeafScript) {
864
+ let sequence = void 0;
865
+ try {
866
+ const scriptWithLeafVersion = tapLeafScript[1];
867
+ const script = scriptWithLeafVersion.subarray(0, scriptWithLeafVersion.length - 1);
868
+ try {
869
+ const params = CSVMultisigTapscript.decode(script).params;
870
+ sequence = timelockToSequence(params.timelock);
871
+ } catch {
872
+ const params = CLTVMultisigTapscript.decode(script).params;
873
+ sequence = Number(params.absoluteTimelock);
874
+ }
875
+ } catch {
876
+ }
877
+ return sequence;
878
+ }
879
+ var Transaction = class extends Transaction$1 {
880
+ static ARK_TX_OPTS = {
881
+ unknown: "ignore",
882
+ allowUnknownOutputs: true,
883
+ allowUnknownInputs: true
884
+ };
885
+ constructor(opts) {
886
+ super(withArkOpts(opts));
887
+ }
888
+ /**
889
+ * Decode a PSBT. PSBTs carrying a legacy `PSBT_OUT_TAP_TREE` (see
890
+ * {@link repairLegacyOutputTapTrees}) are repaired and decoded again
891
+ * instead of being rejected.
892
+ */
893
+ static fromPSBT(psbt_, opts) {
894
+ try {
895
+ return Transaction$1.fromPSBT(psbt_, withArkOpts(opts));
896
+ } catch (err) {
897
+ const repaired = repairLegacyOutputTapTrees(psbt_);
898
+ if (!repaired) throw err;
899
+ return Transaction$1.fromPSBT(repaired, withArkOpts(opts));
900
+ }
901
+ }
902
+ static fromRaw(raw, opts) {
903
+ return Transaction$1.fromRaw(raw, withArkOpts(opts));
904
+ }
905
+ };
906
+ function withArkOpts(opts) {
907
+ return { ...Transaction.ARK_TX_OPTS, ...opts };
908
+ }
909
+ var PSBT_MAGIC = new Uint8Array([112, 115, 98, 116, 255]);
910
+ var PSBT_GLOBAL_UNSIGNED_TX = 0;
911
+ var PSBT_GLOBAL_INPUT_COUNT = 4;
912
+ var PSBT_OUT_TAP_TREE = 6;
913
+ function repairLegacyOutputTapTrees(psbt) {
914
+ let maps;
915
+ let inputsCount;
916
+ try {
917
+ maps = readPsbtMaps(psbt);
918
+ inputsCount = psbtInputsCount(maps[0]);
919
+ } catch {
920
+ return void 0;
921
+ }
922
+ let repaired = false;
923
+ for (const output of maps.slice(1 + inputsCount)) {
924
+ for (const kv of output) {
925
+ if (kv.key.length !== 1 || kv.key[0] !== PSBT_OUT_TAP_TREE) continue;
926
+ const value = legacyTapTreeToBIP371(kv.value);
927
+ if (!value) continue;
928
+ kv.value = value;
929
+ repaired = true;
930
+ }
931
+ }
932
+ return repaired ? writePsbtMaps(maps) : void 0;
933
+ }
934
+ function legacyTapTreeToBIP371(value) {
935
+ try {
936
+ PSBTOutput.tapTree[2].decode(value);
937
+ return void 0;
938
+ } catch {
939
+ }
940
+ let leaves;
941
+ try {
942
+ leaves = TapTreeCoder.decode(value);
943
+ } catch {
944
+ return void 0;
945
+ }
946
+ if (leaves.length === 0 || leaves.some((leaf) => leaf.depth !== 1)) return void 0;
947
+ try {
948
+ return TapTreeCoder.encode(toBIP371TapTree(value));
949
+ } catch {
950
+ return void 0;
951
+ }
952
+ }
953
+ function psbtInputsCount(global) {
954
+ for (const { key, value } of global) {
955
+ if (key.length !== 1) continue;
956
+ if (key[0] === PSBT_GLOBAL_UNSIGNED_TX) return RawTx.decode(value).inputs.length;
957
+ if (key[0] === PSBT_GLOBAL_INPUT_COUNT) return readCompactSize(value, 0)[0];
958
+ }
959
+ throw new Error("PSBT: missing input count");
960
+ }
961
+ function readPsbtMaps(psbt) {
962
+ for (let i = 0; i < PSBT_MAGIC.length; i++) {
963
+ if (psbt[i] !== PSBT_MAGIC[i]) throw new Error("PSBT: invalid magic");
964
+ }
965
+ const maps = [];
966
+ let pos = PSBT_MAGIC.length;
967
+ while (pos < psbt.length) {
968
+ const map = [];
969
+ for (; ; ) {
970
+ const [keyLen, afterKeyLen] = readCompactSize(psbt, pos);
971
+ pos = afterKeyLen;
972
+ if (keyLen === 0) break;
973
+ const key = readBytes(psbt, pos, keyLen);
974
+ pos += keyLen;
975
+ const [valueLen, afterValueLen] = readCompactSize(psbt, pos);
976
+ pos = afterValueLen;
977
+ const value = readBytes(psbt, pos, valueLen);
978
+ pos += valueLen;
979
+ map.push({ key, value });
980
+ }
981
+ maps.push(map);
982
+ }
983
+ if (maps.length === 0) throw new Error("PSBT: missing global map");
984
+ return maps;
985
+ }
986
+ function writePsbtMaps(maps) {
987
+ const parts = [PSBT_MAGIC];
988
+ for (const map of maps) {
989
+ for (const { key, value } of map) {
990
+ parts.push(writeCompactSize(key.length), key, writeCompactSize(value.length), value);
991
+ }
992
+ parts.push(new Uint8Array([0]));
993
+ }
994
+ return concatBytes(...parts);
995
+ }
996
+ function readBytes(data, pos, len) {
997
+ if (pos + len > data.length) throw new Error("PSBT: unexpected end of data");
998
+ return data.slice(pos, pos + len);
999
+ }
1000
+ function readCompactSize(data, pos) {
1001
+ const first = readBytes(data, pos, 1)[0];
1002
+ if (first < 253) return [first, pos + 1];
1003
+ const width = first === 253 ? 2 : first === 254 ? 4 : 8;
1004
+ const bytes = readBytes(data, pos + 1, width);
1005
+ let value = 0;
1006
+ for (let i = width - 1; i >= 0; i--) value = value * 256 + bytes[i];
1007
+ if (!Number.isSafeInteger(value)) throw new Error("PSBT: compact size too large");
1008
+ return [value, pos + 1 + width];
1009
+ }
1010
+ function writeCompactSize(value) {
1011
+ if (value < 253) return new Uint8Array([value]);
1012
+ const width = value <= 65535 ? 2 : value <= 4294967295 ? 4 : 8;
1013
+ const out = new Uint8Array(1 + width);
1014
+ out[0] = width === 2 ? 253 : width === 4 ? 254 : 255;
1015
+ for (let i = 0, v = value; i < width; i++, v = Math.floor(v / 256)) out[1 + i] = v % 256;
1016
+ return out;
1017
+ }
1018
+ function formatSighash(type) {
1019
+ return `0x${type.toString(16).padStart(2, "0")}`;
1020
+ }
1021
+ function assertAllowedSighashTypes(tx, allowedSighashTypes = [SigHash.DEFAULT]) {
1022
+ for (let i = 0; i < tx.inputsLength; i++) {
1023
+ const declared = tx.getInput(i).sighashType;
1024
+ if (declared === void 0) continue;
1025
+ if (!allowedSighashTypes.includes(declared)) {
1026
+ throw new Error(`Unallowed sighash type ${formatSighash(declared)} for input ${i}.`);
1027
+ }
1028
+ }
1029
+ }
1030
+
1031
+ // src/utils/time.ts
1032
+ function assertNonNegativeMs(name, ms) {
1033
+ if (ms !== void 0 && (!Number.isSafeInteger(ms) || ms < 0)) {
1034
+ throw new Error(`${name} must be a non-negative safe integer`);
1035
+ }
1036
+ }
1037
+ var MAX_TIMER_MS = 2 ** 31 - 1;
1038
+ function assertTimerMs(name, ms) {
1039
+ assertNonNegativeMs(name, ms);
1040
+ if (ms !== void 0 && ms > MAX_TIMER_MS) {
1041
+ throw new Error(`${name} must not exceed ${MAX_TIMER_MS} milliseconds`);
1042
+ }
1043
+ }
1044
+ var ArkPsbtFieldKey = /* @__PURE__ */ ((ArkPsbtFieldKey2) => {
1045
+ ArkPsbtFieldKey2["VtxoTaprootTree"] = "taptree";
1046
+ ArkPsbtFieldKey2["VtxoTreeExpiry"] = "expiry";
1047
+ ArkPsbtFieldKey2["Cosigner"] = "cosigner";
1048
+ ArkPsbtFieldKey2["ConditionWitness"] = "condition";
1049
+ ArkPsbtFieldKey2["PrevArkTx"] = "prevarktx";
1050
+ ArkPsbtFieldKey2["PrevoutTx"] = "prevouttx";
1051
+ return ArkPsbtFieldKey2;
1052
+ })(ArkPsbtFieldKey || {});
1053
+ var ArkPsbtFieldKeyType = 222;
1054
+ function setArkPsbtField(tx, inputIndex, coder, value) {
1055
+ tx.updateInput(inputIndex, {
1056
+ unknown: [...tx.getInput(inputIndex)?.unknown ?? [], coder.encode(value)]
1057
+ });
1058
+ }
1059
+ function getArkPsbtFields(tx, inputIndex, coder) {
1060
+ const unknown = tx.getInput(inputIndex)?.unknown ?? [];
1061
+ return unknown.map((u) => coder.decode(u)).filter((v) => v !== null);
1062
+ }
1063
+ var VtxoTaprootTree = {
1064
+ key: "taptree" /* VtxoTaprootTree */,
1065
+ encode: (value) => [
1066
+ {
1067
+ type: ArkPsbtFieldKeyType,
1068
+ key: encodedPsbtFieldKey["taptree" /* VtxoTaprootTree */]
1069
+ },
1070
+ value
1071
+ ],
1072
+ decode: (value) => nullIfCatch(() => {
1073
+ if (!checkKeyMatch(value[0], "taptree" /* VtxoTaprootTree */)) return null;
1074
+ return value[1];
1075
+ })
1076
+ };
1077
+ var ConditionWitness = {
1078
+ key: "condition" /* ConditionWitness */,
1079
+ encode: (value) => [
1080
+ {
1081
+ type: ArkPsbtFieldKeyType,
1082
+ key: encodedPsbtFieldKey["condition" /* ConditionWitness */]
1083
+ },
1084
+ RawWitness.encode(value)
1085
+ ],
1086
+ decode: (value) => nullIfCatch(() => {
1087
+ if (!checkKeyMatch(value[0], "condition" /* ConditionWitness */)) return null;
1088
+ return RawWitness.decode(value[1]);
1089
+ })
1090
+ };
1091
+ var PrevArkTxField = {
1092
+ key: "prevarktx" /* PrevArkTx */,
1093
+ encode: (value) => [
1094
+ {
1095
+ type: ArkPsbtFieldKeyType,
1096
+ key: encodedPsbtFieldKey["prevarktx" /* PrevArkTx */]
1097
+ },
1098
+ value
1099
+ ],
1100
+ decode: (value) => nullIfCatch(() => {
1101
+ if (!checkKeyMatch(value[0], "prevarktx" /* PrevArkTx */)) return null;
1102
+ return value[1];
1103
+ })
1104
+ };
1105
+ var PrevoutTxField = {
1106
+ key: "prevouttx" /* PrevoutTx */,
1107
+ encode: (value) => [
1108
+ {
1109
+ type: ArkPsbtFieldKeyType,
1110
+ key: encodedPsbtFieldKey["prevouttx" /* PrevoutTx */]
1111
+ },
1112
+ value
1113
+ ],
1114
+ decode: (value) => nullIfCatch(() => {
1115
+ if (!checkKeyMatch(value[0], "prevouttx" /* PrevoutTx */)) return null;
1116
+ return value[1];
1117
+ })
1118
+ };
1119
+ var CosignerPublicKey = {
1120
+ key: "cosigner" /* Cosigner */,
1121
+ encode: (value) => [
1122
+ {
1123
+ type: ArkPsbtFieldKeyType,
1124
+ key: new Uint8Array([...encodedPsbtFieldKey["cosigner" /* Cosigner */], value.index])
1125
+ },
1126
+ value.key
1127
+ ],
1128
+ decode: (unknown) => nullIfCatch(() => {
1129
+ if (!checkKeyMatch(unknown[0], "cosigner" /* Cosigner */, true)) return null;
1130
+ return {
1131
+ index: unknown[0].key[unknown[0].key.length - 1],
1132
+ key: unknown[1]
1133
+ };
1134
+ })
1135
+ };
1136
+ var VtxoTreeExpiry = {
1137
+ key: "expiry" /* VtxoTreeExpiry */,
1138
+ encode: (value) => [
1139
+ {
1140
+ type: ArkPsbtFieldKeyType,
1141
+ key: encodedPsbtFieldKey["expiry" /* VtxoTreeExpiry */]
1142
+ },
1143
+ ScriptNum(6, true).encode(value.value)
1144
+ ],
1145
+ decode: (unknown) => nullIfCatch(() => {
1146
+ if (!checkKeyMatch(unknown[0], "expiry" /* VtxoTreeExpiry */)) return null;
1147
+ const v = ScriptNum(6, true).decode(unknown[1]);
1148
+ if (!v) return null;
1149
+ return sequenceToTimelock(Number(v));
1150
+ })
1151
+ };
1152
+ var encodedPsbtFieldKey = Object.fromEntries(
1153
+ Object.values(ArkPsbtFieldKey).map((key) => [key, new TextEncoder().encode(key)])
1154
+ );
1155
+ var nullIfCatch = (fn) => {
990
1156
  try {
991
- const scriptWithLeafVersion = tapLeafScript[1];
992
- const script = scriptWithLeafVersion.subarray(0, scriptWithLeafVersion.length - 1);
993
- try {
994
- const params = CSVMultisigTapscript.decode(script).params;
995
- sequence = timelockToSequence(params.timelock);
996
- } catch {
997
- const params = CLTVMultisigTapscript.decode(script).params;
998
- sequence = Number(params.absoluteTimelock);
999
- }
1157
+ return fn();
1000
1158
  } catch {
1159
+ return null;
1001
1160
  }
1002
- return sequence;
1161
+ };
1162
+ function checkKeyMatch(key, arkPsbtFieldKey, prefixOnly = false) {
1163
+ if (key.type !== ArkPsbtFieldKeyType) return false;
1164
+ const expected = encodedPsbtFieldKey[arkPsbtFieldKey];
1165
+ if (key.key.length < expected.length) return false;
1166
+ if (!prefixOnly && key.key.length !== expected.length) return false;
1167
+ for (let i = 0; i < expected.length; i++) {
1168
+ if (key.key[i] !== expected[i]) return false;
1169
+ }
1170
+ return true;
1003
1171
  }
1004
1172
 
1005
1173
  // src/providers/eventSource.ts
@@ -1027,11 +1195,15 @@ function resolveEventSource(override) {
1027
1195
  }
1028
1196
 
1029
1197
  // package.json
1030
- var version = "0.5.0-rc.8";
1198
+ var version = "0.5.0";
1031
1199
 
1032
1200
  // src/utils/fetch.ts
1033
1201
  var buildVersion = "0.9.9";
1034
1202
  var sdkVersion = `ts-sdk/${version}`;
1203
+ var ARKADE_VERSION_HEADERS = {
1204
+ "X-Build-Version": buildVersion,
1205
+ "X-SDK-VERSION": sdkVersion
1206
+ };
1035
1207
  var FetchError = class extends Error {
1036
1208
  /** The request URL that failed, when derivable from the `fetch` input. */
1037
1209
  url;
@@ -1080,27 +1252,12 @@ function baseFetch(input, init) {
1080
1252
  }
1081
1253
  function fetch(input, init) {
1082
1254
  const headers = new Headers(init?.headers);
1083
- headers.set("X-Build-Version", buildVersion);
1084
- headers.set("X-SDK-VERSION", sdkVersion);
1255
+ for (const [name, value] of Object.entries(ARKADE_VERSION_HEADERS)) headers.set(name, value);
1085
1256
  return baseFetch(input, { ...init, headers });
1086
1257
  }
1087
1258
  function describeRequest(input, init) {
1088
- let url;
1089
- if (typeof input === "string") {
1090
- url = input;
1091
- } else if (input instanceof URL) {
1092
- url = input.href;
1093
- } else {
1094
- url = input.url;
1095
- }
1096
- let method;
1097
- if (init?.method !== void 0) {
1098
- method = init.method;
1099
- } else if (input instanceof Request) {
1100
- method = input.method;
1101
- } else {
1102
- method = "GET";
1103
- }
1259
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
1260
+ const method = init?.method !== void 0 ? init.method : input instanceof Request ? input.method : "GET";
1104
1261
  return { url, method };
1105
1262
  }
1106
1263
 
@@ -1124,15 +1281,13 @@ var ArkErrorName = {
1124
1281
  INVALID_TX_FILTER: "INVALID_TX_FILTER",
1125
1282
  TX_FILTERS_LIMIT_EXCEEDED: "TX_FILTERS_LIMIT_EXCEEDED",
1126
1283
  /**
1127
- * A CLTV closure was spent before its absolute locktime matured. Raised only by
1128
- * `submitTx` (never `finalizeTx`), with metadata
1129
- * `{ locktime, current_locktime, type: "height" | "time" }`.
1130
- *
1131
- * Self-healing, so defer and retry rather than fail: the server matures a
1132
- * seconds-locktime against the **chain tip block's timestamp**, not its wall clock,
1133
- * so a spend attempted promptly at maturity is rejected until a later block lands.
1284
+ * A CLTV closure was spent before its absolute locktime matured. `submitTx` only, with
1285
+ * metadata `{ locktime, current_locktime, type: "height" | "time" }`. Self-healing, so defer
1286
+ * and retry: the server matures a seconds-locktime against the **chain tip block's
1287
+ * timestamp**, not wall clock, so a prompt spend is rejected until a later block lands.
1134
1288
  */
1135
- FORFEIT_CLOSURE_LOCKED: "FORFEIT_CLOSURE_LOCKED"
1289
+ FORFEIT_CLOSURE_LOCKED: "FORFEIT_CLOSURE_LOCKED",
1290
+ INVALID_INTENT_PROOF: "INVALID_INTENT_PROOF"
1136
1291
  };
1137
1292
  function isArkError(error, name) {
1138
1293
  return error instanceof ArkError && (name === void 0 || error.name === name);
@@ -1208,8 +1363,8 @@ var Intent;
1208
1363
  }
1209
1364
  if (ins.length == 0) throw new Error("intent proof requires at least one input");
1210
1365
  const inputs = ins.map(prepareCoinAsIntentProofInput);
1211
- if (!validateInputs(inputs)) ;
1212
- if (!validateOutputs(outputs)) ;
1366
+ validateInputs(inputs);
1367
+ validateOutputs(outputs);
1213
1368
  const toSpend = craftToSpendTx(message, inputs[0].witnessUtxo.script);
1214
1369
  return craftToSignTx(toSpend, inputs, outputs, message);
1215
1370
  }
@@ -1264,7 +1419,6 @@ var OP_RETURN_EMPTY_PKSCRIPT = new Uint8Array([OP.RETURN]);
1264
1419
  var ZERO_32 = new Uint8Array(32).fill(0);
1265
1420
  var MAX_INDEX = 4294967295;
1266
1421
  var TAG_INTENT_PROOF = "ark-intent-proof-message";
1267
- var PSBT_GLOBAL_GENERIC_SIGNED_MESSAGE = 9;
1268
1422
  function validateInput(input) {
1269
1423
  if (input.index === void 0) throw new Error("intent proof input requires index");
1270
1424
  if (input.txid === void 0) throw new Error("intent proof input requires txid");
@@ -1274,7 +1428,6 @@ function validateInput(input) {
1274
1428
  }
1275
1429
  function validateInputs(inputs) {
1276
1430
  inputs.forEach(validateInput);
1277
- return true;
1278
1431
  }
1279
1432
  function validateOutput(output) {
1280
1433
  if (output.amount === void 0) throw new Error("intent proof output requires amount");
@@ -1283,7 +1436,6 @@ function validateOutput(output) {
1283
1436
  }
1284
1437
  function validateOutputs(outputs) {
1285
1438
  outputs.forEach(validateOutput);
1286
- return true;
1287
1439
  }
1288
1440
  function craftToSpendTx(message, pkScript, tag = TAG_INTENT_PROOF) {
1289
1441
  const messageHash = hashMessage(message, tag);
@@ -1311,8 +1463,9 @@ function craftToSignTx(toSpend, inputs, outputs, message) {
1311
1463
  version: 2,
1312
1464
  lockTime: 0
1313
1465
  });
1466
+ const { unknown: _, ...toSpendInput } = firstInput;
1314
1467
  tx.addInput({
1315
- ...firstInput,
1468
+ ...toSpendInput,
1316
1469
  txid: toSpend.id,
1317
1470
  index: 0,
1318
1471
  witnessUtxo: {
@@ -1346,14 +1499,7 @@ function craftToSignTx(toSpend, inputs, outputs, message) {
1346
1499
  script: output.script
1347
1500
  });
1348
1501
  }
1349
- const global = tx.global;
1350
- global.unknown = [
1351
- ...global.unknown ?? [],
1352
- [
1353
- { type: PSBT_GLOBAL_GENERIC_SIGNED_MESSAGE, key: new Uint8Array() },
1354
- new TextEncoder().encode(message)
1355
- ]
1356
- ];
1502
+ tx.global.genericSignedMessage = new TextEncoder().encode(message);
1357
1503
  return tx;
1358
1504
  }
1359
1505
  function hashMessage(message, tag = TAG_INTENT_PROOF) {
@@ -1403,6 +1549,7 @@ function eventSourceIterator(eventSource) {
1403
1549
  cleanedUp = true;
1404
1550
  eventSource.removeEventListener("message", messageHandler);
1405
1551
  eventSource.removeEventListener("error", errorHandler);
1552
+ eventSource.removeEventListener("failure", failureHandler);
1406
1553
  };
1407
1554
  const close = () => {
1408
1555
  if (closed) return;
@@ -1429,10 +1576,8 @@ function eventSourceIterator(eventSource) {
1429
1576
  messageQueue.push(event);
1430
1577
  }
1431
1578
  };
1432
- const errorHandler = () => {
1579
+ const rejectWith = (error) => {
1433
1580
  if (closed) return;
1434
- const error = new Error("EventSource error");
1435
- error.name = "EventSourceError";
1436
1581
  if (errorResolve) {
1437
1582
  const reject = errorResolve;
1438
1583
  messageResolve = null;
@@ -1442,8 +1587,11 @@ function eventSourceIterator(eventSource) {
1442
1587
  errorQueue.push(error);
1443
1588
  }
1444
1589
  };
1590
+ const errorHandler = () => rejectWith(eventSourceError("EventSource error"));
1591
+ const failureHandler = (event) => rejectWith(streamFailureError(event.data));
1445
1592
  eventSource.addEventListener("message", messageHandler);
1446
1593
  eventSource.addEventListener("error", errorHandler);
1594
+ eventSource.addEventListener("failure", failureHandler);
1447
1595
  const gen = (async function* () {
1448
1596
  try {
1449
1597
  while (!closed) {
@@ -1481,6 +1629,20 @@ function eventSourceIterator(eventSource) {
1481
1629
  };
1482
1630
  return managed;
1483
1631
  }
1632
+ function eventSourceError(message) {
1633
+ const error = new Error(message);
1634
+ error.name = "EventSourceError";
1635
+ return error;
1636
+ }
1637
+ function streamFailureError(data) {
1638
+ let message = String(data);
1639
+ try {
1640
+ const parsed = typeof data === "string" ? JSON.parse(data) : data;
1641
+ if (typeof parsed?.message === "string") message = parsed.message;
1642
+ } catch {
1643
+ }
1644
+ return eventSourceError(`EventSource failure: ${message}`);
1645
+ }
1484
1646
  function isEventSourceError(error) {
1485
1647
  return error instanceof Error && error.name === "EventSourceError";
1486
1648
  }
@@ -1490,7 +1652,7 @@ var DEFAULT_MAX_CONCURRENT = 6;
1490
1652
  var DEFAULT_COOLDOWN_MS = 5e3;
1491
1653
  var MAX_COOLDOWN_MS = 6e4;
1492
1654
  var DEFAULT_JITTER_MS = 500;
1493
- var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1655
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, Math.min(ms, MAX_TIMER_MS)));
1494
1656
  function parseRetryAfterMs(header) {
1495
1657
  if (header === null || header === void 0) return void 0;
1496
1658
  const trimmed = header.trim();
@@ -1523,6 +1685,9 @@ var OriginRateGate = class {
1523
1685
  maxCooldownMs;
1524
1686
  jitterMs;
1525
1687
  constructor(options) {
1688
+ assertNonNegativeMs("defaultCooldownMs", options?.defaultCooldownMs);
1689
+ assertNonNegativeMs("maxCooldownMs", options?.maxCooldownMs);
1690
+ assertNonNegativeMs("jitterMs", options?.jitterMs);
1526
1691
  this.maxConcurrent = options?.maxConcurrent ?? DEFAULT_MAX_CONCURRENT;
1527
1692
  this.defaultCooldownMs = options?.defaultCooldownMs ?? DEFAULT_COOLDOWN_MS;
1528
1693
  this.maxCooldownMs = options?.maxCooldownMs ?? MAX_COOLDOWN_MS;
@@ -1728,6 +1893,20 @@ var RestArkProvider = class {
1728
1893
  "Arkade server reported a configuration digest mismatch; server info was refreshed. Rebuild and retry the request under the new server info."
1729
1894
  );
1730
1895
  }
1896
+ async postJson(url, body, failureMessage) {
1897
+ const response = await this.authedFetch(url, {
1898
+ method: "POST",
1899
+ headers: {
1900
+ "Content-Type": "application/json"
1901
+ },
1902
+ body: JSON.stringify(body)
1903
+ });
1904
+ if (!response.ok) {
1905
+ const errorText = await response.text();
1906
+ handleError(errorText, failureMessage(errorText, response));
1907
+ }
1908
+ return response;
1909
+ }
1731
1910
  async getInfo() {
1732
1911
  const url = `${this.serverUrl}/v1/info`;
1733
1912
  const response = await rateGate.runHttp(
@@ -1793,20 +1972,14 @@ var RestArkProvider = class {
1793
1972
  }
1794
1973
  async submitTx(signedArkTx, checkpointTxs) {
1795
1974
  const url = `${this.serverUrl}/v1/tx/submit`;
1796
- const response = await this.authedFetch(url, {
1797
- method: "POST",
1798
- headers: {
1799
- "Content-Type": "application/json"
1800
- },
1801
- body: JSON.stringify({
1975
+ const response = await this.postJson(
1976
+ url,
1977
+ {
1802
1978
  signedArkTx,
1803
1979
  checkpointTxs
1804
- })
1805
- });
1806
- if (!response.ok) {
1807
- const errorText = await response.text();
1808
- handleError(errorText, `Failed to submit virtual transaction: ${errorText}`);
1809
- }
1980
+ },
1981
+ (errorText) => `Failed to submit virtual transaction: ${errorText}`
1982
+ );
1810
1983
  const data = await response.json();
1811
1984
  return {
1812
1985
  arkTxid: data.arkTxid,
@@ -1816,129 +1989,87 @@ var RestArkProvider = class {
1816
1989
  }
1817
1990
  async finalizeTx(arkTxid, finalCheckpointTxs) {
1818
1991
  const url = `${this.serverUrl}/v1/tx/finalize`;
1819
- const response = await this.authedFetch(url, {
1820
- method: "POST",
1821
- headers: {
1822
- "Content-Type": "application/json"
1823
- },
1824
- body: JSON.stringify({
1992
+ await this.postJson(
1993
+ url,
1994
+ {
1825
1995
  arkTxid,
1826
1996
  finalCheckpointTxs
1827
- })
1828
- });
1829
- if (!response.ok) {
1830
- const errorText = await response.text();
1831
- handleError(errorText, `Failed to finalize offchain transaction: ${errorText}`);
1832
- }
1997
+ },
1998
+ (errorText) => `Failed to finalize offchain transaction: ${errorText}`
1999
+ );
1833
2000
  }
1834
2001
  async registerIntent(intent) {
1835
2002
  const url = `${this.serverUrl}/v1/batch/registerIntent`;
1836
- const response = await this.authedFetch(url, {
1837
- method: "POST",
1838
- headers: {
1839
- "Content-Type": "application/json"
1840
- },
1841
- body: JSON.stringify({
2003
+ const response = await this.postJson(
2004
+ url,
2005
+ {
1842
2006
  intent: {
1843
2007
  proof: intent.proof,
1844
2008
  message: Intent.encodeMessage(intent.message)
1845
2009
  }
1846
- })
1847
- });
1848
- if (!response.ok) {
1849
- const errorText = await response.text();
1850
- handleError(errorText, `Failed to register intent: ${errorText}`);
1851
- }
2010
+ },
2011
+ (errorText) => `Failed to register intent: ${errorText}`
2012
+ );
1852
2013
  const data = await response.json();
1853
2014
  return data.intentId;
1854
2015
  }
1855
2016
  async deleteIntent(intent) {
1856
2017
  const url = `${this.serverUrl}/v1/batch/deleteIntent`;
1857
- const response = await this.authedFetch(url, {
1858
- method: "POST",
1859
- headers: {
1860
- "Content-Type": "application/json"
1861
- },
1862
- body: JSON.stringify({
2018
+ await this.postJson(
2019
+ url,
2020
+ {
1863
2021
  intent: {
1864
2022
  proof: intent.proof,
1865
2023
  message: Intent.encodeMessage(intent.message)
1866
2024
  }
1867
- })
1868
- });
1869
- if (!response.ok) {
1870
- const errorText = await response.text();
1871
- handleError(errorText, `Failed to delete intent: ${errorText}`);
1872
- }
2025
+ },
2026
+ (errorText) => `Failed to delete intent: ${errorText}`
2027
+ );
1873
2028
  }
1874
2029
  async confirmRegistration(intentId) {
1875
2030
  const url = `${this.serverUrl}/v1/batch/ack`;
1876
- const response = await this.authedFetch(url, {
1877
- method: "POST",
1878
- headers: {
1879
- "Content-Type": "application/json"
1880
- },
1881
- body: JSON.stringify({
2031
+ await this.postJson(
2032
+ url,
2033
+ {
1882
2034
  intentId
1883
- })
1884
- });
1885
- if (!response.ok) {
1886
- const errorText = await response.text();
1887
- handleError(errorText, `Failed to confirm registration: ${errorText}`);
1888
- }
2035
+ },
2036
+ (errorText) => `Failed to confirm registration: ${errorText}`
2037
+ );
1889
2038
  }
1890
2039
  async submitTreeNonces(batchId, pubkey, nonces) {
1891
2040
  const url = `${this.serverUrl}/v1/batch/tree/submitNonces`;
1892
- const response = await this.authedFetch(url, {
1893
- method: "POST",
1894
- headers: {
1895
- "Content-Type": "application/json"
1896
- },
1897
- body: JSON.stringify({
2041
+ await this.postJson(
2042
+ url,
2043
+ {
1898
2044
  batchId,
1899
2045
  pubkey,
1900
2046
  treeNonces: encodeMusig2Nonces(nonces)
1901
- })
1902
- });
1903
- if (!response.ok) {
1904
- const errorText = await response.text();
1905
- handleError(errorText, `Failed to submit tree nonces: ${errorText}`);
1906
- }
2047
+ },
2048
+ (errorText) => `Failed to submit tree nonces: ${errorText}`
2049
+ );
1907
2050
  }
1908
2051
  async submitTreeSignatures(batchId, pubkey, signatures) {
1909
2052
  const url = `${this.serverUrl}/v1/batch/tree/submitSignatures`;
1910
- const response = await this.authedFetch(url, {
1911
- method: "POST",
1912
- headers: {
1913
- "Content-Type": "application/json"
1914
- },
1915
- body: JSON.stringify({
2053
+ await this.postJson(
2054
+ url,
2055
+ {
1916
2056
  batchId,
1917
2057
  pubkey,
1918
2058
  treeSignatures: encodeMusig2Signatures(signatures)
1919
- })
1920
- });
1921
- if (!response.ok) {
1922
- const errorText = await response.text();
1923
- handleError(errorText, `Failed to submit tree signatures: ${errorText}`);
1924
- }
2059
+ },
2060
+ (errorText) => `Failed to submit tree signatures: ${errorText}`
2061
+ );
1925
2062
  }
1926
2063
  async submitSignedForfeitTxs(signedForfeitTxs, signedCommitmentTx) {
1927
2064
  const url = `${this.serverUrl}/v1/batch/submitForfeitTxs`;
1928
- const response = await this.authedFetch(url, {
1929
- method: "POST",
1930
- headers: {
1931
- "Content-Type": "application/json"
1932
- },
1933
- body: JSON.stringify({
2065
+ await this.postJson(
2066
+ url,
2067
+ {
1934
2068
  signedForfeitTxs,
1935
2069
  signedCommitmentTx
1936
- })
1937
- });
1938
- if (!response.ok) {
1939
- const errorText = await response.text();
1940
- handleError(errorText, `Failed to submit forfeit transactions: ${response.statusText}`);
1941
- }
2070
+ },
2071
+ (_, res) => `Failed to submit forfeit transactions: ${res.statusText}`
2072
+ );
1942
2073
  }
1943
2074
  getEventStream(signal, topics) {
1944
2075
  const url = `${this.serverUrl}/v1/batch/events`;
@@ -2061,22 +2192,16 @@ var RestArkProvider = class {
2061
2192
  }
2062
2193
  async getPendingTxs(intent) {
2063
2194
  const url = `${this.serverUrl}/v1/tx/pending`;
2064
- const response = await this.authedFetch(url, {
2065
- method: "POST",
2066
- headers: {
2067
- "Content-Type": "application/json"
2068
- },
2069
- body: JSON.stringify({
2195
+ const response = await this.postJson(
2196
+ url,
2197
+ {
2070
2198
  intent: {
2071
2199
  proof: intent.proof,
2072
2200
  message: Intent.encodeMessage(intent.message)
2073
2201
  }
2074
- })
2075
- });
2076
- if (!response.ok) {
2077
- const errorText = await response.text();
2078
- handleError(errorText, `Failed to get pending transactions: ${errorText}`);
2079
- }
2202
+ },
2203
+ (errorText) => `Failed to get pending transactions: ${errorText}`
2204
+ );
2080
2205
  const data = await response.json();
2081
2206
  return data.pendingTxs;
2082
2207
  }
@@ -2342,11 +2467,16 @@ async function getNormalizedVtxos(provider, opts) {
2342
2467
  const { vtxos, page } = await provider.getVtxos(opts);
2343
2468
  return { vtxos: vtxos.map(normalizeVtxo), page };
2344
2469
  }
2470
+ var SCRIPT_CHUNK_CONCURRENCY = 4;
2345
2471
  async function getAllNormalizedVtxos(provider, scripts, opts = {}) {
2346
2472
  const { pageSize = DEFAULT_PAGE_SIZE, ...filters } = opts;
2347
2473
  const all = [];
2474
+ const chunks = [];
2348
2475
  for (let i = 0; i < scripts.length; i += SCRIPT_QUERY_CHUNK_SIZE) {
2349
- const chunk = scripts.slice(i, i + SCRIPT_QUERY_CHUNK_SIZE);
2476
+ chunks.push(scripts.slice(i, i + SCRIPT_QUERY_CHUNK_SIZE));
2477
+ }
2478
+ const fetchChunk = async (chunk) => {
2479
+ const result = [];
2350
2480
  let pageIndex = 0;
2351
2481
  let hasMore = true;
2352
2482
  while (hasMore) {
@@ -2356,11 +2486,18 @@ async function getAllNormalizedVtxos(provider, scripts, opts = {}) {
2356
2486
  pageIndex,
2357
2487
  pageSize
2358
2488
  });
2359
- all.push(...vtxos);
2489
+ result.push(...vtxos);
2360
2490
  hasMore = page ? vtxos.length === pageSize : false;
2361
2491
  pageIndex++;
2362
2492
  if (hasMore) await new Promise((r) => setTimeout(r, 500));
2363
2493
  }
2494
+ return result;
2495
+ };
2496
+ for (let i = 0; i < chunks.length; i += SCRIPT_CHUNK_CONCURRENCY) {
2497
+ const batch = await Promise.all(
2498
+ chunks.slice(i, i + SCRIPT_CHUNK_CONCURRENCY).map(fetchChunk)
2499
+ );
2500
+ for (const result of batch) all.push(...result);
2364
2501
  }
2365
2502
  return all;
2366
2503
  }
@@ -2383,7 +2520,7 @@ async function fetchVtxoCreatedAtByTxid(provider, txids) {
2383
2520
  }
2384
2521
  return createdAt;
2385
2522
  }
2386
- function hasTerminalSpend(vtxo) {
2523
+ function isVtxoSpent(vtxo) {
2387
2524
  const n = normalizeVtxo(vtxo);
2388
2525
  return !!n.isSpent || !!n.spentBy || !!n.settledBy;
2389
2526
  }
@@ -2394,15 +2531,19 @@ function isPastExpiry(vtxo, now) {
2394
2531
  }
2395
2532
  function canSpendOffchain(vtxo, now) {
2396
2533
  const n = normalizeVtxo(vtxo);
2397
- return !hasTerminalSpend(n) && !n.isUnrolled && !(n.isSwept || isPastExpiry(n, now));
2534
+ return !isVtxoSpent(n) && !n.isUnrolled && !(n.isSwept || isPastExpiry(n, now));
2398
2535
  }
2399
2536
  function canRecoverOnchain(vtxo, now) {
2400
2537
  const n = normalizeVtxo(vtxo);
2401
- return !hasTerminalSpend(n) && !n.isUnrolled && (n.isSwept || isPastExpiry(n, now));
2538
+ return !isVtxoSpent(n) && !n.isUnrolled && (n.isSwept || isPastExpiry(n, now));
2402
2539
  }
2403
2540
  function canSweepOnchain(vtxo) {
2404
2541
  const n = normalizeVtxo(vtxo);
2405
- return !hasTerminalSpend(n) && !!n.isUnrolled;
2542
+ return !isVtxoSpent(n) && !!n.isUnrolled;
2543
+ }
2544
+ function requiresForfeit(vtxo) {
2545
+ const n = normalizeVtxo(vtxo);
2546
+ return !n.isSwept && !n.isUnrolled;
2406
2547
  }
2407
2548
  function toOffchainInputFeeParams(vtxo) {
2408
2549
  return {
@@ -2417,6 +2558,6 @@ function isVirtualCoin(input) {
2417
2558
  return typeof input === "object" && input !== null && typeof input.script === "string";
2418
2559
  }
2419
2560
 
2420
- export { ArkAddress, ArkError, ArkErrorName, ArkPsbtFieldKey, ArkPsbtFieldKeyType, BITCOIN_EMULATOR_PUBKEY, CLTVMultisigTapscript, CSVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, ConditionWitness, CosignerPublicKey, DEFAULT_ARKADE_SERVER_URL, DEFAULT_NETWORK, DEFAULT_NETWORK_NAME, DEFAULT_PAGE_SIZE, DigestMismatchError, EXPIRY_MIN_PLAUSIBLE_MS, EventSourceUnavailableError, FetchError, INFO_FETCH_TIMEOUT_MS, Intent, MUTINYNET_EMULATOR_PUBKEY, MultisigTapscript, OP_RETURN_EMPTY_PKSCRIPT, PrevArkTxField, PrevoutTxField, ProviderUnavailableError, READ_TIMEOUT_MS, REGTEST_EMULATOR_PUBKEY, RestArkProvider, SCRIPT_QUERY_CHUNK_SIZE, ServerResponseMismatchError, SettlementEventType, TapTreeCoder, Transaction, VtxoScript, VtxoTaprootTree, VtxoTreeExpiry, __export, assembleBtcdTaprootTree, assertAllowedSighashTypes, baseFetch, buildVersion, canRecoverOnchain, canSpendOffchain, canSweepOnchain, configureEventSource, convertVtxo, craftToSpendTx, decodeTapscript, defaultEmulatorPubkey, eventSourceIterator, fetch, fetchVtxoCreatedAtByTxid, formatSighash, getAllNormalizedVtxos, getArkPsbtFields, getConfiguredEventSource, getNetwork, getNormalizedVtxos, getSequence, hasTerminalSpend, isArkError, isEventSourceError, isEventSourceUnavailableError, isFetchTimeoutError, isPastExpiry, isRetryableProviderError, isVirtualCoin, maybeArkError, networkFromArkadeInfo, networks, normalizeVtxo, rateGate, resolveEmulatorPubkey, resolveEventSource, resolveTimeHeight, scriptFromTapLeafScript, sdkVersion, sequenceToTimelock, setArkPsbtField, throwIfHttpUnavailable, timelockToSequence, toOffchainInputFeeParams, toProviderUnavailable };
2421
- //# sourceMappingURL=chunk-MTYQXZ2T.js.map
2422
- //# sourceMappingURL=chunk-MTYQXZ2T.js.map
2561
+ export { ARKADE_VERSION_HEADERS, ArkAddress, ArkError, ArkErrorName, ArkPsbtFieldKey, ArkPsbtFieldKeyType, BITCOIN_EMULATOR_PUBKEY, CLTVMultisigTapscript, CSVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, ConditionWitness, CosignerPublicKey, DEFAULT_ARKADE_EMULATOR_URL, DEFAULT_ARKADE_SERVER_URL, DEFAULT_NETWORK, DEFAULT_NETWORK_NAME, DEFAULT_PAGE_SIZE, DigestMismatchError, EXPIRY_MIN_PLAUSIBLE_MS, EventSourceUnavailableError, FetchError, INFO_FETCH_TIMEOUT_MS, Intent, MUTINYNET_EMULATOR_PUBKEY, MultisigTapscript, OP_RETURN_EMPTY_PKSCRIPT, PrevArkTxField, PrevoutTxField, ProviderUnavailableError, READ_TIMEOUT_MS, REGTEST_EMULATOR_PUBKEY, RestArkProvider, SCRIPT_QUERY_CHUNK_SIZE, ServerResponseMismatchError, SettlementEventType, TapTreeCoder, Transaction, VtxoScript, VtxoTaprootTree, VtxoTreeExpiry, __export, assembleBtcdTaprootTree, assertAllowedSighashTypes, assertNonNegativeMs, assertTimerMs, baseFetch, buildVersion, canRecoverOnchain, canSpendOffchain, canSweepOnchain, configureEventSource, convertVtxo, craftToSpendTx, decodeTapscript, defaultEmulatorPubkey, eventSourceIterator, fetchVtxoCreatedAtByTxid, formatSighash, getAllNormalizedVtxos, getArkPsbtFields, getConfiguredEventSource, getNetwork, getNormalizedVtxos, getSequence, isArkError, isEventSourceError, isEventSourceUnavailableError, isFetchTimeoutError, isPastExpiry, isRetryableProviderError, isVirtualCoin, isVtxoSpent, maybeArkError, networkFromArkadeInfo, networks, normalizeVtxo, rateGate, requiresForfeit, resolveEmulatorPubkey, resolveEventSource, resolveTimeHeight, scriptFromTapLeafScript, sdkVersion, sequenceToCanonicalTimelock, sequenceToTimelock, setArkPsbtField, streamFailureError, throwIfHttpUnavailable, timelockToSequence, toBIP371TapTree, toOffchainInputFeeParams, toProviderUnavailable };
2562
+ //# sourceMappingURL=chunk-ZOEB53NQ.js.map
2563
+ //# sourceMappingURL=chunk-ZOEB53NQ.js.map