@arkade-os/swap 0.0.12 → 0.0.14

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/index.js CHANGED
@@ -65,7 +65,7 @@ import {
65
65
  unilateralRefundWithoutReceiverDelay,
66
66
  verifyLockupAddress,
67
67
  verifyReceiveInvoice
68
- } from "./chunk-XXWOODUE.js";
68
+ } from "./chunk-IFZOBTTG.js";
69
69
  import {
70
70
  InMemoryAssetSwapRepository,
71
71
  marketsCacheKey
@@ -1417,6 +1417,7 @@ async function restoreAssetSwaps(indexer, txs, existingIds, opts) {
1417
1417
  import { base64 as base642, hex as hex6 } from "@scure/base";
1418
1418
  import {
1419
1419
  ArkAddress as ArkAddress3,
1420
+ isContractVtxoEvent,
1420
1421
  RestIndexerProvider as RestIndexerProvider3,
1421
1422
  Transaction as Transaction2
1422
1423
  } from "@arkade-os/sdk";
@@ -1487,7 +1488,7 @@ async function watchOfferSwaps({
1487
1488
  }
1488
1489
  };
1489
1490
  const unsubscribe = manager.onContractEvent((event) => {
1490
- if (event.type !== "vtxo_spent") return;
1491
+ if (!isContractVtxoEvent(event) || event.type !== "vtxo_spent") return;
1491
1492
  enqueue(() => handleSpend(event));
1492
1493
  });
1493
1494
  return {
@@ -1580,7 +1581,14 @@ var solverRendezvous = (markets, payoutCorridor, amountSats, fallbackEmulatorPub
1580
1581
  };
1581
1582
 
1582
1583
  // src/payment/solverOnchain.ts
1583
- import { btcTarget, makeHandle, resolveSendAmount, tryResolveSendAmount } from "@arkade-os/sdk";
1584
+ import {
1585
+ assertNoAssets,
1586
+ assetsOf,
1587
+ btcTarget,
1588
+ makeHandle,
1589
+ resolveSendAmount,
1590
+ tryResolveSendAmount
1591
+ } from "@arkade-os/sdk";
1584
1592
  var SOLVER_ONCHAIN_RAIL = "solver-onchain";
1585
1593
  var solverOnchainRendezvous = (markets, amountSats, fallbackEmulatorPubkey) => solverRendezvous(markets, "onchain", amountSats, fallbackEmulatorPubkey);
1586
1594
  function solverOnchainRail(deps) {
@@ -1593,6 +1601,7 @@ function solverOnchainRail(deps) {
1593
1601
  id: SOLVER_ONCHAIN_RAIL,
1594
1602
  match: (req) => btcTarget(req.raw) !== void 0,
1595
1603
  available: async (req) => {
1604
+ if (assetsOf(req).length > 0) return false;
1596
1605
  const address = btcTarget(req.raw);
1597
1606
  if (!address) return false;
1598
1607
  try {
@@ -1606,6 +1615,7 @@ function solverOnchainRail(deps) {
1606
1615
  },
1607
1616
  quote: async (req, ctx) => {
1608
1617
  const address = btcTarget(req.raw);
1618
+ assertNoAssets(SOLVER_ONCHAIN_RAIL, req);
1609
1619
  const amount = resolveSendAmount(SOLVER_ONCHAIN_RAIL, req.raw, req.amount);
1610
1620
  const payoutPkScript = l1ScriptForAddress(address, deps.l1Network);
1611
1621
  const rendezvous = await rendezvousFor(amount);
@@ -1682,7 +1692,7 @@ function solverOnchainRail(deps) {
1682
1692
  }
1683
1693
 
1684
1694
  // src/payment/solverLightning.ts
1685
- import { invoiceTarget, makeHandle as makeHandle2 } from "@arkade-os/sdk";
1695
+ import { assertNoAssets as assertNoAssets2, assetsOf as assetsOf2, invoiceTarget, makeHandle as makeHandle2 } from "@arkade-os/sdk";
1686
1696
  var SOLVER_LIGHTNING_RAIL = "solver-lightning";
1687
1697
  var factsOf = (raw, decode, now) => {
1688
1698
  const invoice = invoiceTarget(raw);
@@ -1704,12 +1714,14 @@ function solverLightningRail(deps) {
1704
1714
  id: SOLVER_LIGHTNING_RAIL,
1705
1715
  match: (req) => invoiceTarget(req.raw) !== void 0,
1706
1716
  available: async (req) => {
1717
+ if (assetsOf2(req).length > 0) return false;
1707
1718
  const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
1708
1719
  if (!facts) return false;
1709
1720
  if (req.amount !== void 0 && req.amount !== facts.amountSats) return false;
1710
1721
  return await rendezvousFor(facts.amountSats) !== void 0;
1711
1722
  },
1712
1723
  quote: async (req, ctx) => {
1724
+ assertNoAssets2(SOLVER_LIGHTNING_RAIL, req);
1713
1725
  const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
1714
1726
  if (!facts) {
1715
1727
  throw new Error(
@@ -1782,10 +1794,260 @@ function solverLightningRail(deps) {
1782
1794
  };
1783
1795
  }
1784
1796
 
1785
- // src/claim.ts
1786
- import { hex as hex10 } from "@scure/base";
1797
+ // src/payment/crossAsset.ts
1798
+ import {
1799
+ arkTarget,
1800
+ asset as assetExt,
1801
+ assetsOf as assetsOf3,
1802
+ makeHandle as makeHandle3,
1803
+ resolveAssetAmount
1804
+ } from "@arkade-os/sdk";
1805
+ var CROSS_ASSET_RAIL = "cross-asset";
1806
+ var DEFAULT_CARRIER_SATS = 330;
1807
+ var parseAssetId = (assetId) => {
1808
+ try {
1809
+ return assetExt.AssetId.fromString(assetId);
1810
+ } catch {
1811
+ return void 0;
1812
+ }
1813
+ };
1814
+ function crossAssetRail(deps) {
1815
+ const planFor = async (asset2) => {
1816
+ const markets = await deps.discover();
1817
+ const found = findMarket(markets, BTC_ASSET_ID, asset2.assetId);
1818
+ const market = found?.market;
1819
+ if (!market) return void 0;
1820
+ const plan = await deps.quote(market, found.give, asset2.amount);
1821
+ const [balance, dust] = await Promise.all([deps.btcBalance(), deps.dust()]);
1822
+ return { plan, error: validatePlan(plan, balance, dust) };
1823
+ };
1824
+ return {
1825
+ id: CROSS_ASSET_RAIL,
1826
+ match: (req) => arkTarget(req.raw) !== void 0,
1827
+ available: async (req) => {
1828
+ const assets = assetsOf3(req);
1829
+ if (assets.length !== 1) return false;
1830
+ const [asset2] = assets;
1831
+ if (asset2.assetId === BTC_ASSET_ID) return false;
1832
+ if (typeof asset2.amount !== "bigint" || asset2.amount <= 0n) return false;
1833
+ if (!parseAssetId(asset2.assetId)) return false;
1834
+ const planned = await planFor(asset2);
1835
+ return planned !== void 0 && planned.error === void 0;
1836
+ },
1837
+ quote: async (req, ctx) => {
1838
+ const payTo = arkTarget(req.raw);
1839
+ const asset2 = resolveAssetAmount(CROSS_ASSET_RAIL, req);
1840
+ const wantAsset = parseAssetId(asset2.assetId);
1841
+ if (!wantAsset) {
1842
+ throw new Error(
1843
+ `${CROSS_ASSET_RAIL}: ${asset2.assetId} is not an asset id (expected 34 bytes of hex)`
1844
+ );
1845
+ }
1846
+ const planned = await planFor(asset2);
1847
+ if (!planned) {
1848
+ throw new Error(`${CROSS_ASSET_RAIL}: no market swaps BTC into ${asset2.assetId}`);
1849
+ }
1850
+ if (planned.error) {
1851
+ throw new Error(
1852
+ `${CROSS_ASSET_RAIL}: cannot swap into ${asset2.assetId} \u2014 ${planned.error}`
1853
+ );
1854
+ }
1855
+ const { plan } = planned;
1856
+ if (!Number.isSafeInteger(Number(plan.deposit.atomic))) {
1857
+ throw new Error(
1858
+ `${CROSS_ASSET_RAIL}: deposit of ${plan.deposit.atomic} does not fit a JS number`
1859
+ );
1860
+ }
1861
+ const depositSats = Number(plan.deposit.atomic);
1862
+ const carrier = deps.carrierSats ?? DEFAULT_CARRIER_SATS;
1863
+ return {
1864
+ railId: CROSS_ASSET_RAIL,
1865
+ // OPEN QUESTION for review: `total = amount + fee` forces the
1866
+ // purchase price into `fee`, which reads as a service charge.
1867
+ // A third field instead? `assets.spent` labels it correctly.
1868
+ amount: carrier,
1869
+ fee: depositSats,
1870
+ total: depositSats + carrier,
1871
+ assets: {
1872
+ delivered: asset2,
1873
+ spent: { assetId: BTC_ASSET_ID, amount: plan.deposit.atomic }
1874
+ },
1875
+ meta: {
1876
+ market: plan.market.pair,
1877
+ priceDisplay: plan.priceDisplay,
1878
+ give: plan.give
1879
+ },
1880
+ send: async () => makeHandle3(CROSS_ASSET_RAIL, async (emit) => {
1881
+ const offer = await createOffer(ctx.wallet, deps.arkServerUrl, {
1882
+ wantAmount: asset2.amount,
1883
+ wantAsset,
1884
+ ...deps.emulatorPubkey ? { emulatorPubkey: deps.emulatorPubkey } : {}
1885
+ });
1886
+ const swap = {
1887
+ phase: "quoted",
1888
+ offerHex: offer.offerHex,
1889
+ address: offer.address,
1890
+ swapPkScript: offer.swapPkScript,
1891
+ depositSats,
1892
+ asset: asset2,
1893
+ payTo,
1894
+ plan
1895
+ };
1896
+ await deps.persist(swap);
1897
+ await ctx.wallet.send({
1898
+ address: offer.address,
1899
+ amount: depositSats,
1900
+ extensions: [offer.extension]
1901
+ });
1902
+ emit({ status: "sent" });
1903
+ await deps.awaitFill(swap);
1904
+ await deps.persist({ ...swap, phase: "filled" });
1905
+ await deps.persist({ ...swap, phase: "paying" });
1906
+ const txid = await ctx.wallet.send({
1907
+ address: payTo,
1908
+ amount: carrier,
1909
+ assets: [asset2]
1910
+ });
1911
+ await deps.persist({ ...swap, phase: "settled", txid });
1912
+ const result = {
1913
+ railId: CROSS_ASSET_RAIL,
1914
+ txid,
1915
+ swapId: offer.offerHex
1916
+ };
1917
+ emit({ status: "settled", result });
1918
+ return result;
1919
+ })
1920
+ };
1921
+ }
1922
+ };
1923
+ }
1924
+
1925
+ // src/reveal.ts
1926
+ import { base64 as base643, hex as hex9 } from "@scure/base";
1787
1927
  import { ripemd160 } from "@noble/hashes/legacy.js";
1788
- import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
1928
+ import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
1929
+ import { ArkAddress as ArkAddress4 } from "@arkade-os/sdk";
1930
+ var CovclaimdRevealError = class extends Error {
1931
+ name = "CovclaimdRevealError";
1932
+ status;
1933
+ detail;
1934
+ retryable;
1935
+ constructor(what, status, detail) {
1936
+ super(`covclaimd ${what} failed: ${status || "no response"} ${detail}`.trimEnd());
1937
+ this.status = status;
1938
+ this.detail = detail;
1939
+ this.retryable = status === 0 || status === 429 || status >= 500;
1940
+ }
1941
+ };
1942
+ var decodeKey = (value, field) => {
1943
+ if (typeof value !== "string") throw new Error(`covclaimd info: ${field} is not a string`);
1944
+ let bytes;
1945
+ try {
1946
+ bytes = hex9.decode(value);
1947
+ } catch {
1948
+ throw new Error(`covclaimd info: ${field} is not hex`);
1949
+ }
1950
+ if (bytes.length !== 33) {
1951
+ throw new Error(`covclaimd info: ${field} must be 33-byte compressed, got ${bytes.length}`);
1952
+ }
1953
+ return bytes;
1954
+ };
1955
+ var LOOPBACK = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
1956
+ var assertTransportSecure = (baseUrl, allowInsecureHttp) => {
1957
+ const { protocol, hostname } = new URL(baseUrl);
1958
+ if (protocol === "https:" || allowInsecureHttp) return;
1959
+ if (protocol === "http:" && LOOPBACK.has(hostname)) return;
1960
+ throw new Error(
1961
+ `covclaimd URL must be https (got ${protocol}//${hostname}): the key it serves is the one the preimage gets sealed to. Pass allowInsecureHttp to override.`
1962
+ );
1963
+ };
1964
+ var covclaimdClient = (baseUrl, options = {}) => {
1965
+ assertTransportSecure(baseUrl, options.allowInsecureHttp === true);
1966
+ const url = baseUrl.replace(/\/+$/, "");
1967
+ const fetchImpl = options.fetchImpl ?? fetch;
1968
+ const timeoutMs = options.timeoutMs ?? 3e4;
1969
+ const send = async (what, path, init) => {
1970
+ let response;
1971
+ try {
1972
+ response = await fetchImpl(`${url}${path}`, {
1973
+ ...init,
1974
+ // a redirect would move the key fetch off the vetted origin
1975
+ redirect: "error",
1976
+ signal: AbortSignal.timeout(timeoutMs)
1977
+ });
1978
+ } catch (error) {
1979
+ throw new CovclaimdRevealError(what, 0, String(error));
1980
+ }
1981
+ if (!response.ok) {
1982
+ throw new CovclaimdRevealError(what, response.status, await response.text());
1983
+ }
1984
+ return response;
1985
+ };
1986
+ const readJson = async (what, response) => {
1987
+ const body = await response.text();
1988
+ try {
1989
+ return JSON.parse(body);
1990
+ } catch {
1991
+ throw new CovclaimdRevealError(
1992
+ what,
1993
+ response.status,
1994
+ `non-JSON body: ${body.slice(0, 200)}`
1995
+ );
1996
+ }
1997
+ };
1998
+ return {
1999
+ async info() {
2000
+ const response = await send("info", "/v1/preimage/covclaimd-pubkey", {
2001
+ method: "GET"
2002
+ });
2003
+ const body = await readJson("info", response);
2004
+ return {
2005
+ covclaimdPubkey: decodeKey(body?.covclaimd_pub_key, "covclaimd_pub_key"),
2006
+ emulatorPubkey: hex9.encode(decodeKey(body?.emulator_pub_key, "emulator_pub_key"))
2007
+ };
2008
+ },
2009
+ async reveal(params) {
2010
+ await send("reveal", "/v1/reveal", {
2011
+ method: "POST",
2012
+ headers: { "content-type": "application/json" },
2013
+ body: JSON.stringify({
2014
+ swap_address: params.swapAddress,
2015
+ packet: { ciphertext: params.ciphertext, arkade_script: params.arkadeScript },
2016
+ taptree: params.taptree
2017
+ })
2018
+ });
2019
+ }
2020
+ };
2021
+ };
2022
+ function revealFieldsFromScript(script) {
2023
+ if (!script.nonInteractiveClaimArkadeScript) {
2024
+ throw new Error("this covenant has no non-interactive claim leaf to reveal against");
2025
+ }
2026
+ return {
2027
+ arkadeScript: base643.encode(script.nonInteractiveClaimArkadeScript),
2028
+ taptree: hex9.encode(script.encode())
2029
+ };
2030
+ }
2031
+ async function revealClaimPacket(client, input) {
2032
+ const fields = revealFieldsFromScript(input.script);
2033
+ if (hex9.encode(ArkAddress4.decode(input.address).pkScript) !== hex9.encode(input.script.pkScript)) {
2034
+ throw new Error("address does not belong to this covenant");
2035
+ }
2036
+ if (hex9.encode(ripemd160(sha2562(input.preimage))) !== hex9.encode(input.script.options.preimageHash)) {
2037
+ throw new Error("preimage does not match the covenant's payment hash");
2038
+ }
2039
+ const { ciphertext } = await sealClaimPacket({
2040
+ preimage: input.preimage,
2041
+ covclaimdPubkey: (await client.info()).covclaimdPubkey
2042
+ });
2043
+ await client.reveal({ swapAddress: input.address, ciphertext, ...fields });
2044
+ return { ciphertext };
2045
+ }
2046
+
2047
+ // src/claim.ts
2048
+ import { hex as hex11 } from "@scure/base";
2049
+ import { ripemd160 as ripemd1602 } from "@noble/hashes/legacy.js";
2050
+ import { sha256 as sha2564 } from "@noble/hashes/sha2.js";
1789
2051
  import {
1790
2052
  CSVMultisigTapscript as CSVMultisigTapscript2,
1791
2053
  claimWithPreimageIdentity,
@@ -1793,8 +2055,8 @@ import {
1793
2055
  } from "@arkade-os/sdk";
1794
2056
 
1795
2057
  // src/refund.ts
1796
- import { base64 as base643, hex as hex9 } from "@scure/base";
1797
- import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
2058
+ import { base64 as base644, hex as hex10 } from "@scure/base";
2059
+ import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
1798
2060
  import {
1799
2061
  CSVMultisigTapscript,
1800
2062
  ConditionWitness,
@@ -1851,7 +2113,7 @@ var LockupNeedsRecoveryError = class extends Error {
1851
2113
  }
1852
2114
  };
1853
2115
  async function findLockupVtxos(indexer, swapPkScript) {
1854
- const scripts = [hex9.encode(swapPkScript)];
2116
+ const scripts = [hex10.encode(swapPkScript)];
1855
2117
  const [spendable, recoverable] = await Promise.all([
1856
2118
  indexer.getVtxos({ scripts, spendableOnly: true }),
1857
2119
  indexer.getVtxos({ scripts, recoverableOnly: true })
@@ -1877,13 +2139,13 @@ async function findLockupVtxos(indexer, swapPkScript) {
1877
2139
  }
1878
2140
  return out;
1879
2141
  }
1880
- var hashesTo = (candidate, paymentHash) => hex9.encode(sha2562(candidate)) === paymentHash;
2142
+ var hashesTo = (candidate, paymentHash) => hex10.encode(sha2563(candidate)) === paymentHash;
1881
2143
  var candidateWitnessItems = (tx, inputIndex) => [
1882
2144
  ...getArkPsbtFields(tx, inputIndex, ConditionWitness).flat(),
1883
2145
  ...tx.getInput(inputIndex).finalScriptWitness ?? []
1884
2146
  ];
1885
2147
  async function readLockupFate(indexer, input) {
1886
- const { vtxos } = await indexer.getVtxos({ scripts: [hex9.encode(input.swapPkScript)] });
2148
+ const { vtxos } = await indexer.getVtxos({ scripts: [hex10.encode(input.swapPkScript)] });
1887
2149
  const all = vtxos ?? [];
1888
2150
  if (all.length === 0) return { fate: "unknown" };
1889
2151
  const exited = all.filter((vtxo) => vtxo.isUnrolled && !hasTerminalSpend(vtxo));
@@ -1910,7 +2172,7 @@ async function readLockupFate(indexer, input) {
1910
2172
  for (const raw of txs) {
1911
2173
  let tx;
1912
2174
  try {
1913
- tx = Transaction3.fromPSBT(base643.decode(raw));
2175
+ tx = Transaction3.fromPSBT(base644.decode(raw));
1914
2176
  } catch {
1915
2177
  continue;
1916
2178
  }
@@ -1918,7 +2180,7 @@ async function readLockupFate(indexer, input) {
1918
2180
  for (let i = 0; i < tx.inputsLength; i++) {
1919
2181
  const spent = tx.getInput(i);
1920
2182
  if (!spent.txid) continue;
1921
- const txid = hex9.encode(spent.txid);
2183
+ const txid = hex10.encode(spent.txid);
1922
2184
  if (!all.some((vtxo) => vtxo.txid === txid && vtxo.vout === spent.index)) continue;
1923
2185
  for (const candidate of candidateWitnessItems(tx, i)) {
1924
2186
  if (hashesTo(candidate, input.paymentHash)) {
@@ -1947,7 +2209,7 @@ async function pushRefundWithoutReceiver(ark, input) {
1947
2209
  const info = await ark.getInfo();
1948
2210
  let serverUnrollScript;
1949
2211
  try {
1950
- serverUnrollScript = CSVMultisigTapscript.decode(hex9.decode(info.checkpointTapscript));
2212
+ serverUnrollScript = CSVMultisigTapscript.decode(hex10.decode(info.checkpointTapscript));
1951
2213
  } catch {
1952
2214
  throw new Error("invalid checkpointTapscript from the Arkade server");
1953
2215
  }
@@ -1967,8 +2229,8 @@ async function pushRefundWithoutReceiver(ark, input) {
1967
2229
  );
1968
2230
  const signedArkTx = await input.sender.sign(arkTx);
1969
2231
  const submitted = await ark.submitTx(
1970
- base643.encode(signedArkTx.toPSBT()),
1971
- checkpoints.map((c) => base643.encode(c.toPSBT()))
2232
+ base644.encode(signedArkTx.toPSBT()),
2233
+ checkpoints.map((c) => base644.encode(c.toPSBT()))
1972
2234
  );
1973
2235
  assertSubmittedArkTxid(submitted, signedArkTx, "refundWithoutReceiver");
1974
2236
  const matched = matchServerCheckpoints(
@@ -1978,7 +2240,7 @@ async function pushRefundWithoutReceiver(ark, input) {
1978
2240
  );
1979
2241
  const finalCheckpoints = await Promise.all(
1980
2242
  matched.map(
1981
- async ({ server }) => base643.encode((await input.sender.sign(server, [0])).toPSBT())
2243
+ async ({ server }) => base644.encode((await input.sender.sign(server, [0])).toPSBT())
1982
2244
  )
1983
2245
  );
1984
2246
  await ark.finalizeTx(submitted.arkTxid, finalCheckpoints);
@@ -2073,13 +2335,13 @@ async function pushClaim(ark, input) {
2073
2335
  }
2074
2336
  }
2075
2337
  const committed = input.script.options.preimageHash;
2076
- if (hex10.encode(ripemd160(sha2563(input.preimage))) !== hex10.encode(committed)) {
2338
+ if (hex11.encode(ripemd1602(sha2564(input.preimage))) !== hex11.encode(committed)) {
2077
2339
  throw new Error("preimage does not match the covenant's payment hash");
2078
2340
  }
2079
2341
  const info = await ark.getInfo();
2080
2342
  let serverUnrollScript;
2081
2343
  try {
2082
- serverUnrollScript = CSVMultisigTapscript2.decode(hex10.decode(info.checkpointTapscript));
2344
+ serverUnrollScript = CSVMultisigTapscript2.decode(hex11.decode(info.checkpointTapscript));
2083
2345
  } catch {
2084
2346
  throw new Error("invalid checkpointTapscript from the Arkade server");
2085
2347
  }
@@ -2198,7 +2460,10 @@ function arkadeRefunder(deps) {
2198
2460
  }
2199
2461
 
2200
2462
  // src/swapManager.ts
2201
- import { hex as hex11 } from "@scure/base";
2463
+ import { hex as hex12 } from "@scure/base";
2464
+ import {
2465
+ isContractVtxoEvent as isContractVtxoEvent2
2466
+ } from "@arkade-os/sdk";
2202
2467
  function nextOnchainAction(input) {
2203
2468
  switch (input.phase.phase) {
2204
2469
  case "unfunded":
@@ -2646,7 +2911,7 @@ var RfqSwapManager = class {
2646
2911
  // ── internals ────────────────────────────────────────────────────────────
2647
2912
  track(swap) {
2648
2913
  this.monitored.set(swap.rfqId, swap);
2649
- this.byLockupScript.set(hex11.encode(swap.lockupPkScript), swap);
2914
+ this.byLockupScript.set(hex12.encode(swap.lockupPkScript), swap);
2650
2915
  }
2651
2916
  /** Drops the swap from BOTH indexes. The event index is the one that stops
2652
2917
  * a late event finding a swap that is gone; `pollSwap`'s own
@@ -2655,7 +2920,7 @@ var RfqSwapManager = class {
2655
2920
  * them from silently re-driving a cancelled swap. */
2656
2921
  untrack(rfqId) {
2657
2922
  const swap = this.monitored.get(rfqId);
2658
- if (swap) this.byLockupScript.delete(hex11.encode(swap.lockupPkScript));
2923
+ if (swap) this.byLockupScript.delete(hex12.encode(swap.lockupPkScript));
2659
2924
  this.monitored.delete(rfqId);
2660
2925
  this.refundRefused.delete(rfqId);
2661
2926
  this.lastClaimError.delete(rfqId);
@@ -2688,6 +2953,7 @@ var RfqSwapManager = class {
2688
2953
  });
2689
2954
  return;
2690
2955
  }
2956
+ if (!isContractVtxoEvent2(event)) return;
2691
2957
  const swap = this.byLockupScript.get(event.contractScript);
2692
2958
  if (!swap) return;
2693
2959
  void this.pollSwap(swap).catch(() => {
@@ -2717,7 +2983,7 @@ var RfqSwapManager = class {
2717
2983
  if (!lockup) {
2718
2984
  try {
2719
2985
  const [existing] = await contracts.getContracts({
2720
- script: hex11.encode(swap.lockupPkScript)
2986
+ script: hex12.encode(swap.lockupPkScript)
2721
2987
  });
2722
2988
  if (existing) {
2723
2989
  this.registered.set(swap.rfqId, true);
@@ -2736,13 +3002,13 @@ var RfqSwapManager = class {
2736
3002
  );
2737
3003
  return;
2738
3004
  }
2739
- const script = hex11.encode(lockup.script.pkScript);
2740
- if (script !== hex11.encode(swap.lockupPkScript)) {
3005
+ const script = hex12.encode(lockup.script.pkScript);
3006
+ if (script !== hex12.encode(swap.lockupPkScript)) {
2741
3007
  this.registered.set(swap.rfqId, false);
2742
3008
  this.emitFailed(
2743
3009
  swap,
2744
3010
  new Error(
2745
- `swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${hex11.encode(swap.lockupPkScript)}`
3011
+ `swap ${swap.rfqId} lockup script ${script} does not match its lockupPkScript ${hex12.encode(swap.lockupPkScript)}`
2746
3012
  )
2747
3013
  );
2748
3014
  return;
@@ -2761,7 +3027,7 @@ var RfqSwapManager = class {
2761
3027
  * script for its whole life. Best-effort — the swap is over either way. */
2762
3028
  retireContract(swap) {
2763
3029
  if (!this.deps.contracts || !this.registered.get(swap.rfqId)) return;
2764
- void this.deps.contracts.setContractWatchState(hex11.encode(swap.lockupPkScript), "retained").catch((error) => this.emitFailed(swap, error));
3030
+ void this.deps.contracts.setContractWatchState(hex12.encode(swap.lockupPkScript), "retained").catch((error) => this.emitFailed(swap, error));
2765
3031
  }
2766
3032
  arm() {
2767
3033
  if (!this.running) return;
@@ -3235,9 +3501,9 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
3235
3501
 
3236
3502
  // src/activity.ts
3237
3503
  import {
3238
- ArkAddress as ArkAddress4
3504
+ ArkAddress as ArkAddress5
3239
3505
  } from "@arkade-os/sdk";
3240
- import { hex as hex12 } from "@scure/base";
3506
+ import { hex as hex13 } from "@scure/base";
3241
3507
  var LABELS = {
3242
3508
  lightning_send: "Lightning send",
3243
3509
  lightning_receive: "Lightning receive",
@@ -3312,7 +3578,7 @@ async function activityInputOf(record, indexer) {
3312
3578
  async function lockupTxids(indexer, record, wantFunding) {
3313
3579
  let script;
3314
3580
  try {
3315
- script = hex12.encode(ArkAddress4.decode(record.lockupAddress).pkScript);
3581
+ script = hex13.encode(ArkAddress5.decode(record.lockupAddress).pkScript);
3316
3582
  } catch {
3317
3583
  return [];
3318
3584
  }
@@ -3333,6 +3599,8 @@ export {
3333
3599
  ARKADE_BTC,
3334
3600
  AddressMismatch,
3335
3601
  BTC_ASSET_ID,
3602
+ CROSS_ASSET_RAIL,
3603
+ CovclaimdRevealError,
3336
3604
  InMemoryAssetSwapRepository,
3337
3605
  IndexedDbAssetSwapRepository,
3338
3606
  LIGHTNING_BTC,
@@ -3389,8 +3657,10 @@ export {
3389
3657
  classifyDepositSpend,
3390
3658
  classifyOnchainHtlc,
3391
3659
  classifySpend,
3660
+ covclaimdClient,
3392
3661
  createOffer,
3393
3662
  createRfqSwapRecord,
3663
+ crossAssetRail,
3394
3664
  decodeOffer,
3395
3665
  deriveLightningReceive,
3396
3666
  deriveOnchainReceive,
@@ -3436,6 +3706,8 @@ export {
3436
3706
  requestOnchainSend,
3437
3707
  restoreAssetSwaps,
3438
3708
  retireSettledOfferContracts,
3709
+ revealClaimPacket,
3710
+ revealFieldsFromScript,
3439
3711
  rfqClaimSecretOf,
3440
3712
  rfqPair,
3441
3713
  rfqSecretsProfile,
package/dist/nostr.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as RfqTransport } from './rfq-DzsmhXX3.cjs';
1
+ import { R as RfqTransport } from './rfq-CYfKvAPp.cjs';
2
2
  import { SimplePool } from 'nostr-tools';
3
3
  import '@arkade-os/sdk';
4
4
 
package/dist/nostr.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as RfqTransport } from './rfq-DzsmhXX3.js';
1
+ import { R as RfqTransport } from './rfq-CYfKvAPp.js';
2
2
  import { SimplePool } from 'nostr-tools';
3
3
  import '@arkade-os/sdk';
4
4
 
package/dist/nostr.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  expectQuote,
3
3
  pairOf
4
- } from "./chunk-XXWOODUE.js";
4
+ } from "./chunk-IFZOBTTG.js";
5
5
 
6
6
  // src/nostr.ts
7
7
  import {
@@ -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-DaK1RzRq.cjs';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-Vfx65uF1.cjs';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-DzsmhXX3.cjs';
5
+ import '../../rfq-CYfKvAPp.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-DlLvj_y6.js';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-D5JoeqwB.js';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-DzsmhXX3.js';
5
+ import '../../rfq-CYfKvAPp.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-DaK1RzRq.cjs';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-Vfx65uF1.cjs';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-DzsmhXX3.cjs';
5
+ import '../../rfq-CYfKvAPp.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-DlLvj_y6.js';
2
+ import { A as AssetSwapRepository, a as AssetSwap, R as RfqSwapRecord, M as MarketsCacheEntry } from '../../repository-D5JoeqwB.js';
3
3
  import '@arkade-os/solver-discovery';
4
4
  import '@arkade-os/sdk';
5
- import '../../rfq-DzsmhXX3.js';
5
+ import '../../rfq-CYfKvAPp.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 { B as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-DzsmhXX3.js';
3
+ import { B as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-CYfKvAPp.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.
@@ -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 { B as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-DzsmhXX3.cjs';
3
+ import { B as RfqStatus, R as RfqTransport, a as OnchainHtlc, f as ChainUtxo, C as ChainSource, v as OnchainHtlcPhase } from './rfq-CYfKvAPp.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.