@arkade-os/sdk 0.4.13 → 0.4.15
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 +209 -143
- package/dist/cjs/contracts/handlers/helpers.js +24 -0
- package/dist/cjs/contracts/handlers/vhtlc.js +2 -4
- package/dist/cjs/identity/index.js +6 -0
- package/dist/cjs/identity/seedIdentity.js +3 -3
- package/dist/cjs/index.js +6 -3
- package/dist/cjs/script/tapscript.js +8 -2
- package/dist/cjs/wallet/serviceWorker/wallet.js +67 -8
- package/dist/cjs/wallet/vtxo-manager.js +1 -0
- package/dist/cjs/wallet/wallet.js +112 -37
- package/dist/esm/contracts/handlers/helpers.js +23 -0
- package/dist/esm/contracts/handlers/vhtlc.js +3 -5
- package/dist/esm/identity/index.js +5 -0
- package/dist/esm/identity/seedIdentity.js +3 -3
- package/dist/esm/index.js +4 -3
- package/dist/esm/script/tapscript.js +8 -2
- package/dist/esm/wallet/serviceWorker/wallet.js +66 -7
- package/dist/esm/wallet/vtxo-manager.js +1 -0
- package/dist/esm/wallet/wallet.js +113 -38
- package/dist/types/contracts/handlers/helpers.d.ts +10 -0
- package/dist/types/identity/index.d.ts +20 -0
- package/dist/types/identity/seedIdentity.d.ts +2 -2
- package/dist/types/index.d.ts +5 -4
- package/dist/types/wallet/serviceWorker/wallet.d.ts +6 -0
- package/package.json +19 -11
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Transaction } from './utils/transaction.js';
|
|
2
2
|
import { SingleKey, ReadonlySingleKey } from './identity/singleKey.js';
|
|
3
3
|
import { SeedIdentity, MnemonicIdentity, ReadonlyDescriptorIdentity, } from './identity/seedIdentity.js';
|
|
4
|
+
import { isBatchSignable, } from './identity/index.js';
|
|
4
5
|
import { ArkAddress } from './script/address.js';
|
|
5
6
|
import { VHTLC } from './script/vhtlc.js';
|
|
6
7
|
import { DefaultVtxo } from './script/default.js';
|
|
@@ -13,7 +14,7 @@ import { Wallet, ReadonlyWallet, waitForIncomingFunds, } from './wallet/wallet.j
|
|
|
13
14
|
import { TxTree } from './tree/txTree.js';
|
|
14
15
|
import { Ramps } from './wallet/ramps.js';
|
|
15
16
|
import { isVtxoExpiringSoon, VtxoManager } from './wallet/vtxo-manager.js';
|
|
16
|
-
import { ServiceWorkerWallet, ServiceWorkerReadonlyWallet, } from './wallet/serviceWorker/wallet.js';
|
|
17
|
+
import { ServiceWorkerWallet, ServiceWorkerReadonlyWallet, DEFAULT_MESSAGE_TIMEOUTS, } from './wallet/serviceWorker/wallet.js';
|
|
17
18
|
import { OnchainWallet } from './wallet/onchain.js';
|
|
18
19
|
import { setupServiceWorker } from './worker/browser/utils.js';
|
|
19
20
|
import { ESPLORA_URL, EsploraProvider, } from './providers/onchain.js';
|
|
@@ -43,7 +44,7 @@ import { WalletMessageHandler, WalletNotInitializedError, ReadonlyWalletError, D
|
|
|
43
44
|
import { MESSAGE_BUS_NOT_INITIALIZED, MessageBusNotInitializedError, ServiceWorkerTimeoutError, } from './worker/errors.js';
|
|
44
45
|
export {
|
|
45
46
|
// Wallets
|
|
46
|
-
Wallet, ReadonlyWallet, SingleKey, ReadonlySingleKey, SeedIdentity, MnemonicIdentity, ReadonlyDescriptorIdentity, OnchainWallet, Ramps, VtxoManager, DelegatorManagerImpl, RestDelegatorProvider,
|
|
47
|
+
Wallet, ReadonlyWallet, SingleKey, ReadonlySingleKey, SeedIdentity, MnemonicIdentity, ReadonlyDescriptorIdentity, isBatchSignable, OnchainWallet, Ramps, VtxoManager, DelegatorManagerImpl, RestDelegatorProvider,
|
|
47
48
|
// Providers
|
|
48
49
|
ESPLORA_URL, EsploraProvider, RestArkProvider, RestIndexerProvider,
|
|
49
50
|
// Script-related
|
|
@@ -51,7 +52,7 @@ ArkAddress, DefaultVtxo, DelegateVtxo, VtxoScript, VHTLC,
|
|
|
51
52
|
// Enums
|
|
52
53
|
TxType, IndexerTxType, ChainTxType, SettlementEventType,
|
|
53
54
|
// Service Worker
|
|
54
|
-
setupServiceWorker, MessageBus, WalletMessageHandler, WalletNotInitializedError, ReadonlyWalletError, DelegatorNotConfiguredError, MESSAGE_BUS_NOT_INITIALIZED, MessageBusNotInitializedError, ServiceWorkerTimeoutError, ServiceWorkerWallet, ServiceWorkerReadonlyWallet,
|
|
55
|
+
setupServiceWorker, MessageBus, WalletMessageHandler, WalletNotInitializedError, ReadonlyWalletError, DelegatorNotConfiguredError, MESSAGE_BUS_NOT_INITIALIZED, MessageBusNotInitializedError, ServiceWorkerTimeoutError, ServiceWorkerWallet, ServiceWorkerReadonlyWallet, DEFAULT_MESSAGE_TIMEOUTS,
|
|
55
56
|
// Tapscript
|
|
56
57
|
decodeTapscript, MultisigTapscript, CSVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CLTVMultisigTapscript, TapTreeCoder,
|
|
57
58
|
// Ark PSBT fields
|
|
@@ -498,7 +498,7 @@ export var CLTVMultisigTapscript;
|
|
|
498
498
|
throw new Error(`Invalid script: too short (expected at least 3)`);
|
|
499
499
|
}
|
|
500
500
|
const locktime = asm[0];
|
|
501
|
-
if (typeof locktime === "string"
|
|
501
|
+
if (typeof locktime === "string") {
|
|
502
502
|
throw new Error("Invalid script: expected locktime number");
|
|
503
503
|
}
|
|
504
504
|
if (asm[1] !== "CHECKLOCKTIMEVERIFY" || asm[2] !== "DROP") {
|
|
@@ -512,7 +512,13 @@ export var CLTVMultisigTapscript;
|
|
|
512
512
|
catch (error) {
|
|
513
513
|
throw new Error(`Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`);
|
|
514
514
|
}
|
|
515
|
-
|
|
515
|
+
let absoluteTimelock;
|
|
516
|
+
if (typeof locktime === "number") {
|
|
517
|
+
absoluteTimelock = BigInt(locktime);
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
absoluteTimelock = MinimalScriptNum.decode(locktime);
|
|
521
|
+
}
|
|
516
522
|
const reconstructed = encode({
|
|
517
523
|
absoluteTimelock,
|
|
518
524
|
...multisig.params,
|
|
@@ -11,6 +11,47 @@ function isMessageBusNotInitializedError(error) {
|
|
|
11
11
|
return (error instanceof Error &&
|
|
12
12
|
error.message.includes(MESSAGE_BUS_NOT_INITIALIZED));
|
|
13
13
|
}
|
|
14
|
+
export const DEFAULT_MESSAGE_TIMEOUTS = {
|
|
15
|
+
// Fast reads — fail quickly
|
|
16
|
+
GET_ADDRESS: 10000,
|
|
17
|
+
GET_BALANCE: 10000,
|
|
18
|
+
GET_BOARDING_ADDRESS: 10000,
|
|
19
|
+
GET_STATUS: 10000,
|
|
20
|
+
GET_DELEGATE_INFO: 10000,
|
|
21
|
+
IS_CONTRACT_MANAGER_WATCHING: 10000,
|
|
22
|
+
// Medium reads — may involve indexer queries
|
|
23
|
+
GET_VTXOS: 20000,
|
|
24
|
+
GET_BOARDING_UTXOS: 20000,
|
|
25
|
+
GET_TRANSACTION_HISTORY: 20000,
|
|
26
|
+
GET_CONTRACTS: 20000,
|
|
27
|
+
GET_CONTRACTS_WITH_VTXOS: 20000,
|
|
28
|
+
GET_SPENDABLE_PATHS: 20000,
|
|
29
|
+
GET_ALL_SPENDING_PATHS: 20000,
|
|
30
|
+
GET_ASSET_DETAILS: 20000,
|
|
31
|
+
GET_EXPIRING_VTXOS: 20000,
|
|
32
|
+
GET_EXPIRED_BOARDING_UTXOS: 20000,
|
|
33
|
+
GET_RECOVERABLE_BALANCE: 20000,
|
|
34
|
+
RELOAD_WALLET: 20000,
|
|
35
|
+
// Transactions — need more headroom
|
|
36
|
+
SEND_BITCOIN: 50000,
|
|
37
|
+
SEND: 50000,
|
|
38
|
+
SETTLE: 50000,
|
|
39
|
+
ISSUE: 50000,
|
|
40
|
+
REISSUE: 50000,
|
|
41
|
+
BURN: 50000,
|
|
42
|
+
DELEGATE: 50000,
|
|
43
|
+
RECOVER_VTXOS: 50000,
|
|
44
|
+
RENEW_VTXOS: 50000,
|
|
45
|
+
SWEEP_EXPIRED_BOARDING_UTXOS: 50000,
|
|
46
|
+
// Misc writes
|
|
47
|
+
INIT_WALLET: 30000,
|
|
48
|
+
CLEAR: 10000,
|
|
49
|
+
SIGN_TRANSACTION: 30000,
|
|
50
|
+
CREATE_CONTRACT: 30000,
|
|
51
|
+
UPDATE_CONTRACT: 30000,
|
|
52
|
+
DELETE_CONTRACT: 10000,
|
|
53
|
+
REFRESH_VTXOS: 30000,
|
|
54
|
+
};
|
|
14
55
|
const DEDUPABLE_REQUEST_TYPES = new Set([
|
|
15
56
|
"GET_ADDRESS",
|
|
16
57
|
"GET_BALANCE",
|
|
@@ -126,6 +167,7 @@ export class ServiceWorkerReadonlyWallet {
|
|
|
126
167
|
this.messageTag = messageTag;
|
|
127
168
|
this.initConfig = null;
|
|
128
169
|
this.initWalletPayload = null;
|
|
170
|
+
this.messageTimeouts = DEFAULT_MESSAGE_TIMEOUTS;
|
|
129
171
|
this.reinitPromise = null;
|
|
130
172
|
this.pingPromise = null;
|
|
131
173
|
this.inflightRequests = new Map();
|
|
@@ -134,6 +176,9 @@ export class ServiceWorkerReadonlyWallet {
|
|
|
134
176
|
this.contractRepository = contractRepository;
|
|
135
177
|
this._readonlyAssetManager = new ServiceWorkerReadonlyAssetManager((msg) => this.sendMessage(msg), messageTag);
|
|
136
178
|
}
|
|
179
|
+
getTimeoutForRequest(request) {
|
|
180
|
+
return this.messageTimeouts[request.type] ?? 30000;
|
|
181
|
+
}
|
|
137
182
|
static async create(options) {
|
|
138
183
|
const walletRepository = options.storage?.walletRepository ??
|
|
139
184
|
new IndexedDBWalletRepository();
|
|
@@ -185,6 +230,12 @@ export class ServiceWorkerReadonlyWallet {
|
|
|
185
230
|
};
|
|
186
231
|
wallet.initWalletPayload = initConfig;
|
|
187
232
|
wallet.messageBusTimeoutMs = options.messageBusTimeoutMs;
|
|
233
|
+
if (options.messageTimeouts) {
|
|
234
|
+
wallet.messageTimeouts = {
|
|
235
|
+
...DEFAULT_MESSAGE_TIMEOUTS,
|
|
236
|
+
...options.messageTimeouts,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
188
239
|
return wallet;
|
|
189
240
|
}
|
|
190
241
|
/**
|
|
@@ -220,7 +271,7 @@ export class ServiceWorkerReadonlyWallet {
|
|
|
220
271
|
serviceWorker,
|
|
221
272
|
});
|
|
222
273
|
}
|
|
223
|
-
sendMessageDirect(request) {
|
|
274
|
+
sendMessageDirect(request, timeoutMs) {
|
|
224
275
|
return new Promise((resolve, reject) => {
|
|
225
276
|
const cleanup = () => {
|
|
226
277
|
clearTimeout(timeoutId);
|
|
@@ -229,7 +280,7 @@ export class ServiceWorkerReadonlyWallet {
|
|
|
229
280
|
const timeoutId = setTimeout(() => {
|
|
230
281
|
cleanup();
|
|
231
282
|
reject(new ServiceWorkerTimeoutError(`Service worker message timed out (${request.type})`));
|
|
232
|
-
},
|
|
283
|
+
}, timeoutMs);
|
|
233
284
|
const messageHandler = (event) => {
|
|
234
285
|
const response = event.data;
|
|
235
286
|
if (request.id !== response.id) {
|
|
@@ -252,14 +303,14 @@ export class ServiceWorkerReadonlyWallet {
|
|
|
252
303
|
// first response for which isComplete returns true. The timeout resets
|
|
253
304
|
// on every intermediate event so long-running but progressing operations
|
|
254
305
|
// don't time out prematurely.
|
|
255
|
-
sendMessageStreaming(request, onEvent, isComplete) {
|
|
306
|
+
sendMessageStreaming(request, onEvent, isComplete, timeoutMs) {
|
|
256
307
|
return new Promise((resolve, reject) => {
|
|
257
308
|
const resetTimeout = () => {
|
|
258
309
|
clearTimeout(timeoutId);
|
|
259
310
|
timeoutId = setTimeout(() => {
|
|
260
311
|
cleanup();
|
|
261
312
|
reject(new ServiceWorkerTimeoutError(`Service worker message timed out (${request.type})`));
|
|
262
|
-
},
|
|
313
|
+
}, timeoutMs);
|
|
263
314
|
};
|
|
264
315
|
const cleanup = () => {
|
|
265
316
|
clearTimeout(timeoutId);
|
|
@@ -345,10 +396,11 @@ export class ServiceWorkerReadonlyWallet {
|
|
|
345
396
|
await this.reinitialize();
|
|
346
397
|
}
|
|
347
398
|
}
|
|
399
|
+
const timeoutMs = this.getTimeoutForRequest(request);
|
|
348
400
|
const maxRetries = 2;
|
|
349
401
|
for (let attempt = 0;; attempt++) {
|
|
350
402
|
try {
|
|
351
|
-
return await this.sendMessageDirect(request);
|
|
403
|
+
return await this.sendMessageDirect(request, timeoutMs);
|
|
352
404
|
}
|
|
353
405
|
catch (error) {
|
|
354
406
|
if (!isMessageBusNotInitializedError(error) ||
|
|
@@ -370,10 +422,11 @@ export class ServiceWorkerReadonlyWallet {
|
|
|
370
422
|
await this.reinitialize();
|
|
371
423
|
}
|
|
372
424
|
}
|
|
425
|
+
const timeoutMs = this.getTimeoutForRequest(request);
|
|
373
426
|
const maxRetries = 2;
|
|
374
427
|
for (let attempt = 0;; attempt++) {
|
|
375
428
|
try {
|
|
376
|
-
return await this.sendMessageStreaming(request, onEvent, isComplete);
|
|
429
|
+
return await this.sendMessageStreaming(request, onEvent, isComplete, timeoutMs);
|
|
377
430
|
}
|
|
378
431
|
catch (error) {
|
|
379
432
|
if (!isMessageBusNotInitializedError(error) ||
|
|
@@ -398,7 +451,7 @@ export class ServiceWorkerReadonlyWallet {
|
|
|
398
451
|
id: getRandomId(),
|
|
399
452
|
payload: this.initWalletPayload,
|
|
400
453
|
};
|
|
401
|
-
await this.sendMessageDirect(initMessage);
|
|
454
|
+
await this.sendMessageDirect(initMessage, this.getTimeoutForRequest(initMessage));
|
|
402
455
|
})().finally(() => {
|
|
403
456
|
this.reinitPromise = null;
|
|
404
457
|
});
|
|
@@ -789,6 +842,12 @@ export class ServiceWorkerWallet extends ServiceWorkerReadonlyWallet {
|
|
|
789
842
|
};
|
|
790
843
|
wallet.initWalletPayload = initConfig;
|
|
791
844
|
wallet.messageBusTimeoutMs = options.messageBusTimeoutMs;
|
|
845
|
+
if (options.messageTimeouts) {
|
|
846
|
+
wallet.messageTimeouts = {
|
|
847
|
+
...DEFAULT_MESSAGE_TIMEOUTS,
|
|
848
|
+
...options.messageTimeouts,
|
|
849
|
+
};
|
|
850
|
+
}
|
|
792
851
|
return wallet;
|
|
793
852
|
}
|
|
794
853
|
/**
|
|
@@ -576,6 +576,7 @@ export class VtxoManager {
|
|
|
576
576
|
return;
|
|
577
577
|
}
|
|
578
578
|
if (e.message.includes("VTXO_ALREADY_REGISTERED") ||
|
|
579
|
+
e.message.includes("VTXO_ALREADY_SPENT") ||
|
|
579
580
|
e.message.includes("duplicated input")) {
|
|
580
581
|
// VTXO is already being used in a concurrent
|
|
581
582
|
// user-initiated operation. Skip silently — the
|
|
@@ -10,11 +10,12 @@ import { RestArkProvider, } from '../providers/ark.js';
|
|
|
10
10
|
import { buildForfeitTx } from '../forfeit.js';
|
|
11
11
|
import { validateConnectorsTxGraph, validateVtxoTxGraph, } from '../tree/validation.js';
|
|
12
12
|
import { validateBatchRecipients } from './validation.js';
|
|
13
|
+
import { isBatchSignable } from '../identity/index.js';
|
|
13
14
|
import { isExpired, isRecoverable, isSpendable, isSubdust, TxType, } from './index.js';
|
|
14
15
|
import { createAssetPacket, selectedCoinsToAssetInputs, selectCoinsWithAsset, } from './asset.js';
|
|
15
16
|
import { VtxoScript } from '../script/base.js';
|
|
16
17
|
import { CSVMultisigTapscript } from '../script/tapscript.js';
|
|
17
|
-
import { buildOffchainTx, hasBoardingTxExpired, isValidArkAddress, } from '../utils/arkTransaction.js';
|
|
18
|
+
import { buildOffchainTx, combineTapscriptSigs, hasBoardingTxExpired, isValidArkAddress, } from '../utils/arkTransaction.js';
|
|
18
19
|
import { DEFAULT_RENEWAL_CONFIG, DEFAULT_SETTLEMENT_CONFIG, VtxoManager, } from './vtxo-manager.js';
|
|
19
20
|
import { ArkNote } from '../arknote/index.js';
|
|
20
21
|
import { Intent } from '../intent/index.js';
|
|
@@ -340,6 +341,19 @@ export class ReadonlyWallet {
|
|
|
340
341
|
}
|
|
341
342
|
const requestStartedAt = Date.now();
|
|
342
343
|
const allVtxos = [];
|
|
344
|
+
const extendWithScript = (vtxo) => {
|
|
345
|
+
const vtxoScript = vtxo.script
|
|
346
|
+
? scriptMap.get(vtxo.script)
|
|
347
|
+
: undefined;
|
|
348
|
+
if (!vtxoScript)
|
|
349
|
+
return undefined;
|
|
350
|
+
return {
|
|
351
|
+
...vtxo,
|
|
352
|
+
forfeitTapLeafScript: vtxoScript.forfeit(),
|
|
353
|
+
intentTapLeafScript: vtxoScript.forfeit(),
|
|
354
|
+
tapTree: vtxoScript.encode(),
|
|
355
|
+
};
|
|
356
|
+
};
|
|
343
357
|
// Full fetch for scripts with no cursor.
|
|
344
358
|
if (bootstrapScripts.length > 0) {
|
|
345
359
|
const response = await this.indexerProvider.getVtxos({
|
|
@@ -364,46 +378,76 @@ export class ReadonlyWallet {
|
|
|
364
378
|
// Extend every fetched VTXO and upsert into the cache.
|
|
365
379
|
const fetchedExtended = [];
|
|
366
380
|
for (const vtxo of allVtxos) {
|
|
367
|
-
const
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
if (!vtxoScript)
|
|
371
|
-
continue;
|
|
372
|
-
fetchedExtended.push({
|
|
373
|
-
...vtxo,
|
|
374
|
-
forfeitTapLeafScript: vtxoScript.forfeit(),
|
|
375
|
-
intentTapLeafScript: vtxoScript.forfeit(),
|
|
376
|
-
tapTree: vtxoScript.encode(),
|
|
377
|
-
});
|
|
381
|
+
const extended = extendWithScript(vtxo);
|
|
382
|
+
if (extended)
|
|
383
|
+
fetchedExtended.push(extended);
|
|
378
384
|
}
|
|
379
385
|
// Save VTXOs first, then advance cursors only on success.
|
|
380
386
|
const cutoff = cursorCutoff(requestStartedAt);
|
|
381
387
|
await this.walletRepository.saveVtxos(address, fetchedExtended);
|
|
382
388
|
await advanceSyncCursors(this.walletRepository, Object.fromEntries(allScripts.map((s) => [s, cutoff])));
|
|
383
|
-
//
|
|
384
|
-
//
|
|
385
|
-
//
|
|
389
|
+
// Delta-sync reconciliation: full re-fetch for delta scripts.
|
|
390
|
+
//
|
|
391
|
+
// The delta fetch (above) only returns VTXOs changed after the
|
|
392
|
+
// cursor, so it can miss preconfirmed VTXOs that were consumed
|
|
393
|
+
// by a round between syncs. Rather than layering targeted
|
|
394
|
+
// queries (pendingOnly, spendableOnly) with pagination guards
|
|
395
|
+
// and set algebra, we perform a single unfiltered re-fetch for
|
|
396
|
+
// delta scripts. This is slightly more data over the wire but
|
|
397
|
+
// gives us complete, authoritative state in one call and keeps
|
|
398
|
+
// the reconciliation logic simple.
|
|
399
|
+
//
|
|
400
|
+
// Any cached non-spent VTXO that is absent from the full
|
|
401
|
+
// result set is marked spent; any VTXO whose state changed
|
|
402
|
+
// (e.g. preconfirmed → settled) is updated in place.
|
|
386
403
|
if (hasDelta) {
|
|
387
|
-
const { vtxos:
|
|
404
|
+
const { vtxos: fullVtxos, page: fullPage } = await this.indexerProvider.getVtxos({
|
|
388
405
|
scripts: deltaScripts,
|
|
389
|
-
pendingOnly: true,
|
|
390
406
|
});
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
407
|
+
// Reconciliation is best-effort: if the response is
|
|
408
|
+
// paginated we don't have a complete picture, so we skip
|
|
409
|
+
// rather than act on partial data. Wallets with enough
|
|
410
|
+
// VTXOs to exceed a single page rely solely on the
|
|
411
|
+
// cursor-based delta mechanism for state updates.
|
|
412
|
+
const fullSetComplete = !fullPage || fullPage.total <= 1;
|
|
413
|
+
if (fullSetComplete) {
|
|
414
|
+
const fullOutpoints = new Map(fullVtxos.map((v) => [`${v.txid}:${v.vout}`, v]));
|
|
415
|
+
const deltaScriptSet = new Set(deltaScripts);
|
|
416
|
+
const cachedVtxos = await this.walletRepository.getVtxos(address);
|
|
417
|
+
const reconciledExtended = [];
|
|
418
|
+
for (const cached of cachedVtxos) {
|
|
419
|
+
if (!cached.script ||
|
|
420
|
+
!deltaScriptSet.has(cached.script) ||
|
|
421
|
+
cached.isSpent) {
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
const outpoint = `${cached.txid}:${cached.vout}`;
|
|
425
|
+
const fresh = fullOutpoints.get(outpoint);
|
|
426
|
+
if (!fresh) {
|
|
427
|
+
// Server no longer knows about this VTXO —
|
|
428
|
+
// it was spent between syncs.
|
|
429
|
+
reconciledExtended.push({
|
|
430
|
+
...cached,
|
|
431
|
+
isSpent: true,
|
|
432
|
+
});
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
const extended = extendWithScript(fresh);
|
|
436
|
+
if (extended &&
|
|
437
|
+
extended.virtualStatus.state !==
|
|
438
|
+
cached.virtualStatus.state) {
|
|
439
|
+
// State transitioned (e.g. preconfirmed →
|
|
440
|
+
// settled) — update the cached entry.
|
|
441
|
+
reconciledExtended.push(extended);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
if (reconciledExtended.length > 0) {
|
|
445
|
+
console.warn(`[ark-sdk] delta sync: reconciled ${reconciledExtended.length} stale VTXO(s) via full re-fetch`);
|
|
446
|
+
await this.walletRepository.saveVtxos(address, reconciledExtended);
|
|
447
|
+
}
|
|
404
448
|
}
|
|
405
|
-
|
|
406
|
-
|
|
449
|
+
else {
|
|
450
|
+
console.warn("[ark-sdk] delta sync: skipping reconciliation — full re-fetch was paginated");
|
|
407
451
|
}
|
|
408
452
|
}
|
|
409
453
|
return {
|
|
@@ -1713,16 +1757,47 @@ export class Wallet extends ReadonlyWallet {
|
|
|
1713
1757
|
tapLeafScript: input.forfeitTapLeafScript,
|
|
1714
1758
|
};
|
|
1715
1759
|
}), outputs, this.serverUnrollScript);
|
|
1716
|
-
|
|
1760
|
+
let signedVirtualTx;
|
|
1761
|
+
let userSignedCheckpoints;
|
|
1762
|
+
if (isBatchSignable(this.identity)) {
|
|
1763
|
+
// Batch-sign arkTx + all checkpoints in one wallet popup.
|
|
1764
|
+
// Clone so the provider can't mutate originals before submitTx.
|
|
1765
|
+
const requests = [
|
|
1766
|
+
{ tx: offchainTx.arkTx.clone() },
|
|
1767
|
+
...offchainTx.checkpoints.map((c) => ({ tx: c.clone() })),
|
|
1768
|
+
];
|
|
1769
|
+
const signed = await this.identity.signMultiple(requests);
|
|
1770
|
+
if (signed.length !== requests.length) {
|
|
1771
|
+
throw new Error(`signMultiple returned ${signed.length} transactions, expected ${requests.length}`);
|
|
1772
|
+
}
|
|
1773
|
+
const [firstSignedTx, ...signedCheckpoints] = signed;
|
|
1774
|
+
signedVirtualTx = firstSignedTx;
|
|
1775
|
+
userSignedCheckpoints = signedCheckpoints;
|
|
1776
|
+
}
|
|
1777
|
+
else {
|
|
1778
|
+
signedVirtualTx = await this.identity.sign(offchainTx.arkTx);
|
|
1779
|
+
}
|
|
1717
1780
|
// Mark pending before submitting — if we crash between submit and
|
|
1718
1781
|
// finalize, the next init will recover via finalizePendingTxs.
|
|
1719
1782
|
await this.setPendingTxFlag(true);
|
|
1720
1783
|
const { arkTxid, signedCheckpointTxs } = await this.arkProvider.submitTx(base64.encode(signedVirtualTx.toPSBT()), offchainTx.checkpoints.map((c) => base64.encode(c.toPSBT())));
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1784
|
+
let finalCheckpoints;
|
|
1785
|
+
if (userSignedCheckpoints) {
|
|
1786
|
+
// Merge pre-signed user signatures onto server-signed checkpoints
|
|
1787
|
+
finalCheckpoints = signedCheckpointTxs.map((c, i) => {
|
|
1788
|
+
const serverSigned = Transaction.fromPSBT(base64.decode(c));
|
|
1789
|
+
combineTapscriptSigs(userSignedCheckpoints[i], serverSigned);
|
|
1790
|
+
return base64.encode(serverSigned.toPSBT());
|
|
1791
|
+
});
|
|
1792
|
+
}
|
|
1793
|
+
else {
|
|
1794
|
+
// Legacy: sign each checkpoint individually (N popups)
|
|
1795
|
+
finalCheckpoints = await Promise.all(signedCheckpointTxs.map(async (c) => {
|
|
1796
|
+
const tx = Transaction.fromPSBT(base64.decode(c));
|
|
1797
|
+
const signedCheckpoint = await this.identity.sign(tx);
|
|
1798
|
+
return base64.encode(signedCheckpoint.toPSBT());
|
|
1799
|
+
}));
|
|
1800
|
+
}
|
|
1726
1801
|
await this.arkProvider.finalizeTx(arkTxid, finalCheckpoints);
|
|
1727
1802
|
try {
|
|
1728
1803
|
await this.setPendingTxFlag(false);
|
|
@@ -12,6 +12,16 @@ export declare function sequenceToTimelock(sequence: number): RelativeTimelock;
|
|
|
12
12
|
* Resolve wallet's role from explicit role or by matching pubkey.
|
|
13
13
|
*/
|
|
14
14
|
export declare function resolveRole(contract: Contract, context: PathContext): "sender" | "receiver" | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Check if an absolute (CLTV) locktime is currently satisfied.
|
|
17
|
+
*
|
|
18
|
+
* Following the BIP65 convention:
|
|
19
|
+
* - locktime < 500_000_000 → interpreted as a block height; compared against `context.blockHeight`
|
|
20
|
+
* - locktime >= 500_000_000 → interpreted as a Unix timestamp (seconds); compared against `context.currentTime`
|
|
21
|
+
*
|
|
22
|
+
* Returns false if the relevant context field is missing.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isCltvSatisfied(context: PathContext, locktime: bigint): boolean;
|
|
15
25
|
/**
|
|
16
26
|
* Check if a CSV timelock is currently satisfied for the given context/VTXO.
|
|
17
27
|
*/
|
|
@@ -9,5 +9,25 @@ export interface ReadonlyIdentity {
|
|
|
9
9
|
xOnlyPublicKey(): Promise<Uint8Array>;
|
|
10
10
|
compressedPublicKey(): Promise<Uint8Array>;
|
|
11
11
|
}
|
|
12
|
+
/** A single PSBT signing request within a batch. */
|
|
13
|
+
export interface SignRequest {
|
|
14
|
+
tx: Transaction;
|
|
15
|
+
inputIndexes?: number[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Identity that supports signing multiple PSBTs in a single wallet interaction.
|
|
19
|
+
* Browser wallet providers that support batch signing (e.g. Xverse, UniSat, OKX)
|
|
20
|
+
* should implement this interface to reduce the number of confirmation popups
|
|
21
|
+
* from N+1 to 1 during Arkade send transactions.
|
|
22
|
+
*
|
|
23
|
+
* Contract: implementations MUST return exactly one `Transaction` per request,
|
|
24
|
+
* in the same order as the input array. The SDK validates this at runtime and
|
|
25
|
+
* will throw if the lengths do not match.
|
|
26
|
+
*/
|
|
27
|
+
export interface BatchSignableIdentity extends Identity {
|
|
28
|
+
signMultiple(requests: SignRequest[]): Promise<Transaction[]>;
|
|
29
|
+
}
|
|
30
|
+
/** Type guard for identities that support batch signing. */
|
|
31
|
+
export declare function isBatchSignable(identity: Identity): identity is BatchSignableIdentity;
|
|
12
32
|
export * from "./singleKey";
|
|
13
33
|
export * from "./seedIdentity";
|
|
@@ -61,7 +61,7 @@ export declare class SeedIdentity implements Identity {
|
|
|
61
61
|
* @param seed - 64-byte seed (typically from mnemonicToSeedSync)
|
|
62
62
|
* @param opts - Network selection or custom descriptor.
|
|
63
63
|
*/
|
|
64
|
-
static fromSeed(seed: Uint8Array, opts
|
|
64
|
+
static fromSeed(seed: Uint8Array, opts?: SeedIdentityOptions): SeedIdentity;
|
|
65
65
|
xOnlyPublicKey(): Promise<Uint8Array>;
|
|
66
66
|
compressedPublicKey(): Promise<Uint8Array>;
|
|
67
67
|
sign(tx: Transaction, inputIndexes?: number[]): Promise<Transaction>;
|
|
@@ -99,7 +99,7 @@ export declare class MnemonicIdentity extends SeedIdentity {
|
|
|
99
99
|
* @param phrase - BIP39 mnemonic phrase (12 or 24 words)
|
|
100
100
|
* @param opts - Network selection or custom descriptor, plus optional passphrase
|
|
101
101
|
*/
|
|
102
|
-
static fromMnemonic(phrase: string, opts
|
|
102
|
+
static fromMnemonic(phrase: string, opts?: MnemonicOptions): MnemonicIdentity;
|
|
103
103
|
}
|
|
104
104
|
/**
|
|
105
105
|
* Watch-only identity from an output descriptor.
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Transaction } from "./utils/transaction";
|
|
|
2
2
|
import { SingleKey, ReadonlySingleKey } from "./identity/singleKey";
|
|
3
3
|
import { SeedIdentity, MnemonicIdentity, ReadonlyDescriptorIdentity } from "./identity/seedIdentity";
|
|
4
4
|
import type { SeedIdentityOptions, MnemonicOptions, NetworkOptions, DescriptorOptions } from "./identity/seedIdentity";
|
|
5
|
-
import { Identity, ReadonlyIdentity } from "./identity";
|
|
5
|
+
import { Identity, ReadonlyIdentity, BatchSignableIdentity, SignRequest, isBatchSignable } from "./identity";
|
|
6
6
|
import { ArkAddress } from "./script/address";
|
|
7
7
|
import { VHTLC } from "./script/vhtlc";
|
|
8
8
|
import { DefaultVtxo } from "./script/default";
|
|
@@ -17,7 +17,8 @@ import { SignerSession, TreeNonces, TreePartialSigs } from "./tree/signingSessio
|
|
|
17
17
|
import { Ramps } from "./wallet/ramps";
|
|
18
18
|
import { isVtxoExpiringSoon, VtxoManager } from "./wallet/vtxo-manager";
|
|
19
19
|
import type { IVtxoManager, SettlementConfig } from "./wallet/vtxo-manager";
|
|
20
|
-
import { ServiceWorkerWallet, ServiceWorkerReadonlyWallet } from "./wallet/serviceWorker/wallet";
|
|
20
|
+
import { ServiceWorkerWallet, ServiceWorkerReadonlyWallet, DEFAULT_MESSAGE_TIMEOUTS } from "./wallet/serviceWorker/wallet";
|
|
21
|
+
import type { MessageTimeouts } from "./wallet/serviceWorker/wallet";
|
|
21
22
|
import { OnchainWallet } from "./wallet/onchain";
|
|
22
23
|
import { setupServiceWorker } from "./worker/browser/utils";
|
|
23
24
|
import { ESPLORA_URL, EsploraProvider, OnchainProvider, ExplorerTransaction } from "./providers/onchain";
|
|
@@ -49,5 +50,5 @@ import { IContractManager } from "./contracts/contractManager";
|
|
|
49
50
|
import { closeDatabase, openDatabase } from "./repositories/indexedDB/manager";
|
|
50
51
|
import { WalletMessageHandler, WalletNotInitializedError, ReadonlyWalletError, DelegatorNotConfiguredError } from "./wallet/serviceWorker/wallet-message-handler";
|
|
51
52
|
import { MESSAGE_BUS_NOT_INITIALIZED, MessageBusNotInitializedError, ServiceWorkerTimeoutError } from "./worker/errors";
|
|
52
|
-
export { Wallet, ReadonlyWallet, SingleKey, ReadonlySingleKey, SeedIdentity, MnemonicIdentity, ReadonlyDescriptorIdentity, OnchainWallet, Ramps, VtxoManager, DelegatorManagerImpl, RestDelegatorProvider, ESPLORA_URL, EsploraProvider, RestArkProvider, RestIndexerProvider, ArkAddress, DefaultVtxo, DelegateVtxo, VtxoScript, VHTLC, TxType, IndexerTxType, ChainTxType, SettlementEventType, setupServiceWorker, MessageBus, WalletMessageHandler, WalletNotInitializedError, ReadonlyWalletError, DelegatorNotConfiguredError, MESSAGE_BUS_NOT_INITIALIZED, MessageBusNotInitializedError, ServiceWorkerTimeoutError, ServiceWorkerWallet, ServiceWorkerReadonlyWallet, decodeTapscript, MultisigTapscript, CSVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CLTVMultisigTapscript, TapTreeCoder, ArkPsbtFieldKey, ArkPsbtFieldKeyType, setArkPsbtField, getArkPsbtFields, CosignerPublicKey, VtxoTreeExpiry, VtxoTaprootTree, ConditionWitness, buildOffchainTx, verifyTapscriptSignatures, waitForIncomingFunds, hasBoardingTxExpired, combineTapscriptSigs, isVtxoExpiringSoon, isValidArkAddress, ArkNote, networks, closeDatabase, openDatabase, IndexedDBWalletRepository, IndexedDBContractRepository, InMemoryWalletRepository, InMemoryContractRepository, MIGRATION_KEY, migrateWalletRepository, requiresMigration, getMigrationStatus, rollbackMigration, WalletRepositoryImpl, ContractRepositoryImpl, Intent, BIP322, TxTree, P2A, Unroll, Transaction, ArkError, maybeArkError, Batch, validateVtxoTxGraph, validateConnectorsTxGraph, buildForfeitTx, isRecoverable, isSpendable, isSubdust, isExpired, getSequence, ContractManager, ContractWatcher, contractHandlers, DefaultContractHandler, DelegateContractHandler, VHTLCContractHandler, encodeArkContract, decodeArkContract, contractFromArkContract, contractFromArkContractWithAddress, isArkContract, };
|
|
53
|
-
export type { Identity, ReadonlyIdentity, IWallet, IReadonlyWallet, BaseWalletConfig, WalletConfig, ReadonlyWalletConfig, ProviderClass, ArkTransaction, Coin, ExtendedCoin, ExtendedVirtualCoin, WalletBalance, SendBitcoinParams, SettleParams, Status, VirtualStatus, Outpoint, VirtualCoin, TxKey, TapscriptType, ArkTxInput, OffchainTx, TapLeaves, IncomingFunds, SeedIdentityOptions, MnemonicOptions, NetworkOptions, DescriptorOptions, IndexerProvider, PageResponse, BatchInfo, ChainTx, CommitmentTx, TxHistoryRecord, Vtxo, VtxoChain, Tx, OnchainProvider, ArkProvider, SettlementEvent, FeeInfo, ArkInfo, SignedIntent, Output, TxNotification, ExplorerTransaction, BatchFinalizationEvent, BatchFinalizedEvent, BatchFailedEvent, TreeSigningStartedEvent, TreeNoncesEvent, BatchStartedEvent, TreeTxEvent, TreeSignatureEvent, ScheduledSession, PaginationOptions, SubscriptionResponse, SubscriptionHeartbeat, SubscriptionEvent, Network, NetworkName, ArkTapscript, RelativeTimelock, EncodedVtxoScript, TapLeafScript, SignerSession, TreeNonces, TreePartialSigs, GetVtxosFilter, SettlementConfig, IVtxoManager, Asset, Recipient, IssuanceParams, IssuanceResult, ReissuanceParams, BurnParams, AssetDetails, AssetMetadata, KnownMetadata, Nonces, PartialSig, ArkPsbtFieldCoder, TxTreeNode, AnchorBumper, StorageConfig, Contract, ContractVtxo, ContractState, ContractEvent, ContractEventCallback, ContractBalance, ContractWithVtxos, ContractHandler, IContractManager, PathSelection, PathContext, ContractManagerConfig, CreateContractParams, ContractWatcherConfig, ParsedArkContract, DefaultContractParams, DelegateContractParams, VHTLCContractParams, MessageHandler, RequestEnvelope, ResponseEnvelope, IDelegatorManager, DelegatorProvider, DelegateInfo, DelegateOptions, WalletRepository, ContractRepository, MigrationStatus, };
|
|
53
|
+
export { Wallet, ReadonlyWallet, SingleKey, ReadonlySingleKey, SeedIdentity, MnemonicIdentity, ReadonlyDescriptorIdentity, isBatchSignable, OnchainWallet, Ramps, VtxoManager, DelegatorManagerImpl, RestDelegatorProvider, ESPLORA_URL, EsploraProvider, RestArkProvider, RestIndexerProvider, ArkAddress, DefaultVtxo, DelegateVtxo, VtxoScript, VHTLC, TxType, IndexerTxType, ChainTxType, SettlementEventType, setupServiceWorker, MessageBus, WalletMessageHandler, WalletNotInitializedError, ReadonlyWalletError, DelegatorNotConfiguredError, MESSAGE_BUS_NOT_INITIALIZED, MessageBusNotInitializedError, ServiceWorkerTimeoutError, ServiceWorkerWallet, ServiceWorkerReadonlyWallet, DEFAULT_MESSAGE_TIMEOUTS, decodeTapscript, MultisigTapscript, CSVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CLTVMultisigTapscript, TapTreeCoder, ArkPsbtFieldKey, ArkPsbtFieldKeyType, setArkPsbtField, getArkPsbtFields, CosignerPublicKey, VtxoTreeExpiry, VtxoTaprootTree, ConditionWitness, buildOffchainTx, verifyTapscriptSignatures, waitForIncomingFunds, hasBoardingTxExpired, combineTapscriptSigs, isVtxoExpiringSoon, isValidArkAddress, ArkNote, networks, closeDatabase, openDatabase, IndexedDBWalletRepository, IndexedDBContractRepository, InMemoryWalletRepository, InMemoryContractRepository, MIGRATION_KEY, migrateWalletRepository, requiresMigration, getMigrationStatus, rollbackMigration, WalletRepositoryImpl, ContractRepositoryImpl, Intent, BIP322, TxTree, P2A, Unroll, Transaction, ArkError, maybeArkError, Batch, validateVtxoTxGraph, validateConnectorsTxGraph, buildForfeitTx, isRecoverable, isSpendable, isSubdust, isExpired, getSequence, ContractManager, ContractWatcher, contractHandlers, DefaultContractHandler, DelegateContractHandler, VHTLCContractHandler, encodeArkContract, decodeArkContract, contractFromArkContract, contractFromArkContractWithAddress, isArkContract, };
|
|
54
|
+
export type { Identity, ReadonlyIdentity, BatchSignableIdentity, SignRequest, IWallet, IReadonlyWallet, BaseWalletConfig, WalletConfig, ReadonlyWalletConfig, ProviderClass, ArkTransaction, Coin, ExtendedCoin, ExtendedVirtualCoin, WalletBalance, SendBitcoinParams, SettleParams, Status, VirtualStatus, Outpoint, VirtualCoin, TxKey, TapscriptType, ArkTxInput, OffchainTx, TapLeaves, IncomingFunds, SeedIdentityOptions, MnemonicOptions, NetworkOptions, DescriptorOptions, IndexerProvider, PageResponse, BatchInfo, ChainTx, CommitmentTx, TxHistoryRecord, Vtxo, VtxoChain, Tx, OnchainProvider, ArkProvider, SettlementEvent, FeeInfo, ArkInfo, SignedIntent, Output, TxNotification, ExplorerTransaction, BatchFinalizationEvent, BatchFinalizedEvent, BatchFailedEvent, TreeSigningStartedEvent, TreeNoncesEvent, BatchStartedEvent, TreeTxEvent, TreeSignatureEvent, ScheduledSession, PaginationOptions, SubscriptionResponse, SubscriptionHeartbeat, SubscriptionEvent, Network, NetworkName, ArkTapscript, RelativeTimelock, EncodedVtxoScript, TapLeafScript, SignerSession, TreeNonces, TreePartialSigs, GetVtxosFilter, SettlementConfig, IVtxoManager, Asset, Recipient, IssuanceParams, IssuanceResult, ReissuanceParams, BurnParams, AssetDetails, AssetMetadata, KnownMetadata, Nonces, PartialSig, ArkPsbtFieldCoder, TxTreeNode, AnchorBumper, StorageConfig, Contract, ContractVtxo, ContractState, ContractEvent, ContractEventCallback, ContractBalance, ContractWithVtxos, ContractHandler, IContractManager, PathSelection, PathContext, ContractManagerConfig, CreateContractParams, ContractWatcherConfig, ParsedArkContract, DefaultContractParams, DelegateContractParams, VHTLCContractParams, MessageHandler, RequestEnvelope, ResponseEnvelope, MessageTimeouts, IDelegatorManager, DelegatorProvider, DelegateInfo, DelegateOptions, WalletRepository, ContractRepository, MigrationStatus, };
|
|
@@ -8,6 +8,9 @@ import type { IContractManager } from "../../contracts/contractManager";
|
|
|
8
8
|
import type { IDelegatorManager } from "../delegator";
|
|
9
9
|
import type { IVtxoManager, SettlementConfig } from "../vtxo-manager";
|
|
10
10
|
import type { ContractWatcherConfig } from "../../contracts/contractWatcher";
|
|
11
|
+
type RequestType = WalletUpdaterRequest["type"];
|
|
12
|
+
export type MessageTimeouts = Partial<Record<RequestType, number>>;
|
|
13
|
+
export declare const DEFAULT_MESSAGE_TIMEOUTS: Readonly<Record<RequestType, number>>;
|
|
11
14
|
type PrivateKeyIdentity = Identity & {
|
|
12
15
|
toHex(): string;
|
|
13
16
|
};
|
|
@@ -55,6 +58,7 @@ interface ServiceWorkerWalletOptions {
|
|
|
55
58
|
messageBusTimeoutMs?: number;
|
|
56
59
|
settlementConfig?: SettlementConfig | false;
|
|
57
60
|
watcherConfig?: Partial<Omit<ContractWatcherConfig, "indexerProvider">>;
|
|
61
|
+
messageTimeouts?: MessageTimeouts;
|
|
58
62
|
}
|
|
59
63
|
export type ServiceWorkerWalletCreateOptions = ServiceWorkerWalletOptions & {
|
|
60
64
|
serviceWorker: ServiceWorker;
|
|
@@ -90,11 +94,13 @@ export declare class ServiceWorkerReadonlyWallet implements IReadonlyWallet {
|
|
|
90
94
|
protected initConfig: MessageBusInitConfig | null;
|
|
91
95
|
protected initWalletPayload: RequestInitWallet["payload"] | null;
|
|
92
96
|
protected messageBusTimeoutMs?: number;
|
|
97
|
+
protected messageTimeouts: Record<RequestType, number>;
|
|
93
98
|
private reinitPromise;
|
|
94
99
|
private pingPromise;
|
|
95
100
|
private inflightRequests;
|
|
96
101
|
get assetManager(): IReadonlyAssetManager;
|
|
97
102
|
protected constructor(serviceWorker: ServiceWorker, identity: ReadonlyIdentity, walletRepository: WalletRepository, contractRepository: ContractRepository, messageTag: string);
|
|
103
|
+
private getTimeoutForRequest;
|
|
98
104
|
static create(options: ServiceWorkerWalletCreateOptions): Promise<ServiceWorkerReadonlyWallet>;
|
|
99
105
|
/**
|
|
100
106
|
* Simplified setup method that handles service worker registration,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arkade-os/sdk",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.4.15",
|
|
4
|
+
"description": "TypeScript SDK for building Bitcoin wallets using the Arkade protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
7
7
|
"module": "./dist/esm/index.js",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"registry": "https://registry.npmjs.org/"
|
|
81
81
|
},
|
|
82
82
|
"dependencies": {
|
|
83
|
-
"@bitcoinerlab/descriptors-scure": "3.1.
|
|
83
|
+
"@bitcoinerlab/descriptors-scure": "3.1.7",
|
|
84
84
|
"@marcbachmann/cel-js": "7.3.1",
|
|
85
85
|
"@noble/curves": "2.0.1",
|
|
86
86
|
"@noble/secp256k1": "3.0.0",
|
|
@@ -130,12 +130,20 @@
|
|
|
130
130
|
}
|
|
131
131
|
},
|
|
132
132
|
"keywords": [
|
|
133
|
-
"bitcoin",
|
|
134
|
-
"wallet",
|
|
135
|
-
"taproot",
|
|
136
133
|
"ark",
|
|
134
|
+
"arkade",
|
|
135
|
+
"bip39",
|
|
136
|
+
"bitcoin",
|
|
137
|
+
"btc",
|
|
138
|
+
"crypto",
|
|
139
|
+
"lightning",
|
|
137
140
|
"sdk",
|
|
138
|
-
"
|
|
141
|
+
"stablecoin",
|
|
142
|
+
"taproot",
|
|
143
|
+
"typescript",
|
|
144
|
+
"utxo",
|
|
145
|
+
"vtxo",
|
|
146
|
+
"wallet"
|
|
139
147
|
],
|
|
140
148
|
"author": "Ark Labs",
|
|
141
149
|
"license": "MIT",
|
|
@@ -159,11 +167,11 @@
|
|
|
159
167
|
"test:master": "ARK_ENV=master vitest run",
|
|
160
168
|
"test:unit": "vitest run --exclude test/e2e",
|
|
161
169
|
"test:setup": "node test/setup.mjs",
|
|
162
|
-
"regtest": "
|
|
170
|
+
"regtest:start": "./regtest/start-env.sh",
|
|
171
|
+
"regtest:stop": "./regtest/stop-env.sh",
|
|
172
|
+
"regtest:clean": "./regtest/clean-env.sh",
|
|
173
|
+
"regtest": "pnpm regtest:clean && pnpm regtest:start && pnpm test:setup-docker",
|
|
163
174
|
"test:setup-docker": "node test/setup.mjs docker",
|
|
164
|
-
"test:build-docker": "docker compose -f docker-compose.yml build --no-cache",
|
|
165
|
-
"test:up-docker": "docker compose -f docker-compose.yml up -d",
|
|
166
|
-
"test:down-docker": "docker compose -f docker-compose.yml down",
|
|
167
175
|
"test:integration": "vitest run test/e2e/**",
|
|
168
176
|
"test:integration-docker": "ARK_ENV=docker vitest run test/e2e/**",
|
|
169
177
|
"test:watch": "vitest",
|