@arkade-os/swap 0.0.11 → 0.0.12
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/{chunk-RIC5ZTZK.js → chunk-XXWOODUE.js} +46 -1
- package/dist/index.cjs +391 -40
- package/dist/index.d.cts +115 -6
- package/dist/index.d.ts +115 -6
- package/dist/index.js +322 -21
- package/dist/nostr.d.cts +1 -1
- package/dist/nostr.d.ts +1 -1
- package/dist/nostr.js +1 -1
- package/dist/repositories/realm/index.d.cts +2 -2
- package/dist/repositories/realm/index.d.ts +2 -2
- package/dist/repositories/sqlite/index.d.cts +2 -2
- package/dist/repositories/sqlite/index.d.ts +2 -2
- package/dist/{repository-CfE18Fif.d.ts → repository-DaK1RzRq.d.cts} +4 -1
- package/dist/{repository-B02vsgcV.d.cts → repository-DlLvj_y6.d.ts} +4 -1
- package/dist/{rfq-DkckzRKK.d.ts → rfq-DzsmhXX3.d.cts} +31 -4
- package/dist/{rfq-DkckzRKK.d.cts → rfq-DzsmhXX3.d.ts} +31 -4
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
ARKADE_ASSET,
|
|
3
3
|
ARKADE_BTC,
|
|
4
4
|
AddressMismatch,
|
|
5
|
+
L1_NETWORKS,
|
|
5
6
|
LIGHTNING_BTC,
|
|
6
7
|
LIGHTNING_RECEIVE_PAIR,
|
|
7
8
|
LIGHTNING_SEND_PAIR,
|
|
@@ -38,6 +39,7 @@ import {
|
|
|
38
39
|
deriveOnchainSend,
|
|
39
40
|
extractPreimage,
|
|
40
41
|
httpTransport,
|
|
42
|
+
l1ScriptForAddress,
|
|
41
43
|
lightningReceiveRequest,
|
|
42
44
|
lightningSendRequest,
|
|
43
45
|
lightningSendVtxoScript,
|
|
@@ -63,7 +65,7 @@ import {
|
|
|
63
65
|
unilateralRefundWithoutReceiverDelay,
|
|
64
66
|
verifyLockupAddress,
|
|
65
67
|
verifyReceiveInvoice
|
|
66
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-XXWOODUE.js";
|
|
67
69
|
import {
|
|
68
70
|
InMemoryAssetSwapRepository,
|
|
69
71
|
marketsCacheKey
|
|
@@ -1061,7 +1063,8 @@ function onchainSendProfile(result) {
|
|
|
1061
1063
|
htlcLocktime: result.htlcParams.refundLocktime,
|
|
1062
1064
|
network: result.l1Network,
|
|
1063
1065
|
htlcAddress: result.htlc.address,
|
|
1064
|
-
minConfirmations: result.minConfirmations
|
|
1066
|
+
minConfirmations: result.minConfirmations,
|
|
1067
|
+
payoutPkScript: hex3.encode(result.payoutPkScript)
|
|
1065
1068
|
};
|
|
1066
1069
|
}
|
|
1067
1070
|
var OnchainSendCorridor = {
|
|
@@ -1110,6 +1113,9 @@ var OnchainSendCorridor = {
|
|
|
1110
1113
|
paymentHash,
|
|
1111
1114
|
htlc,
|
|
1112
1115
|
minConfirmations: profile.minConfirmations,
|
|
1116
|
+
// Optional here, required at the write: throwing on an older
|
|
1117
|
+
// record would strand the refund it is still owed.
|
|
1118
|
+
...profile.payoutPkScript ? { payoutPkScript: hex3.decode(profile.payoutPkScript) } : {},
|
|
1113
1119
|
...profile.funding ? { funding: profile.funding } : {},
|
|
1114
1120
|
...profile.claimTxid ? { claimTxid: profile.claimTxid } : {}
|
|
1115
1121
|
};
|
|
@@ -1490,8 +1496,294 @@ async function watchOfferSwaps({
|
|
|
1490
1496
|
};
|
|
1491
1497
|
}
|
|
1492
1498
|
|
|
1493
|
-
// src/
|
|
1499
|
+
// src/chainSource.ts
|
|
1500
|
+
import * as btc from "@scure/btc-signer";
|
|
1501
|
+
import { hex as hex7 } from "@scure/base";
|
|
1502
|
+
var addressOf = (pkScript, network) => btc.Address(L1_NETWORKS[network]).encode(btc.OutScript.decode(pkScript));
|
|
1503
|
+
var chainSourceFrom = (provider, network) => {
|
|
1504
|
+
const spenderFromHistory = async (txid, vout, pkScript) => {
|
|
1505
|
+
const txs = await provider.getTransactions(addressOf(pkScript, network));
|
|
1506
|
+
return txs.find((tx) => tx.vin?.some((i) => i.txid === txid && i.vout === vout))?.txid;
|
|
1507
|
+
};
|
|
1508
|
+
return {
|
|
1509
|
+
async getScriptUtxos(pkScript) {
|
|
1510
|
+
const address = addressOf(pkScript, network);
|
|
1511
|
+
const [coins, tip] = await Promise.all([
|
|
1512
|
+
provider.getCoins(address),
|
|
1513
|
+
provider.getChainTip()
|
|
1514
|
+
]);
|
|
1515
|
+
return coins.map((coin) => ({
|
|
1516
|
+
txid: coin.txid,
|
|
1517
|
+
vout: coin.vout,
|
|
1518
|
+
amount: BigInt(coin.value),
|
|
1519
|
+
// Zero, not one: calling a mempool output "1 deep" would let a
|
|
1520
|
+
// 1-confirmation policy claim against a replaceable transaction.
|
|
1521
|
+
confirmations: coin.status.confirmed && typeof coin.status.block_height === "number" ? Math.max(0, tip.height - coin.status.block_height + 1) : 0
|
|
1522
|
+
}));
|
|
1523
|
+
},
|
|
1524
|
+
async getSpendingTx(txid, vout, pkScript) {
|
|
1525
|
+
const outspends = await provider.getTxOutspends(txid);
|
|
1526
|
+
const outspend = outspends[vout];
|
|
1527
|
+
if (!outspend?.spent) return null;
|
|
1528
|
+
const spender = outspend.txid || await spenderFromHistory(txid, vout, pkScript);
|
|
1529
|
+
if (!spender) return null;
|
|
1530
|
+
const raw = await provider.getRawTransaction(spender);
|
|
1531
|
+
return { txHex: hex7.encode(raw) };
|
|
1532
|
+
},
|
|
1533
|
+
broadcast(txHex) {
|
|
1534
|
+
return provider.broadcastTransaction(txHex);
|
|
1535
|
+
},
|
|
1536
|
+
async getMtp() {
|
|
1537
|
+
return (await provider.getChainTip()).time;
|
|
1538
|
+
}
|
|
1539
|
+
};
|
|
1540
|
+
};
|
|
1541
|
+
|
|
1542
|
+
// src/payment/rendezvous.ts
|
|
1543
|
+
import { selectMarkets, sideLimits as sideLimits2 } from "@arkade-os/solver-discovery";
|
|
1494
1544
|
import { hex as hex8 } from "@scure/base";
|
|
1545
|
+
var XONLY_HEX = /^[0-9a-f]{64}$/;
|
|
1546
|
+
var rendezvousOf = (market, pinned) => {
|
|
1547
|
+
const transports = { nostr: { relays: market.transports?.nostr?.relays ?? [] } };
|
|
1548
|
+
if (!market.discovery_pubkey || !transports.nostr.relays.length) return void 0;
|
|
1549
|
+
const advertised = market.emulator_pubkey;
|
|
1550
|
+
const emulatorPubkey = advertised === void 0 || advertised === null || advertised === "" ? pinned : typeof advertised === "string" && XONLY_HEX.test(advertised) ? advertised : void 0;
|
|
1551
|
+
if (!emulatorPubkey) return void 0;
|
|
1552
|
+
if (pinned && emulatorPubkey !== pinned) return void 0;
|
|
1553
|
+
const bounds = sideLimits2(market, "quote");
|
|
1554
|
+
if (!bounds) return void 0;
|
|
1555
|
+
return {
|
|
1556
|
+
solverPubkey: market.discovery_pubkey,
|
|
1557
|
+
transports,
|
|
1558
|
+
minSats: Number(bounds.min),
|
|
1559
|
+
maxSats: Number(bounds.max)
|
|
1560
|
+
};
|
|
1561
|
+
};
|
|
1562
|
+
var solverRendezvous = (markets, payoutCorridor, amountSats, fallbackEmulatorPubkey) => {
|
|
1563
|
+
const encoded = fallbackEmulatorPubkey ? hex8.encode(fallbackEmulatorPubkey) : void 0;
|
|
1564
|
+
if (encoded !== void 0 && !XONLY_HEX.test(encoded)) return void 0;
|
|
1565
|
+
const pinned = encoded;
|
|
1566
|
+
const candidates = selectMarkets(markets, {
|
|
1567
|
+
baseId: BTC_ASSET_ID,
|
|
1568
|
+
quoteId: BTC_ASSET_ID,
|
|
1569
|
+
baseCorridor: "arkade",
|
|
1570
|
+
quoteCorridor: payoutCorridor
|
|
1571
|
+
});
|
|
1572
|
+
for (const market of candidates) {
|
|
1573
|
+
const rendezvous = rendezvousOf(market, pinned);
|
|
1574
|
+
if (!rendezvous) continue;
|
|
1575
|
+
if (amountSats >= rendezvous.minSats && amountSats <= rendezvous.maxSats) {
|
|
1576
|
+
return rendezvous;
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
return void 0;
|
|
1580
|
+
};
|
|
1581
|
+
|
|
1582
|
+
// src/payment/solverOnchain.ts
|
|
1583
|
+
import { btcTarget, makeHandle, resolveSendAmount, tryResolveSendAmount } from "@arkade-os/sdk";
|
|
1584
|
+
var SOLVER_ONCHAIN_RAIL = "solver-onchain";
|
|
1585
|
+
var solverOnchainRendezvous = (markets, amountSats, fallbackEmulatorPubkey) => solverRendezvous(markets, "onchain", amountSats, fallbackEmulatorPubkey);
|
|
1586
|
+
function solverOnchainRail(deps) {
|
|
1587
|
+
const rendezvousFor = async (amount) => {
|
|
1588
|
+
if (amount === void 0) return void 0;
|
|
1589
|
+
const markets = await deps.discover();
|
|
1590
|
+
return solverOnchainRendezvous(markets, amount, deps.fallbackEmulatorPubkey);
|
|
1591
|
+
};
|
|
1592
|
+
return {
|
|
1593
|
+
id: SOLVER_ONCHAIN_RAIL,
|
|
1594
|
+
match: (req) => btcTarget(req.raw) !== void 0,
|
|
1595
|
+
available: async (req) => {
|
|
1596
|
+
const address = btcTarget(req.raw);
|
|
1597
|
+
if (!address) return false;
|
|
1598
|
+
try {
|
|
1599
|
+
l1ScriptForAddress(address, deps.l1Network);
|
|
1600
|
+
} catch {
|
|
1601
|
+
return false;
|
|
1602
|
+
}
|
|
1603
|
+
const amount = tryResolveSendAmount(req.raw, req.amount);
|
|
1604
|
+
if (amount === void 0) return false;
|
|
1605
|
+
return await rendezvousFor(amount) !== void 0;
|
|
1606
|
+
},
|
|
1607
|
+
quote: async (req, ctx) => {
|
|
1608
|
+
const address = btcTarget(req.raw);
|
|
1609
|
+
const amount = resolveSendAmount(SOLVER_ONCHAIN_RAIL, req.raw, req.amount);
|
|
1610
|
+
const payoutPkScript = l1ScriptForAddress(address, deps.l1Network);
|
|
1611
|
+
const rendezvous = await rendezvousFor(amount);
|
|
1612
|
+
if (!rendezvous) {
|
|
1613
|
+
throw new Error(
|
|
1614
|
+
`${SOLVER_ONCHAIN_RAIL}: no solver serves arkade:BTC -> onchain:BTC at ${amount} sats`
|
|
1615
|
+
);
|
|
1616
|
+
}
|
|
1617
|
+
const negotiated = await deps.connect(
|
|
1618
|
+
rendezvous,
|
|
1619
|
+
(transport) => requestOnchainSend(ctx.wallet, deps.arkServerUrl, transport, {
|
|
1620
|
+
amount,
|
|
1621
|
+
amountSide: "to",
|
|
1622
|
+
payoutPubkey: deps.payoutPubkey,
|
|
1623
|
+
...deps.emulatorPubkey ? { emulatorPubkey: deps.emulatorPubkey } : {}
|
|
1624
|
+
})
|
|
1625
|
+
);
|
|
1626
|
+
if (negotiated.l1Network !== deps.l1Network) {
|
|
1627
|
+
throw new Error(
|
|
1628
|
+
`${SOLVER_ONCHAIN_RAIL}: rail built for ${deps.l1Network} but the swap was negotiated on ${negotiated.l1Network}`
|
|
1629
|
+
);
|
|
1630
|
+
}
|
|
1631
|
+
const swap = { ...negotiated, rendezvous, payoutPkScript };
|
|
1632
|
+
return {
|
|
1633
|
+
railId: SOLVER_ONCHAIN_RAIL,
|
|
1634
|
+
amount,
|
|
1635
|
+
fee: swap.fundAmount - amount,
|
|
1636
|
+
total: swap.fundAmount,
|
|
1637
|
+
meta: {
|
|
1638
|
+
rfqId: swap.rfqId,
|
|
1639
|
+
validUntil: swap.quote.valid_until,
|
|
1640
|
+
htlcAddress: swap.htlc.address,
|
|
1641
|
+
minConfirmations: swap.minConfirmations,
|
|
1642
|
+
solverPubkey: rendezvous.solverPubkey,
|
|
1643
|
+
// The claim tx's fee comes out of the HTLC output at a rate
|
|
1644
|
+
// not knowable now, so `amount` is the payout, not the net.
|
|
1645
|
+
claimFeeDeductedFromPayout: true
|
|
1646
|
+
},
|
|
1647
|
+
send: async () => makeHandle(SOLVER_ONCHAIN_RAIL, async (emit) => {
|
|
1648
|
+
assertFundable({
|
|
1649
|
+
quote: swap.quote,
|
|
1650
|
+
now: Math.floor(Date.now() / 1e3),
|
|
1651
|
+
onchain: {
|
|
1652
|
+
htlcLocktime: swap.htlcParams.refundLocktime,
|
|
1653
|
+
minConfirmations: swap.minConfirmations,
|
|
1654
|
+
direction: "send"
|
|
1655
|
+
}
|
|
1656
|
+
});
|
|
1657
|
+
await deps.persist(swap);
|
|
1658
|
+
await ctx.wallet.send({
|
|
1659
|
+
address: swap.address,
|
|
1660
|
+
amount: swap.fundAmount
|
|
1661
|
+
});
|
|
1662
|
+
emit({ status: "sent" });
|
|
1663
|
+
const result = { railId: SOLVER_ONCHAIN_RAIL, swapId: swap.rfqId };
|
|
1664
|
+
if (!deps.awaitSettlement) return result;
|
|
1665
|
+
let txid;
|
|
1666
|
+
try {
|
|
1667
|
+
({ txid } = await deps.awaitSettlement(swap));
|
|
1668
|
+
} catch (e) {
|
|
1669
|
+
console.warn(
|
|
1670
|
+
`${SOLVER_ONCHAIN_RAIL}: settlement watch failed; the payment is sent`,
|
|
1671
|
+
e
|
|
1672
|
+
);
|
|
1673
|
+
return result;
|
|
1674
|
+
}
|
|
1675
|
+
const settled = { ...result, txid };
|
|
1676
|
+
emit({ status: "settled", result: settled });
|
|
1677
|
+
return settled;
|
|
1678
|
+
})
|
|
1679
|
+
};
|
|
1680
|
+
}
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
// src/payment/solverLightning.ts
|
|
1685
|
+
import { invoiceTarget, makeHandle as makeHandle2 } from "@arkade-os/sdk";
|
|
1686
|
+
var SOLVER_LIGHTNING_RAIL = "solver-lightning";
|
|
1687
|
+
var factsOf = (raw, decode, now) => {
|
|
1688
|
+
const invoice = invoiceTarget(raw);
|
|
1689
|
+
if (!invoice) return void 0;
|
|
1690
|
+
let facts;
|
|
1691
|
+
try {
|
|
1692
|
+
facts = decode(invoice);
|
|
1693
|
+
} catch {
|
|
1694
|
+
return void 0;
|
|
1695
|
+
}
|
|
1696
|
+
if (!Number.isInteger(facts.amountSats) || facts.amountSats <= 0) return void 0;
|
|
1697
|
+
if (facts.expiresAt <= now) return void 0;
|
|
1698
|
+
return facts;
|
|
1699
|
+
};
|
|
1700
|
+
var solverLightningRendezvous = (markets, amountSats, fallbackEmulatorPubkey) => solverRendezvous(markets, "lightning", amountSats, fallbackEmulatorPubkey);
|
|
1701
|
+
function solverLightningRail(deps) {
|
|
1702
|
+
const rendezvousFor = async (amountSats) => solverLightningRendezvous(await deps.discover(), amountSats, deps.fallbackEmulatorPubkey);
|
|
1703
|
+
return {
|
|
1704
|
+
id: SOLVER_LIGHTNING_RAIL,
|
|
1705
|
+
match: (req) => invoiceTarget(req.raw) !== void 0,
|
|
1706
|
+
available: async (req) => {
|
|
1707
|
+
const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
|
|
1708
|
+
if (!facts) return false;
|
|
1709
|
+
if (req.amount !== void 0 && req.amount !== facts.amountSats) return false;
|
|
1710
|
+
return await rendezvousFor(facts.amountSats) !== void 0;
|
|
1711
|
+
},
|
|
1712
|
+
quote: async (req, ctx) => {
|
|
1713
|
+
const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
|
|
1714
|
+
if (!facts) {
|
|
1715
|
+
throw new Error(
|
|
1716
|
+
`${SOLVER_LIGHTNING_RAIL}: the request carries no payable BOLT11 invoice (amountless, expired, or undecodable)`
|
|
1717
|
+
);
|
|
1718
|
+
}
|
|
1719
|
+
if (req.amount !== void 0 && req.amount !== facts.amountSats) {
|
|
1720
|
+
throw new Error(
|
|
1721
|
+
`${SOLVER_LIGHTNING_RAIL}: the request names ${req.amount} sats but the invoice is for ${facts.amountSats} \u2014 the payee is paid the invoice`
|
|
1722
|
+
);
|
|
1723
|
+
}
|
|
1724
|
+
const rendezvous = await rendezvousFor(facts.amountSats);
|
|
1725
|
+
if (!rendezvous) {
|
|
1726
|
+
throw new Error(
|
|
1727
|
+
`${SOLVER_LIGHTNING_RAIL}: no solver serves arkade:BTC -> lightning:BTC at ${facts.amountSats} sats`
|
|
1728
|
+
);
|
|
1729
|
+
}
|
|
1730
|
+
const negotiated = await deps.connect(
|
|
1731
|
+
rendezvous,
|
|
1732
|
+
(transport) => requestLightningSend(ctx.wallet, deps.arkServerUrl, transport, {
|
|
1733
|
+
invoice: facts,
|
|
1734
|
+
...deps.emulatorPubkey ? { emulatorPubkey: deps.emulatorPubkey } : {}
|
|
1735
|
+
})
|
|
1736
|
+
);
|
|
1737
|
+
const swap = { ...negotiated, invoice: facts, rendezvous };
|
|
1738
|
+
return {
|
|
1739
|
+
railId: SOLVER_LIGHTNING_RAIL,
|
|
1740
|
+
// `requestLightningSend` refuses a quote that reprices the
|
|
1741
|
+
// invoice, so the spread is a fee on top.
|
|
1742
|
+
amount: facts.amountSats,
|
|
1743
|
+
fee: swap.fundAmount - facts.amountSats,
|
|
1744
|
+
total: swap.fundAmount,
|
|
1745
|
+
meta: {
|
|
1746
|
+
rfqId: swap.rfqId,
|
|
1747
|
+
validUntil: swap.quote.valid_until,
|
|
1748
|
+
paymentHash: facts.paymentHash,
|
|
1749
|
+
invoiceExpiresAt: facts.expiresAt,
|
|
1750
|
+
solverPubkey: rendezvous.solverPubkey
|
|
1751
|
+
},
|
|
1752
|
+
send: async () => makeHandle2(SOLVER_LIGHTNING_RAIL, async (emit) => {
|
|
1753
|
+
assertFundable({
|
|
1754
|
+
quote: swap.quote,
|
|
1755
|
+
invoiceExpiresAt: facts.expiresAt,
|
|
1756
|
+
now: Math.floor(Date.now() / 1e3)
|
|
1757
|
+
});
|
|
1758
|
+
await deps.persist(swap);
|
|
1759
|
+
await ctx.wallet.send({
|
|
1760
|
+
address: swap.address,
|
|
1761
|
+
amount: swap.fundAmount
|
|
1762
|
+
});
|
|
1763
|
+
emit({ status: "sent" });
|
|
1764
|
+
const result = { railId: SOLVER_LIGHTNING_RAIL, swapId: swap.rfqId };
|
|
1765
|
+
if (!deps.awaitSettlement) return result;
|
|
1766
|
+
let preimage;
|
|
1767
|
+
try {
|
|
1768
|
+
({ preimage } = await deps.awaitSettlement(swap));
|
|
1769
|
+
} catch (e) {
|
|
1770
|
+
console.warn(
|
|
1771
|
+
`${SOLVER_LIGHTNING_RAIL}: settlement watch failed; the payment is sent`,
|
|
1772
|
+
e
|
|
1773
|
+
);
|
|
1774
|
+
return result;
|
|
1775
|
+
}
|
|
1776
|
+
const settled = { ...result, ...preimage !== void 0 && { preimage } };
|
|
1777
|
+
emit({ status: "settled", result: settled });
|
|
1778
|
+
return settled;
|
|
1779
|
+
})
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
// src/claim.ts
|
|
1786
|
+
import { hex as hex10 } from "@scure/base";
|
|
1495
1787
|
import { ripemd160 } from "@noble/hashes/legacy.js";
|
|
1496
1788
|
import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
|
|
1497
1789
|
import {
|
|
@@ -1501,7 +1793,7 @@ import {
|
|
|
1501
1793
|
} from "@arkade-os/sdk";
|
|
1502
1794
|
|
|
1503
1795
|
// src/refund.ts
|
|
1504
|
-
import { base64 as base643, hex as
|
|
1796
|
+
import { base64 as base643, hex as hex9 } from "@scure/base";
|
|
1505
1797
|
import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
|
|
1506
1798
|
import {
|
|
1507
1799
|
CSVMultisigTapscript,
|
|
@@ -1559,7 +1851,7 @@ var LockupNeedsRecoveryError = class extends Error {
|
|
|
1559
1851
|
}
|
|
1560
1852
|
};
|
|
1561
1853
|
async function findLockupVtxos(indexer, swapPkScript) {
|
|
1562
|
-
const scripts = [
|
|
1854
|
+
const scripts = [hex9.encode(swapPkScript)];
|
|
1563
1855
|
const [spendable, recoverable] = await Promise.all([
|
|
1564
1856
|
indexer.getVtxos({ scripts, spendableOnly: true }),
|
|
1565
1857
|
indexer.getVtxos({ scripts, recoverableOnly: true })
|
|
@@ -1585,13 +1877,13 @@ async function findLockupVtxos(indexer, swapPkScript) {
|
|
|
1585
1877
|
}
|
|
1586
1878
|
return out;
|
|
1587
1879
|
}
|
|
1588
|
-
var hashesTo = (candidate, paymentHash) =>
|
|
1880
|
+
var hashesTo = (candidate, paymentHash) => hex9.encode(sha2562(candidate)) === paymentHash;
|
|
1589
1881
|
var candidateWitnessItems = (tx, inputIndex) => [
|
|
1590
1882
|
...getArkPsbtFields(tx, inputIndex, ConditionWitness).flat(),
|
|
1591
1883
|
...tx.getInput(inputIndex).finalScriptWitness ?? []
|
|
1592
1884
|
];
|
|
1593
1885
|
async function readLockupFate(indexer, input) {
|
|
1594
|
-
const { vtxos } = await indexer.getVtxos({ scripts: [
|
|
1886
|
+
const { vtxos } = await indexer.getVtxos({ scripts: [hex9.encode(input.swapPkScript)] });
|
|
1595
1887
|
const all = vtxos ?? [];
|
|
1596
1888
|
if (all.length === 0) return { fate: "unknown" };
|
|
1597
1889
|
const exited = all.filter((vtxo) => vtxo.isUnrolled && !hasTerminalSpend(vtxo));
|
|
@@ -1626,7 +1918,7 @@ async function readLockupFate(indexer, input) {
|
|
|
1626
1918
|
for (let i = 0; i < tx.inputsLength; i++) {
|
|
1627
1919
|
const spent = tx.getInput(i);
|
|
1628
1920
|
if (!spent.txid) continue;
|
|
1629
|
-
const txid =
|
|
1921
|
+
const txid = hex9.encode(spent.txid);
|
|
1630
1922
|
if (!all.some((vtxo) => vtxo.txid === txid && vtxo.vout === spent.index)) continue;
|
|
1631
1923
|
for (const candidate of candidateWitnessItems(tx, i)) {
|
|
1632
1924
|
if (hashesTo(candidate, input.paymentHash)) {
|
|
@@ -1655,7 +1947,7 @@ async function pushRefundWithoutReceiver(ark, input) {
|
|
|
1655
1947
|
const info = await ark.getInfo();
|
|
1656
1948
|
let serverUnrollScript;
|
|
1657
1949
|
try {
|
|
1658
|
-
serverUnrollScript = CSVMultisigTapscript.decode(
|
|
1950
|
+
serverUnrollScript = CSVMultisigTapscript.decode(hex9.decode(info.checkpointTapscript));
|
|
1659
1951
|
} catch {
|
|
1660
1952
|
throw new Error("invalid checkpointTapscript from the Arkade server");
|
|
1661
1953
|
}
|
|
@@ -1781,13 +2073,13 @@ async function pushClaim(ark, input) {
|
|
|
1781
2073
|
}
|
|
1782
2074
|
}
|
|
1783
2075
|
const committed = input.script.options.preimageHash;
|
|
1784
|
-
if (
|
|
2076
|
+
if (hex10.encode(ripemd160(sha2563(input.preimage))) !== hex10.encode(committed)) {
|
|
1785
2077
|
throw new Error("preimage does not match the covenant's payment hash");
|
|
1786
2078
|
}
|
|
1787
2079
|
const info = await ark.getInfo();
|
|
1788
2080
|
let serverUnrollScript;
|
|
1789
2081
|
try {
|
|
1790
|
-
serverUnrollScript = CSVMultisigTapscript2.decode(
|
|
2082
|
+
serverUnrollScript = CSVMultisigTapscript2.decode(hex10.decode(info.checkpointTapscript));
|
|
1791
2083
|
} catch {
|
|
1792
2084
|
throw new Error("invalid checkpointTapscript from the Arkade server");
|
|
1793
2085
|
}
|
|
@@ -1906,7 +2198,7 @@ function arkadeRefunder(deps) {
|
|
|
1906
2198
|
}
|
|
1907
2199
|
|
|
1908
2200
|
// src/swapManager.ts
|
|
1909
|
-
import { hex as
|
|
2201
|
+
import { hex as hex11 } from "@scure/base";
|
|
1910
2202
|
function nextOnchainAction(input) {
|
|
1911
2203
|
switch (input.phase.phase) {
|
|
1912
2204
|
case "unfunded":
|
|
@@ -2354,7 +2646,7 @@ var RfqSwapManager = class {
|
|
|
2354
2646
|
// ── internals ────────────────────────────────────────────────────────────
|
|
2355
2647
|
track(swap) {
|
|
2356
2648
|
this.monitored.set(swap.rfqId, swap);
|
|
2357
|
-
this.byLockupScript.set(
|
|
2649
|
+
this.byLockupScript.set(hex11.encode(swap.lockupPkScript), swap);
|
|
2358
2650
|
}
|
|
2359
2651
|
/** Drops the swap from BOTH indexes. The event index is the one that stops
|
|
2360
2652
|
* a late event finding a swap that is gone; `pollSwap`'s own
|
|
@@ -2363,7 +2655,7 @@ var RfqSwapManager = class {
|
|
|
2363
2655
|
* them from silently re-driving a cancelled swap. */
|
|
2364
2656
|
untrack(rfqId) {
|
|
2365
2657
|
const swap = this.monitored.get(rfqId);
|
|
2366
|
-
if (swap) this.byLockupScript.delete(
|
|
2658
|
+
if (swap) this.byLockupScript.delete(hex11.encode(swap.lockupPkScript));
|
|
2367
2659
|
this.monitored.delete(rfqId);
|
|
2368
2660
|
this.refundRefused.delete(rfqId);
|
|
2369
2661
|
this.lastClaimError.delete(rfqId);
|
|
@@ -2425,7 +2717,7 @@ var RfqSwapManager = class {
|
|
|
2425
2717
|
if (!lockup) {
|
|
2426
2718
|
try {
|
|
2427
2719
|
const [existing] = await contracts.getContracts({
|
|
2428
|
-
script:
|
|
2720
|
+
script: hex11.encode(swap.lockupPkScript)
|
|
2429
2721
|
});
|
|
2430
2722
|
if (existing) {
|
|
2431
2723
|
this.registered.set(swap.rfqId, true);
|
|
@@ -2444,13 +2736,13 @@ var RfqSwapManager = class {
|
|
|
2444
2736
|
);
|
|
2445
2737
|
return;
|
|
2446
2738
|
}
|
|
2447
|
-
const script =
|
|
2448
|
-
if (script !==
|
|
2739
|
+
const script = hex11.encode(lockup.script.pkScript);
|
|
2740
|
+
if (script !== hex11.encode(swap.lockupPkScript)) {
|
|
2449
2741
|
this.registered.set(swap.rfqId, false);
|
|
2450
2742
|
this.emitFailed(
|
|
2451
2743
|
swap,
|
|
2452
2744
|
new Error(
|
|
2453
|
-
`swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${
|
|
2745
|
+
`swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${hex11.encode(swap.lockupPkScript)}`
|
|
2454
2746
|
)
|
|
2455
2747
|
);
|
|
2456
2748
|
return;
|
|
@@ -2469,7 +2761,7 @@ var RfqSwapManager = class {
|
|
|
2469
2761
|
* script for its whole life. Best-effort — the swap is over either way. */
|
|
2470
2762
|
retireContract(swap) {
|
|
2471
2763
|
if (!this.deps.contracts || !this.registered.get(swap.rfqId)) return;
|
|
2472
|
-
void this.deps.contracts.setContractWatchState(
|
|
2764
|
+
void this.deps.contracts.setContractWatchState(hex11.encode(swap.lockupPkScript), "retained").catch((error) => this.emitFailed(swap, error));
|
|
2473
2765
|
}
|
|
2474
2766
|
arm() {
|
|
2475
2767
|
if (!this.running) return;
|
|
@@ -2945,7 +3237,7 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
|
2945
3237
|
import {
|
|
2946
3238
|
ArkAddress as ArkAddress4
|
|
2947
3239
|
} from "@arkade-os/sdk";
|
|
2948
|
-
import { hex as
|
|
3240
|
+
import { hex as hex12 } from "@scure/base";
|
|
2949
3241
|
var LABELS = {
|
|
2950
3242
|
lightning_send: "Lightning send",
|
|
2951
3243
|
lightning_receive: "Lightning receive",
|
|
@@ -3020,7 +3312,7 @@ async function activityInputOf(record, indexer) {
|
|
|
3020
3312
|
async function lockupTxids(indexer, record, wantFunding) {
|
|
3021
3313
|
let script;
|
|
3022
3314
|
try {
|
|
3023
|
-
script =
|
|
3315
|
+
script = hex12.encode(ArkAddress4.decode(record.lockupAddress).pkScript);
|
|
3024
3316
|
} catch {
|
|
3025
3317
|
return [];
|
|
3026
3318
|
}
|
|
@@ -3073,6 +3365,8 @@ export {
|
|
|
3073
3365
|
RfqSwapManager,
|
|
3074
3366
|
RfqSwapOriginRequired,
|
|
3075
3367
|
SOLO_REFUND_HEADROOM_SECONDS,
|
|
3368
|
+
SOLVER_LIGHTNING_RAIL,
|
|
3369
|
+
SOLVER_ONCHAIN_RAIL,
|
|
3076
3370
|
SWAP_LOCKUP_CONTRACT_KIND,
|
|
3077
3371
|
SWAP_LOCKUP_CONTRACT_LABEL,
|
|
3078
3372
|
SWAP_LOCKUP_CONTRACT_TYPE,
|
|
@@ -3089,6 +3383,7 @@ export {
|
|
|
3089
3383
|
buildHtlcClaim,
|
|
3090
3384
|
buildHtlcRefund,
|
|
3091
3385
|
cancelOffer,
|
|
3386
|
+
chainSourceFrom,
|
|
3092
3387
|
claimOnchainFill,
|
|
3093
3388
|
claimReceiveLockup,
|
|
3094
3389
|
classifyDepositSpend,
|
|
@@ -3110,6 +3405,7 @@ export {
|
|
|
3110
3405
|
httpTransport,
|
|
3111
3406
|
isRfqSwapTerminal,
|
|
3112
3407
|
isRfqTerminal,
|
|
3408
|
+
l1ScriptForAddress,
|
|
3113
3409
|
lightningReceiveRequest,
|
|
3114
3410
|
lightningSendRequest,
|
|
3115
3411
|
lightningSendVtxoScript,
|
|
@@ -3149,6 +3445,11 @@ export {
|
|
|
3149
3445
|
sealClaimPacket,
|
|
3150
3446
|
senderIdentityForSwapRecord,
|
|
3151
3447
|
shouldRetainRfqSwap,
|
|
3448
|
+
solverLightningRail,
|
|
3449
|
+
solverLightningRendezvous,
|
|
3450
|
+
solverOnchainRail,
|
|
3451
|
+
solverOnchainRendezvous,
|
|
3452
|
+
solverRendezvous,
|
|
3152
3453
|
spendTxidsOf,
|
|
3153
3454
|
spendUpdate,
|
|
3154
3455
|
swapActivityResolver,
|
package/dist/nostr.d.cts
CHANGED
package/dist/nostr.d.ts
CHANGED
package/dist/nostr.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { RealmLike } from '@arkade-os/sdk/repositories/realm';
|
|
2
|
-
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-
|
|
2
|
+
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-DaK1RzRq.cjs';
|
|
3
3
|
import '@arkade-os/solver-discovery';
|
|
4
4
|
import '@arkade-os/sdk';
|
|
5
|
-
import '../../rfq-
|
|
5
|
+
import '../../rfq-DzsmhXX3.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Realm backend for React Native.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { RealmLike } from '@arkade-os/sdk/repositories/realm';
|
|
2
|
-
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-
|
|
2
|
+
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-DlLvj_y6.js';
|
|
3
3
|
import '@arkade-os/solver-discovery';
|
|
4
4
|
import '@arkade-os/sdk';
|
|
5
|
-
import '../../rfq-
|
|
5
|
+
import '../../rfq-DzsmhXX3.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Realm backend for React Native.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
|
|
2
|
-
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-
|
|
2
|
+
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-DaK1RzRq.cjs';
|
|
3
3
|
import '@arkade-os/solver-discovery';
|
|
4
4
|
import '@arkade-os/sdk';
|
|
5
|
-
import '../../rfq-
|
|
5
|
+
import '../../rfq-DzsmhXX3.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* SQLite backend over the SDK's `SQLExecutor`, so any driver plugs in
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SQLExecutor } from '@arkade-os/sdk/repositories/sqlite';
|
|
2
|
-
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-
|
|
2
|
+
import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-DlLvj_y6.js';
|
|
3
3
|
import '@arkade-os/solver-discovery';
|
|
4
4
|
import '@arkade-os/sdk';
|
|
5
|
-
import '../../rfq-
|
|
5
|
+
import '../../rfq-DzsmhXX3.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* SQLite backend over the SDK's `SQLExecutor`, so any driver plugs in
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DiscoveredMarket } from '@arkade-os/solver-discovery';
|
|
2
2
|
import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, RestIndexerProvider, VHTLC, Identity, IContractManager } from '@arkade-os/sdk';
|
|
3
|
-
import {
|
|
3
|
+
import { B as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-DzsmhXX3.cjs';
|
|
4
4
|
|
|
5
5
|
type AssetSwapStatus = "pending" | "cancelling" | "fulfilled" | "cancelled" | "recoverable" | "awaiting_fill" | "claimable" | "claimed" | "refunded_l1";
|
|
6
6
|
/** The sentinel asset id for BTC itself, as opposed to a 68-hex asset id.
|
|
@@ -829,6 +829,9 @@ interface OnchainSendSwap extends RfqSwapCommon {
|
|
|
829
829
|
htlc: OnchainHtlc;
|
|
830
830
|
/** `profile.min_confirmations` from the quote. */
|
|
831
831
|
minConfirmations: number;
|
|
832
|
+
/** Where {@link RfqSwapManagerCallbacks.claimOnchain} pays; optional only
|
|
833
|
+
* so records predating its profile slot still restore. */
|
|
834
|
+
payoutPkScript?: Uint8Array;
|
|
832
835
|
/** The fill's outpoint, learned on first sighting. Without it a SPENT
|
|
833
836
|
* HTLC reads as never funded — see {@link classifyOnchainHtlc}. */
|
|
834
837
|
funding?: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DiscoveredMarket } from '@arkade-os/solver-discovery';
|
|
2
2
|
import { IWallet, ProvisionedKey, ProvisionedClaimSecret, RestArkProvider, RestIndexerProvider, VHTLC, Identity, IContractManager } from '@arkade-os/sdk';
|
|
3
|
-
import {
|
|
3
|
+
import { B as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-DzsmhXX3.js';
|
|
4
4
|
|
|
5
5
|
type AssetSwapStatus = "pending" | "cancelling" | "fulfilled" | "cancelled" | "recoverable" | "awaiting_fill" | "claimable" | "claimed" | "refunded_l1";
|
|
6
6
|
/** The sentinel asset id for BTC itself, as opposed to a 68-hex asset id.
|
|
@@ -829,6 +829,9 @@ interface OnchainSendSwap extends RfqSwapCommon {
|
|
|
829
829
|
htlc: OnchainHtlc;
|
|
830
830
|
/** `profile.min_confirmations` from the quote. */
|
|
831
831
|
minConfirmations: number;
|
|
832
|
+
/** Where {@link RfqSwapManagerCallbacks.claimOnchain} pays; optional only
|
|
833
|
+
* so records predating its profile slot still restore. */
|
|
834
|
+
payoutPkScript?: Uint8Array;
|
|
832
835
|
/** The fill's outpoint, learned on first sighting. Without it a SPENT
|
|
833
836
|
* HTLC reads as never funded — see {@link classifyOnchainHtlc}. */
|
|
834
837
|
funding?: {
|