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