@arkade-os/swap 0.0.12 → 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-XXWOODUE.js → chunk-IFZOBTTG.js} +8 -8
- package/dist/index.cjs +308 -48
- package/dist/index.d.cts +131 -6
- package/dist/index.d.ts +131 -6
- package/dist/index.js +297 -30
- 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-DlLvj_y6.d.ts → repository-D5JoeqwB.d.ts} +1 -1
- package/dist/{repository-DaK1RzRq.d.cts → repository-Vfx65uF1.d.cts} +1 -1
- package/dist/{rfq-DzsmhXX3.d.ts → rfq-CYfKvAPp.d.cts} +14 -8
- package/dist/{rfq-DzsmhXX3.d.cts → rfq-CYfKvAPp.d.ts} +14 -8
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
unilateralRefundWithoutReceiverDelay,
|
|
66
66
|
verifyLockupAddress,
|
|
67
67
|
verifyReceiveInvoice
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-IFZOBTTG.js";
|
|
69
69
|
import {
|
|
70
70
|
InMemoryAssetSwapRepository,
|
|
71
71
|
marketsCacheKey
|
|
@@ -1580,7 +1580,14 @@ var solverRendezvous = (markets, payoutCorridor, amountSats, fallbackEmulatorPub
|
|
|
1580
1580
|
};
|
|
1581
1581
|
|
|
1582
1582
|
// src/payment/solverOnchain.ts
|
|
1583
|
-
import {
|
|
1583
|
+
import {
|
|
1584
|
+
assertNoAssets,
|
|
1585
|
+
assetsOf,
|
|
1586
|
+
btcTarget,
|
|
1587
|
+
makeHandle,
|
|
1588
|
+
resolveSendAmount,
|
|
1589
|
+
tryResolveSendAmount
|
|
1590
|
+
} from "@arkade-os/sdk";
|
|
1584
1591
|
var SOLVER_ONCHAIN_RAIL = "solver-onchain";
|
|
1585
1592
|
var solverOnchainRendezvous = (markets, amountSats, fallbackEmulatorPubkey) => solverRendezvous(markets, "onchain", amountSats, fallbackEmulatorPubkey);
|
|
1586
1593
|
function solverOnchainRail(deps) {
|
|
@@ -1593,6 +1600,7 @@ function solverOnchainRail(deps) {
|
|
|
1593
1600
|
id: SOLVER_ONCHAIN_RAIL,
|
|
1594
1601
|
match: (req) => btcTarget(req.raw) !== void 0,
|
|
1595
1602
|
available: async (req) => {
|
|
1603
|
+
if (assetsOf(req).length > 0) return false;
|
|
1596
1604
|
const address = btcTarget(req.raw);
|
|
1597
1605
|
if (!address) return false;
|
|
1598
1606
|
try {
|
|
@@ -1606,6 +1614,7 @@ function solverOnchainRail(deps) {
|
|
|
1606
1614
|
},
|
|
1607
1615
|
quote: async (req, ctx) => {
|
|
1608
1616
|
const address = btcTarget(req.raw);
|
|
1617
|
+
assertNoAssets(SOLVER_ONCHAIN_RAIL, req);
|
|
1609
1618
|
const amount = resolveSendAmount(SOLVER_ONCHAIN_RAIL, req.raw, req.amount);
|
|
1610
1619
|
const payoutPkScript = l1ScriptForAddress(address, deps.l1Network);
|
|
1611
1620
|
const rendezvous = await rendezvousFor(amount);
|
|
@@ -1682,7 +1691,7 @@ function solverOnchainRail(deps) {
|
|
|
1682
1691
|
}
|
|
1683
1692
|
|
|
1684
1693
|
// src/payment/solverLightning.ts
|
|
1685
|
-
import { invoiceTarget, makeHandle as makeHandle2 } from "@arkade-os/sdk";
|
|
1694
|
+
import { assertNoAssets as assertNoAssets2, assetsOf as assetsOf2, invoiceTarget, makeHandle as makeHandle2 } from "@arkade-os/sdk";
|
|
1686
1695
|
var SOLVER_LIGHTNING_RAIL = "solver-lightning";
|
|
1687
1696
|
var factsOf = (raw, decode, now) => {
|
|
1688
1697
|
const invoice = invoiceTarget(raw);
|
|
@@ -1704,12 +1713,14 @@ function solverLightningRail(deps) {
|
|
|
1704
1713
|
id: SOLVER_LIGHTNING_RAIL,
|
|
1705
1714
|
match: (req) => invoiceTarget(req.raw) !== void 0,
|
|
1706
1715
|
available: async (req) => {
|
|
1716
|
+
if (assetsOf2(req).length > 0) return false;
|
|
1707
1717
|
const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
|
|
1708
1718
|
if (!facts) return false;
|
|
1709
1719
|
if (req.amount !== void 0 && req.amount !== facts.amountSats) return false;
|
|
1710
1720
|
return await rendezvousFor(facts.amountSats) !== void 0;
|
|
1711
1721
|
},
|
|
1712
1722
|
quote: async (req, ctx) => {
|
|
1723
|
+
assertNoAssets2(SOLVER_LIGHTNING_RAIL, req);
|
|
1713
1724
|
const facts = factsOf(req.raw, deps.decodeInvoice, Math.floor(Date.now() / 1e3));
|
|
1714
1725
|
if (!facts) {
|
|
1715
1726
|
throw new Error(
|
|
@@ -1782,10 +1793,260 @@ function solverLightningRail(deps) {
|
|
|
1782
1793
|
};
|
|
1783
1794
|
}
|
|
1784
1795
|
|
|
1785
|
-
// src/
|
|
1786
|
-
import {
|
|
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";
|
|
1787
1926
|
import { ripemd160 } from "@noble/hashes/legacy.js";
|
|
1788
|
-
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";
|
|
1789
2050
|
import {
|
|
1790
2051
|
CSVMultisigTapscript as CSVMultisigTapscript2,
|
|
1791
2052
|
claimWithPreimageIdentity,
|
|
@@ -1793,8 +2054,8 @@ import {
|
|
|
1793
2054
|
} from "@arkade-os/sdk";
|
|
1794
2055
|
|
|
1795
2056
|
// src/refund.ts
|
|
1796
|
-
import { base64 as
|
|
1797
|
-
import { sha256 as
|
|
2057
|
+
import { base64 as base644, hex as hex10 } from "@scure/base";
|
|
2058
|
+
import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
|
|
1798
2059
|
import {
|
|
1799
2060
|
CSVMultisigTapscript,
|
|
1800
2061
|
ConditionWitness,
|
|
@@ -1851,7 +2112,7 @@ var LockupNeedsRecoveryError = class extends Error {
|
|
|
1851
2112
|
}
|
|
1852
2113
|
};
|
|
1853
2114
|
async function findLockupVtxos(indexer, swapPkScript) {
|
|
1854
|
-
const scripts = [
|
|
2115
|
+
const scripts = [hex10.encode(swapPkScript)];
|
|
1855
2116
|
const [spendable, recoverable] = await Promise.all([
|
|
1856
2117
|
indexer.getVtxos({ scripts, spendableOnly: true }),
|
|
1857
2118
|
indexer.getVtxos({ scripts, recoverableOnly: true })
|
|
@@ -1877,13 +2138,13 @@ async function findLockupVtxos(indexer, swapPkScript) {
|
|
|
1877
2138
|
}
|
|
1878
2139
|
return out;
|
|
1879
2140
|
}
|
|
1880
|
-
var hashesTo = (candidate, paymentHash) =>
|
|
2141
|
+
var hashesTo = (candidate, paymentHash) => hex10.encode(sha2563(candidate)) === paymentHash;
|
|
1881
2142
|
var candidateWitnessItems = (tx, inputIndex) => [
|
|
1882
2143
|
...getArkPsbtFields(tx, inputIndex, ConditionWitness).flat(),
|
|
1883
2144
|
...tx.getInput(inputIndex).finalScriptWitness ?? []
|
|
1884
2145
|
];
|
|
1885
2146
|
async function readLockupFate(indexer, input) {
|
|
1886
|
-
const { vtxos } = await indexer.getVtxos({ scripts: [
|
|
2147
|
+
const { vtxos } = await indexer.getVtxos({ scripts: [hex10.encode(input.swapPkScript)] });
|
|
1887
2148
|
const all = vtxos ?? [];
|
|
1888
2149
|
if (all.length === 0) return { fate: "unknown" };
|
|
1889
2150
|
const exited = all.filter((vtxo) => vtxo.isUnrolled && !hasTerminalSpend(vtxo));
|
|
@@ -1910,7 +2171,7 @@ async function readLockupFate(indexer, input) {
|
|
|
1910
2171
|
for (const raw of txs) {
|
|
1911
2172
|
let tx;
|
|
1912
2173
|
try {
|
|
1913
|
-
tx = Transaction3.fromPSBT(
|
|
2174
|
+
tx = Transaction3.fromPSBT(base644.decode(raw));
|
|
1914
2175
|
} catch {
|
|
1915
2176
|
continue;
|
|
1916
2177
|
}
|
|
@@ -1918,7 +2179,7 @@ async function readLockupFate(indexer, input) {
|
|
|
1918
2179
|
for (let i = 0; i < tx.inputsLength; i++) {
|
|
1919
2180
|
const spent = tx.getInput(i);
|
|
1920
2181
|
if (!spent.txid) continue;
|
|
1921
|
-
const txid =
|
|
2182
|
+
const txid = hex10.encode(spent.txid);
|
|
1922
2183
|
if (!all.some((vtxo) => vtxo.txid === txid && vtxo.vout === spent.index)) continue;
|
|
1923
2184
|
for (const candidate of candidateWitnessItems(tx, i)) {
|
|
1924
2185
|
if (hashesTo(candidate, input.paymentHash)) {
|
|
@@ -1947,7 +2208,7 @@ async function pushRefundWithoutReceiver(ark, input) {
|
|
|
1947
2208
|
const info = await ark.getInfo();
|
|
1948
2209
|
let serverUnrollScript;
|
|
1949
2210
|
try {
|
|
1950
|
-
serverUnrollScript = CSVMultisigTapscript.decode(
|
|
2211
|
+
serverUnrollScript = CSVMultisigTapscript.decode(hex10.decode(info.checkpointTapscript));
|
|
1951
2212
|
} catch {
|
|
1952
2213
|
throw new Error("invalid checkpointTapscript from the Arkade server");
|
|
1953
2214
|
}
|
|
@@ -1967,8 +2228,8 @@ async function pushRefundWithoutReceiver(ark, input) {
|
|
|
1967
2228
|
);
|
|
1968
2229
|
const signedArkTx = await input.sender.sign(arkTx);
|
|
1969
2230
|
const submitted = await ark.submitTx(
|
|
1970
|
-
|
|
1971
|
-
checkpoints.map((c) =>
|
|
2231
|
+
base644.encode(signedArkTx.toPSBT()),
|
|
2232
|
+
checkpoints.map((c) => base644.encode(c.toPSBT()))
|
|
1972
2233
|
);
|
|
1973
2234
|
assertSubmittedArkTxid(submitted, signedArkTx, "refundWithoutReceiver");
|
|
1974
2235
|
const matched = matchServerCheckpoints(
|
|
@@ -1978,7 +2239,7 @@ async function pushRefundWithoutReceiver(ark, input) {
|
|
|
1978
2239
|
);
|
|
1979
2240
|
const finalCheckpoints = await Promise.all(
|
|
1980
2241
|
matched.map(
|
|
1981
|
-
async ({ server }) =>
|
|
2242
|
+
async ({ server }) => base644.encode((await input.sender.sign(server, [0])).toPSBT())
|
|
1982
2243
|
)
|
|
1983
2244
|
);
|
|
1984
2245
|
await ark.finalizeTx(submitted.arkTxid, finalCheckpoints);
|
|
@@ -2073,13 +2334,13 @@ async function pushClaim(ark, input) {
|
|
|
2073
2334
|
}
|
|
2074
2335
|
}
|
|
2075
2336
|
const committed = input.script.options.preimageHash;
|
|
2076
|
-
if (
|
|
2337
|
+
if (hex11.encode(ripemd1602(sha2564(input.preimage))) !== hex11.encode(committed)) {
|
|
2077
2338
|
throw new Error("preimage does not match the covenant's payment hash");
|
|
2078
2339
|
}
|
|
2079
2340
|
const info = await ark.getInfo();
|
|
2080
2341
|
let serverUnrollScript;
|
|
2081
2342
|
try {
|
|
2082
|
-
serverUnrollScript = CSVMultisigTapscript2.decode(
|
|
2343
|
+
serverUnrollScript = CSVMultisigTapscript2.decode(hex11.decode(info.checkpointTapscript));
|
|
2083
2344
|
} catch {
|
|
2084
2345
|
throw new Error("invalid checkpointTapscript from the Arkade server");
|
|
2085
2346
|
}
|
|
@@ -2198,7 +2459,7 @@ function arkadeRefunder(deps) {
|
|
|
2198
2459
|
}
|
|
2199
2460
|
|
|
2200
2461
|
// src/swapManager.ts
|
|
2201
|
-
import { hex as
|
|
2462
|
+
import { hex as hex12 } from "@scure/base";
|
|
2202
2463
|
function nextOnchainAction(input) {
|
|
2203
2464
|
switch (input.phase.phase) {
|
|
2204
2465
|
case "unfunded":
|
|
@@ -2646,7 +2907,7 @@ var RfqSwapManager = class {
|
|
|
2646
2907
|
// ── internals ────────────────────────────────────────────────────────────
|
|
2647
2908
|
track(swap) {
|
|
2648
2909
|
this.monitored.set(swap.rfqId, swap);
|
|
2649
|
-
this.byLockupScript.set(
|
|
2910
|
+
this.byLockupScript.set(hex12.encode(swap.lockupPkScript), swap);
|
|
2650
2911
|
}
|
|
2651
2912
|
/** Drops the swap from BOTH indexes. The event index is the one that stops
|
|
2652
2913
|
* a late event finding a swap that is gone; `pollSwap`'s own
|
|
@@ -2655,7 +2916,7 @@ var RfqSwapManager = class {
|
|
|
2655
2916
|
* them from silently re-driving a cancelled swap. */
|
|
2656
2917
|
untrack(rfqId) {
|
|
2657
2918
|
const swap = this.monitored.get(rfqId);
|
|
2658
|
-
if (swap) this.byLockupScript.delete(
|
|
2919
|
+
if (swap) this.byLockupScript.delete(hex12.encode(swap.lockupPkScript));
|
|
2659
2920
|
this.monitored.delete(rfqId);
|
|
2660
2921
|
this.refundRefused.delete(rfqId);
|
|
2661
2922
|
this.lastClaimError.delete(rfqId);
|
|
@@ -2717,7 +2978,7 @@ var RfqSwapManager = class {
|
|
|
2717
2978
|
if (!lockup) {
|
|
2718
2979
|
try {
|
|
2719
2980
|
const [existing] = await contracts.getContracts({
|
|
2720
|
-
script:
|
|
2981
|
+
script: hex12.encode(swap.lockupPkScript)
|
|
2721
2982
|
});
|
|
2722
2983
|
if (existing) {
|
|
2723
2984
|
this.registered.set(swap.rfqId, true);
|
|
@@ -2736,13 +2997,13 @@ var RfqSwapManager = class {
|
|
|
2736
2997
|
);
|
|
2737
2998
|
return;
|
|
2738
2999
|
}
|
|
2739
|
-
const script =
|
|
2740
|
-
if (script !==
|
|
3000
|
+
const script = hex12.encode(lockup.script.pkScript);
|
|
3001
|
+
if (script !== hex12.encode(swap.lockupPkScript)) {
|
|
2741
3002
|
this.registered.set(swap.rfqId, false);
|
|
2742
3003
|
this.emitFailed(
|
|
2743
3004
|
swap,
|
|
2744
3005
|
new Error(
|
|
2745
|
-
`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)}`
|
|
2746
3007
|
)
|
|
2747
3008
|
);
|
|
2748
3009
|
return;
|
|
@@ -2761,7 +3022,7 @@ var RfqSwapManager = class {
|
|
|
2761
3022
|
* script for its whole life. Best-effort — the swap is over either way. */
|
|
2762
3023
|
retireContract(swap) {
|
|
2763
3024
|
if (!this.deps.contracts || !this.registered.get(swap.rfqId)) return;
|
|
2764
|
-
void this.deps.contracts.setContractWatchState(
|
|
3025
|
+
void this.deps.contracts.setContractWatchState(hex12.encode(swap.lockupPkScript), "retained").catch((error) => this.emitFailed(swap, error));
|
|
2765
3026
|
}
|
|
2766
3027
|
arm() {
|
|
2767
3028
|
if (!this.running) return;
|
|
@@ -3235,9 +3496,9 @@ var outpointKey = (vtxo) => `${vtxo.txid}:${vtxo.vout}`;
|
|
|
3235
3496
|
|
|
3236
3497
|
// src/activity.ts
|
|
3237
3498
|
import {
|
|
3238
|
-
ArkAddress as
|
|
3499
|
+
ArkAddress as ArkAddress5
|
|
3239
3500
|
} from "@arkade-os/sdk";
|
|
3240
|
-
import { hex as
|
|
3501
|
+
import { hex as hex13 } from "@scure/base";
|
|
3241
3502
|
var LABELS = {
|
|
3242
3503
|
lightning_send: "Lightning send",
|
|
3243
3504
|
lightning_receive: "Lightning receive",
|
|
@@ -3312,7 +3573,7 @@ async function activityInputOf(record, indexer) {
|
|
|
3312
3573
|
async function lockupTxids(indexer, record, wantFunding) {
|
|
3313
3574
|
let script;
|
|
3314
3575
|
try {
|
|
3315
|
-
script =
|
|
3576
|
+
script = hex13.encode(ArkAddress5.decode(record.lockupAddress).pkScript);
|
|
3316
3577
|
} catch {
|
|
3317
3578
|
return [];
|
|
3318
3579
|
}
|
|
@@ -3333,6 +3594,8 @@ export {
|
|
|
3333
3594
|
ARKADE_BTC,
|
|
3334
3595
|
AddressMismatch,
|
|
3335
3596
|
BTC_ASSET_ID,
|
|
3597
|
+
CROSS_ASSET_RAIL,
|
|
3598
|
+
CovclaimdRevealError,
|
|
3336
3599
|
InMemoryAssetSwapRepository,
|
|
3337
3600
|
IndexedDbAssetSwapRepository,
|
|
3338
3601
|
LIGHTNING_BTC,
|
|
@@ -3389,8 +3652,10 @@ export {
|
|
|
3389
3652
|
classifyDepositSpend,
|
|
3390
3653
|
classifyOnchainHtlc,
|
|
3391
3654
|
classifySpend,
|
|
3655
|
+
covclaimdClient,
|
|
3392
3656
|
createOffer,
|
|
3393
3657
|
createRfqSwapRecord,
|
|
3658
|
+
crossAssetRail,
|
|
3394
3659
|
decodeOffer,
|
|
3395
3660
|
deriveLightningReceive,
|
|
3396
3661
|
deriveOnchainReceive,
|
|
@@ -3436,6 +3701,8 @@ export {
|
|
|
3436
3701
|
requestOnchainSend,
|
|
3437
3702
|
restoreAssetSwaps,
|
|
3438
3703
|
retireSettledOfferContracts,
|
|
3704
|
+
revealClaimPacket,
|
|
3705
|
+
revealFieldsFromScript,
|
|
3439
3706
|
rfqClaimSecretOf,
|
|
3440
3707
|
rfqPair,
|
|
3441
3708
|
rfqSecretsProfile,
|
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-Vfx65uF1.cjs';
|
|
3
3
|
import '@arkade-os/solver-discovery';
|
|
4
4
|
import '@arkade-os/sdk';
|
|
5
|
-
import '../../rfq-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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.
|
|
@@ -640,8 +640,10 @@ declare const lightningReceiveRequest: (input: {
|
|
|
640
640
|
payoutAddress: string;
|
|
641
641
|
/** Trader's x-only arkade key — the covenant's `receiver` role. */
|
|
642
642
|
payoutPubkey: Uint8Array;
|
|
643
|
-
/** `P` sealed to covclaimd, base64 — `sealClaimPacket(...).ciphertext`.
|
|
644
|
-
|
|
643
|
+
/** `P` sealed to covclaimd, base64 — `sealClaimPacket(...).ciphertext`.
|
|
644
|
+
* Omitted when there is no covclaimd to seal to; the field is then left off
|
|
645
|
+
* the wire entirely, since the solver refuses an empty packet. */
|
|
646
|
+
claimPacket?: string;
|
|
645
647
|
amount: number;
|
|
646
648
|
amountSide: "from" | "to";
|
|
647
649
|
}) => Record<string, unknown>;
|
|
@@ -659,8 +661,9 @@ declare const onchainReceiveRequest: (input: {
|
|
|
659
661
|
payoutPubkey: Uint8Array;
|
|
660
662
|
/** Trader's x-only L1 key for the HTLC's refund leaf. */
|
|
661
663
|
refundPubkey: Uint8Array;
|
|
662
|
-
/** `P` sealed to covclaimd, base64
|
|
663
|
-
|
|
664
|
+
/** `P` sealed to covclaimd, base64. Omitted when there is none to seal to —
|
|
665
|
+
* see {@link lightningReceiveRequest}. */
|
|
666
|
+
claimPacket?: string;
|
|
664
667
|
amount: number;
|
|
665
668
|
amountSide: "from" | "to";
|
|
666
669
|
}) => Record<string, unknown>;
|
|
@@ -942,8 +945,10 @@ declare function requestLightningReceive(wallet: IWallet, arkServerUrl: string,
|
|
|
942
945
|
* {@link resolveEmulatorPubkey}. */
|
|
943
946
|
emulatorPubkey?: string;
|
|
944
947
|
/** covclaimd's 33-byte compressed pubkey (from its own info endpoint)
|
|
945
|
-
* — the claim packet seals to it and only it can ever read `P` early.
|
|
946
|
-
|
|
948
|
+
* — the claim packet seals to it and only it can ever read `P` early.
|
|
949
|
+
* Unset where no covclaimd is deployed: nothing is sealed and no packet
|
|
950
|
+
* is sent. Never substitute a throwaway key — nobody could open it. */
|
|
951
|
+
covclaimdPubkey?: Uint8Array;
|
|
947
952
|
/** The caller's own BOLT11 decoder, applied to the SOLVER's invoice.
|
|
948
953
|
* Required: an optional verifier is one integrators skip, and this is
|
|
949
954
|
* the check whose absence loses the whole payment. */
|
|
@@ -1032,8 +1037,9 @@ declare function requestOnchainReceive(wallet: IWallet, arkServerUrl: string, tr
|
|
|
1032
1037
|
emulatorPubkey?: string;
|
|
1033
1038
|
/** Trader's x-only L1 key for the HTLC's refund leaf. */
|
|
1034
1039
|
refundPubkey: Uint8Array;
|
|
1035
|
-
/** covclaimd's 33-byte compressed pubkey
|
|
1036
|
-
|
|
1040
|
+
/** covclaimd's 33-byte compressed pubkey, unset where none is deployed
|
|
1041
|
+
* — see {@link requestLightningReceive}. */
|
|
1042
|
+
covclaimdPubkey?: Uint8Array;
|
|
1037
1043
|
rfqId?: string;
|
|
1038
1044
|
}): Promise<{
|
|
1039
1045
|
rfqId: string;
|