@arkade-os/sdk 0.3.0-alpha.0 → 0.3.0-alpha.2
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/dist/cjs/arknote/index.js +4 -4
- package/dist/cjs/bip322/index.js +9 -7
- package/dist/cjs/forfeit.js +2 -2
- package/dist/cjs/identity/singleKey.js +10 -7
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/musig2/keys.js +1 -1
- package/dist/cjs/musig2/nonces.js +1 -1
- package/dist/cjs/musig2/sign.js +1 -1
- package/dist/cjs/networks.js +6 -6
- package/dist/cjs/providers/ark.js +53 -71
- package/dist/cjs/providers/indexer.js +45 -51
- package/dist/cjs/providers/utils.js +60 -0
- package/dist/cjs/repositories/walletRepository.js +34 -4
- package/dist/cjs/script/address.js +3 -3
- package/dist/cjs/script/base.js +7 -7
- package/dist/cjs/script/tapscript.js +29 -23
- package/dist/cjs/script/vhtlc.js +2 -2
- package/dist/cjs/tree/signingSession.js +11 -10
- package/dist/cjs/tree/txTree.js +9 -9
- package/dist/cjs/tree/validation.js +6 -6
- package/dist/cjs/utils/arkTransaction.js +5 -5
- package/dist/cjs/utils/unknownFields.js +5 -5
- package/dist/cjs/wallet/onchain.js +5 -5
- package/dist/cjs/wallet/unroll.js +6 -6
- package/dist/cjs/wallet/wallet.js +21 -22
- package/dist/esm/arknote/index.js +2 -2
- package/dist/esm/bip322/index.js +3 -1
- package/dist/esm/forfeit.js +1 -1
- package/dist/esm/identity/singleKey.js +5 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/musig2/keys.js +1 -1
- package/dist/esm/musig2/nonces.js +1 -1
- package/dist/esm/musig2/sign.js +1 -1
- package/dist/esm/networks.js +1 -1
- package/dist/esm/providers/ark.js +53 -71
- package/dist/esm/providers/indexer.js +45 -51
- package/dist/esm/providers/utils.js +57 -0
- package/dist/esm/repositories/walletRepository.js +34 -4
- package/dist/esm/script/address.js +1 -1
- package/dist/esm/script/base.js +3 -3
- package/dist/esm/script/tapscript.js +10 -4
- package/dist/esm/script/vhtlc.js +1 -1
- package/dist/esm/tree/signingSession.js +6 -5
- package/dist/esm/tree/txTree.js +5 -5
- package/dist/esm/tree/validation.js +3 -3
- package/dist/esm/utils/arkTransaction.js +2 -2
- package/dist/esm/utils/unknownFields.js +1 -1
- package/dist/esm/wallet/onchain.js +2 -2
- package/dist/esm/wallet/unroll.js +2 -2
- package/dist/esm/wallet/wallet.js +9 -10
- package/dist/types/arknote/index.d.ts +1 -1
- package/dist/types/bip322/index.d.ts +2 -2
- package/dist/types/forfeit.d.ts +1 -1
- package/dist/types/identity/index.d.ts +4 -3
- package/dist/types/identity/singleKey.d.ts +2 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/providers/ark.d.ts +1 -0
- package/dist/types/providers/utils.d.ts +1 -0
- package/dist/types/script/address.d.ts +1 -1
- package/dist/types/script/base.d.ts +1 -1
- package/dist/types/script/default.d.ts +1 -1
- package/dist/types/script/tapscript.d.ts +1 -1
- package/dist/types/script/vhtlc.d.ts +1 -1
- package/dist/types/tree/txTree.d.ts +3 -3
- package/dist/types/tree/validation.d.ts +1 -1
- package/dist/types/utils/anchor.d.ts +1 -1
- package/dist/types/utils/arkTransaction.d.ts +3 -3
- package/dist/types/utils/unknownFields.d.ts +1 -1
- package/dist/types/wallet/index.d.ts +1 -1
- package/dist/types/wallet/onchain.d.ts +2 -2
- package/dist/types/wallet/unroll.d.ts +1 -1
- package/dist/types/wallet/wallet.d.ts +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eventSourceIterator = eventSourceIterator;
|
|
4
|
+
async function* eventSourceIterator(eventSource) {
|
|
5
|
+
const messageQueue = [];
|
|
6
|
+
const errorQueue = [];
|
|
7
|
+
let messageResolve = null;
|
|
8
|
+
let errorResolve = null;
|
|
9
|
+
const messageHandler = (event) => {
|
|
10
|
+
if (messageResolve) {
|
|
11
|
+
messageResolve(event);
|
|
12
|
+
messageResolve = null;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
messageQueue.push(event);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const errorHandler = () => {
|
|
19
|
+
const error = new Error("EventSource error");
|
|
20
|
+
if (errorResolve) {
|
|
21
|
+
errorResolve(error);
|
|
22
|
+
errorResolve = null;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
errorQueue.push(error);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
eventSource.addEventListener("message", messageHandler);
|
|
29
|
+
eventSource.addEventListener("error", errorHandler);
|
|
30
|
+
try {
|
|
31
|
+
while (true) {
|
|
32
|
+
// if we have queued messages, yield the first one, remove it from the queue
|
|
33
|
+
if (messageQueue.length > 0) {
|
|
34
|
+
yield messageQueue.shift();
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
// if we have queued errors, throw the first one, remove it from the queue
|
|
38
|
+
if (errorQueue.length > 0) {
|
|
39
|
+
const error = errorQueue.shift();
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
// wait for the next message or error
|
|
43
|
+
const result = await new Promise((resolve, reject) => {
|
|
44
|
+
messageResolve = resolve;
|
|
45
|
+
errorResolve = reject;
|
|
46
|
+
}).finally(() => {
|
|
47
|
+
messageResolve = null;
|
|
48
|
+
errorResolve = null;
|
|
49
|
+
});
|
|
50
|
+
if (result) {
|
|
51
|
+
yield result;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
// clean up
|
|
57
|
+
eventSource.removeEventListener("message", messageHandler);
|
|
58
|
+
eventSource.removeEventListener("error", errorHandler);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WalletRepositoryImpl = void 0;
|
|
4
|
+
const base_1 = require("@scure/base");
|
|
5
|
+
const btc_signer_1 = require("@scure/btc-signer");
|
|
6
|
+
// Utility functions for (de)serializing complex structures
|
|
7
|
+
const toHex = (b) => (b ? base_1.hex.encode(b) : undefined);
|
|
8
|
+
const fromHex = (h) => h ? base_1.hex.decode(h) : undefined;
|
|
9
|
+
const serializeTapLeaf = ([cb, s]) => ({
|
|
10
|
+
cb: btc_signer_1.TaprootControlBlock.encode(cb) &&
|
|
11
|
+
base_1.hex.encode(btc_signer_1.TaprootControlBlock.encode(cb)),
|
|
12
|
+
s: base_1.hex.encode(s),
|
|
13
|
+
});
|
|
14
|
+
const serializeVtxo = (v) => ({
|
|
15
|
+
...v,
|
|
16
|
+
tapTree: toHex(v.tapTree),
|
|
17
|
+
forfeitTapLeafScript: serializeTapLeaf(v.forfeitTapLeafScript),
|
|
18
|
+
intentTapLeafScript: serializeTapLeaf(v.intentTapLeafScript),
|
|
19
|
+
extraWitness: v.extraWitness?.map((w) => toHex(w)),
|
|
20
|
+
});
|
|
21
|
+
const deserializeTapLeaf = (t) => {
|
|
22
|
+
const cb = btc_signer_1.TaprootControlBlock.decode(fromHex(t.cb));
|
|
23
|
+
const s = fromHex(t.s);
|
|
24
|
+
return [cb, s];
|
|
25
|
+
};
|
|
26
|
+
const deserializeVtxo = (o) => ({
|
|
27
|
+
...o,
|
|
28
|
+
tapTree: fromHex(o.tapTree),
|
|
29
|
+
forfeitTapLeafScript: deserializeTapLeaf(o.forfeitTapLeafScript),
|
|
30
|
+
intentTapLeafScript: deserializeTapLeaf(o.intentTapLeafScript),
|
|
31
|
+
extraWitness: o.extraWitness?.map((w) => fromHex(w)),
|
|
32
|
+
});
|
|
4
33
|
class WalletRepositoryImpl {
|
|
5
34
|
constructor(storage) {
|
|
6
35
|
this.storage = storage;
|
|
@@ -22,7 +51,8 @@ class WalletRepositoryImpl {
|
|
|
22
51
|
return [];
|
|
23
52
|
}
|
|
24
53
|
try {
|
|
25
|
-
const
|
|
54
|
+
const parsed = JSON.parse(stored);
|
|
55
|
+
const vtxos = parsed.map(deserializeVtxo);
|
|
26
56
|
this.cache.vtxos.set(address, vtxos);
|
|
27
57
|
return vtxos.slice();
|
|
28
58
|
}
|
|
@@ -42,7 +72,7 @@ class WalletRepositoryImpl {
|
|
|
42
72
|
vtxos.push(vtxo);
|
|
43
73
|
}
|
|
44
74
|
this.cache.vtxos.set(address, vtxos);
|
|
45
|
-
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(vtxos));
|
|
75
|
+
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(vtxos.map(serializeVtxo)));
|
|
46
76
|
}
|
|
47
77
|
async saveVtxos(address, vtxos) {
|
|
48
78
|
const storedVtxos = await this.getVtxos(address);
|
|
@@ -56,14 +86,14 @@ class WalletRepositoryImpl {
|
|
|
56
86
|
}
|
|
57
87
|
}
|
|
58
88
|
this.cache.vtxos.set(address, storedVtxos);
|
|
59
|
-
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(storedVtxos));
|
|
89
|
+
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(storedVtxos.map(serializeVtxo)));
|
|
60
90
|
}
|
|
61
91
|
async removeVtxo(address, vtxoId) {
|
|
62
92
|
const vtxos = await this.getVtxos(address);
|
|
63
93
|
const [txid, vout] = vtxoId.split(":");
|
|
64
94
|
const filtered = vtxos.filter((v) => !(v.txid === txid && v.vout === parseInt(vout)));
|
|
65
95
|
this.cache.vtxos.set(address, filtered);
|
|
66
|
-
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(filtered));
|
|
96
|
+
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(filtered.map(serializeVtxo)));
|
|
67
97
|
}
|
|
68
98
|
async clearVtxos(address) {
|
|
69
99
|
this.cache.vtxos.set(address, []);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ArkAddress = void 0;
|
|
4
4
|
const base_1 = require("@scure/base");
|
|
5
|
-
const
|
|
5
|
+
const script_js_1 = require("@scure/btc-signer/script.js");
|
|
6
6
|
/**
|
|
7
7
|
* ArkAddress allows to create and decode bech32m encoded ark address.
|
|
8
8
|
* An ark address is composed of:
|
|
@@ -66,11 +66,11 @@ class ArkAddress {
|
|
|
66
66
|
}
|
|
67
67
|
// pkScript is the script that should be used to send non-dust funds to the address
|
|
68
68
|
get pkScript() {
|
|
69
|
-
return
|
|
69
|
+
return script_js_1.Script.encode(["OP_1", this.vtxoTaprootKey]);
|
|
70
70
|
}
|
|
71
71
|
// subdustPkScript is the script that should be used to send sub-dust funds to the address
|
|
72
72
|
get subdustPkScript() {
|
|
73
|
-
return
|
|
73
|
+
return script_js_1.Script.encode(["RETURN", this.vtxoTaprootKey]);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
exports.ArkAddress = ArkAddress;
|
package/dist/cjs/script/base.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VtxoScript = void 0;
|
|
4
4
|
exports.scriptFromTapLeafScript = scriptFromTapLeafScript;
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const payment_js_1 = require("@scure/btc-signer/payment.js");
|
|
6
|
+
const utils_js_1 = require("@scure/btc-signer/utils.js");
|
|
7
7
|
const address_1 = require("./address");
|
|
8
|
-
const
|
|
8
|
+
const script_js_1 = require("@scure/btc-signer/script.js");
|
|
9
9
|
const base_1 = require("@scure/base");
|
|
10
10
|
const tapscript_1 = require("./tapscript");
|
|
11
11
|
function scriptFromTapLeafScript(leaf) {
|
|
@@ -26,8 +26,8 @@ class VtxoScript {
|
|
|
26
26
|
}
|
|
27
27
|
constructor(scripts) {
|
|
28
28
|
this.scripts = scripts;
|
|
29
|
-
const tapTree = (0,
|
|
30
|
-
const payment = (0,
|
|
29
|
+
const tapTree = (0, payment_js_1.taprootListToTree)(scripts.map((script) => ({ script, leafVersion: payment_js_1.TAP_LEAF_VERSION })));
|
|
30
|
+
const payment = (0, payment_js_1.p2tr)(utils_js_1.TAPROOT_UNSPENDABLE_KEY, tapTree, undefined, true);
|
|
31
31
|
if (!payment.tapLeafScript ||
|
|
32
32
|
payment.tapLeafScript.length !== scripts.length) {
|
|
33
33
|
throw new Error("invalid scripts");
|
|
@@ -43,10 +43,10 @@ class VtxoScript {
|
|
|
43
43
|
return new address_1.ArkAddress(serverPubKey, this.tweakedPublicKey, prefix);
|
|
44
44
|
}
|
|
45
45
|
get pkScript() {
|
|
46
|
-
return
|
|
46
|
+
return script_js_1.Script.encode(["OP_1", this.tweakedPublicKey]);
|
|
47
47
|
}
|
|
48
48
|
onchainAddress(network) {
|
|
49
|
-
return (0,
|
|
49
|
+
return (0, payment_js_1.Address)(network).encode({
|
|
50
50
|
type: "tr",
|
|
51
51
|
pubkey: this.tweakedPublicKey,
|
|
52
52
|
});
|
|
@@ -36,10 +36,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.CLTVMultisigTapscript = exports.ConditionMultisigTapscript = exports.ConditionCSVMultisigTapscript = exports.CSVMultisigTapscript = exports.MultisigTapscript = exports.TapscriptType = void 0;
|
|
37
37
|
exports.decodeTapscript = decodeTapscript;
|
|
38
38
|
const bip68 = __importStar(require("bip68"));
|
|
39
|
-
const
|
|
40
|
-
const
|
|
39
|
+
const script_js_1 = require("@scure/btc-signer/script.js");
|
|
40
|
+
const payment_js_1 = require("@scure/btc-signer/payment.js");
|
|
41
41
|
const base_1 = require("@scure/base");
|
|
42
|
-
const MinimalScriptNum = (0,
|
|
42
|
+
const MinimalScriptNum = (0, script_js_1.ScriptNum)(undefined, true);
|
|
43
43
|
var TapscriptType;
|
|
44
44
|
(function (TapscriptType) {
|
|
45
45
|
TapscriptType["Multisig"] = "multisig";
|
|
@@ -109,7 +109,7 @@ var MultisigTapscript;
|
|
|
109
109
|
return {
|
|
110
110
|
type: TapscriptType.Multisig,
|
|
111
111
|
params,
|
|
112
|
-
script: (0,
|
|
112
|
+
script: (0, payment_js_1.p2tr_ms)(params.pubkeys.length, params.pubkeys).script,
|
|
113
113
|
};
|
|
114
114
|
}
|
|
115
115
|
const asm = [];
|
|
@@ -126,7 +126,7 @@ var MultisigTapscript;
|
|
|
126
126
|
return {
|
|
127
127
|
type: TapscriptType.Multisig,
|
|
128
128
|
params,
|
|
129
|
-
script:
|
|
129
|
+
script: script_js_1.Script.encode(asm),
|
|
130
130
|
};
|
|
131
131
|
}
|
|
132
132
|
MultisigTapscript.encode = encode;
|
|
@@ -151,7 +151,7 @@ var MultisigTapscript;
|
|
|
151
151
|
MultisigTapscript.decode = decode;
|
|
152
152
|
// <pubkey> CHECKSIG <pubkey> CHECKSIGADD <len_keys> NUMEQUAL
|
|
153
153
|
function decodeChecksigAdd(script) {
|
|
154
|
-
const asm =
|
|
154
|
+
const asm = script_js_1.Script.decode(script);
|
|
155
155
|
const pubkeys = [];
|
|
156
156
|
let foundNumEqual = false;
|
|
157
157
|
// Parse through ASM operations
|
|
@@ -201,7 +201,7 @@ var MultisigTapscript;
|
|
|
201
201
|
}
|
|
202
202
|
// <pubkey> CHECKSIGVERIFY <pubkey> CHECKSIG
|
|
203
203
|
function decodeChecksig(script) {
|
|
204
|
-
const asm =
|
|
204
|
+
const asm = script_js_1.Script.decode(script);
|
|
205
205
|
const pubkeys = [];
|
|
206
206
|
// Parse through ASM operations
|
|
207
207
|
for (let i = 0; i < asm.length; i++) {
|
|
@@ -278,7 +278,7 @@ var CSVMultisigTapscript;
|
|
|
278
278
|
];
|
|
279
279
|
const multisigScript = MultisigTapscript.encode(params);
|
|
280
280
|
const script = new Uint8Array([
|
|
281
|
-
...
|
|
281
|
+
...script_js_1.Script.encode(asm),
|
|
282
282
|
...multisigScript.script,
|
|
283
283
|
]);
|
|
284
284
|
return {
|
|
@@ -292,18 +292,18 @@ var CSVMultisigTapscript;
|
|
|
292
292
|
if (script.length === 0) {
|
|
293
293
|
throw new Error("Failed to decode: script is empty");
|
|
294
294
|
}
|
|
295
|
-
const asm =
|
|
295
|
+
const asm = script_js_1.Script.decode(script);
|
|
296
296
|
if (asm.length < 3) {
|
|
297
297
|
throw new Error(`Invalid script: too short (expected at least 3)`);
|
|
298
298
|
}
|
|
299
299
|
const sequence = asm[0];
|
|
300
|
-
if (typeof sequence === "string"
|
|
300
|
+
if (typeof sequence === "string") {
|
|
301
301
|
throw new Error("Invalid script: expected sequence number");
|
|
302
302
|
}
|
|
303
303
|
if (asm[1] !== "CHECKSEQUENCEVERIFY" || asm[2] !== "DROP") {
|
|
304
304
|
throw new Error("Invalid script: expected CHECKSEQUENCEVERIFY DROP");
|
|
305
305
|
}
|
|
306
|
-
const multisigScript = new Uint8Array(
|
|
306
|
+
const multisigScript = new Uint8Array(script_js_1.Script.encode(asm.slice(3)));
|
|
307
307
|
let multisig;
|
|
308
308
|
try {
|
|
309
309
|
multisig = MultisigTapscript.decode(multisigScript);
|
|
@@ -311,7 +311,13 @@ var CSVMultisigTapscript;
|
|
|
311
311
|
catch (error) {
|
|
312
312
|
throw new Error(`Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`);
|
|
313
313
|
}
|
|
314
|
-
|
|
314
|
+
let sequenceNum;
|
|
315
|
+
if (typeof sequence === "number") {
|
|
316
|
+
sequenceNum = sequence;
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
sequenceNum = Number(MinimalScriptNum.decode(sequence));
|
|
320
|
+
}
|
|
315
321
|
const decodedTimelock = bip68.decode(sequenceNum);
|
|
316
322
|
const timelock = decodedTimelock.blocks !== undefined
|
|
317
323
|
? { type: "blocks", value: BigInt(decodedTimelock.blocks) }
|
|
@@ -355,7 +361,7 @@ var ConditionCSVMultisigTapscript;
|
|
|
355
361
|
function encode(params) {
|
|
356
362
|
const script = new Uint8Array([
|
|
357
363
|
...params.conditionScript,
|
|
358
|
-
...
|
|
364
|
+
...script_js_1.Script.encode(["VERIFY"]),
|
|
359
365
|
...CSVMultisigTapscript.encode(params).script,
|
|
360
366
|
]);
|
|
361
367
|
return {
|
|
@@ -369,7 +375,7 @@ var ConditionCSVMultisigTapscript;
|
|
|
369
375
|
if (script.length === 0) {
|
|
370
376
|
throw new Error("Failed to decode: script is empty");
|
|
371
377
|
}
|
|
372
|
-
const asm =
|
|
378
|
+
const asm = script_js_1.Script.decode(script);
|
|
373
379
|
if (asm.length < 1) {
|
|
374
380
|
throw new Error(`Invalid script: too short (expected at least 1)`);
|
|
375
381
|
}
|
|
@@ -382,8 +388,8 @@ var ConditionCSVMultisigTapscript;
|
|
|
382
388
|
if (verifyIndex === -1) {
|
|
383
389
|
throw new Error("Invalid script: missing VERIFY operation");
|
|
384
390
|
}
|
|
385
|
-
const conditionScript = new Uint8Array(
|
|
386
|
-
const csvMultisigScript = new Uint8Array(
|
|
391
|
+
const conditionScript = new Uint8Array(script_js_1.Script.encode(asm.slice(0, verifyIndex)));
|
|
392
|
+
const csvMultisigScript = new Uint8Array(script_js_1.Script.encode(asm.slice(verifyIndex + 1)));
|
|
387
393
|
let csvMultisig;
|
|
388
394
|
try {
|
|
389
395
|
csvMultisig = CSVMultisigTapscript.decode(csvMultisigScript);
|
|
@@ -430,7 +436,7 @@ var ConditionMultisigTapscript;
|
|
|
430
436
|
function encode(params) {
|
|
431
437
|
const script = new Uint8Array([
|
|
432
438
|
...params.conditionScript,
|
|
433
|
-
...
|
|
439
|
+
...script_js_1.Script.encode(["VERIFY"]),
|
|
434
440
|
...MultisigTapscript.encode(params).script,
|
|
435
441
|
]);
|
|
436
442
|
return {
|
|
@@ -444,7 +450,7 @@ var ConditionMultisigTapscript;
|
|
|
444
450
|
if (script.length === 0) {
|
|
445
451
|
throw new Error("Failed to decode: script is empty");
|
|
446
452
|
}
|
|
447
|
-
const asm =
|
|
453
|
+
const asm = script_js_1.Script.decode(script);
|
|
448
454
|
if (asm.length < 1) {
|
|
449
455
|
throw new Error(`Invalid script: too short (expected at least 1)`);
|
|
450
456
|
}
|
|
@@ -457,8 +463,8 @@ var ConditionMultisigTapscript;
|
|
|
457
463
|
if (verifyIndex === -1) {
|
|
458
464
|
throw new Error("Invalid script: missing VERIFY operation");
|
|
459
465
|
}
|
|
460
|
-
const conditionScript = new Uint8Array(
|
|
461
|
-
const multisigScript = new Uint8Array(
|
|
466
|
+
const conditionScript = new Uint8Array(script_js_1.Script.encode(asm.slice(0, verifyIndex)));
|
|
467
|
+
const multisigScript = new Uint8Array(script_js_1.Script.encode(asm.slice(verifyIndex + 1)));
|
|
462
468
|
let multisig;
|
|
463
469
|
try {
|
|
464
470
|
multisig = MultisigTapscript.decode(multisigScript);
|
|
@@ -509,7 +515,7 @@ var CLTVMultisigTapscript;
|
|
|
509
515
|
"CHECKLOCKTIMEVERIFY",
|
|
510
516
|
"DROP",
|
|
511
517
|
];
|
|
512
|
-
const timelockedScript =
|
|
518
|
+
const timelockedScript = script_js_1.Script.encode(asm);
|
|
513
519
|
const script = new Uint8Array([
|
|
514
520
|
...timelockedScript,
|
|
515
521
|
...MultisigTapscript.encode(params).script,
|
|
@@ -525,7 +531,7 @@ var CLTVMultisigTapscript;
|
|
|
525
531
|
if (script.length === 0) {
|
|
526
532
|
throw new Error("Failed to decode: script is empty");
|
|
527
533
|
}
|
|
528
|
-
const asm =
|
|
534
|
+
const asm = script_js_1.Script.decode(script);
|
|
529
535
|
if (asm.length < 3) {
|
|
530
536
|
throw new Error(`Invalid script: too short (expected at least 3)`);
|
|
531
537
|
}
|
|
@@ -536,7 +542,7 @@ var CLTVMultisigTapscript;
|
|
|
536
542
|
if (asm[1] !== "CHECKLOCKTIMEVERIFY" || asm[2] !== "DROP") {
|
|
537
543
|
throw new Error("Invalid script: expected CHECKLOCKTIMEVERIFY DROP");
|
|
538
544
|
}
|
|
539
|
-
const multisigScript = new Uint8Array(
|
|
545
|
+
const multisigScript = new Uint8Array(script_js_1.Script.encode(asm.slice(3)));
|
|
540
546
|
let multisig;
|
|
541
547
|
try {
|
|
542
548
|
multisig = MultisigTapscript.decode(multisigScript);
|
package/dist/cjs/script/vhtlc.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VHTLC = void 0;
|
|
4
|
-
const
|
|
4
|
+
const script_js_1 = require("@scure/btc-signer/script.js");
|
|
5
5
|
const tapscript_1 = require("./tapscript");
|
|
6
6
|
const base_1 = require("@scure/base");
|
|
7
7
|
const base_2 = require("./base");
|
|
@@ -158,5 +158,5 @@ var VHTLC;
|
|
|
158
158
|
}
|
|
159
159
|
})(VHTLC || (exports.VHTLC = VHTLC = {}));
|
|
160
160
|
function preimageConditionScript(preimageHash) {
|
|
161
|
-
return
|
|
161
|
+
return script_js_1.Script.encode(["HASH160", preimageHash, "EQUAL"]);
|
|
162
162
|
}
|
|
@@ -36,10 +36,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.TreeSignerSession = exports.ErrMissingAggregateKey = exports.ErrMissingVtxoGraph = void 0;
|
|
37
37
|
exports.validateTreeSigs = validateTreeSigs;
|
|
38
38
|
const musig2 = __importStar(require("../musig2"));
|
|
39
|
-
const
|
|
39
|
+
const script_js_1 = require("@scure/btc-signer/script.js");
|
|
40
|
+
const transaction_js_1 = require("@scure/btc-signer/transaction.js");
|
|
40
41
|
const base_1 = require("@scure/base");
|
|
41
42
|
const secp256k1_js_1 = require("@noble/curves/secp256k1.js");
|
|
42
|
-
const
|
|
43
|
+
const utils_js_1 = require("@scure/btc-signer/utils.js");
|
|
43
44
|
const unknownFields_1 = require("../utils/unknownFields");
|
|
44
45
|
exports.ErrMissingVtxoGraph = new Error("missing vtxo graph");
|
|
45
46
|
exports.ErrMissingAggregateKey = new Error("missing aggregate key");
|
|
@@ -53,7 +54,7 @@ class TreeSignerSession {
|
|
|
53
54
|
this.rootSharedOutputAmount = null;
|
|
54
55
|
}
|
|
55
56
|
static random() {
|
|
56
|
-
const secretKey = (0,
|
|
57
|
+
const secretKey = (0, utils_js_1.randomPrivateKeyBytes)();
|
|
57
58
|
return new TreeSignerSession(secretKey);
|
|
58
59
|
}
|
|
59
60
|
init(tree, scriptRoot, rootInputAmount) {
|
|
@@ -89,7 +90,7 @@ class TreeSignerSession {
|
|
|
89
90
|
if (!this.myNonces)
|
|
90
91
|
throw new Error("nonces not generated");
|
|
91
92
|
const sigs = new Map();
|
|
92
|
-
for (const g of this.graph) {
|
|
93
|
+
for (const g of this.graph.iterator()) {
|
|
93
94
|
const sig = this.signPartial(g);
|
|
94
95
|
sigs.set(g.txid, sig);
|
|
95
96
|
}
|
|
@@ -100,7 +101,7 @@ class TreeSignerSession {
|
|
|
100
101
|
throw exports.ErrMissingVtxoGraph;
|
|
101
102
|
const myNonces = new Map();
|
|
102
103
|
const publicKey = secp256k1_js_1.secp256k1.getPublicKey(this.secretKey);
|
|
103
|
-
for (const g of this.graph) {
|
|
104
|
+
for (const g of this.graph.iterator()) {
|
|
104
105
|
const nonces = musig2.generateNonces(publicKey);
|
|
105
106
|
myNonces.set(g.txid, nonces);
|
|
106
107
|
}
|
|
@@ -131,7 +132,7 @@ class TreeSignerSession {
|
|
|
131
132
|
prevoutScripts.push(prevout.script);
|
|
132
133
|
}
|
|
133
134
|
const message = g.root.preimageWitnessV1(0, // always first input
|
|
134
|
-
prevoutScripts,
|
|
135
|
+
prevoutScripts, transaction_js_1.SigHash.DEFAULT, prevoutAmounts);
|
|
135
136
|
return musig2.sign(myNonce.secNonce, this.secretKey, aggNonce.pubNonce, cosigners, message, {
|
|
136
137
|
taprootTweak: this.scriptRoot,
|
|
137
138
|
sortKeys: true,
|
|
@@ -143,7 +144,7 @@ TreeSignerSession.NOT_INITIALIZED = new Error("session not initialized, call ini
|
|
|
143
144
|
// Helper function to validate tree signatures
|
|
144
145
|
async function validateTreeSigs(finalAggregatedKey, sharedOutputAmount, vtxoTree) {
|
|
145
146
|
// Iterate through each level of the tree
|
|
146
|
-
for (const g of vtxoTree) {
|
|
147
|
+
for (const g of vtxoTree.iterator()) {
|
|
147
148
|
// Parse the transaction
|
|
148
149
|
const input = g.root.getInput(0);
|
|
149
150
|
// Check if input has signature
|
|
@@ -154,7 +155,7 @@ async function validateTreeSigs(finalAggregatedKey, sharedOutputAmount, vtxoTree
|
|
|
154
155
|
const prevout = getPrevOutput(finalAggregatedKey, vtxoTree, sharedOutputAmount, g.root);
|
|
155
156
|
// Calculate the message that was signed
|
|
156
157
|
const message = g.root.preimageWitnessV1(0, // always first input
|
|
157
|
-
[prevout.script],
|
|
158
|
+
[prevout.script], transaction_js_1.SigHash.DEFAULT, [prevout.amount]);
|
|
158
159
|
// Verify the signature
|
|
159
160
|
const isValid = secp256k1_js_1.schnorr.verify(input.tapKeySig, message, finalAggregatedKey);
|
|
160
161
|
if (!isValid) {
|
|
@@ -164,8 +165,8 @@ async function validateTreeSigs(finalAggregatedKey, sharedOutputAmount, vtxoTree
|
|
|
164
165
|
}
|
|
165
166
|
function getPrevOutput(finalKey, graph, sharedOutputAmount, tx) {
|
|
166
167
|
// generate P2TR script from musig2 final key
|
|
167
|
-
const pkScript =
|
|
168
|
-
const txid = base_1.hex.encode((0,
|
|
168
|
+
const pkScript = script_js_1.Script.encode(["OP_1", finalKey.slice(1)]);
|
|
169
|
+
const txid = base_1.hex.encode((0, utils_js_1.sha256x2)(tx.toBytes(true)).reverse());
|
|
169
170
|
// if the input is the root input, return the shared output amount
|
|
170
171
|
if (txid === graph.txid) {
|
|
171
172
|
return {
|
package/dist/cjs/tree/txTree.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TxTree = void 0;
|
|
4
|
-
const
|
|
4
|
+
const transaction_js_1 = require("@scure/btc-signer/transaction.js");
|
|
5
5
|
const base_1 = require("@scure/base");
|
|
6
6
|
const base_2 = require("@scure/base");
|
|
7
|
-
const
|
|
7
|
+
const utils_js_1 = require("@scure/btc-signer/utils.js");
|
|
8
8
|
/**
|
|
9
9
|
* TxTree is a graph of bitcoin transactions.
|
|
10
10
|
* It is used to represent batch tree created during settlement session
|
|
@@ -22,7 +22,7 @@ class TxTree {
|
|
|
22
22
|
const chunksByTxid = new Map();
|
|
23
23
|
for (const chunk of chunks) {
|
|
24
24
|
const decodedChunk = decodeNode(chunk);
|
|
25
|
-
const txid = base_2.hex.encode((0,
|
|
25
|
+
const txid = base_2.hex.encode((0, utils_js_1.sha256x2)(decodedChunk.tx.toBytes(true)).reverse());
|
|
26
26
|
chunksByTxid.set(txid, decodedChunk);
|
|
27
27
|
}
|
|
28
28
|
// Find the root chunks (the ones that aren't referenced as a child)
|
|
@@ -91,7 +91,7 @@ class TxTree {
|
|
|
91
91
|
}
|
|
92
92
|
child.validate();
|
|
93
93
|
const childInput = child.root.getInput(0);
|
|
94
|
-
const parentTxid = base_2.hex.encode((0,
|
|
94
|
+
const parentTxid = base_2.hex.encode((0, utils_js_1.sha256x2)(this.root.toBytes(true)).reverse());
|
|
95
95
|
// verify the input of the child is the output of the parent
|
|
96
96
|
if (!childInput.txid ||
|
|
97
97
|
base_2.hex.encode(childInput.txid) !== parentTxid ||
|
|
@@ -126,7 +126,7 @@ class TxTree {
|
|
|
126
126
|
return leaves;
|
|
127
127
|
}
|
|
128
128
|
get txid() {
|
|
129
|
-
return base_2.hex.encode((0,
|
|
129
|
+
return base_2.hex.encode((0, utils_js_1.sha256x2)(this.root.toBytes(true)).reverse());
|
|
130
130
|
}
|
|
131
131
|
find(txid) {
|
|
132
132
|
if (txid === this.txid) {
|
|
@@ -157,11 +157,11 @@ class TxTree {
|
|
|
157
157
|
}
|
|
158
158
|
throw new Error(`tx not found: ${txid}`);
|
|
159
159
|
}
|
|
160
|
-
*
|
|
161
|
-
yield this;
|
|
160
|
+
*iterator() {
|
|
162
161
|
for (const child of this.children.values()) {
|
|
163
|
-
yield* child;
|
|
162
|
+
yield* child.iterator();
|
|
164
163
|
}
|
|
164
|
+
yield this;
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
167
|
exports.TxTree = TxTree;
|
|
@@ -188,6 +188,6 @@ function buildGraph(rootTxid, chunksByTxid) {
|
|
|
188
188
|
return new TxTree(rootTx, children);
|
|
189
189
|
}
|
|
190
190
|
function decodeNode(chunk) {
|
|
191
|
-
const tx =
|
|
191
|
+
const tx = transaction_js_1.Transaction.fromPSBT(base_1.base64.decode(chunk.tx));
|
|
192
192
|
return { tx, children: chunk.children };
|
|
193
193
|
}
|
|
@@ -4,9 +4,9 @@ exports.ErrMissingCosignersPublicKeys = exports.ErrWrongCommitmentTxid = exports
|
|
|
4
4
|
exports.validateConnectorsTxGraph = validateConnectorsTxGraph;
|
|
5
5
|
exports.validateVtxoTxGraph = validateVtxoTxGraph;
|
|
6
6
|
const base_1 = require("@scure/base");
|
|
7
|
-
const
|
|
7
|
+
const transaction_js_1 = require("@scure/btc-signer/transaction.js");
|
|
8
8
|
const base_2 = require("@scure/base");
|
|
9
|
-
const
|
|
9
|
+
const utils_js_1 = require("@scure/btc-signer/utils.js");
|
|
10
10
|
const musig2_1 = require("../musig2");
|
|
11
11
|
const unknownFields_1 = require("../utils/unknownFields");
|
|
12
12
|
const ErrInvalidSettlementTx = (tx) => new Error(`invalid settlement transaction: ${tx}`);
|
|
@@ -28,10 +28,10 @@ function validateConnectorsTxGraph(settlementTxB64, connectorsGraph) {
|
|
|
28
28
|
if (connectorsGraph.root.inputsLength !== 1)
|
|
29
29
|
throw exports.ErrNumberOfInputs;
|
|
30
30
|
const rootInput = connectorsGraph.root.getInput(0);
|
|
31
|
-
const settlementTx =
|
|
31
|
+
const settlementTx = transaction_js_1.Transaction.fromPSBT(base_2.base64.decode(settlementTxB64));
|
|
32
32
|
if (settlementTx.outputsLength <= BATCH_OUTPUT_CONNECTORS_INDEX)
|
|
33
33
|
throw exports.ErrInvalidSettlementTxOutputs;
|
|
34
|
-
const expectedRootTxid = base_1.hex.encode((0,
|
|
34
|
+
const expectedRootTxid = base_1.hex.encode((0, utils_js_1.sha256x2)(settlementTx.toBytes(true)).reverse());
|
|
35
35
|
if (!rootInput.txid)
|
|
36
36
|
throw exports.ErrWrongSettlementTxid;
|
|
37
37
|
if (base_1.hex.encode(rootInput.txid) !== expectedRootTxid)
|
|
@@ -58,7 +58,7 @@ function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
|
|
|
58
58
|
throw exports.ErrEmptyTree;
|
|
59
59
|
}
|
|
60
60
|
const rootInput = graph.root.getInput(0);
|
|
61
|
-
const commitmentTxid = base_1.hex.encode((0,
|
|
61
|
+
const commitmentTxid = base_1.hex.encode((0, utils_js_1.sha256x2)(roundTransaction.toBytes(true)).reverse());
|
|
62
62
|
if (!rootInput.txid ||
|
|
63
63
|
base_1.hex.encode(rootInput.txid) !== commitmentTxid ||
|
|
64
64
|
rootInput.index !== BATCH_OUTPUT_VTXO_INDEX) {
|
|
@@ -81,7 +81,7 @@ function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
|
|
|
81
81
|
// validate the graph structure
|
|
82
82
|
graph.validate();
|
|
83
83
|
// iterates over all the nodes of the graph to verify that cosigners public keys are corresponding to the parent output
|
|
84
|
-
for (const g of graph) {
|
|
84
|
+
for (const g of graph.iterator()) {
|
|
85
85
|
for (const [childIndex, child] of g.children) {
|
|
86
86
|
const parentOutput = g.root.getOutput(childIndex);
|
|
87
87
|
if (!parentOutput?.script) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildOffchainTx = buildOffchainTx;
|
|
4
|
-
const
|
|
4
|
+
const transaction_js_1 = require("@scure/btc-signer/transaction.js");
|
|
5
5
|
const tapscript_1 = require("../script/tapscript");
|
|
6
6
|
const base_1 = require("../script/base");
|
|
7
7
|
const anchor_1 = require("./anchor");
|
|
8
8
|
const base_2 = require("@scure/base");
|
|
9
|
-
const
|
|
9
|
+
const utils_js_1 = require("@scure/btc-signer/utils.js");
|
|
10
10
|
const unknownFields_1 = require("./unknownFields");
|
|
11
11
|
/**
|
|
12
12
|
* Builds an offchain transaction with checkpoint transactions.
|
|
@@ -45,7 +45,7 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
const tx = new
|
|
48
|
+
const tx = new transaction_js_1.Transaction({
|
|
49
49
|
version: 3,
|
|
50
50
|
allowUnknown: true,
|
|
51
51
|
allowUnknownOutputs: true,
|
|
@@ -55,7 +55,7 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
55
55
|
tx.addInput({
|
|
56
56
|
txid: input.txid,
|
|
57
57
|
index: input.vout,
|
|
58
|
-
sequence: lockTime ?
|
|
58
|
+
sequence: lockTime ? transaction_js_1.DEFAULT_SEQUENCE - 1 : undefined,
|
|
59
59
|
witnessUtxo: {
|
|
60
60
|
script: base_1.VtxoScript.decode(input.tapTree).pkScript,
|
|
61
61
|
amount: BigInt(input.value),
|
|
@@ -91,7 +91,7 @@ function buildCheckpointTx(vtxo, serverUnrollScript) {
|
|
|
91
91
|
const collaborativeLeafProof = checkpointVtxoScript.findLeaf(base_2.hex.encode(collaborativeClosure.script));
|
|
92
92
|
// create the checkpoint input that will be used as input of the virtual tx
|
|
93
93
|
const checkpointInput = {
|
|
94
|
-
txid: base_2.hex.encode((0,
|
|
94
|
+
txid: base_2.hex.encode((0, utils_js_1.sha256x2)(checkpointTx.toBytes(true)).reverse()),
|
|
95
95
|
vout: 0,
|
|
96
96
|
value: vtxo.value,
|
|
97
97
|
tapLeafScript: collaborativeLeafProof,
|
|
@@ -37,7 +37,7 @@ exports.VtxoTreeExpiry = exports.CosignerPublicKey = exports.ConditionWitness =
|
|
|
37
37
|
exports.setArkPsbtField = setArkPsbtField;
|
|
38
38
|
exports.getArkPsbtFields = getArkPsbtFields;
|
|
39
39
|
const bip68 = __importStar(require("bip68"));
|
|
40
|
-
const
|
|
40
|
+
const script_js_1 = require("@scure/btc-signer/script.js");
|
|
41
41
|
const base_1 = require("@scure/base");
|
|
42
42
|
/**
|
|
43
43
|
* ArkPsbtFieldKey is the key values for ark psbt fields.
|
|
@@ -126,12 +126,12 @@ exports.ConditionWitness = {
|
|
|
126
126
|
type: exports.ArkPsbtFieldKeyType,
|
|
127
127
|
key: encodedPsbtFieldKey[ArkPsbtFieldKey.ConditionWitness],
|
|
128
128
|
},
|
|
129
|
-
|
|
129
|
+
script_js_1.RawWitness.encode(value),
|
|
130
130
|
],
|
|
131
131
|
decode: (value) => nullIfCatch(() => {
|
|
132
132
|
if (!checkKeyIncludes(value[0], ArkPsbtFieldKey.ConditionWitness))
|
|
133
133
|
return null;
|
|
134
|
-
return
|
|
134
|
+
return script_js_1.RawWitness.decode(value[1]);
|
|
135
135
|
}),
|
|
136
136
|
};
|
|
137
137
|
/**
|
|
@@ -176,12 +176,12 @@ exports.VtxoTreeExpiry = {
|
|
|
176
176
|
type: exports.ArkPsbtFieldKeyType,
|
|
177
177
|
key: encodedPsbtFieldKey[ArkPsbtFieldKey.VtxoTreeExpiry],
|
|
178
178
|
},
|
|
179
|
-
(0,
|
|
179
|
+
(0, script_js_1.ScriptNum)(6, true).encode(value.value === 0n ? 0n : value.value),
|
|
180
180
|
],
|
|
181
181
|
decode: (unknown) => nullIfCatch(() => {
|
|
182
182
|
if (!checkKeyIncludes(unknown[0], ArkPsbtFieldKey.VtxoTreeExpiry))
|
|
183
183
|
return null;
|
|
184
|
-
const v = (0,
|
|
184
|
+
const v = (0, script_js_1.ScriptNum)(6, true).decode(unknown[1]);
|
|
185
185
|
if (!v)
|
|
186
186
|
return null;
|
|
187
187
|
const { blocks, seconds } = bip68.decode(Number(v));
|