@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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isFetchTimeoutError } from './ark.js';
|
|
2
|
+
import { eventSourceIterator } from './utils.js';
|
|
2
3
|
export var IndexerTxType;
|
|
3
4
|
(function (IndexerTxType) {
|
|
4
5
|
IndexerTxType[IndexerTxType["INDEXER_TX_TYPE_UNSPECIFIED"] = 0] = "INDEXER_TX_TYPE_UNSPECIFIED";
|
|
@@ -27,7 +28,7 @@ export class RestIndexerProvider {
|
|
|
27
28
|
this.serverUrl = serverUrl;
|
|
28
29
|
}
|
|
29
30
|
async getVtxoTree(batchOutpoint, opts) {
|
|
30
|
-
let url = `${this.serverUrl}/v1/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree`;
|
|
31
|
+
let url = `${this.serverUrl}/v1/indexer/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree`;
|
|
31
32
|
const params = new URLSearchParams();
|
|
32
33
|
if (opts) {
|
|
33
34
|
if (opts.pageIndex !== undefined)
|
|
@@ -55,7 +56,7 @@ export class RestIndexerProvider {
|
|
|
55
56
|
return data;
|
|
56
57
|
}
|
|
57
58
|
async getVtxoTreeLeaves(batchOutpoint, opts) {
|
|
58
|
-
let url = `${this.serverUrl}/v1/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree/leaves`;
|
|
59
|
+
let url = `${this.serverUrl}/v1/indexer/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree/leaves`;
|
|
59
60
|
const params = new URLSearchParams();
|
|
60
61
|
if (opts) {
|
|
61
62
|
if (opts.pageIndex !== undefined)
|
|
@@ -77,7 +78,7 @@ export class RestIndexerProvider {
|
|
|
77
78
|
return data;
|
|
78
79
|
}
|
|
79
80
|
async getBatchSweepTransactions(batchOutpoint) {
|
|
80
|
-
const url = `${this.serverUrl}/v1/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/sweepTxs`;
|
|
81
|
+
const url = `${this.serverUrl}/v1/indexer/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/sweepTxs`;
|
|
81
82
|
const res = await fetch(url);
|
|
82
83
|
if (!res.ok) {
|
|
83
84
|
throw new Error(`Failed to fetch batch sweep transactions: ${res.statusText}`);
|
|
@@ -89,7 +90,7 @@ export class RestIndexerProvider {
|
|
|
89
90
|
return data;
|
|
90
91
|
}
|
|
91
92
|
async getCommitmentTx(txid) {
|
|
92
|
-
const url = `${this.serverUrl}/v1/commitmentTx/${txid}`;
|
|
93
|
+
const url = `${this.serverUrl}/v1/indexer/commitmentTx/${txid}`;
|
|
93
94
|
const res = await fetch(url);
|
|
94
95
|
if (!res.ok) {
|
|
95
96
|
throw new Error(`Failed to fetch commitment tx: ${res.statusText}`);
|
|
@@ -101,7 +102,7 @@ export class RestIndexerProvider {
|
|
|
101
102
|
return data;
|
|
102
103
|
}
|
|
103
104
|
async getCommitmentTxConnectors(txid, opts) {
|
|
104
|
-
let url = `${this.serverUrl}/v1/commitmentTx/${txid}/connectors`;
|
|
105
|
+
let url = `${this.serverUrl}/v1/indexer/commitmentTx/${txid}/connectors`;
|
|
105
106
|
const params = new URLSearchParams();
|
|
106
107
|
if (opts) {
|
|
107
108
|
if (opts.pageIndex !== undefined)
|
|
@@ -129,7 +130,7 @@ export class RestIndexerProvider {
|
|
|
129
130
|
return data;
|
|
130
131
|
}
|
|
131
132
|
async getCommitmentTxForfeitTxs(txid, opts) {
|
|
132
|
-
let url = `${this.serverUrl}/v1/commitmentTx/${txid}/forfeitTxs`;
|
|
133
|
+
let url = `${this.serverUrl}/v1/indexer/commitmentTx/${txid}/forfeitTxs`;
|
|
133
134
|
const params = new URLSearchParams();
|
|
134
135
|
if (opts) {
|
|
135
136
|
if (opts.pageIndex !== undefined)
|
|
@@ -151,47 +152,41 @@ export class RestIndexerProvider {
|
|
|
151
152
|
return data;
|
|
152
153
|
}
|
|
153
154
|
async *getSubscription(subscriptionId, abortSignal) {
|
|
154
|
-
const url = `${this.serverUrl}/v1/script/subscription/${subscriptionId}`;
|
|
155
|
-
while (!abortSignal
|
|
155
|
+
const url = `${this.serverUrl}/v1/indexer/script/subscription/${subscriptionId}`;
|
|
156
|
+
while (!abortSignal?.aborted) {
|
|
156
157
|
try {
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if ("result" in data) {
|
|
184
|
-
yield {
|
|
185
|
-
txid: data.result.txid,
|
|
186
|
-
scripts: data.result.scripts || [],
|
|
187
|
-
newVtxos: (data.result.newVtxos || []).map(convertVtxo),
|
|
188
|
-
spentVtxos: (data.result.spentVtxos || []).map(convertVtxo),
|
|
189
|
-
tx: data.result.tx,
|
|
190
|
-
checkpointTxs: data.result.checkpointTxs,
|
|
191
|
-
};
|
|
158
|
+
const eventSource = new EventSource(url);
|
|
159
|
+
// Set up abort handling
|
|
160
|
+
const abortHandler = () => {
|
|
161
|
+
eventSource.close();
|
|
162
|
+
};
|
|
163
|
+
abortSignal?.addEventListener("abort", abortHandler);
|
|
164
|
+
try {
|
|
165
|
+
for await (const event of eventSourceIterator(eventSource)) {
|
|
166
|
+
if (abortSignal?.aborted)
|
|
167
|
+
break;
|
|
168
|
+
try {
|
|
169
|
+
const data = JSON.parse(event.data);
|
|
170
|
+
if (data.event) {
|
|
171
|
+
yield {
|
|
172
|
+
txid: data.event.txid,
|
|
173
|
+
scripts: data.event.scripts || [],
|
|
174
|
+
newVtxos: (data.event.newVtxos || []).map(convertVtxo),
|
|
175
|
+
spentVtxos: (data.event.spentVtxos || []).map(convertVtxo),
|
|
176
|
+
tx: data.event.tx,
|
|
177
|
+
checkpointTxs: data.event.checkpointTxs,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
console.error("Failed to parse subscription event:", err);
|
|
183
|
+
throw err;
|
|
192
184
|
}
|
|
193
185
|
}
|
|
194
|
-
|
|
186
|
+
}
|
|
187
|
+
finally {
|
|
188
|
+
abortSignal?.removeEventListener("abort", abortHandler);
|
|
189
|
+
eventSource.close();
|
|
195
190
|
}
|
|
196
191
|
}
|
|
197
192
|
catch (error) {
|
|
@@ -199,7 +194,6 @@ export class RestIndexerProvider {
|
|
|
199
194
|
break;
|
|
200
195
|
}
|
|
201
196
|
// ignore timeout errors, they're expected when the server is not sending anything for 5 min
|
|
202
|
-
// these timeouts are set by builtin fetch function
|
|
203
197
|
if (isFetchTimeoutError(error)) {
|
|
204
198
|
console.debug("Timeout error ignored");
|
|
205
199
|
continue;
|
|
@@ -210,7 +204,7 @@ export class RestIndexerProvider {
|
|
|
210
204
|
}
|
|
211
205
|
}
|
|
212
206
|
async getVirtualTxs(txids, opts) {
|
|
213
|
-
let url = `${this.serverUrl}/v1/virtualTx/${txids.join(",")}`;
|
|
207
|
+
let url = `${this.serverUrl}/v1/indexer/virtualTx/${txids.join(",")}`;
|
|
214
208
|
const params = new URLSearchParams();
|
|
215
209
|
if (opts) {
|
|
216
210
|
if (opts.pageIndex !== undefined)
|
|
@@ -232,7 +226,7 @@ export class RestIndexerProvider {
|
|
|
232
226
|
return data;
|
|
233
227
|
}
|
|
234
228
|
async getVtxoChain(vtxoOutpoint, opts) {
|
|
235
|
-
let url = `${this.serverUrl}/v1/vtxo/${vtxoOutpoint.txid}/${vtxoOutpoint.vout}/chain`;
|
|
229
|
+
let url = `${this.serverUrl}/v1/indexer/vtxo/${vtxoOutpoint.txid}/${vtxoOutpoint.vout}/chain`;
|
|
236
230
|
const params = new URLSearchParams();
|
|
237
231
|
if (opts) {
|
|
238
232
|
if (opts.pageIndex !== undefined)
|
|
@@ -261,7 +255,7 @@ export class RestIndexerProvider {
|
|
|
261
255
|
if (!opts?.scripts && !opts?.outpoints) {
|
|
262
256
|
throw new Error("Either scripts or outpoints must be provided");
|
|
263
257
|
}
|
|
264
|
-
let url = `${this.serverUrl}/v1/vtxos`;
|
|
258
|
+
let url = `${this.serverUrl}/v1/indexer/vtxos`;
|
|
265
259
|
const params = new URLSearchParams();
|
|
266
260
|
// Handle scripts with multi collection format
|
|
267
261
|
if (opts?.scripts && opts.scripts.length > 0) {
|
|
@@ -304,7 +298,7 @@ export class RestIndexerProvider {
|
|
|
304
298
|
};
|
|
305
299
|
}
|
|
306
300
|
async subscribeForScripts(scripts, subscriptionId) {
|
|
307
|
-
const url = `${this.serverUrl}/v1/script/subscribe`;
|
|
301
|
+
const url = `${this.serverUrl}/v1/indexer/script/subscribe`;
|
|
308
302
|
const res = await fetch(url, {
|
|
309
303
|
headers: {
|
|
310
304
|
"Content-Type": "application/json",
|
|
@@ -322,7 +316,7 @@ export class RestIndexerProvider {
|
|
|
322
316
|
return data.subscriptionId;
|
|
323
317
|
}
|
|
324
318
|
async unsubscribeForScripts(subscriptionId, scripts) {
|
|
325
|
-
const url = `${this.serverUrl}/v1/script/unsubscribe`;
|
|
319
|
+
const url = `${this.serverUrl}/v1/indexer/script/unsubscribe`;
|
|
326
320
|
const res = await fetch(url, {
|
|
327
321
|
headers: {
|
|
328
322
|
"Content-Type": "application/json",
|
|
@@ -438,7 +432,7 @@ var Response;
|
|
|
438
432
|
return (typeof data === "object" &&
|
|
439
433
|
isOutpoint(data.outpoint) &&
|
|
440
434
|
typeof data.createdAt === "string" &&
|
|
441
|
-
typeof data.expiresAt === "string" &&
|
|
435
|
+
(data.expiresAt === null || typeof data.expiresAt === "string") &&
|
|
442
436
|
typeof data.amount === "string" &&
|
|
443
437
|
typeof data.script === "string" &&
|
|
444
438
|
typeof data.isPreconfirmed === "boolean" &&
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export async function* eventSourceIterator(eventSource) {
|
|
2
|
+
const messageQueue = [];
|
|
3
|
+
const errorQueue = [];
|
|
4
|
+
let messageResolve = null;
|
|
5
|
+
let errorResolve = null;
|
|
6
|
+
const messageHandler = (event) => {
|
|
7
|
+
if (messageResolve) {
|
|
8
|
+
messageResolve(event);
|
|
9
|
+
messageResolve = null;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
messageQueue.push(event);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const errorHandler = () => {
|
|
16
|
+
const error = new Error("EventSource error");
|
|
17
|
+
if (errorResolve) {
|
|
18
|
+
errorResolve(error);
|
|
19
|
+
errorResolve = null;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
errorQueue.push(error);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
eventSource.addEventListener("message", messageHandler);
|
|
26
|
+
eventSource.addEventListener("error", errorHandler);
|
|
27
|
+
try {
|
|
28
|
+
while (true) {
|
|
29
|
+
// if we have queued messages, yield the first one, remove it from the queue
|
|
30
|
+
if (messageQueue.length > 0) {
|
|
31
|
+
yield messageQueue.shift();
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
// if we have queued errors, throw the first one, remove it from the queue
|
|
35
|
+
if (errorQueue.length > 0) {
|
|
36
|
+
const error = errorQueue.shift();
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
// wait for the next message or error
|
|
40
|
+
const result = await new Promise((resolve, reject) => {
|
|
41
|
+
messageResolve = resolve;
|
|
42
|
+
errorResolve = reject;
|
|
43
|
+
}).finally(() => {
|
|
44
|
+
messageResolve = null;
|
|
45
|
+
errorResolve = null;
|
|
46
|
+
});
|
|
47
|
+
if (result) {
|
|
48
|
+
yield result;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
// clean up
|
|
54
|
+
eventSource.removeEventListener("message", messageHandler);
|
|
55
|
+
eventSource.removeEventListener("error", errorHandler);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
import { hex } from "@scure/base";
|
|
2
|
+
import { TaprootControlBlock } from "@scure/btc-signer";
|
|
3
|
+
// Utility functions for (de)serializing complex structures
|
|
4
|
+
const toHex = (b) => (b ? hex.encode(b) : undefined);
|
|
5
|
+
const fromHex = (h) => h ? hex.decode(h) : undefined;
|
|
6
|
+
const serializeTapLeaf = ([cb, s]) => ({
|
|
7
|
+
cb: TaprootControlBlock.encode(cb) &&
|
|
8
|
+
hex.encode(TaprootControlBlock.encode(cb)),
|
|
9
|
+
s: hex.encode(s),
|
|
10
|
+
});
|
|
11
|
+
const serializeVtxo = (v) => ({
|
|
12
|
+
...v,
|
|
13
|
+
tapTree: toHex(v.tapTree),
|
|
14
|
+
forfeitTapLeafScript: serializeTapLeaf(v.forfeitTapLeafScript),
|
|
15
|
+
intentTapLeafScript: serializeTapLeaf(v.intentTapLeafScript),
|
|
16
|
+
extraWitness: v.extraWitness?.map((w) => toHex(w)),
|
|
17
|
+
});
|
|
18
|
+
const deserializeTapLeaf = (t) => {
|
|
19
|
+
const cb = TaprootControlBlock.decode(fromHex(t.cb));
|
|
20
|
+
const s = fromHex(t.s);
|
|
21
|
+
return [cb, s];
|
|
22
|
+
};
|
|
23
|
+
const deserializeVtxo = (o) => ({
|
|
24
|
+
...o,
|
|
25
|
+
tapTree: fromHex(o.tapTree),
|
|
26
|
+
forfeitTapLeafScript: deserializeTapLeaf(o.forfeitTapLeafScript),
|
|
27
|
+
intentTapLeafScript: deserializeTapLeaf(o.intentTapLeafScript),
|
|
28
|
+
extraWitness: o.extraWitness?.map((w) => fromHex(w)),
|
|
29
|
+
});
|
|
1
30
|
export class WalletRepositoryImpl {
|
|
2
31
|
constructor(storage) {
|
|
3
32
|
this.storage = storage;
|
|
@@ -19,7 +48,8 @@ export class WalletRepositoryImpl {
|
|
|
19
48
|
return [];
|
|
20
49
|
}
|
|
21
50
|
try {
|
|
22
|
-
const
|
|
51
|
+
const parsed = JSON.parse(stored);
|
|
52
|
+
const vtxos = parsed.map(deserializeVtxo);
|
|
23
53
|
this.cache.vtxos.set(address, vtxos);
|
|
24
54
|
return vtxos.slice();
|
|
25
55
|
}
|
|
@@ -39,7 +69,7 @@ export class WalletRepositoryImpl {
|
|
|
39
69
|
vtxos.push(vtxo);
|
|
40
70
|
}
|
|
41
71
|
this.cache.vtxos.set(address, vtxos);
|
|
42
|
-
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(vtxos));
|
|
72
|
+
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(vtxos.map(serializeVtxo)));
|
|
43
73
|
}
|
|
44
74
|
async saveVtxos(address, vtxos) {
|
|
45
75
|
const storedVtxos = await this.getVtxos(address);
|
|
@@ -53,14 +83,14 @@ export class WalletRepositoryImpl {
|
|
|
53
83
|
}
|
|
54
84
|
}
|
|
55
85
|
this.cache.vtxos.set(address, storedVtxos);
|
|
56
|
-
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(storedVtxos));
|
|
86
|
+
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(storedVtxos.map(serializeVtxo)));
|
|
57
87
|
}
|
|
58
88
|
async removeVtxo(address, vtxoId) {
|
|
59
89
|
const vtxos = await this.getVtxos(address);
|
|
60
90
|
const [txid, vout] = vtxoId.split(":");
|
|
61
91
|
const filtered = vtxos.filter((v) => !(v.txid === txid && v.vout === parseInt(vout)));
|
|
62
92
|
this.cache.vtxos.set(address, filtered);
|
|
63
|
-
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(filtered));
|
|
93
|
+
await this.storage.setItem(`vtxos:${address}`, JSON.stringify(filtered.map(serializeVtxo)));
|
|
64
94
|
}
|
|
65
95
|
async clearVtxos(address) {
|
|
66
96
|
this.cache.vtxos.set(address, []);
|
package/dist/esm/script/base.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Address, p2tr, TAP_LEAF_VERSION, taprootListToTree, } from "@scure/btc-signer/payment";
|
|
2
|
-
import { TAPROOT_UNSPENDABLE_KEY, } from "@scure/btc-signer/utils";
|
|
1
|
+
import { Address, p2tr, TAP_LEAF_VERSION, taprootListToTree, } from "@scure/btc-signer/payment.js";
|
|
2
|
+
import { TAPROOT_UNSPENDABLE_KEY, } from "@scure/btc-signer/utils.js";
|
|
3
3
|
import { ArkAddress } from './address.js';
|
|
4
|
-
import { Script } from "@scure/btc-signer";
|
|
4
|
+
import { Script } from "@scure/btc-signer/script.js";
|
|
5
5
|
import { hex } from "@scure/base";
|
|
6
6
|
import { ConditionCSVMultisigTapscript, CSVMultisigTapscript, } from './tapscript.js';
|
|
7
7
|
export function scriptFromTapLeafScript(leaf) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as bip68 from "bip68";
|
|
2
|
-
import { Script, ScriptNum } from "@scure/btc-signer/script";
|
|
3
|
-
import { p2tr_ms } from "@scure/btc-signer/payment";
|
|
2
|
+
import { Script, ScriptNum } from "@scure/btc-signer/script.js";
|
|
3
|
+
import { p2tr_ms } from "@scure/btc-signer/payment.js";
|
|
4
4
|
import { hex } from "@scure/base";
|
|
5
5
|
const MinimalScriptNum = ScriptNum(undefined, true);
|
|
6
6
|
export var TapscriptType;
|
|
@@ -260,7 +260,7 @@ export var CSVMultisigTapscript;
|
|
|
260
260
|
throw new Error(`Invalid script: too short (expected at least 3)`);
|
|
261
261
|
}
|
|
262
262
|
const sequence = asm[0];
|
|
263
|
-
if (typeof sequence === "string"
|
|
263
|
+
if (typeof sequence === "string") {
|
|
264
264
|
throw new Error("Invalid script: expected sequence number");
|
|
265
265
|
}
|
|
266
266
|
if (asm[1] !== "CHECKSEQUENCEVERIFY" || asm[2] !== "DROP") {
|
|
@@ -274,7 +274,13 @@ export var CSVMultisigTapscript;
|
|
|
274
274
|
catch (error) {
|
|
275
275
|
throw new Error(`Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`);
|
|
276
276
|
}
|
|
277
|
-
|
|
277
|
+
let sequenceNum;
|
|
278
|
+
if (typeof sequence === "number") {
|
|
279
|
+
sequenceNum = sequence;
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
sequenceNum = Number(MinimalScriptNum.decode(sequence));
|
|
283
|
+
}
|
|
278
284
|
const decodedTimelock = bip68.decode(sequenceNum);
|
|
279
285
|
const timelock = decodedTimelock.blocks !== undefined
|
|
280
286
|
? { type: "blocks", value: BigInt(decodedTimelock.blocks) }
|
package/dist/esm/script/vhtlc.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Script } from "@scure/btc-signer";
|
|
1
|
+
import { Script } from "@scure/btc-signer/script.js";
|
|
2
2
|
import { CLTVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CSVMultisigTapscript, MultisigTapscript, } from './tapscript.js';
|
|
3
3
|
import { hex } from "@scure/base";
|
|
4
4
|
import { VtxoScript } from './base.js';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as musig2 from '../musig2/index.js';
|
|
2
|
-
import { Script
|
|
2
|
+
import { Script } from "@scure/btc-signer/script.js";
|
|
3
|
+
import { SigHash } from "@scure/btc-signer/transaction.js";
|
|
3
4
|
import { hex } from "@scure/base";
|
|
4
5
|
import { schnorr, secp256k1 } from "@noble/curves/secp256k1.js";
|
|
5
|
-
import { randomPrivateKeyBytes, sha256x2 } from "@scure/btc-signer/utils";
|
|
6
|
+
import { randomPrivateKeyBytes, sha256x2 } from "@scure/btc-signer/utils.js";
|
|
6
7
|
import { CosignerPublicKey, getArkPsbtFields } from '../utils/unknownFields.js';
|
|
7
8
|
export const ErrMissingVtxoGraph = new Error("missing vtxo graph");
|
|
8
9
|
export const ErrMissingAggregateKey = new Error("missing aggregate key");
|
|
@@ -52,7 +53,7 @@ export class TreeSignerSession {
|
|
|
52
53
|
if (!this.myNonces)
|
|
53
54
|
throw new Error("nonces not generated");
|
|
54
55
|
const sigs = new Map();
|
|
55
|
-
for (const g of this.graph) {
|
|
56
|
+
for (const g of this.graph.iterator()) {
|
|
56
57
|
const sig = this.signPartial(g);
|
|
57
58
|
sigs.set(g.txid, sig);
|
|
58
59
|
}
|
|
@@ -63,7 +64,7 @@ export class TreeSignerSession {
|
|
|
63
64
|
throw ErrMissingVtxoGraph;
|
|
64
65
|
const myNonces = new Map();
|
|
65
66
|
const publicKey = secp256k1.getPublicKey(this.secretKey);
|
|
66
|
-
for (const g of this.graph) {
|
|
67
|
+
for (const g of this.graph.iterator()) {
|
|
67
68
|
const nonces = musig2.generateNonces(publicKey);
|
|
68
69
|
myNonces.set(g.txid, nonces);
|
|
69
70
|
}
|
|
@@ -105,7 +106,7 @@ TreeSignerSession.NOT_INITIALIZED = new Error("session not initialized, call ini
|
|
|
105
106
|
// Helper function to validate tree signatures
|
|
106
107
|
export async function validateTreeSigs(finalAggregatedKey, sharedOutputAmount, vtxoTree) {
|
|
107
108
|
// Iterate through each level of the tree
|
|
108
|
-
for (const g of vtxoTree) {
|
|
109
|
+
for (const g of vtxoTree.iterator()) {
|
|
109
110
|
// Parse the transaction
|
|
110
111
|
const input = g.root.getInput(0);
|
|
111
112
|
// Check if input has signature
|
package/dist/esm/tree/txTree.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Transaction } from "@scure/btc-signer";
|
|
1
|
+
import { Transaction } from "@scure/btc-signer/transaction.js";
|
|
2
2
|
import { base64 } from "@scure/base";
|
|
3
3
|
import { hex } from "@scure/base";
|
|
4
|
-
import { sha256x2 } from "@scure/btc-signer/utils";
|
|
4
|
+
import { sha256x2 } from "@scure/btc-signer/utils.js";
|
|
5
5
|
/**
|
|
6
6
|
* TxTree is a graph of bitcoin transactions.
|
|
7
7
|
* It is used to represent batch tree created during settlement session
|
|
@@ -154,11 +154,11 @@ export class TxTree {
|
|
|
154
154
|
}
|
|
155
155
|
throw new Error(`tx not found: ${txid}`);
|
|
156
156
|
}
|
|
157
|
-
*
|
|
158
|
-
yield this;
|
|
157
|
+
*iterator() {
|
|
159
158
|
for (const child of this.children.values()) {
|
|
160
|
-
yield* child;
|
|
159
|
+
yield* child.iterator();
|
|
161
160
|
}
|
|
161
|
+
yield this;
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
// Helper function to check if a chunk has a specific child
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { hex } from "@scure/base";
|
|
2
|
-
import { Transaction } from "@scure/btc-signer";
|
|
2
|
+
import { Transaction } from "@scure/btc-signer/transaction.js";
|
|
3
3
|
import { base64 } from "@scure/base";
|
|
4
|
-
import { sha256x2 } from "@scure/btc-signer/utils";
|
|
4
|
+
import { sha256x2 } from "@scure/btc-signer/utils.js";
|
|
5
5
|
import { aggregateKeys } from '../musig2/index.js';
|
|
6
6
|
import { CosignerPublicKey, getArkPsbtFields } from '../utils/unknownFields.js';
|
|
7
7
|
export const ErrInvalidSettlementTx = (tx) => new Error(`invalid settlement transaction: ${tx}`);
|
|
@@ -75,7 +75,7 @@ export function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
|
|
|
75
75
|
// validate the graph structure
|
|
76
76
|
graph.validate();
|
|
77
77
|
// iterates over all the nodes of the graph to verify that cosigners public keys are corresponding to the parent output
|
|
78
|
-
for (const g of graph) {
|
|
78
|
+
for (const g of graph.iterator()) {
|
|
79
79
|
for (const [childIndex, child] of g.children) {
|
|
80
80
|
const parentOutput = g.root.getOutput(childIndex);
|
|
81
81
|
if (!parentOutput?.script) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { DEFAULT_SEQUENCE, Transaction } from "@scure/btc-signer";
|
|
1
|
+
import { DEFAULT_SEQUENCE, Transaction, } from "@scure/btc-signer/transaction.js";
|
|
2
2
|
import { CLTVMultisigTapscript, decodeTapscript } from '../script/tapscript.js';
|
|
3
3
|
import { scriptFromTapLeafScript, VtxoScript, } from '../script/base.js';
|
|
4
4
|
import { P2A } from './anchor.js';
|
|
5
5
|
import { hex } from "@scure/base";
|
|
6
|
-
import { sha256x2 } from "@scure/btc-signer/utils";
|
|
6
|
+
import { sha256x2 } from "@scure/btc-signer/utils.js";
|
|
7
7
|
import { setArkPsbtField, VtxoTaprootTree } from './unknownFields.js';
|
|
8
8
|
/**
|
|
9
9
|
* Builds an offchain transaction with checkpoint transactions.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { p2tr } from "@scure/btc-signer/payment";
|
|
1
|
+
import { p2tr } from "@scure/btc-signer/payment.js";
|
|
2
2
|
import { getNetwork } from '../networks.js';
|
|
3
3
|
import { ESPLORA_URL, EsploraProvider, } from '../providers/onchain.js';
|
|
4
|
-
import { Transaction } from "@scure/btc-signer";
|
|
4
|
+
import { Transaction } from "@scure/btc-signer/transaction.js";
|
|
5
5
|
import { findP2AOutput, P2A } from '../utils/anchor.js';
|
|
6
6
|
import { TxWeightEstimator } from '../utils/txSizeEstimator.js';
|
|
7
7
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { SigHash, Transaction } from "@scure/btc-signer";
|
|
1
|
+
import { SigHash, Transaction } from "@scure/btc-signer/transaction.js";
|
|
2
2
|
import { ChainTxType } from '../providers/indexer.js';
|
|
3
3
|
import { base64, hex } from "@scure/base";
|
|
4
4
|
import { VtxoScript } from '../script/base.js';
|
|
5
|
-
import { TaprootControlBlock, } from "@scure/btc-signer/psbt";
|
|
5
|
+
import { TaprootControlBlock, } from "@scure/btc-signer/psbt.js";
|
|
6
6
|
import { TxWeightEstimator } from '../utils/txSizeEstimator.js';
|
|
7
7
|
import { Wallet } from './wallet.js';
|
|
8
8
|
export var Unroll;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { base64, hex } from "@scure/base";
|
|
2
2
|
import * as bip68 from "bip68";
|
|
3
|
-
import { Address, OutScript, tapLeafHash } from "@scure/btc-signer/payment";
|
|
4
|
-
import { SigHash, Transaction } from "@scure/btc-signer";
|
|
5
|
-
import { TaprootControlBlock, } from "@scure/btc-signer/psbt";
|
|
3
|
+
import { Address, OutScript, tapLeafHash } from "@scure/btc-signer/payment.js";
|
|
4
|
+
import { SigHash, Transaction } from "@scure/btc-signer/transaction.js";
|
|
5
|
+
import { TaprootControlBlock, } from "@scure/btc-signer/psbt.js";
|
|
6
6
|
import { vtxosToTxs } from '../utils/transactionHistory.js';
|
|
7
7
|
import { ArkAddress } from '../script/address.js';
|
|
8
8
|
import { DefaultVtxo } from '../script/default.js';
|
|
@@ -12,7 +12,7 @@ import { SettlementEventType, RestArkProvider, } from '../providers/ark.js';
|
|
|
12
12
|
import { buildForfeitTx } from '../forfeit.js';
|
|
13
13
|
import { validateConnectorsTxGraph, validateVtxoTxGraph, } from '../tree/validation.js';
|
|
14
14
|
import { isRecoverable, isSpendable, isSubdust, TxType, } from './index.js';
|
|
15
|
-
import { sha256, sha256x2 } from "@scure/btc-signer/utils";
|
|
15
|
+
import { sha256, sha256x2 } from "@scure/btc-signer/utils.js";
|
|
16
16
|
import { VtxoScript } from '../script/base.js';
|
|
17
17
|
import { CSVMultisigTapscript } from '../script/tapscript.js';
|
|
18
18
|
import { buildOffchainTx } from '../utils/arkTransaction.js';
|
|
@@ -98,10 +98,8 @@ export class Wallet {
|
|
|
98
98
|
// Save tapscripts
|
|
99
99
|
const offchainTapscript = bareVtxoTapscript;
|
|
100
100
|
// the serverUnrollScript is the one used to create output scripts of the checkpoint transactions
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
pubkeys: [serverPubKey],
|
|
104
|
-
});
|
|
101
|
+
const rawCheckpointExitClosure = hex.decode(info.checkpointExitClosure);
|
|
102
|
+
const serverUnrollScript = CSVMultisigTapscript.decode(rawCheckpointExitClosure);
|
|
105
103
|
// parse the server forfeit address
|
|
106
104
|
// server is expecting funds to be sent to this address
|
|
107
105
|
const forfeitAddress = Address(network).decode(info.forfeitAddress);
|
|
@@ -167,8 +165,9 @@ export class Wallet {
|
|
|
167
165
|
}
|
|
168
166
|
async getVtxos(filter) {
|
|
169
167
|
const address = await this.getAddress();
|
|
170
|
-
// Try to get from cache first
|
|
171
|
-
const cachedVtxos = await this.walletRepository.getVtxos(address);
|
|
168
|
+
// Try to get from cache first first (optional fast path)
|
|
169
|
+
// const cachedVtxos = await this.walletRepository.getVtxos(address);
|
|
170
|
+
// if (cachedVtxos.length) return cachedVtxos;
|
|
172
171
|
// For now, always fetch fresh data from provider and update cache
|
|
173
172
|
// In future, we can add cache invalidation logic based on timestamps
|
|
174
173
|
const spendableVtxos = await this.getVirtualCoins(filter);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TapLeafScript, VtxoScript } from "../script/base";
|
|
2
|
-
import { Bytes } from "@scure/btc-signer/utils";
|
|
2
|
+
import { Bytes } from "@scure/btc-signer/utils.js";
|
|
3
3
|
import { ExtendedCoin, Status } from "../wallet";
|
|
4
4
|
/**
|
|
5
5
|
* ArkNotes are special virtual coins in the Ark protocol that can be created
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Transaction } from "@scure/btc-signer";
|
|
2
|
-
import { TransactionInput, TransactionOutput } from "@scure/btc-signer/psbt";
|
|
1
|
+
import { Transaction } from "@scure/btc-signer/transaction.js";
|
|
2
|
+
import { TransactionInput, TransactionOutput } from "@scure/btc-signer/psbt.js";
|
|
3
3
|
/**
|
|
4
4
|
* BIP-322 signature implementation for Bitcoin message signing.
|
|
5
5
|
*
|
package/dist/types/forfeit.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Transaction } from "@scure/btc-signer";
|
|
1
|
+
import { Transaction } from "@scure/btc-signer/transaction.js";
|
|
2
2
|
import { TransactionInputUpdate } from "@scure/btc-signer/psbt";
|
|
3
3
|
export declare function buildForfeitTx(inputs: TransactionInputUpdate[], forfeitPkScript: Uint8Array, txLocktime?: number): Transaction;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Transaction } from "@scure/btc-signer";
|
|
1
|
+
import { Transaction } from "@scure/btc-signer/transaction.js";
|
|
2
2
|
import { SignerSession } from "../tree/signingSession";
|
|
3
3
|
export interface Identity {
|
|
4
|
-
sign(tx: Transaction, inputIndexes?: number[]): Promise<Transaction>;
|
|
5
|
-
xOnlyPublicKey(): Promise<Uint8Array>;
|
|
6
4
|
signerSession(): SignerSession;
|
|
5
|
+
xOnlyPublicKey(): Promise<Uint8Array>;
|
|
6
|
+
compressedPublicKey(): Promise<Uint8Array>;
|
|
7
7
|
signMessage(message: string): Promise<Uint8Array>;
|
|
8
|
+
sign(tx: Transaction, inputIndexes?: number[]): Promise<Transaction>;
|
|
8
9
|
}
|
|
9
10
|
export * from "./singleKey";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Transaction } from "@scure/btc-signer";
|
|
1
|
+
import { Transaction } from "@scure/btc-signer/transaction.js";
|
|
2
2
|
import { Identity } from ".";
|
|
3
3
|
import { SignerSession } from "../tree/signingSession";
|
|
4
4
|
/**
|
|
@@ -32,6 +32,7 @@ export declare class SingleKey implements Identity {
|
|
|
32
32
|
*/
|
|
33
33
|
toHex(): string;
|
|
34
34
|
sign(tx: Transaction, inputIndexes?: number[]): Promise<Transaction>;
|
|
35
|
+
compressedPublicKey(): Promise<Uint8Array>;
|
|
35
36
|
xOnlyPublicKey(): Promise<Uint8Array>;
|
|
36
37
|
signerSession(): SignerSession;
|
|
37
38
|
signMessage(message: string): Promise<Uint8Array>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function eventSourceIterator(eventSource: EventSource): AsyncGenerator<MessageEvent, void, unknown>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BTC_NETWORK, Bytes } from "@scure/btc-signer/utils";
|
|
1
|
+
import { BTC_NETWORK, Bytes } from "@scure/btc-signer/utils.js";
|
|
2
2
|
import { ArkAddress } from "./address";
|
|
3
3
|
import { ConditionCSVMultisigTapscript, CSVMultisigTapscript } from "./tapscript";
|
|
4
4
|
export type TapLeafScript = [
|