@arkade-os/sdk 0.5.0-rc.9 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +231 -50
- package/dist/adapters/expo.cjs +5 -5
- package/dist/adapters/expo.d.cts +5 -5
- package/dist/adapters/expo.d.ts +5 -5
- package/dist/adapters/expo.js +3 -3
- package/dist/{asyncStorageTaskQueue-DZYrAWN8.d.ts → asyncStorageTaskQueue-BFv2O1y1.d.ts} +2 -2
- package/dist/{asyncStorageTaskQueue-ChKX-D51.d.cts → asyncStorageTaskQueue-qRRQUOE8.d.cts} +2 -2
- package/dist/{chunk-PKD5VPYX.cjs → chunk-AU77RYOC.cjs} +6086 -4522
- package/dist/chunk-AU77RYOC.cjs.map +1 -0
- package/dist/{chunk-VMVHRKXM.cjs → chunk-GN2K4WBP.cjs} +494 -1122
- package/dist/chunk-GN2K4WBP.cjs.map +1 -0
- package/dist/{chunk-PO2ZDZZC.cjs → chunk-GOM26K6H.cjs} +12 -10
- package/dist/chunk-GOM26K6H.cjs.map +1 -0
- package/dist/{chunk-3TCWQPAC.js → chunk-GWJWXVUB.js} +5793 -4249
- package/dist/chunk-GWJWXVUB.js.map +1 -0
- package/dist/{chunk-J2K7WWMJ.js → chunk-HABGVRLF.js} +112 -243
- package/dist/chunk-HABGVRLF.js.map +1 -0
- package/dist/{chunk-V4JZOFYT.cjs → chunk-IQWLFYT2.cjs} +124 -254
- package/dist/chunk-IQWLFYT2.cjs.map +1 -0
- package/dist/{chunk-7OL2P5TV.cjs → chunk-JT5YVMCJ.cjs} +39 -46
- package/dist/chunk-JT5YVMCJ.cjs.map +1 -0
- package/dist/{chunk-FQCMEAWN.js → chunk-K2E6X6JT.js} +32 -39
- package/dist/chunk-K2E6X6JT.js.map +1 -0
- package/dist/{chunk-R4KRWX7R.js → chunk-K352GMVL.js} +427 -1078
- package/dist/chunk-K352GMVL.js.map +1 -0
- package/dist/{chunk-Z3QM5XFY.js → chunk-TZSKLERU.js} +7 -5
- package/dist/chunk-TZSKLERU.js.map +1 -0
- package/dist/{chunk-VTXMC4N7.cjs → chunk-UUSKJOSX.cjs} +548 -399
- package/dist/chunk-UUSKJOSX.cjs.map +1 -0
- package/dist/{chunk-JFZBKPSV.js → chunk-ZOEB53NQ.js} +541 -400
- package/dist/chunk-ZOEB53NQ.js.map +1 -0
- package/dist/contracts/handlers/index.cjs +9 -9
- package/dist/contracts/handlers/index.d.cts +5 -5
- package/dist/contracts/handlers/index.d.ts +5 -5
- package/dist/contracts/handlers/index.js +2 -2
- package/dist/{delegate-Cyv2suFd.d.cts → delegate-B5BmYkEY.d.cts} +1 -1
- package/dist/{delegate-CyBnNY9v.d.ts → delegate-DNbiUgy8.d.ts} +1 -1
- package/dist/index-B4QuO9sH.d.cts +645 -0
- package/dist/index-CYeyT3kn.d.ts +645 -0
- package/dist/{index-BIL9boGL.d.ts → index-CZw-MMfY.d.cts} +1644 -2291
- package/dist/{index-BIL9boGL.d.cts → index-CZw-MMfY.d.ts} +1644 -2291
- package/dist/index.cjs +399 -311
- package/dist/index.d.cts +950 -1124
- package/dist/index.d.ts +950 -1124
- package/dist/index.js +4 -4
- package/dist/repositories/realm/index.cjs +165 -103
- package/dist/repositories/realm/index.cjs.map +1 -1
- package/dist/repositories/realm/index.d.cts +18 -14
- package/dist/repositories/realm/index.d.ts +18 -14
- package/dist/repositories/realm/index.js +153 -91
- package/dist/repositories/realm/index.js.map +1 -1
- package/dist/repositories/sqlite/index.cjs +226 -184
- package/dist/repositories/sqlite/index.cjs.map +1 -1
- package/dist/repositories/sqlite/index.d.cts +22 -21
- package/dist/repositories/sqlite/index.d.ts +22 -21
- package/dist/repositories/sqlite/index.js +218 -176
- package/dist/repositories/sqlite/index.js.map +1 -1
- package/dist/{taskRunner-DxpSuKmh.d.cts → taskRunner-B3SLvUfL.d.cts} +2 -2
- package/dist/{taskRunner-Cu4uO1to.d.ts → taskRunner-wm1bhmtP.d.ts} +2 -2
- package/dist/wallet/expo/background.cjs +14 -14
- package/dist/wallet/expo/background.cjs.map +1 -1
- package/dist/wallet/expo/background.d.cts +10 -16
- package/dist/wallet/expo/background.d.ts +10 -16
- package/dist/wallet/expo/background.js +6 -6
- package/dist/wallet/expo/background.js.map +1 -1
- package/dist/wallet/expo/index.cjs +19 -14
- package/dist/wallet/expo/index.cjs.map +1 -1
- package/dist/wallet/expo/index.d.cts +8 -6
- package/dist/wallet/expo/index.d.ts +8 -6
- package/dist/wallet/expo/index.js +10 -5
- package/dist/wallet/expo/index.js.map +1 -1
- package/dist/wallet-DCZ2-Bea.d.cts +1874 -0
- package/dist/wallet-DGLXuwXT.d.ts +1874 -0
- package/dist/worker/expo/index.cjs +9 -9
- package/dist/worker/expo/index.d.cts +6 -6
- package/dist/worker/expo/index.d.ts +6 -6
- package/dist/worker/expo/index.js +5 -5
- package/package.json +10 -11
- package/dist/chunk-3TCWQPAC.js.map +0 -1
- package/dist/chunk-7OL2P5TV.cjs.map +0 -1
- package/dist/chunk-FQCMEAWN.js.map +0 -1
- package/dist/chunk-J2K7WWMJ.js.map +0 -1
- package/dist/chunk-JFZBKPSV.js.map +0 -1
- package/dist/chunk-PKD5VPYX.cjs.map +0 -1
- package/dist/chunk-PO2ZDZZC.cjs.map +0 -1
- package/dist/chunk-R4KRWX7R.js.map +0 -1
- package/dist/chunk-V4JZOFYT.cjs.map +0 -1
- package/dist/chunk-VMVHRKXM.cjs.map +0 -1
- package/dist/chunk-VTXMC4N7.cjs.map +0 -1
- package/dist/chunk-Z3QM5XFY.js.map +0 -1
- package/dist/hdWalletCapable-D1ImQqlu.d.cts +0 -2214
- package/dist/hdWalletCapable-DvumVrKW.d.ts +0 -2214
- package/dist/index-DleNQcz5.d.cts +0 -850
- package/dist/index-QVhQgYvU.d.ts +0 -850
|
@@ -1,41 +1,26 @@
|
|
|
1
|
-
import { __export, VtxoScript, MultisigTapscript, CSVMultisigTapscript, timelockToSequence, sequenceToTimelock, ConditionMultisigTapscript, CLTVMultisigTapscript, ConditionCSVMultisigTapscript, SCRIPT_QUERY_CHUNK_SIZE, getNormalizedVtxos, DEFAULT_PAGE_SIZE } from './chunk-
|
|
1
|
+
import { __export, VtxoScript, MultisigTapscript, CSVMultisigTapscript, timelockToSequence, sequenceToTimelock, ConditionMultisigTapscript, CLTVMultisigTapscript, ConditionCSVMultisigTapscript, SCRIPT_QUERY_CHUNK_SIZE, getNormalizedVtxos, DEFAULT_PAGE_SIZE, sequenceToCanonicalTimelock } from './chunk-ZOEB53NQ.js';
|
|
2
2
|
import { hex } from '@scure/base';
|
|
3
3
|
import { networks, expand } from '@bitcoinerlab/descriptors-scure';
|
|
4
4
|
import { ScriptNum, OP, Script } from '@scure/btc-signer';
|
|
5
|
+
import * as P from 'micro-packed';
|
|
5
6
|
import { schnorr, secp256k1 } from '@noble/curves/secp256k1.js';
|
|
6
7
|
import { bytesToNumberBE } from '@noble/curves/utils.js';
|
|
8
|
+
import { equalBytes } from '@scure/btc-signer/utils.js';
|
|
7
9
|
|
|
8
10
|
// src/contracts/handlers/registry.ts
|
|
9
11
|
var ContractHandlerRegistry = class {
|
|
10
12
|
handlers = /* @__PURE__ */ new Map();
|
|
11
|
-
/**
|
|
12
|
-
* Register a contract handler.
|
|
13
|
-
*
|
|
14
|
-
* @param handler - The handler to register
|
|
15
|
-
* @throws If a handler for this type is already registered
|
|
16
|
-
*/
|
|
13
|
+
/** @throws If a handler for this type is already registered */
|
|
17
14
|
register(handler) {
|
|
18
15
|
if (this.handlers.has(handler.type)) {
|
|
19
16
|
throw new Error(`Contract handler for type '${handler.type}' is already registered`);
|
|
20
17
|
}
|
|
21
18
|
this.handlers.set(handler.type, handler);
|
|
22
19
|
}
|
|
23
|
-
/**
|
|
24
|
-
* Get a handler by type.
|
|
25
|
-
*
|
|
26
|
-
* @param type - The contract type
|
|
27
|
-
* @returns The handler, or undefined if not found
|
|
28
|
-
*/
|
|
29
20
|
get(type) {
|
|
30
21
|
return this.handlers.get(type);
|
|
31
22
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Get a handler by type, throwing if not found.
|
|
34
|
-
*
|
|
35
|
-
* @param type - The contract type
|
|
36
|
-
* @returns The handler
|
|
37
|
-
* @throws If no handler is registered for this type
|
|
38
|
-
*/
|
|
23
|
+
/** @throws If no handler is registered for this type */
|
|
39
24
|
getOrThrow(type) {
|
|
40
25
|
const handler = this.get(type);
|
|
41
26
|
if (!handler) {
|
|
@@ -43,29 +28,17 @@ var ContractHandlerRegistry = class {
|
|
|
43
28
|
}
|
|
44
29
|
return handler;
|
|
45
30
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Check if a handler is registered.
|
|
48
|
-
*
|
|
49
|
-
* @param type - The contract type
|
|
50
|
-
*/
|
|
51
31
|
has(type) {
|
|
52
32
|
return this.handlers.has(type);
|
|
53
33
|
}
|
|
54
|
-
/**
|
|
55
|
-
* Get all registered types.
|
|
56
|
-
*/
|
|
57
34
|
getRegisteredTypes() {
|
|
58
35
|
return Array.from(this.handlers.keys());
|
|
59
36
|
}
|
|
60
|
-
/**
|
|
61
|
-
* Unregister a handler (mainly for testing).
|
|
62
|
-
*/
|
|
37
|
+
/** Unregister a handler (mainly for testing). */
|
|
63
38
|
unregister(type) {
|
|
64
39
|
return this.handlers.delete(type);
|
|
65
40
|
}
|
|
66
|
-
/**
|
|
67
|
-
* Clear all handlers (mainly for testing).
|
|
68
|
-
*/
|
|
41
|
+
/** Clear all handlers (mainly for testing). */
|
|
69
42
|
clear() {
|
|
70
43
|
this.handlers.clear();
|
|
71
44
|
}
|
|
@@ -311,6 +284,135 @@ function assertVhtlcSpendableNow(contract, context) {
|
|
|
311
284
|
`vhtlc ${contract.script} cannot be spent yet: its refund path opens at ${matures}, now ${now}. Until then the lockup is the receiver's to claim, and the server rejects a spend of it. Retry after ${matures}, or wait for the receiver to claim it with the preimage.`
|
|
312
285
|
);
|
|
313
286
|
}
|
|
287
|
+
function selectVhtlcPath(script, contract, context) {
|
|
288
|
+
const role = resolveRole(contract, context);
|
|
289
|
+
const preimage = contract.params?.preimage;
|
|
290
|
+
const refundLocktime = BigInt(contract.params.refundLocktime);
|
|
291
|
+
if (!role) {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
if (context.collaborative) {
|
|
295
|
+
if (role === "receiver" && preimage) {
|
|
296
|
+
return {
|
|
297
|
+
leaf: script.claim(),
|
|
298
|
+
extraWitness: [hex.decode(preimage)]
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
if (role === "sender" && isCltvSatisfied(context, refundLocktime)) {
|
|
302
|
+
return {
|
|
303
|
+
leaf: script.refundWithoutReceiver()
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
if (role === "receiver" && preimage) {
|
|
309
|
+
const sequence = Number(contract.params.claimDelay);
|
|
310
|
+
if (!isCsvSpendable(context, sequence)) return null;
|
|
311
|
+
return {
|
|
312
|
+
leaf: script.unilateralClaim(),
|
|
313
|
+
extraWitness: [hex.decode(preimage)],
|
|
314
|
+
sequence
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
if (role === "sender") {
|
|
318
|
+
const sequence = Number(contract.params.refundNoReceiverDelay);
|
|
319
|
+
if (!isCsvSpendable(context, sequence)) return null;
|
|
320
|
+
return {
|
|
321
|
+
leaf: script.unilateralRefundWithoutReceiver(),
|
|
322
|
+
sequence
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
function vhtlcAllSpendingPaths(script, contract, context) {
|
|
328
|
+
const role = resolveRole(contract, context);
|
|
329
|
+
const paths = [];
|
|
330
|
+
if (!role) {
|
|
331
|
+
return paths;
|
|
332
|
+
}
|
|
333
|
+
const preimage = contract.params?.preimage;
|
|
334
|
+
if (context.collaborative) {
|
|
335
|
+
if (role === "receiver" && preimage) {
|
|
336
|
+
paths.push({
|
|
337
|
+
leaf: script.claim(),
|
|
338
|
+
extraWitness: [hex.decode(preimage)]
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
if (role === "sender") {
|
|
342
|
+
paths.push({
|
|
343
|
+
leaf: script.refundWithoutReceiver()
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
if (role === "receiver" && preimage) {
|
|
348
|
+
const sequence = Number(contract.params.claimDelay);
|
|
349
|
+
paths.push({
|
|
350
|
+
leaf: script.unilateralClaim(),
|
|
351
|
+
extraWitness: [hex.decode(preimage)],
|
|
352
|
+
sequence
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
if (role === "sender") {
|
|
356
|
+
const sequence = Number(contract.params.refundNoReceiverDelay);
|
|
357
|
+
paths.push({
|
|
358
|
+
leaf: script.unilateralRefundWithoutReceiver(),
|
|
359
|
+
sequence
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return paths;
|
|
364
|
+
}
|
|
365
|
+
function vhtlcSpendablePaths(script, contract, context) {
|
|
366
|
+
const role = resolveRole(contract, context);
|
|
367
|
+
const paths = [];
|
|
368
|
+
if (!role) {
|
|
369
|
+
return paths;
|
|
370
|
+
}
|
|
371
|
+
const preimage = contract.params?.preimage;
|
|
372
|
+
const refundLocktime = BigInt(contract.params.refundLocktime);
|
|
373
|
+
if (context.collaborative) {
|
|
374
|
+
if (role === "receiver" && preimage) {
|
|
375
|
+
paths.push({
|
|
376
|
+
leaf: script.claim(),
|
|
377
|
+
extraWitness: [hex.decode(preimage)]
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
if (role === "sender" && isCltvSatisfied(context, refundLocktime)) {
|
|
381
|
+
paths.push({
|
|
382
|
+
leaf: script.refundWithoutReceiver()
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
return paths;
|
|
386
|
+
}
|
|
387
|
+
if (role === "receiver" && preimage) {
|
|
388
|
+
const sequence = Number(contract.params.claimDelay);
|
|
389
|
+
if (isCsvSpendable(context, sequence)) {
|
|
390
|
+
paths.push({
|
|
391
|
+
leaf: script.unilateralClaim(),
|
|
392
|
+
extraWitness: [hex.decode(preimage)],
|
|
393
|
+
sequence
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (role === "sender") {
|
|
398
|
+
const sequence = Number(contract.params.refundNoReceiverDelay);
|
|
399
|
+
if (isCsvSpendable(context, sequence)) {
|
|
400
|
+
paths.push({
|
|
401
|
+
leaf: script.unilateralRefundWithoutReceiver(),
|
|
402
|
+
sequence
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return paths;
|
|
407
|
+
}
|
|
408
|
+
function deriveVhtlcTapscripts(script) {
|
|
409
|
+
const leaf = script.refundWithoutReceiver();
|
|
410
|
+
return {
|
|
411
|
+
forfeitTapLeafScript: leaf,
|
|
412
|
+
intentTapLeafScript: leaf,
|
|
413
|
+
tapTree: script.encode()
|
|
414
|
+
};
|
|
415
|
+
}
|
|
314
416
|
function isCsvSpendable(context, sequence) {
|
|
315
417
|
if (sequence === void 0) return true;
|
|
316
418
|
if (!context.vtxo) return false;
|
|
@@ -479,11 +581,7 @@ function defaultCandidatesAt(_index, descriptor, deps) {
|
|
|
479
581
|
(opts) => new DefaultVtxo.Script(opts)
|
|
480
582
|
).map((c) => ({
|
|
481
583
|
type: "default",
|
|
482
|
-
params:
|
|
483
|
-
pubKey: hex.encode(c.pubKey),
|
|
484
|
-
serverPubKey: hex.encode(c.serverPubKey),
|
|
485
|
-
csvTimelock: timelockToSequence(c.csvTimelock).toString()
|
|
486
|
-
},
|
|
584
|
+
params: DefaultContractHandler.serializeParams(c),
|
|
487
585
|
script: c.scriptHex,
|
|
488
586
|
address: c.script.address(deps.network.hrp, c.serverPubKey).encode()
|
|
489
587
|
}));
|
|
@@ -582,12 +680,7 @@ function delegateCandidatesAt(_index, descriptor, deps) {
|
|
|
582
680
|
(opts) => new DelegateVtxo.Script({ ...opts, delegatePubKey })
|
|
583
681
|
).map((c) => ({
|
|
584
682
|
type: "delegate",
|
|
585
|
-
params: {
|
|
586
|
-
pubKey: hex.encode(c.pubKey),
|
|
587
|
-
serverPubKey: hex.encode(c.serverPubKey),
|
|
588
|
-
delegatePubKey: hex.encode(delegatePubKey),
|
|
589
|
-
csvTimelock: timelockToSequence(c.csvTimelock).toString()
|
|
590
|
-
},
|
|
683
|
+
params: DelegateContractHandler.serializeParams({ ...c, delegatePubKey }),
|
|
591
684
|
script: c.scriptHex,
|
|
592
685
|
address: c.script.address(deps.network.hrp, c.serverPubKey).encode()
|
|
593
686
|
}));
|
|
@@ -603,515 +696,10 @@ function discoverDelegateRange(entries, deps) {
|
|
|
603
696
|
(c, index, descriptor) => ({ ...c, ...rotatedReceiveMetadata(index, descriptor) })
|
|
604
697
|
);
|
|
605
698
|
}
|
|
606
|
-
function equalBytes(a, b) {
|
|
607
|
-
if (a.length !== b.length)
|
|
608
|
-
return false;
|
|
609
|
-
for (let i = 0; i < a.length; i++)
|
|
610
|
-
if (a[i] !== b[i])
|
|
611
|
-
return false;
|
|
612
|
-
return true;
|
|
613
|
-
}
|
|
614
|
-
function isBytes(a) {
|
|
615
|
-
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
616
|
-
}
|
|
617
|
-
var createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
618
|
-
function isPlainObject(obj) {
|
|
619
|
-
return Object.prototype.toString.call(obj) === "[object Object]";
|
|
620
|
-
}
|
|
621
|
-
function isNum(num) {
|
|
622
|
-
return Number.isSafeInteger(num);
|
|
623
|
-
}
|
|
624
|
-
var Bitset = {
|
|
625
|
-
BITS: 32,
|
|
626
|
-
FULL_MASK: -1 >>> 0,
|
|
627
|
-
// 1<<32 will overflow
|
|
628
|
-
len: (len) => Math.ceil(len / 32),
|
|
629
|
-
create: (len) => new Uint32Array(Bitset.len(len)),
|
|
630
|
-
clean: (bs) => bs.fill(0),
|
|
631
|
-
debug: (bs) => Array.from(bs).map((i) => (i >>> 0).toString(2).padStart(32, "0")),
|
|
632
|
-
checkLen: (bs, len) => {
|
|
633
|
-
if (Bitset.len(len) === bs.length)
|
|
634
|
-
return;
|
|
635
|
-
throw new Error(`wrong length=${bs.length}. Expected: ${Bitset.len(len)}`);
|
|
636
|
-
},
|
|
637
|
-
chunkLen: (bsLen, pos, len) => {
|
|
638
|
-
if (pos < 0)
|
|
639
|
-
throw new Error(`wrong pos=${pos}`);
|
|
640
|
-
if (pos + len > bsLen)
|
|
641
|
-
throw new Error(`wrong range=${pos}/${len} of ${bsLen}`);
|
|
642
|
-
},
|
|
643
|
-
set: (bs, chunk, value, allowRewrite = true) => {
|
|
644
|
-
if (!allowRewrite && (bs[chunk] & value) !== 0)
|
|
645
|
-
return false;
|
|
646
|
-
bs[chunk] |= value;
|
|
647
|
-
return true;
|
|
648
|
-
},
|
|
649
|
-
pos: (pos, i) => ({
|
|
650
|
-
chunk: Math.floor((pos + i) / 32),
|
|
651
|
-
mask: 1 << 32 - (pos + i) % 32 - 1
|
|
652
|
-
}),
|
|
653
|
-
indices: (bs, len, invert = false) => {
|
|
654
|
-
Bitset.checkLen(bs, len);
|
|
655
|
-
const { FULL_MASK, BITS } = Bitset;
|
|
656
|
-
const left = BITS - len % BITS;
|
|
657
|
-
const lastMask = left ? FULL_MASK >>> left << left : FULL_MASK;
|
|
658
|
-
const res = [];
|
|
659
|
-
for (let i = 0; i < bs.length; i++) {
|
|
660
|
-
let c = bs[i];
|
|
661
|
-
if (invert)
|
|
662
|
-
c = ~c;
|
|
663
|
-
if (i === bs.length - 1)
|
|
664
|
-
c &= lastMask;
|
|
665
|
-
if (c === 0)
|
|
666
|
-
continue;
|
|
667
|
-
for (let j = 0; j < BITS; j++) {
|
|
668
|
-
const m = 1 << BITS - j - 1;
|
|
669
|
-
if (c & m)
|
|
670
|
-
res.push(i * BITS + j);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
return res;
|
|
674
|
-
},
|
|
675
|
-
range: (arr) => {
|
|
676
|
-
const res = [];
|
|
677
|
-
let cur;
|
|
678
|
-
for (const i of arr) {
|
|
679
|
-
if (cur === void 0 || i !== cur.pos + cur.length)
|
|
680
|
-
res.push(cur = { pos: i, length: 1 });
|
|
681
|
-
else
|
|
682
|
-
cur.length += 1;
|
|
683
|
-
}
|
|
684
|
-
return res;
|
|
685
|
-
},
|
|
686
|
-
rangeDebug: (bs, len, invert = false) => `[${Bitset.range(Bitset.indices(bs, len, invert)).map((i) => `(${i.pos}/${i.length})`).join(", ")}]`,
|
|
687
|
-
setRange: (bs, bsLen, pos, len, allowRewrite = true) => {
|
|
688
|
-
Bitset.chunkLen(bsLen, pos, len);
|
|
689
|
-
const { FULL_MASK, BITS } = Bitset;
|
|
690
|
-
const first = pos % BITS ? Math.floor(pos / BITS) : void 0;
|
|
691
|
-
const lastPos = pos + len;
|
|
692
|
-
const last = lastPos % BITS ? Math.floor(lastPos / BITS) : void 0;
|
|
693
|
-
if (first !== void 0 && first === last)
|
|
694
|
-
return Bitset.set(bs, first, FULL_MASK >>> BITS - len << BITS - len - pos, allowRewrite);
|
|
695
|
-
if (first !== void 0) {
|
|
696
|
-
if (!Bitset.set(bs, first, FULL_MASK >>> pos % BITS, allowRewrite))
|
|
697
|
-
return false;
|
|
698
|
-
}
|
|
699
|
-
const start = first !== void 0 ? first + 1 : pos / BITS;
|
|
700
|
-
const end = last !== void 0 ? last : lastPos / BITS;
|
|
701
|
-
for (let i = start; i < end; i++)
|
|
702
|
-
if (!Bitset.set(bs, i, FULL_MASK, allowRewrite))
|
|
703
|
-
return false;
|
|
704
|
-
if (last !== void 0 && first !== last) {
|
|
705
|
-
if (!Bitset.set(bs, last, FULL_MASK << BITS - lastPos % BITS, allowRewrite))
|
|
706
|
-
return false;
|
|
707
|
-
}
|
|
708
|
-
return true;
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
var Path = {
|
|
712
|
-
/**
|
|
713
|
-
* Internal method for handling stack of paths (debug, errors, dynamic fields via path)
|
|
714
|
-
* This is looks ugly (callback), but allows us to force stack cleaning by construction (.pop always after function).
|
|
715
|
-
* Also, this makes impossible:
|
|
716
|
-
* - pushing field when stack is empty
|
|
717
|
-
* - pushing field inside of field (real bug)
|
|
718
|
-
* NOTE: we don't want to do '.pop' on error!
|
|
719
|
-
*/
|
|
720
|
-
pushObj: (stack, obj, objFn) => {
|
|
721
|
-
const last = { obj };
|
|
722
|
-
stack.push(last);
|
|
723
|
-
objFn((field, fieldFn) => {
|
|
724
|
-
last.field = field;
|
|
725
|
-
fieldFn();
|
|
726
|
-
last.field = void 0;
|
|
727
|
-
});
|
|
728
|
-
stack.pop();
|
|
729
|
-
},
|
|
730
|
-
path: (stack) => {
|
|
731
|
-
const res = [];
|
|
732
|
-
for (const i of stack)
|
|
733
|
-
if (i.field !== void 0)
|
|
734
|
-
res.push(i.field);
|
|
735
|
-
return res.join("/");
|
|
736
|
-
},
|
|
737
|
-
err: (name, stack, msg) => {
|
|
738
|
-
const err = new Error(`${name}(${Path.path(stack)}): ${typeof msg === "string" ? msg : msg.message}`);
|
|
739
|
-
if (msg instanceof Error && msg.stack)
|
|
740
|
-
err.stack = msg.stack;
|
|
741
|
-
return err;
|
|
742
|
-
},
|
|
743
|
-
resolve: (stack, path) => {
|
|
744
|
-
const parts = path.split("/");
|
|
745
|
-
const objPath = stack.map((i2) => i2.obj);
|
|
746
|
-
let i = 0;
|
|
747
|
-
for (; i < parts.length; i++) {
|
|
748
|
-
if (parts[i] === "..")
|
|
749
|
-
objPath.pop();
|
|
750
|
-
else
|
|
751
|
-
break;
|
|
752
|
-
}
|
|
753
|
-
let cur = objPath.pop();
|
|
754
|
-
for (; i < parts.length; i++) {
|
|
755
|
-
if (!cur || cur[parts[i]] === void 0)
|
|
756
|
-
return void 0;
|
|
757
|
-
cur = cur[parts[i]];
|
|
758
|
-
}
|
|
759
|
-
return cur;
|
|
760
|
-
}
|
|
761
|
-
};
|
|
762
|
-
var _Reader = class __Reader {
|
|
763
|
-
pos = 0;
|
|
764
|
-
data;
|
|
765
|
-
opts;
|
|
766
|
-
stack;
|
|
767
|
-
parent;
|
|
768
|
-
parentOffset;
|
|
769
|
-
bitBuf = 0;
|
|
770
|
-
bitPos = 0;
|
|
771
|
-
bs;
|
|
772
|
-
// bitset
|
|
773
|
-
view;
|
|
774
|
-
constructor(data, opts = {}, stack = [], parent = void 0, parentOffset = 0) {
|
|
775
|
-
this.data = data;
|
|
776
|
-
this.opts = opts;
|
|
777
|
-
this.stack = stack;
|
|
778
|
-
this.parent = parent;
|
|
779
|
-
this.parentOffset = parentOffset;
|
|
780
|
-
this.view = createView(data);
|
|
781
|
-
}
|
|
782
|
-
/** Internal method for pointers. */
|
|
783
|
-
_enablePointers() {
|
|
784
|
-
if (this.parent)
|
|
785
|
-
return this.parent._enablePointers();
|
|
786
|
-
if (this.bs)
|
|
787
|
-
return;
|
|
788
|
-
this.bs = Bitset.create(this.data.length);
|
|
789
|
-
Bitset.setRange(this.bs, this.data.length, 0, this.pos, this.opts.allowMultipleReads);
|
|
790
|
-
}
|
|
791
|
-
markBytesBS(pos, len) {
|
|
792
|
-
if (this.parent)
|
|
793
|
-
return this.parent.markBytesBS(this.parentOffset + pos, len);
|
|
794
|
-
if (!len)
|
|
795
|
-
return true;
|
|
796
|
-
if (!this.bs)
|
|
797
|
-
return true;
|
|
798
|
-
return Bitset.setRange(this.bs, this.data.length, pos, len, false);
|
|
799
|
-
}
|
|
800
|
-
markBytes(len) {
|
|
801
|
-
const pos = this.pos;
|
|
802
|
-
this.pos += len;
|
|
803
|
-
const res = this.markBytesBS(pos, len);
|
|
804
|
-
if (!this.opts.allowMultipleReads && !res)
|
|
805
|
-
throw this.err(`multiple read pos=${this.pos} len=${len}`);
|
|
806
|
-
return res;
|
|
807
|
-
}
|
|
808
|
-
pushObj(obj, objFn) {
|
|
809
|
-
return Path.pushObj(this.stack, obj, objFn);
|
|
810
|
-
}
|
|
811
|
-
readView(n, fn) {
|
|
812
|
-
if (!Number.isFinite(n))
|
|
813
|
-
throw this.err(`readView: wrong length=${n}`);
|
|
814
|
-
if (this.pos + n > this.data.length)
|
|
815
|
-
throw this.err("readView: Unexpected end of buffer");
|
|
816
|
-
const res = fn(this.view, this.pos);
|
|
817
|
-
this.markBytes(n);
|
|
818
|
-
return res;
|
|
819
|
-
}
|
|
820
|
-
// read bytes by absolute offset
|
|
821
|
-
absBytes(n) {
|
|
822
|
-
if (n > this.data.length)
|
|
823
|
-
throw new Error("Unexpected end of buffer");
|
|
824
|
-
return this.data.subarray(n);
|
|
825
|
-
}
|
|
826
|
-
finish() {
|
|
827
|
-
if (this.opts.allowUnreadBytes)
|
|
828
|
-
return;
|
|
829
|
-
if (this.bitPos) {
|
|
830
|
-
throw this.err(`${this.bitPos} bits left after unpack: ${hex.encode(this.data.slice(this.pos))}`);
|
|
831
|
-
}
|
|
832
|
-
if (this.bs && !this.parent) {
|
|
833
|
-
const notRead = Bitset.indices(this.bs, this.data.length, true);
|
|
834
|
-
if (notRead.length) {
|
|
835
|
-
const formatted = Bitset.range(notRead).map(({ pos, length }) => `(${pos}/${length})[${hex.encode(this.data.subarray(pos, pos + length))}]`).join(", ");
|
|
836
|
-
throw this.err(`unread byte ranges: ${formatted} (total=${this.data.length})`);
|
|
837
|
-
} else
|
|
838
|
-
return;
|
|
839
|
-
}
|
|
840
|
-
if (!this.isEnd()) {
|
|
841
|
-
throw this.err(`${this.leftBytes} bytes ${this.bitPos} bits left after unpack: ${hex.encode(this.data.slice(this.pos))}`);
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
// User methods
|
|
845
|
-
err(msg) {
|
|
846
|
-
return Path.err("Reader", this.stack, msg);
|
|
847
|
-
}
|
|
848
|
-
offsetReader(n) {
|
|
849
|
-
if (n > this.data.length)
|
|
850
|
-
throw this.err("offsetReader: Unexpected end of buffer");
|
|
851
|
-
return new __Reader(this.absBytes(n), this.opts, this.stack, this, n);
|
|
852
|
-
}
|
|
853
|
-
bytes(n, peek = false) {
|
|
854
|
-
if (this.bitPos)
|
|
855
|
-
throw this.err("readBytes: bitPos not empty");
|
|
856
|
-
if (!Number.isFinite(n))
|
|
857
|
-
throw this.err(`readBytes: wrong length=${n}`);
|
|
858
|
-
if (this.pos + n > this.data.length)
|
|
859
|
-
throw this.err("readBytes: Unexpected end of buffer");
|
|
860
|
-
const slice = this.data.subarray(this.pos, this.pos + n);
|
|
861
|
-
if (!peek)
|
|
862
|
-
this.markBytes(n);
|
|
863
|
-
return slice;
|
|
864
|
-
}
|
|
865
|
-
byte(peek = false) {
|
|
866
|
-
if (this.bitPos)
|
|
867
|
-
throw this.err("readByte: bitPos not empty");
|
|
868
|
-
if (this.pos + 1 > this.data.length)
|
|
869
|
-
throw this.err("readBytes: Unexpected end of buffer");
|
|
870
|
-
const data = this.data[this.pos];
|
|
871
|
-
if (!peek)
|
|
872
|
-
this.markBytes(1);
|
|
873
|
-
return data;
|
|
874
|
-
}
|
|
875
|
-
get leftBytes() {
|
|
876
|
-
return this.data.length - this.pos;
|
|
877
|
-
}
|
|
878
|
-
get totalBytes() {
|
|
879
|
-
return this.data.length;
|
|
880
|
-
}
|
|
881
|
-
isEnd() {
|
|
882
|
-
return this.pos >= this.data.length && !this.bitPos;
|
|
883
|
-
}
|
|
884
|
-
// bits are read in BE mode (left to right): (0b1000_0000).readBits(1) == 1
|
|
885
|
-
bits(bits) {
|
|
886
|
-
if (bits > 32)
|
|
887
|
-
throw this.err("BitReader: cannot read more than 32 bits in single call");
|
|
888
|
-
let out = 0;
|
|
889
|
-
while (bits) {
|
|
890
|
-
if (!this.bitPos) {
|
|
891
|
-
this.bitBuf = this.byte();
|
|
892
|
-
this.bitPos = 8;
|
|
893
|
-
}
|
|
894
|
-
const take = Math.min(bits, this.bitPos);
|
|
895
|
-
this.bitPos -= take;
|
|
896
|
-
out = out << take | this.bitBuf >> this.bitPos & 2 ** take - 1;
|
|
897
|
-
this.bitBuf &= 2 ** this.bitPos - 1;
|
|
898
|
-
bits -= take;
|
|
899
|
-
}
|
|
900
|
-
return out >>> 0;
|
|
901
|
-
}
|
|
902
|
-
find(needle, pos = this.pos) {
|
|
903
|
-
if (!isBytes(needle))
|
|
904
|
-
throw this.err(`find: needle is not bytes! ${needle}`);
|
|
905
|
-
if (this.bitPos)
|
|
906
|
-
throw this.err("findByte: bitPos not empty");
|
|
907
|
-
if (!needle.length)
|
|
908
|
-
throw this.err(`find: needle is empty`);
|
|
909
|
-
for (let idx = pos; (idx = this.data.indexOf(needle[0], idx)) !== -1; idx++) {
|
|
910
|
-
if (idx === -1)
|
|
911
|
-
return;
|
|
912
|
-
const leftBytes = this.data.length - idx;
|
|
913
|
-
if (leftBytes < needle.length)
|
|
914
|
-
return;
|
|
915
|
-
if (equalBytes(needle, this.data.subarray(idx, idx + needle.length)))
|
|
916
|
-
return idx;
|
|
917
|
-
}
|
|
918
|
-
return;
|
|
919
|
-
}
|
|
920
|
-
};
|
|
921
|
-
var _Writer = class {
|
|
922
|
-
pos = 0;
|
|
923
|
-
stack;
|
|
924
|
-
// We could have a single buffer here and re-alloc it with
|
|
925
|
-
// x1.5-2 size each time it full, but it will be slower:
|
|
926
|
-
// basic/encode bench: 395ns -> 560ns
|
|
927
|
-
buffers = [];
|
|
928
|
-
ptrs = [];
|
|
929
|
-
bitBuf = 0;
|
|
930
|
-
bitPos = 0;
|
|
931
|
-
viewBuf = new Uint8Array(8);
|
|
932
|
-
view;
|
|
933
|
-
finished = false;
|
|
934
|
-
constructor(stack = []) {
|
|
935
|
-
this.stack = stack;
|
|
936
|
-
this.view = createView(this.viewBuf);
|
|
937
|
-
}
|
|
938
|
-
pushObj(obj, objFn) {
|
|
939
|
-
return Path.pushObj(this.stack, obj, objFn);
|
|
940
|
-
}
|
|
941
|
-
writeView(len, fn) {
|
|
942
|
-
if (this.finished)
|
|
943
|
-
throw this.err("buffer: finished");
|
|
944
|
-
if (!isNum(len) || len > 8)
|
|
945
|
-
throw new Error(`wrong writeView length=${len}`);
|
|
946
|
-
fn(this.view);
|
|
947
|
-
this.bytes(this.viewBuf.slice(0, len));
|
|
948
|
-
this.viewBuf.fill(0);
|
|
949
|
-
}
|
|
950
|
-
// User methods
|
|
951
|
-
err(msg) {
|
|
952
|
-
if (this.finished)
|
|
953
|
-
throw this.err("buffer: finished");
|
|
954
|
-
return Path.err("Reader", this.stack, msg);
|
|
955
|
-
}
|
|
956
|
-
bytes(b) {
|
|
957
|
-
if (this.finished)
|
|
958
|
-
throw this.err("buffer: finished");
|
|
959
|
-
if (this.bitPos)
|
|
960
|
-
throw this.err("writeBytes: ends with non-empty bit buffer");
|
|
961
|
-
this.buffers.push(b);
|
|
962
|
-
this.pos += b.length;
|
|
963
|
-
}
|
|
964
|
-
byte(b) {
|
|
965
|
-
if (this.finished)
|
|
966
|
-
throw this.err("buffer: finished");
|
|
967
|
-
if (this.bitPos)
|
|
968
|
-
throw this.err("writeByte: ends with non-empty bit buffer");
|
|
969
|
-
this.buffers.push(new Uint8Array([b]));
|
|
970
|
-
this.pos++;
|
|
971
|
-
}
|
|
972
|
-
finish(clean = true) {
|
|
973
|
-
if (this.finished)
|
|
974
|
-
throw this.err("buffer: finished");
|
|
975
|
-
if (this.bitPos)
|
|
976
|
-
throw this.err("buffer: ends with non-empty bit buffer");
|
|
977
|
-
const buffers = this.buffers.concat(this.ptrs.map((i) => i.buffer));
|
|
978
|
-
const sum = buffers.map((b) => b.length).reduce((a, b) => a + b, 0);
|
|
979
|
-
const buf = new Uint8Array(sum);
|
|
980
|
-
for (let i = 0, pad = 0; i < buffers.length; i++) {
|
|
981
|
-
const a = buffers[i];
|
|
982
|
-
buf.set(a, pad);
|
|
983
|
-
pad += a.length;
|
|
984
|
-
}
|
|
985
|
-
for (let pos = this.pos, i = 0; i < this.ptrs.length; i++) {
|
|
986
|
-
const ptr = this.ptrs[i];
|
|
987
|
-
buf.set(ptr.ptr.encode(pos), ptr.pos);
|
|
988
|
-
pos += ptr.buffer.length;
|
|
989
|
-
}
|
|
990
|
-
if (clean) {
|
|
991
|
-
this.buffers = [];
|
|
992
|
-
for (const p of this.ptrs)
|
|
993
|
-
p.buffer.fill(0);
|
|
994
|
-
this.ptrs = [];
|
|
995
|
-
this.finished = true;
|
|
996
|
-
this.bitBuf = 0;
|
|
997
|
-
}
|
|
998
|
-
return buf;
|
|
999
|
-
}
|
|
1000
|
-
bits(value, bits) {
|
|
1001
|
-
if (bits > 32)
|
|
1002
|
-
throw this.err("writeBits: cannot write more than 32 bits in single call");
|
|
1003
|
-
if (value >= 2 ** bits)
|
|
1004
|
-
throw this.err(`writeBits: value (${value}) >= 2**bits (${bits})`);
|
|
1005
|
-
while (bits) {
|
|
1006
|
-
const take = Math.min(bits, 8 - this.bitPos);
|
|
1007
|
-
this.bitBuf = this.bitBuf << take | value >> bits - take;
|
|
1008
|
-
this.bitPos += take;
|
|
1009
|
-
bits -= take;
|
|
1010
|
-
value &= 2 ** bits - 1;
|
|
1011
|
-
if (this.bitPos === 8) {
|
|
1012
|
-
this.bitPos = 0;
|
|
1013
|
-
this.buffers.push(new Uint8Array([this.bitBuf]));
|
|
1014
|
-
this.pos++;
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
};
|
|
1019
|
-
function _wrap(inner) {
|
|
1020
|
-
return {
|
|
1021
|
-
// NOTE: we cannot export validate here, since it is likely mistake.
|
|
1022
|
-
encodeStream: inner.encodeStream,
|
|
1023
|
-
decodeStream: inner.decodeStream,
|
|
1024
|
-
size: inner.size,
|
|
1025
|
-
encode: (value) => {
|
|
1026
|
-
const w = new _Writer();
|
|
1027
|
-
inner.encodeStream(w, value);
|
|
1028
|
-
return w.finish();
|
|
1029
|
-
},
|
|
1030
|
-
decode: (data, opts = {}) => {
|
|
1031
|
-
const r = new _Reader(data, opts);
|
|
1032
|
-
const res = inner.decodeStream(r);
|
|
1033
|
-
r.finish();
|
|
1034
|
-
return res;
|
|
1035
|
-
}
|
|
1036
|
-
};
|
|
1037
|
-
}
|
|
1038
|
-
function validate(inner, fn) {
|
|
1039
|
-
if (!isCoder(inner))
|
|
1040
|
-
throw new Error(`validate: invalid inner value ${inner}`);
|
|
1041
|
-
if (typeof fn !== "function")
|
|
1042
|
-
throw new Error("validate: fn should be function");
|
|
1043
|
-
return _wrap({
|
|
1044
|
-
size: inner.size,
|
|
1045
|
-
encodeStream: (w, value) => {
|
|
1046
|
-
let res;
|
|
1047
|
-
try {
|
|
1048
|
-
res = fn(value);
|
|
1049
|
-
} catch (e) {
|
|
1050
|
-
throw w.err(e);
|
|
1051
|
-
}
|
|
1052
|
-
inner.encodeStream(w, res);
|
|
1053
|
-
},
|
|
1054
|
-
decodeStream: (r) => {
|
|
1055
|
-
const res = inner.decodeStream(r);
|
|
1056
|
-
try {
|
|
1057
|
-
return fn(res);
|
|
1058
|
-
} catch (e) {
|
|
1059
|
-
throw r.err(e);
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
});
|
|
1063
|
-
}
|
|
1064
|
-
var wrap = (inner) => {
|
|
1065
|
-
const res = _wrap(inner);
|
|
1066
|
-
return inner.validate ? validate(res, inner.validate) : res;
|
|
1067
|
-
};
|
|
1068
|
-
var isBaseCoder = (elm) => isPlainObject(elm) && typeof elm.decode === "function" && typeof elm.encode === "function";
|
|
1069
|
-
function isCoder(elm) {
|
|
1070
|
-
return isPlainObject(elm) && isBaseCoder(elm) && typeof elm.encodeStream === "function" && typeof elm.decodeStream === "function" && (elm.size === void 0 || isNum(elm.size));
|
|
1071
|
-
}
|
|
1072
|
-
var view = (len, opts) => wrap({
|
|
1073
|
-
size: len,
|
|
1074
|
-
encodeStream: (w, value) => w.writeView(len, (view2) => opts.write(view2, value)),
|
|
1075
|
-
decodeStream: (r) => r.readView(len, opts.read),
|
|
1076
|
-
validate: (value) => {
|
|
1077
|
-
if (typeof value !== "number")
|
|
1078
|
-
throw new Error(`viewCoder: expected number, got ${typeof value}`);
|
|
1079
|
-
if (opts.validate)
|
|
1080
|
-
opts.validate(value);
|
|
1081
|
-
return value;
|
|
1082
|
-
}
|
|
1083
|
-
});
|
|
1084
|
-
var intView = (len, signed, opts) => {
|
|
1085
|
-
const bits = len * 8;
|
|
1086
|
-
const maxVal = 2 ** bits;
|
|
1087
|
-
const validateUnsigned = (value) => {
|
|
1088
|
-
if (!isNum(value))
|
|
1089
|
-
throw new Error(`uintView: value is not safe integer: ${value}`);
|
|
1090
|
-
if (0 > value || value >= maxVal) {
|
|
1091
|
-
throw new Error(`uintView: value out of bounds. Expected 0 <= ${value} < ${maxVal}`);
|
|
1092
|
-
}
|
|
1093
|
-
};
|
|
1094
|
-
return view(len, {
|
|
1095
|
-
write: opts.write,
|
|
1096
|
-
read: opts.read,
|
|
1097
|
-
validate: validateUnsigned
|
|
1098
|
-
});
|
|
1099
|
-
};
|
|
1100
|
-
var U32LE = /* @__PURE__ */ intView(4, false, {
|
|
1101
|
-
read: (view2, pos) => view2.getUint32(pos, true),
|
|
1102
|
-
write: (view2, value) => view2.setUint32(0, value, true)
|
|
1103
|
-
});
|
|
1104
|
-
var U16LE = /* @__PURE__ */ intView(2, false, {
|
|
1105
|
-
read: (view2, pos) => view2.getUint16(pos, true),
|
|
1106
|
-
write: (view2, value) => view2.setUint16(0, value, true)
|
|
1107
|
-
});
|
|
1108
|
-
var U8 = /* @__PURE__ */ intView(1, false, {
|
|
1109
|
-
read: (view2, pos) => view2.getUint8(pos),
|
|
1110
|
-
write: (view2, value) => view2.setUint8(0, value)
|
|
1111
|
-
});
|
|
1112
699
|
var ARKADE_OP = {
|
|
1113
700
|
// Merkle Branch Verification (0xb3 — repurposed NOP4 slot)
|
|
1114
701
|
MERKLEBRANCHVERIFY: 179,
|
|
702
|
+
PUT: 187,
|
|
1115
703
|
// Digest (0xc3)
|
|
1116
704
|
DIGEST: 195,
|
|
1117
705
|
// SHA256 Streaming (0xc4-0xc6)
|
|
@@ -1143,7 +731,10 @@ var ARKADE_OP = {
|
|
|
1143
731
|
BIN2NUM: 216,
|
|
1144
732
|
REVERSEBYTES: 217,
|
|
1145
733
|
MODEXP: 218,
|
|
1146
|
-
//
|
|
734
|
+
// VTXO Expiry & Emulator Clock (0xdb-0xdc)
|
|
735
|
+
PUSHEXPIRY: 219,
|
|
736
|
+
CHECKTIME: 220,
|
|
737
|
+
// 0xdd-0xdf are unassigned (OP_UNKNOWN221-223)
|
|
1147
738
|
// EC Operations (0xe0-0xe2)
|
|
1148
739
|
ECADD: 224,
|
|
1149
740
|
ECMUL: 225,
|
|
@@ -1172,7 +763,10 @@ var ARKADE_OP = {
|
|
|
1172
763
|
INSPECTPACKET: 244,
|
|
1173
764
|
INSPECTINPUTPACKET: 245,
|
|
1174
765
|
// Signature Hash (0xf6)
|
|
1175
|
-
SIGHASH: 246
|
|
766
|
+
SIGHASH: 246,
|
|
767
|
+
// Continuation & Intent Introspection (0xf7-0xf8)
|
|
768
|
+
TUNNEL: 247,
|
|
769
|
+
INSPECTINTENTMESSAGE: 248
|
|
1176
770
|
};
|
|
1177
771
|
var ARKADE_OPCODES = Object.values(ARKADE_OP);
|
|
1178
772
|
var ARKADE_OPCODE_NAMES = Object.fromEntries(
|
|
@@ -1268,7 +862,7 @@ var ArkadeOPNames = {};
|
|
|
1268
862
|
for (const [k, v] of Object.entries(ARKADE_OPS)) {
|
|
1269
863
|
if (typeof v === "number") ArkadeOPNames[v] = k;
|
|
1270
864
|
}
|
|
1271
|
-
var ArkadeScript = wrap({
|
|
865
|
+
var ArkadeScript = P.wrap({
|
|
1272
866
|
encodeStream: (w, value) => {
|
|
1273
867
|
for (let o of value) {
|
|
1274
868
|
if (typeof o === "string") {
|
|
@@ -1294,10 +888,10 @@ var ArkadeScript = wrap({
|
|
|
1294
888
|
w.byte(len);
|
|
1295
889
|
} else if (len <= 65535) {
|
|
1296
890
|
w.byte(OP.PUSHDATA2);
|
|
1297
|
-
w.bytes(U16LE.encode(len));
|
|
891
|
+
w.bytes(P.U16LE.encode(len));
|
|
1298
892
|
} else {
|
|
1299
893
|
w.byte(OP.PUSHDATA4);
|
|
1300
|
-
w.bytes(U32LE.encode(len));
|
|
894
|
+
w.bytes(P.U32LE.encode(len));
|
|
1301
895
|
}
|
|
1302
896
|
w.bytes(o);
|
|
1303
897
|
}
|
|
@@ -1309,9 +903,9 @@ var ArkadeScript = wrap({
|
|
|
1309
903
|
if (OP.OP_0 < cur && cur <= OP.PUSHDATA4) {
|
|
1310
904
|
let len;
|
|
1311
905
|
if (cur < OP.PUSHDATA1) len = cur;
|
|
1312
|
-
else if (cur === OP.PUSHDATA1) len = U8.decodeStream(r);
|
|
1313
|
-
else if (cur === OP.PUSHDATA2) len = U16LE.decodeStream(r);
|
|
1314
|
-
else if (cur === OP.PUSHDATA4) len = U32LE.decodeStream(r);
|
|
906
|
+
else if (cur === OP.PUSHDATA1) len = P.U8.decodeStream(r);
|
|
907
|
+
else if (cur === OP.PUSHDATA2) len = P.U16LE.decodeStream(r);
|
|
908
|
+
else if (cur === OP.PUSHDATA4) len = P.U32LE.decodeStream(r);
|
|
1315
909
|
else throw new Error("Should be not possible");
|
|
1316
910
|
out.push(r.bytes(len));
|
|
1317
911
|
} else if (cur === 0) {
|
|
@@ -1593,54 +1187,19 @@ var VHTLC;
|
|
|
1593
1187
|
/**
|
|
1594
1188
|
* Return the timelocked non-interactive refund tapleaf and its ArkadeScript.
|
|
1595
1189
|
*
|
|
1596
|
-
*
|
|
1597
|
-
*
|
|
1598
|
-
*
|
|
1599
|
-
*
|
|
1600
|
-
* the
|
|
1601
|
-
*
|
|
1190
|
+
* Spent through the generic covenant path ({@link EmulatorProvider},
|
|
1191
|
+
* {@link ArkadeTransactionBuilder}): build the ark tx on this leaf plus its checkpoint;
|
|
1192
|
+
* attach this ArkadeScript to the input in an `EmulatorPacket` (type 1, empty witness:
|
|
1193
|
+
* the script pushes its own index with `PUSHCURRENTINPUTINDEX`) inside an `Extension`
|
|
1194
|
+
* OP_RETURN; attach the input's creating ark tx as `PrevArkTx` (the emulator can't
|
|
1195
|
+
* otherwise resolve its prevout); POST to the emulator's `/v1/tx`. The emulator co-signs
|
|
1196
|
+
* for `nirCosigner` only if `enforcePayTo(senderPkScript)` holds, and finalizes with arkd.
|
|
1197
|
+
* `server`'s signature is still required at consensus level, outside the covenant.
|
|
1602
1198
|
*
|
|
1603
|
-
*
|
|
1604
|
-
*
|
|
1605
|
-
*
|
|
1606
|
-
*
|
|
1607
|
-
* input via an `EmulatorPacket` (type 1) — `{ vin, script:
|
|
1608
|
-
* <this ArkadeScript>, witness: <empty> }`, empty because the
|
|
1609
|
-
* script pushes its own input/output index with
|
|
1610
|
-
* `PUSHCURRENTINPUTINDEX` rather than reading one from the
|
|
1611
|
-
* witness — wrapped in an `Extension` OP_RETURN output on the
|
|
1612
|
-
* ark tx.
|
|
1613
|
-
* 3. Attach the spent input's OWN creating ark tx as `PrevArkTx` on
|
|
1614
|
-
* input 0 — required so the emulator can resolve that input's
|
|
1615
|
-
* prevout pkScript/value; it does not otherwise have them.
|
|
1616
|
-
* 4. POST the (base64-PSBT) ark tx and checkpoint(s) as `{ arkTx,
|
|
1617
|
-
* checkpointTxs }` to the emulator's `POST /v1/tx`.
|
|
1618
|
-
*
|
|
1619
|
-
* THE COVENANT CHECK the emulator runs against that ArkadeScript —
|
|
1620
|
-
* `enforcePayTo(senderPkScript)`, see that function above — is: the
|
|
1621
|
-
* output at this SAME input's index is a v1 P2TR output paying
|
|
1622
|
-
* `senderPkScript`, with a value at least the input's. Only on that
|
|
1623
|
-
* check passing does the emulator sign for `nirCosigner` (the
|
|
1624
|
-
* `emulatorPubkey` tweaked by this ArkadeScript's hash); the
|
|
1625
|
-
* response carries the fully co-signed `signedArkTx` and
|
|
1626
|
-
* `signedCheckpointTxs` — `ArkadeTransactionBuilder.send()`'s own
|
|
1627
|
-
* comment on this path: "the emulator executes the arkade script
|
|
1628
|
-
* and finalizes with arkd" — no separate call to arkd is made by
|
|
1629
|
-
* this SDK for a covenant spend.
|
|
1630
|
-
* Neither `server` nor `receiver` play any part in that check: this
|
|
1631
|
-
* leaf's tapscript still requires `server`'s own signature
|
|
1632
|
-
* alongside `nirCosigner`'s (see the class doc above), but that is
|
|
1633
|
-
* consensus-level multisig, not something the covenant enforces.
|
|
1634
|
-
*
|
|
1635
|
-
* NOT SPENDABLE UNTIL `refundLocktime` MATURES — the tapscript's
|
|
1636
|
-
* `OP_CHECKLOCKTIMEVERIFY` is arkd's concern, not the emulator's;
|
|
1637
|
-
* the emulator will happily co-sign an immature spend and arkd will
|
|
1638
|
-
* then refuse it. A block-height-typed `refundLocktime` (below the
|
|
1639
|
-
* standard height/timestamp boundary this SDK names
|
|
1640
|
-
* `CLTV_HEIGHT_THRESHOLD`, 500,000,000, in
|
|
1641
|
-
* `src/contracts/handlers/helpers.ts`) is refused by arkd for a
|
|
1642
|
-
* forfeit-eligible leaf independent of maturity — use a
|
|
1643
|
-
* seconds-typed (absolute Unix timestamp) value.
|
|
1199
|
+
* The emulator does not check `refundLocktime`: it co-signs an immature spend and arkd's
|
|
1200
|
+
* CLTV refuses it. arkd also refuses a block-height `refundLocktime`
|
|
1201
|
+
* (< `CLTV_HEIGHT_THRESHOLD`, 500,000,000) on a forfeit-eligible leaf regardless of
|
|
1202
|
+
* maturity: use a seconds-typed (Unix timestamp) value.
|
|
1644
1203
|
*/
|
|
1645
1204
|
nonInteractiveRefundWithoutReceiver() {
|
|
1646
1205
|
if (!this.nonInteractiveRefundWithoutReceiverScript || !this.nonInteractiveRefundWithoutReceiverArkadeScript) {
|
|
@@ -1783,10 +1342,7 @@ function enforcePayToAsset(destinationPkScript, asset) {
|
|
|
1783
1342
|
}
|
|
1784
1343
|
const inspectionTxid = Uint8Array.from(asset.txid).reverse();
|
|
1785
1344
|
return ArkadeScript.encode([
|
|
1786
|
-
// The output carries at least
|
|
1787
|
-
// Output index is the input's -- the same index alignment the sat
|
|
1788
|
-
// covenant relies on, and the same liveness obligation on whoever
|
|
1789
|
-
// assembles the spend.
|
|
1345
|
+
// The output at the input's index carries at least the input's amount of the asset.
|
|
1790
1346
|
"PUSHCURRENTINPUTINDEX",
|
|
1791
1347
|
inspectionTxid,
|
|
1792
1348
|
asset.groupIndex,
|
|
@@ -1850,139 +1406,18 @@ var VHTLCContractHandler = {
|
|
|
1850
1406
|
};
|
|
1851
1407
|
},
|
|
1852
1408
|
/**
|
|
1853
|
-
* Select spending path based on context.
|
|
1854
|
-
*
|
|
1855
|
-
* Role is determined from `context.role` or by matching
|
|
1856
|
-
* `context.walletDescriptor`
|
|
1857
|
-
* against sender/receiver in contract params.
|
|
1409
|
+
* Select spending path based on context. Role comes from `context.role` or from matching
|
|
1410
|
+
* `context.walletDescriptor` against sender/receiver.
|
|
1858
1411
|
*/
|
|
1859
1412
|
selectPath(script, contract, context) {
|
|
1860
|
-
|
|
1861
|
-
const preimage = contract.params?.preimage;
|
|
1862
|
-
const refundLocktime = BigInt(contract.params.refundLocktime);
|
|
1863
|
-
if (!role) {
|
|
1864
|
-
return null;
|
|
1865
|
-
}
|
|
1866
|
-
if (context.collaborative) {
|
|
1867
|
-
if (role === "receiver" && preimage) {
|
|
1868
|
-
return {
|
|
1869
|
-
leaf: script.claim(),
|
|
1870
|
-
extraWitness: [hex.decode(preimage)]
|
|
1871
|
-
};
|
|
1872
|
-
}
|
|
1873
|
-
if (role === "sender" && isCltvSatisfied(context, refundLocktime)) {
|
|
1874
|
-
return {
|
|
1875
|
-
leaf: script.refundWithoutReceiver()
|
|
1876
|
-
};
|
|
1877
|
-
}
|
|
1878
|
-
return null;
|
|
1879
|
-
}
|
|
1880
|
-
if (role === "receiver" && preimage) {
|
|
1881
|
-
const sequence = Number(contract.params.claimDelay);
|
|
1882
|
-
if (!isCsvSpendable(context, sequence)) return null;
|
|
1883
|
-
return {
|
|
1884
|
-
leaf: script.unilateralClaim(),
|
|
1885
|
-
extraWitness: [hex.decode(preimage)],
|
|
1886
|
-
sequence
|
|
1887
|
-
};
|
|
1888
|
-
}
|
|
1889
|
-
if (role === "sender") {
|
|
1890
|
-
const sequence = Number(contract.params.refundNoReceiverDelay);
|
|
1891
|
-
if (!isCsvSpendable(context, sequence)) return null;
|
|
1892
|
-
return {
|
|
1893
|
-
leaf: script.unilateralRefundWithoutReceiver(),
|
|
1894
|
-
sequence
|
|
1895
|
-
};
|
|
1896
|
-
}
|
|
1897
|
-
return null;
|
|
1413
|
+
return selectVhtlcPath(script, contract, context);
|
|
1898
1414
|
},
|
|
1899
|
-
/**
|
|
1900
|
-
* Get all possible spending paths (no timelock checks).
|
|
1901
|
-
*
|
|
1902
|
-
* Role is determined from `context.role` or by matching
|
|
1903
|
-
* `context.walletDescriptor`
|
|
1904
|
-
* against sender/receiver in contract params.
|
|
1905
|
-
*/
|
|
1415
|
+
/** All possible spending paths (no timelock checks); role as in {@link selectPath}. */
|
|
1906
1416
|
getAllSpendingPaths(script, contract, context) {
|
|
1907
|
-
|
|
1908
|
-
const paths = [];
|
|
1909
|
-
if (!role) {
|
|
1910
|
-
return paths;
|
|
1911
|
-
}
|
|
1912
|
-
const preimage = contract.params?.preimage;
|
|
1913
|
-
if (context.collaborative) {
|
|
1914
|
-
if (role === "receiver" && preimage) {
|
|
1915
|
-
paths.push({
|
|
1916
|
-
leaf: script.claim(),
|
|
1917
|
-
extraWitness: [hex.decode(preimage)]
|
|
1918
|
-
});
|
|
1919
|
-
}
|
|
1920
|
-
if (role === "sender") {
|
|
1921
|
-
paths.push({
|
|
1922
|
-
leaf: script.refundWithoutReceiver()
|
|
1923
|
-
});
|
|
1924
|
-
}
|
|
1925
|
-
} else {
|
|
1926
|
-
if (role === "receiver" && preimage) {
|
|
1927
|
-
const sequence = Number(contract.params.claimDelay);
|
|
1928
|
-
paths.push({
|
|
1929
|
-
leaf: script.unilateralClaim(),
|
|
1930
|
-
extraWitness: [hex.decode(preimage)],
|
|
1931
|
-
sequence
|
|
1932
|
-
});
|
|
1933
|
-
}
|
|
1934
|
-
if (role === "sender") {
|
|
1935
|
-
const sequence = Number(contract.params.refundNoReceiverDelay);
|
|
1936
|
-
paths.push({
|
|
1937
|
-
leaf: script.unilateralRefundWithoutReceiver(),
|
|
1938
|
-
sequence
|
|
1939
|
-
});
|
|
1940
|
-
}
|
|
1941
|
-
}
|
|
1942
|
-
return paths;
|
|
1417
|
+
return vhtlcAllSpendingPaths(script, contract, context);
|
|
1943
1418
|
},
|
|
1944
1419
|
getSpendablePaths(script, contract, context) {
|
|
1945
|
-
|
|
1946
|
-
const paths = [];
|
|
1947
|
-
if (!role) {
|
|
1948
|
-
return paths;
|
|
1949
|
-
}
|
|
1950
|
-
const preimage = contract.params?.preimage;
|
|
1951
|
-
const refundLocktime = BigInt(contract.params.refundLocktime);
|
|
1952
|
-
if (context.collaborative) {
|
|
1953
|
-
if (role === "receiver" && preimage) {
|
|
1954
|
-
paths.push({
|
|
1955
|
-
leaf: script.claim(),
|
|
1956
|
-
extraWitness: [hex.decode(preimage)]
|
|
1957
|
-
});
|
|
1958
|
-
}
|
|
1959
|
-
if (role === "sender" && isCltvSatisfied(context, refundLocktime)) {
|
|
1960
|
-
paths.push({
|
|
1961
|
-
leaf: script.refundWithoutReceiver()
|
|
1962
|
-
});
|
|
1963
|
-
}
|
|
1964
|
-
return paths;
|
|
1965
|
-
}
|
|
1966
|
-
if (role === "receiver" && preimage) {
|
|
1967
|
-
const sequence = Number(contract.params.claimDelay);
|
|
1968
|
-
if (isCsvSpendable(context, sequence)) {
|
|
1969
|
-
paths.push({
|
|
1970
|
-
leaf: script.unilateralClaim(),
|
|
1971
|
-
extraWitness: [hex.decode(preimage)],
|
|
1972
|
-
sequence
|
|
1973
|
-
});
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
if (role === "sender") {
|
|
1977
|
-
const sequence = Number(contract.params.refundNoReceiverDelay);
|
|
1978
|
-
if (isCsvSpendable(context, sequence)) {
|
|
1979
|
-
paths.push({
|
|
1980
|
-
leaf: script.unilateralRefundWithoutReceiver(),
|
|
1981
|
-
sequence
|
|
1982
|
-
});
|
|
1983
|
-
}
|
|
1984
|
-
}
|
|
1985
|
-
return paths;
|
|
1420
|
+
return vhtlcSpendablePaths(script, contract, context);
|
|
1986
1421
|
},
|
|
1987
1422
|
/**
|
|
1988
1423
|
* Refuse an explicit spend of a lockup whose refund path has not opened.
|
|
@@ -1993,70 +1428,38 @@ var VHTLCContractHandler = {
|
|
|
1993
1428
|
assertVhtlcSpendableNow(contract, context);
|
|
1994
1429
|
},
|
|
1995
1430
|
/**
|
|
1996
|
-
* Never. A live VHTLC is escrow:
|
|
1997
|
-
*
|
|
1998
|
-
* lockup out from under a swap the counterparty is still entitled to
|
|
1999
|
-
* complete, or race a claim already in flight.
|
|
2000
|
-
*
|
|
2001
|
-
* Two narrow reasons, and neither is "spending this would destroy the
|
|
2002
|
-
* VTXO". It would not: the leaf {@link deriveTapscripts} stamps is
|
|
2003
|
-
* `refundWithoutReceiver` — `CLTV[sender, server]`, the sender's OWN
|
|
2004
|
-
* refund, which the server rejects until `refundLocktime` matures. The
|
|
2005
|
-
* reasons are that an escrowed lockup must not count toward the
|
|
2006
|
-
* `available` balance bucket, and that generic RENEWAL must not silently
|
|
2007
|
-
* execute a refund the caller never asked for — `runPeriodicSettle` selects
|
|
2008
|
-
* through `getSpendableVtxos`, which this gate filters, and it runs
|
|
2009
|
-
* unprompted whenever a wallet is built without an explicit
|
|
2010
|
-
* `settlementConfig`.
|
|
1431
|
+
* Never. A live VHTLC is escrow: generic selection (send, settle, renewal, offboard) would
|
|
1432
|
+
* move the lockup out from under a swap the counterparty may still complete, or race a claim.
|
|
2011
1433
|
*
|
|
2012
|
-
*
|
|
2013
|
-
*
|
|
2014
|
-
*
|
|
2015
|
-
*
|
|
1434
|
+
* The stamped leaf is the sender's own CLTV refund, so this is not about destroying the
|
|
1435
|
+
* VTXO: an escrowed lockup must not count toward the `available` balance, and generic
|
|
1436
|
+
* renewal (`runPeriodicSettle`, unprompted without an explicit `settlementConfig`) must not
|
|
1437
|
+
* silently execute a refund nobody asked for.
|
|
2016
1438
|
*
|
|
2017
|
-
*
|
|
2018
|
-
*
|
|
1439
|
+
* **Inseparable from {@link deriveTapscripts}**: deriving the leaf without closing this gate
|
|
1440
|
+
* hands renewal an escrow. Recovery filters on {@link assertSpendableNow} instead; this
|
|
1441
|
+
* permanent gate would strand a matured lockup.
|
|
2019
1442
|
*/
|
|
2020
1443
|
isGenericallySpendable: () => false,
|
|
2021
1444
|
/**
|
|
2022
1445
|
* The annotation leaf stamped onto every VTXO locked to this contract.
|
|
2023
1446
|
*
|
|
2024
|
-
* **
|
|
2025
|
-
* `
|
|
2026
|
-
*
|
|
2027
|
-
* script version has a `forfeit()` — `VtxoScript` does not define one and
|
|
2028
|
-
* `VHTLC.BaseScript` does not add one. The fallback therefore threw
|
|
2029
|
-
* `legacy.forfeit is not a function`, `annotatableIn` caught it, and
|
|
2030
|
-
* `fetchContractVtxosBulk` dropped this contract's VTXOs before they were
|
|
2031
|
-
* persisted. The row existed and was watched while its balance stayed
|
|
2032
|
-
* permanently invisible, and `getSyncState()` reported `degraded` forever.
|
|
1447
|
+
* **Required, not an optimization.** Without it `deriveContractTapscripts` falls back to
|
|
1448
|
+
* `script.forfeit()`, which no VHTLC script has, so the contract's VTXOs are dropped before
|
|
1449
|
+
* persisting: balance invisible, `getSyncState()` degraded forever.
|
|
2033
1450
|
*
|
|
2034
|
-
* `refundWithoutReceiver` is the
|
|
2035
|
-
*
|
|
2036
|
-
*
|
|
2037
|
-
*
|
|
2038
|
-
* the receiver and need a preimage the sender does not have; `refund` and
|
|
2039
|
-
* `unilateralRefund` both need the counterparty's signature, which this
|
|
2040
|
-
* protocol has no message to ask for. V1 has no covenant leaves at all.
|
|
1451
|
+
* `refundWithoutReceiver` is the only collaborative path this wallet can satisfy as sender
|
|
1452
|
+
* (kept in step with `selectPath`): the claim leaves need the preimage, and `refund` /
|
|
1453
|
+
* `unilateralRefund` need a counterparty signature the protocol can't request. V1 has no
|
|
1454
|
+
* covenant leaves.
|
|
2041
1455
|
*
|
|
2042
|
-
* **It carries a CLTV
|
|
2043
|
-
*
|
|
2044
|
-
*
|
|
2045
|
-
*
|
|
2046
|
-
* derived per contract and knows no clock; `recoverVtxos` filters on
|
|
2047
|
-
* {@link assertSpendableNow} for it.
|
|
2048
|
-
*
|
|
2049
|
-
* **Role-blind.** A receiver's row gets the same leaf, which names keys that
|
|
2050
|
-
* wallet does not hold, so it is satisfiable only by the wallet holding the
|
|
2051
|
-
* lockup's `sender` key and fails at intent registration for anyone else.
|
|
1456
|
+
* **It carries a CLTV**: a settlement on it is rejected until `refundLocktime` matures, and
|
|
1457
|
+
* the per-contract annotation knows no clock, so `recoverVtxos` filters on
|
|
1458
|
+
* {@link assertSpendableNow}. **Role-blind**: a receiver's row gets the same leaf, satisfiable
|
|
1459
|
+
* only by the `sender` key holder; anyone else fails at intent registration.
|
|
2052
1460
|
*/
|
|
2053
1461
|
deriveTapscripts(script) {
|
|
2054
|
-
|
|
2055
|
-
return {
|
|
2056
|
-
forfeitTapLeafScript: leaf,
|
|
2057
|
-
intentTapLeafScript: leaf,
|
|
2058
|
-
tapTree: script.encode()
|
|
2059
|
-
};
|
|
1462
|
+
return deriveVhtlcTapscripts(script);
|
|
2060
1463
|
}
|
|
2061
1464
|
};
|
|
2062
1465
|
var parseGroupIndex = (raw) => {
|
|
@@ -2095,43 +1498,21 @@ var VHTLCV2ContractHandler = {
|
|
|
2095
1498
|
refundNoReceiverDelay: timelockToSequence(
|
|
2096
1499
|
params.unilateralRefundWithoutReceiverDelay
|
|
2097
1500
|
).toString(),
|
|
2098
|
-
//
|
|
2099
|
-
//
|
|
2100
|
-
//
|
|
2101
|
-
// The group maps onto them without loss — one emulator key serves
|
|
2102
|
-
// both covenant destinations by construction (see the option's doc
|
|
2103
|
-
// on VHTLC.Options), so the two emulator-key columns always hold
|
|
2104
|
-
// the same value on a row written from here.
|
|
2105
|
-
//
|
|
2106
|
-
// Spread rather than written as `undefined`: a `Record<string,
|
|
2107
|
-
// string>` round-tripped through a repository must not gain keys
|
|
2108
|
-
// whose value is the string "undefined".
|
|
1501
|
+
// Per-leaf on-disk keys predate the grouped param and older rows carry exactly these;
|
|
1502
|
+
// both emulator columns hold the same key. Spread, not `undefined`, so a repository
|
|
1503
|
+
// round-trip never gains "undefined" string values.
|
|
2109
1504
|
...covenants && {
|
|
2110
1505
|
nonInteractiveClaimReceiverPkScript: hex.encode(covenants.receiverPkScript),
|
|
2111
1506
|
nonInteractiveClaimEmulatorPubkey: hex.encode(covenants.emulatorPubkey),
|
|
2112
1507
|
nonInteractiveRefundSenderPkScript: hex.encode(covenants.senderPkScript),
|
|
2113
1508
|
nonInteractiveRefundEmulatorPubkey: hex.encode(covenants.emulatorPubkey),
|
|
2114
|
-
// The legacy marker is
|
|
2115
|
-
// row carrying it re-derives the full suite (nine leaves), a
|
|
2116
|
-
// row lacking it the pre-timelocked-refund eight — the same
|
|
2117
|
-
// encoding older SDKs wrote for eight-leaf rows, so those rows
|
|
2118
|
-
// read back unchanged. Spread rather than a "false"/"undefined"
|
|
2119
|
-
// string: a dropped flag re-derives the EIGHT-leaf script, a
|
|
2120
|
-
// different pkScript, and registration dies at
|
|
2121
|
-
// `upsertContractRow` with an opaque `Script mismatch`.
|
|
1509
|
+
// The legacy (eight-leaf) marker is this key's ABSENCE, as older SDKs wrote it.
|
|
2122
1510
|
...covenants.legacy === void 0 && {
|
|
2123
1511
|
nonInteractiveRefundWithoutReceiver: "1"
|
|
2124
1512
|
}
|
|
2125
1513
|
},
|
|
2126
|
-
//
|
|
2127
|
-
//
|
|
2128
|
-
// these params; dropping the asset derives the SAT-ONLY script, so
|
|
2129
|
-
// registration died at `upsertContractRow` with a `Script mismatch`
|
|
2130
|
-
// naming two hex strings and no cause. Same silent-drop class
|
|
2131
|
-
// `validateOptions` refuses one layer up.
|
|
2132
|
-
//
|
|
2133
|
-
// Two keys rather than one blob, mirroring the script's own view of
|
|
2134
|
-
// an Asset ID as a (txid, groupIndex) pair.
|
|
1514
|
+
// Must round-trip: dropping the asset re-derives the sat-only script and registration
|
|
1515
|
+
// dies at `upsertContractRow` with an opaque `Script mismatch`.
|
|
2135
1516
|
...params.asset && {
|
|
2136
1517
|
assetTxid: hex.encode(params.asset.txid),
|
|
2137
1518
|
assetGroupIndex: params.asset.groupIndex.toString()
|
|
@@ -2202,8 +1583,6 @@ var VHTLCV2ContractHandler = {
|
|
|
2202
1583
|
receiverPkScript: claim.destination,
|
|
2203
1584
|
senderPkScript: refund.destination,
|
|
2204
1585
|
emulatorPubkey: claim.emulatorPubkey,
|
|
2205
|
-
// Absence of the flag IS the legacy marker — the same
|
|
2206
|
-
// encoding older SDKs wrote for eight-leaf rows.
|
|
2207
1586
|
...params.nonInteractiveRefundWithoutReceiver !== "1" && {
|
|
2208
1587
|
legacy: "preTimelockedRefund"
|
|
2209
1588
|
}
|
|
@@ -2212,139 +1591,18 @@ var VHTLCV2ContractHandler = {
|
|
|
2212
1591
|
};
|
|
2213
1592
|
},
|
|
2214
1593
|
/**
|
|
2215
|
-
* Select spending path based on context.
|
|
2216
|
-
*
|
|
2217
|
-
* Role is determined from `context.role` or by matching
|
|
2218
|
-
* `context.walletDescriptor`
|
|
2219
|
-
* against sender/receiver in contract params.
|
|
1594
|
+
* Select spending path based on context. Role comes from `context.role` or by matching
|
|
1595
|
+
* `context.walletDescriptor` against sender/receiver.
|
|
2220
1596
|
*/
|
|
2221
1597
|
selectPath(script, contract, context) {
|
|
2222
|
-
|
|
2223
|
-
const preimage = contract.params?.preimage;
|
|
2224
|
-
const refundLocktime = BigInt(contract.params.refundLocktime);
|
|
2225
|
-
if (!role) {
|
|
2226
|
-
return null;
|
|
2227
|
-
}
|
|
2228
|
-
if (context.collaborative) {
|
|
2229
|
-
if (role === "receiver" && preimage) {
|
|
2230
|
-
return {
|
|
2231
|
-
leaf: script.claim(),
|
|
2232
|
-
extraWitness: [hex.decode(preimage)]
|
|
2233
|
-
};
|
|
2234
|
-
}
|
|
2235
|
-
if (role === "sender" && isCltvSatisfied(context, refundLocktime)) {
|
|
2236
|
-
return {
|
|
2237
|
-
leaf: script.refundWithoutReceiver()
|
|
2238
|
-
};
|
|
2239
|
-
}
|
|
2240
|
-
return null;
|
|
2241
|
-
}
|
|
2242
|
-
if (role === "receiver" && preimage) {
|
|
2243
|
-
const sequence = Number(contract.params.claimDelay);
|
|
2244
|
-
if (!isCsvSpendable(context, sequence)) return null;
|
|
2245
|
-
return {
|
|
2246
|
-
leaf: script.unilateralClaim(),
|
|
2247
|
-
extraWitness: [hex.decode(preimage)],
|
|
2248
|
-
sequence
|
|
2249
|
-
};
|
|
2250
|
-
}
|
|
2251
|
-
if (role === "sender") {
|
|
2252
|
-
const sequence = Number(contract.params.refundNoReceiverDelay);
|
|
2253
|
-
if (!isCsvSpendable(context, sequence)) return null;
|
|
2254
|
-
return {
|
|
2255
|
-
leaf: script.unilateralRefundWithoutReceiver(),
|
|
2256
|
-
sequence
|
|
2257
|
-
};
|
|
2258
|
-
}
|
|
2259
|
-
return null;
|
|
1598
|
+
return selectVhtlcPath(script, contract, context);
|
|
2260
1599
|
},
|
|
2261
|
-
/**
|
|
2262
|
-
* Get all possible spending paths (no timelock checks).
|
|
2263
|
-
*
|
|
2264
|
-
* Role is determined from `context.role` or by matching
|
|
2265
|
-
* `context.walletDescriptor`
|
|
2266
|
-
* against sender/receiver in contract params.
|
|
2267
|
-
*/
|
|
1600
|
+
/** Get all possible spending paths (no timelock checks); role resolved as in `selectPath`. */
|
|
2268
1601
|
getAllSpendingPaths(script, contract, context) {
|
|
2269
|
-
|
|
2270
|
-
const paths = [];
|
|
2271
|
-
if (!role) {
|
|
2272
|
-
return paths;
|
|
2273
|
-
}
|
|
2274
|
-
const preimage = contract.params?.preimage;
|
|
2275
|
-
if (context.collaborative) {
|
|
2276
|
-
if (role === "receiver" && preimage) {
|
|
2277
|
-
paths.push({
|
|
2278
|
-
leaf: script.claim(),
|
|
2279
|
-
extraWitness: [hex.decode(preimage)]
|
|
2280
|
-
});
|
|
2281
|
-
}
|
|
2282
|
-
if (role === "sender") {
|
|
2283
|
-
paths.push({
|
|
2284
|
-
leaf: script.refundWithoutReceiver()
|
|
2285
|
-
});
|
|
2286
|
-
}
|
|
2287
|
-
} else {
|
|
2288
|
-
if (role === "receiver" && preimage) {
|
|
2289
|
-
const sequence = Number(contract.params.claimDelay);
|
|
2290
|
-
paths.push({
|
|
2291
|
-
leaf: script.unilateralClaim(),
|
|
2292
|
-
extraWitness: [hex.decode(preimage)],
|
|
2293
|
-
sequence
|
|
2294
|
-
});
|
|
2295
|
-
}
|
|
2296
|
-
if (role === "sender") {
|
|
2297
|
-
const sequence = Number(contract.params.refundNoReceiverDelay);
|
|
2298
|
-
paths.push({
|
|
2299
|
-
leaf: script.unilateralRefundWithoutReceiver(),
|
|
2300
|
-
sequence
|
|
2301
|
-
});
|
|
2302
|
-
}
|
|
2303
|
-
}
|
|
2304
|
-
return paths;
|
|
1602
|
+
return vhtlcAllSpendingPaths(script, contract, context);
|
|
2305
1603
|
},
|
|
2306
1604
|
getSpendablePaths(script, contract, context) {
|
|
2307
|
-
|
|
2308
|
-
const paths = [];
|
|
2309
|
-
if (!role) {
|
|
2310
|
-
return paths;
|
|
2311
|
-
}
|
|
2312
|
-
const preimage = contract.params?.preimage;
|
|
2313
|
-
const refundLocktime = BigInt(contract.params.refundLocktime);
|
|
2314
|
-
if (context.collaborative) {
|
|
2315
|
-
if (role === "receiver" && preimage) {
|
|
2316
|
-
paths.push({
|
|
2317
|
-
leaf: script.claim(),
|
|
2318
|
-
extraWitness: [hex.decode(preimage)]
|
|
2319
|
-
});
|
|
2320
|
-
}
|
|
2321
|
-
if (role === "sender" && isCltvSatisfied(context, refundLocktime)) {
|
|
2322
|
-
paths.push({
|
|
2323
|
-
leaf: script.refundWithoutReceiver()
|
|
2324
|
-
});
|
|
2325
|
-
}
|
|
2326
|
-
return paths;
|
|
2327
|
-
}
|
|
2328
|
-
if (role === "receiver" && preimage) {
|
|
2329
|
-
const sequence = Number(contract.params.claimDelay);
|
|
2330
|
-
if (isCsvSpendable(context, sequence)) {
|
|
2331
|
-
paths.push({
|
|
2332
|
-
leaf: script.unilateralClaim(),
|
|
2333
|
-
extraWitness: [hex.decode(preimage)],
|
|
2334
|
-
sequence
|
|
2335
|
-
});
|
|
2336
|
-
}
|
|
2337
|
-
}
|
|
2338
|
-
if (role === "sender") {
|
|
2339
|
-
const sequence = Number(contract.params.refundNoReceiverDelay);
|
|
2340
|
-
if (isCsvSpendable(context, sequence)) {
|
|
2341
|
-
paths.push({
|
|
2342
|
-
leaf: script.unilateralRefundWithoutReceiver(),
|
|
2343
|
-
sequence
|
|
2344
|
-
});
|
|
2345
|
-
}
|
|
2346
|
-
}
|
|
2347
|
-
return paths;
|
|
1605
|
+
return vhtlcSpendablePaths(script, contract, context);
|
|
2348
1606
|
},
|
|
2349
1607
|
/**
|
|
2350
1608
|
* Refuse an explicit spend of a lockup whose refund path has not opened.
|
|
@@ -2354,62 +1612,28 @@ var VHTLCV2ContractHandler = {
|
|
|
2354
1612
|
assertVhtlcSpendableNow(contract, context);
|
|
2355
1613
|
},
|
|
2356
1614
|
/**
|
|
2357
|
-
* Never. A live VHTLC is escrow
|
|
2358
|
-
*
|
|
2359
|
-
*
|
|
2360
|
-
*
|
|
2361
|
-
*
|
|
2362
|
-
*
|
|
2363
|
-
* The gate covers `available` and renewal. Recovery is generic and names
|
|
2364
|
-
* nothing, so it is not covered here: `recoverVtxos` filters on
|
|
2365
|
-
* {@link assertSpendableNow} instead, which drops a lockup only while its
|
|
2366
|
-
* refund path is shut rather than forever. The explicit routes out —
|
|
2367
|
-
* `settle({ inputs })`, or `@arkade-os/swap`'s `pushRefundWithoutReceiver`
|
|
2368
|
-
* over `findLockupVtxos`' outpoints — are unaffected either way.
|
|
1615
|
+
* Never. A live VHTLC is escrow with the counterparty's claim leaf armed; generic selection
|
|
1616
|
+
* (send, settle, renewal, offboard) would move it out from under the swap or race a claim.
|
|
1617
|
+
* Recovery isn't covered by this gate: `recoverVtxos` filters on {@link assertSpendableNow},
|
|
1618
|
+
* dropping a lockup only while its refund path is shut. Explicit routes (`settle({ inputs })`,
|
|
1619
|
+
* `pushRefundWithoutReceiver`) are unaffected.
|
|
2369
1620
|
*/
|
|
2370
1621
|
isGenericallySpendable: () => false,
|
|
2371
1622
|
/**
|
|
2372
1623
|
* The annotation leaf stamped onto every VTXO locked to this contract.
|
|
2373
1624
|
*
|
|
2374
|
-
*
|
|
2375
|
-
* `
|
|
2376
|
-
*
|
|
2377
|
-
* script version has a `forfeit()` — `VtxoScript` does not define one and
|
|
2378
|
-
* `VHTLC.BaseScript` does not add one. The fallback therefore throws
|
|
2379
|
-
* `legacy.forfeit is not a function`, `annotatableIn` catches it, and
|
|
2380
|
-
* `fetchContractVtxosBulk` drops this contract's VTXOs before they are
|
|
2381
|
-
* persisted. The row would exist and be watched while its balance stayed
|
|
2382
|
-
* permanently invisible, and `getSyncState()` would report `degraded`
|
|
2383
|
-
* forever. (The `vhtlc` handler had the same gap and now closes it the same
|
|
2384
|
-
* way; nothing registers V1 rows through `ContractManager` in this repo, so
|
|
2385
|
-
* it was never hit here.)
|
|
2386
|
-
*
|
|
2387
|
-
* `refundWithoutReceiver` is the leaf, for both roles the annotation
|
|
2388
|
-
* serves, because it is the only collaborative path this wallet can
|
|
2389
|
-
* actually satisfy as the sender — the same conclusion `selectPath`
|
|
2390
|
-
* reaches, kept in step with it deliberately. The claim leaves belong to
|
|
2391
|
-
* the receiver and need a preimage the sender does not have; `refund` and
|
|
2392
|
-
* `unilateralRefund` need the counterparty; the covenant leaves are the
|
|
2393
|
-
* emulator's.
|
|
2394
|
-
*
|
|
2395
|
-
* **It carries a CLTV, and callers must respect it.** A settlement built on
|
|
2396
|
-
* this leaf is only valid once `refundLocktime` has matured, so a recovery
|
|
2397
|
-
* round that sweeps this VTXO early is rejected by the server. Nothing in
|
|
2398
|
-
* this handler can enforce it, because the annotation is derived per
|
|
2399
|
-
* contract and knows no clock. `recoverVtxos` filters on
|
|
2400
|
-
* {@link assertSpendableNow} for it.
|
|
1625
|
+
* Required, not an optimization: without {@link TapscriptDeriving} the fallback calls
|
|
1626
|
+
* `script.forfeit()`, which no VHTLC version has, so the VTXOs are silently dropped before
|
|
1627
|
+
* persisting and `getSyncState()` stays `degraded`.
|
|
2401
1628
|
*
|
|
2402
|
-
*
|
|
2403
|
-
*
|
|
2404
|
-
*
|
|
1629
|
+
* `refundWithoutReceiver` is used (in step with `selectPath`) as the only collaborative leaf
|
|
1630
|
+
* the sender can satisfy. It carries a CLTV: settling on it before `refundLocktime` matures is
|
|
1631
|
+
* rejected, and this handler has no clock, so `recoverVtxos` filters on
|
|
1632
|
+
* {@link assertSpendableNow}. Role-blind: a receiver's row gets the same leaf and fails at
|
|
1633
|
+
* intent registration.
|
|
2405
1634
|
*/
|
|
2406
1635
|
deriveTapscripts(script) {
|
|
2407
|
-
|
|
2408
|
-
return {
|
|
2409
|
-
forfeitTapLeafScript: leaf,
|
|
2410
|
-
intentTapLeafScript: leaf,
|
|
2411
|
-
tapTree: script.encode()
|
|
2412
|
-
};
|
|
1636
|
+
return deriveVhtlcTapscripts(script);
|
|
2413
1637
|
}
|
|
2414
1638
|
};
|
|
2415
1639
|
var BoardingContractHandler = {
|
|
@@ -2435,24 +1659,10 @@ var BoardingContractHandler = {
|
|
|
2435
1659
|
/** Preserves today's settle/board behaviour. */
|
|
2436
1660
|
isGenericallySpendable: () => true,
|
|
2437
1661
|
/**
|
|
2438
|
-
* Probe the on-chain
|
|
2439
|
-
*
|
|
2440
|
-
*
|
|
2441
|
-
*
|
|
2442
|
-
* boarding output becomes an L2 VTXO at the receive index, so the
|
|
2443
|
-
* indexer probe already keeps the gap window open for it; only an
|
|
2444
|
-
* *unspent* boarding output needs the on-chain probe (see plan §2).
|
|
2445
|
-
*
|
|
2446
|
-
* No-ops (returns `[]`) when boarding discovery is not plumbed — i.e.
|
|
2447
|
-
* `deps.boardingTimelock` or `deps.onchainNetwork` is absent — so the
|
|
2448
|
-
* scanner unit harness (which sets neither) is unaffected.
|
|
2449
|
-
*
|
|
2450
|
-
* Always emits `type: "boarding"`, even in the degenerate equal-delay case
|
|
2451
|
-
* where the boarding script is byte-identical to a `default` script at this
|
|
2452
|
-
* index (`boardingExitDelay === unilateralExitDelay`). The collision is no
|
|
2453
|
-
* longer pre-judged in discovery; it is tolerated FIRST-WINS at the
|
|
2454
|
-
* persistence layer ({@link ContractManager.upsertContract}). `deps.csvTimelocks`
|
|
2455
|
-
* is intentionally not read here.
|
|
1662
|
+
* Probe the **current** on-chain coin set for a boarding output at this HD index. Only an
|
|
1663
|
+
* unspent boarding output needs this: a boarded one became an L2 VTXO at the receive index,
|
|
1664
|
+
* which the indexer probe already covers. Always emits `type: "boarding"` (see the handler
|
|
1665
|
+
* doc on collisions); `deps.csvTimelocks` is intentionally not read.
|
|
2456
1666
|
*/
|
|
2457
1667
|
async discoverAt(index, descriptor, deps) {
|
|
2458
1668
|
if (!deps.boardingTimelock || !deps.onchainNetwork) return [];
|
|
@@ -2466,38 +1676,49 @@ var BoardingContractHandler = {
|
|
|
2466
1676
|
const coins = await deps.onchainProvider.getCoins(onchainAddress);
|
|
2467
1677
|
if (coins.length === 0) return [];
|
|
2468
1678
|
const scriptHex = hex.encode(script.pkScript);
|
|
2469
|
-
const boardingSeq = timelockToSequence(deps.boardingTimelock);
|
|
2470
1679
|
return [
|
|
2471
1680
|
{
|
|
2472
1681
|
type: "boarding",
|
|
2473
|
-
params: {
|
|
2474
|
-
pubKey
|
|
2475
|
-
serverPubKey:
|
|
2476
|
-
csvTimelock:
|
|
2477
|
-
},
|
|
1682
|
+
params: BoardingContractHandler.serializeParams({
|
|
1683
|
+
pubKey,
|
|
1684
|
+
serverPubKey: deps.serverPubKey,
|
|
1685
|
+
csvTimelock: deps.boardingTimelock
|
|
1686
|
+
}),
|
|
2478
1687
|
script: scriptHex,
|
|
2479
|
-
// The
|
|
2480
|
-
//
|
|
2481
|
-
// ContractWatcher keeps monitoring the same L2 script and the
|
|
2482
|
-
// VTXO repository bucket lines up (plan §6-I.4). The P2TR is
|
|
2483
|
-
// recomputed from params only for the `getCoins` probe.
|
|
1688
|
+
// The Ark address, not the P2TR: must match the row registered at init so the
|
|
1689
|
+
// watcher monitors the same L2 script and the VTXO repository bucket lines up.
|
|
2484
1690
|
address: script.address(deps.network.hrp, deps.serverPubKey).encode(),
|
|
2485
|
-
// Tag rotated rows (index > 0)
|
|
2486
|
-
// newest boarding address and descriptor-aware signing can
|
|
2487
|
-
// recover the per-index key (plan §6-II/§6-III.3). The index-0
|
|
2488
|
-
// baseline stays untagged, matching `default`/`delegate`.
|
|
1691
|
+
// Tag rotated rows (index > 0) for boot resolution and per-index signing.
|
|
2489
1692
|
...rotatedReceiveMetadata(index, descriptor)
|
|
2490
1693
|
}
|
|
2491
1694
|
];
|
|
2492
1695
|
}
|
|
2493
1696
|
};
|
|
2494
1697
|
var MinimalScriptNum = ScriptNum(void 0, true);
|
|
2495
|
-
var
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
1698
|
+
var ARKADE_TYPE_ENCODINGS = {
|
|
1699
|
+
pubkey: "raw",
|
|
1700
|
+
signature: "schnorr-64",
|
|
1701
|
+
bytes: "raw",
|
|
1702
|
+
bytes20: "raw-20",
|
|
1703
|
+
bytes32: "raw-32",
|
|
1704
|
+
asset: "raw-32",
|
|
1705
|
+
int: "scriptnum",
|
|
1706
|
+
bool: "scriptnum",
|
|
1707
|
+
AssetGroup: "scriptnum"
|
|
1708
|
+
};
|
|
1709
|
+
var SUPPORTED_PROGRAM_VERSION = 1;
|
|
1710
|
+
var UnsupportedProgramVersionError = class extends Error {
|
|
1711
|
+
constructor(version, context) {
|
|
1712
|
+
super(
|
|
1713
|
+
`${context}: unsupported program version ${String(version)}; this SDK supports version ${SUPPORTED_PROGRAM_VERSION}. Recover it with an SDK that reads version ${String(version)}, re-create it with current params, or delete it.`
|
|
1714
|
+
);
|
|
1715
|
+
this.version = version;
|
|
1716
|
+
}
|
|
1717
|
+
version;
|
|
1718
|
+
name = "UnsupportedProgramVersionError";
|
|
1719
|
+
};
|
|
2499
1720
|
function bindValue(bind, name) {
|
|
2500
|
-
const v = bind[name];
|
|
1721
|
+
const v = Object.hasOwn(bind, name) ? bind[name] : void 0;
|
|
2501
1722
|
if (v === void 0) throw new Error(`unbound parameter '${name}'`);
|
|
2502
1723
|
return v;
|
|
2503
1724
|
}
|
|
@@ -2512,6 +1733,17 @@ function resolveTimelockValue(value, args) {
|
|
|
2512
1733
|
`invalid timelock value '${value}' \u2014 expected a bigint or a '$param' reference`
|
|
2513
1734
|
);
|
|
2514
1735
|
}
|
|
1736
|
+
function resolveCsvTimelock(csv, args) {
|
|
1737
|
+
const value = resolveTimelockValue(csv.value, args);
|
|
1738
|
+
if (csv.type !== "sequence") return { type: csv.type, value };
|
|
1739
|
+
const timelock = sequenceToCanonicalTimelock(value);
|
|
1740
|
+
if (!timelock) {
|
|
1741
|
+
throw new Error(
|
|
1742
|
+
`csv '${csv.value}' resolved to ${value}, which is not a canonical BIP68 sequence`
|
|
1743
|
+
);
|
|
1744
|
+
}
|
|
1745
|
+
return timelock;
|
|
1746
|
+
}
|
|
2515
1747
|
function resolveAsm(asm, bind) {
|
|
2516
1748
|
const tokens = asm.map((t) => {
|
|
2517
1749
|
if (typeof t === "string" && t.startsWith("$")) {
|
|
@@ -2560,6 +1792,7 @@ function collectParamRefs(program) {
|
|
|
2560
1792
|
const collect = (items) => {
|
|
2561
1793
|
for (const t of items ?? []) {
|
|
2562
1794
|
if (typeof t === "string" && t.startsWith("$")) refs.add(t.slice(1));
|
|
1795
|
+
else if (isTweakedSigner(t) && t.tweak.startsWith("$")) refs.add(t.tweak.slice(1));
|
|
2563
1796
|
}
|
|
2564
1797
|
};
|
|
2565
1798
|
for (const fn of Object.values(program.functions)) {
|
|
@@ -2574,11 +1807,28 @@ function collectParamRefs(program) {
|
|
|
2574
1807
|
}
|
|
2575
1808
|
return refs;
|
|
2576
1809
|
}
|
|
2577
|
-
var TYPED_BYTE_LENGTHS = {
|
|
1810
|
+
var TYPED_BYTE_LENGTHS = {
|
|
1811
|
+
pubkey: 32,
|
|
1812
|
+
signature: 64,
|
|
1813
|
+
bytes20: 20,
|
|
1814
|
+
bytes32: 32,
|
|
1815
|
+
asset: 32
|
|
1816
|
+
};
|
|
2578
1817
|
function validateParamValue(def, value) {
|
|
2579
|
-
if (def.type
|
|
1818
|
+
if (typeof def.type !== "string" || !Object.hasOwn(ARKADE_TYPE_ENCODINGS, def.type)) {
|
|
1819
|
+
throw new Error(`program parameter '${def.name}': unknown type '${def.type}'`);
|
|
1820
|
+
}
|
|
1821
|
+
if (ARKADE_TYPE_ENCODINGS[def.type] === "scriptnum") {
|
|
2580
1822
|
if (typeof value !== "bigint" && typeof value !== "number") {
|
|
2581
|
-
throw new Error(`program parameter '${def.name}' expects
|
|
1823
|
+
throw new Error(`program parameter '${def.name}' expects ${def.type}, got bytes`);
|
|
1824
|
+
}
|
|
1825
|
+
if (typeof value === "number" && !Number.isSafeInteger(value)) {
|
|
1826
|
+
throw new Error(
|
|
1827
|
+
`program parameter '${def.name}' expects a safe integer; use bigint for larger values`
|
|
1828
|
+
);
|
|
1829
|
+
}
|
|
1830
|
+
if (def.type === "bool" && value !== 0 && value !== 1 && value !== 0n && value !== 1n) {
|
|
1831
|
+
throw new Error(`program parameter '${def.name}' expects a boolean encoded as 0 or 1`);
|
|
2582
1832
|
}
|
|
2583
1833
|
return;
|
|
2584
1834
|
}
|
|
@@ -2595,11 +1845,10 @@ function validateParamValue(def, value) {
|
|
|
2595
1845
|
}
|
|
2596
1846
|
}
|
|
2597
1847
|
function validateProgram(program, args) {
|
|
2598
|
-
const params = program.params;
|
|
2599
|
-
|
|
2600
|
-
const declared = new Set(params.map(inputName));
|
|
1848
|
+
const params = program.params ?? [];
|
|
1849
|
+
const declared = new Set(params.map((p) => p.name));
|
|
2601
1850
|
for (const name of declared) {
|
|
2602
|
-
if (args[name] === void 0) {
|
|
1851
|
+
if (!Object.hasOwn(args, name) || args[name] === void 0) {
|
|
2603
1852
|
throw new Error(`program parameter '${name}' is declared but not bound in args`);
|
|
2604
1853
|
}
|
|
2605
1854
|
}
|
|
@@ -2609,13 +1858,21 @@ function validateProgram(program, args) {
|
|
|
2609
1858
|
}
|
|
2610
1859
|
}
|
|
2611
1860
|
for (const p of params) {
|
|
2612
|
-
|
|
1861
|
+
validateParamValue(p, args[p.name]);
|
|
2613
1862
|
}
|
|
1863
|
+
for (const name of Object.keys(args)) {
|
|
1864
|
+
if (!declared.has(name)) throw new Error(`program: undeclared argument '${name}'`);
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
function isTweakedSigner(ref) {
|
|
1868
|
+
if (typeof ref !== "object" || ref === null || ref instanceof Uint8Array) return false;
|
|
1869
|
+
const { tweak, fn } = ref;
|
|
1870
|
+
return typeof tweak === "string" && typeof fn === "string";
|
|
2614
1871
|
}
|
|
2615
1872
|
function resolveSigner(ref, args) {
|
|
2616
1873
|
if (ref instanceof Uint8Array) return ref;
|
|
2617
|
-
if (!ref.startsWith("$")) {
|
|
2618
|
-
throw new Error(`unknown signer reference '${ref}' \u2014 use '
|
|
1874
|
+
if (typeof ref !== "string" || !ref.startsWith("$")) {
|
|
1875
|
+
throw new Error(`unknown signer reference '${ref}' \u2014 use a '$param' or key bytes`);
|
|
2619
1876
|
}
|
|
2620
1877
|
const v = bindValue(args, ref.slice(1));
|
|
2621
1878
|
if (!(v instanceof Uint8Array)) {
|
|
@@ -2625,7 +1882,7 @@ function resolveSigner(ref, args) {
|
|
|
2625
1882
|
}
|
|
2626
1883
|
function encodeTapscriptSegment(seg, pubkeys, args) {
|
|
2627
1884
|
if (seg.csv) {
|
|
2628
|
-
const timelock =
|
|
1885
|
+
const timelock = resolveCsvTimelock(seg.csv, args);
|
|
2629
1886
|
if (seg.asm) {
|
|
2630
1887
|
return ConditionCSVMultisigTapscript.encode({
|
|
2631
1888
|
conditionScript: resolveAsm(seg.asm, args),
|
|
@@ -2651,9 +1908,7 @@ function encodeTapscriptSegment(seg, pubkeys, args) {
|
|
|
2651
1908
|
}
|
|
2652
1909
|
function compileFunctions(program, args, keys) {
|
|
2653
1910
|
if (program.version !== SUPPORTED_PROGRAM_VERSION) {
|
|
2654
|
-
throw new
|
|
2655
|
-
`ArkadeContract: unsupported program version ${program.version} \u2014 this SDK supports version ${SUPPORTED_PROGRAM_VERSION}`
|
|
2656
|
-
);
|
|
1911
|
+
throw new UnsupportedProgramVersionError(program.version, "ArkadeContract");
|
|
2657
1912
|
}
|
|
2658
1913
|
const functions = program.functions;
|
|
2659
1914
|
const names = Object.keys(functions);
|
|
@@ -2661,18 +1916,69 @@ function compileFunctions(program, args, keys) {
|
|
|
2661
1916
|
throw new Error("ArkadeContract: program has no functions");
|
|
2662
1917
|
}
|
|
2663
1918
|
validateProgram(program, args);
|
|
1919
|
+
if (args.server !== void 0 && (!(args.server instanceof Uint8Array) || !equalBytes(args.server, keys.serverKey))) {
|
|
1920
|
+
throw new Error(
|
|
1921
|
+
"ArkadeContract: reserved server parameter must match the contract server key"
|
|
1922
|
+
);
|
|
1923
|
+
}
|
|
2664
1924
|
const defs = names.map((n) => functions[n]);
|
|
2665
|
-
const
|
|
1925
|
+
const covenants = /* @__PURE__ */ new Map();
|
|
1926
|
+
for (const [name, def] of Object.entries(functions)) {
|
|
1927
|
+
if (!def.arkadeScript) continue;
|
|
1928
|
+
const script = resolveAsm(def.arkadeScript.asm, args);
|
|
1929
|
+
for (const target of [name, ...def.group ? [def.group] : []]) {
|
|
1930
|
+
const previous = covenants.get(target);
|
|
1931
|
+
if (previous && !equalBytes(previous, script)) {
|
|
1932
|
+
throw new Error(`ArkadeContract: ambiguous covenant '${target}'`);
|
|
1933
|
+
}
|
|
1934
|
+
covenants.set(target, script);
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
const covenant = names.find(
|
|
1938
|
+
(_, i) => defs[i].arkadeScript && defs[i].tapscript.emulator !== null
|
|
1939
|
+
);
|
|
2666
1940
|
if (covenant && !keys.emulatorKey) {
|
|
2667
1941
|
throw new Error(
|
|
2668
1942
|
`ArkadeContract: function '${covenant}' has an arkadeScript but no emulator is configured \u2014 pass an \`emulator\` to Arkade.connect`
|
|
2669
1943
|
);
|
|
2670
1944
|
}
|
|
2671
1945
|
return defs.map((def, i) => {
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
1946
|
+
const pubkeys = def.tapscript.signers.map((signer) => {
|
|
1947
|
+
if (!isTweakedSigner(signer)) return resolveSigner(signer, args);
|
|
1948
|
+
const script = covenants.get(signer.fn);
|
|
1949
|
+
if (!script) {
|
|
1950
|
+
throw new Error(
|
|
1951
|
+
`ArkadeContract: function '${names[i]}' tweaks '${signer.fn}', which has no arkade script`
|
|
1952
|
+
);
|
|
1953
|
+
}
|
|
1954
|
+
return computeArkadeScriptPublicKey(resolveSigner(signer.tweak, args), script);
|
|
1955
|
+
});
|
|
1956
|
+
const arkadeScript = def.arkadeScript ? covenants.get(names[i]) : void 0;
|
|
1957
|
+
const leafPubkeys = [...pubkeys];
|
|
1958
|
+
if (arkadeScript && def.tapscript.emulator !== null) {
|
|
1959
|
+
const position = def.tapscript.emulatorIndex ?? pubkeys.length;
|
|
1960
|
+
if (!Number.isInteger(position) || position < 0 || position > pubkeys.length) {
|
|
1961
|
+
throw new Error(
|
|
1962
|
+
`ArkadeContract: function '${names[i]}' has an invalid emulator position ${position}`
|
|
1963
|
+
);
|
|
1964
|
+
}
|
|
1965
|
+
const target = def.group ? covenants.get(def.tapscript.emulator ?? def.group) : arkadeScript;
|
|
1966
|
+
if (!target || !equalBytes(target, arkadeScript)) {
|
|
1967
|
+
throw new Error(
|
|
1968
|
+
`ArkadeContract: function '${names[i]}' has an invalid emulator covenant '${def.tapscript.emulator}'`
|
|
1969
|
+
);
|
|
1970
|
+
}
|
|
1971
|
+
leafPubkeys.splice(
|
|
1972
|
+
position,
|
|
1973
|
+
0,
|
|
1974
|
+
computeArkadeScriptPublicKey(keys.emulatorKey, target)
|
|
1975
|
+
);
|
|
1976
|
+
} else if (def.tapscript.emulatorIndex !== void 0) {
|
|
1977
|
+
throw new Error(
|
|
1978
|
+
`ArkadeContract: function '${names[i]}' specifies an emulator position without an emulator`
|
|
1979
|
+
);
|
|
1980
|
+
}
|
|
1981
|
+
validateTapscript({ ...def.tapscript, signers: leafPubkeys });
|
|
2676
1982
|
const leafScript = encodeTapscriptSegment(def.tapscript, leafPubkeys, args).script;
|
|
2677
1983
|
return { name: names[i], def, leafScript, arkadeScript, signerKeys: pubkeys };
|
|
2678
1984
|
});
|
|
@@ -2700,23 +2006,72 @@ var ArkadeProgramScript = class extends VtxoScript {
|
|
|
2700
2006
|
}
|
|
2701
2007
|
};
|
|
2702
2008
|
function parseArtifact(artifact) {
|
|
2009
|
+
if (Array.isArray(artifact.functions)) {
|
|
2010
|
+
throw new Error(
|
|
2011
|
+
"parseArtifact: `functions` is an array, which is the arkadec artifact shape, not an SDK program \u2014 read it with programFromArtifact instead"
|
|
2012
|
+
);
|
|
2013
|
+
}
|
|
2014
|
+
if (typeof artifact.functions !== "object" || artifact.functions === null) {
|
|
2015
|
+
throw new Error("parseArtifact: `functions` must be an object keyed by function name");
|
|
2016
|
+
}
|
|
2703
2017
|
const hexToken = (t) => typeof t === "string" && t.startsWith("0x") ? hex.decode(t.slice(2)) : t;
|
|
2018
|
+
const signerRef = (s) => {
|
|
2019
|
+
if (s instanceof Uint8Array || typeof s === "string") return hexToken(s);
|
|
2020
|
+
if (isTweakedSigner(s)) return { tweak: s.tweak, fn: s.fn };
|
|
2021
|
+
throw new Error("parseArtifact: a tweaked signer needs string `tweak` and `fn`");
|
|
2022
|
+
};
|
|
2704
2023
|
const timelockValue = (v) => typeof v === "string" && v.startsWith("$") ? v : BigInt(v);
|
|
2705
|
-
|
|
2024
|
+
if (artifact.version !== void 0 && artifact.version !== SUPPORTED_PROGRAM_VERSION) {
|
|
2025
|
+
throw new UnsupportedProgramVersionError(artifact.version, "parseArtifact");
|
|
2026
|
+
}
|
|
2027
|
+
const declarations = [artifact.params];
|
|
2028
|
+
for (const [name, fn] of Object.entries(artifact.functions)) {
|
|
2029
|
+
if (!fn || typeof fn !== "object" || Array.isArray(fn)) {
|
|
2030
|
+
throw new Error(`parseArtifact: function '${name}' must be an object`);
|
|
2031
|
+
}
|
|
2032
|
+
const tap = fn.tapscript;
|
|
2033
|
+
if (tap !== void 0 && (!tap || typeof tap !== "object" || Array.isArray(tap))) {
|
|
2034
|
+
throw new Error(`parseArtifact: function '${name}' tapscript must be an object`);
|
|
2035
|
+
}
|
|
2036
|
+
declarations.push(fn.inputs, tap?.signatures);
|
|
2037
|
+
if (tap?.emulatorIndex !== void 0 && (!Number.isInteger(tap.emulatorIndex) || tap.emulatorIndex < 0)) {
|
|
2038
|
+
throw new Error(`parseArtifact: function '${name}' has an invalid emulator position`);
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
for (const defs of declarations) {
|
|
2042
|
+
if (defs === void 0) continue;
|
|
2043
|
+
if (!Array.isArray(defs)) {
|
|
2044
|
+
throw new Error(
|
|
2045
|
+
"parseArtifact: parameters, inputs and signatures require arrays of typed declarations"
|
|
2046
|
+
);
|
|
2047
|
+
}
|
|
2048
|
+
for (const def of defs) {
|
|
2049
|
+
if (!def || typeof def.name !== "string" || def.name.length === 0 || typeof def.type !== "string" || !Object.hasOwn(ARKADE_TYPE_ENCODINGS, def.type)) {
|
|
2050
|
+
throw new Error(
|
|
2051
|
+
"parseArtifact: parameters, inputs and signatures require typed { name, type } declarations"
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
const functions = /* @__PURE__ */ Object.create(null);
|
|
2706
2057
|
for (const [name, fn] of Object.entries(artifact.functions)) {
|
|
2707
2058
|
const tap = fn.tapscript ?? {};
|
|
2708
2059
|
const tapscript = {
|
|
2709
|
-
signers: (tap.signers ?? []).map(
|
|
2060
|
+
signers: (tap.signers ?? []).map(signerRef),
|
|
2061
|
+
...tap.signatures ? { signatures: tap.signatures } : {},
|
|
2710
2062
|
...tap.asm ? { asm: tap.asm.map(hexToken) } : {},
|
|
2711
2063
|
...tap.witness ? { witness: tap.witness.map(hexToken) } : {},
|
|
2712
2064
|
...tap.csv ? { csv: { type: tap.csv.type, value: timelockValue(tap.csv.value) } } : {},
|
|
2713
|
-
...tap.cltv !== void 0 ? { cltv: timelockValue(tap.cltv) } : {}
|
|
2065
|
+
...tap.cltv !== void 0 ? { cltv: timelockValue(tap.cltv) } : {},
|
|
2066
|
+
..."emulator" in tap ? { emulator: tap.emulator } : {},
|
|
2067
|
+
...tap.emulatorIndex !== void 0 ? { emulatorIndex: tap.emulatorIndex } : {}
|
|
2714
2068
|
};
|
|
2715
2069
|
const arkadeScript = fn.arkadeScript ? {
|
|
2716
2070
|
asm: fn.arkadeScript.asm.map(hexToken),
|
|
2717
2071
|
...fn.arkadeScript.witness ? { witness: fn.arkadeScript.witness.map(hexToken) } : {}
|
|
2718
2072
|
} : void 0;
|
|
2719
2073
|
functions[name] = {
|
|
2074
|
+
...fn.group !== void 0 ? { group: fn.group } : {},
|
|
2720
2075
|
...fn.inputs ? { inputs: fn.inputs } : {},
|
|
2721
2076
|
tapscript,
|
|
2722
2077
|
...arkadeScript ? { arkadeScript } : {}
|
|
@@ -2740,17 +2095,21 @@ function stringifyArtifact(program) {
|
|
|
2740
2095
|
}
|
|
2741
2096
|
return t;
|
|
2742
2097
|
};
|
|
2743
|
-
const functions =
|
|
2098
|
+
const functions = /* @__PURE__ */ Object.create(null);
|
|
2744
2099
|
for (const [name, fn] of Object.entries(program.functions)) {
|
|
2745
2100
|
const tap = fn.tapscript;
|
|
2746
2101
|
functions[name] = {
|
|
2102
|
+
...fn.group !== void 0 ? { group: fn.group } : {},
|
|
2747
2103
|
...fn.inputs ? { inputs: fn.inputs } : {},
|
|
2748
2104
|
tapscript: {
|
|
2749
2105
|
signers: tap.signers.map(token),
|
|
2106
|
+
...tap.signatures ? { signatures: tap.signatures } : {},
|
|
2750
2107
|
...tap.asm ? { asm: tap.asm.map(token) } : {},
|
|
2751
2108
|
...tap.witness ? { witness: tap.witness.map(token) } : {},
|
|
2752
2109
|
...tap.csv ? { csv: { type: tap.csv.type, value: tap.csv.value.toString() } } : {},
|
|
2753
|
-
...tap.cltv !== void 0 ? { cltv: tap.cltv.toString() } : {}
|
|
2110
|
+
...tap.cltv !== void 0 ? { cltv: tap.cltv.toString() } : {},
|
|
2111
|
+
...tap.emulator !== void 0 ? { emulator: tap.emulator } : {},
|
|
2112
|
+
...tap.emulatorIndex !== void 0 ? { emulatorIndex: tap.emulatorIndex } : {}
|
|
2754
2113
|
},
|
|
2755
2114
|
...fn.arkadeScript ? {
|
|
2756
2115
|
arkadeScript: {
|
|
@@ -2772,20 +2131,12 @@ function serializeArgValue(v) {
|
|
|
2772
2131
|
if (typeof v === "bigint") return v.toString();
|
|
2773
2132
|
return v;
|
|
2774
2133
|
}
|
|
2775
|
-
function parseArgValue(v) {
|
|
2776
|
-
if (typeof v === "number") return v;
|
|
2777
|
-
if (typeof v === "string") {
|
|
2778
|
-
if (v.startsWith("0x")) return hex.decode(v.slice(2));
|
|
2779
|
-
return BigInt(v);
|
|
2780
|
-
}
|
|
2781
|
-
throw new Error(`invalid arkade arg value: ${JSON.stringify(v)}`);
|
|
2782
|
-
}
|
|
2783
2134
|
function parseTypedArgValue(name, type, v) {
|
|
2784
|
-
if (type === "
|
|
2135
|
+
if (ARKADE_TYPE_ENCODINGS[type] === "scriptnum") {
|
|
2785
2136
|
if (typeof v === "number") return v;
|
|
2786
2137
|
if (typeof v === "string") return BigInt(v);
|
|
2787
2138
|
throw new Error(
|
|
2788
|
-
`arkade contract params: '${name}' expects
|
|
2139
|
+
`arkade contract params: '${name}' expects ${type}, got ${JSON.stringify(v)}`
|
|
2789
2140
|
);
|
|
2790
2141
|
}
|
|
2791
2142
|
if (typeof v === "string" && v.startsWith("0x")) return hex.decode(v.slice(2));
|
|
@@ -2794,7 +2145,7 @@ function parseTypedArgValue(name, type, v) {
|
|
|
2794
2145
|
);
|
|
2795
2146
|
}
|
|
2796
2147
|
function serializeArkadeContractParams(typed) {
|
|
2797
|
-
const args =
|
|
2148
|
+
const args = /* @__PURE__ */ Object.create(null);
|
|
2798
2149
|
for (const [k, v] of Object.entries(typed.args)) {
|
|
2799
2150
|
args[k] = serializeArgValue(v);
|
|
2800
2151
|
}
|
|
@@ -2814,15 +2165,13 @@ function deserializeArkadeContractParams(params) {
|
|
|
2814
2165
|
throw new Error("arkade contract params: missing 'serverKey'");
|
|
2815
2166
|
}
|
|
2816
2167
|
const program = parseArtifact(JSON.parse(params.program));
|
|
2817
|
-
const paramTypes =
|
|
2818
|
-
|
|
2819
|
-
if (typeof p !== "string") paramTypes.set(p.name, p.type);
|
|
2820
|
-
}
|
|
2821
|
-
const args = {};
|
|
2168
|
+
const paramTypes = new Map((program.params ?? []).map((p) => [p.name, p.type]));
|
|
2169
|
+
const args = /* @__PURE__ */ Object.create(null);
|
|
2822
2170
|
if (params.args) {
|
|
2823
2171
|
for (const [k, v] of Object.entries(JSON.parse(params.args))) {
|
|
2824
2172
|
const type = paramTypes.get(k);
|
|
2825
|
-
|
|
2173
|
+
if (!type) throw new Error(`arkade contract params: undeclared argument '${k}'`);
|
|
2174
|
+
args[k] = parseTypedArgValue(k, type, v);
|
|
2826
2175
|
}
|
|
2827
2176
|
}
|
|
2828
2177
|
return {
|
|
@@ -2866,7 +2215,7 @@ function pathsFor(script, context, opts) {
|
|
|
2866
2215
|
continue;
|
|
2867
2216
|
}
|
|
2868
2217
|
const csvDef = fn.def.tapscript.csv;
|
|
2869
|
-
const csv = csvDef ?
|
|
2218
|
+
const csv = csvDef ? resolveCsvTimelock(csvDef, script.args) : void 0;
|
|
2870
2219
|
const cltv = fn.def.tapscript.cltv !== void 0 ? resolveTimelockValue(fn.def.tapscript.cltv, script.args) : void 0;
|
|
2871
2220
|
if (context.collaborative) {
|
|
2872
2221
|
if (csv) continue;
|
|
@@ -2962,6 +2311,6 @@ contractHandlers.register(VHTLCV2ContractHandler);
|
|
|
2962
2311
|
contractHandlers.register(BoardingContractHandler);
|
|
2963
2312
|
contractHandlers.register(ArkadeContractHandler);
|
|
2964
2313
|
|
|
2965
|
-
export { ARKADE_OP, ARKADE_OPCODES, ARKADE_OPCODE_NAMES, ARKADE_OPCODE_VALUES, ARKADE_OPS, ArkadeContractHandler, ArkadeProgramScript, ArkadeScript, BoardingContractHandler, DefaultContractHandler, DefaultVtxo, DelegateContractHandler, DelegateVtxo, OPCODE_NAMES, OPCODE_VALUES, SUPPORTED_PROGRAM_VERSION, VHTLC, VHTLCContractHandler, VHTLCV2ContractHandler, WALLET_RECEIVE_SOURCE, arkadeScriptHash, arkadeWitnessHash, asmToBytes, bignum_exports, bytesToASM, computeArkadeScriptPublicKey, contractHandlers, deriveDescriptorLeafCompressedPubKey, deriveDescriptorLeafPubKey, descriptorIsOurs, deserializeArkadeContractParams, fromASM, getOpcodeName, getOpcodeValue, identityDescriptor,
|
|
2966
|
-
//# sourceMappingURL=chunk-
|
|
2967
|
-
//# sourceMappingURL=chunk-
|
|
2314
|
+
export { ARKADE_OP, ARKADE_OPCODES, ARKADE_OPCODE_NAMES, ARKADE_OPCODE_VALUES, ARKADE_OPS, ARKADE_TYPE_ENCODINGS, ArkadeContractHandler, ArkadeProgramScript, ArkadeScript, BoardingContractHandler, DefaultContractHandler, DefaultVtxo, DelegateContractHandler, DelegateVtxo, OPCODE_NAMES, OPCODE_VALUES, SUPPORTED_PROGRAM_VERSION, UnsupportedProgramVersionError, VHTLC, VHTLCContractHandler, VHTLCV2ContractHandler, WALLET_RECEIVE_SOURCE, arkadeScriptHash, arkadeWitnessHash, asmToBytes, bignum_exports, bytesToASM, computeArkadeScriptPublicKey, contractHandlers, deriveDescriptorLeafCompressedPubKey, deriveDescriptorLeafPubKey, descriptorIsOurs, deserializeArkadeContractParams, extractPubKey, fromASM, getOpcodeName, getOpcodeValue, identityDescriptor, isCltvSatisfied, isCsvSpendable, isMainnetDescriptor, normalizeToDescriptor, parseArtifact, parseHDDescriptor, resolveAsm, serializeArkadeContractParams, speculativeReceiveMetadata, stringifyArtifact, toASM, toXOnly, validateParamValue, validateProgram, witnessRefToBytes };
|
|
2315
|
+
//# sourceMappingURL=chunk-K352GMVL.js.map
|
|
2316
|
+
//# sourceMappingURL=chunk-K352GMVL.js.map
|