@arkade-os/swap 0.0.11 → 0.0.13
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-IFZOBTTG.js} +54 -9
- package/dist/index.cjs +661 -50
- package/dist/index.d.cts +240 -6
- package/dist/index.d.ts +240 -6
- package/dist/index.js +596 -28
- 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-B02vsgcV.d.cts → repository-D5JoeqwB.d.ts} +4 -1
- package/dist/{repository-CfE18Fif.d.ts → repository-Vfx65uF1.d.cts} +4 -1
- package/dist/{rfq-DkckzRKK.d.ts → rfq-CYfKvAPp.d.cts} +45 -12
- package/dist/{rfq-DkckzRKK.d.cts → rfq-CYfKvAPp.d.ts} +45 -12
- 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-IFZOBTTG.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,10 +1496,557 @@ 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 {
|
|
1584
|
+
assertNoAssets,
|
|
1585
|
+
assetsOf,
|
|
1586
|
+
btcTarget,
|
|
1587
|
+
makeHandle,
|
|
1588
|
+
resolveSendAmount,
|
|
1589
|
+
tryResolveSendAmount
|
|
1590
|
+
} from "@arkade-os/sdk";
|
|
1591
|
+
var SOLVER_ONCHAIN_RAIL = "solver-onchain";
|
|
1592
|
+
var solverOnchainRendezvous = (markets, amountSats, fallbackEmulatorPubkey) => solverRendezvous(markets, "onchain", amountSats, fallbackEmulatorPubkey);
|
|
1593
|
+
function solverOnchainRail(deps) {
|
|
1594
|
+
const rendezvousFor = async (amount) => {
|
|
1595
|
+
if (amount === void 0) return void 0;
|
|
1596
|
+
const markets = await deps.discover();
|
|
1597
|
+
return solverOnchainRendezvous(markets, amount, deps.fallbackEmulatorPubkey);
|
|
1598
|
+
};
|
|
1599
|
+
return {
|
|
1600
|
+
id: SOLVER_ONCHAIN_RAIL,
|
|
1601
|
+
match: (req) => btcTarget(req.raw) !== void 0,
|
|
1602
|
+
available: async (req) => {
|
|
1603
|
+
if (assetsOf(req).length > 0) return false;
|
|
1604
|
+
const address = btcTarget(req.raw);
|
|
1605
|
+
if (!address) return false;
|
|
1606
|
+
try {
|
|
1607
|
+
l1ScriptForAddress(address, deps.l1Network);
|
|
1608
|
+
} catch {
|
|
1609
|
+
return false;
|
|
1610
|
+
}
|
|
1611
|
+
const amount = tryResolveSendAmount(req.raw, req.amount);
|
|
1612
|
+
if (amount === void 0) return false;
|
|
1613
|
+
return await rendezvousFor(amount) !== void 0;
|
|
1614
|
+
},
|
|
1615
|
+
quote: async (req, ctx) => {
|
|
1616
|
+
const address = btcTarget(req.raw);
|
|
1617
|
+
assertNoAssets(SOLVER_ONCHAIN_RAIL, req);
|
|
1618
|
+
const amount = resolveSendAmount(SOLVER_ONCHAIN_RAIL, req.raw, req.amount);
|
|
1619
|
+
const payoutPkScript = l1ScriptForAddress(address, deps.l1Network);
|
|
1620
|
+
const rendezvous = await rendezvousFor(amount);
|
|
1621
|
+
if (!rendezvous) {
|
|
1622
|
+
throw new Error(
|
|
1623
|
+
`${SOLVER_ONCHAIN_RAIL}: no solver serves arkade:BTC -> onchain:BTC at ${amount} sats`
|
|
1624
|
+
);
|
|
1625
|
+
}
|
|
1626
|
+
const negotiated = await deps.connect(
|
|
1627
|
+
rendezvous,
|
|
1628
|
+
(transport) => requestOnchainSend(ctx.wallet, deps.arkServerUrl, transport, {
|
|
1629
|
+
amount,
|
|
1630
|
+
amountSide: "to",
|
|
1631
|
+
payoutPubkey: deps.payoutPubkey,
|
|
1632
|
+
...deps.emulatorPubkey ? { emulatorPubkey: deps.emulatorPubkey } : {}
|
|
1633
|
+
})
|
|
1634
|
+
);
|
|
1635
|
+
if (negotiated.l1Network !== deps.l1Network) {
|
|
1636
|
+
throw new Error(
|
|
1637
|
+
`${SOLVER_ONCHAIN_RAIL}: rail built for ${deps.l1Network} but the swap was negotiated on ${negotiated.l1Network}`
|
|
1638
|
+
);
|
|
1639
|
+
}
|
|
1640
|
+
const swap = { ...negotiated, rendezvous, payoutPkScript };
|
|
1641
|
+
return {
|
|
1642
|
+
railId: SOLVER_ONCHAIN_RAIL,
|
|
1643
|
+
amount,
|
|
1644
|
+
fee: swap.fundAmount - amount,
|
|
1645
|
+
total: swap.fundAmount,
|
|
1646
|
+
meta: {
|
|
1647
|
+
rfqId: swap.rfqId,
|
|
1648
|
+
validUntil: swap.quote.valid_until,
|
|
1649
|
+
htlcAddress: swap.htlc.address,
|
|
1650
|
+
minConfirmations: swap.minConfirmations,
|
|
1651
|
+
solverPubkey: rendezvous.solverPubkey,
|
|
1652
|
+
// The claim tx's fee comes out of the HTLC output at a rate
|
|
1653
|
+
// not knowable now, so `amount` is the payout, not the net.
|
|
1654
|
+
claimFeeDeductedFromPayout: true
|
|
1655
|
+
},
|
|
1656
|
+
send: async () => makeHandle(SOLVER_ONCHAIN_RAIL, async (emit) => {
|
|
1657
|
+
assertFundable({
|
|
1658
|
+
quote: swap.quote,
|
|
1659
|
+
now: Math.floor(Date.now() / 1e3),
|
|
1660
|
+
onchain: {
|
|
1661
|
+
htlcLocktime: swap.htlcParams.refundLocktime,
|
|
1662
|
+
minConfirmations: swap.minConfirmations,
|
|
1663
|
+
direction: "send"
|
|
1664
|
+
}
|
|
1665
|
+
});
|
|
1666
|
+
await deps.persist(swap);
|
|
1667
|
+
await ctx.wallet.send({
|
|
1668
|
+
address: swap.address,
|
|
1669
|
+
amount: swap.fundAmount
|
|
1670
|
+
});
|
|
1671
|
+
emit({ status: "sent" });
|
|
1672
|
+
const result = { railId: SOLVER_ONCHAIN_RAIL, swapId: swap.rfqId };
|
|
1673
|
+
if (!deps.awaitSettlement) return result;
|
|
1674
|
+
let txid;
|
|
1675
|
+
try {
|
|
1676
|
+
({ txid } = await deps.awaitSettlement(swap));
|
|
1677
|
+
} catch (e) {
|
|
1678
|
+
console.warn(
|
|
1679
|
+
`${SOLVER_ONCHAIN_RAIL}: settlement watch failed; the payment is sent`,
|
|
1680
|
+
e
|
|
1681
|
+
);
|
|
1682
|
+
return result;
|
|
1683
|
+
}
|
|
1684
|
+
const settled = { ...result, txid };
|
|
1685
|
+
emit({ status: "settled", result: settled });
|
|
1686
|
+
return settled;
|
|
1687
|
+
})
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
};
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
// src/payment/solverLightning.ts
|
|
1694
|
+
import { assertNoAssets as assertNoAssets2, assetsOf as assetsOf2, invoiceTarget, makeHandle as makeHandle2 } from "@arkade-os/sdk";
|
|
1695
|
+
var SOLVER_LIGHTNING_RAIL = "solver-lightning";
|
|
1696
|
+
var factsOf = (raw, decode, now) => {
|
|
1697
|
+
const invoice = invoiceTarget(raw);
|
|
1698
|
+
if (!invoice) return void 0;
|
|
1699
|
+
let facts;
|
|
1700
|
+
try {
|
|
1701
|
+
facts = decode(invoice);
|
|
1702
|
+
} catch {
|
|
1703
|
+
return void 0;
|
|
1704
|
+
}
|
|
1705
|
+
if (!Number.isInteger(facts.amountSats) || facts.amountSats <= 0) return void 0;
|
|
1706
|
+
if (facts.expiresAt <= now) return void 0;
|
|
1707
|
+
return facts;
|
|
1708
|
+
};
|
|
1709
|
+
var solverLightningRendezvous = (markets, amountSats, fallbackEmulatorPubkey) => solverRendezvous(markets, "lightning", amountSats, fallbackEmulatorPubkey);
|
|
1710
|
+
function solverLightningRail(deps) {
|
|
1711
|
+
const rendezvousFor = async (amountSats) => solverLightningRendezvous(await deps.discover(), amountSats, deps.fallbackEmulatorPubkey);
|
|
1712
|
+
return {
|
|
1713
|
+
id: SOLVER_LIGHTNING_RAIL,
|
|
1714
|
+
match: (req) => invoiceTarget(req.raw) !== void 0,
|
|
1715
|
+
available: async (req) => {
|
|
1716
|
+
if (assetsOf2(req).length > 0) return false;
|
|
1717
|
+
const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
|
|
1718
|
+
if (!facts) return false;
|
|
1719
|
+
if (req.amount !== void 0 && req.amount !== facts.amountSats) return false;
|
|
1720
|
+
return await rendezvousFor(facts.amountSats) !== void 0;
|
|
1721
|
+
},
|
|
1722
|
+
quote: async (req, ctx) => {
|
|
1723
|
+
assertNoAssets2(SOLVER_LIGHTNING_RAIL, req);
|
|
1724
|
+
const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
|
|
1725
|
+
if (!facts) {
|
|
1726
|
+
throw new Error(
|
|
1727
|
+
`${SOLVER_LIGHTNING_RAIL}: the request carries no payable BOLT11 invoice (amountless, expired, or undecodable)`
|
|
1728
|
+
);
|
|
1729
|
+
}
|
|
1730
|
+
if (req.amount !== void 0 && req.amount !== facts.amountSats) {
|
|
1731
|
+
throw new Error(
|
|
1732
|
+
`${SOLVER_LIGHTNING_RAIL}: the request names ${req.amount} sats but the invoice is for ${facts.amountSats} \u2014 the payee is paid the invoice`
|
|
1733
|
+
);
|
|
1734
|
+
}
|
|
1735
|
+
const rendezvous = await rendezvousFor(facts.amountSats);
|
|
1736
|
+
if (!rendezvous) {
|
|
1737
|
+
throw new Error(
|
|
1738
|
+
`${SOLVER_LIGHTNING_RAIL}: no solver serves arkade:BTC -> lightning:BTC at ${facts.amountSats} sats`
|
|
1739
|
+
);
|
|
1740
|
+
}
|
|
1741
|
+
const negotiated = await deps.connect(
|
|
1742
|
+
rendezvous,
|
|
1743
|
+
(transport) => requestLightningSend(ctx.wallet, deps.arkServerUrl, transport, {
|
|
1744
|
+
invoice: facts,
|
|
1745
|
+
...deps.emulatorPubkey ? { emulatorPubkey: deps.emulatorPubkey } : {}
|
|
1746
|
+
})
|
|
1747
|
+
);
|
|
1748
|
+
const swap = { ...negotiated, invoice: facts, rendezvous };
|
|
1749
|
+
return {
|
|
1750
|
+
railId: SOLVER_LIGHTNING_RAIL,
|
|
1751
|
+
// `requestLightningSend` refuses a quote that reprices the
|
|
1752
|
+
// invoice, so the spread is a fee on top.
|
|
1753
|
+
amount: facts.amountSats,
|
|
1754
|
+
fee: swap.fundAmount - facts.amountSats,
|
|
1755
|
+
total: swap.fundAmount,
|
|
1756
|
+
meta: {
|
|
1757
|
+
rfqId: swap.rfqId,
|
|
1758
|
+
validUntil: swap.quote.valid_until,
|
|
1759
|
+
paymentHash: facts.paymentHash,
|
|
1760
|
+
invoiceExpiresAt: facts.expiresAt,
|
|
1761
|
+
solverPubkey: rendezvous.solverPubkey
|
|
1762
|
+
},
|
|
1763
|
+
send: async () => makeHandle2(SOLVER_LIGHTNING_RAIL, async (emit) => {
|
|
1764
|
+
assertFundable({
|
|
1765
|
+
quote: swap.quote,
|
|
1766
|
+
invoiceExpiresAt: facts.expiresAt,
|
|
1767
|
+
now: Math.floor(Date.now() / 1e3)
|
|
1768
|
+
});
|
|
1769
|
+
await deps.persist(swap);
|
|
1770
|
+
await ctx.wallet.send({
|
|
1771
|
+
address: swap.address,
|
|
1772
|
+
amount: swap.fundAmount
|
|
1773
|
+
});
|
|
1774
|
+
emit({ status: "sent" });
|
|
1775
|
+
const result = { railId: SOLVER_LIGHTNING_RAIL, swapId: swap.rfqId };
|
|
1776
|
+
if (!deps.awaitSettlement) return result;
|
|
1777
|
+
let preimage;
|
|
1778
|
+
try {
|
|
1779
|
+
({ preimage } = await deps.awaitSettlement(swap));
|
|
1780
|
+
} catch (e) {
|
|
1781
|
+
console.warn(
|
|
1782
|
+
`${SOLVER_LIGHTNING_RAIL}: settlement watch failed; the payment is sent`,
|
|
1783
|
+
e
|
|
1784
|
+
);
|
|
1785
|
+
return result;
|
|
1786
|
+
}
|
|
1787
|
+
const settled = { ...result, ...preimage !== void 0 && { preimage } };
|
|
1788
|
+
emit({ status: "settled", result: settled });
|
|
1789
|
+
return settled;
|
|
1790
|
+
})
|
|
1791
|
+
};
|
|
1792
|
+
}
|
|
1793
|
+
};
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
// src/payment/crossAsset.ts
|
|
1797
|
+
import {
|
|
1798
|
+
arkTarget,
|
|
1799
|
+
asset as assetExt,
|
|
1800
|
+
assetsOf as assetsOf3,
|
|
1801
|
+
makeHandle as makeHandle3,
|
|
1802
|
+
resolveAssetAmount
|
|
1803
|
+
} from "@arkade-os/sdk";
|
|
1804
|
+
var CROSS_ASSET_RAIL = "cross-asset";
|
|
1805
|
+
var DEFAULT_CARRIER_SATS = 330;
|
|
1806
|
+
var parseAssetId = (assetId) => {
|
|
1807
|
+
try {
|
|
1808
|
+
return assetExt.AssetId.fromString(assetId);
|
|
1809
|
+
} catch {
|
|
1810
|
+
return void 0;
|
|
1811
|
+
}
|
|
1812
|
+
};
|
|
1813
|
+
function crossAssetRail(deps) {
|
|
1814
|
+
const planFor = async (asset2) => {
|
|
1815
|
+
const markets = await deps.discover();
|
|
1816
|
+
const found = findMarket(markets, BTC_ASSET_ID, asset2.assetId);
|
|
1817
|
+
const market = found?.market;
|
|
1818
|
+
if (!market) return void 0;
|
|
1819
|
+
const plan = await deps.quote(market, found.give, asset2.amount);
|
|
1820
|
+
const [balance, dust] = await Promise.all([deps.btcBalance(), deps.dust()]);
|
|
1821
|
+
return { plan, error: validatePlan(plan, balance, dust) };
|
|
1822
|
+
};
|
|
1823
|
+
return {
|
|
1824
|
+
id: CROSS_ASSET_RAIL,
|
|
1825
|
+
match: (req) => arkTarget(req.raw) !== void 0,
|
|
1826
|
+
available: async (req) => {
|
|
1827
|
+
const assets = assetsOf3(req);
|
|
1828
|
+
if (assets.length !== 1) return false;
|
|
1829
|
+
const [asset2] = assets;
|
|
1830
|
+
if (asset2.assetId === BTC_ASSET_ID) return false;
|
|
1831
|
+
if (typeof asset2.amount !== "bigint" || asset2.amount <= 0n) return false;
|
|
1832
|
+
if (!parseAssetId(asset2.assetId)) return false;
|
|
1833
|
+
const planned = await planFor(asset2);
|
|
1834
|
+
return planned !== void 0 && planned.error === void 0;
|
|
1835
|
+
},
|
|
1836
|
+
quote: async (req, ctx) => {
|
|
1837
|
+
const payTo = arkTarget(req.raw);
|
|
1838
|
+
const asset2 = resolveAssetAmount(CROSS_ASSET_RAIL, req);
|
|
1839
|
+
const wantAsset = parseAssetId(asset2.assetId);
|
|
1840
|
+
if (!wantAsset) {
|
|
1841
|
+
throw new Error(
|
|
1842
|
+
`${CROSS_ASSET_RAIL}: ${asset2.assetId} is not an asset id (expected 34 bytes of hex)`
|
|
1843
|
+
);
|
|
1844
|
+
}
|
|
1845
|
+
const planned = await planFor(asset2);
|
|
1846
|
+
if (!planned) {
|
|
1847
|
+
throw new Error(`${CROSS_ASSET_RAIL}: no market swaps BTC into ${asset2.assetId}`);
|
|
1848
|
+
}
|
|
1849
|
+
if (planned.error) {
|
|
1850
|
+
throw new Error(
|
|
1851
|
+
`${CROSS_ASSET_RAIL}: cannot swap into ${asset2.assetId} \u2014 ${planned.error}`
|
|
1852
|
+
);
|
|
1853
|
+
}
|
|
1854
|
+
const { plan } = planned;
|
|
1855
|
+
if (!Number.isSafeInteger(Number(plan.deposit.atomic))) {
|
|
1856
|
+
throw new Error(
|
|
1857
|
+
`${CROSS_ASSET_RAIL}: deposit of ${plan.deposit.atomic} does not fit a JS number`
|
|
1858
|
+
);
|
|
1859
|
+
}
|
|
1860
|
+
const depositSats = Number(plan.deposit.atomic);
|
|
1861
|
+
const carrier = deps.carrierSats ?? DEFAULT_CARRIER_SATS;
|
|
1862
|
+
return {
|
|
1863
|
+
railId: CROSS_ASSET_RAIL,
|
|
1864
|
+
// OPEN QUESTION for review: `total = amount + fee` forces the
|
|
1865
|
+
// purchase price into `fee`, which reads as a service charge.
|
|
1866
|
+
// A third field instead? `assets.spent` labels it correctly.
|
|
1867
|
+
amount: carrier,
|
|
1868
|
+
fee: depositSats,
|
|
1869
|
+
total: depositSats + carrier,
|
|
1870
|
+
assets: {
|
|
1871
|
+
delivered: asset2,
|
|
1872
|
+
spent: { assetId: BTC_ASSET_ID, amount: plan.deposit.atomic }
|
|
1873
|
+
},
|
|
1874
|
+
meta: {
|
|
1875
|
+
market: plan.market.pair,
|
|
1876
|
+
priceDisplay: plan.priceDisplay,
|
|
1877
|
+
give: plan.give
|
|
1878
|
+
},
|
|
1879
|
+
send: async () => makeHandle3(CROSS_ASSET_RAIL, async (emit) => {
|
|
1880
|
+
const offer = await createOffer(ctx.wallet, deps.arkServerUrl, {
|
|
1881
|
+
wantAmount: asset2.amount,
|
|
1882
|
+
wantAsset,
|
|
1883
|
+
...deps.emulatorPubkey ? { emulatorPubkey: deps.emulatorPubkey } : {}
|
|
1884
|
+
});
|
|
1885
|
+
const swap = {
|
|
1886
|
+
phase: "quoted",
|
|
1887
|
+
offerHex: offer.offerHex,
|
|
1888
|
+
address: offer.address,
|
|
1889
|
+
swapPkScript: offer.swapPkScript,
|
|
1890
|
+
depositSats,
|
|
1891
|
+
asset: asset2,
|
|
1892
|
+
payTo,
|
|
1893
|
+
plan
|
|
1894
|
+
};
|
|
1895
|
+
await deps.persist(swap);
|
|
1896
|
+
await ctx.wallet.send({
|
|
1897
|
+
address: offer.address,
|
|
1898
|
+
amount: depositSats,
|
|
1899
|
+
extensions: [offer.extension]
|
|
1900
|
+
});
|
|
1901
|
+
emit({ status: "sent" });
|
|
1902
|
+
await deps.awaitFill(swap);
|
|
1903
|
+
await deps.persist({ ...swap, phase: "filled" });
|
|
1904
|
+
await deps.persist({ ...swap, phase: "paying" });
|
|
1905
|
+
const txid = await ctx.wallet.send({
|
|
1906
|
+
address: payTo,
|
|
1907
|
+
amount: carrier,
|
|
1908
|
+
assets: [asset2]
|
|
1909
|
+
});
|
|
1910
|
+
await deps.persist({ ...swap, phase: "settled", txid });
|
|
1911
|
+
const result = {
|
|
1912
|
+
railId: CROSS_ASSET_RAIL,
|
|
1913
|
+
txid,
|
|
1914
|
+
swapId: offer.offerHex
|
|
1915
|
+
};
|
|
1916
|
+
emit({ status: "settled", result });
|
|
1917
|
+
return result;
|
|
1918
|
+
})
|
|
1919
|
+
};
|
|
1920
|
+
}
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
// src/reveal.ts
|
|
1925
|
+
import { base64 as base643, hex as hex9 } from "@scure/base";
|
|
1495
1926
|
import { ripemd160 } from "@noble/hashes/legacy.js";
|
|
1496
|
-
import { sha256 as
|
|
1927
|
+
import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
|
|
1928
|
+
import { ArkAddress as ArkAddress4 } from "@arkade-os/sdk";
|
|
1929
|
+
var CovclaimdRevealError = class extends Error {
|
|
1930
|
+
name = "CovclaimdRevealError";
|
|
1931
|
+
status;
|
|
1932
|
+
detail;
|
|
1933
|
+
retryable;
|
|
1934
|
+
constructor(what, status, detail) {
|
|
1935
|
+
super(`covclaimd ${what} failed: ${status || "no response"} ${detail}`.trimEnd());
|
|
1936
|
+
this.status = status;
|
|
1937
|
+
this.detail = detail;
|
|
1938
|
+
this.retryable = status === 0 || status === 429 || status >= 500;
|
|
1939
|
+
}
|
|
1940
|
+
};
|
|
1941
|
+
var decodeKey = (value, field) => {
|
|
1942
|
+
if (typeof value !== "string") throw new Error(`covclaimd info: ${field} is not a string`);
|
|
1943
|
+
let bytes;
|
|
1944
|
+
try {
|
|
1945
|
+
bytes = hex9.decode(value);
|
|
1946
|
+
} catch {
|
|
1947
|
+
throw new Error(`covclaimd info: ${field} is not hex`);
|
|
1948
|
+
}
|
|
1949
|
+
if (bytes.length !== 33) {
|
|
1950
|
+
throw new Error(`covclaimd info: ${field} must be 33-byte compressed, got ${bytes.length}`);
|
|
1951
|
+
}
|
|
1952
|
+
return bytes;
|
|
1953
|
+
};
|
|
1954
|
+
var LOOPBACK = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
1955
|
+
var assertTransportSecure = (baseUrl, allowInsecureHttp) => {
|
|
1956
|
+
const { protocol, hostname } = new URL(baseUrl);
|
|
1957
|
+
if (protocol === "https:" || allowInsecureHttp) return;
|
|
1958
|
+
if (protocol === "http:" && LOOPBACK.has(hostname)) return;
|
|
1959
|
+
throw new Error(
|
|
1960
|
+
`covclaimd URL must be https (got ${protocol}//${hostname}): the key it serves is the one the preimage gets sealed to. Pass allowInsecureHttp to override.`
|
|
1961
|
+
);
|
|
1962
|
+
};
|
|
1963
|
+
var covclaimdClient = (baseUrl, options = {}) => {
|
|
1964
|
+
assertTransportSecure(baseUrl, options.allowInsecureHttp === true);
|
|
1965
|
+
const url = baseUrl.replace(/\/+$/, "");
|
|
1966
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
1967
|
+
const timeoutMs = options.timeoutMs ?? 3e4;
|
|
1968
|
+
const send = async (what, path, init) => {
|
|
1969
|
+
let response;
|
|
1970
|
+
try {
|
|
1971
|
+
response = await fetchImpl(`${url}${path}`, {
|
|
1972
|
+
...init,
|
|
1973
|
+
// a redirect would move the key fetch off the vetted origin
|
|
1974
|
+
redirect: "error",
|
|
1975
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
1976
|
+
});
|
|
1977
|
+
} catch (error) {
|
|
1978
|
+
throw new CovclaimdRevealError(what, 0, String(error));
|
|
1979
|
+
}
|
|
1980
|
+
if (!response.ok) {
|
|
1981
|
+
throw new CovclaimdRevealError(what, response.status, await response.text());
|
|
1982
|
+
}
|
|
1983
|
+
return response;
|
|
1984
|
+
};
|
|
1985
|
+
const readJson = async (what, response) => {
|
|
1986
|
+
const body = await response.text();
|
|
1987
|
+
try {
|
|
1988
|
+
return JSON.parse(body);
|
|
1989
|
+
} catch {
|
|
1990
|
+
throw new CovclaimdRevealError(
|
|
1991
|
+
what,
|
|
1992
|
+
response.status,
|
|
1993
|
+
`non-JSON body: ${body.slice(0, 200)}`
|
|
1994
|
+
);
|
|
1995
|
+
}
|
|
1996
|
+
};
|
|
1997
|
+
return {
|
|
1998
|
+
async info() {
|
|
1999
|
+
const response = await send("info", "/v1/preimage/covclaimd-pubkey", {
|
|
2000
|
+
method: "GET"
|
|
2001
|
+
});
|
|
2002
|
+
const body = await readJson("info", response);
|
|
2003
|
+
return {
|
|
2004
|
+
covclaimdPubkey: decodeKey(body?.covclaimd_pub_key, "covclaimd_pub_key"),
|
|
2005
|
+
emulatorPubkey: hex9.encode(decodeKey(body?.emulator_pub_key, "emulator_pub_key"))
|
|
2006
|
+
};
|
|
2007
|
+
},
|
|
2008
|
+
async reveal(params) {
|
|
2009
|
+
await send("reveal", "/v1/reveal", {
|
|
2010
|
+
method: "POST",
|
|
2011
|
+
headers: { "content-type": "application/json" },
|
|
2012
|
+
body: JSON.stringify({
|
|
2013
|
+
swap_address: params.swapAddress,
|
|
2014
|
+
packet: { ciphertext: params.ciphertext, arkade_script: params.arkadeScript },
|
|
2015
|
+
taptree: params.taptree
|
|
2016
|
+
})
|
|
2017
|
+
});
|
|
2018
|
+
}
|
|
2019
|
+
};
|
|
2020
|
+
};
|
|
2021
|
+
function revealFieldsFromScript(script) {
|
|
2022
|
+
if (!script.nonInteractiveClaimArkadeScript) {
|
|
2023
|
+
throw new Error("this covenant has no non-interactive claim leaf to reveal against");
|
|
2024
|
+
}
|
|
2025
|
+
return {
|
|
2026
|
+
arkadeScript: base643.encode(script.nonInteractiveClaimArkadeScript),
|
|
2027
|
+
taptree: hex9.encode(script.encode())
|
|
2028
|
+
};
|
|
2029
|
+
}
|
|
2030
|
+
async function revealClaimPacket(client, input) {
|
|
2031
|
+
const fields = revealFieldsFromScript(input.script);
|
|
2032
|
+
if (hex9.encode(ArkAddress4.decode(input.address).pkScript) !== hex9.encode(input.script.pkScript)) {
|
|
2033
|
+
throw new Error("address does not belong to this covenant");
|
|
2034
|
+
}
|
|
2035
|
+
if (hex9.encode(ripemd160(sha2562(input.preimage))) !== hex9.encode(input.script.options.preimageHash)) {
|
|
2036
|
+
throw new Error("preimage does not match the covenant's payment hash");
|
|
2037
|
+
}
|
|
2038
|
+
const { ciphertext } = await sealClaimPacket({
|
|
2039
|
+
preimage: input.preimage,
|
|
2040
|
+
covclaimdPubkey: (await client.info()).covclaimdPubkey
|
|
2041
|
+
});
|
|
2042
|
+
await client.reveal({ swapAddress: input.address, ciphertext, ...fields });
|
|
2043
|
+
return { ciphertext };
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
// src/claim.ts
|
|
2047
|
+
import { hex as hex11 } from "@scure/base";
|
|
2048
|
+
import { ripemd160 as ripemd1602 } from "@noble/hashes/legacy.js";
|
|
2049
|
+
import { sha256 as sha2564 } from "@noble/hashes/sha2.js";
|
|
1497
2050
|
import {
|
|
1498
2051
|
CSVMultisigTapscript as CSVMultisigTapscript2,
|
|
1499
2052
|
claimWithPreimageIdentity,
|
|
@@ -1501,8 +2054,8 @@ import {
|
|
|
1501
2054
|
} from "@arkade-os/sdk";
|
|
1502
2055
|
|
|
1503
2056
|
// src/refund.ts
|
|
1504
|
-
import { base64 as
|
|
1505
|
-
import { sha256 as
|
|
2057
|
+
import { base64 as base644, hex as hex10 } from "@scure/base";
|
|
2058
|
+
import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
|
|
1506
2059
|
import {
|
|
1507
2060
|
CSVMultisigTapscript,
|
|
1508
2061
|
ConditionWitness,
|
|
@@ -1559,7 +2112,7 @@ var LockupNeedsRecoveryError = class extends Error {
|
|
|
1559
2112
|
}
|
|
1560
2113
|
};
|
|
1561
2114
|
async function findLockupVtxos(indexer, swapPkScript) {
|
|
1562
|
-
const scripts = [
|
|
2115
|
+
const scripts = [hex10.encode(swapPkScript)];
|
|
1563
2116
|
const [spendable, recoverable] = await Promise.all([
|
|
1564
2117
|
indexer.getVtxos({ scripts, spendableOnly: true }),
|
|
1565
2118
|
indexer.getVtxos({ scripts, recoverableOnly: true })
|
|
@@ -1585,13 +2138,13 @@ async function findLockupVtxos(indexer, swapPkScript) {
|
|
|
1585
2138
|
}
|
|
1586
2139
|
return out;
|
|
1587
2140
|
}
|
|
1588
|
-
var hashesTo = (candidate, paymentHash) =>
|
|
2141
|
+
var hashesTo = (candidate, paymentHash) => hex10.encode(sha2563(candidate)) === paymentHash;
|
|
1589
2142
|
var candidateWitnessItems = (tx, inputIndex) => [
|
|
1590
2143
|
...getArkPsbtFields(tx, inputIndex, ConditionWitness).flat(),
|
|
1591
2144
|
...tx.getInput(inputIndex).finalScriptWitness ?? []
|
|
1592
2145
|
];
|
|
1593
2146
|
async function readLockupFate(indexer, input) {
|
|
1594
|
-
const { vtxos } = await indexer.getVtxos({ scripts: [
|
|
2147
|
+
const { vtxos } = await indexer.getVtxos({ scripts: [hex10.encode(input.swapPkScript)] });
|
|
1595
2148
|
const all = vtxos ?? [];
|
|
1596
2149
|
if (all.length === 0) return { fate: "unknown" };
|
|
1597
2150
|
const exited = all.filter((vtxo) => vtxo.isUnrolled && !hasTerminalSpend(vtxo));
|
|
@@ -1618,7 +2171,7 @@ async function readLockupFate(indexer, input) {
|
|
|
1618
2171
|
for (const raw of txs) {
|
|
1619
2172
|
let tx;
|
|
1620
2173
|
try {
|
|
1621
|
-
tx = Transaction3.fromPSBT(
|
|
2174
|
+
tx = Transaction3.fromPSBT(base644.decode(raw));
|
|
1622
2175
|
} catch {
|
|
1623
2176
|
continue;
|
|
1624
2177
|
}
|
|
@@ -1626,7 +2179,7 @@ async function readLockupFate(indexer, input) {
|
|
|
1626
2179
|
for (let i = 0; i < tx.inputsLength; i++) {
|
|
1627
2180
|
const spent = tx.getInput(i);
|
|
1628
2181
|
if (!spent.txid) continue;
|
|
1629
|
-
const txid =
|
|
2182
|
+
const txid = hex10.encode(spent.txid);
|
|
1630
2183
|
if (!all.some((vtxo) => vtxo.txid === txid && vtxo.vout === spent.index)) continue;
|
|
1631
2184
|
for (const candidate of candidateWitnessItems(tx, i)) {
|
|
1632
2185
|
if (hashesTo(candidate, input.paymentHash)) {
|
|
@@ -1655,7 +2208,7 @@ async function pushRefundWithoutReceiver(ark, input) {
|
|
|
1655
2208
|
const info = await ark.getInfo();
|
|
1656
2209
|
let serverUnrollScript;
|
|
1657
2210
|
try {
|
|
1658
|
-
serverUnrollScript = CSVMultisigTapscript.decode(
|
|
2211
|
+
serverUnrollScript = CSVMultisigTapscript.decode(hex10.decode(info.checkpointTapscript));
|
|
1659
2212
|
} catch {
|
|
1660
2213
|
throw new Error("invalid checkpointTapscript from the Arkade server");
|
|
1661
2214
|
}
|
|
@@ -1675,8 +2228,8 @@ async function pushRefundWithoutReceiver(ark, input) {
|
|
|
1675
2228
|
);
|
|
1676
2229
|
const signedArkTx = await input.sender.sign(arkTx);
|
|
1677
2230
|
const submitted = await ark.submitTx(
|
|
1678
|
-
|
|
1679
|
-
checkpoints.map((c) =>
|
|
2231
|
+
base644.encode(signedArkTx.toPSBT()),
|
|
2232
|
+
checkpoints.map((c) => base644.encode(c.toPSBT()))
|
|
1680
2233
|
);
|
|
1681
2234
|
assertSubmittedArkTxid(submitted, signedArkTx, "refundWithoutReceiver");
|
|
1682
2235
|
const matched = matchServerCheckpoints(
|
|
@@ -1686,7 +2239,7 @@ async function pushRefundWithoutReceiver(ark, input) {
|
|
|
1686
2239
|
);
|
|
1687
2240
|
const finalCheckpoints = await Promise.all(
|
|
1688
2241
|
matched.map(
|
|
1689
|
-
async ({ server }) =>
|
|
2242
|
+
async ({ server }) => base644.encode((await input.sender.sign(server, [0])).toPSBT())
|
|
1690
2243
|
)
|
|
1691
2244
|
);
|
|
1692
2245
|
await ark.finalizeTx(submitted.arkTxid, finalCheckpoints);
|
|
@@ -1781,13 +2334,13 @@ async function pushClaim(ark, input) {
|
|
|
1781
2334
|
}
|
|
1782
2335
|
}
|
|
1783
2336
|
const committed = input.script.options.preimageHash;
|
|
1784
|
-
if (
|
|
2337
|
+
if (hex11.encode(ripemd1602(sha2564(input.preimage))) !== hex11.encode(committed)) {
|
|
1785
2338
|
throw new Error("preimage does not match the covenant's payment hash");
|
|
1786
2339
|
}
|
|
1787
2340
|
const info = await ark.getInfo();
|
|
1788
2341
|
let serverUnrollScript;
|
|
1789
2342
|
try {
|
|
1790
|
-
serverUnrollScript = CSVMultisigTapscript2.decode(
|
|
2343
|
+
serverUnrollScript = CSVMultisigTapscript2.decode(hex11.decode(info.checkpointTapscript));
|
|
1791
2344
|
} catch {
|
|
1792
2345
|
throw new Error("invalid checkpointTapscript from the Arkade server");
|
|
1793
2346
|
}
|
|
@@ -1906,7 +2459,7 @@ function arkadeRefunder(deps) {
|
|
|
1906
2459
|
}
|
|
1907
2460
|
|
|
1908
2461
|
// src/swapManager.ts
|
|
1909
|
-
import { hex as
|
|
2462
|
+
import { hex as hex12 } from "@scure/base";
|
|
1910
2463
|
function nextOnchainAction(input) {
|
|
1911
2464
|
switch (input.phase.phase) {
|
|
1912
2465
|
case "unfunded":
|
|
@@ -2354,7 +2907,7 @@ var RfqSwapManager = class {
|
|
|
2354
2907
|
// ── internals ────────────────────────────────────────────────────────────
|
|
2355
2908
|
track(swap) {
|
|
2356
2909
|
this.monitored.set(swap.rfqId, swap);
|
|
2357
|
-
this.byLockupScript.set(
|
|
2910
|
+
this.byLockupScript.set(hex12.encode(swap.lockupPkScript), swap);
|
|
2358
2911
|
}
|
|
2359
2912
|
/** Drops the swap from BOTH indexes. The event index is the one that stops
|
|
2360
2913
|
* a late event finding a swap that is gone; `pollSwap`'s own
|
|
@@ -2363,7 +2916,7 @@ var RfqSwapManager = class {
|
|
|
2363
2916
|
* them from silently re-driving a cancelled swap. */
|
|
2364
2917
|
untrack(rfqId) {
|
|
2365
2918
|
const swap = this.monitored.get(rfqId);
|
|
2366
|
-
if (swap) this.byLockupScript.delete(
|
|
2919
|
+
if (swap) this.byLockupScript.delete(hex12.encode(swap.lockupPkScript));
|
|
2367
2920
|
this.monitored.delete(rfqId);
|
|
2368
2921
|
this.refundRefused.delete(rfqId);
|
|
2369
2922
|
this.lastClaimError.delete(rfqId);
|
|
@@ -2425,7 +2978,7 @@ var RfqSwapManager = class {
|
|
|
2425
2978
|
if (!lockup) {
|
|
2426
2979
|
try {
|
|
2427
2980
|
const [existing] = await contracts.getContracts({
|
|
2428
|
-
script:
|
|
2981
|
+
script: hex12.encode(swap.lockupPkScript)
|
|
2429
2982
|
});
|
|
2430
2983
|
if (existing) {
|
|
2431
2984
|
this.registered.set(swap.rfqId, true);
|
|
@@ -2444,13 +2997,13 @@ var RfqSwapManager = class {
|
|
|
2444
2997
|
);
|
|
2445
2998
|
return;
|
|
2446
2999
|
}
|
|
2447
|
-
const script =
|
|
2448
|
-
if (script !==
|
|
3000
|
+
const script = hex12.encode(lockup.script.pkScript);
|
|
3001
|
+
if (script !== hex12.encode(swap.lockupPkScript)) {
|
|
2449
3002
|
this.registered.set(swap.rfqId, false);
|
|
2450
3003
|
this.emitFailed(
|
|
2451
3004
|
swap,
|
|
2452
3005
|
new Error(
|
|
2453
|
-
`swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${
|
|
3006
|
+
`swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${hex12.encode(swap.lockupPkScript)}`
|
|
2454
3007
|
)
|
|
2455
3008
|
);
|
|
2456
3009
|
return;
|
|
@@ -2469,7 +3022,7 @@ var RfqSwapManager = class {
|
|
|
2469
3022
|
* script for its whole life. Best-effort — the swap is over either way. */
|
|
2470
3023
|
retireContract(swap) {
|
|
2471
3024
|
if (!this.deps.contracts || !this.registered.get(swap.rfqId)) return;
|
|
2472
|
-
void this.deps.contracts.setContractWatchState(
|
|
3025
|
+
void this.deps.contracts.setContractWatchState(hex12.encode(swap.lockupPkScript), "retained").catch((error) => this.emitFailed(swap, error));
|
|
2473
3026
|
}
|
|
2474
3027
|
arm() {
|
|
2475
3028
|
if (!this.running) return;
|
|
@@ -2943,9 +3496,9 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
|
2943
3496
|
|
|
2944
3497
|
// src/activity.ts
|
|
2945
3498
|
import {
|
|
2946
|
-
ArkAddress as
|
|
3499
|
+
ArkAddress as ArkAddress5
|
|
2947
3500
|
} from "@arkade-os/sdk";
|
|
2948
|
-
import { hex as
|
|
3501
|
+
import { hex as hex13 } from "@scure/base";
|
|
2949
3502
|
var LABELS = {
|
|
2950
3503
|
lightning_send: "Lightning send",
|
|
2951
3504
|
lightning_receive: "Lightning receive",
|
|
@@ -3020,7 +3573,7 @@ async function activityInputOf(record, indexer) {
|
|
|
3020
3573
|
async function lockupTxids(indexer, record, wantFunding) {
|
|
3021
3574
|
let script;
|
|
3022
3575
|
try {
|
|
3023
|
-
script =
|
|
3576
|
+
script = hex13.encode(ArkAddress5.decode(record.lockupAddress).pkScript);
|
|
3024
3577
|
} catch {
|
|
3025
3578
|
return [];
|
|
3026
3579
|
}
|
|
@@ -3041,6 +3594,8 @@ export {
|
|
|
3041
3594
|
ARKADE_BTC,
|
|
3042
3595
|
AddressMismatch,
|
|
3043
3596
|
BTC_ASSET_ID,
|
|
3597
|
+
CROSS_ASSET_RAIL,
|
|
3598
|
+
CovclaimdRevealError,
|
|
3044
3599
|
InMemoryAssetSwapRepository,
|
|
3045
3600
|
IndexedDbAssetSwapRepository,
|
|
3046
3601
|
LIGHTNING_BTC,
|
|
@@ -3073,6 +3628,8 @@ export {
|
|
|
3073
3628
|
RfqSwapManager,
|
|
3074
3629
|
RfqSwapOriginRequired,
|
|
3075
3630
|
SOLO_REFUND_HEADROOM_SECONDS,
|
|
3631
|
+
SOLVER_LIGHTNING_RAIL,
|
|
3632
|
+
SOLVER_ONCHAIN_RAIL,
|
|
3076
3633
|
SWAP_LOCKUP_CONTRACT_KIND,
|
|
3077
3634
|
SWAP_LOCKUP_CONTRACT_LABEL,
|
|
3078
3635
|
SWAP_LOCKUP_CONTRACT_TYPE,
|
|
@@ -3089,13 +3646,16 @@ export {
|
|
|
3089
3646
|
buildHtlcClaim,
|
|
3090
3647
|
buildHtlcRefund,
|
|
3091
3648
|
cancelOffer,
|
|
3649
|
+
chainSourceFrom,
|
|
3092
3650
|
claimOnchainFill,
|
|
3093
3651
|
claimReceiveLockup,
|
|
3094
3652
|
classifyDepositSpend,
|
|
3095
3653
|
classifyOnchainHtlc,
|
|
3096
3654
|
classifySpend,
|
|
3655
|
+
covclaimdClient,
|
|
3097
3656
|
createOffer,
|
|
3098
3657
|
createRfqSwapRecord,
|
|
3658
|
+
crossAssetRail,
|
|
3099
3659
|
decodeOffer,
|
|
3100
3660
|
deriveLightningReceive,
|
|
3101
3661
|
deriveOnchainReceive,
|
|
@@ -3110,6 +3670,7 @@ export {
|
|
|
3110
3670
|
httpTransport,
|
|
3111
3671
|
isRfqSwapTerminal,
|
|
3112
3672
|
isRfqTerminal,
|
|
3673
|
+
l1ScriptForAddress,
|
|
3113
3674
|
lightningReceiveRequest,
|
|
3114
3675
|
lightningSendRequest,
|
|
3115
3676
|
lightningSendVtxoScript,
|
|
@@ -3140,6 +3701,8 @@ export {
|
|
|
3140
3701
|
requestOnchainSend,
|
|
3141
3702
|
restoreAssetSwaps,
|
|
3142
3703
|
retireSettledOfferContracts,
|
|
3704
|
+
revealClaimPacket,
|
|
3705
|
+
revealFieldsFromScript,
|
|
3143
3706
|
rfqClaimSecretOf,
|
|
3144
3707
|
rfqPair,
|
|
3145
3708
|
rfqSecretsProfile,
|
|
@@ -3149,6 +3712,11 @@ export {
|
|
|
3149
3712
|
sealClaimPacket,
|
|
3150
3713
|
senderIdentityForSwapRecord,
|
|
3151
3714
|
shouldRetainRfqSwap,
|
|
3715
|
+
solverLightningRail,
|
|
3716
|
+
solverLightningRendezvous,
|
|
3717
|
+
solverOnchainRail,
|
|
3718
|
+
solverOnchainRendezvous,
|
|
3719
|
+
solverRendezvous,
|
|
3152
3720
|
spendTxidsOf,
|
|
3153
3721
|
spendUpdate,
|
|
3154
3722
|
swapActivityResolver,
|