@satora/swap 0.3.2 → 1.1.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 +1 -1
- package/dist/bitcoin-reader-electrum-PY7DHD6T.js +7 -0
- package/dist/{bitcoin-reader-esplora-HV6CANAA.js → bitcoin-reader-esplora-ZLPMM5FF.js} +2 -2
- package/dist/bitcoin-reader-esplora-ZLPMM5FF.js.map +1 -0
- package/dist/chunk-FTPIQSRW.js +152 -0
- package/dist/chunk-FTPIQSRW.js.map +1 -0
- package/dist/{chunk-EIWELJJK.js → chunk-THI4UO6R.js} +11 -5
- package/dist/chunk-THI4UO6R.js.map +1 -0
- package/dist/index.cjs +295 -112
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +86 -12
- package/dist/index.d.ts +86 -12
- package/dist/index.js +116 -106
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-EIWELJJK.js.map +0 -1
- /package/dist/{bitcoin-reader-esplora-HV6CANAA.js.map → bitcoin-reader-electrum-PY7DHD6T.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -2,7 +2,10 @@ import {
|
|
|
2
2
|
DEFAULT_ESPLORA_URLS,
|
|
3
3
|
esploraReader,
|
|
4
4
|
htlcFactsFromEsploraTxs
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-THI4UO6R.js";
|
|
6
|
+
import {
|
|
7
|
+
electrumReader
|
|
8
|
+
} from "./chunk-FTPIQSRW.js";
|
|
6
9
|
|
|
7
10
|
// src/index.ts
|
|
8
11
|
export * from "@lendasat/lendaswap-sdk-pure";
|
|
@@ -311,6 +314,7 @@ function payOnLightningStatus(serverHtlc) {
|
|
|
311
314
|
|
|
312
315
|
// src/client.ts
|
|
313
316
|
import {
|
|
317
|
+
DEFAULT_ELECTRUM_WS_URLS,
|
|
314
318
|
Client as LegacyClient
|
|
315
319
|
} from "@lendasat/lendaswap-sdk-pure";
|
|
316
320
|
|
|
@@ -344,10 +348,12 @@ function arkadeObservation(facts) {
|
|
|
344
348
|
}
|
|
345
349
|
function classifyArkadeSpend(encodedSpendTx, paymentHash) {
|
|
346
350
|
const tx = Transaction.fromPSBT(base64.decode(encodedSpendTx));
|
|
347
|
-
for (
|
|
348
|
-
for (const
|
|
349
|
-
|
|
350
|
-
|
|
351
|
+
for (let inputIndex = 0; inputIndex < tx.inputsLength; inputIndex++) {
|
|
352
|
+
for (const witness of getArkPsbtFields(tx, inputIndex, ConditionWitness)) {
|
|
353
|
+
for (const element of witness) {
|
|
354
|
+
if (element.length === 32 && preimageMatches(element, paymentHash)) {
|
|
355
|
+
return { spend: "claim", preimage: element };
|
|
356
|
+
}
|
|
351
357
|
}
|
|
352
358
|
}
|
|
353
359
|
}
|
|
@@ -551,6 +557,8 @@ var BitcoinContractManager = class _BitcoinContractManager {
|
|
|
551
557
|
#obs = /* @__PURE__ */ new Map();
|
|
552
558
|
/** address → the preimage a claim revealed. */
|
|
553
559
|
#preimages = /* @__PURE__ */ new Map();
|
|
560
|
+
/** address → push-subscription teardown (only when the reader supports push). */
|
|
561
|
+
#subscriptions = /* @__PURE__ */ new Map();
|
|
554
562
|
#listeners = /* @__PURE__ */ new Set();
|
|
555
563
|
/** Last MTP reading (ms) + when it was fetched, for extrapolation. */
|
|
556
564
|
#now;
|
|
@@ -562,11 +570,25 @@ var BitcoinContractManager = class _BitcoinContractManager {
|
|
|
562
570
|
return new _BitcoinContractManager(deps);
|
|
563
571
|
}
|
|
564
572
|
static async create(config) {
|
|
565
|
-
const { esploraReader: esploraReader2 } = await import("./bitcoin-reader-esplora-
|
|
573
|
+
const { esploraReader: esploraReader2 } = await import("./bitcoin-reader-esplora-ZLPMM5FF.js");
|
|
574
|
+
let reader = esploraReader2(
|
|
575
|
+
config.esploraUrl,
|
|
576
|
+
void 0,
|
|
577
|
+
{ minConfirmations: config.minConfirmations }
|
|
578
|
+
);
|
|
579
|
+
if (config.electrumWsUrl) {
|
|
580
|
+
const [{ electrumReader: electrumReader2 }, { ElectrumWsClient }] = await Promise.all([
|
|
581
|
+
import("./bitcoin-reader-electrum-PY7DHD6T.js"),
|
|
582
|
+
import("@lendasat/lendaswap-sdk-pure")
|
|
583
|
+
]);
|
|
584
|
+
reader = electrumReader2(new ElectrumWsClient(config.electrumWsUrl), {
|
|
585
|
+
network: config.network,
|
|
586
|
+
minConfirmations: config.minConfirmations,
|
|
587
|
+
fallback: reader
|
|
588
|
+
});
|
|
589
|
+
}
|
|
566
590
|
return _BitcoinContractManager.fromDeps({
|
|
567
|
-
reader
|
|
568
|
-
minConfirmations: config.minConfirmations
|
|
569
|
-
}),
|
|
591
|
+
reader,
|
|
570
592
|
chainTime: config.chainTime
|
|
571
593
|
});
|
|
572
594
|
}
|
|
@@ -579,10 +601,25 @@ var BitcoinContractManager = class _BitcoinContractManager {
|
|
|
579
601
|
`BitcoinContractManager can't track a '${ref.ledger}' HTLC`
|
|
580
602
|
);
|
|
581
603
|
this.#refs.set(ref.address, ref);
|
|
604
|
+
if (this.#reader.subscribe && !this.#subscriptions.has(ref.address)) {
|
|
605
|
+
this.#subscriptions.set(
|
|
606
|
+
ref.address,
|
|
607
|
+
this.#reader.subscribe(ref.address, () => {
|
|
608
|
+
this.#reconcileRef(ref).catch((error) => {
|
|
609
|
+
console.warn(
|
|
610
|
+
"BitcoinContractManager: push reconcile failed:",
|
|
611
|
+
error instanceof Error ? error.message : error
|
|
612
|
+
);
|
|
613
|
+
});
|
|
614
|
+
})
|
|
615
|
+
);
|
|
616
|
+
}
|
|
582
617
|
await this.#reconcileRef(ref);
|
|
583
618
|
}
|
|
584
619
|
async unregister(ref) {
|
|
585
620
|
if (ref.ledger !== "bitcoin") return;
|
|
621
|
+
this.#subscriptions.get(ref.address)?.();
|
|
622
|
+
this.#subscriptions.delete(ref.address);
|
|
586
623
|
this.#refs.delete(ref.address);
|
|
587
624
|
this.#obs.delete(ref.address);
|
|
588
625
|
this.#preimages.delete(ref.address);
|
|
@@ -617,6 +654,8 @@ var BitcoinContractManager = class _BitcoinContractManager {
|
|
|
617
654
|
this.#now = { mtpMs: await this.#chainTime(), fetchedAtMs: Date.now() };
|
|
618
655
|
}
|
|
619
656
|
dispose() {
|
|
657
|
+
for (const unsubscribe of this.#subscriptions.values()) unsubscribe();
|
|
658
|
+
this.#subscriptions.clear();
|
|
620
659
|
this.#listeners.clear();
|
|
621
660
|
}
|
|
622
661
|
/** The preimage a claim revealed on this HTLC, if one was seen. */
|
|
@@ -1519,9 +1558,8 @@ function defaultWebSocketFactory(url) {
|
|
|
1519
1558
|
}
|
|
1520
1559
|
|
|
1521
1560
|
// src/contracts/arkade-vhtlc.ts
|
|
1522
|
-
import {
|
|
1561
|
+
import { VHTLCContractHandler } from "@arkade-os/sdk";
|
|
1523
1562
|
import {
|
|
1524
|
-
ARKADE_HTLC_SCRIPT_VERSION_LEGACY,
|
|
1525
1563
|
ARKADE_HTLC_SCRIPT_VERSION_STRICT,
|
|
1526
1564
|
StrictVhtlcScript
|
|
1527
1565
|
} from "@lendasat/lendaswap-sdk-pure";
|
|
@@ -1551,18 +1589,12 @@ function buildArkadeVhtlcRef(input) {
|
|
|
1551
1589
|
input.unilateralRefundWithoutReceiverDelay
|
|
1552
1590
|
)
|
|
1553
1591
|
};
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
default:
|
|
1561
|
-
throw new Error(
|
|
1562
|
-
`Unsupported Arkade HTLC script version: ${input.arkadeHtlcScriptVersion}`
|
|
1563
|
-
);
|
|
1564
|
-
}
|
|
1565
|
-
})();
|
|
1592
|
+
if (input.arkadeHtlcScriptVersion !== void 0 && input.arkadeHtlcScriptVersion !== ARKADE_HTLC_SCRIPT_VERSION_STRICT) {
|
|
1593
|
+
throw new Error(
|
|
1594
|
+
`Unsupported Arkade HTLC script version: ${input.arkadeHtlcScriptVersion}`
|
|
1595
|
+
);
|
|
1596
|
+
}
|
|
1597
|
+
const vhtlc = new StrictVhtlcScript(params);
|
|
1566
1598
|
return {
|
|
1567
1599
|
ledger: "arkade",
|
|
1568
1600
|
script: hex5.encode(vhtlc.pkScript),
|
|
@@ -1759,47 +1791,6 @@ function swapToTracked(stored) {
|
|
|
1759
1791
|
serverRefundLocktime: ms(r.vhtlc_refund_locktime)
|
|
1760
1792
|
};
|
|
1761
1793
|
// ─── Lightning: one on-chain leg, one off-chain LN payment ───────────────
|
|
1762
|
-
// Receive-on-Lightning: the client funds an on-chain HTLC and is paid over
|
|
1763
|
-
// Lightning. No server leg to watch — the server sweeping the client's leg
|
|
1764
|
-
// (with the preimage it got by paying the invoice) is the done signal.
|
|
1765
|
-
// Client funds the Arkade VHTLC; Boltz pays the invoice. The deposit is
|
|
1766
|
-
// `boltz_amount_sats` (source minus fees) — the amount actually locked, not
|
|
1767
|
-
// `source_amount` — else the client's own funding reads as under-funded.
|
|
1768
|
-
case "arkade_to_lightning":
|
|
1769
|
-
return {
|
|
1770
|
-
swapId: r.id,
|
|
1771
|
-
clientHtlc: arkadeLeg(
|
|
1772
|
-
r,
|
|
1773
|
-
r.arkade_vhtlc_address,
|
|
1774
|
-
Number(r.boltz_amount_sats)
|
|
1775
|
-
),
|
|
1776
|
-
clientRefundLocktime: ms(r.vhtlc_refund_locktime),
|
|
1777
|
-
serverRefundLocktime: 0
|
|
1778
|
-
// no on-chain server leg
|
|
1779
|
-
};
|
|
1780
|
-
// Client funds the EVM HTLC (server claims it after paying the invoice).
|
|
1781
|
-
case "evm_to_lightning":
|
|
1782
|
-
return {
|
|
1783
|
-
swapId: r.id,
|
|
1784
|
-
clientHtlc: evmLeg({
|
|
1785
|
-
chainId: r.evm_chain_id,
|
|
1786
|
-
htlc: r.evm_htlc_address,
|
|
1787
|
-
hashLock: r.hash_lock,
|
|
1788
|
-
claimAddress: r.server_evm_address,
|
|
1789
|
-
// the server claims the client's leg
|
|
1790
|
-
expectedSats: r.evm_expected_sats,
|
|
1791
|
-
// evm_to_lightning doesn't expose the locked token — fall back to the
|
|
1792
|
-
// per-chain mainnet constant so the isActive tuple is complete.
|
|
1793
|
-
token: lockedTokenFallback(r.evm_chain_id, r.network),
|
|
1794
|
-
sender: r.client_evm_address,
|
|
1795
|
-
// the client funded it
|
|
1796
|
-
timelockSec: r.evm_refund_locktime,
|
|
1797
|
-
createdAt: r.created_at
|
|
1798
|
-
}),
|
|
1799
|
-
clientRefundLocktime: ms(r.evm_refund_locktime),
|
|
1800
|
-
serverRefundLocktime: 0
|
|
1801
|
-
// no on-chain server leg
|
|
1802
|
-
};
|
|
1803
1794
|
// Pay-on-Lightning: the client pays a Lightning invoice (off-chain, nothing to
|
|
1804
1795
|
// watch) and claims an on-chain HTLC. No client-funded leg — the client's
|
|
1805
1796
|
// claim completes the swap; a hold invoice that never settles auto-unwinds.
|
|
@@ -1816,26 +1807,20 @@ function swapToTracked(stored) {
|
|
|
1816
1807
|
// no on-chain client leg
|
|
1817
1808
|
serverRefundLocktime: ms(r.vhtlc_refund_locktime)
|
|
1818
1809
|
};
|
|
1819
|
-
// Client
|
|
1820
|
-
|
|
1810
|
+
// Client funds the Arkade VHTLC (source_amount); the server pays the
|
|
1811
|
+
// Lightning invoice off-chain and claims the VHTLC — no server leg to
|
|
1812
|
+
// watch.
|
|
1813
|
+
case "arkade_to_lightning":
|
|
1821
1814
|
return {
|
|
1822
1815
|
swapId: r.id,
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
sender: r.server_evm_address,
|
|
1832
|
-
// the server funded it
|
|
1833
|
-
timelockSec: r.evm_refund_locktime,
|
|
1834
|
-
createdAt: r.created_at
|
|
1835
|
-
}),
|
|
1836
|
-
clientRefundLocktime: 0,
|
|
1837
|
-
// no on-chain client leg
|
|
1838
|
-
serverRefundLocktime: ms(r.evm_refund_locktime)
|
|
1816
|
+
clientHtlc: arkadeLeg(
|
|
1817
|
+
r,
|
|
1818
|
+
r.arkade_vhtlc_address,
|
|
1819
|
+
Number(r.source_amount)
|
|
1820
|
+
),
|
|
1821
|
+
clientRefundLocktime: ms(r.vhtlc_refund_locktime),
|
|
1822
|
+
serverRefundLocktime: 0
|
|
1823
|
+
// no on-chain server leg
|
|
1839
1824
|
};
|
|
1840
1825
|
default:
|
|
1841
1826
|
return void 0;
|
|
@@ -2347,12 +2332,6 @@ var Client = class {
|
|
|
2347
2332
|
);
|
|
2348
2333
|
}
|
|
2349
2334
|
/** Delegated to the legacy client (migration checkpoint). */
|
|
2350
|
-
createLightningToEvmSwapGeneric(...args) {
|
|
2351
|
-
return this.#trackAfterCreate(
|
|
2352
|
-
this.#legacy.createLightningToEvmSwapGeneric(...args)
|
|
2353
|
-
);
|
|
2354
|
-
}
|
|
2355
|
-
/** Delegated to the legacy client (migration checkpoint). */
|
|
2356
2335
|
createBitcoinToEvmSwap(...args) {
|
|
2357
2336
|
return this.#trackAfterCreate(this.#legacy.createBitcoinToEvmSwap(...args));
|
|
2358
2337
|
}
|
|
@@ -2375,16 +2354,6 @@ var Client = class {
|
|
|
2375
2354
|
);
|
|
2376
2355
|
}
|
|
2377
2356
|
/** Delegated to the legacy client (migration checkpoint). */
|
|
2378
|
-
getArkadeToLightningQuote(...args) {
|
|
2379
|
-
return this.#legacy.getArkadeToLightningQuote(...args);
|
|
2380
|
-
}
|
|
2381
|
-
/** Delegated to the legacy client (migration checkpoint). */
|
|
2382
|
-
retryArkadeToLightningSwap(...args) {
|
|
2383
|
-
return this.#trackAfterRetry(
|
|
2384
|
-
this.#legacy.retryArkadeToLightningSwap(...args)
|
|
2385
|
-
);
|
|
2386
|
-
}
|
|
2387
|
-
/** Delegated to the legacy client (migration checkpoint). */
|
|
2388
2357
|
createEvmToArkadeSwapGeneric(...args) {
|
|
2389
2358
|
return this.#trackAfterCreate(
|
|
2390
2359
|
this.#legacy.createEvmToArkadeSwapGeneric(...args)
|
|
@@ -2395,12 +2364,6 @@ var Client = class {
|
|
|
2395
2364
|
return this.#trackAfterCreate(this.#legacy.createEvmToBitcoinSwap(...args));
|
|
2396
2365
|
}
|
|
2397
2366
|
/** Delegated to the legacy client (migration checkpoint). */
|
|
2398
|
-
createEvmToLightningSwapGeneric(...args) {
|
|
2399
|
-
return this.#trackAfterCreate(
|
|
2400
|
-
this.#legacy.createEvmToLightningSwapGeneric(...args)
|
|
2401
|
-
);
|
|
2402
|
-
}
|
|
2403
|
-
/** Delegated to the legacy client (migration checkpoint). */
|
|
2404
2367
|
getCoordinatorFundingCallDataPermit2(...args) {
|
|
2405
2368
|
return this.#legacy.getCoordinatorFundingCallDataPermit2(...args);
|
|
2406
2369
|
}
|
|
@@ -2520,7 +2483,17 @@ var Client = class {
|
|
|
2520
2483
|
/** Every stored swap whose ledgers are observable, mapped to a {@link TrackedSwap}. */
|
|
2521
2484
|
async #loadTrackedSwaps() {
|
|
2522
2485
|
const swaps = await this.listAllSwaps();
|
|
2523
|
-
return swaps.filter((s) => !SETTLED_STORED_STATUSES.has(s.response.status)).map(
|
|
2486
|
+
return swaps.filter((s) => !SETTLED_STORED_STATUSES.has(s.response.status)).map((s) => {
|
|
2487
|
+
try {
|
|
2488
|
+
return swapToTracked(s);
|
|
2489
|
+
} catch (error) {
|
|
2490
|
+
console.warn(
|
|
2491
|
+
`Client: skipping untrackable stored swap ${s.response.id}:`,
|
|
2492
|
+
error
|
|
2493
|
+
);
|
|
2494
|
+
return void 0;
|
|
2495
|
+
}
|
|
2496
|
+
}).filter((s) => s !== void 0);
|
|
2524
2497
|
}
|
|
2525
2498
|
/**
|
|
2526
2499
|
* Run a create, then fold the new swap into tracking.
|
|
@@ -2640,7 +2613,14 @@ var Client = class {
|
|
|
2640
2613
|
return this.#managers;
|
|
2641
2614
|
}
|
|
2642
2615
|
const managers = /* @__PURE__ */ new Map();
|
|
2643
|
-
const {
|
|
2616
|
+
const {
|
|
2617
|
+
arkadeServerUrl,
|
|
2618
|
+
evmRpcUrls,
|
|
2619
|
+
esploraUrl,
|
|
2620
|
+
electrumWsUrl,
|
|
2621
|
+
bitcoinNetwork,
|
|
2622
|
+
bitcoinMinConfirmations
|
|
2623
|
+
} = this.#tracking;
|
|
2644
2624
|
const chainTime = async () => (await this.getMtp()).mtp * 1e3;
|
|
2645
2625
|
const arkadeUrl = arkadeServerUrl ?? defaultArkadeServerUrl("bitcoin");
|
|
2646
2626
|
if (arkadeUrl) {
|
|
@@ -2652,10 +2632,13 @@ var Client = class {
|
|
|
2652
2632
|
const readers = defaultEvmReaders(evmRpcUrls);
|
|
2653
2633
|
if (readers.size > 0)
|
|
2654
2634
|
managers.set("evm", EvmContractManager.fromDeps({ readers }));
|
|
2635
|
+
const network = bitcoinNetwork ?? "mainnet";
|
|
2655
2636
|
managers.set(
|
|
2656
2637
|
"bitcoin",
|
|
2657
2638
|
await BitcoinContractManager.create({
|
|
2658
2639
|
esploraUrl: esploraUrl ? [esploraUrl] : DEFAULT_ESPLORA_URLS,
|
|
2640
|
+
electrumWsUrl: electrumWsUrl ?? DEFAULT_ELECTRUM_WS_URLS[network],
|
|
2641
|
+
network,
|
|
2659
2642
|
chainTime,
|
|
2660
2643
|
minConfirmations: bitcoinMinConfirmations
|
|
2661
2644
|
})
|
|
@@ -2672,6 +2655,8 @@ var ClientBuilder = class {
|
|
|
2672
2655
|
#serverUrl;
|
|
2673
2656
|
#arkadeServerUrl;
|
|
2674
2657
|
#esploraUrl;
|
|
2658
|
+
#electrumWsUrl;
|
|
2659
|
+
#bitcoinNetwork;
|
|
2675
2660
|
#bitcoinMinConfirmations;
|
|
2676
2661
|
#evmRpcUrls;
|
|
2677
2662
|
#managers;
|
|
@@ -2737,6 +2722,28 @@ var ClientBuilder = class {
|
|
|
2737
2722
|
this.#esploraUrl = url;
|
|
2738
2723
|
return this;
|
|
2739
2724
|
}
|
|
2725
|
+
/**
|
|
2726
|
+
* Set an Electrum server WebSocket URL (a Fulcrum `ws`/`wss` port) for
|
|
2727
|
+
* Bitcoin claim/refund chain access. When set, the underlying client
|
|
2728
|
+
* prefers it over Esplora for lookups and broadcasts, and waits for HTLC
|
|
2729
|
+
* fundings via `blockchain.scripthash.subscribe` push instead of polling.
|
|
2730
|
+
* Esplora remains the fallback whenever the Electrum server errors.
|
|
2731
|
+
*/
|
|
2732
|
+
withElectrumWsUrl(url) {
|
|
2733
|
+
this.#inner.withElectrumWsUrl(url);
|
|
2734
|
+
this.#electrumWsUrl = url;
|
|
2735
|
+
return this;
|
|
2736
|
+
}
|
|
2737
|
+
/**
|
|
2738
|
+
* Declare the Bitcoin network of this deployment's HTLC addresses. Only
|
|
2739
|
+
* needed together with {@link withElectrumWsUrl} on a non-mainnet
|
|
2740
|
+
* deployment — the Electrum reader decodes addresses to scripthashes and
|
|
2741
|
+
* defaults to mainnet parameters.
|
|
2742
|
+
*/
|
|
2743
|
+
withBitcoinNetwork(network) {
|
|
2744
|
+
this.#bitcoinNetwork = network;
|
|
2745
|
+
return this;
|
|
2746
|
+
}
|
|
2740
2747
|
/**
|
|
2741
2748
|
* Confirmations a Bitcoin funding tx needs before it observes as `confirmed`
|
|
2742
2749
|
* (gating e.g. the evm→bitcoin claim). Default `0`: claim as soon as the
|
|
@@ -2793,6 +2800,8 @@ var ClientBuilder = class {
|
|
|
2793
2800
|
managers: this.#managers,
|
|
2794
2801
|
arkadeServerUrl: this.#arkadeServerUrl,
|
|
2795
2802
|
esploraUrl: this.#esploraUrl,
|
|
2803
|
+
electrumWsUrl: this.#electrumWsUrl,
|
|
2804
|
+
bitcoinNetwork: this.#bitcoinNetwork,
|
|
2796
2805
|
bitcoinMinConfirmations: this.#bitcoinMinConfirmations,
|
|
2797
2806
|
evmRpcUrls: this.#evmRpcUrls,
|
|
2798
2807
|
autoClaim: this.#autoClaim
|
|
@@ -2828,6 +2837,7 @@ export {
|
|
|
2828
2837
|
defaultEvmReaders,
|
|
2829
2838
|
deriveSwapActions,
|
|
2830
2839
|
deriveSwapStatus,
|
|
2840
|
+
electrumReader,
|
|
2831
2841
|
esploraReader,
|
|
2832
2842
|
evmReaderFromClient,
|
|
2833
2843
|
htlcFactsFromEsploraTxs,
|