@owney/sdk 0.7.26-beta.4 → 0.7.26-beta.6
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.cjs +842 -116
- package/dist/index.d.cts +328 -34
- package/dist/index.d.ts +328 -34
- package/dist/index.js +845 -115
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2294,11 +2294,12 @@ function createSwapApi(baseUrl, apiKey) {
|
|
|
2294
2294
|
baseUrl,
|
|
2295
2295
|
apiKey,
|
|
2296
2296
|
`/tokens/search?${new URLSearchParams({
|
|
2297
|
-
query: params.query,
|
|
2297
|
+
...params.query === void 0 ? {} : { query: params.query },
|
|
2298
2298
|
// Omitted, the routing API searches every supported chain — which is
|
|
2299
2299
|
// what a picker wants, since its rows already span all three.
|
|
2300
2300
|
...params.chainId === void 0 ? {} : { chainId: String(params.chainId) },
|
|
2301
|
-
...params.limit === void 0 ? {} : { limit: String(params.limit) }
|
|
2301
|
+
...params.limit === void 0 ? {} : { limit: String(params.limit) },
|
|
2302
|
+
...params.direction === void 0 ? {} : { direction: params.direction }
|
|
2302
2303
|
}).toString()}`
|
|
2303
2304
|
),
|
|
2304
2305
|
/**
|
|
@@ -2384,12 +2385,41 @@ function createSwapApi(baseUrl, apiKey) {
|
|
|
2384
2385
|
// src/lib/swap/swap.rpc.ts
|
|
2385
2386
|
import { fallback, http as http2 } from "viem";
|
|
2386
2387
|
var DEFAULT_RPC_URLS = {
|
|
2387
|
-
|
|
2388
|
+
// NOT cloudflare-eth.com, which used to lead this list. It answers
|
|
2389
|
+
// eth_chainId happily, errors on eth_blockNumber, and — the part that
|
|
2390
|
+
// actually broke things — returns `result: null` for the receipt of a
|
|
2391
|
+
// transaction that is demonstrably mined. Null is a VALID answer meaning
|
|
2392
|
+
// "not found", so viem's fallback has no reason to try the next endpoint:
|
|
2393
|
+
// waitForTransactionReceipt simply polls until it times out, which on this
|
|
2394
|
+
// chain is ten minutes of a spinner (ROUT-242). An endpoint that ERRORS is
|
|
2395
|
+
// safe; an endpoint that lies quietly is not.
|
|
2396
|
+
1: ["https://ethereum-rpc.publicnode.com", "https://eth.drpc.org"],
|
|
2388
2397
|
8453: ["https://mainnet.base.org", "https://base-rpc.publicnode.com"],
|
|
2389
2398
|
42161: [
|
|
2390
2399
|
"https://arb1.arbitrum.io/rpc",
|
|
2391
2400
|
"https://arbitrum-one-rpc.publicnode.com"
|
|
2392
|
-
]
|
|
2401
|
+
],
|
|
2402
|
+
// Added with the wider swap chain set (ROUT-242, comment 15982). Every one
|
|
2403
|
+
// of these answered with `access-control-allow-origin: *` on 2026-09-29;
|
|
2404
|
+
// a chain without two verified endpoints does not belong in the list.
|
|
2405
|
+
10: ["https://mainnet.optimism.io", "https://optimism-rpc.publicnode.com"],
|
|
2406
|
+
// polygon-rpc.com led this list until it started answering every call with
|
|
2407
|
+
// "API key disabled, reason: tenant disabled". It errors rather than lying,
|
|
2408
|
+
// so the fallback did cover it — at the cost of a failed request in front of
|
|
2409
|
+
// every Polygon read.
|
|
2410
|
+
137: ["https://polygon-bor-rpc.publicnode.com", "https://polygon.drpc.org"],
|
|
2411
|
+
56: ["https://bsc-dataseed.bnbchain.org", "https://bsc-rpc.publicnode.com"],
|
|
2412
|
+
43114: [
|
|
2413
|
+
"https://api.avax.network/ext/bc/C/rpc",
|
|
2414
|
+
"https://avalanche-c-chain-rpc.publicnode.com"
|
|
2415
|
+
],
|
|
2416
|
+
143: ["https://rpc.monad.xyz", "https://rpc1.monad.xyz"],
|
|
2417
|
+
// ONE endpoint, not two: of the six the public chain registry lists for Arc,
|
|
2418
|
+
// this is the only one that answers a browser at all. viem ships none. It
|
|
2419
|
+
// was checked with a real eth_chainId call (0x13b2), not just a CORS header,
|
|
2420
|
+
// but a single provider is a single point of failure - add a second when one
|
|
2421
|
+
// exists.
|
|
2422
|
+
5042: ["https://rpc.beamrpc.com"]
|
|
2393
2423
|
};
|
|
2394
2424
|
function swapReadTransport(chainId, overrides) {
|
|
2395
2425
|
const override = overrides?.[chainId];
|
|
@@ -2402,6 +2432,167 @@ function receiptTimeoutMs(chainId) {
|
|
|
2402
2432
|
return chainId === 1 ? 6e5 : 18e4;
|
|
2403
2433
|
}
|
|
2404
2434
|
|
|
2435
|
+
// src/lib/swap/swap.wrap.ts
|
|
2436
|
+
var WRAP_SELECTOR = "0xd0e30db0";
|
|
2437
|
+
var FALLBACK_WRAP_GAS = 50000n;
|
|
2438
|
+
var APPROVE_GAS = 60000n;
|
|
2439
|
+
var GAS_SAFETY = 2n;
|
|
2440
|
+
var MIN_WALLET_GAS_PRICE = 3000000000n;
|
|
2441
|
+
async function wrapNative(deps, options) {
|
|
2442
|
+
const { chainId, wrapper, nativeSymbol, requested } = options;
|
|
2443
|
+
const balance = await deps.readNativeBalance();
|
|
2444
|
+
let wrapGas;
|
|
2445
|
+
try {
|
|
2446
|
+
wrapGas = await deps.estimateWrapGas(wrapper, requested);
|
|
2447
|
+
} catch (error) {
|
|
2448
|
+
wrapGas = FALLBACK_WRAP_GAS;
|
|
2449
|
+
debugLog("owney-sdk", "wrap: gas estimate failed, using the fallback", {
|
|
2450
|
+
fallback: FALLBACK_WRAP_GAS.toString(),
|
|
2451
|
+
message: error instanceof Error ? error.message : String(error)
|
|
2452
|
+
});
|
|
2453
|
+
}
|
|
2454
|
+
const measured = await deps.getMaxFeePerGas();
|
|
2455
|
+
const gasPrice = measured > MIN_WALLET_GAS_PRICE ? measured : MIN_WALLET_GAS_PRICE;
|
|
2456
|
+
const reserve = (wrapGas + APPROVE_GAS) * gasPrice * GAS_SAFETY;
|
|
2457
|
+
const spendable = balance > reserve ? balance - reserve : 0n;
|
|
2458
|
+
const wrapped = requested < spendable ? requested : spendable;
|
|
2459
|
+
debugLog("owney-sdk", "wrap: sizing", {
|
|
2460
|
+
balance: balance.toString(),
|
|
2461
|
+
requested: requested.toString(),
|
|
2462
|
+
measuredGasPrice: measured.toString(),
|
|
2463
|
+
reservedAtGasPrice: gasPrice.toString(),
|
|
2464
|
+
reserve: reserve.toString(),
|
|
2465
|
+
wrapped: wrapped.toString()
|
|
2466
|
+
});
|
|
2467
|
+
if (wrapped <= 0n) {
|
|
2468
|
+
throw new OwneyError(
|
|
2469
|
+
"SWAP_INSUFFICIENT_GAS",
|
|
2470
|
+
`Not enough ${nativeSymbol} to cover both the swap and its network fees. Leave a little ${nativeSymbol} for gas, or swap a smaller amount.`,
|
|
2471
|
+
{
|
|
2472
|
+
chainId,
|
|
2473
|
+
// Named in the details as well as the message so the app's own copy
|
|
2474
|
+
// can say "leave a little POL" rather than re-deriving it.
|
|
2475
|
+
symbol: nativeSymbol,
|
|
2476
|
+
balance: balance.toString(),
|
|
2477
|
+
requested: requested.toString(),
|
|
2478
|
+
reserve: reserve.toString()
|
|
2479
|
+
}
|
|
2480
|
+
);
|
|
2481
|
+
}
|
|
2482
|
+
await deps.ensureChain(chainId);
|
|
2483
|
+
debugLog("owney-sdk", "wrap: sending deposit()", {
|
|
2484
|
+
wrapper,
|
|
2485
|
+
value: wrapped.toString()
|
|
2486
|
+
});
|
|
2487
|
+
const txHash = await deps.sendTransaction(
|
|
2488
|
+
{ to: wrapper, data: WRAP_SELECTOR, value: wrapped.toString() },
|
|
2489
|
+
options.onSubmitted
|
|
2490
|
+
);
|
|
2491
|
+
return { wrapped, txHash };
|
|
2492
|
+
}
|
|
2493
|
+
function requireWrapper(quote) {
|
|
2494
|
+
const wrapper = quote.wrappedNative;
|
|
2495
|
+
if (!wrapper?.address) {
|
|
2496
|
+
throw new OwneyError(
|
|
2497
|
+
"SWAP_NATIVE_UNSUPPORTED",
|
|
2498
|
+
`Swapping ${quote.src.symbol} from this chain to another isn't supported yet. Swap a token instead, or move to the destination chain first.`,
|
|
2499
|
+
{ chainId: quote.src.chainId, symbol: quote.src.symbol }
|
|
2500
|
+
);
|
|
2501
|
+
}
|
|
2502
|
+
return { symbol: wrapper.symbol, address: wrapper.address };
|
|
2503
|
+
}
|
|
2504
|
+
|
|
2505
|
+
// src/lib/swap/swap.chains.ts
|
|
2506
|
+
import {
|
|
2507
|
+
arbitrum as arbitrum2,
|
|
2508
|
+
arc,
|
|
2509
|
+
avalanche,
|
|
2510
|
+
base as base2,
|
|
2511
|
+
bsc,
|
|
2512
|
+
mainnet as mainnet2,
|
|
2513
|
+
monad,
|
|
2514
|
+
optimism,
|
|
2515
|
+
polygon
|
|
2516
|
+
} from "viem/chains";
|
|
2517
|
+
var CHAINS = {
|
|
2518
|
+
8453: base2,
|
|
2519
|
+
42161: arbitrum2,
|
|
2520
|
+
1: mainnet2,
|
|
2521
|
+
10: optimism,
|
|
2522
|
+
137: polygon,
|
|
2523
|
+
56: bsc,
|
|
2524
|
+
43114: avalanche,
|
|
2525
|
+
143: monad,
|
|
2526
|
+
5042: arc
|
|
2527
|
+
};
|
|
2528
|
+
var SWAP_CHAIN_IDS = Object.keys(CHAINS).map(Number);
|
|
2529
|
+
function swapChain(chainId) {
|
|
2530
|
+
return CHAINS[chainId];
|
|
2531
|
+
}
|
|
2532
|
+
|
|
2533
|
+
// src/lib/swap/swap.arrival.ts
|
|
2534
|
+
var DEFAULT_TIMEOUT_MS = 18e4;
|
|
2535
|
+
var DEFAULT_POLL_MS = 4e3;
|
|
2536
|
+
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
2537
|
+
async function awaitWithdrawalArrival(options) {
|
|
2538
|
+
const { arrived, lastReadError } = await awaitBalanceIncrease(options);
|
|
2539
|
+
if (arrived !== null) return arrived;
|
|
2540
|
+
throw new OwneyError(
|
|
2541
|
+
"WITHDRAW_ARRIVAL_TIMEOUT",
|
|
2542
|
+
"The withdrawal was accepted but the funds had not arrived in time to swap them. They are on their way to your wallet in the original asset.",
|
|
2543
|
+
{
|
|
2544
|
+
baseline: options.baseline.toString(),
|
|
2545
|
+
waitedMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
2546
|
+
...lastReadError ? { lastReadError } : {}
|
|
2547
|
+
}
|
|
2548
|
+
);
|
|
2549
|
+
}
|
|
2550
|
+
async function awaitBalanceIncrease(options) {
|
|
2551
|
+
const {
|
|
2552
|
+
readBalance,
|
|
2553
|
+
baseline,
|
|
2554
|
+
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
2555
|
+
pollMs = DEFAULT_POLL_MS
|
|
2556
|
+
} = options;
|
|
2557
|
+
const deadline = Date.now() + timeoutMs;
|
|
2558
|
+
debugLog("owney-sdk", "arrival: waiting for funds to land", {
|
|
2559
|
+
baseline: baseline.toString(),
|
|
2560
|
+
timeoutMs
|
|
2561
|
+
});
|
|
2562
|
+
let lastError;
|
|
2563
|
+
for (; ; ) {
|
|
2564
|
+
try {
|
|
2565
|
+
const balance = await readBalance();
|
|
2566
|
+
if (balance > baseline) {
|
|
2567
|
+
const arrived = balance - baseline;
|
|
2568
|
+
debugLog("owney-sdk", "arrival: funds landed", {
|
|
2569
|
+
arrived: arrived.toString()
|
|
2570
|
+
});
|
|
2571
|
+
return { arrived };
|
|
2572
|
+
}
|
|
2573
|
+
} catch (error) {
|
|
2574
|
+
lastError = error;
|
|
2575
|
+
debugLog("owney-sdk", "arrival: balance read failed, retrying", {
|
|
2576
|
+
message: error instanceof Error ? error.message : String(error)
|
|
2577
|
+
});
|
|
2578
|
+
}
|
|
2579
|
+
if (Date.now() >= deadline) {
|
|
2580
|
+
debugLog("owney-sdk", "arrival: nothing landed before the deadline", {
|
|
2581
|
+
baseline: baseline.toString(),
|
|
2582
|
+
waitedMs: timeoutMs,
|
|
2583
|
+
...lastError ? {
|
|
2584
|
+
lastReadError: lastError instanceof Error ? lastError.message : String(lastError)
|
|
2585
|
+
} : {}
|
|
2586
|
+
});
|
|
2587
|
+
return lastError ? {
|
|
2588
|
+
arrived: null,
|
|
2589
|
+
lastReadError: lastError instanceof Error ? lastError.message : String(lastError)
|
|
2590
|
+
} : { arrived: null };
|
|
2591
|
+
}
|
|
2592
|
+
await sleep(pollMs);
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2405
2596
|
// src/lib/permit2.ts
|
|
2406
2597
|
import { bytesToHex } from "viem";
|
|
2407
2598
|
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
@@ -2525,17 +2716,17 @@ var SWAP_TERMINAL_STATUSES = [
|
|
|
2525
2716
|
var isSwapTerminal = (status) => SWAP_TERMINAL_STATUSES.includes(status);
|
|
2526
2717
|
|
|
2527
2718
|
// src/lib/swap/swap.order-runner.ts
|
|
2528
|
-
var
|
|
2719
|
+
var DEFAULT_POLL_MS2 = 5e3;
|
|
2529
2720
|
var MAX_BACKOFF_MS = 3e4;
|
|
2530
|
-
var backoffFor = (failures,
|
|
2531
|
-
var
|
|
2721
|
+
var backoffFor = (failures, base4) => Math.min(base4 * 2 ** Math.min(failures, 5), MAX_BACKOFF_MS);
|
|
2722
|
+
var DEFAULT_TIMEOUT_MS2 = 15 * 60 * 1e3;
|
|
2532
2723
|
async function runFusionOrder(deps, options) {
|
|
2533
2724
|
const {
|
|
2534
2725
|
orderHash,
|
|
2535
2726
|
secrets,
|
|
2536
2727
|
onStage,
|
|
2537
|
-
pollIntervalMs =
|
|
2538
|
-
timeoutMs =
|
|
2728
|
+
pollIntervalMs = DEFAULT_POLL_MS2,
|
|
2729
|
+
timeoutMs = DEFAULT_TIMEOUT_MS2
|
|
2539
2730
|
} = options;
|
|
2540
2731
|
const deadline = deps.now() + timeoutMs;
|
|
2541
2732
|
let failures = 0;
|
|
@@ -2546,7 +2737,11 @@ async function runFusionOrder(deps, options) {
|
|
|
2546
2737
|
throw new OwneyError(
|
|
2547
2738
|
"SWAP_REQUEST_FAILED",
|
|
2548
2739
|
"Timed out waiting for the swap to settle. It may still complete \u2014 check the order status before retrying.",
|
|
2549
|
-
|
|
2740
|
+
// Marks the one failure that means "we stopped watching a live order",
|
|
2741
|
+
// as opposed to a verdict or a prompt nobody answered. The executor
|
|
2742
|
+
// checks the wallet before believing it: resolvers do not stop filling
|
|
2743
|
+
// because we stopped looking (ROUT-242, comment 15980).
|
|
2744
|
+
{ orderHash, settlementUnconfirmed: true }
|
|
2550
2745
|
);
|
|
2551
2746
|
}
|
|
2552
2747
|
let ready;
|
|
@@ -2599,10 +2794,10 @@ async function runFusionOrder(deps, options) {
|
|
|
2599
2794
|
}
|
|
2600
2795
|
|
|
2601
2796
|
// src/lib/swap/swap.same-chain-runner.ts
|
|
2602
|
-
var
|
|
2797
|
+
var DEFAULT_POLL_MS3 = 5e3;
|
|
2603
2798
|
var MAX_BACKOFF_MS2 = 3e4;
|
|
2604
|
-
var backoffFor2 = (failures,
|
|
2605
|
-
var
|
|
2799
|
+
var backoffFor2 = (failures, base4) => Math.min(base4 * 2 ** Math.min(failures, 5), MAX_BACKOFF_MS2);
|
|
2800
|
+
var DEFAULT_TIMEOUT_MS3 = 3 * 60 * 1e3;
|
|
2606
2801
|
function explain(status) {
|
|
2607
2802
|
switch (status) {
|
|
2608
2803
|
case "expired":
|
|
@@ -2625,8 +2820,8 @@ async function runSameChainOrder(deps, options) {
|
|
|
2625
2820
|
const {
|
|
2626
2821
|
orderHash,
|
|
2627
2822
|
onStage,
|
|
2628
|
-
pollIntervalMs =
|
|
2629
|
-
timeoutMs =
|
|
2823
|
+
pollIntervalMs = DEFAULT_POLL_MS3,
|
|
2824
|
+
timeoutMs = DEFAULT_TIMEOUT_MS3
|
|
2630
2825
|
} = options;
|
|
2631
2826
|
const deadline = deps.now() + timeoutMs;
|
|
2632
2827
|
let failures = 0;
|
|
@@ -2724,6 +2919,35 @@ function listOrders(now = Date.now()) {
|
|
|
2724
2919
|
}
|
|
2725
2920
|
|
|
2726
2921
|
// src/lib/swap/swap.executor.ts
|
|
2922
|
+
var WALLET_PROMPT_TIMEOUT_MS = 3 * 60 * 1e3;
|
|
2923
|
+
async function awaitWalletPrompt(prompt, what) {
|
|
2924
|
+
let timer;
|
|
2925
|
+
try {
|
|
2926
|
+
return await Promise.race([
|
|
2927
|
+
prompt(),
|
|
2928
|
+
new Promise((_, reject) => {
|
|
2929
|
+
timer = setTimeout(() => {
|
|
2930
|
+
reject(
|
|
2931
|
+
new OwneyError(
|
|
2932
|
+
"SWAP_WALLET_PROMPT_TIMEOUT",
|
|
2933
|
+
// Naming the stale request matters: the wallet is still holding
|
|
2934
|
+
// it, which is why the next connection attempt is refused too
|
|
2935
|
+
// ("Connection can be declined if a previous request is still
|
|
2936
|
+
// active"). Dismissing it is what actually unblocks them.
|
|
2937
|
+
`Your wallet didn't answer the request to ${what}. Open your wallet, dismiss any request still waiting there, and try again.`,
|
|
2938
|
+
{ prompt: what, timeoutMs: WALLET_PROMPT_TIMEOUT_MS }
|
|
2939
|
+
)
|
|
2940
|
+
);
|
|
2941
|
+
}, WALLET_PROMPT_TIMEOUT_MS);
|
|
2942
|
+
})
|
|
2943
|
+
]);
|
|
2944
|
+
} finally {
|
|
2945
|
+
if (timer) clearTimeout(timer);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
function stoppedWatching(error) {
|
|
2949
|
+
return error instanceof OwneyError && error.details?.settlementUnconfirmed === true;
|
|
2950
|
+
}
|
|
2727
2951
|
var DEFAULT_SLIPPAGE = 1;
|
|
2728
2952
|
async function affordableAmount(deps, quoted) {
|
|
2729
2953
|
const balance = await deps.readSourceBalance();
|
|
@@ -2746,21 +2970,39 @@ async function executeSwap(deps, options) {
|
|
|
2746
2970
|
});
|
|
2747
2971
|
const before = await deps.readTargetBalance();
|
|
2748
2972
|
debugLog("owney-sdk", "swap: target balance before", before.toString());
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2973
|
+
let result;
|
|
2974
|
+
let railError;
|
|
2975
|
+
try {
|
|
2976
|
+
result = quote.rail === "classic" ? await runClassic(deps, options) : quote.rail === "fusion" ? await runSameChainFusion(deps, options, walletAddress) : await runFusion(deps, options, walletAddress);
|
|
2977
|
+
} catch (error) {
|
|
2978
|
+
if (!stoppedWatching(error)) throw error;
|
|
2979
|
+
railError = error;
|
|
2980
|
+
debugLog("owney-sdk", "swap: rail failed, checking whether funds landed", {
|
|
2981
|
+
message: error instanceof Error ? error.message : String(error)
|
|
2982
|
+
});
|
|
2983
|
+
}
|
|
2984
|
+
const { arrived } = await awaitBalanceIncrease({
|
|
2985
|
+
readBalance: () => deps.readTargetBalance(),
|
|
2986
|
+
baseline: before,
|
|
2987
|
+
...options.arrivalTimeoutMs === void 0 ? {} : { timeoutMs: options.arrivalTimeoutMs },
|
|
2988
|
+
...options.arrivalPollMs === void 0 ? {} : { pollMs: options.arrivalPollMs }
|
|
2755
2989
|
});
|
|
2756
|
-
if (
|
|
2990
|
+
if (arrived === null) {
|
|
2991
|
+
if (railError) throw railError;
|
|
2757
2992
|
throw new OwneyError(
|
|
2758
2993
|
"SWAP_REQUEST_FAILED",
|
|
2759
2994
|
"The swap completed but no funds arrived in the wallet. Check the transaction before retrying.",
|
|
2760
|
-
{ rail: quote.rail, ...result }
|
|
2995
|
+
{ rail: quote.rail, ...result ?? {} }
|
|
2761
2996
|
);
|
|
2762
2997
|
}
|
|
2763
|
-
|
|
2998
|
+
if (railError) {
|
|
2999
|
+
debugLog("owney-sdk", "swap: rail gave up but the funds are here", {
|
|
3000
|
+
received: arrived.toString()
|
|
3001
|
+
});
|
|
3002
|
+
const orderHash = railError.details?.orderHash;
|
|
3003
|
+
if (orderHash) clearOrder(orderHash);
|
|
3004
|
+
}
|
|
3005
|
+
return { received: arrived.toString(), ...result ?? {} };
|
|
2764
3006
|
}
|
|
2765
3007
|
async function runClassic(deps, options) {
|
|
2766
3008
|
const {
|
|
@@ -2840,7 +3082,10 @@ async function runSameChainFusion(deps, options, walletAddress) {
|
|
|
2840
3082
|
});
|
|
2841
3083
|
onStage?.("signing");
|
|
2842
3084
|
await deps.ensureChain(quote.src.chainId);
|
|
2843
|
-
const signature = await
|
|
3085
|
+
const signature = await awaitWalletPrompt(
|
|
3086
|
+
() => deps.signTypedData(built.typedData),
|
|
3087
|
+
"sign the swap"
|
|
3088
|
+
);
|
|
2844
3089
|
debugLog("owney-sdk", "swap: signed, submitting same-chain order");
|
|
2845
3090
|
await deps.api.submitOrder({
|
|
2846
3091
|
// Without this the routing API hands the order to the Fusion+ relayer,
|
|
@@ -2852,6 +3097,10 @@ async function runSameChainFusion(deps, options, walletAddress) {
|
|
|
2852
3097
|
quoteId: built.quoteId,
|
|
2853
3098
|
...built.extension ? { extension: built.extension } : {}
|
|
2854
3099
|
});
|
|
3100
|
+
try {
|
|
3101
|
+
options.onOrderSubmitted?.(built.orderHash);
|
|
3102
|
+
} catch {
|
|
3103
|
+
}
|
|
2855
3104
|
await runSameChainOrder(deps.sameChainRunner ?? deps.runner, {
|
|
2856
3105
|
orderHash: built.orderHash,
|
|
2857
3106
|
...onStage ? { onStage } : {}
|
|
@@ -2870,7 +3119,10 @@ async function authoriseSpend(deps, options, amount, isNativeSource) {
|
|
|
2870
3119
|
if (current >= amount) return void 0;
|
|
2871
3120
|
onStage?.("approving");
|
|
2872
3121
|
await deps.ensureChain(quote.src.chainId);
|
|
2873
|
-
const permit = quote.permitSupported ? await
|
|
3122
|
+
const permit = quote.permitSupported ? await awaitWalletPrompt(
|
|
3123
|
+
async () => deps.buildPermit?.(quote.spender, MAX_UINT256),
|
|
3124
|
+
`approve ${quote.src.symbol}`
|
|
3125
|
+
) ?? void 0 : void 0;
|
|
2874
3126
|
if (permit) {
|
|
2875
3127
|
debugLog("owney-sdk", "swap: permitting limit order protocol", {
|
|
2876
3128
|
bytes: (permit.length - 2) / 2
|
|
@@ -2884,8 +3136,15 @@ async function authoriseSpend(deps, options, amount, isNativeSource) {
|
|
|
2884
3136
|
async function runFusion(deps, options, walletAddress) {
|
|
2885
3137
|
const { quote, direction, onStage } = options;
|
|
2886
3138
|
const isNativeSource = quote.src.address.toLowerCase().startsWith("0xeeee");
|
|
2887
|
-
|
|
2888
|
-
|
|
3139
|
+
if (isNativeSource) {
|
|
3140
|
+
throw new OwneyError(
|
|
3141
|
+
"SWAP_NATIVE_UNSUPPORTED",
|
|
3142
|
+
`${quote.src.symbol} has to be wrapped before it can be swapped to another chain. Nothing has left your wallet.`,
|
|
3143
|
+
{ chainId: quote.src.chainId, symbol: quote.src.symbol }
|
|
3144
|
+
);
|
|
3145
|
+
}
|
|
3146
|
+
const amount = await affordableAmount(deps, BigInt(quote.src.amount));
|
|
3147
|
+
const permit = await authoriseSpend(deps, options, amount, false);
|
|
2889
3148
|
const { secrets, secretHashes } = mintSecrets(quote.secretsCount ?? 1);
|
|
2890
3149
|
onStage?.("quoting");
|
|
2891
3150
|
debugLog("owney-sdk", "swap: building fusion order", {
|
|
@@ -2920,7 +3179,10 @@ async function runFusion(deps, options, walletAddress) {
|
|
|
2920
3179
|
debugLog("owney-sdk", "swap: awaiting signature in wallet", {
|
|
2921
3180
|
signingOnChain: quote.src.chainId
|
|
2922
3181
|
});
|
|
2923
|
-
const signature = await
|
|
3182
|
+
const signature = await awaitWalletPrompt(
|
|
3183
|
+
() => deps.signTypedData(built.typedData),
|
|
3184
|
+
"sign the swap"
|
|
3185
|
+
);
|
|
2924
3186
|
debugLog("owney-sdk", "swap: signed, submitting to relayer");
|
|
2925
3187
|
await deps.api.submitOrder({
|
|
2926
3188
|
srcChainId: quote.src.chainId,
|
|
@@ -2937,6 +3199,10 @@ async function runFusion(deps, options, walletAddress) {
|
|
|
2937
3199
|
...built.extension ? { extension: built.extension } : {}
|
|
2938
3200
|
});
|
|
2939
3201
|
debugLog("owney-sdk", "swap: order submitted, polling escrows");
|
|
3202
|
+
try {
|
|
3203
|
+
options.onOrderSubmitted?.(built.orderHash);
|
|
3204
|
+
} catch {
|
|
3205
|
+
}
|
|
2940
3206
|
try {
|
|
2941
3207
|
await runFusionOrder(deps.runner, {
|
|
2942
3208
|
orderHash: built.orderHash,
|
|
@@ -3056,54 +3322,158 @@ async function buildErc2612Permit(reads, input) {
|
|
|
3056
3322
|
);
|
|
3057
3323
|
}
|
|
3058
3324
|
|
|
3059
|
-
// src/lib/swap/swap.
|
|
3060
|
-
var
|
|
3061
|
-
var
|
|
3062
|
-
var
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3325
|
+
// src/lib/swap/swap.withdraw-swap.ts
|
|
3326
|
+
var KEY_PREFIX3 = "owney.swap.withdraw";
|
|
3327
|
+
var MAX_AGE_MS2 = 24 * 60 * 60 * 1e3;
|
|
3328
|
+
var storage3 = () => {
|
|
3329
|
+
if (typeof window === "undefined") return null;
|
|
3330
|
+
try {
|
|
3331
|
+
return window.localStorage;
|
|
3332
|
+
} catch {
|
|
3333
|
+
return null;
|
|
3334
|
+
}
|
|
3335
|
+
};
|
|
3336
|
+
var keyFor2 = (orderHash) => `${KEY_PREFIX3}.${orderHash}`;
|
|
3337
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
3338
|
+
function subscribeWithdrawSwaps(listener) {
|
|
3339
|
+
listeners.add(listener);
|
|
3340
|
+
return () => {
|
|
3341
|
+
listeners.delete(listener);
|
|
3342
|
+
};
|
|
3343
|
+
}
|
|
3344
|
+
var notify = () => {
|
|
3345
|
+
for (const listener of listeners) {
|
|
3077
3346
|
try {
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3347
|
+
listener();
|
|
3348
|
+
} catch {
|
|
3349
|
+
}
|
|
3350
|
+
}
|
|
3351
|
+
};
|
|
3352
|
+
function saveWithdrawSwap(record) {
|
|
3353
|
+
const store = storage3();
|
|
3354
|
+
if (!store) return;
|
|
3355
|
+
try {
|
|
3356
|
+
store.setItem(keyFor2(record.orderHash), JSON.stringify(record));
|
|
3357
|
+
} catch {
|
|
3358
|
+
return;
|
|
3359
|
+
}
|
|
3360
|
+
notify();
|
|
3361
|
+
}
|
|
3362
|
+
function updateWithdrawSwap(orderHash, patch) {
|
|
3363
|
+
const store = storage3();
|
|
3364
|
+
if (!store) return;
|
|
3365
|
+
try {
|
|
3366
|
+
const raw = store.getItem(keyFor2(orderHash));
|
|
3367
|
+
if (!raw) return;
|
|
3368
|
+
const current = JSON.parse(raw);
|
|
3369
|
+
const next = { ...current, ...patch };
|
|
3370
|
+
if (next.status !== "swapping" && current.status === "swapping" && next.settledAt === void 0) {
|
|
3371
|
+
next.settledAt = Date.now();
|
|
3372
|
+
}
|
|
3373
|
+
store.setItem(keyFor2(orderHash), JSON.stringify(next));
|
|
3374
|
+
} catch {
|
|
3375
|
+
return;
|
|
3376
|
+
}
|
|
3377
|
+
notify();
|
|
3378
|
+
}
|
|
3379
|
+
function clearWithdrawSwap(orderHash) {
|
|
3380
|
+
const store = storage3();
|
|
3381
|
+
if (!store) return;
|
|
3382
|
+
try {
|
|
3383
|
+
store.removeItem(keyFor2(orderHash));
|
|
3384
|
+
} catch {
|
|
3385
|
+
return;
|
|
3386
|
+
}
|
|
3387
|
+
notify();
|
|
3388
|
+
}
|
|
3389
|
+
function listWithdrawSwaps(now = Date.now()) {
|
|
3390
|
+
const store = storage3();
|
|
3391
|
+
if (!store) return [];
|
|
3392
|
+
const out = [];
|
|
3393
|
+
try {
|
|
3394
|
+
const keys = [];
|
|
3395
|
+
for (let i = 0; i < store.length; i++) {
|
|
3396
|
+
const key2 = store.key(i);
|
|
3397
|
+
if (key2?.startsWith(`${KEY_PREFIX3}.`)) keys.push(key2);
|
|
3398
|
+
}
|
|
3399
|
+
for (const key2 of keys) {
|
|
3400
|
+
const raw = store.getItem(key2);
|
|
3401
|
+
if (!raw) continue;
|
|
3402
|
+
try {
|
|
3403
|
+
const parsed = JSON.parse(raw);
|
|
3404
|
+
if (now - parsed.createdAt > MAX_AGE_MS2) {
|
|
3405
|
+
store.removeItem(key2);
|
|
3406
|
+
continue;
|
|
3407
|
+
}
|
|
3408
|
+
out.push(parsed);
|
|
3409
|
+
} catch {
|
|
3410
|
+
store.removeItem(key2);
|
|
3085
3411
|
}
|
|
3086
|
-
} catch (error) {
|
|
3087
|
-
lastError = error;
|
|
3088
|
-
debugLog("owney-sdk", "withdraw: balance read failed, retrying", {
|
|
3089
|
-
message: error instanceof Error ? error.message : String(error)
|
|
3090
|
-
});
|
|
3091
3412
|
}
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3413
|
+
} catch {
|
|
3414
|
+
return out;
|
|
3415
|
+
}
|
|
3416
|
+
return out.sort((a, b) => b.createdAt - a.createdAt);
|
|
3417
|
+
}
|
|
3418
|
+
|
|
3419
|
+
// src/lib/swap/swap.pending-deposit.ts
|
|
3420
|
+
var KEY_PREFIX4 = "owney.swap.pending-deposit";
|
|
3421
|
+
var MAX_AGE_MS3 = 24 * 60 * 60 * 1e3;
|
|
3422
|
+
var storage4 = () => {
|
|
3423
|
+
if (typeof window === "undefined") return null;
|
|
3424
|
+
try {
|
|
3425
|
+
return window.localStorage;
|
|
3426
|
+
} catch {
|
|
3427
|
+
return null;
|
|
3428
|
+
}
|
|
3429
|
+
};
|
|
3430
|
+
var keyFor3 = (id) => `${KEY_PREFIX4}.${id}`;
|
|
3431
|
+
function savePendingDeposit(entry) {
|
|
3432
|
+
const store = storage4();
|
|
3433
|
+
if (!store) return;
|
|
3434
|
+
try {
|
|
3435
|
+
store.setItem(keyFor3(entry.id), JSON.stringify(entry));
|
|
3436
|
+
} catch {
|
|
3437
|
+
return;
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
function clearPendingDeposit(id) {
|
|
3441
|
+
const store = storage4();
|
|
3442
|
+
if (!store) return;
|
|
3443
|
+
try {
|
|
3444
|
+
store.removeItem(keyFor3(id));
|
|
3445
|
+
} catch {
|
|
3446
|
+
return;
|
|
3447
|
+
}
|
|
3448
|
+
}
|
|
3449
|
+
function listPendingDeposits(now = Date.now()) {
|
|
3450
|
+
const store = storage4();
|
|
3451
|
+
if (!store) return [];
|
|
3452
|
+
const out = [];
|
|
3453
|
+
try {
|
|
3454
|
+
const keys = [];
|
|
3455
|
+
for (let i = 0; i < store.length; i++) {
|
|
3456
|
+
const key2 = store.key(i);
|
|
3457
|
+
if (key2?.startsWith(`${KEY_PREFIX4}.`)) keys.push(key2);
|
|
3458
|
+
}
|
|
3459
|
+
for (const key2 of keys) {
|
|
3460
|
+
const raw = store.getItem(key2);
|
|
3461
|
+
if (!raw) continue;
|
|
3462
|
+
try {
|
|
3463
|
+
const parsed = JSON.parse(raw);
|
|
3464
|
+
if (now - parsed.createdAt > MAX_AGE_MS3) {
|
|
3465
|
+
store.removeItem(key2);
|
|
3466
|
+
continue;
|
|
3102
3467
|
}
|
|
3103
|
-
|
|
3468
|
+
out.push(parsed);
|
|
3469
|
+
} catch {
|
|
3470
|
+
store.removeItem(key2);
|
|
3471
|
+
}
|
|
3104
3472
|
}
|
|
3105
|
-
|
|
3473
|
+
} catch {
|
|
3474
|
+
return out;
|
|
3106
3475
|
}
|
|
3476
|
+
return out.sort((a, b) => b.createdAt - a.createdAt);
|
|
3107
3477
|
}
|
|
3108
3478
|
|
|
3109
3479
|
// src/lib/health-report.ts
|
|
@@ -3303,7 +3673,7 @@ import {
|
|
|
3303
3673
|
custom,
|
|
3304
3674
|
erc20Abi as erc20Abi2
|
|
3305
3675
|
} from "viem";
|
|
3306
|
-
import { base as
|
|
3676
|
+
import { base as base3, arbitrum as arbitrum3, mainnet as mainnet3 } from "viem/chains";
|
|
3307
3677
|
|
|
3308
3678
|
// src/lib/transfer-auth.ts
|
|
3309
3679
|
import { bytesToHex as bytesToHex2 } from "viem";
|
|
@@ -3344,10 +3714,10 @@ function randomAuthNonce() {
|
|
|
3344
3714
|
// src/lib/sponsor-client.ts
|
|
3345
3715
|
var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
3346
3716
|
async function postSponsorTransferAuth(input) {
|
|
3347
|
-
const
|
|
3717
|
+
const base4 = input.baseUrl ?? ROUTING_API_BASE_URL3;
|
|
3348
3718
|
let res;
|
|
3349
3719
|
try {
|
|
3350
|
-
res = await fetch(`${
|
|
3720
|
+
res = await fetch(`${base4}/api/v1/sponsor/erc20-transfer-auth`, {
|
|
3351
3721
|
method: "POST",
|
|
3352
3722
|
headers: {
|
|
3353
3723
|
"content-type": "application/json",
|
|
@@ -3384,10 +3754,10 @@ async function postSponsorTransferAuth(input) {
|
|
|
3384
3754
|
return parsed.data;
|
|
3385
3755
|
}
|
|
3386
3756
|
async function postSponsorPermit2Transfer(input) {
|
|
3387
|
-
const
|
|
3757
|
+
const base4 = input.baseUrl ?? ROUTING_API_BASE_URL3;
|
|
3388
3758
|
let res;
|
|
3389
3759
|
try {
|
|
3390
|
-
res = await fetch(`${
|
|
3760
|
+
res = await fetch(`${base4}/api/v1/sponsor/permit2-transfer`, {
|
|
3391
3761
|
method: "POST",
|
|
3392
3762
|
headers: {
|
|
3393
3763
|
"content-type": "application/json",
|
|
@@ -3422,11 +3792,11 @@ async function postSponsorPermit2Transfer(input) {
|
|
|
3422
3792
|
return parsed.data;
|
|
3423
3793
|
}
|
|
3424
3794
|
async function getSponsorRelayerAddress(input) {
|
|
3425
|
-
const
|
|
3795
|
+
const base4 = input.baseUrl ?? ROUTING_API_BASE_URL3;
|
|
3426
3796
|
let res;
|
|
3427
3797
|
try {
|
|
3428
3798
|
res = await fetch(
|
|
3429
|
-
`${
|
|
3799
|
+
`${base4}/api/v1/sponsor/relayer-address?chainId=${input.chainId}`,
|
|
3430
3800
|
{
|
|
3431
3801
|
headers: { "x-owney-api-key": input.apiKey }
|
|
3432
3802
|
}
|
|
@@ -3711,6 +4081,7 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
3711
4081
|
}
|
|
3712
4082
|
|
|
3713
4083
|
// src/client.ts
|
|
4084
|
+
var WALLET_CATCHUP_TIMEOUT_MS = 3e4;
|
|
3714
4085
|
function encodeMultiAgentCursor(map) {
|
|
3715
4086
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
3716
4087
|
}
|
|
@@ -3737,9 +4108,9 @@ var SPONSORED_USDC_BY_CHAIN = {
|
|
|
3737
4108
|
1: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
|
|
3738
4109
|
};
|
|
3739
4110
|
var VIEM_CHAIN2 = {
|
|
3740
|
-
8453:
|
|
3741
|
-
42161:
|
|
3742
|
-
1:
|
|
4111
|
+
8453: base3,
|
|
4112
|
+
42161: arbitrum3,
|
|
4113
|
+
1: mainnet3
|
|
3743
4114
|
};
|
|
3744
4115
|
var SPONSORED_WETH_BY_CHAIN = {
|
|
3745
4116
|
8453: "0x4200000000000000000000000000000000000006",
|
|
@@ -4528,7 +4899,7 @@ var OwneySDK = class {
|
|
|
4528
4899
|
async ensureSwapChain(chainId) {
|
|
4529
4900
|
const provider = this.requireConnectedProvider();
|
|
4530
4901
|
const state = this.requireState();
|
|
4531
|
-
const chain =
|
|
4902
|
+
const chain = swapChain(chainId);
|
|
4532
4903
|
if (!chain) {
|
|
4533
4904
|
throw new OwneyError(
|
|
4534
4905
|
"CHAIN_UNSUPPORTED",
|
|
@@ -4546,6 +4917,111 @@ var OwneySDK = class {
|
|
|
4546
4917
|
chainId
|
|
4547
4918
|
);
|
|
4548
4919
|
}
|
|
4920
|
+
/**
|
|
4921
|
+
* Turn a native-source cross-chain quote into an ERC-20 one.
|
|
4922
|
+
*
|
|
4923
|
+
* Fusion+ cannot escrow native value, so the quote arrives with
|
|
4924
|
+
* `requiresOnchainOrder` set and the relayer would refuse the order after
|
|
4925
|
+
* the user signed it (ROUT-242). Wrapping first costs one transaction and
|
|
4926
|
+
* puts the swap back on the ERC-20 rail that already works, rather than
|
|
4927
|
+
* adding a second order type that would need its own escrow handling.
|
|
4928
|
+
*
|
|
4929
|
+
* Re-quoted afterwards rather than patched: the amount wrapped may be less
|
|
4930
|
+
* than the amount quoted (gas has to come out of the same balance), and
|
|
4931
|
+
* every executor dep — allowance, permit, balances — is derived from the
|
|
4932
|
+
* quote's source token. A quote naming ETH would have all of them reading
|
|
4933
|
+
* the wrong asset.
|
|
4934
|
+
*/
|
|
4935
|
+
async wrapNativeSource(quote, walletAddress, onStage, direction) {
|
|
4936
|
+
const wrapper = requireWrapper(quote);
|
|
4937
|
+
const chainId = quote.src.chainId;
|
|
4938
|
+
const chain = swapChain(chainId);
|
|
4939
|
+
const provider = this.requireConnectedProvider();
|
|
4940
|
+
const publicClient = createPublicClient2({
|
|
4941
|
+
chain,
|
|
4942
|
+
transport: swapReadTransport(chainId, this.zyfaiRpcUrls)
|
|
4943
|
+
});
|
|
4944
|
+
const wallet = createWalletClient({
|
|
4945
|
+
account: walletAddress,
|
|
4946
|
+
chain,
|
|
4947
|
+
transport: custom(provider)
|
|
4948
|
+
});
|
|
4949
|
+
onStage?.("wrapping");
|
|
4950
|
+
const { wrapped } = await wrapNative(
|
|
4951
|
+
{
|
|
4952
|
+
readNativeBalance: () => publicClient.getBalance({
|
|
4953
|
+
address: walletAddress
|
|
4954
|
+
}),
|
|
4955
|
+
estimateWrapGas: (to, value) => publicClient.estimateGas({
|
|
4956
|
+
account: walletAddress,
|
|
4957
|
+
to,
|
|
4958
|
+
data: WRAP_SELECTOR,
|
|
4959
|
+
value
|
|
4960
|
+
}),
|
|
4961
|
+
// The 1559 ceiling, not the spot price: a wallet bills against the
|
|
4962
|
+
// former and the two differ wildly on a quiet chain.
|
|
4963
|
+
getMaxFeePerGas: async () => {
|
|
4964
|
+
const fees = await publicClient.estimateFeesPerGas();
|
|
4965
|
+
return fees.maxFeePerGas ?? publicClient.getGasPrice();
|
|
4966
|
+
},
|
|
4967
|
+
sendTransaction: async (tx, onSubmitted) => {
|
|
4968
|
+
const hash = await wallet.sendTransaction({
|
|
4969
|
+
to: tx.to,
|
|
4970
|
+
data: tx.data,
|
|
4971
|
+
value: BigInt(tx.value),
|
|
4972
|
+
account: walletAddress,
|
|
4973
|
+
chain
|
|
4974
|
+
});
|
|
4975
|
+
onSubmitted?.(hash);
|
|
4976
|
+
const receipt = await publicClient.waitForTransactionReceipt({
|
|
4977
|
+
hash,
|
|
4978
|
+
confirmations: 1,
|
|
4979
|
+
timeout: receiptTimeoutMs(chainId)
|
|
4980
|
+
});
|
|
4981
|
+
if (receipt.status !== "success") {
|
|
4982
|
+
throw new OwneyError(
|
|
4983
|
+
"SWAP_REQUEST_FAILED",
|
|
4984
|
+
`Wrapping your ${quote.src.symbol} failed (tx ${hash}). Nothing was swapped.`,
|
|
4985
|
+
{ hash }
|
|
4986
|
+
);
|
|
4987
|
+
}
|
|
4988
|
+
return hash;
|
|
4989
|
+
},
|
|
4990
|
+
ensureChain: (id) => this.ensureSwapChain(id)
|
|
4991
|
+
},
|
|
4992
|
+
{
|
|
4993
|
+
chainId,
|
|
4994
|
+
wrapper: wrapper.address,
|
|
4995
|
+
nativeSymbol: quote.src.symbol,
|
|
4996
|
+
requested: BigInt(quote.src.amount),
|
|
4997
|
+
onSubmitted: () => onStage?.("wrapped")
|
|
4998
|
+
}
|
|
4999
|
+
);
|
|
5000
|
+
debugLog("owney-sdk", "swap: wrapped native source", {
|
|
5001
|
+
symbol: wrapper.symbol,
|
|
5002
|
+
amount: wrapped.toString()
|
|
5003
|
+
});
|
|
5004
|
+
try {
|
|
5005
|
+
return await this.swapApi().quote({
|
|
5006
|
+
from: { chainId, symbol: wrapper.symbol, amount: wrapped.toString() },
|
|
5007
|
+
to: { chainId: quote.dst.chainId, symbol: quote.dst.symbol },
|
|
5008
|
+
walletAddress,
|
|
5009
|
+
...direction ? { direction } : {}
|
|
5010
|
+
});
|
|
5011
|
+
} catch (error) {
|
|
5012
|
+
throw new OwneyError(
|
|
5013
|
+
"SWAP_REQUEST_FAILED",
|
|
5014
|
+
`Your ${quote.src.symbol} was wrapped to ${wrapper.symbol}, but the swap couldn't be priced. The funds are in your wallet as ${wrapper.symbol} \u2014 swap that instead, no need to wrap again.`,
|
|
5015
|
+
{
|
|
5016
|
+
wrappedSymbol: wrapper.symbol,
|
|
5017
|
+
wrappedAmount: wrapped.toString(),
|
|
5018
|
+
chainId,
|
|
5019
|
+
cause: error instanceof Error ? error.message : String(error),
|
|
5020
|
+
...error instanceof OwneyError ? { causeCode: error.code } : {}
|
|
5021
|
+
}
|
|
5022
|
+
);
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
4549
5025
|
/**
|
|
4550
5026
|
* Binds the executor's abstract deps to this client's wallet.
|
|
4551
5027
|
*
|
|
@@ -4555,8 +5031,8 @@ var OwneySDK = class {
|
|
|
4555
5031
|
buildSwapDeps(quote) {
|
|
4556
5032
|
const state = this.requireState();
|
|
4557
5033
|
const provider = this.requireConnectedProvider();
|
|
4558
|
-
const srcChain =
|
|
4559
|
-
const dstChain =
|
|
5034
|
+
const srcChain = swapChain(quote.src.chainId);
|
|
5035
|
+
const dstChain = swapChain(quote.dst.chainId);
|
|
4560
5036
|
const wallet = createWalletClient({
|
|
4561
5037
|
account: state.walletAddress,
|
|
4562
5038
|
chain: srcChain,
|
|
@@ -4686,13 +5162,59 @@ var OwneySDK = class {
|
|
|
4686
5162
|
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
4687
5163
|
now: () => Date.now()
|
|
4688
5164
|
},
|
|
4689
|
-
runner:
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
5165
|
+
runner: this.swapRunnerDeps()
|
|
5166
|
+
};
|
|
5167
|
+
}
|
|
5168
|
+
/**
|
|
5169
|
+
* Waits until the WALLET'S OWN node reports at least `amount` of `token`.
|
|
5170
|
+
*
|
|
5171
|
+
* Separate from the swap's arrival measurement on purpose: that one runs on
|
|
5172
|
+
* a pinned HTTP RPC, and what matters here is the view the deposit will
|
|
5173
|
+
* actually use. Returns whether it got there — a courtesy, not a gate, since
|
|
5174
|
+
* the deposit's own check is the authority and refusing to even attempt
|
|
5175
|
+
* would strand funds we might have been able to move.
|
|
5176
|
+
*/
|
|
5177
|
+
async walletSeesBalance(chainId, token, amount) {
|
|
5178
|
+
const provider = this.requireConnectedProvider();
|
|
5179
|
+
const state = this.requireState();
|
|
5180
|
+
const pub = createPublicClient2({
|
|
5181
|
+
chain: swapChain(chainId),
|
|
5182
|
+
transport: custom(provider)
|
|
5183
|
+
});
|
|
5184
|
+
const { arrived } = await awaitBalanceIncrease({
|
|
5185
|
+
readBalance: () => pub.readContract({
|
|
5186
|
+
address: token,
|
|
5187
|
+
abi: ERC20_ALLOWANCE_ABI,
|
|
5188
|
+
functionName: "balanceOf",
|
|
5189
|
+
args: [state.walletAddress]
|
|
5190
|
+
}),
|
|
5191
|
+
// `awaitBalanceIncrease` resolves on the first read STRICTLY above the
|
|
5192
|
+
// baseline, so one below the target means "at least the target".
|
|
5193
|
+
baseline: amount - 1n,
|
|
5194
|
+
timeoutMs: WALLET_CATCHUP_TIMEOUT_MS
|
|
5195
|
+
});
|
|
5196
|
+
return arrived !== null;
|
|
5197
|
+
}
|
|
5198
|
+
/**
|
|
5199
|
+
* Runs a quoted swap. A named seam rather than an inline `executeSwap` call
|
|
5200
|
+
* so the deposit half of `swapAndDeposit` can be exercised on its own.
|
|
5201
|
+
*/
|
|
5202
|
+
runSwap(quote, options) {
|
|
5203
|
+
return executeSwap(this.buildSwapDeps(quote), { quote, ...options });
|
|
5204
|
+
}
|
|
5205
|
+
/**
|
|
5206
|
+
* The half of the swap deps that only ever talks to the routing API.
|
|
5207
|
+
*
|
|
5208
|
+
* Split out because resuming an order needs exactly this and nothing else —
|
|
5209
|
+
* no provider, no wallet client, no chain. See `resumePendingSwaps`.
|
|
5210
|
+
*/
|
|
5211
|
+
swapRunnerDeps() {
|
|
5212
|
+
return {
|
|
5213
|
+
readyForSecrets: (h) => this.swapApi().readyForSecrets(h),
|
|
5214
|
+
submitSecret: (h, secret) => this.swapApi().submitSecret(h, secret),
|
|
5215
|
+
orderStatus: (h) => this.swapApi().orderStatus(h),
|
|
5216
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
5217
|
+
now: () => Date.now()
|
|
4696
5218
|
};
|
|
4697
5219
|
}
|
|
4698
5220
|
/**
|
|
@@ -4704,6 +5226,167 @@ var OwneySDK = class {
|
|
|
4704
5226
|
async getSwapTokens() {
|
|
4705
5227
|
return this.swapApi().listTokens();
|
|
4706
5228
|
}
|
|
5229
|
+
/**
|
|
5230
|
+
* Swaps that landed but were never deposited, newest first.
|
|
5231
|
+
*
|
|
5232
|
+
* The money is already in the wallet in the right asset — what is missing is
|
|
5233
|
+
* an ordinary deposit, which is why this needs no order and no signature to
|
|
5234
|
+
* describe. See `completePendingDeposit`.
|
|
5235
|
+
*/
|
|
5236
|
+
listPendingDeposits() {
|
|
5237
|
+
return listPendingDeposits();
|
|
5238
|
+
}
|
|
5239
|
+
/**
|
|
5240
|
+
* Backgrounded withdrawal swaps and how they ended, newest first.
|
|
5241
|
+
*
|
|
5242
|
+
* Nothing to act on — unlike `listPendingDeposits`, which describes a job the
|
|
5243
|
+
* user can finish. This is a watch: the funds are in escrow and the only
|
|
5244
|
+
* open question is where they land. See `swap.withdraw-swap.ts`.
|
|
5245
|
+
*/
|
|
5246
|
+
listWithdrawSwaps() {
|
|
5247
|
+
return listWithdrawSwaps();
|
|
5248
|
+
}
|
|
5249
|
+
/**
|
|
5250
|
+
* Retire a settled record. The user has read the outcome.
|
|
5251
|
+
*
|
|
5252
|
+
* Only they do this — a record that disappears on its own takes with it the
|
|
5253
|
+
* only thing telling someone where their money went.
|
|
5254
|
+
*/
|
|
5255
|
+
dismissWithdrawSwap(orderHash) {
|
|
5256
|
+
clearWithdrawSwap(orderHash);
|
|
5257
|
+
}
|
|
5258
|
+
/**
|
|
5259
|
+
* Deposit a swap that already landed.
|
|
5260
|
+
*
|
|
5261
|
+
* Nothing is swapped again: the funds are in the wallet, so this is the
|
|
5262
|
+
* second half of `swapAndDeposit` on its own. Cleared only once the deposit
|
|
5263
|
+
* has actually gone through — a failure here leaves the record in place so it
|
|
5264
|
+
* can be offered again rather than silently dropped.
|
|
5265
|
+
*/
|
|
5266
|
+
async completePendingDeposit(id) {
|
|
5267
|
+
const entry = listPendingDeposits().find((p) => p.id === id);
|
|
5268
|
+
if (!entry) {
|
|
5269
|
+
throw new OwneyError(
|
|
5270
|
+
"SWAP_REQUEST_FAILED",
|
|
5271
|
+
"That swap is no longer waiting to be added.",
|
|
5272
|
+
{ id }
|
|
5273
|
+
);
|
|
5274
|
+
}
|
|
5275
|
+
await this.ensureSwapChain(entry.chainId);
|
|
5276
|
+
const deposit = await this.deposit({
|
|
5277
|
+
amount: entry.received,
|
|
5278
|
+
asset: entry.symbol,
|
|
5279
|
+
...entry.agentId ? { agentId: entry.agentId } : {}
|
|
5280
|
+
});
|
|
5281
|
+
clearPendingDeposit(entry.id);
|
|
5282
|
+
return deposit;
|
|
5283
|
+
}
|
|
5284
|
+
/**
|
|
5285
|
+
* Pick up cross-chain swaps a previous session left in flight.
|
|
5286
|
+
*
|
|
5287
|
+
* A Fusion+ order is only finished when the client publishes a secret for
|
|
5288
|
+
* each fill, once the escrows exist — so a user who closed the tab mid-swap
|
|
5289
|
+
* leaves an order nobody will ever complete, and it expires and refunds
|
|
5290
|
+
* instead of arriving. The preimages are stored for exactly this (24h sweep,
|
|
5291
|
+
* see the secret store); this is the other half.
|
|
5292
|
+
*
|
|
5293
|
+
* Needs NO wallet, deliberately. The signature already happened and the funds
|
|
5294
|
+
* are already escrowed, so finishing is pure API work — demanding a reconnect
|
|
5295
|
+
* first would strand the people it exists for.
|
|
5296
|
+
*
|
|
5297
|
+
* Every order is attempted even if an earlier one throws: they are unrelated
|
|
5298
|
+
* escrows, and one ending badly must not abandon the next one's secrets.
|
|
5299
|
+
* `unfinished` is not a verdict — the order may still settle, so unless the
|
|
5300
|
+
* chain has said refunded or cancelled its preimages are kept.
|
|
5301
|
+
*/
|
|
5302
|
+
async resumePendingSwaps(options = {}) {
|
|
5303
|
+
const pending = listOrders();
|
|
5304
|
+
if (pending.length === 0) {
|
|
5305
|
+
await this.resumeSameChainSwaps(options);
|
|
5306
|
+
return [];
|
|
5307
|
+
}
|
|
5308
|
+
const runner = this.swapRunnerDeps();
|
|
5309
|
+
const results = [];
|
|
5310
|
+
for (const order of pending) {
|
|
5311
|
+
try {
|
|
5312
|
+
await runFusionOrder(runner, {
|
|
5313
|
+
orderHash: order.orderHash,
|
|
5314
|
+
secrets: order.secrets,
|
|
5315
|
+
...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs },
|
|
5316
|
+
...options.onStage ? {
|
|
5317
|
+
onStage: (stage) => options.onStage(order.orderHash, stage)
|
|
5318
|
+
} : {}
|
|
5319
|
+
});
|
|
5320
|
+
clearOrder(order.orderHash);
|
|
5321
|
+
updateWithdrawSwap(order.orderHash, { status: "landed" });
|
|
5322
|
+
results.push({
|
|
5323
|
+
orderHash: order.orderHash,
|
|
5324
|
+
status: "completed"
|
|
5325
|
+
});
|
|
5326
|
+
} catch (error) {
|
|
5327
|
+
if (error instanceof OwneyError && (error.code === "SWAP_ORDER_REFUNDED" || error.code === "SWAP_ORDER_CANCELLED")) {
|
|
5328
|
+
clearOrder(order.orderHash);
|
|
5329
|
+
updateWithdrawSwap(order.orderHash, { status: "refunded" });
|
|
5330
|
+
} else {
|
|
5331
|
+
updateWithdrawSwap(order.orderHash, { status: "unknown" });
|
|
5332
|
+
}
|
|
5333
|
+
results.push({
|
|
5334
|
+
orderHash: order.orderHash,
|
|
5335
|
+
status: "unfinished",
|
|
5336
|
+
...error instanceof OwneyError ? { error } : {}
|
|
5337
|
+
});
|
|
5338
|
+
}
|
|
5339
|
+
}
|
|
5340
|
+
await this.resumeSameChainSwaps(options);
|
|
5341
|
+
return results;
|
|
5342
|
+
}
|
|
5343
|
+
/**
|
|
5344
|
+
* Pick up SAME-CHAIN orders a previous session left in the auction.
|
|
5345
|
+
*
|
|
5346
|
+
* They are not in the secret store and never will be: that store exists to
|
|
5347
|
+
* keep preimages, and a same-chain fill needs none — the resolver takes the
|
|
5348
|
+
* maker's tokens and delivers the taker's in one transaction. So the only
|
|
5349
|
+
* record of one is the withdrawal record itself, which carries the order
|
|
5350
|
+
* hash, and that is all a resume needs here.
|
|
5351
|
+
*
|
|
5352
|
+
* Gentler than the Fusion+ case in the way that matters. Nothing is
|
|
5353
|
+
* escrowed, so an order nobody ever picks up leaves the wallet exactly as it
|
|
5354
|
+
* was — this is catching up on news, not rescuing funds.
|
|
5355
|
+
*
|
|
5356
|
+
* Same-chain is read off the record rather than stored as a rail: a
|
|
5357
|
+
* withdrawal whose source and destination share a chain could not have been
|
|
5358
|
+
* anything else.
|
|
5359
|
+
*/
|
|
5360
|
+
async resumeSameChainSwaps(options = {}) {
|
|
5361
|
+
const running = listWithdrawSwaps().filter(
|
|
5362
|
+
(record) => record.status === "swapping" && record.srcChainId === record.dstChainId
|
|
5363
|
+
);
|
|
5364
|
+
for (const record of running) {
|
|
5365
|
+
const runner = {
|
|
5366
|
+
// The chain bound in. That product keys its orders per chain, and the
|
|
5367
|
+
// Fusion+ endpoint answers 404 for one — which would read as an order
|
|
5368
|
+
// that vanished rather than one still in the auction.
|
|
5369
|
+
orderStatus: (h) => this.swapApi().orderStatus(h, record.srcChainId),
|
|
5370
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
5371
|
+
now: () => Date.now()
|
|
5372
|
+
};
|
|
5373
|
+
try {
|
|
5374
|
+
await runSameChainOrder(runner, {
|
|
5375
|
+
orderHash: record.orderHash,
|
|
5376
|
+
...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs },
|
|
5377
|
+
...options.onStage ? {
|
|
5378
|
+
onStage: (stage) => options.onStage(record.orderHash, stage)
|
|
5379
|
+
} : {}
|
|
5380
|
+
});
|
|
5381
|
+
updateWithdrawSwap(record.orderHash, { status: "landed" });
|
|
5382
|
+
} catch (error) {
|
|
5383
|
+
const code = error instanceof OwneyError ? error.code : void 0;
|
|
5384
|
+
updateWithdrawSwap(record.orderHash, {
|
|
5385
|
+
status: code === "SWAP_ORDER_EXPIRED" || code === "SWAP_ORDER_CANCELLED" ? "refunded" : "unknown"
|
|
5386
|
+
});
|
|
5387
|
+
}
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
4707
5390
|
/**
|
|
4708
5391
|
* What the wallet actually holds, across every supported chain, restricted
|
|
4709
5392
|
* to tokens a swap could use.
|
|
@@ -4750,15 +5433,19 @@ var OwneySDK = class {
|
|
|
4750
5433
|
* tokens can share a ticker, and `providers` (how many token lists carry the
|
|
4751
5434
|
* address) is the only usable signal for telling them apart. Surface it.
|
|
4752
5435
|
*
|
|
4753
|
-
*
|
|
5436
|
+
* A blank query WITH a chainId lists that chain's catalogue instead of
|
|
5437
|
+
* searching it — what a picker wants when someone selects a chain before
|
|
5438
|
+
* typing anything. Blank with no chain returns nothing: that would be asking
|
|
5439
|
+
* for the top of every catalogue at once, which is a download, not a list.
|
|
4754
5440
|
*/
|
|
4755
5441
|
async searchSwapTokens(params) {
|
|
4756
|
-
const query = params.query
|
|
4757
|
-
if (!query) return { tokens: [] };
|
|
5442
|
+
const query = params.query?.trim() ?? "";
|
|
5443
|
+
if (!query && params.chainId === void 0) return { tokens: [] };
|
|
4758
5444
|
return this.swapApi().searchTokens({
|
|
4759
|
-
query,
|
|
5445
|
+
...query ? { query } : {},
|
|
4760
5446
|
...params.chainId === void 0 ? {} : { chainId: params.chainId },
|
|
4761
|
-
...params.limit === void 0 ? {} : { limit: params.limit }
|
|
5447
|
+
...params.limit === void 0 ? {} : { limit: params.limit },
|
|
5448
|
+
...params.direction === void 0 ? {} : { direction: params.direction }
|
|
4762
5449
|
});
|
|
4763
5450
|
}
|
|
4764
5451
|
/**
|
|
@@ -4797,26 +5484,56 @@ var OwneySDK = class {
|
|
|
4797
5484
|
async swapAndDeposit(options) {
|
|
4798
5485
|
const state = this.requireState();
|
|
4799
5486
|
const api = this.swapApi();
|
|
4800
|
-
const
|
|
5487
|
+
const quoted = await api.quote({
|
|
4801
5488
|
from: options.from,
|
|
4802
5489
|
to: options.to,
|
|
4803
5490
|
walletAddress: state.walletAddress
|
|
4804
5491
|
});
|
|
5492
|
+
const quote = quoted.requiresOnchainOrder ? await this.wrapNativeSource(
|
|
5493
|
+
quoted,
|
|
5494
|
+
state.walletAddress,
|
|
5495
|
+
options.onSwapProgress
|
|
5496
|
+
) : quoted;
|
|
4805
5497
|
await this.ensureSwapChain(quote.src.chainId);
|
|
4806
|
-
const swap = await
|
|
4807
|
-
quote,
|
|
5498
|
+
const swap = await this.runSwap(quote, {
|
|
4808
5499
|
walletAddress: state.walletAddress,
|
|
4809
5500
|
...options.slippage === void 0 ? {} : { slippage: options.slippage },
|
|
4810
5501
|
...options.onSwapProgress ? { onStage: options.onSwapProgress } : {}
|
|
4811
5502
|
});
|
|
4812
5503
|
options.onSwapProgress?.("depositing");
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
5504
|
+
try {
|
|
5505
|
+
await this.ensureSwapChain(quote.dst.chainId);
|
|
5506
|
+
await this.walletSeesBalance(
|
|
5507
|
+
quote.dst.chainId,
|
|
5508
|
+
quote.dst.address,
|
|
5509
|
+
BigInt(swap.received)
|
|
5510
|
+
);
|
|
5511
|
+
const deposit = await this.deposit({
|
|
5512
|
+
amount: swap.received,
|
|
5513
|
+
asset: options.to.symbol,
|
|
5514
|
+
...options.agentId ? { agentId: options.agentId } : {}
|
|
5515
|
+
});
|
|
5516
|
+
return { swap, deposit };
|
|
5517
|
+
} catch (error) {
|
|
5518
|
+
const pending = {
|
|
5519
|
+
id: `${quote.dst.chainId}-${options.to.symbol}-${Date.now()}`,
|
|
5520
|
+
received: swap.received,
|
|
5521
|
+
symbol: options.to.symbol,
|
|
5522
|
+
chainId: quote.dst.chainId,
|
|
5523
|
+
...options.agentId ? { agentId: options.agentId } : {},
|
|
5524
|
+
createdAt: Date.now()
|
|
5525
|
+
};
|
|
5526
|
+
savePendingDeposit(pending);
|
|
5527
|
+
throw new OwneyError(
|
|
5528
|
+
"SWAP_DEPOSIT_PENDING",
|
|
5529
|
+
`The swap went through and your ${options.to.symbol} is in your wallet, but adding it to the agent didn't complete. Nothing needs swapping again.`,
|
|
5530
|
+
{
|
|
5531
|
+
...pending,
|
|
5532
|
+
cause: error instanceof Error ? error.message : String(error),
|
|
5533
|
+
...error instanceof OwneyError ? { causeCode: error.code } : {}
|
|
5534
|
+
}
|
|
5535
|
+
);
|
|
5536
|
+
}
|
|
4820
5537
|
}
|
|
4821
5538
|
/**
|
|
4822
5539
|
* Withdraw from an agent and swap the proceeds into whatever the user wants
|
|
@@ -4905,7 +5622,14 @@ var OwneySDK = class {
|
|
|
4905
5622
|
walletAddress: state.walletAddress,
|
|
4906
5623
|
direction: "withdraw",
|
|
4907
5624
|
...options.slippage === void 0 ? {} : { slippage: options.slippage },
|
|
4908
|
-
...options.onSwapProgress ? { onStage: options.onSwapProgress } : {}
|
|
5625
|
+
...options.onSwapProgress ? { onStage: options.onSwapProgress } : {},
|
|
5626
|
+
...options.onOrderSubmitted ? {
|
|
5627
|
+
onOrderSubmitted: (orderHash) => options.onOrderSubmitted({
|
|
5628
|
+
orderHash,
|
|
5629
|
+
withdrawn,
|
|
5630
|
+
expected: quote.dst.amount
|
|
5631
|
+
})
|
|
5632
|
+
} : {}
|
|
4909
5633
|
});
|
|
4910
5634
|
return { withdraw, withdrawn, swap };
|
|
4911
5635
|
} catch (error) {
|
|
@@ -5664,8 +6388,8 @@ import { SiweMessage } from "siwe";
|
|
|
5664
6388
|
import { ZyfaiSDK as ZyfaiSDK2 } from "@zyfai/sdk";
|
|
5665
6389
|
|
|
5666
6390
|
// src/agents/zyfai/zyfai.siwx-cache.ts
|
|
5667
|
-
var
|
|
5668
|
-
var
|
|
6391
|
+
var KEY_PREFIX5 = "owney.siwx.session";
|
|
6392
|
+
var storage5 = () => {
|
|
5669
6393
|
if (typeof window === "undefined") return null;
|
|
5670
6394
|
try {
|
|
5671
6395
|
return window.localStorage;
|
|
@@ -5673,8 +6397,8 @@ var storage3 = () => {
|
|
|
5673
6397
|
return null;
|
|
5674
6398
|
}
|
|
5675
6399
|
};
|
|
5676
|
-
var buildKey2 = (address) => `${
|
|
5677
|
-
var legacyKeyPrefix2 = (address) => `${
|
|
6400
|
+
var buildKey2 = (address) => `${KEY_PREFIX5}:${address.toLowerCase()}`;
|
|
6401
|
+
var legacyKeyPrefix2 = (address) => `${KEY_PREFIX5}:${address.toLowerCase()}:`;
|
|
5678
6402
|
var memorySiwxSessions = /* @__PURE__ */ new Map();
|
|
5679
6403
|
var readLegacySiwxSession = (store, address) => {
|
|
5680
6404
|
if (!store) return null;
|
|
@@ -5706,7 +6430,7 @@ var readLegacySiwxSession = (store, address) => {
|
|
|
5706
6430
|
var readSiwxSession = (address, chainId) => {
|
|
5707
6431
|
if (typeof window === "undefined") return null;
|
|
5708
6432
|
const key2 = buildKey2(address);
|
|
5709
|
-
const store =
|
|
6433
|
+
const store = storage5();
|
|
5710
6434
|
let raw = null;
|
|
5711
6435
|
try {
|
|
5712
6436
|
raw = store?.getItem(key2) ?? null;
|
|
@@ -5736,7 +6460,7 @@ var writeSiwxSession = (address, _chainId, session) => {
|
|
|
5736
6460
|
if (typeof window === "undefined") return;
|
|
5737
6461
|
const key2 = buildKey2(address);
|
|
5738
6462
|
memorySiwxSessions.set(key2, session);
|
|
5739
|
-
const store =
|
|
6463
|
+
const store = storage5();
|
|
5740
6464
|
try {
|
|
5741
6465
|
store?.setItem(key2, JSON.stringify(session));
|
|
5742
6466
|
} catch {
|
|
@@ -5745,7 +6469,7 @@ var writeSiwxSession = (address, _chainId, session) => {
|
|
|
5745
6469
|
var clearSiwxSession = (address, _chainId) => {
|
|
5746
6470
|
const key2 = buildKey2(address);
|
|
5747
6471
|
memorySiwxSessions.delete(key2);
|
|
5748
|
-
const store =
|
|
6472
|
+
const store = storage5();
|
|
5749
6473
|
try {
|
|
5750
6474
|
store?.removeItem(key2);
|
|
5751
6475
|
} catch {
|
|
@@ -5877,7 +6601,13 @@ export {
|
|
|
5877
6601
|
NotConnectedError,
|
|
5878
6602
|
OwneyError,
|
|
5879
6603
|
OwneySDK,
|
|
6604
|
+
clearWithdrawSwap,
|
|
5880
6605
|
createOwneySIWX,
|
|
6606
|
+
listPendingDeposits,
|
|
5881
6607
|
listOrders as listPendingSwaps,
|
|
5882
|
-
|
|
6608
|
+
listWithdrawSwaps,
|
|
6609
|
+
saveWithdrawSwap,
|
|
6610
|
+
setOwneyDebug,
|
|
6611
|
+
subscribeWithdrawSwaps,
|
|
6612
|
+
updateWithdrawSwap
|
|
5883
6613
|
};
|