@arkade-os/sdk 0.4.20 → 0.4.22
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/contracts/contractWatcher.js +42 -20
- package/dist/cjs/providers/ark.js +65 -48
- package/dist/cjs/providers/indexer.js +60 -47
- package/dist/cjs/providers/utils.js +58 -12
- package/dist/cjs/wallet/delegator.js +27 -18
- package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +3 -1
- package/dist/cjs/wallet/vtxo-manager.js +7 -5
- package/dist/cjs/wallet/wallet.js +127 -153
- package/dist/esm/contracts/contractWatcher.js +40 -18
- package/dist/esm/providers/ark.js +65 -48
- package/dist/esm/providers/indexer.js +60 -47
- package/dist/esm/providers/utils.js +58 -12
- package/dist/esm/wallet/delegator.js +27 -18
- package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +3 -1
- package/dist/esm/wallet/vtxo-manager.js +7 -5
- package/dist/esm/wallet/wallet.js +127 -153
- package/dist/types/contracts/contractWatcher.d.ts +3 -0
- package/dist/types/contracts/types.d.ts +5 -5
- package/dist/types/providers/utils.d.ts +9 -5
- package/dist/types/wallet/delegator.d.ts +8 -3
- package/dist/types/wallet/wallet.d.ts +7 -6
- package/package.json +4 -4
|
@@ -34,10 +34,28 @@ import { ContractManager } from '../contracts/contractManager.js';
|
|
|
34
34
|
import { contractHandlers } from '../contracts/handlers/index.js';
|
|
35
35
|
import { timelockToSequence } from '../contracts/handlers/helpers.js';
|
|
36
36
|
import { clearSyncCursor, updateWalletState } from '../utils/syncCursors.js';
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
37
|
+
// Historical unilateral exit delay for mainnet (~7 days in seconds).
|
|
38
|
+
// Kept so existing wallets can still discover and spend VTXOs sent to the
|
|
39
|
+
// legacy address after arkd starts advertising a different delay.
|
|
40
40
|
const MAINNET_UNILATERAL_EXIT_DELAY = 605184n;
|
|
41
|
+
function delayToTimelock(delay) {
|
|
42
|
+
return {
|
|
43
|
+
value: delay,
|
|
44
|
+
type: delay < 512n ? "blocks" : "seconds",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function dedupeTimelocks(timelocks) {
|
|
48
|
+
const seen = new Set();
|
|
49
|
+
const deduped = [];
|
|
50
|
+
for (const timelock of timelocks) {
|
|
51
|
+
const sequence = timelockToSequence(timelock).toString();
|
|
52
|
+
if (seen.has(sequence))
|
|
53
|
+
continue;
|
|
54
|
+
seen.add(sequence);
|
|
55
|
+
deduped.push(timelock);
|
|
56
|
+
}
|
|
57
|
+
return deduped;
|
|
58
|
+
}
|
|
41
59
|
/**
|
|
42
60
|
* Type guard function to check if an identity has a toReadonly method.
|
|
43
61
|
*/
|
|
@@ -51,7 +69,7 @@ export class ReadonlyWallet {
|
|
|
51
69
|
get assetManager() {
|
|
52
70
|
return this._assetManager;
|
|
53
71
|
}
|
|
54
|
-
constructor(identity, network, onchainProvider, indexerProvider, arkServerPublicKey, offchainTapscript, boardingTapscript, dustAmount, walletRepository, contractRepository, delegatorProvider, watcherConfig) {
|
|
72
|
+
constructor(identity, network, onchainProvider, indexerProvider, arkServerPublicKey, offchainTapscript, boardingTapscript, dustAmount, walletRepository, contractRepository, delegatorProvider, watcherConfig, walletContractTimelocks) {
|
|
55
73
|
this.identity = identity;
|
|
56
74
|
this.network = network;
|
|
57
75
|
this.onchainProvider = onchainProvider;
|
|
@@ -84,6 +102,15 @@ export class ReadonlyWallet {
|
|
|
84
102
|
}
|
|
85
103
|
this.watcherConfig = watcherConfig;
|
|
86
104
|
this._assetManager = new ReadonlyAssetManager(this.indexerProvider);
|
|
105
|
+
// Defensive for direct-construction callers; setupWalletConfig already
|
|
106
|
+
// passes a deduped list through the public create() factories.
|
|
107
|
+
this.walletContractTimelocks =
|
|
108
|
+
walletContractTimelocks && walletContractTimelocks.length > 0
|
|
109
|
+
? dedupeTimelocks(walletContractTimelocks)
|
|
110
|
+
: [
|
|
111
|
+
this.offchainTapscript.options.csvTimelock ??
|
|
112
|
+
DefaultVtxo.Script.DEFAULT_TIMELOCK,
|
|
113
|
+
];
|
|
87
114
|
}
|
|
88
115
|
/**
|
|
89
116
|
* Protected helper to set up shared wallet configuration.
|
|
@@ -139,17 +166,17 @@ export class ReadonlyWallet {
|
|
|
139
166
|
throw new Error("invalid exitTimelock");
|
|
140
167
|
}
|
|
141
168
|
}
|
|
142
|
-
|
|
143
|
-
// that addresses derived by existing wallets remain stable even if the
|
|
144
|
-
// server starts advertising a shorter delay.
|
|
145
|
-
const unilateralExitDelay = info.network === "bitcoin"
|
|
146
|
-
? MAINNET_UNILATERAL_EXIT_DELAY
|
|
147
|
-
: info.unilateralExitDelay;
|
|
169
|
+
const arkdExitTimelock = delayToTimelock(info.unilateralExitDelay);
|
|
148
170
|
// create unilateral exit timelock
|
|
149
|
-
const exitTimelock = config.exitTimelock ??
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
171
|
+
const exitTimelock = config.exitTimelock ?? arkdExitTimelock;
|
|
172
|
+
const walletContractTimelocks = config.exitTimelock
|
|
173
|
+
? [exitTimelock]
|
|
174
|
+
: dedupeTimelocks([
|
|
175
|
+
arkdExitTimelock,
|
|
176
|
+
...(info.network === "bitcoin"
|
|
177
|
+
? [delayToTimelock(MAINNET_UNILATERAL_EXIT_DELAY)]
|
|
178
|
+
: []),
|
|
179
|
+
]);
|
|
153
180
|
// validate boarding timelock passed in config if any
|
|
154
181
|
if (config.boardingTimelock) {
|
|
155
182
|
const { value, type } = config.boardingTimelock;
|
|
@@ -199,6 +226,7 @@ export class ReadonlyWallet {
|
|
|
199
226
|
contractRepository,
|
|
200
227
|
info,
|
|
201
228
|
delegatorProvider: config.delegatorProvider,
|
|
229
|
+
walletContractTimelocks,
|
|
202
230
|
};
|
|
203
231
|
}
|
|
204
232
|
/**
|
|
@@ -213,14 +241,14 @@ export class ReadonlyWallet {
|
|
|
213
241
|
throw new Error("Invalid configured public key");
|
|
214
242
|
}
|
|
215
243
|
const setup = await ReadonlyWallet.setupWalletConfig(config, pubkey);
|
|
216
|
-
return new ReadonlyWallet(config.identity, setup.network, setup.onchainProvider, setup.indexerProvider, setup.serverPubKey, setup.offchainTapscript, setup.boardingTapscript, setup.dustAmount, setup.walletRepository, setup.contractRepository, setup.delegatorProvider, config.watcherConfig);
|
|
244
|
+
return new ReadonlyWallet(config.identity, setup.network, setup.onchainProvider, setup.indexerProvider, setup.serverPubKey, setup.offchainTapscript, setup.boardingTapscript, setup.dustAmount, setup.walletRepository, setup.contractRepository, setup.delegatorProvider, config.watcherConfig, setup.walletContractTimelocks);
|
|
217
245
|
}
|
|
218
246
|
get arkAddress() {
|
|
219
247
|
return this.offchainTapscript.address(this.network.hrp, this.arkServerPublicKey);
|
|
220
248
|
}
|
|
221
249
|
/**
|
|
222
|
-
* Get the
|
|
223
|
-
*
|
|
250
|
+
* Get the pkScript hex for the wallet's primary offchain address.
|
|
251
|
+
* For the full wallet-owned script set registered in ContractManager, use getWalletScripts().
|
|
224
252
|
*/
|
|
225
253
|
get defaultContractScript() {
|
|
226
254
|
return hex.encode(this.offchainTapscript.pkScript);
|
|
@@ -464,56 +492,39 @@ export class ReadonlyWallet {
|
|
|
464
492
|
});
|
|
465
493
|
}
|
|
466
494
|
if (this.indexerProvider && arkAddress) {
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
// resolves to the owning contract so the extension uses the
|
|
480
|
-
// correct forfeit/intent tapscripts.
|
|
481
|
-
(async () => {
|
|
482
|
-
try {
|
|
483
|
-
const cm = await this.getContractManager();
|
|
484
|
-
for await (const update of subscription) {
|
|
485
|
-
if (update.newVtxos?.length === 0 &&
|
|
486
|
-
update.spentVtxos?.length === 0) {
|
|
487
|
-
continue;
|
|
488
|
-
}
|
|
489
|
-
// Isolate per-update annotation failures (e.g. a VTXO
|
|
490
|
-
// arriving for a contract we haven't registered yet).
|
|
491
|
-
// Without this a single bad update would kill the
|
|
492
|
-
// for-await loop and silently drop every subsequent
|
|
493
|
-
// subscription event for the session.
|
|
494
|
-
try {
|
|
495
|
-
// Default to `[]` so a one-sided update (e.g.
|
|
496
|
-
// only `newVtxos`) doesn't pass `undefined` into
|
|
497
|
-
// annotateVtxos and throw on `.length`.
|
|
498
|
-
const [newVtxos, spentVtxos] = await Promise.all([
|
|
499
|
-
cm.annotateVtxos(update.newVtxos ?? []),
|
|
500
|
-
cm.annotateVtxos(update.spentVtxos ?? []),
|
|
501
|
-
]);
|
|
502
|
-
eventCallback({
|
|
503
|
-
type: "vtxo",
|
|
504
|
-
newVtxos,
|
|
505
|
-
spentVtxos,
|
|
506
|
-
});
|
|
507
|
-
}
|
|
508
|
-
catch (error) {
|
|
509
|
-
console.warn("Dropping subscription update after annotation failed; next sync will reconcile:", error);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
495
|
+
// Share the ContractWatcher's single subscription instead of
|
|
496
|
+
// opening a second SSE stream.
|
|
497
|
+
const cm = await this.getContractManager();
|
|
498
|
+
// Serialize annotation+notification: parallel `annotateVtxos`
|
|
499
|
+
// awaits could resolve out of order and deliver eventCallback
|
|
500
|
+
// calls in the wrong sequence (e.g. `vtxo_spent` before its
|
|
501
|
+
// matching `vtxo_received`).
|
|
502
|
+
let annotationQueue = Promise.resolve();
|
|
503
|
+
indexerStopFunc = cm.onContractEvent((event) => {
|
|
504
|
+
if (event.type !== "vtxo_received" &&
|
|
505
|
+
event.type !== "vtxo_spent") {
|
|
506
|
+
return;
|
|
512
507
|
}
|
|
513
|
-
|
|
514
|
-
|
|
508
|
+
if (event.contract.type !== "default" &&
|
|
509
|
+
event.contract.type !== "delegate") {
|
|
510
|
+
return;
|
|
515
511
|
}
|
|
516
|
-
|
|
512
|
+
// `event.vtxos` carries placeholder tapscript fields from
|
|
513
|
+
// the watcher; `annotateVtxos` fills them in.
|
|
514
|
+
annotationQueue = annotationQueue.then(async () => {
|
|
515
|
+
try {
|
|
516
|
+
const annotated = await cm.annotateVtxos(event.vtxos);
|
|
517
|
+
eventCallback({
|
|
518
|
+
type: "vtxo",
|
|
519
|
+
newVtxos: event.type === "vtxo_received" ? annotated : [],
|
|
520
|
+
spentVtxos: event.type === "vtxo_spent" ? annotated : [],
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
catch (error) {
|
|
524
|
+
console.warn("Dropping subscription update after annotation failed; next sync will reconcile:", error);
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
});
|
|
517
528
|
}
|
|
518
529
|
const stopFunc = () => {
|
|
519
530
|
onchainStopFunc?.();
|
|
@@ -540,27 +551,13 @@ export class ReadonlyWallet {
|
|
|
540
551
|
/**
|
|
541
552
|
* Get all pkScript hex strings for the wallet's own addresses
|
|
542
553
|
* (both delegate and non-delegate, current and historical).
|
|
543
|
-
* Falls back to only the current script if ContractManager is not yet initialized.
|
|
544
554
|
*/
|
|
545
555
|
async getWalletScripts() {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
const manager = await this.getContractManager();
|
|
552
|
-
const contracts = await manager.getContracts({
|
|
553
|
-
type: ["default", "delegate"],
|
|
554
|
-
});
|
|
555
|
-
if (contracts.length > 0) {
|
|
556
|
-
return contracts.map((c) => c.script);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
catch {
|
|
560
|
-
// fall through to current script only
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
return [hex.encode(this.offchainTapscript.pkScript)];
|
|
556
|
+
const manager = await this.getContractManager();
|
|
557
|
+
const contracts = await manager.getContracts({
|
|
558
|
+
type: ["default", "delegate"],
|
|
559
|
+
});
|
|
560
|
+
return contracts.map((c) => c.script);
|
|
564
561
|
}
|
|
565
562
|
/**
|
|
566
563
|
* Build a map of scriptHex → VtxoScript for all wallet contracts,
|
|
@@ -568,26 +565,17 @@ export class ReadonlyWallet {
|
|
|
568
565
|
*/
|
|
569
566
|
async getScriptMap() {
|
|
570
567
|
const map = new Map();
|
|
571
|
-
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
const handler = contractHandlers.get(contract.type);
|
|
583
|
-
if (handler) {
|
|
584
|
-
const script = handler.createScript(contract.params);
|
|
585
|
-
map.set(contract.script, script);
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
catch {
|
|
590
|
-
// ContractManager error — only current script in map
|
|
568
|
+
const manager = await this.getContractManager();
|
|
569
|
+
const contracts = await manager.getContracts({
|
|
570
|
+
type: ["default", "delegate"],
|
|
571
|
+
});
|
|
572
|
+
for (const contract of contracts) {
|
|
573
|
+
if (map.has(contract.script))
|
|
574
|
+
continue;
|
|
575
|
+
const handler = contractHandlers.get(contract.type);
|
|
576
|
+
if (handler) {
|
|
577
|
+
const script = handler.createScript(contract.params);
|
|
578
|
+
map.set(contract.script, script);
|
|
591
579
|
}
|
|
592
580
|
}
|
|
593
581
|
return map;
|
|
@@ -655,62 +643,48 @@ export class ReadonlyWallet {
|
|
|
655
643
|
walletRepository: this.walletRepository,
|
|
656
644
|
watcherConfig: this.watcherConfig,
|
|
657
645
|
});
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
DefaultVtxo.Script
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
if (isDelegateScript) {
|
|
664
|
-
const delegateScript = this
|
|
665
|
-
.offchainTapscript;
|
|
666
|
-
// Register the delegate contract (current address)
|
|
667
|
-
await manager.createContract({
|
|
668
|
-
type: "delegate",
|
|
669
|
-
params: {
|
|
670
|
-
pubKey: hex.encode(delegateScript.options.pubKey),
|
|
671
|
-
serverPubKey: hex.encode(delegateScript.options.serverPubKey),
|
|
672
|
-
delegatePubKey: hex.encode(delegateScript.options.delegatePubKey),
|
|
673
|
-
csvTimelock: csvTimelockStr,
|
|
674
|
-
},
|
|
675
|
-
script: this.defaultContractScript,
|
|
676
|
-
address: await this.getAddress(),
|
|
677
|
-
state: "active",
|
|
678
|
-
});
|
|
679
|
-
// Also register the non-delegate version so old virtual outputs remain visible
|
|
680
|
-
const nonDelegateScript = new DefaultVtxo.Script({
|
|
681
|
-
pubKey: delegateScript.options.pubKey,
|
|
682
|
-
serverPubKey: delegateScript.options.serverPubKey,
|
|
646
|
+
for (const csvTimelock of this.walletContractTimelocks) {
|
|
647
|
+
const csvTimelockStr = timelockToSequence(csvTimelock).toString();
|
|
648
|
+
const defaultScript = new DefaultVtxo.Script({
|
|
649
|
+
pubKey: this.offchainTapscript.options.pubKey,
|
|
650
|
+
serverPubKey: this.offchainTapscript.options.serverPubKey,
|
|
683
651
|
csvTimelock,
|
|
684
652
|
});
|
|
685
653
|
await manager.createContract({
|
|
686
654
|
type: "default",
|
|
687
655
|
params: {
|
|
688
|
-
pubKey: hex.encode(
|
|
689
|
-
serverPubKey: hex.encode(
|
|
656
|
+
pubKey: hex.encode(defaultScript.options.pubKey),
|
|
657
|
+
serverPubKey: hex.encode(defaultScript.options.serverPubKey),
|
|
690
658
|
csvTimelock: csvTimelockStr,
|
|
691
659
|
},
|
|
692
|
-
script: hex.encode(
|
|
693
|
-
address:
|
|
660
|
+
script: hex.encode(defaultScript.pkScript),
|
|
661
|
+
address: defaultScript
|
|
694
662
|
.address(this.network.hrp, this.arkServerPublicKey)
|
|
695
663
|
.encode(),
|
|
696
664
|
state: "active",
|
|
697
665
|
});
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
666
|
+
if (this.offchainTapscript instanceof DelegateVtxo.Script) {
|
|
667
|
+
const delegateScript = new DelegateVtxo.Script({
|
|
668
|
+
pubKey: this.offchainTapscript.options.pubKey,
|
|
669
|
+
serverPubKey: this.offchainTapscript.options.serverPubKey,
|
|
670
|
+
delegatePubKey: this.offchainTapscript.options.delegatePubKey,
|
|
671
|
+
csvTimelock,
|
|
672
|
+
});
|
|
673
|
+
await manager.createContract({
|
|
674
|
+
type: "delegate",
|
|
675
|
+
params: {
|
|
676
|
+
pubKey: hex.encode(delegateScript.options.pubKey),
|
|
677
|
+
serverPubKey: hex.encode(delegateScript.options.serverPubKey),
|
|
678
|
+
delegatePubKey: hex.encode(delegateScript.options.delegatePubKey),
|
|
679
|
+
csvTimelock: csvTimelockStr,
|
|
680
|
+
},
|
|
681
|
+
script: hex.encode(delegateScript.pkScript),
|
|
682
|
+
address: delegateScript
|
|
683
|
+
.address(this.network.hrp, this.arkServerPublicKey)
|
|
684
|
+
.encode(),
|
|
685
|
+
state: "active",
|
|
686
|
+
});
|
|
687
|
+
}
|
|
714
688
|
}
|
|
715
689
|
return manager;
|
|
716
690
|
}
|
|
@@ -793,8 +767,8 @@ export class Wallet extends ReadonlyWallet {
|
|
|
793
767
|
}
|
|
794
768
|
constructor(identity, network, onchainProvider, arkProvider, indexerProvider, arkServerPublicKey, offchainTapscript, boardingTapscript, serverUnrollScript, forfeitOutputScript, forfeitPubkey, dustAmount, walletRepository, contractRepository,
|
|
795
769
|
/** @deprecated Use settlementConfig */
|
|
796
|
-
renewalConfig, delegatorProvider, watcherConfig, settlementConfig) {
|
|
797
|
-
super(identity, network, onchainProvider, indexerProvider, arkServerPublicKey, offchainTapscript, boardingTapscript, dustAmount, walletRepository, contractRepository, delegatorProvider, watcherConfig);
|
|
770
|
+
renewalConfig, delegatorProvider, watcherConfig, settlementConfig, walletContractTimelocks) {
|
|
771
|
+
super(identity, network, onchainProvider, indexerProvider, arkServerPublicKey, offchainTapscript, boardingTapscript, dustAmount, walletRepository, contractRepository, delegatorProvider, watcherConfig, walletContractTimelocks);
|
|
798
772
|
this.arkProvider = arkProvider;
|
|
799
773
|
this.serverUnrollScript = serverUnrollScript;
|
|
800
774
|
this.forfeitOutputScript = forfeitOutputScript;
|
|
@@ -914,7 +888,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
914
888
|
const forfeitPubkey = hex.decode(setup.info.forfeitPubkey).slice(1);
|
|
915
889
|
const forfeitAddress = Address(setup.network).decode(setup.info.forfeitAddress);
|
|
916
890
|
const forfeitOutputScript = OutScript.encode(forfeitAddress);
|
|
917
|
-
const wallet = new Wallet(config.identity, setup.network, setup.onchainProvider, setup.arkProvider, setup.indexerProvider, setup.serverPubKey, setup.offchainTapscript, setup.boardingTapscript, serverUnrollScript, forfeitOutputScript, forfeitPubkey, setup.dustAmount, setup.walletRepository, setup.contractRepository, config.renewalConfig, config.delegatorProvider, config.watcherConfig, config.settlementConfig);
|
|
891
|
+
const wallet = new Wallet(config.identity, setup.network, setup.onchainProvider, setup.arkProvider, setup.indexerProvider, setup.serverPubKey, setup.offchainTapscript, setup.boardingTapscript, serverUnrollScript, forfeitOutputScript, forfeitPubkey, setup.dustAmount, setup.walletRepository, setup.contractRepository, config.renewalConfig, config.delegatorProvider, config.watcherConfig, config.settlementConfig, setup.walletContractTimelocks);
|
|
918
892
|
await wallet.getVtxoManager();
|
|
919
893
|
return wallet;
|
|
920
894
|
}
|
|
@@ -940,7 +914,7 @@ export class Wallet extends ReadonlyWallet {
|
|
|
940
914
|
const readonlyIdentity = hasToReadonly(this.identity)
|
|
941
915
|
? await this.identity.toReadonly()
|
|
942
916
|
: this.identity; // Identity extends ReadonlyIdentity, so this is safe
|
|
943
|
-
return new ReadonlyWallet(readonlyIdentity, this.network, this.onchainProvider, this.indexerProvider, this.arkServerPublicKey, this.offchainTapscript, this.boardingTapscript, this.dustAmount, this.walletRepository, this.contractRepository, this.delegatorProvider, this.watcherConfig);
|
|
917
|
+
return new ReadonlyWallet(readonlyIdentity, this.network, this.onchainProvider, this.indexerProvider, this.arkServerPublicKey, this.offchainTapscript, this.boardingTapscript, this.dustAmount, this.walletRepository, this.contractRepository, this.delegatorProvider, this.watcherConfig, this.walletContractTimelocks);
|
|
944
918
|
}
|
|
945
919
|
/** Returns the delegator manager when delegation support is configured. */
|
|
946
920
|
async getDelegatorManager() {
|
|
@@ -168,6 +168,9 @@ export declare class ContractWatcher {
|
|
|
168
168
|
forcePoll(): Promise<void>;
|
|
169
169
|
/**
|
|
170
170
|
* Connect to the subscription.
|
|
171
|
+
*
|
|
172
|
+
* @param skipUpdate - Skip the leading `updateSubscription` call when
|
|
173
|
+
* the caller has already established `subscriptionId`.
|
|
171
174
|
*/
|
|
172
175
|
private connect;
|
|
173
176
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Bytes } from "@scure/btc-signer/utils.js";
|
|
2
|
-
import { TapLeafScript, VtxoScript } from "../script/base";
|
|
3
|
-
import { VirtualCoin,
|
|
2
|
+
import { EncodedVtxoScript, TapLeafScript, VtxoScript } from "../script/base";
|
|
3
|
+
import { VirtualCoin, TapLeaves } from "../wallet";
|
|
4
4
|
import { ContractFilter } from "../repositories";
|
|
5
5
|
/**
|
|
6
6
|
* Contract state indicating whether it should be actively monitored.
|
|
@@ -66,10 +66,10 @@ export interface Contract {
|
|
|
66
66
|
/**
|
|
67
67
|
* A virtual output that has been associated with a specific contract.
|
|
68
68
|
*/
|
|
69
|
-
export
|
|
70
|
-
|
|
69
|
+
export type ContractVtxo = VirtualCoin & Partial<TapLeaves & EncodedVtxoScript> & {
|
|
70
|
+
extraWitness?: Bytes[];
|
|
71
71
|
contractScript: string;
|
|
72
|
-
}
|
|
72
|
+
};
|
|
73
73
|
/**
|
|
74
74
|
* Result of path selection, including the tapleaf to use and any extra witness data.
|
|
75
75
|
*/
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
export type ManagedEventSourceIterator = AsyncGenerator<MessageEvent, void, unknown> & {
|
|
2
|
+
close(): void;
|
|
3
|
+
};
|
|
1
4
|
/**
|
|
2
|
-
* Creates
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
5
|
+
* Creates a close-aware EventSource async iterator.
|
|
6
|
+
*
|
|
7
|
+
* Listeners attach eagerly so events are buffered before the first next() call.
|
|
8
|
+
* close() closes the EventSource, removes listeners, and wakes any pending
|
|
9
|
+
* next() even when the browser does not emit an error from EventSource.close().
|
|
6
10
|
*/
|
|
7
|
-
export declare function eventSourceIterator(eventSource: EventSource):
|
|
11
|
+
export declare function eventSourceIterator(eventSource: EventSource): ManagedEventSourceIterator;
|
|
8
12
|
export declare function isEventSourceError(error: unknown): error is Error;
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { TransactionOutput } from "@scure/btc-signer/psbt";
|
|
2
|
-
import { ArkProvider, DelegateInfo,
|
|
2
|
+
import { ArkProvider, DelegateInfo, Identity, Outpoint } from "..";
|
|
3
|
+
import { ContractVtxo } from "../contracts/types";
|
|
3
4
|
import { DelegatorProvider } from "../providers/delegator";
|
|
4
5
|
import { Bytes } from "@scure/btc-signer/utils";
|
|
5
6
|
export interface IDelegatorManager {
|
|
6
7
|
/**
|
|
7
8
|
* Delegate virtual outputs to the remote delegation service.
|
|
8
9
|
*
|
|
10
|
+
* Vtxos that are not locked to a delegate-type contract (no tap leaf
|
|
11
|
+
* matches the delegator's pubkey) are filtered out silently, since they
|
|
12
|
+
* cannot be co-signed by the delegator.
|
|
13
|
+
*
|
|
9
14
|
* @param vtxos - Virtual outputs to delegate
|
|
10
15
|
* @param destination - Arkade address that should receive renewed funds
|
|
11
16
|
* @param delegateAt - Optional timestamp to force a specific delegation time
|
|
12
17
|
* @returns Successfully delegated and failed outpoint groups
|
|
13
18
|
*/
|
|
14
|
-
delegate(vtxos:
|
|
19
|
+
delegate(vtxos: ContractVtxo[], destination: string, delegateAt?: Date): Promise<{
|
|
15
20
|
delegated: Outpoint[];
|
|
16
21
|
failed: {
|
|
17
22
|
outpoints: Outpoint[];
|
|
@@ -28,7 +33,7 @@ export declare class DelegatorManagerImpl implements IDelegatorManager {
|
|
|
28
33
|
/** Create a delegator manager from the configured provider, Arkade info source, and wallet identity. */
|
|
29
34
|
constructor(delegatorProvider: DelegatorProvider, arkInfoProvider: Pick<ArkProvider, "getInfo">, identity: Identity);
|
|
30
35
|
getDelegateInfo(): Promise<DelegateInfo>;
|
|
31
|
-
delegate(vtxos:
|
|
36
|
+
delegate(vtxos: ContractVtxo[], destination: string, delegateAt?: Date): Promise<{
|
|
32
37
|
delegated: Outpoint[];
|
|
33
38
|
failed: {
|
|
34
39
|
outpoints: Outpoint[];
|
|
@@ -8,7 +8,7 @@ import { ArkProvider, SettlementEvent, SignedIntent } from "../providers/ark";
|
|
|
8
8
|
import { SignerSession } from "../tree/signingSession";
|
|
9
9
|
import { Identity, ReadonlyIdentity } from "../identity";
|
|
10
10
|
import { ArkTransaction, Coin, ExtendedCoin, ExtendedVirtualCoin, GetVtxosFilter, IAssetManager, IReadonlyAssetManager, IReadonlyWallet, IWallet, ReadonlyWalletConfig, Recipient, SendBitcoinParams, SettleParams, WalletBalance, WalletConfig } from ".";
|
|
11
|
-
import { CSVMultisigTapscript } from "../script/tapscript";
|
|
11
|
+
import { CSVMultisigTapscript, RelativeTimelock } from "../script/tapscript";
|
|
12
12
|
import { SettlementConfig, VtxoManager } from "./vtxo-manager";
|
|
13
13
|
import { Intent } from "../intent";
|
|
14
14
|
import { IndexerProvider } from "../providers/indexer";
|
|
@@ -44,9 +44,10 @@ export declare class ReadonlyWallet implements IReadonlyWallet {
|
|
|
44
44
|
protected readonly watcherConfig?: ReadonlyWalletConfig["watcherConfig"];
|
|
45
45
|
private readonly _assetManager;
|
|
46
46
|
private _syncVtxosInflight?;
|
|
47
|
+
readonly walletContractTimelocks: RelativeTimelock[];
|
|
47
48
|
protected _pendingSpendOutpoints: Set<string>;
|
|
48
49
|
get assetManager(): IReadonlyAssetManager;
|
|
49
|
-
protected constructor(identity: ReadonlyIdentity, network: Network, onchainProvider: OnchainProvider, indexerProvider: IndexerProvider, arkServerPublicKey: Bytes, offchainTapscript: DefaultVtxo.Script | DelegateVtxo.Script, boardingTapscript: DefaultVtxo.Script, dustAmount: bigint, walletRepository: WalletRepository, contractRepository: ContractRepository, delegatorProvider?: DelegatorProvider | undefined, watcherConfig?: ReadonlyWalletConfig["watcherConfig"]);
|
|
50
|
+
protected constructor(identity: ReadonlyIdentity, network: Network, onchainProvider: OnchainProvider, indexerProvider: IndexerProvider, arkServerPublicKey: Bytes, offchainTapscript: DefaultVtxo.Script | DelegateVtxo.Script, boardingTapscript: DefaultVtxo.Script, dustAmount: bigint, walletRepository: WalletRepository, contractRepository: ContractRepository, delegatorProvider?: DelegatorProvider | undefined, watcherConfig?: ReadonlyWalletConfig["watcherConfig"], walletContractTimelocks?: RelativeTimelock[]);
|
|
50
51
|
/**
|
|
51
52
|
* Protected helper to set up shared wallet configuration.
|
|
52
53
|
* Extracts common logic used by both ReadonlyWallet.create() and Wallet.create().
|
|
@@ -65,6 +66,7 @@ export declare class ReadonlyWallet implements IReadonlyWallet {
|
|
|
65
66
|
contractRepository: ContractRepository;
|
|
66
67
|
info: import("../providers/ark").ArkInfo;
|
|
67
68
|
delegatorProvider: DelegatorProvider | undefined;
|
|
69
|
+
walletContractTimelocks: RelativeTimelock[];
|
|
68
70
|
}>;
|
|
69
71
|
/**
|
|
70
72
|
* Create a readonly wallet for querying balances, addresses, and history.
|
|
@@ -75,8 +77,8 @@ export declare class ReadonlyWallet implements IReadonlyWallet {
|
|
|
75
77
|
static create(config: ReadonlyWalletConfig): Promise<ReadonlyWallet>;
|
|
76
78
|
get arkAddress(): ArkAddress;
|
|
77
79
|
/**
|
|
78
|
-
* Get the
|
|
79
|
-
*
|
|
80
|
+
* Get the pkScript hex for the wallet's primary offchain address.
|
|
81
|
+
* For the full wallet-owned script set registered in ContractManager, use getWalletScripts().
|
|
80
82
|
*/
|
|
81
83
|
get defaultContractScript(): string;
|
|
82
84
|
/** Returns the wallet's Arkade address. */
|
|
@@ -125,7 +127,6 @@ export declare class ReadonlyWallet implements IReadonlyWallet {
|
|
|
125
127
|
/**
|
|
126
128
|
* Get all pkScript hex strings for the wallet's own addresses
|
|
127
129
|
* (both delegate and non-delegate, current and historical).
|
|
128
|
-
* Falls back to only the current script if ContractManager is not yet initialized.
|
|
129
130
|
*/
|
|
130
131
|
getWalletScripts(): Promise<string[]>;
|
|
131
132
|
/**
|
|
@@ -229,7 +230,7 @@ export declare class Wallet extends ReadonlyWallet implements IWallet {
|
|
|
229
230
|
readonly settlementConfig: SettlementConfig | false;
|
|
230
231
|
protected constructor(identity: Identity, network: Network, onchainProvider: OnchainProvider, arkProvider: ArkProvider, indexerProvider: IndexerProvider, arkServerPublicKey: Bytes, offchainTapscript: DefaultVtxo.Script | DelegateVtxo.Script, boardingTapscript: DefaultVtxo.Script, serverUnrollScript: CSVMultisigTapscript.Type, forfeitOutputScript: Bytes, forfeitPubkey: Bytes, dustAmount: bigint, walletRepository: WalletRepository, contractRepository: ContractRepository,
|
|
231
232
|
/** @deprecated Use settlementConfig */
|
|
232
|
-
renewalConfig?: WalletConfig["renewalConfig"], delegatorProvider?: DelegatorProvider, watcherConfig?: WalletConfig["watcherConfig"], settlementConfig?: WalletConfig["settlementConfig"]);
|
|
233
|
+
renewalConfig?: WalletConfig["renewalConfig"], delegatorProvider?: DelegatorProvider, watcherConfig?: WalletConfig["watcherConfig"], settlementConfig?: WalletConfig["settlementConfig"], walletContractTimelocks?: RelativeTimelock[]);
|
|
233
234
|
get assetManager(): IAssetManager;
|
|
234
235
|
getVtxoManager(): Promise<VtxoManager>;
|
|
235
236
|
dispose(): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arkade-os/sdk",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.22",
|
|
4
4
|
"description": "TypeScript SDK for building Bitcoin wallets using the Arkade protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -109,9 +109,9 @@
|
|
|
109
109
|
"peerDependencies": {
|
|
110
110
|
"@react-native-async-storage/async-storage": ">=1.0.0",
|
|
111
111
|
"expo": ">=54.0.0",
|
|
112
|
-
"expo-background-task": "~1.0.10",
|
|
113
|
-
"expo-sqlite": "~16.0.10",
|
|
114
|
-
"expo-task-manager": "~14.0.9"
|
|
112
|
+
"expo-background-task": "~1.0.10 || >=55.0.0",
|
|
113
|
+
"expo-sqlite": "~16.0.10 || >=55.0.0",
|
|
114
|
+
"expo-task-manager": "~14.0.9 || >=55.0.0"
|
|
115
115
|
},
|
|
116
116
|
"peerDependenciesMeta": {
|
|
117
117
|
"expo": {
|