@satora/swap 0.0.5 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/bitcoin-reader-esplora-GRUP7RAG.js +11 -0
- package/dist/bitcoin-reader-esplora-GRUP7RAG.js.map +1 -0
- package/dist/chunk-J35RZBDW.js +65 -0
- package/dist/chunk-J35RZBDW.js.map +1 -0
- package/dist/index.cjs +1856 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +955 -3
- package/dist/index.d.ts +955 -3
- package/dist/index.js +1770 -0
- package/dist/index.js.map +1 -1
- package/dist/node.d.cts +2 -0
- package/dist/node.d.ts +2 -0
- package/package.json +10 -3
package/README.md
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
The Satora swap client — a Lightning / on-chain BTC / Arkade ↔ EVM on/off-ramp.
|
|
4
4
|
Pure TypeScript, works in every JS environment (browser, Node, React Native).
|
|
5
5
|
|
|
6
|
-
This is the `@satora`-scoped
|
|
6
|
+
This is the `@satora`-scoped swap client. `Client` and `ClientBuilder` are
|
|
7
|
+
drop-in replacements that wrap the underlying
|
|
7
8
|
[`@lendasat/lendaswap-sdk-pure`](https://www.npmjs.com/package/@lendasat/lendaswap-sdk-pure)
|
|
8
|
-
|
|
9
|
-
backends, …)
|
|
9
|
+
client — same API, plus room for Satora-native features. Everything else
|
|
10
|
+
(`Asset`, `EvmSigner`, storage backends, types, …) is re-exported verbatim.
|
|
11
|
+
New code should import `@satora/swap`.
|
|
10
12
|
|
|
11
13
|
## Install
|
|
12
14
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// src/contracts/bitcoin-reader-esplora.ts
|
|
2
|
+
function htlcFactsFromEsploraTxs(txs, address) {
|
|
3
|
+
for (const tx of txs) {
|
|
4
|
+
const spend = tx.vin.find(
|
|
5
|
+
(vin) => vin.prevout?.scriptpubkey_address === address
|
|
6
|
+
);
|
|
7
|
+
if (spend)
|
|
8
|
+
return {
|
|
9
|
+
funding: "confirmed",
|
|
10
|
+
fundedSats: 0,
|
|
11
|
+
// already spent — the amount no longer matters
|
|
12
|
+
spendWitness: spend.witness ?? []
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const funding = txs.find(
|
|
16
|
+
(tx) => tx.vout.some((vout) => vout.scriptpubkey_address === address)
|
|
17
|
+
);
|
|
18
|
+
if (funding) {
|
|
19
|
+
const fundedSats = funding.vout.filter((vout) => vout.scriptpubkey_address === address).reduce((sum, vout) => sum + (vout.value ?? 0), 0);
|
|
20
|
+
return {
|
|
21
|
+
funding: funding.status?.confirmed ? "confirmed" : "mempool",
|
|
22
|
+
fundedSats
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return { funding: "absent", fundedSats: 0 };
|
|
26
|
+
}
|
|
27
|
+
var DEFAULT_ESPLORA_URLS = [
|
|
28
|
+
"https://mempool.space/api",
|
|
29
|
+
"https://blockstream.info/api"
|
|
30
|
+
];
|
|
31
|
+
function esploraReader(esploraUrls, fetchImpl = fetch) {
|
|
32
|
+
const bases = (Array.isArray(esploraUrls) ? esploraUrls : [esploraUrls]).map(
|
|
33
|
+
(url) => url.replace(/\/+$/, "")
|
|
34
|
+
);
|
|
35
|
+
let start = 0;
|
|
36
|
+
return {
|
|
37
|
+
async getHtlcFacts(address) {
|
|
38
|
+
const from = start++ % bases.length;
|
|
39
|
+
let lastError;
|
|
40
|
+
for (let i = 0; i < bases.length; i++) {
|
|
41
|
+
const base = bases[(from + i) % bases.length];
|
|
42
|
+
try {
|
|
43
|
+
const res = await fetchImpl(
|
|
44
|
+
`${base}/address/${encodeURIComponent(address)}/txs`
|
|
45
|
+
);
|
|
46
|
+
if (!res.ok) throw new Error(`esplora ${res.status} at ${base}`);
|
|
47
|
+
return htlcFactsFromEsploraTxs(
|
|
48
|
+
await res.json(),
|
|
49
|
+
address
|
|
50
|
+
);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
lastError = error;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
throw lastError ?? new Error("no esplora endpoints configured");
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
htlcFactsFromEsploraTxs,
|
|
62
|
+
DEFAULT_ESPLORA_URLS,
|
|
63
|
+
esploraReader
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=chunk-J35RZBDW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/contracts/bitcoin-reader-esplora.ts"],"sourcesContent":["/**\n * A esplora-backed {@link BitcoinChainReader} — the concrete chain source the\n * {@link BitcoinContractManager} uses in production.\n *\n * Kept separate from the manager so the manager stays free of any HTTP/esplora\n * dependency (and unit-testable against a fake reader). A single\n * `GET /address/{addr}/txs` yields both the funding state and the spending\n * input's witness, so no extra round-trips are needed.\n */\n\nimport type { BitcoinHtlcFacts } from \"./bitcoin.js\";\nimport type { BitcoinChainReader } from \"./bitcoin-manager.js\";\n\n/** The slice of esplora's tx JSON we read. */\ntype EsploraTx = {\n vin: Array<{\n witness?: string[];\n prevout?: { scriptpubkey_address?: string } | null;\n }>;\n vout: Array<{ scriptpubkey_address?: string; value?: number }>;\n status?: { confirmed?: boolean };\n};\n\n/**\n * Reduce an address's esplora tx history to HTLC facts. If a tx spends an output\n * at the address, that's the resolving spend (its witness classifies claim vs\n * refund); otherwise a tx paying the address is the funding.\n */\nexport function htlcFactsFromEsploraTxs(\n txs: EsploraTx[],\n address: string,\n): BitcoinHtlcFacts {\n for (const tx of txs) {\n const spend = tx.vin.find(\n (vin) => vin.prevout?.scriptpubkey_address === address,\n );\n if (spend)\n return {\n funding: \"confirmed\",\n fundedSats: 0, // already spent — the amount no longer matters\n spendWitness: spend.witness ?? [],\n };\n }\n const funding = txs.find((tx) =>\n tx.vout.some((vout) => vout.scriptpubkey_address === address),\n );\n if (funding) {\n const fundedSats = funding.vout\n .filter((vout) => vout.scriptpubkey_address === address)\n .reduce((sum, vout) => sum + (vout.value ?? 0), 0);\n return {\n funding: funding.status?.confirmed ? \"confirmed\" : \"mempool\",\n fundedSats,\n };\n }\n return { funding: \"absent\", fundedSats: 0 };\n}\n\n/**\n * Public esplora endpoints tried in rotation (mainnet). blockstream.info runs the\n * reference esplora, so it's API-compatible with mempool.space; spreading calls\n * across both halves the per-provider load and survives one being throttled.\n */\nexport const DEFAULT_ESPLORA_URLS = [\n \"https://mempool.space/api\",\n \"https://blockstream.info/api\",\n];\n\n/**\n * Build a {@link BitcoinChainReader} over one or more esplora REST endpoints.\n * With several, each call starts at a rotating endpoint (to spread load across\n * providers) and fails over to the rest on error — so a throttled or failing\n * provider doesn't stall tracking.\n */\nexport function esploraReader(\n esploraUrls: string | string[],\n fetchImpl: typeof fetch = fetch,\n): BitcoinChainReader {\n const bases = (Array.isArray(esploraUrls) ? esploraUrls : [esploraUrls]).map(\n (url) => url.replace(/\\/+$/, \"\"),\n );\n let start = 0;\n return {\n async getHtlcFacts(address) {\n const from = start++ % bases.length; // rotate the primary to spread load\n let lastError: unknown;\n for (let i = 0; i < bases.length; i++) {\n const base = bases[(from + i) % bases.length];\n try {\n const res = await fetchImpl(\n `${base}/address/${encodeURIComponent(address)}/txs`,\n );\n if (!res.ok) throw new Error(`esplora ${res.status} at ${base}`);\n return htlcFactsFromEsploraTxs(\n (await res.json()) as EsploraTx[],\n address,\n );\n } catch (error) {\n lastError = error;\n }\n }\n throw lastError ?? new Error(\"no esplora endpoints configured\");\n },\n };\n}\n"],"mappings":";AA4BO,SAAS,wBACd,KACA,SACkB;AAClB,aAAW,MAAM,KAAK;AACpB,UAAM,QAAQ,GAAG,IAAI;AAAA,MACnB,CAAC,QAAQ,IAAI,SAAS,yBAAyB;AAAA,IACjD;AACA,QAAI;AACF,aAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY;AAAA;AAAA,QACZ,cAAc,MAAM,WAAW,CAAC;AAAA,MAClC;AAAA,EACJ;AACA,QAAM,UAAU,IAAI;AAAA,IAAK,CAAC,OACxB,GAAG,KAAK,KAAK,CAAC,SAAS,KAAK,yBAAyB,OAAO;AAAA,EAC9D;AACA,MAAI,SAAS;AACX,UAAM,aAAa,QAAQ,KACxB,OAAO,CAAC,SAAS,KAAK,yBAAyB,OAAO,EACtD,OAAO,CAAC,KAAK,SAAS,OAAO,KAAK,SAAS,IAAI,CAAC;AACnD,WAAO;AAAA,MACL,SAAS,QAAQ,QAAQ,YAAY,cAAc;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,SAAS,UAAU,YAAY,EAAE;AAC5C;AAOO,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AACF;AAQO,SAAS,cACd,aACA,YAA0B,OACN;AACpB,QAAM,SAAS,MAAM,QAAQ,WAAW,IAAI,cAAc,CAAC,WAAW,GAAG;AAAA,IACvE,CAAC,QAAQ,IAAI,QAAQ,QAAQ,EAAE;AAAA,EACjC;AACA,MAAI,QAAQ;AACZ,SAAO;AAAA,IACL,MAAM,aAAa,SAAS;AAC1B,YAAM,OAAO,UAAU,MAAM;AAC7B,UAAI;AACJ,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,cAAM,OAAO,OAAO,OAAO,KAAK,MAAM,MAAM;AAC5C,YAAI;AACF,gBAAM,MAAM,MAAM;AAAA,YAChB,GAAG,IAAI,YAAY,mBAAmB,OAAO,CAAC;AAAA,UAChD;AACA,cAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,WAAW,IAAI,MAAM,OAAO,IAAI,EAAE;AAC/D,iBAAO;AAAA,YACJ,MAAM,IAAI,KAAK;AAAA,YAChB;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,sBAAY;AAAA,QACd;AAAA,MACF;AACA,YAAM,aAAa,IAAI,MAAM,iCAAiC;AAAA,IAChE;AAAA,EACF;AACF;","names":[]}
|