@arkade-os/sdk 0.3.0-alpha.7 → 0.3.1-alpha.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 +115 -14
- package/dist/cjs/adapters/expo.js +8 -0
- package/dist/cjs/arknote/index.js +3 -3
- package/dist/cjs/forfeit.js +5 -2
- package/dist/cjs/identity/singleKey.js +5 -4
- package/dist/cjs/index.js +7 -3
- package/dist/cjs/{bip322 → intent}/index.js +37 -55
- package/dist/cjs/providers/ark.js +62 -23
- package/dist/cjs/providers/expoArk.js +82 -0
- package/dist/cjs/providers/expoIndexer.js +105 -0
- package/dist/cjs/providers/indexer.js +3 -1
- package/dist/cjs/providers/utils.js +122 -0
- package/dist/cjs/script/base.js +1 -2
- package/dist/cjs/script/tapscript.js +20 -21
- package/dist/cjs/script/vhtlc.js +2 -2
- package/dist/cjs/tree/signingSession.js +7 -8
- package/dist/cjs/tree/txTree.js +3 -4
- package/dist/cjs/tree/validation.js +2 -3
- package/dist/cjs/utils/arkTransaction.js +117 -12
- package/dist/cjs/utils/unknownFields.js +5 -5
- package/dist/cjs/wallet/index.js +1 -1
- package/dist/cjs/wallet/onchain.js +4 -5
- package/dist/cjs/wallet/serviceWorker/utils.js +2 -9
- package/dist/cjs/wallet/serviceWorker/wallet.js +4 -8
- package/dist/cjs/wallet/serviceWorker/worker.js +25 -23
- package/dist/cjs/wallet/unroll.js +6 -7
- package/dist/cjs/wallet/utils.js +11 -0
- package/dist/cjs/wallet/vtxo-manager.js +381 -0
- package/dist/cjs/wallet/wallet.js +130 -143
- package/dist/esm/adapters/expo.js +3 -0
- package/dist/esm/arknote/index.js +2 -2
- package/dist/esm/forfeit.js +4 -1
- package/dist/esm/identity/singleKey.js +7 -6
- package/dist/esm/index.js +7 -6
- package/dist/esm/{bip322 → intent}/index.js +31 -48
- package/dist/esm/providers/ark.js +62 -23
- package/dist/esm/providers/expoArk.js +78 -0
- package/dist/esm/providers/expoIndexer.js +101 -0
- package/dist/esm/providers/indexer.js +3 -1
- package/dist/esm/providers/utils.js +87 -0
- package/dist/esm/script/base.js +1 -2
- package/dist/esm/script/tapscript.js +1 -2
- package/dist/esm/script/vhtlc.js +1 -1
- package/dist/esm/tree/signingSession.js +8 -9
- package/dist/esm/tree/txTree.js +3 -4
- package/dist/esm/tree/validation.js +2 -3
- package/dist/esm/utils/arkTransaction.js +108 -5
- package/dist/esm/utils/unknownFields.js +1 -1
- package/dist/esm/wallet/index.js +1 -1
- package/dist/esm/wallet/onchain.js +1 -2
- package/dist/esm/wallet/serviceWorker/utils.js +1 -8
- package/dist/esm/wallet/serviceWorker/wallet.js +5 -9
- package/dist/esm/wallet/serviceWorker/worker.js +26 -24
- package/dist/esm/wallet/unroll.js +2 -3
- package/dist/esm/wallet/utils.js +8 -0
- package/dist/esm/wallet/vtxo-manager.js +372 -0
- package/dist/esm/wallet/wallet.js +124 -137
- package/dist/types/adapters/expo.d.ts +4 -0
- package/dist/types/arknote/index.d.ts +1 -1
- package/dist/types/forfeit.d.ts +2 -2
- package/dist/types/identity/index.d.ts +1 -1
- package/dist/types/identity/singleKey.d.ts +1 -1
- package/dist/types/index.d.ts +8 -7
- package/dist/types/intent/index.d.ts +41 -0
- package/dist/types/providers/ark.d.ts +190 -22
- package/dist/types/providers/expoArk.d.ts +22 -0
- package/dist/types/providers/expoIndexer.d.ts +18 -0
- package/dist/types/providers/indexer.d.ts +8 -8
- package/dist/types/providers/utils.d.ts +18 -0
- package/dist/types/script/base.d.ts +3 -2
- package/dist/types/tree/signingSession.d.ts +10 -10
- package/dist/types/utils/anchor.d.ts +2 -2
- package/dist/types/utils/arkTransaction.d.ts +16 -4
- package/dist/types/utils/unknownFields.d.ts +2 -2
- package/dist/types/wallet/index.d.ts +47 -7
- package/dist/types/wallet/onchain.d.ts +1 -1
- package/dist/types/wallet/serviceWorker/utils.d.ts +1 -2
- package/dist/types/wallet/serviceWorker/wallet.d.ts +2 -2
- package/dist/types/wallet/serviceWorker/worker.d.ts +3 -1
- package/dist/types/wallet/unroll.d.ts +1 -1
- package/dist/types/wallet/utils.d.ts +2 -0
- package/dist/types/wallet/vtxo-manager.d.ts +207 -0
- package/dist/types/wallet/wallet.d.ts +16 -4
- package/package.json +11 -3
- package/dist/cjs/bip322/errors.js +0 -13
- package/dist/esm/bip322/errors.js +0 -9
- package/dist/types/bip322/errors.d.ts +0 -6
- package/dist/types/bip322/index.d.ts +0 -57
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExpoArkProvider = void 0;
|
|
4
|
+
const ark_1 = require("./ark");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
/**
|
|
7
|
+
* Expo-compatible Ark provider implementation using expo/fetch for SSE support.
|
|
8
|
+
* This provider works specifically in React Native/Expo environments where
|
|
9
|
+
* standard EventSource is not available but expo/fetch provides SSE capabilities.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import { ExpoArkProvider } from '@arkade-os/sdk/providers/expo';
|
|
14
|
+
*
|
|
15
|
+
* const provider = new ExpoArkProvider('https://ark.example.com');
|
|
16
|
+
* const info = await provider.getInfo();
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
class ExpoArkProvider extends ark_1.RestArkProvider {
|
|
20
|
+
constructor(serverUrl) {
|
|
21
|
+
super(serverUrl);
|
|
22
|
+
}
|
|
23
|
+
async *getEventStream(signal, topics) {
|
|
24
|
+
const expoFetch = await (0, utils_1.getExpoFetch)();
|
|
25
|
+
const url = `${this.serverUrl}/v1/batch/events`;
|
|
26
|
+
const queryParams = topics.length > 0
|
|
27
|
+
? `?${topics.map((topic) => `topics=${encodeURIComponent(topic)}`).join("&")}`
|
|
28
|
+
: "";
|
|
29
|
+
while (!signal?.aborted) {
|
|
30
|
+
try {
|
|
31
|
+
yield* (0, utils_1.sseStreamIterator)(url + queryParams, signal, expoFetch, {}, (data) => {
|
|
32
|
+
// Handle different response structures
|
|
33
|
+
// v8 mesh API might wrap in {result: ...} or send directly
|
|
34
|
+
const eventData = data.result || data;
|
|
35
|
+
// Skip heartbeat messages
|
|
36
|
+
if (eventData.heartbeat !== undefined) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return this.parseSettlementEvent(eventData);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
// ignore timeout errors, they're expected when the server is not sending anything for 5 min
|
|
47
|
+
// these timeouts are set by expo/fetch function
|
|
48
|
+
if ((0, ark_1.isFetchTimeoutError)(error)) {
|
|
49
|
+
console.debug("Timeout error ignored");
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
console.error("Event stream error:", error);
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async *getTransactionsStream(signal) {
|
|
58
|
+
const expoFetch = await (0, utils_1.getExpoFetch)();
|
|
59
|
+
const url = `${this.serverUrl}/v1/txs`;
|
|
60
|
+
while (!signal?.aborted) {
|
|
61
|
+
try {
|
|
62
|
+
yield* (0, utils_1.sseStreamIterator)(url, signal, expoFetch, {}, (data) => {
|
|
63
|
+
return this.parseTransactionNotification(data.result);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
// ignore timeout errors, they're expected when the server is not sending anything for 5 min
|
|
71
|
+
// these timeouts are set by expo/fetch function
|
|
72
|
+
if ((0, ark_1.isFetchTimeoutError)(error)) {
|
|
73
|
+
console.debug("Timeout error ignored");
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
console.error("Transaction stream error:", error);
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.ExpoArkProvider = ExpoArkProvider;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExpoIndexerProvider = void 0;
|
|
4
|
+
const indexer_1 = require("./indexer");
|
|
5
|
+
const ark_1 = require("./ark");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
// Helper function to convert Vtxo to VirtualCoin (same as in indexer.ts)
|
|
8
|
+
function convertVtxo(vtxo) {
|
|
9
|
+
return {
|
|
10
|
+
txid: vtxo.outpoint.txid,
|
|
11
|
+
vout: vtxo.outpoint.vout,
|
|
12
|
+
value: Number(vtxo.amount),
|
|
13
|
+
status: {
|
|
14
|
+
confirmed: !vtxo.isSwept && !vtxo.isPreconfirmed,
|
|
15
|
+
},
|
|
16
|
+
virtualStatus: {
|
|
17
|
+
state: vtxo.isSwept
|
|
18
|
+
? "swept"
|
|
19
|
+
: vtxo.isPreconfirmed
|
|
20
|
+
? "preconfirmed"
|
|
21
|
+
: "settled",
|
|
22
|
+
commitmentTxIds: vtxo.commitmentTxids,
|
|
23
|
+
batchExpiry: vtxo.expiresAt
|
|
24
|
+
? Number(vtxo.expiresAt) * 1000
|
|
25
|
+
: undefined,
|
|
26
|
+
},
|
|
27
|
+
spentBy: vtxo.spentBy ?? "",
|
|
28
|
+
settledBy: vtxo.settledBy,
|
|
29
|
+
arkTxId: vtxo.arkTxid,
|
|
30
|
+
createdAt: new Date(Number(vtxo.createdAt) * 1000),
|
|
31
|
+
isUnrolled: vtxo.isUnrolled,
|
|
32
|
+
isSpent: vtxo.isSpent,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Expo-compatible Indexer provider implementation using expo/fetch for streaming support.
|
|
37
|
+
* This provider works specifically in React Native/Expo environments where
|
|
38
|
+
* standard fetch streaming may not work properly but expo/fetch provides streaming capabilities.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* import { ExpoIndexerProvider } from '@arkade-os/sdk/adapters/expo';
|
|
43
|
+
*
|
|
44
|
+
* const provider = new ExpoIndexerProvider('https://indexer.example.com');
|
|
45
|
+
* const vtxos = await provider.getVtxos({ scripts: ['script1'] });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
class ExpoIndexerProvider extends indexer_1.RestIndexerProvider {
|
|
49
|
+
constructor(serverUrl) {
|
|
50
|
+
super(serverUrl);
|
|
51
|
+
}
|
|
52
|
+
async *getSubscription(subscriptionId, abortSignal) {
|
|
53
|
+
// Detect if we're running in React Native/Expo environment
|
|
54
|
+
const isReactNative = typeof navigator !== "undefined" &&
|
|
55
|
+
navigator.product === "ReactNative";
|
|
56
|
+
const expoFetch = await (0, utils_1.getExpoFetch)().catch((error) => {
|
|
57
|
+
// In React Native/Expo, expo/fetch is required for proper streaming support
|
|
58
|
+
if (isReactNative) {
|
|
59
|
+
throw new Error("expo/fetch is unavailable in React Native environment. " +
|
|
60
|
+
"Please ensure expo/fetch is installed and properly configured. " +
|
|
61
|
+
"Streaming support may not work with standard fetch in React Native.");
|
|
62
|
+
}
|
|
63
|
+
throw error;
|
|
64
|
+
});
|
|
65
|
+
const url = `${this.serverUrl}/v1/indexer/script/subscription/${subscriptionId}`;
|
|
66
|
+
while (!abortSignal.aborted) {
|
|
67
|
+
try {
|
|
68
|
+
yield* (0, utils_1.sseStreamIterator)(url, abortSignal, expoFetch, { "Content-Type": "application/json" }, (data) => {
|
|
69
|
+
// Handle new v8 proto format with heartbeat or event
|
|
70
|
+
if (data.heartbeat !== undefined) {
|
|
71
|
+
// Skip heartbeat messages
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
// Process event messages
|
|
75
|
+
if (data.event) {
|
|
76
|
+
return {
|
|
77
|
+
txid: data.event.txid,
|
|
78
|
+
scripts: data.event.scripts || [],
|
|
79
|
+
newVtxos: (data.event.newVtxos || []).map(convertVtxo),
|
|
80
|
+
spentVtxos: (data.event.spentVtxos || []).map(convertVtxo),
|
|
81
|
+
sweptVtxos: (data.event.sweptVtxos || []).map(convertVtxo),
|
|
82
|
+
tx: data.event.tx,
|
|
83
|
+
checkpointTxs: data.event.checkpointTxs,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
// ignore timeout errors, they're expected when the server is not sending anything for 5 min
|
|
94
|
+
// these timeouts are set by expo/fetch function
|
|
95
|
+
if ((0, ark_1.isFetchTimeoutError)(error)) {
|
|
96
|
+
console.debug("Timeout error ignored");
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
console.error("Subscription error:", error);
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.ExpoIndexerProvider = ExpoIndexerProvider;
|
|
@@ -176,6 +176,7 @@ class RestIndexerProvider {
|
|
|
176
176
|
scripts: data.event.scripts || [],
|
|
177
177
|
newVtxos: (data.event.newVtxos || []).map(convertVtxo),
|
|
178
178
|
spentVtxos: (data.event.spentVtxos || []).map(convertVtxo),
|
|
179
|
+
sweptVtxos: (data.event.sweptVtxos || []).map(convertVtxo),
|
|
179
180
|
tx: data.event.tx,
|
|
180
181
|
checkpointTxs: data.event.checkpointTxs,
|
|
181
182
|
};
|
|
@@ -329,7 +330,7 @@ class RestIndexerProvider {
|
|
|
329
330
|
});
|
|
330
331
|
if (!res.ok) {
|
|
331
332
|
const errorText = await res.text();
|
|
332
|
-
|
|
333
|
+
console.warn(`Failed to unsubscribe to scripts: ${errorText}`);
|
|
333
334
|
}
|
|
334
335
|
}
|
|
335
336
|
}
|
|
@@ -358,6 +359,7 @@ function convertVtxo(vtxo) {
|
|
|
358
359
|
arkTxId: vtxo.arkTxid,
|
|
359
360
|
createdAt: new Date(Number(vtxo.createdAt) * 1000),
|
|
360
361
|
isUnrolled: vtxo.isUnrolled,
|
|
362
|
+
isSpent: vtxo.isSpent,
|
|
361
363
|
};
|
|
362
364
|
}
|
|
363
365
|
// Unexported namespace for type guards only
|
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.eventSourceIterator = eventSourceIterator;
|
|
37
|
+
exports.getExpoFetch = getExpoFetch;
|
|
38
|
+
exports.sseStreamIterator = sseStreamIterator;
|
|
4
39
|
async function* eventSourceIterator(eventSource) {
|
|
5
40
|
const messageQueue = [];
|
|
6
41
|
const errorQueue = [];
|
|
@@ -58,3 +93,90 @@ async function* eventSourceIterator(eventSource) {
|
|
|
58
93
|
eventSource.removeEventListener("error", errorHandler);
|
|
59
94
|
}
|
|
60
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Dynamically imports expo/fetch with fallback to standard fetch.
|
|
98
|
+
* @returns A fetch function suitable for SSE streaming
|
|
99
|
+
*/
|
|
100
|
+
async function getExpoFetch(options) {
|
|
101
|
+
const requireExpo = options?.requireExpo ?? false;
|
|
102
|
+
try {
|
|
103
|
+
const expoFetchModule = await Promise.resolve().then(() => __importStar(require("expo/fetch")));
|
|
104
|
+
console.debug("Using expo/fetch for streaming");
|
|
105
|
+
return expoFetchModule.fetch;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (requireExpo) {
|
|
109
|
+
throw new Error("expo/fetch is unavailable in this environment. " +
|
|
110
|
+
"Please ensure expo/fetch is installed and properly configured.");
|
|
111
|
+
}
|
|
112
|
+
console.warn("Using standard fetch instead of expo/fetch. " +
|
|
113
|
+
"Streaming may not be fully supported in some environments.", error);
|
|
114
|
+
return fetch;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Generic SSE stream processor using fetch API with ReadableStream.
|
|
119
|
+
* Handles SSE format parsing, buffer management, and abort signals.
|
|
120
|
+
*
|
|
121
|
+
* @param url - The SSE endpoint URL
|
|
122
|
+
* @param abortSignal - Signal to abort the stream
|
|
123
|
+
* @param fetchFn - Fetch function to use (defaults to standard fetch)
|
|
124
|
+
* @param headers - Additional headers to send
|
|
125
|
+
* @param parseData - Function to parse and yield data from SSE events
|
|
126
|
+
*/
|
|
127
|
+
async function* sseStreamIterator(url, abortSignal, fetchFn, headers, parseData) {
|
|
128
|
+
const fetchController = new AbortController();
|
|
129
|
+
const cleanup = () => fetchController.abort();
|
|
130
|
+
abortSignal?.addEventListener("abort", cleanup, { once: true });
|
|
131
|
+
try {
|
|
132
|
+
const response = await fetchFn(url, {
|
|
133
|
+
headers: {
|
|
134
|
+
Accept: "text/event-stream",
|
|
135
|
+
...headers,
|
|
136
|
+
},
|
|
137
|
+
signal: fetchController.signal,
|
|
138
|
+
});
|
|
139
|
+
if (!response.ok) {
|
|
140
|
+
throw new Error(`Unexpected status ${response.status} when fetching SSE stream`);
|
|
141
|
+
}
|
|
142
|
+
if (!response.body) {
|
|
143
|
+
throw new Error("Response body is null");
|
|
144
|
+
}
|
|
145
|
+
const reader = response.body.getReader();
|
|
146
|
+
const decoder = new TextDecoder();
|
|
147
|
+
let buffer = "";
|
|
148
|
+
while (!abortSignal?.aborted) {
|
|
149
|
+
const { done, value } = await reader.read();
|
|
150
|
+
if (done) {
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
buffer += decoder.decode(value, { stream: true });
|
|
154
|
+
const lines = buffer.split("\n");
|
|
155
|
+
for (let i = 0; i < lines.length - 1; i++) {
|
|
156
|
+
const line = lines[i].trim();
|
|
157
|
+
if (!line)
|
|
158
|
+
continue;
|
|
159
|
+
if (line.startsWith("data:")) {
|
|
160
|
+
const jsonStr = line.substring(5).trim();
|
|
161
|
+
if (!jsonStr)
|
|
162
|
+
continue;
|
|
163
|
+
try {
|
|
164
|
+
const data = JSON.parse(jsonStr);
|
|
165
|
+
const parsed = parseData(data);
|
|
166
|
+
if (parsed !== null) {
|
|
167
|
+
yield parsed;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (parseError) {
|
|
171
|
+
console.error("Failed to parse SSE data:", parseError);
|
|
172
|
+
throw parseError;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
buffer = lines[lines.length - 1];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
abortSignal?.removeEventListener("abort", cleanup);
|
|
181
|
+
}
|
|
182
|
+
}
|
package/dist/cjs/script/base.js
CHANGED
|
@@ -5,7 +5,6 @@ exports.scriptFromTapLeafScript = scriptFromTapLeafScript;
|
|
|
5
5
|
const btc_signer_1 = require("@scure/btc-signer");
|
|
6
6
|
const payment_js_1 = require("@scure/btc-signer/payment.js");
|
|
7
7
|
const psbt_js_1 = require("@scure/btc-signer/psbt.js");
|
|
8
|
-
const utils_js_1 = require("@scure/btc-signer/utils.js");
|
|
9
8
|
const base_1 = require("@scure/base");
|
|
10
9
|
const address_1 = require("./address");
|
|
11
10
|
const tapscript_1 = require("./tapscript");
|
|
@@ -30,7 +29,7 @@ class VtxoScript {
|
|
|
30
29
|
constructor(scripts) {
|
|
31
30
|
this.scripts = scripts;
|
|
32
31
|
const tapTree = (0, btc_signer_1.taprootListToTree)(scripts.map((script) => ({ script, leafVersion: payment_js_1.TAP_LEAF_VERSION })));
|
|
33
|
-
const payment = (0, btc_signer_1.p2tr)(
|
|
32
|
+
const payment = (0, btc_signer_1.p2tr)(btc_signer_1.TAPROOT_UNSPENDABLE_KEY, tapTree, undefined, true);
|
|
34
33
|
if (!payment.tapLeafScript ||
|
|
35
34
|
payment.tapLeafScript.length !== scripts.length) {
|
|
36
35
|
throw new Error("invalid scripts");
|
|
@@ -36,10 +36,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.CLTVMultisigTapscript = exports.ConditionMultisigTapscript = exports.ConditionCSVMultisigTapscript = exports.CSVMultisigTapscript = exports.MultisigTapscript = exports.TapscriptType = void 0;
|
|
37
37
|
exports.decodeTapscript = decodeTapscript;
|
|
38
38
|
const bip68 = __importStar(require("bip68"));
|
|
39
|
-
const
|
|
40
|
-
const payment_js_1 = require("@scure/btc-signer/payment.js");
|
|
39
|
+
const btc_signer_1 = require("@scure/btc-signer");
|
|
41
40
|
const base_1 = require("@scure/base");
|
|
42
|
-
const MinimalScriptNum = (0,
|
|
41
|
+
const MinimalScriptNum = (0, btc_signer_1.ScriptNum)(undefined, true);
|
|
43
42
|
var TapscriptType;
|
|
44
43
|
(function (TapscriptType) {
|
|
45
44
|
TapscriptType["Multisig"] = "multisig";
|
|
@@ -109,7 +108,7 @@ var MultisigTapscript;
|
|
|
109
108
|
return {
|
|
110
109
|
type: TapscriptType.Multisig,
|
|
111
110
|
params,
|
|
112
|
-
script: (0,
|
|
111
|
+
script: (0, btc_signer_1.p2tr_ms)(params.pubkeys.length, params.pubkeys).script,
|
|
113
112
|
};
|
|
114
113
|
}
|
|
115
114
|
const asm = [];
|
|
@@ -126,7 +125,7 @@ var MultisigTapscript;
|
|
|
126
125
|
return {
|
|
127
126
|
type: TapscriptType.Multisig,
|
|
128
127
|
params,
|
|
129
|
-
script:
|
|
128
|
+
script: btc_signer_1.Script.encode(asm),
|
|
130
129
|
};
|
|
131
130
|
}
|
|
132
131
|
MultisigTapscript.encode = encode;
|
|
@@ -151,7 +150,7 @@ var MultisigTapscript;
|
|
|
151
150
|
MultisigTapscript.decode = decode;
|
|
152
151
|
// <pubkey> CHECKSIG <pubkey> CHECKSIGADD <len_keys> NUMEQUAL
|
|
153
152
|
function decodeChecksigAdd(script) {
|
|
154
|
-
const asm =
|
|
153
|
+
const asm = btc_signer_1.Script.decode(script);
|
|
155
154
|
const pubkeys = [];
|
|
156
155
|
let foundNumEqual = false;
|
|
157
156
|
// Parse through ASM operations
|
|
@@ -201,7 +200,7 @@ var MultisigTapscript;
|
|
|
201
200
|
}
|
|
202
201
|
// <pubkey> CHECKSIGVERIFY <pubkey> CHECKSIG
|
|
203
202
|
function decodeChecksig(script) {
|
|
204
|
-
const asm =
|
|
203
|
+
const asm = btc_signer_1.Script.decode(script);
|
|
205
204
|
const pubkeys = [];
|
|
206
205
|
// Parse through ASM operations
|
|
207
206
|
for (let i = 0; i < asm.length; i++) {
|
|
@@ -278,7 +277,7 @@ var CSVMultisigTapscript;
|
|
|
278
277
|
];
|
|
279
278
|
const multisigScript = MultisigTapscript.encode(params);
|
|
280
279
|
const script = new Uint8Array([
|
|
281
|
-
...
|
|
280
|
+
...btc_signer_1.Script.encode(asm),
|
|
282
281
|
...multisigScript.script,
|
|
283
282
|
]);
|
|
284
283
|
return {
|
|
@@ -292,7 +291,7 @@ var CSVMultisigTapscript;
|
|
|
292
291
|
if (script.length === 0) {
|
|
293
292
|
throw new Error("Failed to decode: script is empty");
|
|
294
293
|
}
|
|
295
|
-
const asm =
|
|
294
|
+
const asm = btc_signer_1.Script.decode(script);
|
|
296
295
|
if (asm.length < 3) {
|
|
297
296
|
throw new Error(`Invalid script: too short (expected at least 3)`);
|
|
298
297
|
}
|
|
@@ -303,7 +302,7 @@ var CSVMultisigTapscript;
|
|
|
303
302
|
if (asm[1] !== "CHECKSEQUENCEVERIFY" || asm[2] !== "DROP") {
|
|
304
303
|
throw new Error("Invalid script: expected CHECKSEQUENCEVERIFY DROP");
|
|
305
304
|
}
|
|
306
|
-
const multisigScript = new Uint8Array(
|
|
305
|
+
const multisigScript = new Uint8Array(btc_signer_1.Script.encode(asm.slice(3)));
|
|
307
306
|
let multisig;
|
|
308
307
|
try {
|
|
309
308
|
multisig = MultisigTapscript.decode(multisigScript);
|
|
@@ -361,7 +360,7 @@ var ConditionCSVMultisigTapscript;
|
|
|
361
360
|
function encode(params) {
|
|
362
361
|
const script = new Uint8Array([
|
|
363
362
|
...params.conditionScript,
|
|
364
|
-
...
|
|
363
|
+
...btc_signer_1.Script.encode(["VERIFY"]),
|
|
365
364
|
...CSVMultisigTapscript.encode(params).script,
|
|
366
365
|
]);
|
|
367
366
|
return {
|
|
@@ -375,7 +374,7 @@ var ConditionCSVMultisigTapscript;
|
|
|
375
374
|
if (script.length === 0) {
|
|
376
375
|
throw new Error("Failed to decode: script is empty");
|
|
377
376
|
}
|
|
378
|
-
const asm =
|
|
377
|
+
const asm = btc_signer_1.Script.decode(script);
|
|
379
378
|
if (asm.length < 1) {
|
|
380
379
|
throw new Error(`Invalid script: too short (expected at least 1)`);
|
|
381
380
|
}
|
|
@@ -388,8 +387,8 @@ var ConditionCSVMultisigTapscript;
|
|
|
388
387
|
if (verifyIndex === -1) {
|
|
389
388
|
throw new Error("Invalid script: missing VERIFY operation");
|
|
390
389
|
}
|
|
391
|
-
const conditionScript = new Uint8Array(
|
|
392
|
-
const csvMultisigScript = new Uint8Array(
|
|
390
|
+
const conditionScript = new Uint8Array(btc_signer_1.Script.encode(asm.slice(0, verifyIndex)));
|
|
391
|
+
const csvMultisigScript = new Uint8Array(btc_signer_1.Script.encode(asm.slice(verifyIndex + 1)));
|
|
393
392
|
let csvMultisig;
|
|
394
393
|
try {
|
|
395
394
|
csvMultisig = CSVMultisigTapscript.decode(csvMultisigScript);
|
|
@@ -436,7 +435,7 @@ var ConditionMultisigTapscript;
|
|
|
436
435
|
function encode(params) {
|
|
437
436
|
const script = new Uint8Array([
|
|
438
437
|
...params.conditionScript,
|
|
439
|
-
...
|
|
438
|
+
...btc_signer_1.Script.encode(["VERIFY"]),
|
|
440
439
|
...MultisigTapscript.encode(params).script,
|
|
441
440
|
]);
|
|
442
441
|
return {
|
|
@@ -450,7 +449,7 @@ var ConditionMultisigTapscript;
|
|
|
450
449
|
if (script.length === 0) {
|
|
451
450
|
throw new Error("Failed to decode: script is empty");
|
|
452
451
|
}
|
|
453
|
-
const asm =
|
|
452
|
+
const asm = btc_signer_1.Script.decode(script);
|
|
454
453
|
if (asm.length < 1) {
|
|
455
454
|
throw new Error(`Invalid script: too short (expected at least 1)`);
|
|
456
455
|
}
|
|
@@ -463,8 +462,8 @@ var ConditionMultisigTapscript;
|
|
|
463
462
|
if (verifyIndex === -1) {
|
|
464
463
|
throw new Error("Invalid script: missing VERIFY operation");
|
|
465
464
|
}
|
|
466
|
-
const conditionScript = new Uint8Array(
|
|
467
|
-
const multisigScript = new Uint8Array(
|
|
465
|
+
const conditionScript = new Uint8Array(btc_signer_1.Script.encode(asm.slice(0, verifyIndex)));
|
|
466
|
+
const multisigScript = new Uint8Array(btc_signer_1.Script.encode(asm.slice(verifyIndex + 1)));
|
|
468
467
|
let multisig;
|
|
469
468
|
try {
|
|
470
469
|
multisig = MultisigTapscript.decode(multisigScript);
|
|
@@ -515,7 +514,7 @@ var CLTVMultisigTapscript;
|
|
|
515
514
|
"CHECKLOCKTIMEVERIFY",
|
|
516
515
|
"DROP",
|
|
517
516
|
];
|
|
518
|
-
const timelockedScript =
|
|
517
|
+
const timelockedScript = btc_signer_1.Script.encode(asm);
|
|
519
518
|
const script = new Uint8Array([
|
|
520
519
|
...timelockedScript,
|
|
521
520
|
...MultisigTapscript.encode(params).script,
|
|
@@ -531,7 +530,7 @@ var CLTVMultisigTapscript;
|
|
|
531
530
|
if (script.length === 0) {
|
|
532
531
|
throw new Error("Failed to decode: script is empty");
|
|
533
532
|
}
|
|
534
|
-
const asm =
|
|
533
|
+
const asm = btc_signer_1.Script.decode(script);
|
|
535
534
|
if (asm.length < 3) {
|
|
536
535
|
throw new Error(`Invalid script: too short (expected at least 3)`);
|
|
537
536
|
}
|
|
@@ -542,7 +541,7 @@ var CLTVMultisigTapscript;
|
|
|
542
541
|
if (asm[1] !== "CHECKLOCKTIMEVERIFY" || asm[2] !== "DROP") {
|
|
543
542
|
throw new Error("Invalid script: expected CHECKLOCKTIMEVERIFY DROP");
|
|
544
543
|
}
|
|
545
|
-
const multisigScript = new Uint8Array(
|
|
544
|
+
const multisigScript = new Uint8Array(btc_signer_1.Script.encode(asm.slice(3)));
|
|
546
545
|
let multisig;
|
|
547
546
|
try {
|
|
548
547
|
multisig = MultisigTapscript.decode(multisigScript);
|
package/dist/cjs/script/vhtlc.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VHTLC = void 0;
|
|
4
|
-
const
|
|
4
|
+
const btc_signer_1 = require("@scure/btc-signer");
|
|
5
5
|
const tapscript_1 = require("./tapscript");
|
|
6
6
|
const base_1 = require("@scure/base");
|
|
7
7
|
const base_2 = require("./base");
|
|
@@ -158,5 +158,5 @@ var VHTLC;
|
|
|
158
158
|
}
|
|
159
159
|
})(VHTLC || (exports.VHTLC = VHTLC = {}));
|
|
160
160
|
function preimageConditionScript(preimageHash) {
|
|
161
|
-
return
|
|
161
|
+
return btc_signer_1.Script.encode(["HASH160", preimageHash, "EQUAL"]);
|
|
162
162
|
}
|
|
@@ -57,15 +57,15 @@ class TreeSignerSession {
|
|
|
57
57
|
const secretKey = (0, utils_js_1.randomPrivateKeyBytes)();
|
|
58
58
|
return new TreeSignerSession(secretKey);
|
|
59
59
|
}
|
|
60
|
-
init(tree, scriptRoot, rootInputAmount) {
|
|
60
|
+
async init(tree, scriptRoot, rootInputAmount) {
|
|
61
61
|
this.graph = tree;
|
|
62
62
|
this.scriptRoot = scriptRoot;
|
|
63
63
|
this.rootSharedOutputAmount = rootInputAmount;
|
|
64
64
|
}
|
|
65
|
-
getPublicKey() {
|
|
65
|
+
async getPublicKey() {
|
|
66
66
|
return secp256k1_js_1.secp256k1.getPublicKey(this.secretKey);
|
|
67
67
|
}
|
|
68
|
-
getNonces() {
|
|
68
|
+
async getNonces() {
|
|
69
69
|
if (!this.graph)
|
|
70
70
|
throw exports.ErrMissingVtxoGraph;
|
|
71
71
|
if (!this.myNonces) {
|
|
@@ -77,12 +77,12 @@ class TreeSignerSession {
|
|
|
77
77
|
}
|
|
78
78
|
return publicNonces;
|
|
79
79
|
}
|
|
80
|
-
setAggregatedNonces(nonces) {
|
|
80
|
+
async setAggregatedNonces(nonces) {
|
|
81
81
|
if (this.aggregateNonces)
|
|
82
82
|
throw new Error("nonces already set");
|
|
83
83
|
this.aggregateNonces = nonces;
|
|
84
84
|
}
|
|
85
|
-
sign() {
|
|
85
|
+
async sign() {
|
|
86
86
|
if (!this.graph)
|
|
87
87
|
throw exports.ErrMissingVtxoGraph;
|
|
88
88
|
if (!this.aggregateNonces)
|
|
@@ -166,9 +166,8 @@ async function validateTreeSigs(finalAggregatedKey, sharedOutputAmount, vtxoTree
|
|
|
166
166
|
function getPrevOutput(finalKey, graph, sharedOutputAmount, tx) {
|
|
167
167
|
// generate P2TR script from musig2 final key
|
|
168
168
|
const pkScript = script_js_1.Script.encode(["OP_1", finalKey.slice(1)]);
|
|
169
|
-
const txid = base_1.hex.encode((0, utils_js_1.sha256x2)(tx.toBytes(true)).reverse());
|
|
170
169
|
// if the input is the root input, return the shared output amount
|
|
171
|
-
if (
|
|
170
|
+
if (tx.id === graph.txid) {
|
|
172
171
|
return {
|
|
173
172
|
amount: sharedOutputAmount,
|
|
174
173
|
script: pkScript,
|
|
@@ -178,7 +177,7 @@ function getPrevOutput(finalKey, graph, sharedOutputAmount, tx) {
|
|
|
178
177
|
const parentInput = tx.getInput(0);
|
|
179
178
|
if (!parentInput.txid)
|
|
180
179
|
throw new Error("missing parent input txid");
|
|
181
|
-
const parentTxid = base_1.hex.encode(
|
|
180
|
+
const parentTxid = base_1.hex.encode(parentInput.txid);
|
|
182
181
|
const parent = graph.find(parentTxid);
|
|
183
182
|
if (!parent)
|
|
184
183
|
throw new Error("parent tx not found");
|
package/dist/cjs/tree/txTree.js
CHANGED
|
@@ -4,7 +4,6 @@ exports.TxTree = void 0;
|
|
|
4
4
|
const transaction_js_1 = require("@scure/btc-signer/transaction.js");
|
|
5
5
|
const base_1 = require("@scure/base");
|
|
6
6
|
const base_2 = require("@scure/base");
|
|
7
|
-
const utils_js_1 = require("@scure/btc-signer/utils.js");
|
|
8
7
|
/**
|
|
9
8
|
* TxTree is a graph of bitcoin transactions.
|
|
10
9
|
* It is used to represent batch tree created during settlement session
|
|
@@ -22,7 +21,7 @@ class TxTree {
|
|
|
22
21
|
const chunksByTxid = new Map();
|
|
23
22
|
for (const chunk of chunks) {
|
|
24
23
|
const decodedChunk = decodeNode(chunk);
|
|
25
|
-
const txid =
|
|
24
|
+
const txid = decodedChunk.tx.id;
|
|
26
25
|
chunksByTxid.set(txid, decodedChunk);
|
|
27
26
|
}
|
|
28
27
|
// Find the root chunks (the ones that aren't referenced as a child)
|
|
@@ -91,7 +90,7 @@ class TxTree {
|
|
|
91
90
|
}
|
|
92
91
|
child.validate();
|
|
93
92
|
const childInput = child.root.getInput(0);
|
|
94
|
-
const parentTxid =
|
|
93
|
+
const parentTxid = this.root.id;
|
|
95
94
|
// verify the input of the child is the output of the parent
|
|
96
95
|
if (!childInput.txid ||
|
|
97
96
|
base_2.hex.encode(childInput.txid) !== parentTxid ||
|
|
@@ -126,7 +125,7 @@ class TxTree {
|
|
|
126
125
|
return leaves;
|
|
127
126
|
}
|
|
128
127
|
get txid() {
|
|
129
|
-
return
|
|
128
|
+
return this.root.id;
|
|
130
129
|
}
|
|
131
130
|
find(txid) {
|
|
132
131
|
if (txid === this.txid) {
|
|
@@ -6,7 +6,6 @@ exports.validateVtxoTxGraph = validateVtxoTxGraph;
|
|
|
6
6
|
const base_1 = require("@scure/base");
|
|
7
7
|
const transaction_js_1 = require("@scure/btc-signer/transaction.js");
|
|
8
8
|
const base_2 = require("@scure/base");
|
|
9
|
-
const utils_js_1 = require("@scure/btc-signer/utils.js");
|
|
10
9
|
const musig2_1 = require("../musig2");
|
|
11
10
|
const unknownFields_1 = require("../utils/unknownFields");
|
|
12
11
|
const ErrInvalidSettlementTx = (tx) => new Error(`invalid settlement transaction: ${tx}`);
|
|
@@ -31,7 +30,7 @@ function validateConnectorsTxGraph(settlementTxB64, connectorsGraph) {
|
|
|
31
30
|
const settlementTx = transaction_js_1.Transaction.fromPSBT(base_2.base64.decode(settlementTxB64));
|
|
32
31
|
if (settlementTx.outputsLength <= BATCH_OUTPUT_CONNECTORS_INDEX)
|
|
33
32
|
throw exports.ErrInvalidSettlementTxOutputs;
|
|
34
|
-
const expectedRootTxid =
|
|
33
|
+
const expectedRootTxid = settlementTx.id;
|
|
35
34
|
if (!rootInput.txid)
|
|
36
35
|
throw exports.ErrWrongSettlementTxid;
|
|
37
36
|
if (base_1.hex.encode(rootInput.txid) !== expectedRootTxid)
|
|
@@ -58,7 +57,7 @@ function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
|
|
|
58
57
|
throw exports.ErrEmptyTree;
|
|
59
58
|
}
|
|
60
59
|
const rootInput = graph.root.getInput(0);
|
|
61
|
-
const commitmentTxid =
|
|
60
|
+
const commitmentTxid = roundTransaction.id;
|
|
62
61
|
if (!rootInput.txid ||
|
|
63
62
|
base_1.hex.encode(rootInput.txid) !== commitmentTxid ||
|
|
64
63
|
rootInput.index !== BATCH_OUTPUT_VTXO_INDEX) {
|