@arkade-os/sdk 0.4.46 → 0.4.47

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 (83) 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-C9ognsOV.d.cts → ark-CoJgwTi_.d.cts} +26 -2
  8. package/dist/{ark-C9ognsOV.d.ts → ark-CoJgwTi_.d.ts} +26 -2
  9. package/dist/{asyncStorageTaskQueue-CmBYVlxw.d.cts → asyncStorageTaskQueue-Dowyo59a.d.cts} +2 -2
  10. package/dist/{asyncStorageTaskQueue-BAKZ5cS5.d.ts → asyncStorageTaskQueue-Z3aFoXCl.d.ts} +2 -2
  11. package/dist/{chunk-R2SVAM5Q.js → chunk-3N5I6GT6.js} +3 -3
  12. package/dist/{chunk-R2SVAM5Q.js.map → chunk-3N5I6GT6.js.map} +1 -1
  13. package/dist/{chunk-JTCQ6QXQ.js → chunk-AJQ4AOT3.js} +4 -4
  14. package/dist/{chunk-JTCQ6QXQ.js.map → chunk-AJQ4AOT3.js.map} +1 -1
  15. package/dist/{chunk-FWG4TSPN.js → chunk-C7TXXTMS.js} +4 -5
  16. package/dist/chunk-C7TXXTMS.js.map +1 -0
  17. package/dist/{chunk-CWJ7ZCP7.js → chunk-CDDWXBEM.js} +87 -16
  18. package/dist/chunk-CDDWXBEM.js.map +1 -0
  19. package/dist/{chunk-7IYIFMF4.cjs → chunk-HHV5FPC6.cjs} +94 -20
  20. package/dist/chunk-HHV5FPC6.cjs.map +1 -0
  21. package/dist/{chunk-SOXGAA52.cjs → chunk-JAYOXOLT.cjs} +14 -14
  22. package/dist/{chunk-SOXGAA52.cjs.map → chunk-JAYOXOLT.cjs.map} +1 -1
  23. package/dist/{chunk-MQB5H4X5.cjs → chunk-L5ND2FJJ.cjs} +4 -5
  24. package/dist/chunk-L5ND2FJJ.cjs.map +1 -0
  25. package/dist/{chunk-P6VBP3CT.js → chunk-OCS5S3L3.js} +1010 -98
  26. package/dist/chunk-OCS5S3L3.js.map +1 -0
  27. package/dist/chunk-RQSA7ADZ.cjs +2286 -0
  28. package/dist/chunk-RQSA7ADZ.cjs.map +1 -0
  29. package/dist/{chunk-6TQJOD72.cjs → chunk-VE67GMGM.cjs} +7 -7
  30. package/dist/{chunk-6TQJOD72.cjs.map → chunk-VE67GMGM.cjs.map} +1 -1
  31. package/dist/{chunk-D46YDM36.cjs → chunk-WTTLIFS7.cjs} +1207 -285
  32. package/dist/chunk-WTTLIFS7.cjs.map +1 -0
  33. package/dist/chunk-XN3554FT.js +2244 -0
  34. package/dist/chunk-XN3554FT.js.map +1 -0
  35. package/dist/contracts/handlers/index.cjs +11 -7
  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-aOd5qINr.d.ts → delegate-CuaDqqQi.d.ts} +1 -1
  40. package/dist/{delegate-DVEgyRwI.d.cts → delegate-Dl87_zMA.d.cts} +1 -1
  41. package/dist/index-BC_G0VTh.d.cts +512 -0
  42. package/dist/index-CKwpZEpw.d.ts +512 -0
  43. package/dist/index.cjs +213 -161
  44. package/dist/index.d.cts +3097 -2090
  45. package/dist/index.d.ts +3097 -2090
  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-B48-V-Pb.d.ts → taskRunner-Dz-TI4Rb.d.ts} +2 -2
  56. package/dist/{taskRunner-nNecmQ2C.d.cts → taskRunner-Dz47k0lp.d.cts} +2 -2
  57. package/dist/wallet/expo/background.cjs +14 -14
  58. package/dist/wallet/expo/background.d.cts +3 -3
  59. package/dist/wallet/expo/background.d.ts +3 -3
  60. package/dist/wallet/expo/background.js +6 -6
  61. package/dist/wallet/expo/index.cjs +14 -14
  62. package/dist/wallet/expo/index.d.cts +4 -4
  63. package/dist/wallet/expo/index.d.ts +4 -4
  64. package/dist/wallet/expo/index.js +5 -5
  65. package/dist/{wallet-BUg3D4WJ.d.cts → wallet-Oxz_wLxo.d.cts} +13 -3
  66. package/dist/{wallet-DM0oShTu.d.ts → wallet-x7egmXq6.d.ts} +13 -3
  67. package/dist/worker/expo/index.cjs +9 -9
  68. package/dist/worker/expo/index.d.cts +4 -4
  69. package/dist/worker/expo/index.d.ts +4 -4
  70. package/dist/worker/expo/index.js +5 -5
  71. package/package.json +1 -1
  72. package/dist/chunk-4KXOCVXP.cjs +0 -973
  73. package/dist/chunk-4KXOCVXP.cjs.map +0 -1
  74. package/dist/chunk-7IYIFMF4.cjs.map +0 -1
  75. package/dist/chunk-CWJ7ZCP7.js.map +0 -1
  76. package/dist/chunk-D46YDM36.cjs.map +0 -1
  77. package/dist/chunk-FWG4TSPN.js.map +0 -1
  78. package/dist/chunk-MQB5H4X5.cjs.map +0 -1
  79. package/dist/chunk-P6VBP3CT.js.map +0 -1
  80. package/dist/chunk-QKC2T54O.js +0 -960
  81. package/dist/chunk-QKC2T54O.js.map +0 -1
  82. package/dist/index-CPzL4tqg.d.ts +0 -259
  83. package/dist/index-D8vmtWWO.d.cts +0 -259
@@ -0,0 +1,2286 @@
1
+ 'use strict';
2
+
3
+ var chunkL5ND2FJJ_cjs = require('./chunk-L5ND2FJJ.cjs');
4
+ var chunk5BLDMQED_cjs = require('./chunk-5BLDMQED.cjs');
5
+ var base = require('@scure/base');
6
+ var descriptorsScure = require('@bitcoinerlab/descriptors-scure');
7
+ var btcSigner = require('@scure/btc-signer');
8
+ var secp256k1_js = require('@noble/curves/secp256k1.js');
9
+ var utils_js = require('@noble/curves/utils.js');
10
+
11
+ // src/contracts/handlers/registry.ts
12
+ var ContractHandlerRegistry = class {
13
+ handlers = /* @__PURE__ */ new Map();
14
+ /**
15
+ * Register a contract handler.
16
+ *
17
+ * @param handler - The handler to register
18
+ * @throws If a handler for this type is already registered
19
+ */
20
+ register(handler) {
21
+ if (this.handlers.has(handler.type)) {
22
+ throw new Error(`Contract handler for type '${handler.type}' is already registered`);
23
+ }
24
+ this.handlers.set(handler.type, handler);
25
+ }
26
+ /**
27
+ * Get a handler by type.
28
+ *
29
+ * @param type - The contract type
30
+ * @returns The handler, or undefined if not found
31
+ */
32
+ get(type) {
33
+ return this.handlers.get(type);
34
+ }
35
+ /**
36
+ * Get a handler by type, throwing if not found.
37
+ *
38
+ * @param type - The contract type
39
+ * @returns The handler
40
+ * @throws If no handler is registered for this type
41
+ */
42
+ getOrThrow(type) {
43
+ const handler = this.get(type);
44
+ if (!handler) {
45
+ throw new Error(`No contract handler registered for type '${type}'`);
46
+ }
47
+ return handler;
48
+ }
49
+ /**
50
+ * Check if a handler is registered.
51
+ *
52
+ * @param type - The contract type
53
+ */
54
+ has(type) {
55
+ return this.handlers.has(type);
56
+ }
57
+ /**
58
+ * Get all registered types.
59
+ */
60
+ getRegisteredTypes() {
61
+ return Array.from(this.handlers.keys());
62
+ }
63
+ /**
64
+ * Unregister a handler (mainly for testing).
65
+ */
66
+ unregister(type) {
67
+ return this.handlers.delete(type);
68
+ }
69
+ /**
70
+ * Clear all handlers (mainly for testing).
71
+ */
72
+ clear() {
73
+ this.handlers.clear();
74
+ }
75
+ };
76
+ var contractHandlers = new ContractHandlerRegistry();
77
+ exports.DefaultVtxo = void 0;
78
+ ((DefaultVtxo2) => {
79
+ class Script3 extends chunkL5ND2FJJ_cjs.VtxoScript {
80
+ /** Create the default virtual output script with one forfeit path and one exit path. */
81
+ constructor(options) {
82
+ const { pubKey, serverPubKey, csvTimelock } = options;
83
+ const forfeitScript = chunkL5ND2FJJ_cjs.MultisigTapscript.encode({
84
+ pubkeys: [pubKey, serverPubKey]
85
+ }).script;
86
+ const exitScript = chunkL5ND2FJJ_cjs.CSVMultisigTapscript.encode({
87
+ timelock: csvTimelock,
88
+ pubkeys: [pubKey]
89
+ }).script;
90
+ super([forfeitScript, exitScript]);
91
+ this.options = options;
92
+ this.forfeitScript = base.hex.encode(forfeitScript);
93
+ this.exitScript = base.hex.encode(exitScript);
94
+ }
95
+ options;
96
+ static DEFAULT_TIMELOCK = {
97
+ value: 144n,
98
+ type: "blocks"
99
+ };
100
+ // 1 day in blocks
101
+ forfeitScript;
102
+ exitScript;
103
+ /** Return the forfeit tapleaf script. */
104
+ forfeit() {
105
+ return this.findLeaf(this.forfeitScript);
106
+ }
107
+ /** Return the unilateral exit tapleaf script. */
108
+ exit() {
109
+ return this.findLeaf(this.exitScript);
110
+ }
111
+ }
112
+ DefaultVtxo2.Script = Script3;
113
+ })(exports.DefaultVtxo || (exports.DefaultVtxo = {}));
114
+ function isMainnetDescriptor(descriptor) {
115
+ return !descriptor.includes("tpub");
116
+ }
117
+ function descriptorIsOurs(candidate, ourDescriptor, ourXOnlyPubkey) {
118
+ if (!isDescriptor(candidate)) return false;
119
+ try {
120
+ const candidateInfo = descriptorsScure.expand({
121
+ descriptor: candidate,
122
+ network: isMainnetDescriptor(candidate) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet
123
+ }).expansionMap?.["@0"];
124
+ if (!candidateInfo) return false;
125
+ if (candidateInfo.bip32) {
126
+ const ourBip32 = descriptorsScure.expand({
127
+ descriptor: ourDescriptor,
128
+ network: isMainnetDescriptor(ourDescriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet
129
+ }).expansionMap?.["@0"]?.bip32;
130
+ if (!ourBip32) return false;
131
+ return ourBip32.toBase58() === candidateInfo.bip32.toBase58();
132
+ }
133
+ if (candidateInfo.pubkey) {
134
+ const candidatePub = candidateInfo.pubkey.length === 33 ? candidateInfo.pubkey.subarray(1) : candidateInfo.pubkey;
135
+ if (candidatePub.length !== ourXOnlyPubkey.length) return false;
136
+ return base.hex.encode(candidatePub) === base.hex.encode(ourXOnlyPubkey);
137
+ }
138
+ return false;
139
+ } catch {
140
+ return false;
141
+ }
142
+ }
143
+ function isDescriptor(value) {
144
+ if (typeof value !== "string") return false;
145
+ if (!value.startsWith("tr(") || !value.endsWith(")")) return false;
146
+ return value.length > "tr()".length;
147
+ }
148
+ function normalizeToDescriptor(value) {
149
+ if (typeof value !== "string" || value.length === 0) {
150
+ throw new Error("normalizeToDescriptor: expected a non-empty string value");
151
+ }
152
+ if (isDescriptor(value)) {
153
+ return value;
154
+ }
155
+ return `tr(${value})`;
156
+ }
157
+ function extractPubKey(descriptor) {
158
+ if (!isDescriptor(descriptor)) {
159
+ return descriptor;
160
+ }
161
+ const network = isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
162
+ const expansion = descriptorsScure.expand({ descriptor, network });
163
+ if (!expansion.expansionMap) {
164
+ throw new Error("Cannot extract pubkey from descriptor: expansion failed.");
165
+ }
166
+ const key = expansion.expansionMap["@0"];
167
+ if (key?.bip32) {
168
+ throw new Error(
169
+ "Cannot extract pubkey from HD descriptor without derivation. Use DescriptorProvider to derive the key from the xpub."
170
+ );
171
+ }
172
+ if (!key?.pubkey) {
173
+ throw new Error("Cannot extract pubkey from descriptor: no key found.");
174
+ }
175
+ return base.hex.encode(key.pubkey);
176
+ }
177
+ function deriveDescriptorLeafPubKey(descriptor) {
178
+ const network = isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
179
+ let expansion;
180
+ try {
181
+ expansion = descriptorsScure.expand({ descriptor, network });
182
+ } catch (e) {
183
+ throw new Error(
184
+ `Cannot derive leaf pubkey from descriptor (length=${descriptor.length}): ensure it is materialized (no wildcard) and parsable.`,
185
+ { cause: e }
186
+ );
187
+ }
188
+ const key = expansion.expansionMap?.["@0"];
189
+ if (!key?.pubkey) {
190
+ throw new Error(
191
+ `Cannot derive leaf pubkey from descriptor (length=${descriptor.length}): parsed but no '@0' pubkey in the expansion map.`
192
+ );
193
+ }
194
+ return key.pubkey;
195
+ }
196
+
197
+ // src/contracts/constants.ts
198
+ var DEFAULT_PAGE_SIZE = 500;
199
+
200
+ // src/contracts/handlers/helpers.ts
201
+ function extractRawPubKey(value) {
202
+ if (!isDescriptor(value)) {
203
+ return value.toLowerCase();
204
+ }
205
+ try {
206
+ return extractPubKey(value).toLowerCase();
207
+ } catch {
208
+ return void 0;
209
+ }
210
+ }
211
+ function resolveRole(contract, context) {
212
+ if (context.role === "sender" || context.role === "receiver") {
213
+ return context.role;
214
+ }
215
+ const senderKey = contract.params.sender ? extractRawPubKey(contract.params.sender) : void 0;
216
+ const receiverKey = contract.params.receiver ? extractRawPubKey(contract.params.receiver) : void 0;
217
+ const matchRole = (rawWalletKey) => {
218
+ if (!rawWalletKey) return void 0;
219
+ if (senderKey && rawWalletKey === senderKey) {
220
+ return "sender";
221
+ }
222
+ if (receiverKey && rawWalletKey === receiverKey) {
223
+ return "receiver";
224
+ }
225
+ return void 0;
226
+ };
227
+ if (context.walletDescriptor) {
228
+ const walletDescriptorKey = extractRawPubKey(context.walletDescriptor);
229
+ const matchedRole = matchRole(walletDescriptorKey);
230
+ if (matchedRole) {
231
+ return matchedRole;
232
+ }
233
+ if (!walletDescriptorKey && context.walletPubKey) {
234
+ return matchRole(extractRawPubKey(context.walletPubKey));
235
+ }
236
+ return void 0;
237
+ }
238
+ if (context.walletPubKey) {
239
+ return matchRole(extractRawPubKey(context.walletPubKey));
240
+ }
241
+ return void 0;
242
+ }
243
+ var CLTV_HEIGHT_THRESHOLD = 500000000n;
244
+ function isCltvSatisfied(context, locktime) {
245
+ if (locktime < CLTV_HEIGHT_THRESHOLD) {
246
+ if (context.blockHeight === void 0) return false;
247
+ return BigInt(context.blockHeight) >= locktime;
248
+ }
249
+ const currentTimeSec = BigInt(Math.floor(context.currentTime / 1e3));
250
+ return currentTimeSec >= locktime;
251
+ }
252
+ function isCsvSpendable(context, sequence) {
253
+ if (sequence === void 0) return true;
254
+ if (!context.vtxo) return false;
255
+ const timelock = chunkL5ND2FJJ_cjs.sequenceToTimelock(sequence);
256
+ if (timelock.type === "blocks") {
257
+ if (context.blockHeight === void 0 || context.vtxo.status.block_height === void 0) {
258
+ return false;
259
+ }
260
+ return context.blockHeight - context.vtxo.status.block_height >= Number(timelock.value);
261
+ }
262
+ if (timelock.type === "seconds") {
263
+ const blockTime = context.vtxo.status.block_time;
264
+ if (blockTime === void 0) return false;
265
+ return context.currentTime / 1e3 - blockTime >= Number(timelock.value);
266
+ }
267
+ return false;
268
+ }
269
+ async function detectUsedScripts(indexerProvider, scriptHexes) {
270
+ const used = /* @__PURE__ */ new Set();
271
+ if (scriptHexes.length === 0) return used;
272
+ const remaining = new Set(scriptHexes);
273
+ let pageIndex = 0;
274
+ let hasMore = true;
275
+ while (hasMore && remaining.size > 0) {
276
+ const { vtxos, page } = await indexerProvider.getVtxos({
277
+ scripts: scriptHexes,
278
+ pageIndex,
279
+ pageSize: DEFAULT_PAGE_SIZE
280
+ });
281
+ for (const vtxo of vtxos) {
282
+ if (remaining.delete(vtxo.script)) used.add(vtxo.script);
283
+ }
284
+ hasMore = page ? vtxos.length === DEFAULT_PAGE_SIZE : false;
285
+ pageIndex++;
286
+ }
287
+ return used;
288
+ }
289
+
290
+ // src/contracts/metadata.ts
291
+ var WALLET_RECEIVE_SOURCE = "wallet-receive";
292
+
293
+ // src/contracts/handlers/default.ts
294
+ function extractPubKeyBytes(value) {
295
+ return base.hex.decode(extractPubKey(normalizeToDescriptor(value)));
296
+ }
297
+ var DefaultContractHandler = {
298
+ type: "default",
299
+ createScript(params) {
300
+ const typed = this.deserializeParams(params);
301
+ return new exports.DefaultVtxo.Script(typed);
302
+ },
303
+ serializeParams(params) {
304
+ return {
305
+ pubKey: base.hex.encode(params.pubKey),
306
+ serverPubKey: base.hex.encode(params.serverPubKey),
307
+ csvTimelock: chunkL5ND2FJJ_cjs.timelockToSequence(params.csvTimelock).toString()
308
+ };
309
+ },
310
+ deserializeParams(params) {
311
+ const csvTimelock = params.csvTimelock !== void 0 && params.csvTimelock !== "" ? chunkL5ND2FJJ_cjs.sequenceToTimelock(Number(params.csvTimelock)) : exports.DefaultVtxo.Script.DEFAULT_TIMELOCK;
312
+ return {
313
+ pubKey: extractPubKeyBytes(params.pubKey),
314
+ serverPubKey: extractPubKeyBytes(params.serverPubKey),
315
+ csvTimelock
316
+ };
317
+ },
318
+ selectPath(script, contract, context) {
319
+ if (context.collaborative) {
320
+ return { leaf: script.forfeit() };
321
+ }
322
+ const sequence = contract.params.csvTimelock ? Number(contract.params.csvTimelock) : void 0;
323
+ if (!isCsvSpendable(context, sequence)) {
324
+ return null;
325
+ }
326
+ return {
327
+ leaf: script.exit(),
328
+ sequence
329
+ };
330
+ },
331
+ getAllSpendingPaths(script, contract, context) {
332
+ const paths = [];
333
+ if (context.collaborative) {
334
+ paths.push({ leaf: script.forfeit() });
335
+ }
336
+ const exitPath = { leaf: script.exit() };
337
+ if (contract.params.csvTimelock) {
338
+ exitPath.sequence = Number(contract.params.csvTimelock);
339
+ }
340
+ paths.push(exitPath);
341
+ return paths;
342
+ },
343
+ getSpendablePaths(script, contract, context) {
344
+ const paths = [];
345
+ if (context.collaborative) {
346
+ paths.push({ leaf: script.forfeit() });
347
+ }
348
+ const exitSequence = contract.params.csvTimelock ? Number(contract.params.csvTimelock) : void 0;
349
+ if (isCsvSpendable(context, exitSequence)) {
350
+ const exitPath = { leaf: script.exit() };
351
+ if (exitSequence !== void 0) {
352
+ exitPath.sequence = exitSequence;
353
+ }
354
+ paths.push(exitPath);
355
+ }
356
+ return paths;
357
+ },
358
+ async discoverAt(index, descriptor, deps) {
359
+ const pubKey = deriveDescriptorLeafPubKey(descriptor);
360
+ const signers = [deps.serverPubKey, ...deps.deprecatedSignerPubKeys ?? []];
361
+ const seen = /* @__PURE__ */ new Set();
362
+ const candidates = [];
363
+ for (const serverPubKey of signers) {
364
+ for (const csvTimelock of deps.csvTimelocks) {
365
+ const script = new exports.DefaultVtxo.Script({
366
+ pubKey,
367
+ serverPubKey,
368
+ csvTimelock
369
+ });
370
+ const scriptHex = base.hex.encode(script.pkScript);
371
+ if (seen.has(scriptHex)) continue;
372
+ seen.add(scriptHex);
373
+ candidates.push({ serverPubKey, csvTimelock, script, scriptHex });
374
+ }
375
+ }
376
+ const used = await detectUsedScripts(
377
+ deps.indexerProvider,
378
+ candidates.map((c) => c.scriptHex)
379
+ );
380
+ const out = [];
381
+ for (const c of candidates) {
382
+ if (!used.has(c.scriptHex)) continue;
383
+ out.push({
384
+ type: "default",
385
+ params: {
386
+ pubKey: base.hex.encode(pubKey),
387
+ serverPubKey: base.hex.encode(c.serverPubKey),
388
+ csvTimelock: chunkL5ND2FJJ_cjs.timelockToSequence(c.csvTimelock).toString()
389
+ },
390
+ script: c.scriptHex,
391
+ address: c.script.address(deps.network.hrp, c.serverPubKey).encode(),
392
+ ...index > 0 ? {
393
+ metadata: {
394
+ source: WALLET_RECEIVE_SOURCE,
395
+ signingDescriptor: descriptor
396
+ }
397
+ } : {}
398
+ });
399
+ }
400
+ return out;
401
+ }
402
+ };
403
+ exports.DelegateVtxo = void 0;
404
+ ((DelegateVtxo2) => {
405
+ class Script3 extends chunkL5ND2FJJ_cjs.VtxoScript {
406
+ /** Create a delegated virtual output script with forfeit, exit, and delegate paths. */
407
+ constructor(options) {
408
+ const defaultVtxo = new exports.DefaultVtxo.Script(options);
409
+ const { delegatePubKey, pubKey, serverPubKey } = options;
410
+ const delegateScript = chunkL5ND2FJJ_cjs.MultisigTapscript.encode({
411
+ pubkeys: [pubKey, delegatePubKey, serverPubKey]
412
+ }).script;
413
+ super([...defaultVtxo.scripts, delegateScript]);
414
+ this.options = options;
415
+ this.defaultVtxo = defaultVtxo;
416
+ this.delegateScript = base.hex.encode(delegateScript);
417
+ }
418
+ options;
419
+ defaultVtxo;
420
+ delegateScript;
421
+ /** Return the forfeit tapleaf script. */
422
+ forfeit() {
423
+ return this.findLeaf(this.defaultVtxo.forfeitScript);
424
+ }
425
+ /** Return the unilateral exit tapleaf script. */
426
+ exit() {
427
+ return this.findLeaf(this.defaultVtxo.exitScript);
428
+ }
429
+ /** Return the delegate tapleaf script. */
430
+ delegate() {
431
+ return this.findLeaf(this.delegateScript);
432
+ }
433
+ }
434
+ DelegateVtxo2.Script = Script3;
435
+ })(exports.DelegateVtxo || (exports.DelegateVtxo = {}));
436
+
437
+ // src/contracts/handlers/delegate.ts
438
+ var DelegateContractHandler = {
439
+ type: "delegate",
440
+ createScript(params) {
441
+ const typed = this.deserializeParams(params);
442
+ return new exports.DelegateVtxo.Script(typed);
443
+ },
444
+ serializeParams(params) {
445
+ return {
446
+ pubKey: base.hex.encode(params.pubKey),
447
+ serverPubKey: base.hex.encode(params.serverPubKey),
448
+ delegatePubKey: base.hex.encode(params.delegatePubKey),
449
+ csvTimelock: chunkL5ND2FJJ_cjs.timelockToSequence(params.csvTimelock).toString()
450
+ };
451
+ },
452
+ deserializeParams(params) {
453
+ const csvTimelock = chunkL5ND2FJJ_cjs.sequenceToTimelock(Number(params.csvTimelock));
454
+ return {
455
+ pubKey: base.hex.decode(params.pubKey),
456
+ serverPubKey: base.hex.decode(params.serverPubKey),
457
+ delegatePubKey: base.hex.decode(params.delegatePubKey),
458
+ csvTimelock
459
+ };
460
+ },
461
+ selectPath(script, contract, context) {
462
+ if (context.collaborative) {
463
+ return { leaf: script.forfeit() };
464
+ }
465
+ const sequence = contract.params.csvTimelock ? Number(contract.params.csvTimelock) : void 0;
466
+ if (!isCsvSpendable(context, sequence)) {
467
+ return null;
468
+ }
469
+ return {
470
+ leaf: script.exit(),
471
+ sequence
472
+ };
473
+ },
474
+ getAllSpendingPaths(script, contract, context) {
475
+ const paths = [];
476
+ if (context.collaborative) {
477
+ paths.push({ leaf: script.forfeit() });
478
+ }
479
+ const exitPath = { leaf: script.exit() };
480
+ if (contract.params.csvTimelock) {
481
+ exitPath.sequence = Number(contract.params.csvTimelock);
482
+ }
483
+ paths.push(exitPath);
484
+ if (context.collaborative) {
485
+ paths.push({ leaf: script.delegate() });
486
+ }
487
+ return paths;
488
+ },
489
+ getSpendablePaths(script, contract, context) {
490
+ const paths = [];
491
+ if (context.collaborative) {
492
+ paths.push({ leaf: script.forfeit() });
493
+ }
494
+ const exitSequence = contract.params.csvTimelock ? Number(contract.params.csvTimelock) : void 0;
495
+ if (isCsvSpendable(context, exitSequence)) {
496
+ const exitPath = { leaf: script.exit() };
497
+ if (exitSequence !== void 0) {
498
+ exitPath.sequence = exitSequence;
499
+ }
500
+ paths.push(exitPath);
501
+ }
502
+ return paths;
503
+ },
504
+ async discoverAt(index, descriptor, deps) {
505
+ if (!deps.delegatePubKey) return [];
506
+ const pubKey = deriveDescriptorLeafPubKey(descriptor);
507
+ const signers = [deps.serverPubKey, ...deps.deprecatedSignerPubKeys ?? []];
508
+ const seen = /* @__PURE__ */ new Set();
509
+ const candidates = [];
510
+ for (const serverPubKey of signers) {
511
+ for (const csvTimelock of deps.csvTimelocks) {
512
+ const script = new exports.DelegateVtxo.Script({
513
+ pubKey,
514
+ serverPubKey,
515
+ delegatePubKey: deps.delegatePubKey,
516
+ csvTimelock
517
+ });
518
+ const scriptHex = base.hex.encode(script.pkScript);
519
+ if (seen.has(scriptHex)) continue;
520
+ seen.add(scriptHex);
521
+ candidates.push({ serverPubKey, csvTimelock, script, scriptHex });
522
+ }
523
+ }
524
+ const used = await detectUsedScripts(
525
+ deps.indexerProvider,
526
+ candidates.map((c) => c.scriptHex)
527
+ );
528
+ const out = [];
529
+ for (const c of candidates) {
530
+ if (!used.has(c.scriptHex)) continue;
531
+ out.push({
532
+ type: "delegate",
533
+ params: {
534
+ pubKey: base.hex.encode(pubKey),
535
+ serverPubKey: base.hex.encode(c.serverPubKey),
536
+ delegatePubKey: base.hex.encode(deps.delegatePubKey),
537
+ csvTimelock: chunkL5ND2FJJ_cjs.timelockToSequence(c.csvTimelock).toString()
538
+ },
539
+ script: c.scriptHex,
540
+ address: c.script.address(deps.network.hrp, c.serverPubKey).encode(),
541
+ ...index > 0 ? {
542
+ metadata: {
543
+ source: WALLET_RECEIVE_SOURCE,
544
+ signingDescriptor: descriptor
545
+ }
546
+ } : {}
547
+ });
548
+ }
549
+ return out;
550
+ }
551
+ };
552
+ exports.VHTLC = void 0;
553
+ ((VHTLC2) => {
554
+ class Script3 extends chunkL5ND2FJJ_cjs.VtxoScript {
555
+ /** Create a VHTLC script from the supplied participant keys, hash, and timelocks. */
556
+ constructor(options) {
557
+ validateOptions(options);
558
+ const {
559
+ sender,
560
+ receiver,
561
+ server,
562
+ preimageHash,
563
+ refundLocktime,
564
+ unilateralClaimDelay,
565
+ unilateralRefundDelay,
566
+ unilateralRefundWithoutReceiverDelay
567
+ } = options;
568
+ const conditionScript = preimageConditionScript(preimageHash);
569
+ const claimScript = chunkL5ND2FJJ_cjs.ConditionMultisigTapscript.encode({
570
+ conditionScript,
571
+ pubkeys: [receiver, server]
572
+ }).script;
573
+ const refundScript = chunkL5ND2FJJ_cjs.MultisigTapscript.encode({
574
+ pubkeys: [sender, receiver, server]
575
+ }).script;
576
+ const refundWithoutReceiverScript = chunkL5ND2FJJ_cjs.CLTVMultisigTapscript.encode({
577
+ absoluteTimelock: refundLocktime,
578
+ pubkeys: [sender, server]
579
+ }).script;
580
+ const unilateralClaimScript = chunkL5ND2FJJ_cjs.ConditionCSVMultisigTapscript.encode({
581
+ conditionScript,
582
+ timelock: unilateralClaimDelay,
583
+ pubkeys: [receiver]
584
+ }).script;
585
+ const unilateralRefundScript = chunkL5ND2FJJ_cjs.CSVMultisigTapscript.encode({
586
+ timelock: unilateralRefundDelay,
587
+ pubkeys: [sender, receiver]
588
+ }).script;
589
+ const unilateralRefundWithoutReceiverScript = chunkL5ND2FJJ_cjs.CSVMultisigTapscript.encode({
590
+ timelock: unilateralRefundWithoutReceiverDelay,
591
+ pubkeys: [sender]
592
+ }).script;
593
+ super([
594
+ claimScript,
595
+ refundScript,
596
+ refundWithoutReceiverScript,
597
+ unilateralClaimScript,
598
+ unilateralRefundScript,
599
+ unilateralRefundWithoutReceiverScript
600
+ ]);
601
+ this.options = options;
602
+ this.claimScript = base.hex.encode(claimScript);
603
+ this.refundScript = base.hex.encode(refundScript);
604
+ this.refundWithoutReceiverScript = base.hex.encode(refundWithoutReceiverScript);
605
+ this.unilateralClaimScript = base.hex.encode(unilateralClaimScript);
606
+ this.unilateralRefundScript = base.hex.encode(unilateralRefundScript);
607
+ this.unilateralRefundWithoutReceiverScript = base.hex.encode(
608
+ unilateralRefundWithoutReceiverScript
609
+ );
610
+ }
611
+ options;
612
+ claimScript;
613
+ refundScript;
614
+ refundWithoutReceiverScript;
615
+ unilateralClaimScript;
616
+ unilateralRefundScript;
617
+ unilateralRefundWithoutReceiverScript;
618
+ /** Return the collaborative claim tapleaf script. */
619
+ claim() {
620
+ return this.findLeaf(this.claimScript);
621
+ }
622
+ /** Return the collaborative refund tapleaf script. */
623
+ refund() {
624
+ return this.findLeaf(this.refundScript);
625
+ }
626
+ /** Return the refund-without-receiver tapleaf script. */
627
+ refundWithoutReceiver() {
628
+ return this.findLeaf(this.refundWithoutReceiverScript);
629
+ }
630
+ /** Return the unilateral claim tapleaf script. */
631
+ unilateralClaim() {
632
+ return this.findLeaf(this.unilateralClaimScript);
633
+ }
634
+ /** Return the unilateral refund tapleaf script. */
635
+ unilateralRefund() {
636
+ return this.findLeaf(this.unilateralRefundScript);
637
+ }
638
+ /** Return the unilateral refund-without-receiver tapleaf script. */
639
+ unilateralRefundWithoutReceiver() {
640
+ return this.findLeaf(this.unilateralRefundWithoutReceiverScript);
641
+ }
642
+ }
643
+ VHTLC2.Script = Script3;
644
+ function validateOptions(options) {
645
+ const {
646
+ sender,
647
+ receiver,
648
+ server,
649
+ preimageHash,
650
+ refundLocktime,
651
+ unilateralClaimDelay,
652
+ unilateralRefundDelay,
653
+ unilateralRefundWithoutReceiverDelay
654
+ } = options;
655
+ if (!preimageHash || preimageHash.length !== 20) {
656
+ throw new Error("preimage hash must be 20 bytes");
657
+ }
658
+ if (!receiver || receiver.length !== 32) {
659
+ throw new Error("Invalid public key length (receiver)");
660
+ }
661
+ if (!sender || sender.length !== 32) {
662
+ throw new Error("Invalid public key length (sender)");
663
+ }
664
+ if (!server || server.length !== 32) {
665
+ throw new Error("Invalid public key length (server)");
666
+ }
667
+ if (typeof refundLocktime !== "bigint" || refundLocktime <= 0n) {
668
+ throw new Error("refund locktime must be greater than 0");
669
+ }
670
+ if (!unilateralClaimDelay || typeof unilateralClaimDelay.value !== "bigint" || unilateralClaimDelay.value <= 0n) {
671
+ throw new Error("unilateral claim delay must greater than 0");
672
+ }
673
+ if (unilateralClaimDelay.type === "seconds" && unilateralClaimDelay.value % 512n !== 0n) {
674
+ throw new Error("seconds timelock must be multiple of 512");
675
+ }
676
+ if (unilateralClaimDelay.type === "seconds" && unilateralClaimDelay.value < 512n) {
677
+ throw new Error("seconds timelock must be greater or equal to 512");
678
+ }
679
+ if (!unilateralRefundDelay || typeof unilateralRefundDelay.value !== "bigint" || unilateralRefundDelay.value <= 0n) {
680
+ throw new Error("unilateral refund delay must greater than 0");
681
+ }
682
+ if (unilateralRefundDelay.type === "seconds" && unilateralRefundDelay.value % 512n !== 0n) {
683
+ throw new Error("seconds timelock must be multiple of 512");
684
+ }
685
+ if (unilateralRefundDelay.type === "seconds" && unilateralRefundDelay.value < 512n) {
686
+ throw new Error("seconds timelock must be greater or equal to 512");
687
+ }
688
+ if (!unilateralRefundWithoutReceiverDelay || typeof unilateralRefundWithoutReceiverDelay.value !== "bigint" || unilateralRefundWithoutReceiverDelay.value <= 0n) {
689
+ throw new Error("unilateral refund without receiver delay must greater than 0");
690
+ }
691
+ if (unilateralRefundWithoutReceiverDelay.type === "seconds" && unilateralRefundWithoutReceiverDelay.value % 512n !== 0n) {
692
+ throw new Error("seconds timelock must be multiple of 512");
693
+ }
694
+ if (unilateralRefundWithoutReceiverDelay.type === "seconds" && unilateralRefundWithoutReceiverDelay.value < 512n) {
695
+ throw new Error("seconds timelock must be greater or equal to 512");
696
+ }
697
+ }
698
+ })(exports.VHTLC || (exports.VHTLC = {}));
699
+ function preimageConditionScript(preimageHash) {
700
+ return btcSigner.Script.encode(["HASH160", preimageHash, "EQUAL"]);
701
+ }
702
+
703
+ // src/contracts/handlers/vhtlc.ts
704
+ var VHTLCContractHandler = {
705
+ type: "vhtlc",
706
+ createScript(params) {
707
+ const typed = this.deserializeParams(params);
708
+ return new exports.VHTLC.Script(typed);
709
+ },
710
+ serializeParams(params) {
711
+ return {
712
+ sender: base.hex.encode(params.sender),
713
+ receiver: base.hex.encode(params.receiver),
714
+ server: base.hex.encode(params.server),
715
+ hash: base.hex.encode(params.preimageHash),
716
+ refundLocktime: params.refundLocktime.toString(),
717
+ claimDelay: chunkL5ND2FJJ_cjs.timelockToSequence(params.unilateralClaimDelay).toString(),
718
+ refundDelay: chunkL5ND2FJJ_cjs.timelockToSequence(params.unilateralRefundDelay).toString(),
719
+ refundNoReceiverDelay: chunkL5ND2FJJ_cjs.timelockToSequence(
720
+ params.unilateralRefundWithoutReceiverDelay
721
+ ).toString()
722
+ };
723
+ },
724
+ deserializeParams(params) {
725
+ return {
726
+ sender: base.hex.decode(params.sender),
727
+ receiver: base.hex.decode(params.receiver),
728
+ server: base.hex.decode(params.server),
729
+ preimageHash: base.hex.decode(params.hash),
730
+ refundLocktime: BigInt(params.refundLocktime),
731
+ unilateralClaimDelay: chunkL5ND2FJJ_cjs.sequenceToTimelock(Number(params.claimDelay)),
732
+ unilateralRefundDelay: chunkL5ND2FJJ_cjs.sequenceToTimelock(Number(params.refundDelay)),
733
+ unilateralRefundWithoutReceiverDelay: chunkL5ND2FJJ_cjs.sequenceToTimelock(
734
+ Number(params.refundNoReceiverDelay)
735
+ )
736
+ };
737
+ },
738
+ /**
739
+ * Select spending path based on context.
740
+ *
741
+ * Role is determined from `context.role` or by matching
742
+ * `context.walletDescriptor` (preferred) / `context.walletPubKey`
743
+ * against sender/receiver in contract params.
744
+ */
745
+ selectPath(script, contract, context) {
746
+ const role = resolveRole(contract, context);
747
+ const preimage = contract.params?.preimage;
748
+ const refundLocktime = BigInt(contract.params.refundLocktime);
749
+ if (!role) {
750
+ return null;
751
+ }
752
+ if (context.collaborative) {
753
+ if (role === "receiver" && preimage) {
754
+ return {
755
+ leaf: script.claim(),
756
+ extraWitness: [base.hex.decode(preimage)]
757
+ };
758
+ }
759
+ if (role === "sender" && isCltvSatisfied(context, refundLocktime)) {
760
+ return {
761
+ leaf: script.refundWithoutReceiver()
762
+ };
763
+ }
764
+ return null;
765
+ }
766
+ if (role === "receiver" && preimage) {
767
+ const sequence = Number(contract.params.claimDelay);
768
+ if (!isCsvSpendable(context, sequence)) return null;
769
+ return {
770
+ leaf: script.unilateralClaim(),
771
+ extraWitness: [base.hex.decode(preimage)],
772
+ sequence
773
+ };
774
+ }
775
+ if (role === "sender") {
776
+ const sequence = Number(contract.params.refundNoReceiverDelay);
777
+ if (!isCsvSpendable(context, sequence)) return null;
778
+ return {
779
+ leaf: script.unilateralRefundWithoutReceiver(),
780
+ sequence
781
+ };
782
+ }
783
+ return null;
784
+ },
785
+ /**
786
+ * Get all possible spending paths (no timelock checks).
787
+ *
788
+ * Role is determined from `context.role` or by matching
789
+ * `context.walletDescriptor` (preferred) / `context.walletPubKey`
790
+ * against sender/receiver in contract params.
791
+ */
792
+ getAllSpendingPaths(script, contract, context) {
793
+ const role = resolveRole(contract, context);
794
+ const paths = [];
795
+ if (!role) {
796
+ return paths;
797
+ }
798
+ const preimage = contract.params?.preimage;
799
+ if (context.collaborative) {
800
+ if (role === "receiver" && preimage) {
801
+ paths.push({
802
+ leaf: script.claim(),
803
+ extraWitness: [base.hex.decode(preimage)]
804
+ });
805
+ }
806
+ if (role === "sender") {
807
+ paths.push({
808
+ leaf: script.refundWithoutReceiver()
809
+ });
810
+ }
811
+ } else {
812
+ if (role === "receiver" && preimage) {
813
+ const sequence = Number(contract.params.claimDelay);
814
+ paths.push({
815
+ leaf: script.unilateralClaim(),
816
+ extraWitness: [base.hex.decode(preimage)],
817
+ sequence
818
+ });
819
+ }
820
+ if (role === "sender") {
821
+ const sequence = Number(contract.params.refundNoReceiverDelay);
822
+ paths.push({
823
+ leaf: script.unilateralRefundWithoutReceiver(),
824
+ sequence
825
+ });
826
+ }
827
+ }
828
+ return paths;
829
+ },
830
+ getSpendablePaths(script, contract, context) {
831
+ const role = resolveRole(contract, context);
832
+ const paths = [];
833
+ if (!role) {
834
+ return paths;
835
+ }
836
+ const preimage = contract.params?.preimage;
837
+ const refundLocktime = BigInt(contract.params.refundLocktime);
838
+ if (context.collaborative) {
839
+ if (role === "receiver" && preimage) {
840
+ paths.push({
841
+ leaf: script.claim(),
842
+ extraWitness: [base.hex.decode(preimage)]
843
+ });
844
+ }
845
+ if (role === "sender" && isCltvSatisfied(context, refundLocktime)) {
846
+ paths.push({
847
+ leaf: script.refundWithoutReceiver()
848
+ });
849
+ }
850
+ return paths;
851
+ }
852
+ if (role === "receiver" && preimage) {
853
+ const sequence = Number(contract.params.claimDelay);
854
+ if (isCsvSpendable(context, sequence)) {
855
+ paths.push({
856
+ leaf: script.unilateralClaim(),
857
+ extraWitness: [base.hex.decode(preimage)],
858
+ sequence
859
+ });
860
+ }
861
+ }
862
+ if (role === "sender") {
863
+ const sequence = Number(contract.params.refundNoReceiverDelay);
864
+ if (isCsvSpendable(context, sequence)) {
865
+ paths.push({
866
+ leaf: script.unilateralRefundWithoutReceiver(),
867
+ sequence
868
+ });
869
+ }
870
+ }
871
+ return paths;
872
+ }
873
+ };
874
+ var BoardingContractHandler = {
875
+ type: "boarding",
876
+ createScript(params) {
877
+ return DefaultContractHandler.createScript(params);
878
+ },
879
+ serializeParams(params) {
880
+ return DefaultContractHandler.serializeParams(params);
881
+ },
882
+ deserializeParams(params) {
883
+ return DefaultContractHandler.deserializeParams(params);
884
+ },
885
+ selectPath(script, contract, context) {
886
+ return DefaultContractHandler.selectPath(script, contract, context);
887
+ },
888
+ getAllSpendingPaths(script, contract, context) {
889
+ return DefaultContractHandler.getAllSpendingPaths(script, contract, context);
890
+ },
891
+ getSpendablePaths(script, contract, context) {
892
+ return DefaultContractHandler.getSpendablePaths(script, contract, context);
893
+ },
894
+ /**
895
+ * Probe the on-chain UTXO set for a boarding output at this HD index.
896
+ *
897
+ * Boarding's source of truth is the **current** on-chain coin set
898
+ * (`OnchainProvider.getCoins`), not the Ark indexer: a boarded (spent)
899
+ * boarding output becomes an L2 VTXO at the receive index, so the
900
+ * indexer probe already keeps the gap window open for it; only an
901
+ * *unspent* boarding output needs the on-chain probe (see plan §2).
902
+ *
903
+ * No-ops (returns `[]`) when boarding discovery is not plumbed — i.e.
904
+ * `deps.boardingTimelock` or `deps.onchainNetwork` is absent — so the
905
+ * scanner unit harness (which sets neither) is unaffected.
906
+ *
907
+ * Always emits `type: "boarding"`, even in the degenerate equal-delay case
908
+ * where the boarding script is byte-identical to a `default` script at this
909
+ * index (`boardingExitDelay === unilateralExitDelay`). The collision is no
910
+ * longer pre-judged in discovery; it is tolerated FIRST-WINS at the
911
+ * persistence layer ({@link ContractManager.upsertContract}). `deps.csvTimelocks`
912
+ * is intentionally not read here.
913
+ */
914
+ async discoverAt(index, descriptor, deps) {
915
+ if (!deps.boardingTimelock || !deps.onchainNetwork) return [];
916
+ const pubKey = deriveDescriptorLeafPubKey(descriptor);
917
+ const script = new exports.DefaultVtxo.Script({
918
+ pubKey,
919
+ serverPubKey: deps.serverPubKey,
920
+ csvTimelock: deps.boardingTimelock
921
+ });
922
+ const onchainAddress = script.onchainAddress(deps.onchainNetwork);
923
+ const coins = await deps.onchainProvider.getCoins(onchainAddress);
924
+ if (coins.length === 0) return [];
925
+ const scriptHex = base.hex.encode(script.pkScript);
926
+ const boardingSeq = chunkL5ND2FJJ_cjs.timelockToSequence(deps.boardingTimelock);
927
+ return [
928
+ {
929
+ type: "boarding",
930
+ params: {
931
+ pubKey: base.hex.encode(pubKey),
932
+ serverPubKey: base.hex.encode(deps.serverPubKey),
933
+ csvTimelock: boardingSeq.toString()
934
+ },
935
+ script: scriptHex,
936
+ // The persisted row's `address` is the *Ark* address (not the
937
+ // on-chain P2TR), matching the row registered at init so the
938
+ // ContractWatcher keeps monitoring the same L2 script and the
939
+ // VTXO repository bucket lines up (plan §6-I.4). The P2TR is
940
+ // recomputed from params only for the `getCoins` probe.
941
+ address: script.address(deps.network.hrp, deps.serverPubKey).encode(),
942
+ // Tag rotated rows (index > 0) so boot resolution can find the
943
+ // newest boarding address and descriptor-aware signing can
944
+ // recover the per-index key (plan §6-II/§6-III.3). The index-0
945
+ // baseline stays untagged, matching `default`/`delegate`.
946
+ ...index > 0 ? {
947
+ metadata: {
948
+ source: WALLET_RECEIVE_SOURCE,
949
+ signingDescriptor: descriptor
950
+ }
951
+ } : {}
952
+ }
953
+ ];
954
+ }
955
+ };
956
+ function equalBytes(a, b) {
957
+ if (a.length !== b.length)
958
+ return false;
959
+ for (let i = 0; i < a.length; i++)
960
+ if (a[i] !== b[i])
961
+ return false;
962
+ return true;
963
+ }
964
+ function isBytes(a) {
965
+ return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
966
+ }
967
+ var createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
968
+ function isPlainObject(obj) {
969
+ return Object.prototype.toString.call(obj) === "[object Object]";
970
+ }
971
+ function isNum(num) {
972
+ return Number.isSafeInteger(num);
973
+ }
974
+ var Bitset = {
975
+ BITS: 32,
976
+ FULL_MASK: -1 >>> 0,
977
+ // 1<<32 will overflow
978
+ len: (len) => Math.ceil(len / 32),
979
+ create: (len) => new Uint32Array(Bitset.len(len)),
980
+ clean: (bs) => bs.fill(0),
981
+ debug: (bs) => Array.from(bs).map((i) => (i >>> 0).toString(2).padStart(32, "0")),
982
+ checkLen: (bs, len) => {
983
+ if (Bitset.len(len) === bs.length)
984
+ return;
985
+ throw new Error(`wrong length=${bs.length}. Expected: ${Bitset.len(len)}`);
986
+ },
987
+ chunkLen: (bsLen, pos, len) => {
988
+ if (pos < 0)
989
+ throw new Error(`wrong pos=${pos}`);
990
+ if (pos + len > bsLen)
991
+ throw new Error(`wrong range=${pos}/${len} of ${bsLen}`);
992
+ },
993
+ set: (bs, chunk, value, allowRewrite = true) => {
994
+ if (!allowRewrite && (bs[chunk] & value) !== 0)
995
+ return false;
996
+ bs[chunk] |= value;
997
+ return true;
998
+ },
999
+ pos: (pos, i) => ({
1000
+ chunk: Math.floor((pos + i) / 32),
1001
+ mask: 1 << 32 - (pos + i) % 32 - 1
1002
+ }),
1003
+ indices: (bs, len, invert = false) => {
1004
+ Bitset.checkLen(bs, len);
1005
+ const { FULL_MASK, BITS } = Bitset;
1006
+ const left = BITS - len % BITS;
1007
+ const lastMask = left ? FULL_MASK >>> left << left : FULL_MASK;
1008
+ const res = [];
1009
+ for (let i = 0; i < bs.length; i++) {
1010
+ let c = bs[i];
1011
+ if (invert)
1012
+ c = ~c;
1013
+ if (i === bs.length - 1)
1014
+ c &= lastMask;
1015
+ if (c === 0)
1016
+ continue;
1017
+ for (let j = 0; j < BITS; j++) {
1018
+ const m = 1 << BITS - j - 1;
1019
+ if (c & m)
1020
+ res.push(i * BITS + j);
1021
+ }
1022
+ }
1023
+ return res;
1024
+ },
1025
+ range: (arr) => {
1026
+ const res = [];
1027
+ let cur;
1028
+ for (const i of arr) {
1029
+ if (cur === void 0 || i !== cur.pos + cur.length)
1030
+ res.push(cur = { pos: i, length: 1 });
1031
+ else
1032
+ cur.length += 1;
1033
+ }
1034
+ return res;
1035
+ },
1036
+ rangeDebug: (bs, len, invert = false) => `[${Bitset.range(Bitset.indices(bs, len, invert)).map((i) => `(${i.pos}/${i.length})`).join(", ")}]`,
1037
+ setRange: (bs, bsLen, pos, len, allowRewrite = true) => {
1038
+ Bitset.chunkLen(bsLen, pos, len);
1039
+ const { FULL_MASK, BITS } = Bitset;
1040
+ const first = pos % BITS ? Math.floor(pos / BITS) : void 0;
1041
+ const lastPos = pos + len;
1042
+ const last = lastPos % BITS ? Math.floor(lastPos / BITS) : void 0;
1043
+ if (first !== void 0 && first === last)
1044
+ return Bitset.set(bs, first, FULL_MASK >>> BITS - len << BITS - len - pos, allowRewrite);
1045
+ if (first !== void 0) {
1046
+ if (!Bitset.set(bs, first, FULL_MASK >>> pos % BITS, allowRewrite))
1047
+ return false;
1048
+ }
1049
+ const start = first !== void 0 ? first + 1 : pos / BITS;
1050
+ const end = last !== void 0 ? last : lastPos / BITS;
1051
+ for (let i = start; i < end; i++)
1052
+ if (!Bitset.set(bs, i, FULL_MASK, allowRewrite))
1053
+ return false;
1054
+ if (last !== void 0 && first !== last) {
1055
+ if (!Bitset.set(bs, last, FULL_MASK << BITS - lastPos % BITS, allowRewrite))
1056
+ return false;
1057
+ }
1058
+ return true;
1059
+ }
1060
+ };
1061
+ var Path = {
1062
+ /**
1063
+ * Internal method for handling stack of paths (debug, errors, dynamic fields via path)
1064
+ * This is looks ugly (callback), but allows us to force stack cleaning by construction (.pop always after function).
1065
+ * Also, this makes impossible:
1066
+ * - pushing field when stack is empty
1067
+ * - pushing field inside of field (real bug)
1068
+ * NOTE: we don't want to do '.pop' on error!
1069
+ */
1070
+ pushObj: (stack, obj, objFn) => {
1071
+ const last = { obj };
1072
+ stack.push(last);
1073
+ objFn((field, fieldFn) => {
1074
+ last.field = field;
1075
+ fieldFn();
1076
+ last.field = void 0;
1077
+ });
1078
+ stack.pop();
1079
+ },
1080
+ path: (stack) => {
1081
+ const res = [];
1082
+ for (const i of stack)
1083
+ if (i.field !== void 0)
1084
+ res.push(i.field);
1085
+ return res.join("/");
1086
+ },
1087
+ err: (name, stack, msg) => {
1088
+ const err = new Error(`${name}(${Path.path(stack)}): ${typeof msg === "string" ? msg : msg.message}`);
1089
+ if (msg instanceof Error && msg.stack)
1090
+ err.stack = msg.stack;
1091
+ return err;
1092
+ },
1093
+ resolve: (stack, path) => {
1094
+ const parts = path.split("/");
1095
+ const objPath = stack.map((i2) => i2.obj);
1096
+ let i = 0;
1097
+ for (; i < parts.length; i++) {
1098
+ if (parts[i] === "..")
1099
+ objPath.pop();
1100
+ else
1101
+ break;
1102
+ }
1103
+ let cur = objPath.pop();
1104
+ for (; i < parts.length; i++) {
1105
+ if (!cur || cur[parts[i]] === void 0)
1106
+ return void 0;
1107
+ cur = cur[parts[i]];
1108
+ }
1109
+ return cur;
1110
+ }
1111
+ };
1112
+ var _Reader = class __Reader {
1113
+ pos = 0;
1114
+ data;
1115
+ opts;
1116
+ stack;
1117
+ parent;
1118
+ parentOffset;
1119
+ bitBuf = 0;
1120
+ bitPos = 0;
1121
+ bs;
1122
+ // bitset
1123
+ view;
1124
+ constructor(data, opts = {}, stack = [], parent = void 0, parentOffset = 0) {
1125
+ this.data = data;
1126
+ this.opts = opts;
1127
+ this.stack = stack;
1128
+ this.parent = parent;
1129
+ this.parentOffset = parentOffset;
1130
+ this.view = createView(data);
1131
+ }
1132
+ /** Internal method for pointers. */
1133
+ _enablePointers() {
1134
+ if (this.parent)
1135
+ return this.parent._enablePointers();
1136
+ if (this.bs)
1137
+ return;
1138
+ this.bs = Bitset.create(this.data.length);
1139
+ Bitset.setRange(this.bs, this.data.length, 0, this.pos, this.opts.allowMultipleReads);
1140
+ }
1141
+ markBytesBS(pos, len) {
1142
+ if (this.parent)
1143
+ return this.parent.markBytesBS(this.parentOffset + pos, len);
1144
+ if (!len)
1145
+ return true;
1146
+ if (!this.bs)
1147
+ return true;
1148
+ return Bitset.setRange(this.bs, this.data.length, pos, len, false);
1149
+ }
1150
+ markBytes(len) {
1151
+ const pos = this.pos;
1152
+ this.pos += len;
1153
+ const res = this.markBytesBS(pos, len);
1154
+ if (!this.opts.allowMultipleReads && !res)
1155
+ throw this.err(`multiple read pos=${this.pos} len=${len}`);
1156
+ return res;
1157
+ }
1158
+ pushObj(obj, objFn) {
1159
+ return Path.pushObj(this.stack, obj, objFn);
1160
+ }
1161
+ readView(n, fn) {
1162
+ if (!Number.isFinite(n))
1163
+ throw this.err(`readView: wrong length=${n}`);
1164
+ if (this.pos + n > this.data.length)
1165
+ throw this.err("readView: Unexpected end of buffer");
1166
+ const res = fn(this.view, this.pos);
1167
+ this.markBytes(n);
1168
+ return res;
1169
+ }
1170
+ // read bytes by absolute offset
1171
+ absBytes(n) {
1172
+ if (n > this.data.length)
1173
+ throw new Error("Unexpected end of buffer");
1174
+ return this.data.subarray(n);
1175
+ }
1176
+ finish() {
1177
+ if (this.opts.allowUnreadBytes)
1178
+ return;
1179
+ if (this.bitPos) {
1180
+ throw this.err(`${this.bitPos} bits left after unpack: ${base.hex.encode(this.data.slice(this.pos))}`);
1181
+ }
1182
+ if (this.bs && !this.parent) {
1183
+ const notRead = Bitset.indices(this.bs, this.data.length, true);
1184
+ if (notRead.length) {
1185
+ const formatted = Bitset.range(notRead).map(({ pos, length }) => `(${pos}/${length})[${base.hex.encode(this.data.subarray(pos, pos + length))}]`).join(", ");
1186
+ throw this.err(`unread byte ranges: ${formatted} (total=${this.data.length})`);
1187
+ } else
1188
+ return;
1189
+ }
1190
+ if (!this.isEnd()) {
1191
+ throw this.err(`${this.leftBytes} bytes ${this.bitPos} bits left after unpack: ${base.hex.encode(this.data.slice(this.pos))}`);
1192
+ }
1193
+ }
1194
+ // User methods
1195
+ err(msg) {
1196
+ return Path.err("Reader", this.stack, msg);
1197
+ }
1198
+ offsetReader(n) {
1199
+ if (n > this.data.length)
1200
+ throw this.err("offsetReader: Unexpected end of buffer");
1201
+ return new __Reader(this.absBytes(n), this.opts, this.stack, this, n);
1202
+ }
1203
+ bytes(n, peek = false) {
1204
+ if (this.bitPos)
1205
+ throw this.err("readBytes: bitPos not empty");
1206
+ if (!Number.isFinite(n))
1207
+ throw this.err(`readBytes: wrong length=${n}`);
1208
+ if (this.pos + n > this.data.length)
1209
+ throw this.err("readBytes: Unexpected end of buffer");
1210
+ const slice = this.data.subarray(this.pos, this.pos + n);
1211
+ if (!peek)
1212
+ this.markBytes(n);
1213
+ return slice;
1214
+ }
1215
+ byte(peek = false) {
1216
+ if (this.bitPos)
1217
+ throw this.err("readByte: bitPos not empty");
1218
+ if (this.pos + 1 > this.data.length)
1219
+ throw this.err("readBytes: Unexpected end of buffer");
1220
+ const data = this.data[this.pos];
1221
+ if (!peek)
1222
+ this.markBytes(1);
1223
+ return data;
1224
+ }
1225
+ get leftBytes() {
1226
+ return this.data.length - this.pos;
1227
+ }
1228
+ get totalBytes() {
1229
+ return this.data.length;
1230
+ }
1231
+ isEnd() {
1232
+ return this.pos >= this.data.length && !this.bitPos;
1233
+ }
1234
+ // bits are read in BE mode (left to right): (0b1000_0000).readBits(1) == 1
1235
+ bits(bits) {
1236
+ if (bits > 32)
1237
+ throw this.err("BitReader: cannot read more than 32 bits in single call");
1238
+ let out = 0;
1239
+ while (bits) {
1240
+ if (!this.bitPos) {
1241
+ this.bitBuf = this.byte();
1242
+ this.bitPos = 8;
1243
+ }
1244
+ const take = Math.min(bits, this.bitPos);
1245
+ this.bitPos -= take;
1246
+ out = out << take | this.bitBuf >> this.bitPos & 2 ** take - 1;
1247
+ this.bitBuf &= 2 ** this.bitPos - 1;
1248
+ bits -= take;
1249
+ }
1250
+ return out >>> 0;
1251
+ }
1252
+ find(needle, pos = this.pos) {
1253
+ if (!isBytes(needle))
1254
+ throw this.err(`find: needle is not bytes! ${needle}`);
1255
+ if (this.bitPos)
1256
+ throw this.err("findByte: bitPos not empty");
1257
+ if (!needle.length)
1258
+ throw this.err(`find: needle is empty`);
1259
+ for (let idx = pos; (idx = this.data.indexOf(needle[0], idx)) !== -1; idx++) {
1260
+ if (idx === -1)
1261
+ return;
1262
+ const leftBytes = this.data.length - idx;
1263
+ if (leftBytes < needle.length)
1264
+ return;
1265
+ if (equalBytes(needle, this.data.subarray(idx, idx + needle.length)))
1266
+ return idx;
1267
+ }
1268
+ return;
1269
+ }
1270
+ };
1271
+ var _Writer = class {
1272
+ pos = 0;
1273
+ stack;
1274
+ // We could have a single buffer here and re-alloc it with
1275
+ // x1.5-2 size each time it full, but it will be slower:
1276
+ // basic/encode bench: 395ns -> 560ns
1277
+ buffers = [];
1278
+ ptrs = [];
1279
+ bitBuf = 0;
1280
+ bitPos = 0;
1281
+ viewBuf = new Uint8Array(8);
1282
+ view;
1283
+ finished = false;
1284
+ constructor(stack = []) {
1285
+ this.stack = stack;
1286
+ this.view = createView(this.viewBuf);
1287
+ }
1288
+ pushObj(obj, objFn) {
1289
+ return Path.pushObj(this.stack, obj, objFn);
1290
+ }
1291
+ writeView(len, fn) {
1292
+ if (this.finished)
1293
+ throw this.err("buffer: finished");
1294
+ if (!isNum(len) || len > 8)
1295
+ throw new Error(`wrong writeView length=${len}`);
1296
+ fn(this.view);
1297
+ this.bytes(this.viewBuf.slice(0, len));
1298
+ this.viewBuf.fill(0);
1299
+ }
1300
+ // User methods
1301
+ err(msg) {
1302
+ if (this.finished)
1303
+ throw this.err("buffer: finished");
1304
+ return Path.err("Reader", this.stack, msg);
1305
+ }
1306
+ bytes(b) {
1307
+ if (this.finished)
1308
+ throw this.err("buffer: finished");
1309
+ if (this.bitPos)
1310
+ throw this.err("writeBytes: ends with non-empty bit buffer");
1311
+ this.buffers.push(b);
1312
+ this.pos += b.length;
1313
+ }
1314
+ byte(b) {
1315
+ if (this.finished)
1316
+ throw this.err("buffer: finished");
1317
+ if (this.bitPos)
1318
+ throw this.err("writeByte: ends with non-empty bit buffer");
1319
+ this.buffers.push(new Uint8Array([b]));
1320
+ this.pos++;
1321
+ }
1322
+ finish(clean = true) {
1323
+ if (this.finished)
1324
+ throw this.err("buffer: finished");
1325
+ if (this.bitPos)
1326
+ throw this.err("buffer: ends with non-empty bit buffer");
1327
+ const buffers = this.buffers.concat(this.ptrs.map((i) => i.buffer));
1328
+ const sum = buffers.map((b) => b.length).reduce((a, b) => a + b, 0);
1329
+ const buf = new Uint8Array(sum);
1330
+ for (let i = 0, pad = 0; i < buffers.length; i++) {
1331
+ const a = buffers[i];
1332
+ buf.set(a, pad);
1333
+ pad += a.length;
1334
+ }
1335
+ for (let pos = this.pos, i = 0; i < this.ptrs.length; i++) {
1336
+ const ptr = this.ptrs[i];
1337
+ buf.set(ptr.ptr.encode(pos), ptr.pos);
1338
+ pos += ptr.buffer.length;
1339
+ }
1340
+ if (clean) {
1341
+ this.buffers = [];
1342
+ for (const p of this.ptrs)
1343
+ p.buffer.fill(0);
1344
+ this.ptrs = [];
1345
+ this.finished = true;
1346
+ this.bitBuf = 0;
1347
+ }
1348
+ return buf;
1349
+ }
1350
+ bits(value, bits) {
1351
+ if (bits > 32)
1352
+ throw this.err("writeBits: cannot write more than 32 bits in single call");
1353
+ if (value >= 2 ** bits)
1354
+ throw this.err(`writeBits: value (${value}) >= 2**bits (${bits})`);
1355
+ while (bits) {
1356
+ const take = Math.min(bits, 8 - this.bitPos);
1357
+ this.bitBuf = this.bitBuf << take | value >> bits - take;
1358
+ this.bitPos += take;
1359
+ bits -= take;
1360
+ value &= 2 ** bits - 1;
1361
+ if (this.bitPos === 8) {
1362
+ this.bitPos = 0;
1363
+ this.buffers.push(new Uint8Array([this.bitBuf]));
1364
+ this.pos++;
1365
+ }
1366
+ }
1367
+ }
1368
+ };
1369
+ function _wrap(inner) {
1370
+ return {
1371
+ // NOTE: we cannot export validate here, since it is likely mistake.
1372
+ encodeStream: inner.encodeStream,
1373
+ decodeStream: inner.decodeStream,
1374
+ size: inner.size,
1375
+ encode: (value) => {
1376
+ const w = new _Writer();
1377
+ inner.encodeStream(w, value);
1378
+ return w.finish();
1379
+ },
1380
+ decode: (data, opts = {}) => {
1381
+ const r = new _Reader(data, opts);
1382
+ const res = inner.decodeStream(r);
1383
+ r.finish();
1384
+ return res;
1385
+ }
1386
+ };
1387
+ }
1388
+ function validate(inner, fn) {
1389
+ if (!isCoder(inner))
1390
+ throw new Error(`validate: invalid inner value ${inner}`);
1391
+ if (typeof fn !== "function")
1392
+ throw new Error("validate: fn should be function");
1393
+ return _wrap({
1394
+ size: inner.size,
1395
+ encodeStream: (w, value) => {
1396
+ let res;
1397
+ try {
1398
+ res = fn(value);
1399
+ } catch (e) {
1400
+ throw w.err(e);
1401
+ }
1402
+ inner.encodeStream(w, res);
1403
+ },
1404
+ decodeStream: (r) => {
1405
+ const res = inner.decodeStream(r);
1406
+ try {
1407
+ return fn(res);
1408
+ } catch (e) {
1409
+ throw r.err(e);
1410
+ }
1411
+ }
1412
+ });
1413
+ }
1414
+ var wrap = (inner) => {
1415
+ const res = _wrap(inner);
1416
+ return inner.validate ? validate(res, inner.validate) : res;
1417
+ };
1418
+ var isBaseCoder = (elm) => isPlainObject(elm) && typeof elm.decode === "function" && typeof elm.encode === "function";
1419
+ function isCoder(elm) {
1420
+ return isPlainObject(elm) && isBaseCoder(elm) && typeof elm.encodeStream === "function" && typeof elm.decodeStream === "function" && (elm.size === void 0 || isNum(elm.size));
1421
+ }
1422
+ var view = (len, opts) => wrap({
1423
+ size: len,
1424
+ encodeStream: (w, value) => w.writeView(len, (view2) => opts.write(view2, value)),
1425
+ decodeStream: (r) => r.readView(len, opts.read),
1426
+ validate: (value) => {
1427
+ if (typeof value !== "number")
1428
+ throw new Error(`viewCoder: expected number, got ${typeof value}`);
1429
+ if (opts.validate)
1430
+ opts.validate(value);
1431
+ return value;
1432
+ }
1433
+ });
1434
+ var intView = (len, signed, opts) => {
1435
+ const bits = len * 8;
1436
+ const maxVal = 2 ** bits;
1437
+ const validateUnsigned = (value) => {
1438
+ if (!isNum(value))
1439
+ throw new Error(`uintView: value is not safe integer: ${value}`);
1440
+ if (0 > value || value >= maxVal) {
1441
+ throw new Error(`uintView: value out of bounds. Expected 0 <= ${value} < ${maxVal}`);
1442
+ }
1443
+ };
1444
+ return view(len, {
1445
+ write: opts.write,
1446
+ read: opts.read,
1447
+ validate: validateUnsigned
1448
+ });
1449
+ };
1450
+ var U32LE = /* @__PURE__ */ intView(4, false, {
1451
+ read: (view2, pos) => view2.getUint32(pos, true),
1452
+ write: (view2, value) => view2.setUint32(0, value, true)
1453
+ });
1454
+ var U16LE = /* @__PURE__ */ intView(2, false, {
1455
+ read: (view2, pos) => view2.getUint16(pos, true),
1456
+ write: (view2, value) => view2.setUint16(0, value, true)
1457
+ });
1458
+ var U8 = /* @__PURE__ */ intView(1, false, {
1459
+ read: (view2, pos) => view2.getUint8(pos),
1460
+ write: (view2, value) => view2.setUint8(0, value)
1461
+ });
1462
+ var ARKADE_OP = {
1463
+ // Merkle Branch Verification (0xb3 — repurposed NOP4 slot)
1464
+ MERKLEBRANCHVERIFY: 179,
1465
+ // Digest (0xc3)
1466
+ DIGEST: 195,
1467
+ // SHA256 Streaming (0xc4-0xc6)
1468
+ SHA256INITIALIZE: 196,
1469
+ SHA256UPDATE: 197,
1470
+ SHA256FINALIZE: 198,
1471
+ // Input Introspection (0xc7-0xcb)
1472
+ INSPECTINPUTOUTPOINT: 199,
1473
+ INSPECTINPUTARKADESCRIPTHASH: 200,
1474
+ INSPECTINPUTVALUE: 201,
1475
+ INSPECTINPUTSCRIPTPUBKEY: 202,
1476
+ INSPECTINPUTSEQUENCE: 203,
1477
+ // Signatures (0xcc-0xcd)
1478
+ CHECKSIGFROMSTACK: 204,
1479
+ PUSHCURRENTINPUTINDEX: 205,
1480
+ // Input Arkade Witness Introspection (0xce)
1481
+ INSPECTINPUTARKADEWITNESSHASH: 206,
1482
+ // Output Introspection (0xcf, 0xd1)
1483
+ INSPECTOUTPUTVALUE: 207,
1484
+ INSPECTOUTPUTSCRIPTPUBKEY: 209,
1485
+ // Transaction Introspection (0xd2-0xd6)
1486
+ INSPECTVERSION: 210,
1487
+ INSPECTLOCKTIME: 211,
1488
+ INSPECTNUMINPUTS: 212,
1489
+ INSPECTNUMOUTPUTS: 213,
1490
+ TXWEIGHT: 214,
1491
+ // Byte/Number Conversion & Arithmetic (0xd7-0xda)
1492
+ NUM2BIN: 215,
1493
+ BIN2NUM: 216,
1494
+ REVERSEBYTES: 217,
1495
+ MODEXP: 218,
1496
+ // 0xdb-0xdf are unassigned (OP_UNKNOWN219-223)
1497
+ // EC Operations (0xe0-0xe2)
1498
+ ECADD: 224,
1499
+ ECMUL: 225,
1500
+ ECPAIRING: 226,
1501
+ // EC Operations (0xe3-0xe4)
1502
+ ECMULSCALARVERIFY: 227,
1503
+ TWEAKVERIFY: 228,
1504
+ // Asset Groups (0xe5-0xf2)
1505
+ INSPECTNUMASSETGROUPS: 229,
1506
+ INSPECTASSETGROUPASSETID: 230,
1507
+ INSPECTASSETGROUPCTRL: 231,
1508
+ FINDASSETGROUPBYASSETID: 232,
1509
+ INSPECTASSETGROUPMETADATAHASH: 233,
1510
+ INSPECTASSETGROUPNUM: 234,
1511
+ INSPECTASSETGROUP: 235,
1512
+ INSPECTASSETGROUPSUM: 236,
1513
+ INSPECTOUTASSETCOUNT: 237,
1514
+ INSPECTOUTASSETAT: 238,
1515
+ INSPECTOUTASSETLOOKUP: 239,
1516
+ INSPECTINASSETCOUNT: 240,
1517
+ INSPECTINASSETAT: 241,
1518
+ INSPECTINASSETLOOKUP: 242,
1519
+ // Transaction ID (0xf3)
1520
+ TXID: 243,
1521
+ // Packet Introspection (0xf4-0xf5) — added in emulator v0.0.1
1522
+ INSPECTPACKET: 244,
1523
+ INSPECTINPUTPACKET: 245,
1524
+ // Signature Hash (0xf6)
1525
+ SIGHASH: 246
1526
+ };
1527
+ var ARKADE_OPCODES = Object.values(ARKADE_OP);
1528
+ var ARKADE_OPCODE_NAMES = Object.fromEntries(
1529
+ Object.entries(ARKADE_OP).map(([name, value]) => [value, name])
1530
+ );
1531
+ var ARKADE_OPCODE_VALUES = Object.fromEntries(
1532
+ Object.entries(ARKADE_OPCODE_NAMES).map(([value, name]) => [name, Number(value)])
1533
+ );
1534
+ function buildBitcoinOpcodeNames() {
1535
+ const names = {};
1536
+ for (const [key, value] of Object.entries(btcSigner.OP)) {
1537
+ if (typeof value === "number") {
1538
+ const name = key.startsWith("OP_") ? key : `OP_${key}`;
1539
+ names[value] = name;
1540
+ }
1541
+ }
1542
+ names[0] = "OP_0";
1543
+ return names;
1544
+ }
1545
+ function buildBitcoinOpcodeValues() {
1546
+ const values = {};
1547
+ for (const [key, value] of Object.entries(btcSigner.OP)) {
1548
+ if (typeof value === "number") {
1549
+ const name = key.startsWith("OP_") ? key : `OP_${key}`;
1550
+ values[name] = value;
1551
+ values[key] = value;
1552
+ }
1553
+ }
1554
+ return values;
1555
+ }
1556
+ var BITCOIN_OPCODE_NAMES = buildBitcoinOpcodeNames();
1557
+ var BITCOIN_OPCODE_VALUES = buildBitcoinOpcodeValues();
1558
+ var OPCODE_NAMES = {
1559
+ ...BITCOIN_OPCODE_NAMES,
1560
+ // Add Arkade opcodes with OP_ prefix
1561
+ ...Object.fromEntries(
1562
+ Object.entries(ARKADE_OPCODE_NAMES).map(([value, name]) => [Number(value), `OP_${name}`])
1563
+ )
1564
+ };
1565
+ var OPCODE_VALUES = {
1566
+ ...BITCOIN_OPCODE_VALUES,
1567
+ // Add Arkade opcodes with and without OP_ prefix
1568
+ ...ARKADE_OPCODE_VALUES,
1569
+ ...Object.fromEntries(
1570
+ Object.entries(ARKADE_OPCODE_VALUES).map(([name, value]) => [`OP_${name}`, value])
1571
+ )
1572
+ };
1573
+ function getOpcodeName(value) {
1574
+ if (value >= 1 && value <= 75) {
1575
+ return `OP_DATA_${value}`;
1576
+ }
1577
+ return OPCODE_NAMES[value];
1578
+ }
1579
+ function getOpcodeValue(name) {
1580
+ const dataMatch = name.match(/^OP_DATA_(\d+)$/);
1581
+ if (dataMatch) {
1582
+ const n = parseInt(dataMatch[1], 10);
1583
+ if (n >= 1 && n <= 75) {
1584
+ return n;
1585
+ }
1586
+ return void 0;
1587
+ }
1588
+ return OPCODE_VALUES[name];
1589
+ }
1590
+
1591
+ // src/arkade/bignum.ts
1592
+ var bignum_exports = {};
1593
+ chunk5BLDMQED_cjs.__export(bignum_exports, {
1594
+ BIGNUM_MAX_BYTES: () => BIGNUM_MAX_BYTES,
1595
+ decode: () => decode,
1596
+ encode: () => encode
1597
+ });
1598
+ var BIGNUM_MAX_BYTES = 520;
1599
+ var codec = btcSigner.ScriptNum(
1600
+ BIGNUM_MAX_BYTES,
1601
+ /* forceMinimal */
1602
+ true
1603
+ );
1604
+ function encode(value) {
1605
+ const result = codec.encode(value);
1606
+ if (result.length > BIGNUM_MAX_BYTES) {
1607
+ throw new Error(`BigNum value exceeds 520 bytes (encoded to ${result.length} bytes)`);
1608
+ }
1609
+ return result;
1610
+ }
1611
+ function decode(value) {
1612
+ return codec.decode(value);
1613
+ }
1614
+
1615
+ // src/arkade/script.ts
1616
+ var ARKADE_OPS = { ...btcSigner.OP, ...ARKADE_OP };
1617
+ var ArkadeOPNames = {};
1618
+ for (const [k, v] of Object.entries(ARKADE_OPS)) {
1619
+ if (typeof v === "number") ArkadeOPNames[v] = k;
1620
+ }
1621
+ var ArkadeScript = wrap({
1622
+ encodeStream: (w, value) => {
1623
+ for (let o of value) {
1624
+ if (typeof o === "string") {
1625
+ const v = ARKADE_OPS[o];
1626
+ if (v === void 0) throw new Error(`Unknown opcode=${o}`);
1627
+ w.byte(v);
1628
+ continue;
1629
+ } else if (typeof o === "number" || typeof o === "bigint") {
1630
+ if (o === 0 || o === 0n) {
1631
+ w.byte(0);
1632
+ continue;
1633
+ } else if (o >= 1 && o <= 16) {
1634
+ w.byte(btcSigner.OP.OP_1 - 1 + Number(o));
1635
+ continue;
1636
+ } else if (o === -1 || o === -1n) {
1637
+ w.byte(btcSigner.OP["1NEGATE"]);
1638
+ continue;
1639
+ }
1640
+ const big = typeof o === "number" ? BigInt(o) : o;
1641
+ o = encode(big);
1642
+ }
1643
+ if (!(o instanceof Uint8Array)) throw new Error(`Wrong Script OP=${o} (${typeof o})`);
1644
+ const len = o.length;
1645
+ if (len < btcSigner.OP.PUSHDATA1) w.byte(len);
1646
+ else if (len <= 255) {
1647
+ w.byte(btcSigner.OP.PUSHDATA1);
1648
+ w.byte(len);
1649
+ } else if (len <= 65535) {
1650
+ w.byte(btcSigner.OP.PUSHDATA2);
1651
+ w.bytes(U16LE.encode(len));
1652
+ } else {
1653
+ w.byte(btcSigner.OP.PUSHDATA4);
1654
+ w.bytes(U32LE.encode(len));
1655
+ }
1656
+ w.bytes(o);
1657
+ }
1658
+ },
1659
+ decodeStream: (r) => {
1660
+ const out = [];
1661
+ while (!r.isEnd()) {
1662
+ const cur = r.byte();
1663
+ if (btcSigner.OP.OP_0 < cur && cur <= btcSigner.OP.PUSHDATA4) {
1664
+ let len;
1665
+ if (cur < btcSigner.OP.PUSHDATA1) len = cur;
1666
+ else if (cur === btcSigner.OP.PUSHDATA1) len = U8.decodeStream(r);
1667
+ else if (cur === btcSigner.OP.PUSHDATA2) len = U16LE.decodeStream(r);
1668
+ else if (cur === btcSigner.OP.PUSHDATA4) len = U32LE.decodeStream(r);
1669
+ else throw new Error("Should be not possible");
1670
+ out.push(r.bytes(len));
1671
+ } else if (cur === 0) {
1672
+ out.push(0);
1673
+ } else if (btcSigner.OP.OP_1 <= cur && cur <= btcSigner.OP.OP_16) {
1674
+ out.push(cur - (btcSigner.OP.OP_1 - 1));
1675
+ } else if (cur === btcSigner.OP["1NEGATE"]) {
1676
+ out.push(-1);
1677
+ } else {
1678
+ const op = ArkadeOPNames[cur];
1679
+ if (op === void 0) throw new Error(`Unknown opcode=${cur.toString(16)}`);
1680
+ out.push(op);
1681
+ }
1682
+ }
1683
+ return out;
1684
+ }
1685
+ });
1686
+ function toASM(script) {
1687
+ const parts = [];
1688
+ for (const op of script) {
1689
+ if (typeof op === "string") {
1690
+ const name = op.startsWith("OP_") ? op : `OP_${op}`;
1691
+ parts.push(name);
1692
+ } else if (typeof op === "number" || typeof op === "bigint") {
1693
+ if (op === 0 || op === 0n) {
1694
+ parts.push("OP_0");
1695
+ } else if (op >= 1 && op <= 16) {
1696
+ parts.push(`OP_${op}`);
1697
+ } else if (op === -1 || op === -1n) {
1698
+ parts.push("OP_1NEGATE");
1699
+ } else {
1700
+ parts.push(base.hex.encode(encode(BigInt(op))));
1701
+ }
1702
+ } else {
1703
+ parts.push(base.hex.encode(op));
1704
+ }
1705
+ }
1706
+ return parts.join(" ");
1707
+ }
1708
+ function fromASM(asm) {
1709
+ const tokens = asm.trim().split(/\s+/).filter(Boolean);
1710
+ const out = [];
1711
+ for (const token of tokens) {
1712
+ if (token === "OP_0" || token === "OP_FALSE") {
1713
+ out.push(0);
1714
+ continue;
1715
+ }
1716
+ if (token === "OP_TRUE") {
1717
+ out.push(1);
1718
+ continue;
1719
+ }
1720
+ const numMatch = token.match(/^OP_(\d+)$/);
1721
+ if (numMatch) {
1722
+ const n = parseInt(numMatch[1], 10);
1723
+ if (n >= 1 && n <= 16) {
1724
+ out.push(n);
1725
+ continue;
1726
+ }
1727
+ }
1728
+ let key;
1729
+ if (token.startsWith("OP_")) {
1730
+ key = token.slice(3);
1731
+ } else {
1732
+ key = token;
1733
+ }
1734
+ if (key in ARKADE_OPS) {
1735
+ out.push(key);
1736
+ continue;
1737
+ }
1738
+ if (/^[0-9a-fA-F]+$/.test(token) && token.length % 2 === 0) {
1739
+ try {
1740
+ out.push(base.hex.decode(token));
1741
+ continue;
1742
+ } catch {
1743
+ }
1744
+ }
1745
+ throw new Error(`Invalid ASM token: ${token}`);
1746
+ }
1747
+ return out;
1748
+ }
1749
+ function asmToBytes(asm) {
1750
+ return ArkadeScript.encode(fromASM(asm));
1751
+ }
1752
+ function bytesToASM(script) {
1753
+ return toASM(ArkadeScript.decode(script));
1754
+ }
1755
+ var TAG_SCRIPT = "ArkScriptHash";
1756
+ var TAG_WITNESS = "ArkWitnessHash";
1757
+ function arkadeScriptHash(script) {
1758
+ return secp256k1_js.schnorr.utils.taggedHash(TAG_SCRIPT, script);
1759
+ }
1760
+ function arkadeWitnessHash(witness) {
1761
+ if (witness.length === 0) {
1762
+ return new Uint8Array(32);
1763
+ }
1764
+ return secp256k1_js.schnorr.utils.taggedHash(TAG_WITNESS, witness);
1765
+ }
1766
+ function computeArkadeScriptPublicKey(pubKey, script) {
1767
+ const hash = arkadeScriptHash(script);
1768
+ const xOnly = pubKey.length === 33 ? pubKey.subarray(1) : pubKey;
1769
+ const point = secp256k1_js.schnorr.utils.lift_x(utils_js.bytesToNumberBE(xOnly));
1770
+ const scalar = utils_js.bytesToNumberBE(hash) % secp256k1_js.secp256k1.Point.CURVE().n;
1771
+ const tweak = secp256k1_js.secp256k1.Point.BASE.multiply(scalar);
1772
+ return secp256k1_js.schnorr.utils.pointToBytes(point.add(tweak));
1773
+ }
1774
+
1775
+ // src/arkade/program.ts
1776
+ var MinimalScriptNum = btcSigner.ScriptNum(void 0, true);
1777
+ var SUPPORTED_PROGRAM_VERSION = 0;
1778
+ function inputName(ref) {
1779
+ return typeof ref === "string" ? ref : ref.name;
1780
+ }
1781
+ function bindValue(bind, name) {
1782
+ const v = bind[name];
1783
+ if (v === void 0) throw new Error(`unbound parameter '${name}'`);
1784
+ return v;
1785
+ }
1786
+ function resolveTimelockValue(value, args) {
1787
+ if (typeof value === "bigint") return value;
1788
+ if (value.startsWith("$")) {
1789
+ const v = bindValue(args, value.slice(1));
1790
+ if (typeof v === "bigint" || typeof v === "number") return BigInt(v);
1791
+ throw new Error(`timelock value '${value}' must resolve to a number`);
1792
+ }
1793
+ throw new Error(
1794
+ `invalid timelock value '${value}' \u2014 expected a bigint or a '$param' reference`
1795
+ );
1796
+ }
1797
+ function resolveAsm(asm, bind) {
1798
+ const tokens = asm.map((t) => {
1799
+ if (typeof t === "string" && t.startsWith("$")) {
1800
+ return bindValue(bind, t.slice(1));
1801
+ }
1802
+ if (t === "<SELF>") {
1803
+ throw new Error(
1804
+ "<SELF> is not a placeholder; use INSPECTINPUTSCRIPTPUBKEY for continuation covenants"
1805
+ );
1806
+ }
1807
+ return t;
1808
+ });
1809
+ return ArkadeScript.encode(tokens);
1810
+ }
1811
+ function witnessRefToBytes(ref, callArgs, programArgs) {
1812
+ if (ref instanceof Uint8Array) return ref;
1813
+ if (typeof ref === "number" || typeof ref === "bigint") {
1814
+ return MinimalScriptNum.encode(BigInt(ref));
1815
+ }
1816
+ const v = ref.startsWith("$") ? bindValue(programArgs, ref.slice(1)) : bindValue(callArgs, ref);
1817
+ if (v instanceof Uint8Array) return v;
1818
+ return MinimalScriptNum.encode(BigInt(v));
1819
+ }
1820
+ function validateTapscript(seg) {
1821
+ if (!seg.signers || seg.signers.length === 0) {
1822
+ throw new Error("tapscript: at least one signer is required");
1823
+ }
1824
+ if (seg.asm !== void 0 && seg.cltv !== void 0) {
1825
+ throw new Error(
1826
+ "tapscript: `asm` and `cltv` conflict \u2014 arkd has no condition+CLTV closure"
1827
+ );
1828
+ }
1829
+ if (seg.csv !== void 0 && seg.cltv !== void 0) {
1830
+ throw new Error("tapscript: `csv` and `cltv` conflict \u2014 use at most one timelock");
1831
+ }
1832
+ for (const t of seg.asm ?? []) {
1833
+ if (typeof t === "string" && t in ARKADE_OP) {
1834
+ throw new Error(
1835
+ `tapscript: arkade opcode '${t}' is not enforceable on-chain \u2014 move it to arkadeScript`
1836
+ );
1837
+ }
1838
+ }
1839
+ }
1840
+ function collectParamRefs(program) {
1841
+ const refs = /* @__PURE__ */ new Set();
1842
+ const collect = (items) => {
1843
+ for (const t of items ?? []) {
1844
+ if (typeof t === "string" && t.startsWith("$")) refs.add(t.slice(1));
1845
+ }
1846
+ };
1847
+ for (const fn of Object.values(program.functions)) {
1848
+ const tap = fn.tapscript;
1849
+ collect(tap.signers);
1850
+ collect(tap.asm);
1851
+ collect(tap.witness);
1852
+ collect(tap.csv ? [tap.csv.value] : void 0);
1853
+ collect(tap.cltv !== void 0 ? [tap.cltv] : void 0);
1854
+ collect(fn.arkadeScript?.asm);
1855
+ collect(fn.arkadeScript?.witness);
1856
+ }
1857
+ return refs;
1858
+ }
1859
+ var TYPED_BYTE_LENGTHS = { pubkey: 32, sig: 64 };
1860
+ function validateParamValue(def, value) {
1861
+ if (def.type === "int") {
1862
+ if (typeof value !== "bigint" && typeof value !== "number") {
1863
+ throw new Error(`program parameter '${def.name}' expects an int, got bytes`);
1864
+ }
1865
+ return;
1866
+ }
1867
+ if (!(value instanceof Uint8Array)) {
1868
+ throw new Error(
1869
+ `program parameter '${def.name}' expects ${def.type} bytes, got ${typeof value}`
1870
+ );
1871
+ }
1872
+ const length = TYPED_BYTE_LENGTHS[def.type];
1873
+ if (length !== void 0 && value.length !== length) {
1874
+ throw new Error(
1875
+ `program parameter '${def.name}' expects a ${length}-byte ${def.type}, got ${value.length} bytes`
1876
+ );
1877
+ }
1878
+ }
1879
+ function validateProgram(program, args) {
1880
+ const params = program.params;
1881
+ if (!params || !params.some((p) => typeof p !== "string")) return;
1882
+ const declared = new Set(params.map(inputName));
1883
+ for (const name of declared) {
1884
+ if (args[name] === void 0) {
1885
+ throw new Error(`program parameter '${name}' is declared but not bound in args`);
1886
+ }
1887
+ }
1888
+ for (const ref of collectParamRefs(program)) {
1889
+ if (!declared.has(ref)) {
1890
+ throw new Error(`'$${ref}' is referenced but not declared in program params`);
1891
+ }
1892
+ }
1893
+ for (const p of params) {
1894
+ if (typeof p !== "string") validateParamValue(p, args[p.name]);
1895
+ }
1896
+ }
1897
+ function resolveSigner(ref, args) {
1898
+ if (ref instanceof Uint8Array) return ref;
1899
+ if (!ref.startsWith("$")) {
1900
+ throw new Error(`unknown signer reference '${ref}' \u2014 use '$${ref}'`);
1901
+ }
1902
+ const v = bindValue(args, ref.slice(1));
1903
+ if (!(v instanceof Uint8Array)) {
1904
+ throw new Error(`signer ${ref} must be a pubkey (bytes)`);
1905
+ }
1906
+ return v;
1907
+ }
1908
+ function encodeTapscriptSegment(seg, pubkeys, args) {
1909
+ if (seg.csv) {
1910
+ const timelock = { type: seg.csv.type, value: resolveTimelockValue(seg.csv.value, args) };
1911
+ if (seg.asm) {
1912
+ return chunkL5ND2FJJ_cjs.ConditionCSVMultisigTapscript.encode({
1913
+ conditionScript: resolveAsm(seg.asm, args),
1914
+ timelock,
1915
+ pubkeys
1916
+ });
1917
+ }
1918
+ return chunkL5ND2FJJ_cjs.CSVMultisigTapscript.encode({ timelock, pubkeys });
1919
+ }
1920
+ if (seg.cltv !== void 0) {
1921
+ return chunkL5ND2FJJ_cjs.CLTVMultisigTapscript.encode({
1922
+ absoluteTimelock: resolveTimelockValue(seg.cltv, args),
1923
+ pubkeys
1924
+ });
1925
+ }
1926
+ if (seg.asm) {
1927
+ return chunkL5ND2FJJ_cjs.ConditionMultisigTapscript.encode({
1928
+ conditionScript: resolveAsm(seg.asm, args),
1929
+ pubkeys
1930
+ });
1931
+ }
1932
+ return chunkL5ND2FJJ_cjs.MultisigTapscript.encode({ pubkeys });
1933
+ }
1934
+ function compileFunctions(program, args, keys) {
1935
+ if (program.version !== SUPPORTED_PROGRAM_VERSION) {
1936
+ throw new Error(
1937
+ `ArkadeContract: unsupported program version ${program.version} \u2014 this SDK supports version ${SUPPORTED_PROGRAM_VERSION}`
1938
+ );
1939
+ }
1940
+ const functions = program.functions;
1941
+ const names = Object.keys(functions);
1942
+ if (names.length === 0) {
1943
+ throw new Error("ArkadeContract: program has no functions");
1944
+ }
1945
+ validateProgram(program, args);
1946
+ const defs = names.map((n) => functions[n]);
1947
+ const covenant = names.find((_, i) => defs[i].arkadeScript);
1948
+ if (covenant && !keys.emulatorKey) {
1949
+ throw new Error(
1950
+ `ArkadeContract: function '${covenant}' has an arkadeScript but no emulator is configured \u2014 pass an \`emulator\` to Arkade.connect`
1951
+ );
1952
+ }
1953
+ return defs.map((def, i) => {
1954
+ validateTapscript(def.tapscript);
1955
+ const pubkeys = def.tapscript.signers.map((s) => resolveSigner(s, args));
1956
+ const arkadeScript = def.arkadeScript ? resolveAsm(def.arkadeScript.asm, args) : void 0;
1957
+ const leafPubkeys = arkadeScript ? [...pubkeys, computeArkadeScriptPublicKey(keys.emulatorKey, arkadeScript)] : pubkeys;
1958
+ const leafScript = encodeTapscriptSegment(def.tapscript, leafPubkeys, args).script;
1959
+ return { name: names[i], def, leafScript, arkadeScript, signerKeys: pubkeys };
1960
+ });
1961
+ }
1962
+ var ArkadeProgramScript = class extends chunkL5ND2FJJ_cjs.VtxoScript {
1963
+ constructor(program, args, keys) {
1964
+ const partial = compileFunctions(program, args, keys);
1965
+ super(partial.map((p) => p.leafScript));
1966
+ this.program = program;
1967
+ this.args = args;
1968
+ this.keys = keys;
1969
+ this.compiled = partial.map((p) => ({
1970
+ ...p,
1971
+ tapLeafScript: this.findLeaf(base.hex.encode(p.leafScript))
1972
+ }));
1973
+ }
1974
+ program;
1975
+ args;
1976
+ keys;
1977
+ /** Spending paths in declaration order. */
1978
+ compiled;
1979
+ /** The compiled spending path with the given function name, if any. */
1980
+ functionByName(name) {
1981
+ return this.compiled.find((f) => f.name === name);
1982
+ }
1983
+ };
1984
+ function parseArtifact(artifact) {
1985
+ const hexToken = (t) => typeof t === "string" && t.startsWith("0x") ? base.hex.decode(t.slice(2)) : t;
1986
+ const timelockValue = (v) => typeof v === "string" && v.startsWith("$") ? v : BigInt(v);
1987
+ const functions = {};
1988
+ for (const [name, fn] of Object.entries(artifact.functions)) {
1989
+ const tap = fn.tapscript ?? {};
1990
+ const tapscript = {
1991
+ signers: (tap.signers ?? []).map(hexToken),
1992
+ ...tap.asm ? { asm: tap.asm.map(hexToken) } : {},
1993
+ ...tap.witness ? { witness: tap.witness.map(hexToken) } : {},
1994
+ ...tap.csv ? { csv: { type: tap.csv.type, value: timelockValue(tap.csv.value) } } : {},
1995
+ ...tap.cltv !== void 0 ? { cltv: timelockValue(tap.cltv) } : {}
1996
+ };
1997
+ const arkadeScript = fn.arkadeScript ? {
1998
+ asm: fn.arkadeScript.asm.map(hexToken),
1999
+ ...fn.arkadeScript.witness ? { witness: fn.arkadeScript.witness.map(hexToken) } : {}
2000
+ } : void 0;
2001
+ functions[name] = {
2002
+ ...fn.inputs ? { inputs: fn.inputs } : {},
2003
+ tapscript,
2004
+ ...arkadeScript ? { arkadeScript } : {}
2005
+ };
2006
+ }
2007
+ return {
2008
+ version: artifact.version ?? SUPPORTED_PROGRAM_VERSION,
2009
+ ...artifact.name !== void 0 ? { name: artifact.name } : {},
2010
+ ...artifact.params ? { params: artifact.params } : {},
2011
+ functions
2012
+ };
2013
+ }
2014
+ function stringifyArtifact(program) {
2015
+ const token = (t) => {
2016
+ if (t instanceof Uint8Array) return "0x" + base.hex.encode(t);
2017
+ if (typeof t === "bigint") {
2018
+ if (t >= BigInt(Number.MIN_SAFE_INTEGER) && t <= BigInt(Number.MAX_SAFE_INTEGER)) {
2019
+ return Number(t);
2020
+ }
2021
+ return "0x" + base.hex.encode(MinimalScriptNum.encode(t));
2022
+ }
2023
+ return t;
2024
+ };
2025
+ const functions = {};
2026
+ for (const [name, fn] of Object.entries(program.functions)) {
2027
+ const tap = fn.tapscript;
2028
+ functions[name] = {
2029
+ ...fn.inputs ? { inputs: fn.inputs } : {},
2030
+ tapscript: {
2031
+ signers: tap.signers.map(token),
2032
+ ...tap.asm ? { asm: tap.asm.map(token) } : {},
2033
+ ...tap.witness ? { witness: tap.witness.map(token) } : {},
2034
+ ...tap.csv ? { csv: { type: tap.csv.type, value: tap.csv.value.toString() } } : {},
2035
+ ...tap.cltv !== void 0 ? { cltv: tap.cltv.toString() } : {}
2036
+ },
2037
+ ...fn.arkadeScript ? {
2038
+ arkadeScript: {
2039
+ asm: fn.arkadeScript.asm.map(token),
2040
+ ...fn.arkadeScript.witness ? { witness: fn.arkadeScript.witness.map(token) } : {}
2041
+ }
2042
+ } : {}
2043
+ };
2044
+ }
2045
+ return JSON.stringify({
2046
+ version: program.version,
2047
+ ...program.name !== void 0 ? { name: program.name } : {},
2048
+ ...program.params ? { params: program.params } : {},
2049
+ functions
2050
+ });
2051
+ }
2052
+ function serializeArgValue(v) {
2053
+ if (v instanceof Uint8Array) return "0x" + base.hex.encode(v);
2054
+ if (typeof v === "bigint") return v.toString();
2055
+ return v;
2056
+ }
2057
+ function parseArgValue(v) {
2058
+ if (typeof v === "number") return v;
2059
+ if (typeof v === "string") {
2060
+ if (v.startsWith("0x")) return base.hex.decode(v.slice(2));
2061
+ return BigInt(v);
2062
+ }
2063
+ throw new Error(`invalid arkade arg value: ${JSON.stringify(v)}`);
2064
+ }
2065
+ function parseTypedArgValue(name, type, v) {
2066
+ if (type === "int") {
2067
+ if (typeof v === "number") return v;
2068
+ if (typeof v === "string") return BigInt(v);
2069
+ throw new Error(
2070
+ `arkade contract params: '${name}' expects an int, got ${JSON.stringify(v)}`
2071
+ );
2072
+ }
2073
+ if (typeof v === "string" && v.startsWith("0x")) return base.hex.decode(v.slice(2));
2074
+ throw new Error(
2075
+ `arkade contract params: '${name}' expects ${type} as 0x-prefixed hex, got ${JSON.stringify(v)}`
2076
+ );
2077
+ }
2078
+ function serializeArkadeContractParams(typed) {
2079
+ const args = {};
2080
+ for (const [k, v] of Object.entries(typed.args)) {
2081
+ args[k] = serializeArgValue(v);
2082
+ }
2083
+ return {
2084
+ program: stringifyArtifact(typed.program),
2085
+ args: JSON.stringify(args),
2086
+ serverKey: base.hex.encode(typed.serverKey),
2087
+ ...typed.userKey ? { userKey: base.hex.encode(typed.userKey) } : {},
2088
+ ...typed.emulatorKey ? { emulatorKey: base.hex.encode(typed.emulatorKey) } : {}
2089
+ };
2090
+ }
2091
+ function deserializeArkadeContractParams(params) {
2092
+ if (!params.program) {
2093
+ throw new Error("arkade contract params: missing 'program'");
2094
+ }
2095
+ if (!params.serverKey) {
2096
+ throw new Error("arkade contract params: missing 'serverKey'");
2097
+ }
2098
+ const program = parseArtifact(JSON.parse(params.program));
2099
+ const paramTypes = /* @__PURE__ */ new Map();
2100
+ for (const p of program.params ?? []) {
2101
+ if (typeof p !== "string") paramTypes.set(p.name, p.type);
2102
+ }
2103
+ const args = {};
2104
+ if (params.args) {
2105
+ for (const [k, v] of Object.entries(JSON.parse(params.args))) {
2106
+ const type = paramTypes.get(k);
2107
+ args[k] = type ? parseTypedArgValue(k, type, v) : parseArgValue(v);
2108
+ }
2109
+ }
2110
+ return {
2111
+ program,
2112
+ args,
2113
+ serverKey: base.hex.decode(params.serverKey),
2114
+ ...params.userKey ? { userKey: base.hex.decode(params.userKey) } : {},
2115
+ ...params.emulatorKey ? { emulatorKey: base.hex.decode(params.emulatorKey) } : {}
2116
+ };
2117
+ }
2118
+
2119
+ // src/contracts/handlers/arkade.ts
2120
+ function walletKeyFrom(context) {
2121
+ const extract = (value) => {
2122
+ if (!isDescriptor(value)) return value.toLowerCase();
2123
+ try {
2124
+ return extractPubKey(value).toLowerCase();
2125
+ } catch {
2126
+ return void 0;
2127
+ }
2128
+ };
2129
+ if (context.walletDescriptor) {
2130
+ const key = extract(context.walletDescriptor);
2131
+ if (key) return key;
2132
+ }
2133
+ if (context.walletPubKey) {
2134
+ return extract(context.walletPubKey);
2135
+ }
2136
+ return void 0;
2137
+ }
2138
+ function staticWitness(fn, script) {
2139
+ const refs = fn.def.tapscript.witness ?? [];
2140
+ try {
2141
+ return refs.map((w) => witnessRefToBytes(w, {}, script.args));
2142
+ } catch {
2143
+ return null;
2144
+ }
2145
+ }
2146
+ function pathsFor(script, context, opts) {
2147
+ const walletKey = walletKeyFrom(context);
2148
+ const serverHex = base.hex.encode(script.keys.serverKey);
2149
+ const paths = [];
2150
+ for (const fn of script.compiled) {
2151
+ if (fn.arkadeScript) continue;
2152
+ const witness = staticWitness(fn, script);
2153
+ if (witness === null) continue;
2154
+ const signerHexes = fn.signerKeys.map((s) => base.hex.encode(s));
2155
+ const requiresServer = signerHexes.includes(serverHex);
2156
+ const nonServer = signerHexes.filter((s) => s !== serverHex);
2157
+ if (walletKey && nonServer.length > 0 && !nonServer.includes(walletKey)) {
2158
+ continue;
2159
+ }
2160
+ const csvDef = fn.def.tapscript.csv;
2161
+ const csv = csvDef ? { type: csvDef.type, value: resolveTimelockValue(csvDef.value, script.args) } : void 0;
2162
+ const cltv = fn.def.tapscript.cltv !== void 0 ? resolveTimelockValue(fn.def.tapscript.cltv, script.args) : void 0;
2163
+ if (context.collaborative) {
2164
+ if (csv) continue;
2165
+ if (opts.checkTimelocks && cltv !== void 0 && !isCltvSatisfied(context, cltv)) {
2166
+ continue;
2167
+ }
2168
+ paths.push({
2169
+ leaf: fn.tapLeafScript,
2170
+ ...witness.length > 0 ? { extraWitness: witness } : {}
2171
+ });
2172
+ continue;
2173
+ }
2174
+ if (requiresServer) continue;
2175
+ const sequence = csv ? Number(chunkL5ND2FJJ_cjs.timelockToSequence(csv)) : void 0;
2176
+ if (opts.checkTimelocks && csv && !isCsvSpendable(context, sequence)) continue;
2177
+ if (opts.checkTimelocks && cltv !== void 0 && !isCltvSatisfied(context, cltv)) {
2178
+ continue;
2179
+ }
2180
+ paths.push({
2181
+ leaf: fn.tapLeafScript,
2182
+ ...sequence !== void 0 ? { sequence } : {},
2183
+ ...witness.length > 0 ? { extraWitness: witness } : {}
2184
+ });
2185
+ }
2186
+ return paths;
2187
+ }
2188
+ var ArkadeContractHandler = {
2189
+ type: "arkade",
2190
+ createScript(params) {
2191
+ const typed = this.deserializeParams(params);
2192
+ return new ArkadeProgramScript(typed.program, typed.args, {
2193
+ serverKey: typed.serverKey,
2194
+ userKey: typed.userKey,
2195
+ emulatorKey: typed.emulatorKey
2196
+ });
2197
+ },
2198
+ serializeParams(params) {
2199
+ return serializeArkadeContractParams(params);
2200
+ },
2201
+ deserializeParams(params) {
2202
+ return deserializeArkadeContractParams(params);
2203
+ },
2204
+ selectPath(script, _contract, context) {
2205
+ const paths = pathsFor(script, context, { checkTimelocks: true });
2206
+ return paths.length > 0 ? paths[0] : null;
2207
+ },
2208
+ getAllSpendingPaths(script, _contract, context) {
2209
+ return pathsFor(script, context, { checkTimelocks: false });
2210
+ },
2211
+ getSpendablePaths(script, _contract, context) {
2212
+ return pathsFor(script, context, { checkTimelocks: true });
2213
+ },
2214
+ /**
2215
+ * Annotation tapscripts for VTXOs locked to this contract: prefer the
2216
+ * collaborative tapscript path (the multisig the Arkade Service co-signs,
2217
+ * mirroring `forfeit()` on the built-in script shapes); covenant-only
2218
+ * programs fall back to their first covenant leaf (its forfeit is
2219
+ * co-signed by the emulator during batch settlement); otherwise the first
2220
+ * declared leaf.
2221
+ */
2222
+ deriveTapscripts(script, _contract) {
2223
+ const collaborative = pathsFor(
2224
+ script,
2225
+ { collaborative: true, currentTime: 0 },
2226
+ { checkTimelocks: false }
2227
+ );
2228
+ const leaf = collaborative[0]?.leaf ?? script.compiled.find((f) => f.arkadeScript)?.tapLeafScript ?? script.compiled[0].tapLeafScript;
2229
+ return {
2230
+ forfeitTapLeafScript: leaf,
2231
+ intentTapLeafScript: leaf,
2232
+ tapTree: script.encode()
2233
+ };
2234
+ }
2235
+ };
2236
+
2237
+ // src/contracts/handlers/index.ts
2238
+ contractHandlers.register(DefaultContractHandler);
2239
+ contractHandlers.register(DelegateContractHandler);
2240
+ contractHandlers.register(VHTLCContractHandler);
2241
+ contractHandlers.register(BoardingContractHandler);
2242
+ contractHandlers.register(ArkadeContractHandler);
2243
+
2244
+ exports.ARKADE_OP = ARKADE_OP;
2245
+ exports.ARKADE_OPCODES = ARKADE_OPCODES;
2246
+ exports.ARKADE_OPCODE_NAMES = ARKADE_OPCODE_NAMES;
2247
+ exports.ARKADE_OPCODE_VALUES = ARKADE_OPCODE_VALUES;
2248
+ exports.ARKADE_OPS = ARKADE_OPS;
2249
+ exports.ArkadeContractHandler = ArkadeContractHandler;
2250
+ exports.ArkadeProgramScript = ArkadeProgramScript;
2251
+ exports.ArkadeScript = ArkadeScript;
2252
+ exports.BoardingContractHandler = BoardingContractHandler;
2253
+ exports.DEFAULT_PAGE_SIZE = DEFAULT_PAGE_SIZE;
2254
+ exports.DefaultContractHandler = DefaultContractHandler;
2255
+ exports.DelegateContractHandler = DelegateContractHandler;
2256
+ exports.OPCODE_NAMES = OPCODE_NAMES;
2257
+ exports.OPCODE_VALUES = OPCODE_VALUES;
2258
+ exports.SUPPORTED_PROGRAM_VERSION = SUPPORTED_PROGRAM_VERSION;
2259
+ exports.VHTLCContractHandler = VHTLCContractHandler;
2260
+ exports.WALLET_RECEIVE_SOURCE = WALLET_RECEIVE_SOURCE;
2261
+ exports.arkadeScriptHash = arkadeScriptHash;
2262
+ exports.arkadeWitnessHash = arkadeWitnessHash;
2263
+ exports.asmToBytes = asmToBytes;
2264
+ exports.bignum_exports = bignum_exports;
2265
+ exports.bytesToASM = bytesToASM;
2266
+ exports.computeArkadeScriptPublicKey = computeArkadeScriptPublicKey;
2267
+ exports.contractHandlers = contractHandlers;
2268
+ exports.deriveDescriptorLeafPubKey = deriveDescriptorLeafPubKey;
2269
+ exports.descriptorIsOurs = descriptorIsOurs;
2270
+ exports.deserializeArkadeContractParams = deserializeArkadeContractParams;
2271
+ exports.fromASM = fromASM;
2272
+ exports.getOpcodeName = getOpcodeName;
2273
+ exports.getOpcodeValue = getOpcodeValue;
2274
+ exports.inputName = inputName;
2275
+ exports.isCltvSatisfied = isCltvSatisfied;
2276
+ exports.isCsvSpendable = isCsvSpendable;
2277
+ exports.isMainnetDescriptor = isMainnetDescriptor;
2278
+ exports.parseArtifact = parseArtifact;
2279
+ exports.resolveAsm = resolveAsm;
2280
+ exports.serializeArkadeContractParams = serializeArkadeContractParams;
2281
+ exports.stringifyArtifact = stringifyArtifact;
2282
+ exports.toASM = toASM;
2283
+ exports.validateProgram = validateProgram;
2284
+ exports.witnessRefToBytes = witnessRefToBytes;
2285
+ //# sourceMappingURL=chunk-RQSA7ADZ.cjs.map
2286
+ //# sourceMappingURL=chunk-RQSA7ADZ.cjs.map