@satora/swap 1.5.0 → 1.6.1
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 +1 -1
- package/dist/bitcoin-reader-electrum-KEI7VWW6.js +8 -0
- package/dist/{chunk-INWVLX4A.js → chunk-3ZMSZSAV.js} +6 -4
- package/dist/chunk-3ZMSZSAV.js.map +1 -0
- package/dist/index.cjs +52 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +46 -15
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/bitcoin-reader-electrum-Z2YCNDLB.js +0 -8
- package/dist/chunk-INWVLX4A.js.map +0 -1
- /package/dist/{bitcoin-reader-electrum-Z2YCNDLB.js.map → bitcoin-reader-electrum-KEI7VWW6.js.map} +0 -0
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ npm install @satora/swap
|
|
|
18
18
|
|
|
19
19
|
## Compatibility headers
|
|
20
20
|
|
|
21
|
-
API requests include `X-Lendaswap-Client: <sdk-name>/<semver>` and `x-satora
|
|
21
|
+
API requests include `X-Lendaswap-Client: <sdk-name>/<semver>` and one `x-satora-<component>-version: <epoch>` header per protocol component (`bitcoin-htlc`, `arkade-vhtlc`, `lightning`, `evm-erc20-htlc`, `evm-native-htlc`). The server rejects a client whose epoch for a component the swap uses is too old.
|
|
22
22
|
|
|
23
23
|
## Supported swaps
|
|
24
24
|
|
|
@@ -29,9 +29,11 @@ function scriptHashOf(script) {
|
|
|
29
29
|
function electrumReader(client, opts) {
|
|
30
30
|
const network = opts?.network ?? "mainnet";
|
|
31
31
|
const fallback = opts?.fallback;
|
|
32
|
-
const scriptFor = (address) =>
|
|
33
|
-
btc.Address(toBtcSignerNetwork(network)).decode(address)
|
|
34
|
-
|
|
32
|
+
const scriptFor = (address) => {
|
|
33
|
+
const decoded = btc.Address(toBtcSignerNetwork(network)).decode(address);
|
|
34
|
+
if (!decoded) throw new Error(`Unrecognised Bitcoin address: ${address}`);
|
|
35
|
+
return btc.OutScript.encode(decoded);
|
|
36
|
+
};
|
|
35
37
|
async function getHtlcFactsElectrum(address, required) {
|
|
36
38
|
const script = scriptFor(address);
|
|
37
39
|
const scripthash = scriptHashOf(script);
|
|
@@ -152,4 +154,4 @@ function electrumReader(client, opts) {
|
|
|
152
154
|
export {
|
|
153
155
|
electrumReader
|
|
154
156
|
};
|
|
155
|
-
//# sourceMappingURL=chunk-
|
|
157
|
+
//# sourceMappingURL=chunk-3ZMSZSAV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/contracts/bitcoin-reader-electrum.ts"],"sourcesContent":["/**\n * An Electrum-backed {@link BitcoinChainReader} — reads HTLC facts from our own\n * Fulcrum over WebSocket instead of public esplora REST endpoints.\n *\n * Two advantages over the esplora reader:\n *\n * - **Freshness**: our Fulcrum sees a transaction the moment its bitcoind\n * accepts it, while public explorers index with a lag — the exact lag that\n * made a server-funding hint's targeted verify come back \"absent\" and park\n * the claim on the 60s at-risk poller.\n * - **Push**: implements the reader's optional `subscribe` capability via\n * `blockchain.scripthash.subscribe`, so the manager reconciles the moment\n * an HTLC address's history changes instead of waiting for a poll tick.\n *\n * Reads fall back to a wrapped reader (typically the esplora one) whenever the\n * Electrum server errors, so a Fulcrum outage degrades to today's behavior\n * rather than blinding the tracker.\n */\n\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport { hex } from \"@scure/base\";\nimport * as btc from \"@scure/btc-signer\";\nimport type { BitcoinHtlcFacts } from \"./bitcoin.js\";\nimport type { BitcoinChainReader } from \"./bitcoin-manager.js\";\nimport {\n type BitcoinReaderPolicy,\n resolveMinConfirmations,\n} from \"./bitcoin-reader-esplora.js\";\n\n/** One entry of `blockchain.scripthash.get_history`. */\ntype ElectrumHistoryEntry = {\n tx_hash: string;\n /** Block height; 0 for mempool, -1 for mempool with unconfirmed parents. */\n height: number;\n};\n\n/**\n * The Electrum client surface this reader needs. The pure SDK's\n * `ElectrumWsClient` satisfies it; tests inject a fake.\n */\nexport type ElectrumRpc = {\n request<T>(method: string, params: unknown[]): Promise<T>;\n subscribeScriptHash(\n scripthash: string,\n onChange: (status: string | null) => void,\n ): Promise<string | null>;\n unsubscribeScriptHash(\n scripthash: string,\n onChange: (status: string | null) => void,\n ): void;\n};\n\nexport type ElectrumReaderNetwork =\n | \"mainnet\"\n | \"testnet\"\n | \"signet\"\n | \"regtest\";\n\n/** btc-signer only ships mainnet/testnet; regtest differs in bech32 prefix. */\nconst REGTEST_NETWORK = {\n bech32: \"bcrt\",\n pubKeyHash: 0x6f,\n scriptHash: 0xc4,\n wif: 0xef,\n} as const;\n\nfunction toBtcSignerNetwork(network: ElectrumReaderNetwork) {\n switch (network) {\n case \"mainnet\":\n return btc.NETWORK;\n case \"testnet\":\n case \"signet\":\n return btc.TEST_NETWORK;\n case \"regtest\":\n return REGTEST_NETWORK;\n }\n}\n\n/** Electrum scripthash: sha256 of the output script, reversed, hex. */\nfunction scriptHashOf(script: Uint8Array): string {\n return hex.encode(sha256(script).reverse());\n}\n\n/**\n * Build a {@link BitcoinChainReader} over an Electrum connection, with push\n * support and an optional fallback reader for outages.\n */\nexport function electrumReader(\n client: ElectrumRpc,\n opts?: BitcoinReaderPolicy & {\n /** Network the HTLC addresses live on; defaults to mainnet. */\n network?: ElectrumReaderNetwork;\n /** Reader consulted when the Electrum server errors (e.g. esplora). */\n fallback?: BitcoinChainReader;\n },\n): BitcoinChainReader {\n const network = opts?.network ?? \"mainnet\";\n const fallback = opts?.fallback;\n\n const scriptFor = (address: string): Uint8Array => {\n const decoded = btc.Address(toBtcSignerNetwork(network)).decode(address);\n if (!decoded) throw new Error(`Unrecognised Bitcoin address: ${address}`);\n return btc.OutScript.encode(decoded);\n };\n\n async function getHtlcFactsElectrum(\n address: string,\n required: number,\n ): Promise<BitcoinHtlcFacts> {\n const script = scriptFor(address);\n const scripthash = scriptHashOf(script);\n const history = await client.request<ElectrumHistoryEntry[]>(\n \"blockchain.scripthash.get_history\",\n [scripthash],\n );\n if (!history || history.length === 0)\n return { funding: \"absent\", fundedSats: 0 };\n\n // HTLC addresses see at most a handful of txs (fund + resolve), so\n // fetching each raw tx is cheap.\n const txs = await Promise.all(\n history.map(async (entry) => {\n const raw = await client.request<string>(\"blockchain.transaction.get\", [\n entry.tx_hash,\n ]);\n return {\n entry,\n tx: btc.Transaction.fromRaw(hex.decode(raw), {\n allowUnknownOutputs: true,\n allowUnknownInputs: true,\n disableScriptCheck: true,\n }),\n };\n }),\n );\n\n const scriptHex = hex.encode(script);\n const outputIndicesPaying = (tx: btc.Transaction): number[] => {\n const indices: number[] = [];\n for (let i = 0; i < tx.outputsLength; i++) {\n const out = tx.getOutput(i);\n if (out.script && hex.encode(out.script) === scriptHex) indices.push(i);\n }\n return indices;\n };\n\n // Among all txs paying the address, the one paying the MOST is the\n // funding candidate — same rule as the pure SDK's UTXO lookup. The\n // address is public, so a stray dust payment (whether it landed before\n // or after the real funding) must not be mistaken for the funding and\n // observe the swap as underfunded/invalid.\n let funding: (typeof txs)[number] | undefined;\n let fundedSats = 0;\n for (const candidate of txs) {\n let paid = 0;\n for (const i of outputIndicesPaying(candidate.tx))\n paid += Number(candidate.tx.getOutput(i).amount ?? 0n);\n if (paid > fundedSats) {\n funding = candidate;\n fundedSats = paid;\n }\n }\n if (!funding) return { funding: \"absent\", fundedSats: 0 };\n const fundedVouts = outputIndicesPaying(funding.tx);\n\n // A tx spending one of the funding outputs is the resolving spend; its\n // witness classifies claim vs refund.\n for (const { tx } of txs) {\n for (let i = 0; i < tx.inputsLength; i++) {\n const input = tx.getInput(i);\n if (\n input.txid &&\n hex.encode(input.txid) === funding.entry.tx_hash &&\n input.index !== undefined &&\n fundedVouts.includes(input.index)\n ) {\n return {\n funding: \"confirmed\",\n fundedSats: 0, // already spent — the amount no longer matters\n spendWitness: (input.finalScriptWitness ?? []).map((item) =>\n hex.encode(item),\n ),\n };\n }\n }\n }\n\n // Same depth policy as the esplora reader: 0/1 read straight off the\n // confirmed flag; deeper policies need the tip to compute depth.\n const height = funding.entry.height;\n const isConfirmed = height > 0;\n let deepEnough: boolean;\n if (isConfirmed) {\n if (required <= 1) {\n deepEnough = true;\n } else {\n const tip = await client.request<{ height: number }>(\n \"blockchain.headers.subscribe\",\n [],\n );\n deepEnough = tip.height - height + 1 >= required;\n }\n } else {\n deepEnough = required === 0;\n }\n return { funding: deepEnough ? \"confirmed\" : \"mempool\", fundedSats };\n }\n\n return {\n async getHtlcFacts(address, minConfirmations) {\n const required =\n minConfirmations ?? resolveMinConfirmations(opts?.minConfirmations);\n try {\n return await getHtlcFactsElectrum(address, required);\n } catch (error) {\n if (!fallback) throw error;\n console.warn(\n \"electrumReader: falling back to secondary reader:\",\n error instanceof Error ? error.message : error,\n );\n return fallback.getHtlcFacts(address, minConfirmations);\n }\n },\n\n subscribe(address, onChange) {\n // An address the configured network can't decode (e.g. a signet address\n // under a mainnet-configured reader) must not throw out of register()\n // and abort tracking — degrade to the poll cadence instead.\n let scripthash: string;\n try {\n scripthash = scriptHashOf(scriptFor(address));\n } catch (error) {\n console.warn(\n \"electrumReader: subscribe skipped (address decode failed):\",\n error instanceof Error ? error.message : error,\n );\n return () => {};\n }\n const handler = () => onChange();\n // Best-effort: if the subscription fails the tracker's poll cadence\n // remains the backstop, so the error is logged, not thrown.\n client.subscribeScriptHash(scripthash, handler).catch((error) => {\n console.warn(\n \"electrumReader: scripthash subscribe failed:\",\n error instanceof Error ? error.message : error,\n );\n });\n return () => client.unsubscribeScriptHash(scripthash, handler);\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -149,9 +149,11 @@ function scriptHashOf(script) {
|
|
|
149
149
|
function electrumReader(client, opts) {
|
|
150
150
|
const network = opts?.network ?? "mainnet";
|
|
151
151
|
const fallback2 = opts?.fallback;
|
|
152
|
-
const scriptFor = (address) =>
|
|
153
|
-
btc.Address(toBtcSignerNetwork(network)).decode(address)
|
|
154
|
-
|
|
152
|
+
const scriptFor = (address) => {
|
|
153
|
+
const decoded = btc.Address(toBtcSignerNetwork(network)).decode(address);
|
|
154
|
+
if (!decoded) throw new Error(`Unrecognised Bitcoin address: ${address}`);
|
|
155
|
+
return btc.OutScript.encode(decoded);
|
|
156
|
+
};
|
|
155
157
|
async function getHtlcFactsElectrum(address, required) {
|
|
156
158
|
const script = scriptFor(address);
|
|
157
159
|
const scripthash = scriptHashOf(script);
|
|
@@ -671,7 +673,7 @@ function payOnLightningStatus(serverHtlc) {
|
|
|
671
673
|
}
|
|
672
674
|
|
|
673
675
|
// src/client.ts
|
|
674
|
-
var
|
|
676
|
+
var import_lendaswap_sdk_pure3 = require("@lendasat/lendaswap-sdk-pure");
|
|
675
677
|
|
|
676
678
|
// src/contracts/arkade-manager.ts
|
|
677
679
|
var import_sdk2 = require("@arkade-os/sdk");
|
|
@@ -1117,7 +1119,9 @@ var AVG_BLOCK_MS = {
|
|
|
1117
1119
|
1: 12e3,
|
|
1118
1120
|
137: 2100,
|
|
1119
1121
|
42161: 250,
|
|
1120
|
-
30: 3e4
|
|
1122
|
+
30: 3e4,
|
|
1123
|
+
31: 3e4
|
|
1124
|
+
// Rootstock testnet: same merge-mined cadence
|
|
1121
1125
|
};
|
|
1122
1126
|
var SCAN_MARGIN_BLOCKS = 1000n;
|
|
1123
1127
|
var EvmContractManager = class _EvmContractManager {
|
|
@@ -1298,7 +1302,10 @@ var EvmContractManager = class _EvmContractManager {
|
|
|
1298
1302
|
for (const ref of refs) {
|
|
1299
1303
|
const { observation, preimage } = evmObservation(
|
|
1300
1304
|
events.get(refQueryKey(ref)) ?? [],
|
|
1301
|
-
{
|
|
1305
|
+
{
|
|
1306
|
+
amount: ref.minAmount ?? ref.expectedAmount,
|
|
1307
|
+
token: ref.expectedToken
|
|
1308
|
+
}
|
|
1302
1309
|
);
|
|
1303
1310
|
const key = htlcKey(ref);
|
|
1304
1311
|
if (preimage) this.#preimages.set(key, preimage);
|
|
@@ -1375,7 +1382,8 @@ var DEFAULT_EVM_RPCS = {
|
|
|
1375
1382
|
"https://arbitrum-one-rpc.publicnode.com"
|
|
1376
1383
|
],
|
|
1377
1384
|
// Rootstock: the public node, HTTP only (no WebSocket endpoint exists).
|
|
1378
|
-
30: ["https://public-node.rsk.co"]
|
|
1385
|
+
30: ["https://public-node.rsk.co"],
|
|
1386
|
+
31: ["https://public-node.testnet.rsk.co"]
|
|
1379
1387
|
};
|
|
1380
1388
|
var SWAP_CREATED = (0, import_viem.parseAbiItem)(
|
|
1381
1389
|
"event SwapCreated(bytes32 indexed preimageHash, address indexed refundAddress, address indexed claimAddress, address token, uint256 amount, uint256 timelock, bytes32 key)"
|
|
@@ -1576,7 +1584,8 @@ function createEvmRpcReader(rpcUrls, options = {}) {
|
|
|
1576
1584
|
return evmReaderFromClient(client, options);
|
|
1577
1585
|
}
|
|
1578
1586
|
var EVM_LOG_RANGE_LIMITS = {
|
|
1579
|
-
30: 2000n
|
|
1587
|
+
30: 2000n,
|
|
1588
|
+
31: 2000n
|
|
1580
1589
|
};
|
|
1581
1590
|
function defaultEvmReaders(overrides) {
|
|
1582
1591
|
const chainIds = /* @__PURE__ */ new Set([
|
|
@@ -2049,6 +2058,9 @@ function defaultWebSocketFactory(url) {
|
|
|
2049
2058
|
return new WS(url);
|
|
2050
2059
|
}
|
|
2051
2060
|
|
|
2061
|
+
// src/tracker/from-swap.ts
|
|
2062
|
+
var import_lendaswap_sdk_pure2 = require("@lendasat/lendaswap-sdk-pure");
|
|
2063
|
+
|
|
2052
2064
|
// src/contracts/arkade-vhtlc.ts
|
|
2053
2065
|
var import_sdk3 = require("@arkade-os/sdk");
|
|
2054
2066
|
var import_lendaswap_sdk_pure = require("@lendasat/lendaswap-sdk-pure");
|
|
@@ -2134,6 +2146,7 @@ function evmLeg(args) {
|
|
|
2134
2146
|
preimageHash: ensure0x(args.hashLock),
|
|
2135
2147
|
claimAddress: ensure0x(args.claimAddress),
|
|
2136
2148
|
expectedAmount: BigInt(args.expectedSats),
|
|
2149
|
+
minAmount: args.minAmount,
|
|
2137
2150
|
expectedToken: args.token ? ensure0x(args.token) : void 0,
|
|
2138
2151
|
sender: args.sender ? ensure0x(args.sender) : void 0,
|
|
2139
2152
|
timelockSec: args.timelockSec,
|
|
@@ -2141,6 +2154,13 @@ function evmLeg(args) {
|
|
|
2141
2154
|
};
|
|
2142
2155
|
}
|
|
2143
2156
|
var CLIENT_FUNDING_MIN_CONFIRMATIONS = 1;
|
|
2157
|
+
var FEE_ROUNDING_SLACK_SATS = 2;
|
|
2158
|
+
function minServerPayout(r) {
|
|
2159
|
+
return Math.max(
|
|
2160
|
+
0,
|
|
2161
|
+
Number(r.target_amount) - r.fee_sats - FEE_ROUNDING_SLACK_SATS
|
|
2162
|
+
);
|
|
2163
|
+
}
|
|
2144
2164
|
function bitcoinLeg(address, hashLock, expectedSats, minConfirmations) {
|
|
2145
2165
|
return {
|
|
2146
2166
|
ledger: "bitcoin",
|
|
@@ -2185,15 +2205,19 @@ function swapToTracked(stored) {
|
|
|
2185
2205
|
claimAddress: r.server_evm_address,
|
|
2186
2206
|
// the server claims the client's EVM HTLC
|
|
2187
2207
|
expectedSats: r.evm_expected_sats,
|
|
2188
|
-
|
|
2189
|
-
//
|
|
2190
|
-
token
|
|
2191
|
-
|
|
2192
|
-
// the
|
|
2208
|
+
minAmount: 0n,
|
|
2209
|
+
// see SHORT_LOCK_RULE
|
|
2210
|
+
// A native lock's asset word is zero; an ERC20 lock's token is not
|
|
2211
|
+
// on this response yet, so fall back to the per-chain mainnet
|
|
2212
|
+
// constant to complete the isActive tuple.
|
|
2213
|
+
token: r.evm_htlc_kind === "native" ? import_lendaswap_sdk_pure2.NATIVE_TOKEN_ADDRESS : lockedTokenFallback(r.evm_chain_id, r.network),
|
|
2214
|
+
// The coordinator created the HTLC on the client's behalf, so it
|
|
2215
|
+
// is the lock's sender (refund address), as on evm_to_lightning.
|
|
2216
|
+
sender: r.evm_coordinator_address,
|
|
2193
2217
|
timelockSec: r.evm_refund_locktime,
|
|
2194
2218
|
createdAt: r.created_at
|
|
2195
2219
|
}),
|
|
2196
|
-
serverHtlc: arkadeLeg(r, r.btc_vhtlc_address,
|
|
2220
|
+
serverHtlc: arkadeLeg(r, r.btc_vhtlc_address, minServerPayout(r)),
|
|
2197
2221
|
clientRefundLocktime: ms(r.evm_refund_locktime),
|
|
2198
2222
|
serverRefundLocktime: ms(r.vhtlc_refund_locktime)
|
|
2199
2223
|
};
|
|
@@ -2234,16 +2258,19 @@ function swapToTracked(stored) {
|
|
|
2234
2258
|
claimAddress: r.server_evm_address,
|
|
2235
2259
|
// the server claims the client's EVM HTLC
|
|
2236
2260
|
expectedSats: r.evm_expected_sats,
|
|
2261
|
+
minAmount: 0n,
|
|
2262
|
+
// see SHORT_LOCK_RULE
|
|
2237
2263
|
token: r.wbtc_address,
|
|
2238
|
-
|
|
2239
|
-
// the
|
|
2264
|
+
// The coordinator created the HTLC on the client's behalf, so it
|
|
2265
|
+
// is the lock's sender (refund address).
|
|
2266
|
+
sender: r.evm_coordinator_address,
|
|
2240
2267
|
timelockSec: r.evm_refund_locktime,
|
|
2241
2268
|
createdAt: r.created_at
|
|
2242
2269
|
}),
|
|
2243
2270
|
serverHtlc: bitcoinLeg(
|
|
2244
2271
|
r.btc_htlc_address,
|
|
2245
2272
|
r.evm_hash_lock,
|
|
2246
|
-
|
|
2273
|
+
minServerPayout(r)
|
|
2247
2274
|
),
|
|
2248
2275
|
clientRefundLocktime: ms(r.evm_refund_locktime),
|
|
2249
2276
|
serverRefundLocktime: ms(r.btc_refund_locktime)
|
|
@@ -2729,7 +2756,7 @@ var Client = class {
|
|
|
2729
2756
|
/** Read per chain read, so it can change without rebuilding the client. */
|
|
2730
2757
|
#bitcoinMinConfirmations;
|
|
2731
2758
|
constructor(...args) {
|
|
2732
|
-
if (args[0] instanceof
|
|
2759
|
+
if (args[0] instanceof import_lendaswap_sdk_pure3.Client) {
|
|
2733
2760
|
this.#legacy = args[0];
|
|
2734
2761
|
this.#tracking = args[1] ?? {
|
|
2735
2762
|
enabled: false
|
|
@@ -2737,7 +2764,7 @@ var Client = class {
|
|
|
2737
2764
|
assertMinConfirmations(this.#tracking.bitcoinMinConfirmations);
|
|
2738
2765
|
this.#bitcoinMinConfirmations = this.#tracking.bitcoinMinConfirmations;
|
|
2739
2766
|
} else {
|
|
2740
|
-
this.#legacy = new
|
|
2767
|
+
this.#legacy = new import_lendaswap_sdk_pure3.Client(
|
|
2741
2768
|
...args
|
|
2742
2769
|
);
|
|
2743
2770
|
this.#tracking = { enabled: false };
|
|
@@ -2918,6 +2945,10 @@ var Client = class {
|
|
|
2918
2945
|
return this.#legacy.claim(...args);
|
|
2919
2946
|
}
|
|
2920
2947
|
/** Delegated to the legacy client (migration checkpoint). */
|
|
2948
|
+
claimEvmWithSigner(...args) {
|
|
2949
|
+
return this.#legacy.claimEvmWithSigner(...args);
|
|
2950
|
+
}
|
|
2951
|
+
/** Delegated to the legacy client (migration checkpoint). */
|
|
2921
2952
|
claimViaGasless(...args) {
|
|
2922
2953
|
return this.#legacy.claimViaGasless(...args);
|
|
2923
2954
|
}
|
|
@@ -3305,7 +3336,7 @@ var Client = class {
|
|
|
3305
3336
|
"bitcoin",
|
|
3306
3337
|
await BitcoinContractManager.create({
|
|
3307
3338
|
esploraUrl: esploraUrl ? [esploraUrl] : DEFAULT_ESPLORA_URLS,
|
|
3308
|
-
electrumWsUrl: electrumWsUrl ??
|
|
3339
|
+
electrumWsUrl: electrumWsUrl ?? import_lendaswap_sdk_pure3.DEFAULT_ELECTRUM_WS_URLS[network],
|
|
3309
3340
|
network,
|
|
3310
3341
|
chainTime,
|
|
3311
3342
|
minConfirmations: () => this.#bitcoinMinConfirmations
|
|
@@ -3316,7 +3347,7 @@ var Client = class {
|
|
|
3316
3347
|
}
|
|
3317
3348
|
};
|
|
3318
3349
|
var ClientBuilder = class {
|
|
3319
|
-
#inner =
|
|
3350
|
+
#inner = import_lendaswap_sdk_pure3.Client.builder();
|
|
3320
3351
|
// Observe-mode tracking is on by default; the built client auto-builds its
|
|
3321
3352
|
// managers from config unless disabled or given an explicit override.
|
|
3322
3353
|
#trackingEnabled = true;
|