@arkade-os/sdk 0.4.52 → 0.4.54

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 (81) 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-B69ugeJw.d.cts → ark-acFuA57I.d.cts} +2 -1
  8. package/dist/{ark-B69ugeJw.d.ts → ark-acFuA57I.d.ts} +2 -1
  9. package/dist/{asyncStorageTaskQueue-DScPdQAy.d.cts → asyncStorageTaskQueue-BO3cvMpP.d.cts} +1 -1
  10. package/dist/{asyncStorageTaskQueue-BImF14sj.d.ts → asyncStorageTaskQueue-DACXtP0I.d.ts} +1 -1
  11. package/dist/chunk-4EIKOJLD.js +2319 -0
  12. package/dist/chunk-4EIKOJLD.js.map +1 -0
  13. package/dist/{chunk-IEMPH7J6.cjs → chunk-53XNU2EL.cjs} +40 -40
  14. package/dist/{chunk-IEMPH7J6.cjs.map → chunk-53XNU2EL.cjs.map} +1 -1
  15. package/dist/{chunk-3ZGANANS.js → chunk-7L3P3EP5.js} +4 -4
  16. package/dist/{chunk-3ZGANANS.js.map → chunk-7L3P3EP5.js.map} +1 -1
  17. package/dist/{chunk-UZLQUWYP.js → chunk-A37WVZ5T.js} +3 -3
  18. package/dist/{chunk-UZLQUWYP.js.map → chunk-A37WVZ5T.js.map} +1 -1
  19. package/dist/{chunk-E6RT5XYB.cjs → chunk-BYJJIITU.cjs} +17 -17
  20. package/dist/{chunk-E6RT5XYB.cjs.map → chunk-BYJJIITU.cjs.map} +1 -1
  21. package/dist/{chunk-ML33GFCH.cjs → chunk-D5LUPJJP.cjs} +837 -437
  22. package/dist/chunk-D5LUPJJP.cjs.map +1 -0
  23. package/dist/chunk-GMUVWKOK.cjs +2407 -0
  24. package/dist/chunk-GMUVWKOK.cjs.map +1 -0
  25. package/dist/{chunk-WIVQWYPZ.js → chunk-QY2YVFZT.js} +4 -4
  26. package/dist/{chunk-WIVQWYPZ.js.map → chunk-QY2YVFZT.js.map} +1 -1
  27. package/dist/{chunk-FZPYPEWN.cjs → chunk-RNECH3TA.cjs} +19 -1367
  28. package/dist/chunk-RNECH3TA.cjs.map +1 -0
  29. package/dist/{chunk-AXCKRS2D.js → chunk-TEHJCEF3.js} +473 -91
  30. package/dist/chunk-TEHJCEF3.js.map +1 -0
  31. package/dist/{chunk-3Z5HK35D.cjs → chunk-YRLBZJYO.cjs} +9 -9
  32. package/dist/{chunk-3Z5HK35D.cjs.map → chunk-YRLBZJYO.cjs.map} +1 -1
  33. package/dist/{chunk-ZK3JITHP.js → chunk-ZOY5JSVA.js} +8 -1327
  34. package/dist/chunk-ZOY5JSVA.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-C_Y2YrXC.d.cts → delegate-Ca_wXiYE.d.cts} +1 -1
  40. package/dist/{delegate-BU-Cpyjw.d.ts → delegate-DjwZZi6L.d.ts} +1 -1
  41. package/dist/{index-tzAInyiX.d.cts → index-DFfefdpc.d.cts} +2 -2
  42. package/dist/{index-BWF-C9eh.d.ts → index-Ddq0mIKX.d.ts} +2 -2
  43. package/dist/index.cjs +319 -239
  44. package/dist/index.d.cts +300 -12
  45. package/dist/index.d.ts +300 -12
  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-ClwI8jU8.d.cts → taskRunner-DEwlrgId.d.cts} +1 -1
  56. package/dist/{taskRunner-Cf80BqSy.d.ts → taskRunner-DbCNRP31.d.ts} +1 -1
  57. package/dist/wallet/expo/background.cjs +15 -15
  58. package/dist/wallet/expo/background.cjs.map +1 -1
  59. package/dist/wallet/expo/background.d.cts +3 -3
  60. package/dist/wallet/expo/background.d.ts +3 -3
  61. package/dist/wallet/expo/background.js +7 -7
  62. package/dist/wallet/expo/background.js.map +1 -1
  63. package/dist/wallet/expo/index.cjs +14 -14
  64. package/dist/wallet/expo/index.d.cts +4 -4
  65. package/dist/wallet/expo/index.d.ts +4 -4
  66. package/dist/wallet/expo/index.js +5 -5
  67. package/dist/{wallet-B6Xiferv.d.cts → wallet-B9rpddG2.d.ts} +2 -2
  68. package/dist/{wallet-CuHAI-eW.d.ts → wallet-ByjM6L20.d.cts} +2 -2
  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 +1 -1
  74. package/dist/chunk-AXCKRS2D.js.map +0 -1
  75. package/dist/chunk-E7HB3GKK.cjs +0 -1030
  76. package/dist/chunk-E7HB3GKK.cjs.map +0 -1
  77. package/dist/chunk-EFNLTS6Q.js +0 -976
  78. package/dist/chunk-EFNLTS6Q.js.map +0 -1
  79. package/dist/chunk-FZPYPEWN.cjs.map +0 -1
  80. package/dist/chunk-ML33GFCH.cjs.map +0 -1
  81. package/dist/chunk-ZK3JITHP.js.map +0 -1
@@ -1,976 +0,0 @@
1
- import * as bip68 from 'bip68';
2
- import { TEST_NETWORK, NETWORK } from '@scure/btc-signer/utils.js';
3
- import { hex, bech32m } from '@scure/base';
4
- import { Script as Script$1 } from '@scure/btc-signer/script.js';
5
- import { ScriptNum, p2tr_ms, Script, p2tr, TAPROOT_UNSPENDABLE_KEY, Address } from '@scure/btc-signer';
6
- import { TAP_LEAF_VERSION } from '@scure/btc-signer/payment.js';
7
- import { PSBTOutput } from '@scure/btc-signer/psbt.js';
8
-
9
- // src/utils/timelock.ts
10
- function timelockToSequence(timelock) {
11
- return bip68.encode(
12
- timelock.type === "blocks" ? { blocks: Number(timelock.value) } : { seconds: Number(timelock.value) }
13
- );
14
- }
15
- function sequenceToTimelock(sequence) {
16
- const decoded = bip68.decode(sequence);
17
- if ("blocks" in decoded && decoded.blocks !== void 0) {
18
- return { type: "blocks", value: BigInt(decoded.blocks) };
19
- }
20
- if ("seconds" in decoded && decoded.seconds !== void 0) {
21
- return { type: "seconds", value: BigInt(decoded.seconds) };
22
- }
23
- throw new Error(`Invalid BIP68 sequence: ${sequence}`);
24
- }
25
- var getNetwork = (network) => {
26
- const found = networks[network];
27
- if (!found) throw new Error(`Unsupported network: ${network}`);
28
- return found;
29
- };
30
- var networks = {
31
- bitcoin: withArkPrefix(NETWORK, "ark"),
32
- testnet: withArkPrefix(TEST_NETWORK, "tark"),
33
- signet: withArkPrefix(TEST_NETWORK, "tark"),
34
- mutinynet: withArkPrefix(TEST_NETWORK, "tark"),
35
- regtest: withArkPrefix(
36
- {
37
- ...TEST_NETWORK,
38
- bech32: "bcrt",
39
- pubKeyHash: 111,
40
- scriptHash: 196
41
- },
42
- "tark"
43
- )
44
- };
45
- function withArkPrefix(network, prefix) {
46
- return {
47
- ...network,
48
- hrp: prefix
49
- };
50
- }
51
- var DEFAULT_ARKADE_SERVER_URL = "https://arkade.computer";
52
- var DEFAULT_NETWORK = networks.bitcoin;
53
- var DEFAULT_NETWORK_NAME = "bitcoin";
54
- var ArkAddress = class _ArkAddress {
55
- /**
56
- * Create an Arkade address from its server public key, Taproot output key, and prefix.
57
- *
58
- * @param serverPubKey - 32-byte Arkade server public key
59
- * @param vtxoTaprootKey - 32-byte Taproot output key (a.k.a. tweaked public key)
60
- * @param hrp - Bech32 human-readable prefix
61
- * @param version - Address version byte
62
- * @defaultValue `version = 0`
63
- * @throws Error if either public key is not 32 bytes long
64
- */
65
- constructor(serverPubKey, vtxoTaprootKey, hrp = DEFAULT_NETWORK.hrp, version = 0) {
66
- this.serverPubKey = serverPubKey;
67
- this.vtxoTaprootKey = vtxoTaprootKey;
68
- this.hrp = hrp;
69
- this.version = version;
70
- if (serverPubKey.length !== 32) {
71
- throw new Error(
72
- "Invalid server public key length, expected 32 bytes, got " + serverPubKey.length
73
- );
74
- }
75
- if (vtxoTaprootKey.length !== 32) {
76
- throw new Error(
77
- "Invalid vtxo taproot public key length, expected 32 bytes, got " + vtxoTaprootKey.length
78
- );
79
- }
80
- }
81
- serverPubKey;
82
- vtxoTaprootKey;
83
- hrp;
84
- version;
85
- /**
86
- * Decode an Arkade address from its bech32m string form.
87
- *
88
- * @param address - Bech32m-encoded Arkade address
89
- * @returns Decoded Arkade address
90
- * @throws Error if the address is malformed or has an invalid payload length
91
- * @see encode
92
- */
93
- static decode(address) {
94
- const decoded = bech32m.decodeUnsafe(address, 1023);
95
- if (!decoded) {
96
- throw new Error("Invalid address");
97
- }
98
- const data = new Uint8Array(bech32m.fromWords(decoded.words));
99
- if (data.length !== 1 + 32 + 32) {
100
- throw new Error("Invalid data length, expected 65 bytes, got " + data.length);
101
- }
102
- const version = data[0];
103
- const serverPubKey = data.slice(1, 33);
104
- const vtxoTaprootPubKey = data.slice(33, 65);
105
- return new _ArkAddress(serverPubKey, vtxoTaprootPubKey, decoded.prefix, version);
106
- }
107
- /**
108
- * Encode the address to its bech32m string form.
109
- *
110
- * @returns Bech32m-encoded Arkade address
111
- * @see decode
112
- */
113
- encode() {
114
- const data = new Uint8Array(1 + 32 + 32);
115
- data[0] = this.version;
116
- data.set(this.serverPubKey, 1);
117
- data.set(this.vtxoTaprootKey, 33);
118
- const words = bech32m.toWords(data);
119
- return bech32m.encode(this.hrp, words, 1023);
120
- }
121
- /** ScriptPubKey used to send non-dust funds to the address. */
122
- get pkScript() {
123
- return Script$1.encode(["OP_1", this.vtxoTaprootKey]);
124
- }
125
- /** ScriptPubKey used to send sub-dust funds to the address. */
126
- get subdustPkScript() {
127
- return Script$1.encode(["RETURN", this.vtxoTaprootKey]);
128
- }
129
- };
130
- var MinimalScriptNum = ScriptNum(void 0, true);
131
- function decodeTapscript(script) {
132
- const types = [
133
- MultisigTapscript,
134
- CSVMultisigTapscript,
135
- ConditionCSVMultisigTapscript,
136
- ConditionMultisigTapscript,
137
- CLTVMultisigTapscript
138
- ];
139
- for (const type of types) {
140
- try {
141
- return type.decode(script);
142
- } catch (error) {
143
- continue;
144
- }
145
- }
146
- throw new Error(`Failed to decode: script ${hex.encode(script)} is not a valid tapscript`);
147
- }
148
- var MultisigTapscript;
149
- ((MultisigTapscript2) => {
150
- ((MultisigType2) => {
151
- MultisigType2[MultisigType2["CHECKSIG"] = 0] = "CHECKSIG";
152
- MultisigType2[MultisigType2["CHECKSIGADD"] = 1] = "CHECKSIGADD";
153
- })(MultisigTapscript2.MultisigType || (MultisigTapscript2.MultisigType = {}));
154
- function encode2(params) {
155
- if (params.pubkeys.length === 0) {
156
- throw new Error("At least 1 pubkey is required");
157
- }
158
- for (const pubkey of params.pubkeys) {
159
- if (pubkey.length !== 32) {
160
- throw new Error(`Invalid pubkey length: expected 32, got ${pubkey.length}`);
161
- }
162
- }
163
- if (!params.type) {
164
- params.type = 0 /* CHECKSIG */;
165
- }
166
- if (params.type === 1 /* CHECKSIGADD */) {
167
- return {
168
- type: "multisig" /* Multisig */,
169
- params,
170
- script: p2tr_ms(params.pubkeys.length, params.pubkeys).script
171
- };
172
- }
173
- const asm = [];
174
- for (let i = 0; i < params.pubkeys.length; i++) {
175
- asm.push(params.pubkeys[i]);
176
- if (i < params.pubkeys.length - 1) {
177
- asm.push("CHECKSIGVERIFY");
178
- } else {
179
- asm.push("CHECKSIG");
180
- }
181
- }
182
- return {
183
- type: "multisig" /* Multisig */,
184
- params,
185
- script: Script.encode(asm)
186
- };
187
- }
188
- MultisigTapscript2.encode = encode2;
189
- function decode2(script) {
190
- if (script.length === 0) {
191
- throw new Error("Failed to decode: script is empty");
192
- }
193
- try {
194
- return decodeChecksigAdd(script);
195
- } catch (error) {
196
- try {
197
- return decodeChecksig(script);
198
- } catch (error2) {
199
- throw new Error(
200
- `Failed to decode script: ${error2 instanceof Error ? error2.message : String(error2)}`
201
- );
202
- }
203
- }
204
- }
205
- MultisigTapscript2.decode = decode2;
206
- function decodeChecksigAdd(script) {
207
- const asm = Script.decode(script);
208
- const pubkeys = [];
209
- let foundNumEqual = false;
210
- for (let i = 0; i < asm.length; i++) {
211
- const op = asm[i];
212
- if (typeof op !== "string" && typeof op !== "number") {
213
- if (op.length !== 32) {
214
- throw new Error(`Invalid pubkey length: expected 32, got ${op.length}`);
215
- }
216
- pubkeys.push(op);
217
- if (i + 1 >= asm.length || asm[i + 1] !== "CHECKSIGADD" && asm[i + 1] !== "CHECKSIG") {
218
- throw new Error("Expected CHECKSIGADD or CHECKSIG after pubkey");
219
- }
220
- i++;
221
- continue;
222
- }
223
- if (i === asm.length - 1) {
224
- if (op !== "NUMEQUAL") {
225
- throw new Error("Expected NUMEQUAL at end of script");
226
- }
227
- foundNumEqual = true;
228
- }
229
- }
230
- if (!foundNumEqual) {
231
- throw new Error("Missing NUMEQUAL operation");
232
- }
233
- if (pubkeys.length === 0) {
234
- throw new Error("Invalid script: must have at least 1 pubkey");
235
- }
236
- const reconstructed = encode2({
237
- pubkeys,
238
- type: 1 /* CHECKSIGADD */
239
- });
240
- if (hex.encode(reconstructed.script) !== hex.encode(script)) {
241
- throw new Error("Invalid script format: script reconstruction mismatch");
242
- }
243
- return {
244
- type: "multisig" /* Multisig */,
245
- params: { pubkeys, type: 1 /* CHECKSIGADD */ },
246
- script
247
- };
248
- }
249
- function decodeChecksig(script) {
250
- const asm = Script.decode(script);
251
- const pubkeys = [];
252
- for (let i = 0; i < asm.length; i++) {
253
- const op = asm[i];
254
- if (typeof op !== "string" && typeof op !== "number") {
255
- if (op.length !== 32) {
256
- throw new Error(`Invalid pubkey length: expected 32, got ${op.length}`);
257
- }
258
- pubkeys.push(op);
259
- if (i + 1 >= asm.length) {
260
- throw new Error("Unexpected end of script");
261
- }
262
- const nextOp = asm[i + 1];
263
- if (nextOp !== "CHECKSIGVERIFY" && nextOp !== "CHECKSIG") {
264
- throw new Error("Expected CHECKSIGVERIFY or CHECKSIG after pubkey");
265
- }
266
- if (i === asm.length - 2 && nextOp !== "CHECKSIG") {
267
- throw new Error("Last operation must be CHECKSIG");
268
- }
269
- i++;
270
- continue;
271
- }
272
- }
273
- if (pubkeys.length === 0) {
274
- throw new Error("Invalid script: must have at least 1 pubkey");
275
- }
276
- const reconstructed = encode2({ pubkeys, type: 0 /* CHECKSIG */ });
277
- if (hex.encode(reconstructed.script) !== hex.encode(script)) {
278
- throw new Error("Invalid script format: script reconstruction mismatch");
279
- }
280
- return {
281
- type: "multisig" /* Multisig */,
282
- params: { pubkeys, type: 0 /* CHECKSIG */ },
283
- script
284
- };
285
- }
286
- function is(tapscript) {
287
- return tapscript.type === "multisig" /* Multisig */;
288
- }
289
- MultisigTapscript2.is = is;
290
- })(MultisigTapscript || (MultisigTapscript = {}));
291
- var CSVMultisigTapscript;
292
- ((CSVMultisigTapscript2) => {
293
- function encode2(params) {
294
- for (const pubkey of params.pubkeys) {
295
- if (pubkey.length !== 32) {
296
- throw new Error(`Invalid pubkey length: expected 32, got ${pubkey.length}`);
297
- }
298
- }
299
- const sequence = MinimalScriptNum.encode(BigInt(timelockToSequence(params.timelock)));
300
- const asm = [
301
- sequence.length === 1 ? sequence[0] : sequence,
302
- "CHECKSEQUENCEVERIFY",
303
- "DROP"
304
- ];
305
- const multisigScript = MultisigTapscript.encode(params);
306
- const script = new Uint8Array([...Script.encode(asm), ...multisigScript.script]);
307
- return {
308
- type: "csv-multisig" /* CSVMultisig */,
309
- params,
310
- script
311
- };
312
- }
313
- CSVMultisigTapscript2.encode = encode2;
314
- function decode2(script) {
315
- if (script.length === 0) {
316
- throw new Error("Failed to decode: script is empty");
317
- }
318
- const isValid = isScriptValid(script);
319
- if (isValid instanceof Error) {
320
- throw isValid;
321
- }
322
- const asm = Script.decode(script);
323
- const sequence = asm[0];
324
- const multisigScript = new Uint8Array(Script.encode(asm.slice(3)));
325
- let multisig;
326
- try {
327
- multisig = MultisigTapscript.decode(multisigScript);
328
- } catch (error) {
329
- throw new Error(
330
- `Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`
331
- );
332
- }
333
- let sequenceNum;
334
- if (typeof sequence === "number") {
335
- sequenceNum = sequence;
336
- } else {
337
- sequenceNum = Number(MinimalScriptNum.decode(sequence));
338
- }
339
- const timelock = sequenceToTimelock(sequenceNum);
340
- const reconstructed = encode2({
341
- timelock,
342
- ...multisig.params
343
- });
344
- if (hex.encode(reconstructed.script) !== hex.encode(script)) {
345
- throw new Error("Invalid script format: script reconstruction mismatch");
346
- }
347
- return {
348
- type: "csv-multisig" /* CSVMultisig */,
349
- params: {
350
- timelock,
351
- ...multisig.params
352
- },
353
- script
354
- };
355
- }
356
- CSVMultisigTapscript2.decode = decode2;
357
- function is(tapscript) {
358
- return tapscript.type === "csv-multisig" /* CSVMultisig */;
359
- }
360
- CSVMultisigTapscript2.is = is;
361
- function isScriptValid(script) {
362
- const asm = Script.decode(script);
363
- if (asm.length < 3) {
364
- return new Error(`Invalid script: too short (expected at least 3)`);
365
- }
366
- const sequence = asm[0];
367
- if (typeof sequence === "string") {
368
- return new Error("Invalid script: expected sequence number");
369
- }
370
- if (asm[1] !== "CHECKSEQUENCEVERIFY" || asm[2] !== "DROP") {
371
- return new Error("Invalid script: expected CHECKSEQUENCEVERIFY DROP");
372
- }
373
- return true;
374
- }
375
- CSVMultisigTapscript2.isScriptValid = isScriptValid;
376
- })(CSVMultisigTapscript || (CSVMultisigTapscript = {}));
377
- var ConditionCSVMultisigTapscript;
378
- ((ConditionCSVMultisigTapscript2) => {
379
- function encode2(params) {
380
- const script = new Uint8Array([
381
- ...params.conditionScript,
382
- ...Script.encode(["VERIFY"]),
383
- ...CSVMultisigTapscript.encode(params).script
384
- ]);
385
- return {
386
- type: "condition-csv-multisig" /* ConditionCSVMultisig */,
387
- params,
388
- script
389
- };
390
- }
391
- ConditionCSVMultisigTapscript2.encode = encode2;
392
- function decode2(script) {
393
- if (script.length === 0) {
394
- throw new Error("Failed to decode: script is empty");
395
- }
396
- const isValid = isScriptValid(script);
397
- if (isValid instanceof Error) {
398
- throw isValid;
399
- }
400
- const asm = Script.decode(script);
401
- let verifyIndex = getVerifyIndex(asm);
402
- if (verifyIndex === -1) {
403
- throw Error("Invalid script: missing VERIFY operation");
404
- }
405
- const conditionScript = new Uint8Array(Script.encode(asm.slice(0, verifyIndex)));
406
- const csvMultisigScript = new Uint8Array(Script.encode(asm.slice(verifyIndex + 1)));
407
- let csvMultisig;
408
- try {
409
- csvMultisig = CSVMultisigTapscript.decode(csvMultisigScript);
410
- } catch (error) {
411
- throw new Error(
412
- `Invalid CSV multisig script: ${error instanceof Error ? error.message : String(error)}`
413
- );
414
- }
415
- const reconstructed = encode2({
416
- conditionScript,
417
- ...csvMultisig.params
418
- });
419
- if (hex.encode(reconstructed.script) !== hex.encode(script)) {
420
- throw new Error("Invalid script format: script reconstruction mismatch");
421
- }
422
- return {
423
- type: "condition-csv-multisig" /* ConditionCSVMultisig */,
424
- params: {
425
- conditionScript,
426
- ...csvMultisig.params
427
- },
428
- script
429
- };
430
- }
431
- ConditionCSVMultisigTapscript2.decode = decode2;
432
- function is(tapscript) {
433
- return tapscript.type === "condition-csv-multisig" /* ConditionCSVMultisig */;
434
- }
435
- ConditionCSVMultisigTapscript2.is = is;
436
- function getVerifyIndex(asm) {
437
- let verifyIndex = -1;
438
- for (let i = asm.length - 1; i >= 0; i--) {
439
- if (asm[i] === "VERIFY") {
440
- verifyIndex = i;
441
- return verifyIndex;
442
- }
443
- }
444
- return verifyIndex;
445
- }
446
- function isScriptValid(script) {
447
- const asm = Script.decode(script);
448
- if (asm.length < 1) {
449
- return new Error(`Invalid script: too short (expected at least 1)`);
450
- }
451
- let verifyIndex = getVerifyIndex(asm);
452
- if (verifyIndex === -1) {
453
- return new Error("Invalid script: missing VERIFY operation");
454
- }
455
- return true;
456
- }
457
- ConditionCSVMultisigTapscript2.isScriptValid = isScriptValid;
458
- })(ConditionCSVMultisigTapscript || (ConditionCSVMultisigTapscript = {}));
459
- var ConditionMultisigTapscript;
460
- ((ConditionMultisigTapscript2) => {
461
- function encode2(params) {
462
- const script = new Uint8Array([
463
- ...params.conditionScript,
464
- ...Script.encode(["VERIFY"]),
465
- ...MultisigTapscript.encode(params).script
466
- ]);
467
- return {
468
- type: "condition-multisig" /* ConditionMultisig */,
469
- params,
470
- script
471
- };
472
- }
473
- ConditionMultisigTapscript2.encode = encode2;
474
- function decode2(script) {
475
- if (script.length === 0) {
476
- throw new Error("Failed to decode: script is empty");
477
- }
478
- const isValid = isScriptValid(script);
479
- if (isValid instanceof Error) {
480
- throw isValid;
481
- }
482
- const asm = Script.decode(script);
483
- let verifyIndex = getVerifyIndex(asm);
484
- if (verifyIndex === -1) {
485
- throw Error("Invalid script: missing VERIFY operation");
486
- }
487
- const conditionScript = new Uint8Array(Script.encode(asm.slice(0, verifyIndex)));
488
- const multisigScript = new Uint8Array(Script.encode(asm.slice(verifyIndex + 1)));
489
- let multisig;
490
- try {
491
- multisig = MultisigTapscript.decode(multisigScript);
492
- } catch (error) {
493
- throw new Error(
494
- `Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`
495
- );
496
- }
497
- const reconstructed = encode2({
498
- conditionScript,
499
- ...multisig.params
500
- });
501
- if (hex.encode(reconstructed.script) !== hex.encode(script)) {
502
- throw new Error("Invalid script format: script reconstruction mismatch");
503
- }
504
- return {
505
- type: "condition-multisig" /* ConditionMultisig */,
506
- params: {
507
- conditionScript,
508
- ...multisig.params
509
- },
510
- script
511
- };
512
- }
513
- ConditionMultisigTapscript2.decode = decode2;
514
- function is(tapscript) {
515
- return tapscript.type === "condition-multisig" /* ConditionMultisig */;
516
- }
517
- ConditionMultisigTapscript2.is = is;
518
- function getVerifyIndex(asm) {
519
- let verifyIndex = -1;
520
- for (let i = asm.length - 1; i >= 0; i--) {
521
- if (asm[i] === "VERIFY") {
522
- verifyIndex = i;
523
- return verifyIndex;
524
- }
525
- }
526
- return verifyIndex;
527
- }
528
- function isScriptValid(script) {
529
- const asm = Script.decode(script);
530
- if (asm.length < 1) {
531
- return new Error(`Invalid script: too short (expected at least 1)`);
532
- }
533
- let verifyIndex = getVerifyIndex(asm);
534
- if (verifyIndex === -1) {
535
- return new Error("Invalid script: missing VERIFY operation");
536
- }
537
- return true;
538
- }
539
- ConditionMultisigTapscript2.isScriptValid = isScriptValid;
540
- })(ConditionMultisigTapscript || (ConditionMultisigTapscript = {}));
541
- var CLTVMultisigTapscript;
542
- ((CLTVMultisigTapscript2) => {
543
- function encode2(params) {
544
- const locktime = MinimalScriptNum.encode(params.absoluteTimelock);
545
- const asm = [
546
- locktime.length === 1 ? locktime[0] : locktime,
547
- "CHECKLOCKTIMEVERIFY",
548
- "DROP"
549
- ];
550
- const timelockedScript = Script.encode(asm);
551
- const script = new Uint8Array([
552
- ...timelockedScript,
553
- ...MultisigTapscript.encode(params).script
554
- ]);
555
- return {
556
- type: "cltv-multisig" /* CLTVMultisig */,
557
- params,
558
- script
559
- };
560
- }
561
- CLTVMultisigTapscript2.encode = encode2;
562
- function decode2(script) {
563
- if (script.length === 0) {
564
- throw new Error("Failed to decode: script is empty");
565
- }
566
- const isValid = isScriptValid(script);
567
- if (isValid instanceof Error) {
568
- throw isValid;
569
- }
570
- const asm = Script.decode(script);
571
- const locktime = asm[0];
572
- if (typeof locktime === "string") {
573
- throw new Error("Invalid script: expected locktime number");
574
- }
575
- if (asm[1] !== "CHECKLOCKTIMEVERIFY" || asm[2] !== "DROP") {
576
- throw new Error("Invalid script: expected CHECKLOCKTIMEVERIFY DROP");
577
- }
578
- const multisigScript = new Uint8Array(Script.encode(asm.slice(3)));
579
- let multisig;
580
- try {
581
- multisig = MultisigTapscript.decode(multisigScript);
582
- } catch (error) {
583
- throw new Error(
584
- `Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`
585
- );
586
- }
587
- let absoluteTimelock;
588
- if (typeof locktime === "number") {
589
- absoluteTimelock = BigInt(locktime);
590
- } else {
591
- absoluteTimelock = MinimalScriptNum.decode(locktime);
592
- }
593
- const reconstructed = encode2({
594
- absoluteTimelock,
595
- ...multisig.params
596
- });
597
- if (hex.encode(reconstructed.script) !== hex.encode(script)) {
598
- throw new Error("Invalid script format: script reconstruction mismatch");
599
- }
600
- return {
601
- type: "cltv-multisig" /* CLTVMultisig */,
602
- params: {
603
- absoluteTimelock,
604
- ...multisig.params
605
- },
606
- script
607
- };
608
- }
609
- CLTVMultisigTapscript2.decode = decode2;
610
- function is(tapscript) {
611
- return tapscript.type === "cltv-multisig" /* CLTVMultisig */;
612
- }
613
- CLTVMultisigTapscript2.is = is;
614
- function isScriptValid(script) {
615
- const asm = Script.decode(script);
616
- if (asm.length < 3) {
617
- return new Error(`Invalid script: too short (expected at least 3)`);
618
- }
619
- const locktime = asm[0];
620
- if (typeof locktime === "string") {
621
- return new Error("Invalid script: expected locktime as number or bytes");
622
- }
623
- if (asm[1] !== "CHECKLOCKTIMEVERIFY" || asm[2] !== "DROP") {
624
- return new Error("Invalid script: expected CHECKLOCKTIMEVERIFY DROP");
625
- }
626
- return true;
627
- }
628
- CLTVMultisigTapscript2.isScriptValid = isScriptValid;
629
- })(CLTVMultisigTapscript || (CLTVMultisigTapscript = {}));
630
- function assembleBtcdTaprootTree(scripts) {
631
- if (scripts.length === 0) {
632
- throw new Error("assembleBtcdTaprootTree: empty scripts list");
633
- }
634
- const leaves = scripts.map((script) => ({
635
- script,
636
- leafVersion: TAP_LEAF_VERSION
637
- }));
638
- if (leaves.length === 1) {
639
- return leaves[0];
640
- }
641
- const branches = [];
642
- for (let i = 0; i < leaves.length; i += 2) {
643
- if (i === leaves.length - 1) {
644
- const last = branches.pop();
645
- if (last === void 0) {
646
- throw new Error(
647
- `assembleBtcdTaprootTree: unexpected odd leaf at i=${i} with no prior branch`
648
- );
649
- }
650
- branches.push([last, leaves[i]]);
651
- } else {
652
- branches.push([leaves[i], leaves[i + 1]]);
653
- }
654
- }
655
- while (branches.length >= 2) {
656
- const left = branches.shift();
657
- const right = branches.shift();
658
- branches.push([left, right]);
659
- }
660
- return branches[0];
661
- }
662
- var TapTreeCoder = PSBTOutput.tapTree[2];
663
- function scriptFromTapLeafScript(leaf) {
664
- return leaf[1].subarray(0, leaf[1].length - 1);
665
- }
666
- var VtxoScript = class _VtxoScript {
667
- /**
668
- * Create a virtual output script from its tapleaf scripts.
669
- *
670
- * The Taproot script tree is assembled using btcd's algorithm
671
- * (`txscript.AssembleTaprootScriptTree`) so the derived taproot output
672
- * key agrees with arkd for any leaf count. `@scure/btc-signer`'s
673
- * default `taprootListToTree` is a Huffman builder that only agrees
674
- * with arkd for power-of-2 leaf counts.
675
- *
676
- * @param scripts - Raw tapscript bytes for each leaf
677
- * @throws Error if the provided leaves cannot produce a valid Taproot tree
678
- */
679
- constructor(scripts) {
680
- this.scripts = scripts;
681
- const tapTree = assembleBtcdTaprootTree(scripts);
682
- const payment = p2tr(TAPROOT_UNSPENDABLE_KEY, tapTree, void 0, true);
683
- if (!payment.tapLeafScript || payment.tapLeafScript.length !== scripts.length) {
684
- throw new Error("invalid scripts");
685
- }
686
- this.leaves = payment.tapLeafScript;
687
- this.tweakedPublicKey = payment.tweakedPubkey;
688
- this.pkScript = payment.script;
689
- }
690
- scripts;
691
- leaves;
692
- tweakedPublicKey;
693
- pkScript;
694
- /**
695
- * Decode a virtual output script from an encoded TapTree.
696
- *
697
- * @param tapTree - Encoded TapTree bytes
698
- * @returns Decoded virtual output script
699
- * @throws Error if the TapTree cannot be decoded into a valid script set
700
- * @see encode
701
- */
702
- static decode(tapTree) {
703
- const leaves = TapTreeCoder.decode(tapTree);
704
- const scripts = leaves.map((leaf) => leaf.script);
705
- return new _VtxoScript(scripts);
706
- }
707
- /**
708
- * Encode the virtual output script to a TapTree byte representation.
709
- *
710
- * @returns Encoded TapTree bytes
711
- * @see decode
712
- */
713
- encode() {
714
- const tapTree = TapTreeCoder.encode(
715
- this.scripts.map((script) => ({
716
- depth: 1,
717
- version: TAP_LEAF_VERSION,
718
- script
719
- }))
720
- );
721
- return tapTree;
722
- }
723
- /**
724
- * Build the Arkade address corresponding to this virtual output script.
725
- *
726
- * @param prefix - Bech32 human-readable prefix
727
- * @param serverPubKey - 32-byte Arkade server public key
728
- * @returns Arkade address for this script
729
- * @see ArkAddress
730
- */
731
- address(prefix = DEFAULT_NETWORK.hrp, serverPubKey) {
732
- return new ArkAddress(serverPubKey, this.tweakedPublicKey, prefix);
733
- }
734
- /**
735
- * Build the Taproot onchain address corresponding to this virtual output script.
736
- *
737
- * @param network - Bitcoin network descriptor
738
- * @returns Taproot onchain address
739
- * @see address
740
- */
741
- onchainAddress(network = DEFAULT_NETWORK) {
742
- return Address(network).encode({
743
- type: "tr",
744
- pubkey: this.tweakedPublicKey
745
- });
746
- }
747
- /**
748
- * Look up a tapleaf script by its hex-encoded tapscript body.
749
- *
750
- * @param scriptHex - Hex-encoded tapscript body without the leaf version byte
751
- * @returns Matching tapleaf script
752
- * @throws Error if no matching leaf exists
753
- */
754
- findLeaf(scriptHex) {
755
- const leaf = this.leaves.find(
756
- (leaf2) => hex.encode(scriptFromTapLeafScript(leaf2)) === scriptHex
757
- );
758
- if (!leaf) {
759
- throw new Error(`leaf '${scriptHex}' not found`);
760
- }
761
- return leaf;
762
- }
763
- /**
764
- * Return all unilateral exit paths embedded in the virtual output script.
765
- *
766
- * @returns CSV-based exit paths found in the leaves
767
- * @see getSequence
768
- */
769
- exitPaths() {
770
- const paths = [];
771
- for (const leaf of this.leaves) {
772
- try {
773
- const script = scriptFromTapLeafScript(leaf);
774
- if (CSVMultisigTapscript.isScriptValid(script) === true) {
775
- const tapScript = CSVMultisigTapscript.decode(script);
776
- paths.push(tapScript);
777
- } else if (ConditionCSVMultisigTapscript.isScriptValid(script) === true) {
778
- const tapScript = ConditionCSVMultisigTapscript.decode(script);
779
- paths.push(tapScript);
780
- }
781
- } catch (e) {
782
- console.debug("Failed to decode script", e);
783
- }
784
- }
785
- return paths;
786
- }
787
- };
788
- function getSequence(tapLeafScript) {
789
- let sequence = void 0;
790
- try {
791
- const scriptWithLeafVersion = tapLeafScript[1];
792
- const script = scriptWithLeafVersion.subarray(0, scriptWithLeafVersion.length - 1);
793
- try {
794
- const params = CSVMultisigTapscript.decode(script).params;
795
- sequence = timelockToSequence(params.timelock);
796
- } catch {
797
- const params = CLTVMultisigTapscript.decode(script).params;
798
- sequence = Number(params.absoluteTimelock);
799
- }
800
- } catch {
801
- }
802
- return sequence;
803
- }
804
-
805
- // src/contracts/constants.ts
806
- var DEFAULT_PAGE_SIZE = 500;
807
- var SCRIPT_QUERY_CHUNK_SIZE = 32;
808
-
809
- // src/wallet/vtxo.ts
810
- var EXPIRY_MIN_PLAUSIBLE_MS = Date.UTC(2025, 0, 1);
811
- async function resolveTimeHeight(provider) {
812
- const timestamp = /* @__PURE__ */ new Date();
813
- if (!provider) return { timestamp };
814
- try {
815
- const tip = await provider.getChainTip();
816
- return { timestamp, height: tip.height };
817
- } catch (e) {
818
- console.warn("Failed to fetch chain tip; height-based expiry will not be evaluated", e);
819
- return { timestamp };
820
- }
821
- }
822
- function parseWireExpiry(raw) {
823
- if (raw === null || raw === void 0 || raw === "") return {};
824
- const n = Number(raw);
825
- if (!Number.isFinite(n) || n <= 0) return {};
826
- const ms = n * 1e3;
827
- if (ms >= EXPIRY_MIN_PLAUSIBLE_MS) return { expiresAt: new Date(ms) };
828
- return { expiresAtHeight: n };
829
- }
830
- function toBatchExpiry(c) {
831
- if (c.expiresAt !== void 0) return c.expiresAt.getTime();
832
- if (c.expiresAtHeight !== void 0) return c.expiresAtHeight * 1e3;
833
- return void 0;
834
- }
835
- function parseLegacyExpiry(batchExpiry) {
836
- if (batchExpiry === void 0 || batchExpiry <= 0) return {};
837
- if (batchExpiry >= EXPIRY_MIN_PLAUSIBLE_MS) return { expiresAt: new Date(batchExpiry) };
838
- return { expiresAtHeight: batchExpiry / 1e3 };
839
- }
840
- function toVirtualStatus(c) {
841
- return {
842
- // Precedence is load-bearing: consumers bucket on this label, so any other order silently
843
- // moves VTXOs between buckets.
844
- state: c.isSpent ? "spent" : c.isSwept ? "swept" : c.isPreconfirmed ? "preconfirmed" : "settled",
845
- commitmentTxIds: c.commitmentTxIds,
846
- batchExpiry: toBatchExpiry(c)
847
- };
848
- }
849
- function normalizeVtxo(v) {
850
- const state = v.virtualStatus?.state;
851
- const canonicalExpiry = v.expiresAt !== void 0 || v.expiresAtHeight !== void 0;
852
- const expiry = canonicalExpiry ? (
853
- // Coerce: a backend that persists through JSON hands back an ISO string, which typechecks
854
- // as `Date` but returns NaN from `.getTime()` — comparing false against everything.
855
- {
856
- expiresAt: v.expiresAt === void 0 ? void 0 : new Date(v.expiresAt),
857
- expiresAtHeight: v.expiresAtHeight
858
- }
859
- ) : parseLegacyExpiry(v.virtualStatus?.batchExpiry);
860
- const isSpent = v.isSpent ?? state === "spent";
861
- const isSwept = v.isSwept ?? state === "swept";
862
- const isPreconfirmed = v.isPreconfirmed ?? state === "preconfirmed";
863
- const commitmentTxIds = v.commitmentTxIds ?? v.virtualStatus?.commitmentTxIds ?? [];
864
- return {
865
- ...v,
866
- isSpent,
867
- isSwept,
868
- isPreconfirmed,
869
- spentBy: v.spentBy ?? "",
870
- commitmentTxIds,
871
- ...expiry,
872
- virtualStatus: v.virtualStatus ?? toVirtualStatus({ isSpent, isSwept, isPreconfirmed, commitmentTxIds, ...expiry })
873
- };
874
- }
875
- function convertVtxo(vtxo) {
876
- const expiry = parseWireExpiry(vtxo.expiresAt);
877
- const facts = {
878
- isSpent: vtxo.isSpent,
879
- isSwept: vtxo.isSwept,
880
- isPreconfirmed: vtxo.isPreconfirmed,
881
- commitmentTxIds: vtxo.commitmentTxids,
882
- ...expiry
883
- };
884
- return {
885
- txid: vtxo.outpoint.txid,
886
- vout: vtxo.outpoint.vout,
887
- value: Number(vtxo.amount),
888
- status: {
889
- confirmed: !vtxo.isSwept && !vtxo.isPreconfirmed,
890
- isLeaf: !vtxo.isPreconfirmed
891
- },
892
- ...facts,
893
- virtualStatus: toVirtualStatus(facts),
894
- spentBy: vtxo.spentBy ?? "",
895
- settledBy: vtxo.settledBy,
896
- arkTxId: vtxo.arkTxid,
897
- createdAt: new Date(Number(vtxo.createdAt) * 1e3),
898
- isUnrolled: vtxo.isUnrolled,
899
- script: vtxo.script,
900
- assets: vtxo.assets?.map((a) => ({
901
- assetId: a.assetId,
902
- amount: BigInt(a.amount)
903
- }))
904
- };
905
- }
906
- async function getNormalizedVtxos(provider, opts) {
907
- const { vtxos, page } = await provider.getVtxos(opts);
908
- return { vtxos: vtxos.map(normalizeVtxo), page };
909
- }
910
- async function getAllNormalizedVtxos(provider, scripts, opts = {}) {
911
- const { pageSize = DEFAULT_PAGE_SIZE, ...filters } = opts;
912
- const all = [];
913
- for (let i = 0; i < scripts.length; i += SCRIPT_QUERY_CHUNK_SIZE) {
914
- const chunk = scripts.slice(i, i + SCRIPT_QUERY_CHUNK_SIZE);
915
- let pageIndex = 0;
916
- let hasMore = true;
917
- while (hasMore) {
918
- const { vtxos, page } = await getNormalizedVtxos(provider, {
919
- ...filters,
920
- scripts: chunk,
921
- pageIndex,
922
- pageSize
923
- });
924
- all.push(...vtxos);
925
- hasMore = page ? vtxos.length === pageSize : false;
926
- pageIndex++;
927
- if (hasMore) await new Promise((r) => setTimeout(r, 500));
928
- }
929
- }
930
- return all;
931
- }
932
- function hasTerminalSpend(vtxo) {
933
- const n = normalizeVtxo(vtxo);
934
- return !!n.isSpent || !!n.spentBy || !!n.settledBy;
935
- }
936
- function isPastExpiry(vtxo, now) {
937
- const n = normalizeVtxo(vtxo);
938
- if (n.expiresAt !== void 0 && now.timestamp.getTime() >= n.expiresAt.getTime()) return true;
939
- return n.expiresAtHeight !== void 0 && now.height !== void 0 && now.height >= n.expiresAtHeight;
940
- }
941
- function canSpendOffchain(vtxo, now) {
942
- const n = normalizeVtxo(vtxo);
943
- return !hasTerminalSpend(n) && !(n.isSwept || isPastExpiry(n, now));
944
- }
945
- function canRecoverOnchain(vtxo, now) {
946
- const n = normalizeVtxo(vtxo);
947
- return !hasTerminalSpend(n) && (n.isSwept || isPastExpiry(n, now));
948
- }
949
- function toOffchainInputFeeParams(vtxo) {
950
- const batchExpiry = toBatchExpiry(vtxo);
951
- return {
952
- amount: BigInt(vtxo.value),
953
- type: vtxo.isSwept ? "recoverable" : "vtxo",
954
- weight: 0,
955
- birth: vtxo.createdAt,
956
- expiry: batchExpiry ? new Date(batchExpiry) : void 0
957
- };
958
- }
959
- function isVirtualCoin(input) {
960
- return typeof input === "object" && input !== null && typeof input.script === "string";
961
- }
962
- function isSpendable(vtxo) {
963
- return !hasTerminalSpend(vtxo);
964
- }
965
- function isRecoverable(vtxo) {
966
- const n = normalizeVtxo(vtxo);
967
- return n.isSwept && !hasTerminalSpend(n);
968
- }
969
- function isExpired(vtxo) {
970
- const n = normalizeVtxo(vtxo);
971
- return n.isSwept || n.expiresAt !== void 0 && n.expiresAt.getTime() <= Date.now();
972
- }
973
-
974
- export { ArkAddress, CLTVMultisigTapscript, CSVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, DEFAULT_ARKADE_SERVER_URL, DEFAULT_NETWORK, DEFAULT_NETWORK_NAME, DEFAULT_PAGE_SIZE, MultisigTapscript, SCRIPT_QUERY_CHUNK_SIZE, TapTreeCoder, VtxoScript, assembleBtcdTaprootTree, canRecoverOnchain, canSpendOffchain, convertVtxo, decodeTapscript, getAllNormalizedVtxos, getNetwork, getNormalizedVtxos, getSequence, hasTerminalSpend, isExpired, isPastExpiry, isRecoverable, isSpendable, isVirtualCoin, networks, normalizeVtxo, parseLegacyExpiry, resolveTimeHeight, scriptFromTapLeafScript, sequenceToTimelock, timelockToSequence, toBatchExpiry, toOffchainInputFeeParams, toVirtualStatus };
975
- //# sourceMappingURL=chunk-EFNLTS6Q.js.map
976
- //# sourceMappingURL=chunk-EFNLTS6Q.js.map