@owney/sdk 0.7.28-beta.3 → 0.7.28-beta.5
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 +147 -17
- package/dist/index.d.cts +25 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.js +147 -17
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2884,6 +2884,33 @@ function swapChain(chainId) {
|
|
|
2884
2884
|
return CHAINS[chainId];
|
|
2885
2885
|
}
|
|
2886
2886
|
|
|
2887
|
+
// src/lib/swap/swap.gas-check.ts
|
|
2888
|
+
var CLASSIC_SWAP_GAS = 300000n;
|
|
2889
|
+
var APPROVE_GAS2 = 60000n;
|
|
2890
|
+
var isNative = (address) => address.toLowerCase().startsWith("0xeeee");
|
|
2891
|
+
async function swapGasShortfall(deps, quote) {
|
|
2892
|
+
if (quote.rail !== "classic" || isNative(quote.src.address)) return null;
|
|
2893
|
+
const gas = CLASSIC_SWAP_GAS + APPROVE_GAS2;
|
|
2894
|
+
const [balance, gasPrice] = await Promise.all([
|
|
2895
|
+
deps.readNativeBalance(),
|
|
2896
|
+
deps.getMaxFeePerGas()
|
|
2897
|
+
]);
|
|
2898
|
+
const required = gas * gasPrice;
|
|
2899
|
+
return balance < required ? { chainId: quote.src.chainId, balance, required } : null;
|
|
2900
|
+
}
|
|
2901
|
+
function swapGasError(shortfall, nativeSymbol) {
|
|
2902
|
+
return new OwneyError(
|
|
2903
|
+
"SWAP_INSUFFICIENT_GAS",
|
|
2904
|
+
`This swap needs a little ${nativeSymbol} for network fees, and your wallet has too little. Add some ${nativeSymbol}, or choose a different asset to receive.`,
|
|
2905
|
+
{
|
|
2906
|
+
chainId: shortfall.chainId,
|
|
2907
|
+
symbol: nativeSymbol,
|
|
2908
|
+
balance: shortfall.balance.toString(),
|
|
2909
|
+
required: shortfall.required.toString()
|
|
2910
|
+
}
|
|
2911
|
+
);
|
|
2912
|
+
}
|
|
2913
|
+
|
|
2887
2914
|
// src/lib/swap/swap.arrival.ts
|
|
2888
2915
|
var DEFAULT_TIMEOUT_MS = 18e4;
|
|
2889
2916
|
var DEFAULT_POLL_MS = 4e3;
|
|
@@ -3074,6 +3101,10 @@ var DEFAULT_POLL_MS2 = 5e3;
|
|
|
3074
3101
|
var MAX_BACKOFF_MS = 3e4;
|
|
3075
3102
|
var backoffFor = (failures, base4) => Math.min(base4 * 2 ** Math.min(failures, 5), MAX_BACKOFF_MS);
|
|
3076
3103
|
var DEFAULT_TIMEOUT_MS2 = 15 * 60 * 1e3;
|
|
3104
|
+
var NOT_FOUND_GRACE_MS = 2 * 60 * 1e3;
|
|
3105
|
+
function isNotFound(error) {
|
|
3106
|
+
return error instanceof OwneyError && error.details?.statusCode === 404;
|
|
3107
|
+
}
|
|
3077
3108
|
async function runFusionOrder(deps, options) {
|
|
3078
3109
|
const {
|
|
3079
3110
|
orderHash,
|
|
@@ -3084,6 +3115,7 @@ async function runFusionOrder(deps, options) {
|
|
|
3084
3115
|
} = options;
|
|
3085
3116
|
const deadline = deps.now() + timeoutMs;
|
|
3086
3117
|
let failures = 0;
|
|
3118
|
+
let notFoundSince;
|
|
3087
3119
|
const published = /* @__PURE__ */ new Set();
|
|
3088
3120
|
onStage?.("swapping");
|
|
3089
3121
|
for (; ; ) {
|
|
@@ -3125,7 +3157,20 @@ async function runFusionOrder(deps, options) {
|
|
|
3125
3157
|
try {
|
|
3126
3158
|
({ status } = await deps.orderStatus(orderHash));
|
|
3127
3159
|
failures = 0;
|
|
3128
|
-
|
|
3160
|
+
notFoundSince = void 0;
|
|
3161
|
+
} catch (error) {
|
|
3162
|
+
if (isNotFound(error)) {
|
|
3163
|
+
notFoundSince ??= deps.now();
|
|
3164
|
+
if (deps.now() - notFoundSince >= NOT_FOUND_GRACE_MS) {
|
|
3165
|
+
throw new OwneyError(
|
|
3166
|
+
"SWAP_ORDER_NOT_FOUND",
|
|
3167
|
+
"The swap provider has no record of this order, so nothing was exchanged.",
|
|
3168
|
+
{ orderHash }
|
|
3169
|
+
);
|
|
3170
|
+
}
|
|
3171
|
+
} else {
|
|
3172
|
+
notFoundSince = void 0;
|
|
3173
|
+
}
|
|
3129
3174
|
failures += 1;
|
|
3130
3175
|
await deps.sleep(backoffFor(failures, pollIntervalMs));
|
|
3131
3176
|
continue;
|
|
@@ -3183,9 +3228,9 @@ async function runSameChainOrder(deps, options) {
|
|
|
3183
3228
|
for (; ; ) {
|
|
3184
3229
|
if (deps.now() >= deadline) {
|
|
3185
3230
|
throw new OwneyError(
|
|
3186
|
-
"
|
|
3187
|
-
"
|
|
3188
|
-
{ orderHash }
|
|
3231
|
+
"SWAP_REQUEST_FAILED",
|
|
3232
|
+
"Timed out waiting for the swap to fill. It may still complete \u2014 if it does, the swapped funds will be in your wallet. Check before retrying.",
|
|
3233
|
+
{ orderHash, settlementUnconfirmed: true }
|
|
3189
3234
|
);
|
|
3190
3235
|
}
|
|
3191
3236
|
let status;
|
|
@@ -3382,8 +3427,8 @@ async function runClassic(deps, options) {
|
|
|
3382
3427
|
onStage?.("quoting");
|
|
3383
3428
|
debugLog("owney-sdk", "swap: fetching classic calldata");
|
|
3384
3429
|
let { tx } = await deps.api.swapTx(swapTxRequest);
|
|
3385
|
-
const
|
|
3386
|
-
if (!
|
|
3430
|
+
const isNative2 = BigInt(tx.value ?? "0") > 0n;
|
|
3431
|
+
if (!isNative2) {
|
|
3387
3432
|
const needed = amount;
|
|
3388
3433
|
const current = await deps.readAllowance(tx.to);
|
|
3389
3434
|
debugLog("owney-sdk", "swap: allowance", {
|
|
@@ -3533,10 +3578,16 @@ async function runFusion(deps, options, walletAddress) {
|
|
|
3533
3578
|
debugLog("owney-sdk", "swap: awaiting signature in wallet", {
|
|
3534
3579
|
signingOnChain: quote.src.chainId
|
|
3535
3580
|
});
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3581
|
+
let signature;
|
|
3582
|
+
try {
|
|
3583
|
+
signature = await awaitWalletPrompt(
|
|
3584
|
+
() => deps.signTypedData(built.typedData),
|
|
3585
|
+
"sign the swap"
|
|
3586
|
+
);
|
|
3587
|
+
} catch (error) {
|
|
3588
|
+
clearOrder(built.orderHash);
|
|
3589
|
+
throw error;
|
|
3590
|
+
}
|
|
3540
3591
|
debugLog("owney-sdk", "swap: signed, submitting to relayer");
|
|
3541
3592
|
await deps.api.submitOrder({
|
|
3542
3593
|
srcChainId: quote.src.chainId,
|
|
@@ -3564,7 +3615,7 @@ async function runFusion(deps, options, walletAddress) {
|
|
|
3564
3615
|
...onStage ? { onStage } : {}
|
|
3565
3616
|
});
|
|
3566
3617
|
} catch (error) {
|
|
3567
|
-
if (error instanceof OwneyError && (error.code === "SWAP_ORDER_REFUNDED" || error.code === "SWAP_ORDER_CANCELLED")) {
|
|
3618
|
+
if (error instanceof OwneyError && (error.code === "SWAP_ORDER_REFUNDED" || error.code === "SWAP_ORDER_CANCELLED" || error.code === "SWAP_ORDER_NOT_FOUND")) {
|
|
3568
3619
|
clearOrder(built.orderHash);
|
|
3569
3620
|
}
|
|
3570
3621
|
throw error;
|
|
@@ -4443,6 +4494,15 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
4443
4494
|
|
|
4444
4495
|
// src/client.ts
|
|
4445
4496
|
var WALLET_CATCHUP_TIMEOUT_MS = 3e4;
|
|
4497
|
+
function shortfallBalance(error, asked) {
|
|
4498
|
+
if (!(error instanceof OwneyError)) return void 0;
|
|
4499
|
+
if (error.code !== "DEPOSIT_INSUFFICIENT_BALANCE") return void 0;
|
|
4500
|
+
const seen = error.details?.balance;
|
|
4501
|
+
if (typeof seen !== "string") return void 0;
|
|
4502
|
+
const balance = BigInt(seen);
|
|
4503
|
+
if (balance <= 0n || balance >= asked) return void 0;
|
|
4504
|
+
return (asked - balance) * 100n <= asked ? balance : void 0;
|
|
4505
|
+
}
|
|
4446
4506
|
function encodeMultiAgentCursor(map) {
|
|
4447
4507
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
4448
4508
|
}
|
|
@@ -5649,6 +5709,38 @@ var OwneySDK = class {
|
|
|
5649
5709
|
const balance = await this.readTokenBalance(chainId, token);
|
|
5650
5710
|
return (balance < received ? balance : received).toString();
|
|
5651
5711
|
}
|
|
5712
|
+
/**
|
|
5713
|
+
* Deposit a swap's output, retrying once at the balance the deposit saw.
|
|
5714
|
+
*
|
|
5715
|
+
* `settleSwapDepositAmount` approves and THEN reads, but the read and the
|
|
5716
|
+
* deposit's own pre-check can disagree: the approval is confirmed through
|
|
5717
|
+
* the wallet's node, the read goes to a pinned RPC, and gas paid in WETH
|
|
5718
|
+
* (MetaMask offers this to a wallet with no ETH) can land after either.
|
|
5719
|
+
* ROUT-618 failed that way with the settle step in place.
|
|
5720
|
+
*
|
|
5721
|
+
* The pre-check reports the balance it saw, and that is the authority, so
|
|
5722
|
+
* a shortfall is retried once at that figure. Only a small one: a node that
|
|
5723
|
+
* has not caught up can read near zero, and depositing that would leave the
|
|
5724
|
+
* rest of the swap stranded behind a "success".
|
|
5725
|
+
*/
|
|
5726
|
+
async depositSwapOutput(options) {
|
|
5727
|
+
const attempt = (amount) => this.deposit({
|
|
5728
|
+
amount,
|
|
5729
|
+
asset: options.asset,
|
|
5730
|
+
...options.agentId ? { agentId: options.agentId } : {}
|
|
5731
|
+
});
|
|
5732
|
+
try {
|
|
5733
|
+
return {
|
|
5734
|
+
deposit: await attempt(options.amount),
|
|
5735
|
+
deposited: options.amount
|
|
5736
|
+
};
|
|
5737
|
+
} catch (error) {
|
|
5738
|
+
const balance = shortfallBalance(error, BigInt(options.amount));
|
|
5739
|
+
if (balance === void 0) throw error;
|
|
5740
|
+
const deposited = balance.toString();
|
|
5741
|
+
return { deposit: await attempt(deposited), deposited };
|
|
5742
|
+
}
|
|
5743
|
+
}
|
|
5652
5744
|
async walletSeesBalance(chainId, token, amount) {
|
|
5653
5745
|
const provider = this.requireConnectedProvider();
|
|
5654
5746
|
const state = this.requireState();
|
|
@@ -5674,9 +5766,39 @@ var OwneySDK = class {
|
|
|
5674
5766
|
* Runs a quoted swap. A named seam rather than an inline `executeSwap` call
|
|
5675
5767
|
* so the deposit half of `swapAndDeposit` can be exercised on its own.
|
|
5676
5768
|
*/
|
|
5677
|
-
runSwap(quote, options) {
|
|
5769
|
+
async runSwap(quote, options) {
|
|
5770
|
+
await this.checkSwapGas(quote);
|
|
5678
5771
|
return executeSwap(this.buildSwapDeps(quote), { quote, ...options });
|
|
5679
5772
|
}
|
|
5773
|
+
/**
|
|
5774
|
+
* Throws SWAP_INSUFFICIENT_GAS when the wallet cannot pay for this swap.
|
|
5775
|
+
*
|
|
5776
|
+
* Only the classic rail is ever refused: it is the one where the user sends
|
|
5777
|
+
* the transactions. Call it on a preview quote to warn BEFORE a withdrawal
|
|
5778
|
+
* moves anything — `withdrawAndSwap` repeats it on its own quote, but by
|
|
5779
|
+
* then the funds have already left the agent (ROUT-622).
|
|
5780
|
+
*/
|
|
5781
|
+
async checkSwapGas(quote) {
|
|
5782
|
+
const state = this.requireState();
|
|
5783
|
+
const chain = swapChain(quote.src.chainId);
|
|
5784
|
+
if (!chain) return;
|
|
5785
|
+
const pub = (0, import_viem9.createPublicClient)({
|
|
5786
|
+
chain,
|
|
5787
|
+
transport: swapReadTransport(quote.src.chainId, this.zyfaiRpcUrls)
|
|
5788
|
+
});
|
|
5789
|
+
const shortfall = await swapGasShortfall(
|
|
5790
|
+
{
|
|
5791
|
+
readNativeBalance: () => pub.getBalance({ address: state.walletAddress }),
|
|
5792
|
+
// The 1559 ceiling, as the wrap reserve reads it.
|
|
5793
|
+
getMaxFeePerGas: async () => {
|
|
5794
|
+
const fees = await pub.estimateFeesPerGas();
|
|
5795
|
+
return fees.maxFeePerGas ?? pub.getGasPrice();
|
|
5796
|
+
}
|
|
5797
|
+
},
|
|
5798
|
+
quote
|
|
5799
|
+
);
|
|
5800
|
+
if (shortfall) throw swapGasError(shortfall, chain.nativeCurrency.symbol);
|
|
5801
|
+
}
|
|
5680
5802
|
/**
|
|
5681
5803
|
* The half of the swap deps that only ever talks to the routing API.
|
|
5682
5804
|
*
|
|
@@ -5748,8 +5870,15 @@ var OwneySDK = class {
|
|
|
5748
5870
|
);
|
|
5749
5871
|
}
|
|
5750
5872
|
await this.ensureSwapChain(entry.chainId);
|
|
5751
|
-
const
|
|
5752
|
-
|
|
5873
|
+
const token = entry.symbol === "WETH" ? SPONSORED_WETH_BY_CHAIN[entry.chainId] : void 0;
|
|
5874
|
+
const amount = token ? await this.settleSwapDepositAmount(
|
|
5875
|
+
entry.chainId,
|
|
5876
|
+
token,
|
|
5877
|
+
entry.symbol,
|
|
5878
|
+
BigInt(entry.received)
|
|
5879
|
+
) : entry.received;
|
|
5880
|
+
const { deposit } = await this.depositSwapOutput({
|
|
5881
|
+
amount,
|
|
5753
5882
|
asset: entry.symbol,
|
|
5754
5883
|
...entry.agentId ? { agentId: entry.agentId } : {}
|
|
5755
5884
|
});
|
|
@@ -5799,7 +5928,7 @@ var OwneySDK = class {
|
|
|
5799
5928
|
status: "completed"
|
|
5800
5929
|
});
|
|
5801
5930
|
} catch (error) {
|
|
5802
|
-
if (error instanceof OwneyError && (error.code === "SWAP_ORDER_REFUNDED" || error.code === "SWAP_ORDER_CANCELLED")) {
|
|
5931
|
+
if (error instanceof OwneyError && (error.code === "SWAP_ORDER_REFUNDED" || error.code === "SWAP_ORDER_CANCELLED" || error.code === "SWAP_ORDER_NOT_FOUND")) {
|
|
5803
5932
|
clearOrder(order.orderHash);
|
|
5804
5933
|
updateWithdrawSwap(order.orderHash, { status: "refunded" });
|
|
5805
5934
|
} else {
|
|
@@ -5989,12 +6118,12 @@ var OwneySDK = class {
|
|
|
5989
6118
|
options.to.symbol,
|
|
5990
6119
|
BigInt(swap.received)
|
|
5991
6120
|
);
|
|
5992
|
-
const deposit = await this.
|
|
6121
|
+
const { deposit, deposited } = await this.depositSwapOutput({
|
|
5993
6122
|
amount,
|
|
5994
6123
|
asset: options.to.symbol,
|
|
5995
6124
|
...options.agentId ? { agentId: options.agentId } : {}
|
|
5996
6125
|
});
|
|
5997
|
-
return { swap, deposit, deposited
|
|
6126
|
+
return { swap, deposit, deposited };
|
|
5998
6127
|
} catch (error) {
|
|
5999
6128
|
const pending = {
|
|
6000
6129
|
id: `${quote.dst.chainId}-${options.to.symbol}-${Date.now()}`,
|
|
@@ -6098,6 +6227,7 @@ var OwneySDK = class {
|
|
|
6098
6227
|
walletAddress: state.walletAddress
|
|
6099
6228
|
});
|
|
6100
6229
|
await this.ensureSwapChain(quote.src.chainId);
|
|
6230
|
+
await this.checkSwapGas(quote);
|
|
6101
6231
|
const swap = await executeSwap(this.buildSwapDeps(quote), {
|
|
6102
6232
|
quote,
|
|
6103
6233
|
walletAddress: state.walletAddress,
|
package/dist/index.d.cts
CHANGED
|
@@ -964,7 +964,7 @@ type AgentApyOptions = {
|
|
|
964
964
|
chainId?: number;
|
|
965
965
|
};
|
|
966
966
|
|
|
967
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_BALANCE_UNAVAILABLE" | "DEPOSIT_PARTIAL_FAILURE" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_NOTHING_TO_WITHDRAW" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "SWAP_DISABLED" | "SWAP_RATE_LIMITED" | "SWAP_REQUEST_FAILED" | "SWAP_QUOTE_FAILED" | "SWAP_UNSUPPORTED_PAIR" | "SWAP_APPROVAL_REQUIRED" | "SWAP_BELOW_DEPOSIT_MINIMUM" | "SWAP_DEPOSIT_PENDING" | "SWAP_WALLET_PROMPT_TIMEOUT" | "SWAP_INSUFFICIENT_GAS" | "SWAP_NATIVE_UNSUPPORTED" | "SWAP_ORDER_EXPIRED" | "SWAP_ORDER_REFUNDED" | "SWAP_ORDER_CANCELLED" | "WITHDRAW_ARRIVAL_TIMEOUT" | "WITHDRAW_SWAP_FAILED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "POOL_CATALOG_UNSUPPORTED" | "POOL_SELECTION_UNSUPPORTED" | "VALIDATION_INVALID_DAYS";
|
|
967
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_BALANCE_UNAVAILABLE" | "DEPOSIT_PARTIAL_FAILURE" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_NOTHING_TO_WITHDRAW" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "SWAP_DISABLED" | "SWAP_RATE_LIMITED" | "SWAP_REQUEST_FAILED" | "SWAP_QUOTE_FAILED" | "SWAP_UNSUPPORTED_PAIR" | "SWAP_APPROVAL_REQUIRED" | "SWAP_BELOW_DEPOSIT_MINIMUM" | "SWAP_DEPOSIT_PENDING" | "SWAP_WALLET_PROMPT_TIMEOUT" | "SWAP_INSUFFICIENT_GAS" | "SWAP_NATIVE_UNSUPPORTED" | "SWAP_ORDER_EXPIRED" | "SWAP_ORDER_REFUNDED" | "SWAP_ORDER_CANCELLED" | "SWAP_ORDER_NOT_FOUND" | "WITHDRAW_ARRIVAL_TIMEOUT" | "WITHDRAW_SWAP_FAILED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "POOL_CATALOG_UNSUPPORTED" | "POOL_SELECTION_UNSUPPORTED" | "VALIDATION_INVALID_DAYS";
|
|
968
968
|
declare class OwneyError extends Error {
|
|
969
969
|
readonly code: OwneyErrorCode;
|
|
970
970
|
readonly details?: Record<string, unknown>;
|
|
@@ -1393,12 +1393,36 @@ declare class OwneySDK {
|
|
|
1393
1393
|
* where the sponsor covers the transfer and Permit2 never applies.
|
|
1394
1394
|
*/
|
|
1395
1395
|
private settleSwapDepositAmount;
|
|
1396
|
+
/**
|
|
1397
|
+
* Deposit a swap's output, retrying once at the balance the deposit saw.
|
|
1398
|
+
*
|
|
1399
|
+
* `settleSwapDepositAmount` approves and THEN reads, but the read and the
|
|
1400
|
+
* deposit's own pre-check can disagree: the approval is confirmed through
|
|
1401
|
+
* the wallet's node, the read goes to a pinned RPC, and gas paid in WETH
|
|
1402
|
+
* (MetaMask offers this to a wallet with no ETH) can land after either.
|
|
1403
|
+
* ROUT-618 failed that way with the settle step in place.
|
|
1404
|
+
*
|
|
1405
|
+
* The pre-check reports the balance it saw, and that is the authority, so
|
|
1406
|
+
* a shortfall is retried once at that figure. Only a small one: a node that
|
|
1407
|
+
* has not caught up can read near zero, and depositing that would leave the
|
|
1408
|
+
* rest of the swap stranded behind a "success".
|
|
1409
|
+
*/
|
|
1410
|
+
private depositSwapOutput;
|
|
1396
1411
|
private walletSeesBalance;
|
|
1397
1412
|
/**
|
|
1398
1413
|
* Runs a quoted swap. A named seam rather than an inline `executeSwap` call
|
|
1399
1414
|
* so the deposit half of `swapAndDeposit` can be exercised on its own.
|
|
1400
1415
|
*/
|
|
1401
1416
|
private runSwap;
|
|
1417
|
+
/**
|
|
1418
|
+
* Throws SWAP_INSUFFICIENT_GAS when the wallet cannot pay for this swap.
|
|
1419
|
+
*
|
|
1420
|
+
* Only the classic rail is ever refused: it is the one where the user sends
|
|
1421
|
+
* the transactions. Call it on a preview quote to warn BEFORE a withdrawal
|
|
1422
|
+
* moves anything — `withdrawAndSwap` repeats it on its own quote, but by
|
|
1423
|
+
* then the funds have already left the agent (ROUT-622).
|
|
1424
|
+
*/
|
|
1425
|
+
checkSwapGas(quote: SwapQuote): Promise<void>;
|
|
1402
1426
|
/**
|
|
1403
1427
|
* The half of the swap deps that only ever talks to the routing API.
|
|
1404
1428
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -964,7 +964,7 @@ type AgentApyOptions = {
|
|
|
964
964
|
chainId?: number;
|
|
965
965
|
};
|
|
966
966
|
|
|
967
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_BALANCE_UNAVAILABLE" | "DEPOSIT_PARTIAL_FAILURE" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_NOTHING_TO_WITHDRAW" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "SWAP_DISABLED" | "SWAP_RATE_LIMITED" | "SWAP_REQUEST_FAILED" | "SWAP_QUOTE_FAILED" | "SWAP_UNSUPPORTED_PAIR" | "SWAP_APPROVAL_REQUIRED" | "SWAP_BELOW_DEPOSIT_MINIMUM" | "SWAP_DEPOSIT_PENDING" | "SWAP_WALLET_PROMPT_TIMEOUT" | "SWAP_INSUFFICIENT_GAS" | "SWAP_NATIVE_UNSUPPORTED" | "SWAP_ORDER_EXPIRED" | "SWAP_ORDER_REFUNDED" | "SWAP_ORDER_CANCELLED" | "WITHDRAW_ARRIVAL_TIMEOUT" | "WITHDRAW_SWAP_FAILED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "POOL_CATALOG_UNSUPPORTED" | "POOL_SELECTION_UNSUPPORTED" | "VALIDATION_INVALID_DAYS";
|
|
967
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_BALANCE_UNAVAILABLE" | "DEPOSIT_PARTIAL_FAILURE" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_NOTHING_TO_WITHDRAW" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "AGENT_RATE_LIMITED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "SWAP_DISABLED" | "SWAP_RATE_LIMITED" | "SWAP_REQUEST_FAILED" | "SWAP_QUOTE_FAILED" | "SWAP_UNSUPPORTED_PAIR" | "SWAP_APPROVAL_REQUIRED" | "SWAP_BELOW_DEPOSIT_MINIMUM" | "SWAP_DEPOSIT_PENDING" | "SWAP_WALLET_PROMPT_TIMEOUT" | "SWAP_INSUFFICIENT_GAS" | "SWAP_NATIVE_UNSUPPORTED" | "SWAP_ORDER_EXPIRED" | "SWAP_ORDER_REFUNDED" | "SWAP_ORDER_CANCELLED" | "SWAP_ORDER_NOT_FOUND" | "WITHDRAW_ARRIVAL_TIMEOUT" | "WITHDRAW_SWAP_FAILED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "POOL_CATALOG_UNSUPPORTED" | "POOL_SELECTION_UNSUPPORTED" | "VALIDATION_INVALID_DAYS";
|
|
968
968
|
declare class OwneyError extends Error {
|
|
969
969
|
readonly code: OwneyErrorCode;
|
|
970
970
|
readonly details?: Record<string, unknown>;
|
|
@@ -1393,12 +1393,36 @@ declare class OwneySDK {
|
|
|
1393
1393
|
* where the sponsor covers the transfer and Permit2 never applies.
|
|
1394
1394
|
*/
|
|
1395
1395
|
private settleSwapDepositAmount;
|
|
1396
|
+
/**
|
|
1397
|
+
* Deposit a swap's output, retrying once at the balance the deposit saw.
|
|
1398
|
+
*
|
|
1399
|
+
* `settleSwapDepositAmount` approves and THEN reads, but the read and the
|
|
1400
|
+
* deposit's own pre-check can disagree: the approval is confirmed through
|
|
1401
|
+
* the wallet's node, the read goes to a pinned RPC, and gas paid in WETH
|
|
1402
|
+
* (MetaMask offers this to a wallet with no ETH) can land after either.
|
|
1403
|
+
* ROUT-618 failed that way with the settle step in place.
|
|
1404
|
+
*
|
|
1405
|
+
* The pre-check reports the balance it saw, and that is the authority, so
|
|
1406
|
+
* a shortfall is retried once at that figure. Only a small one: a node that
|
|
1407
|
+
* has not caught up can read near zero, and depositing that would leave the
|
|
1408
|
+
* rest of the swap stranded behind a "success".
|
|
1409
|
+
*/
|
|
1410
|
+
private depositSwapOutput;
|
|
1396
1411
|
private walletSeesBalance;
|
|
1397
1412
|
/**
|
|
1398
1413
|
* Runs a quoted swap. A named seam rather than an inline `executeSwap` call
|
|
1399
1414
|
* so the deposit half of `swapAndDeposit` can be exercised on its own.
|
|
1400
1415
|
*/
|
|
1401
1416
|
private runSwap;
|
|
1417
|
+
/**
|
|
1418
|
+
* Throws SWAP_INSUFFICIENT_GAS when the wallet cannot pay for this swap.
|
|
1419
|
+
*
|
|
1420
|
+
* Only the classic rail is ever refused: it is the one where the user sends
|
|
1421
|
+
* the transactions. Call it on a preview quote to warn BEFORE a withdrawal
|
|
1422
|
+
* moves anything — `withdrawAndSwap` repeats it on its own quote, but by
|
|
1423
|
+
* then the funds have already left the agent (ROUT-622).
|
|
1424
|
+
*/
|
|
1425
|
+
checkSwapGas(quote: SwapQuote): Promise<void>;
|
|
1402
1426
|
/**
|
|
1403
1427
|
* The half of the swap deps that only ever talks to the routing API.
|
|
1404
1428
|
*
|
package/dist/index.js
CHANGED
|
@@ -2854,6 +2854,33 @@ function swapChain(chainId) {
|
|
|
2854
2854
|
return CHAINS[chainId];
|
|
2855
2855
|
}
|
|
2856
2856
|
|
|
2857
|
+
// src/lib/swap/swap.gas-check.ts
|
|
2858
|
+
var CLASSIC_SWAP_GAS = 300000n;
|
|
2859
|
+
var APPROVE_GAS2 = 60000n;
|
|
2860
|
+
var isNative = (address) => address.toLowerCase().startsWith("0xeeee");
|
|
2861
|
+
async function swapGasShortfall(deps, quote) {
|
|
2862
|
+
if (quote.rail !== "classic" || isNative(quote.src.address)) return null;
|
|
2863
|
+
const gas = CLASSIC_SWAP_GAS + APPROVE_GAS2;
|
|
2864
|
+
const [balance, gasPrice] = await Promise.all([
|
|
2865
|
+
deps.readNativeBalance(),
|
|
2866
|
+
deps.getMaxFeePerGas()
|
|
2867
|
+
]);
|
|
2868
|
+
const required = gas * gasPrice;
|
|
2869
|
+
return balance < required ? { chainId: quote.src.chainId, balance, required } : null;
|
|
2870
|
+
}
|
|
2871
|
+
function swapGasError(shortfall, nativeSymbol) {
|
|
2872
|
+
return new OwneyError(
|
|
2873
|
+
"SWAP_INSUFFICIENT_GAS",
|
|
2874
|
+
`This swap needs a little ${nativeSymbol} for network fees, and your wallet has too little. Add some ${nativeSymbol}, or choose a different asset to receive.`,
|
|
2875
|
+
{
|
|
2876
|
+
chainId: shortfall.chainId,
|
|
2877
|
+
symbol: nativeSymbol,
|
|
2878
|
+
balance: shortfall.balance.toString(),
|
|
2879
|
+
required: shortfall.required.toString()
|
|
2880
|
+
}
|
|
2881
|
+
);
|
|
2882
|
+
}
|
|
2883
|
+
|
|
2857
2884
|
// src/lib/swap/swap.arrival.ts
|
|
2858
2885
|
var DEFAULT_TIMEOUT_MS = 18e4;
|
|
2859
2886
|
var DEFAULT_POLL_MS = 4e3;
|
|
@@ -3044,6 +3071,10 @@ var DEFAULT_POLL_MS2 = 5e3;
|
|
|
3044
3071
|
var MAX_BACKOFF_MS = 3e4;
|
|
3045
3072
|
var backoffFor = (failures, base4) => Math.min(base4 * 2 ** Math.min(failures, 5), MAX_BACKOFF_MS);
|
|
3046
3073
|
var DEFAULT_TIMEOUT_MS2 = 15 * 60 * 1e3;
|
|
3074
|
+
var NOT_FOUND_GRACE_MS = 2 * 60 * 1e3;
|
|
3075
|
+
function isNotFound(error) {
|
|
3076
|
+
return error instanceof OwneyError && error.details?.statusCode === 404;
|
|
3077
|
+
}
|
|
3047
3078
|
async function runFusionOrder(deps, options) {
|
|
3048
3079
|
const {
|
|
3049
3080
|
orderHash,
|
|
@@ -3054,6 +3085,7 @@ async function runFusionOrder(deps, options) {
|
|
|
3054
3085
|
} = options;
|
|
3055
3086
|
const deadline = deps.now() + timeoutMs;
|
|
3056
3087
|
let failures = 0;
|
|
3088
|
+
let notFoundSince;
|
|
3057
3089
|
const published = /* @__PURE__ */ new Set();
|
|
3058
3090
|
onStage?.("swapping");
|
|
3059
3091
|
for (; ; ) {
|
|
@@ -3095,7 +3127,20 @@ async function runFusionOrder(deps, options) {
|
|
|
3095
3127
|
try {
|
|
3096
3128
|
({ status } = await deps.orderStatus(orderHash));
|
|
3097
3129
|
failures = 0;
|
|
3098
|
-
|
|
3130
|
+
notFoundSince = void 0;
|
|
3131
|
+
} catch (error) {
|
|
3132
|
+
if (isNotFound(error)) {
|
|
3133
|
+
notFoundSince ??= deps.now();
|
|
3134
|
+
if (deps.now() - notFoundSince >= NOT_FOUND_GRACE_MS) {
|
|
3135
|
+
throw new OwneyError(
|
|
3136
|
+
"SWAP_ORDER_NOT_FOUND",
|
|
3137
|
+
"The swap provider has no record of this order, so nothing was exchanged.",
|
|
3138
|
+
{ orderHash }
|
|
3139
|
+
);
|
|
3140
|
+
}
|
|
3141
|
+
} else {
|
|
3142
|
+
notFoundSince = void 0;
|
|
3143
|
+
}
|
|
3099
3144
|
failures += 1;
|
|
3100
3145
|
await deps.sleep(backoffFor(failures, pollIntervalMs));
|
|
3101
3146
|
continue;
|
|
@@ -3153,9 +3198,9 @@ async function runSameChainOrder(deps, options) {
|
|
|
3153
3198
|
for (; ; ) {
|
|
3154
3199
|
if (deps.now() >= deadline) {
|
|
3155
3200
|
throw new OwneyError(
|
|
3156
|
-
"
|
|
3157
|
-
"
|
|
3158
|
-
{ orderHash }
|
|
3201
|
+
"SWAP_REQUEST_FAILED",
|
|
3202
|
+
"Timed out waiting for the swap to fill. It may still complete \u2014 if it does, the swapped funds will be in your wallet. Check before retrying.",
|
|
3203
|
+
{ orderHash, settlementUnconfirmed: true }
|
|
3159
3204
|
);
|
|
3160
3205
|
}
|
|
3161
3206
|
let status;
|
|
@@ -3352,8 +3397,8 @@ async function runClassic(deps, options) {
|
|
|
3352
3397
|
onStage?.("quoting");
|
|
3353
3398
|
debugLog("owney-sdk", "swap: fetching classic calldata");
|
|
3354
3399
|
let { tx } = await deps.api.swapTx(swapTxRequest);
|
|
3355
|
-
const
|
|
3356
|
-
if (!
|
|
3400
|
+
const isNative2 = BigInt(tx.value ?? "0") > 0n;
|
|
3401
|
+
if (!isNative2) {
|
|
3357
3402
|
const needed = amount;
|
|
3358
3403
|
const current = await deps.readAllowance(tx.to);
|
|
3359
3404
|
debugLog("owney-sdk", "swap: allowance", {
|
|
@@ -3503,10 +3548,16 @@ async function runFusion(deps, options, walletAddress) {
|
|
|
3503
3548
|
debugLog("owney-sdk", "swap: awaiting signature in wallet", {
|
|
3504
3549
|
signingOnChain: quote.src.chainId
|
|
3505
3550
|
});
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3551
|
+
let signature;
|
|
3552
|
+
try {
|
|
3553
|
+
signature = await awaitWalletPrompt(
|
|
3554
|
+
() => deps.signTypedData(built.typedData),
|
|
3555
|
+
"sign the swap"
|
|
3556
|
+
);
|
|
3557
|
+
} catch (error) {
|
|
3558
|
+
clearOrder(built.orderHash);
|
|
3559
|
+
throw error;
|
|
3560
|
+
}
|
|
3510
3561
|
debugLog("owney-sdk", "swap: signed, submitting to relayer");
|
|
3511
3562
|
await deps.api.submitOrder({
|
|
3512
3563
|
srcChainId: quote.src.chainId,
|
|
@@ -3534,7 +3585,7 @@ async function runFusion(deps, options, walletAddress) {
|
|
|
3534
3585
|
...onStage ? { onStage } : {}
|
|
3535
3586
|
});
|
|
3536
3587
|
} catch (error) {
|
|
3537
|
-
if (error instanceof OwneyError && (error.code === "SWAP_ORDER_REFUNDED" || error.code === "SWAP_ORDER_CANCELLED")) {
|
|
3588
|
+
if (error instanceof OwneyError && (error.code === "SWAP_ORDER_REFUNDED" || error.code === "SWAP_ORDER_CANCELLED" || error.code === "SWAP_ORDER_NOT_FOUND")) {
|
|
3538
3589
|
clearOrder(built.orderHash);
|
|
3539
3590
|
}
|
|
3540
3591
|
throw error;
|
|
@@ -4424,6 +4475,15 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
4424
4475
|
|
|
4425
4476
|
// src/client.ts
|
|
4426
4477
|
var WALLET_CATCHUP_TIMEOUT_MS = 3e4;
|
|
4478
|
+
function shortfallBalance(error, asked) {
|
|
4479
|
+
if (!(error instanceof OwneyError)) return void 0;
|
|
4480
|
+
if (error.code !== "DEPOSIT_INSUFFICIENT_BALANCE") return void 0;
|
|
4481
|
+
const seen = error.details?.balance;
|
|
4482
|
+
if (typeof seen !== "string") return void 0;
|
|
4483
|
+
const balance = BigInt(seen);
|
|
4484
|
+
if (balance <= 0n || balance >= asked) return void 0;
|
|
4485
|
+
return (asked - balance) * 100n <= asked ? balance : void 0;
|
|
4486
|
+
}
|
|
4427
4487
|
function encodeMultiAgentCursor(map) {
|
|
4428
4488
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
4429
4489
|
}
|
|
@@ -5630,6 +5690,38 @@ var OwneySDK = class {
|
|
|
5630
5690
|
const balance = await this.readTokenBalance(chainId, token);
|
|
5631
5691
|
return (balance < received ? balance : received).toString();
|
|
5632
5692
|
}
|
|
5693
|
+
/**
|
|
5694
|
+
* Deposit a swap's output, retrying once at the balance the deposit saw.
|
|
5695
|
+
*
|
|
5696
|
+
* `settleSwapDepositAmount` approves and THEN reads, but the read and the
|
|
5697
|
+
* deposit's own pre-check can disagree: the approval is confirmed through
|
|
5698
|
+
* the wallet's node, the read goes to a pinned RPC, and gas paid in WETH
|
|
5699
|
+
* (MetaMask offers this to a wallet with no ETH) can land after either.
|
|
5700
|
+
* ROUT-618 failed that way with the settle step in place.
|
|
5701
|
+
*
|
|
5702
|
+
* The pre-check reports the balance it saw, and that is the authority, so
|
|
5703
|
+
* a shortfall is retried once at that figure. Only a small one: a node that
|
|
5704
|
+
* has not caught up can read near zero, and depositing that would leave the
|
|
5705
|
+
* rest of the swap stranded behind a "success".
|
|
5706
|
+
*/
|
|
5707
|
+
async depositSwapOutput(options) {
|
|
5708
|
+
const attempt = (amount) => this.deposit({
|
|
5709
|
+
amount,
|
|
5710
|
+
asset: options.asset,
|
|
5711
|
+
...options.agentId ? { agentId: options.agentId } : {}
|
|
5712
|
+
});
|
|
5713
|
+
try {
|
|
5714
|
+
return {
|
|
5715
|
+
deposit: await attempt(options.amount),
|
|
5716
|
+
deposited: options.amount
|
|
5717
|
+
};
|
|
5718
|
+
} catch (error) {
|
|
5719
|
+
const balance = shortfallBalance(error, BigInt(options.amount));
|
|
5720
|
+
if (balance === void 0) throw error;
|
|
5721
|
+
const deposited = balance.toString();
|
|
5722
|
+
return { deposit: await attempt(deposited), deposited };
|
|
5723
|
+
}
|
|
5724
|
+
}
|
|
5633
5725
|
async walletSeesBalance(chainId, token, amount) {
|
|
5634
5726
|
const provider = this.requireConnectedProvider();
|
|
5635
5727
|
const state = this.requireState();
|
|
@@ -5655,9 +5747,39 @@ var OwneySDK = class {
|
|
|
5655
5747
|
* Runs a quoted swap. A named seam rather than an inline `executeSwap` call
|
|
5656
5748
|
* so the deposit half of `swapAndDeposit` can be exercised on its own.
|
|
5657
5749
|
*/
|
|
5658
|
-
runSwap(quote, options) {
|
|
5750
|
+
async runSwap(quote, options) {
|
|
5751
|
+
await this.checkSwapGas(quote);
|
|
5659
5752
|
return executeSwap(this.buildSwapDeps(quote), { quote, ...options });
|
|
5660
5753
|
}
|
|
5754
|
+
/**
|
|
5755
|
+
* Throws SWAP_INSUFFICIENT_GAS when the wallet cannot pay for this swap.
|
|
5756
|
+
*
|
|
5757
|
+
* Only the classic rail is ever refused: it is the one where the user sends
|
|
5758
|
+
* the transactions. Call it on a preview quote to warn BEFORE a withdrawal
|
|
5759
|
+
* moves anything — `withdrawAndSwap` repeats it on its own quote, but by
|
|
5760
|
+
* then the funds have already left the agent (ROUT-622).
|
|
5761
|
+
*/
|
|
5762
|
+
async checkSwapGas(quote) {
|
|
5763
|
+
const state = this.requireState();
|
|
5764
|
+
const chain = swapChain(quote.src.chainId);
|
|
5765
|
+
if (!chain) return;
|
|
5766
|
+
const pub = createPublicClient2({
|
|
5767
|
+
chain,
|
|
5768
|
+
transport: swapReadTransport(quote.src.chainId, this.zyfaiRpcUrls)
|
|
5769
|
+
});
|
|
5770
|
+
const shortfall = await swapGasShortfall(
|
|
5771
|
+
{
|
|
5772
|
+
readNativeBalance: () => pub.getBalance({ address: state.walletAddress }),
|
|
5773
|
+
// The 1559 ceiling, as the wrap reserve reads it.
|
|
5774
|
+
getMaxFeePerGas: async () => {
|
|
5775
|
+
const fees = await pub.estimateFeesPerGas();
|
|
5776
|
+
return fees.maxFeePerGas ?? pub.getGasPrice();
|
|
5777
|
+
}
|
|
5778
|
+
},
|
|
5779
|
+
quote
|
|
5780
|
+
);
|
|
5781
|
+
if (shortfall) throw swapGasError(shortfall, chain.nativeCurrency.symbol);
|
|
5782
|
+
}
|
|
5661
5783
|
/**
|
|
5662
5784
|
* The half of the swap deps that only ever talks to the routing API.
|
|
5663
5785
|
*
|
|
@@ -5729,8 +5851,15 @@ var OwneySDK = class {
|
|
|
5729
5851
|
);
|
|
5730
5852
|
}
|
|
5731
5853
|
await this.ensureSwapChain(entry.chainId);
|
|
5732
|
-
const
|
|
5733
|
-
|
|
5854
|
+
const token = entry.symbol === "WETH" ? SPONSORED_WETH_BY_CHAIN[entry.chainId] : void 0;
|
|
5855
|
+
const amount = token ? await this.settleSwapDepositAmount(
|
|
5856
|
+
entry.chainId,
|
|
5857
|
+
token,
|
|
5858
|
+
entry.symbol,
|
|
5859
|
+
BigInt(entry.received)
|
|
5860
|
+
) : entry.received;
|
|
5861
|
+
const { deposit } = await this.depositSwapOutput({
|
|
5862
|
+
amount,
|
|
5734
5863
|
asset: entry.symbol,
|
|
5735
5864
|
...entry.agentId ? { agentId: entry.agentId } : {}
|
|
5736
5865
|
});
|
|
@@ -5780,7 +5909,7 @@ var OwneySDK = class {
|
|
|
5780
5909
|
status: "completed"
|
|
5781
5910
|
});
|
|
5782
5911
|
} catch (error) {
|
|
5783
|
-
if (error instanceof OwneyError && (error.code === "SWAP_ORDER_REFUNDED" || error.code === "SWAP_ORDER_CANCELLED")) {
|
|
5912
|
+
if (error instanceof OwneyError && (error.code === "SWAP_ORDER_REFUNDED" || error.code === "SWAP_ORDER_CANCELLED" || error.code === "SWAP_ORDER_NOT_FOUND")) {
|
|
5784
5913
|
clearOrder(order.orderHash);
|
|
5785
5914
|
updateWithdrawSwap(order.orderHash, { status: "refunded" });
|
|
5786
5915
|
} else {
|
|
@@ -5970,12 +6099,12 @@ var OwneySDK = class {
|
|
|
5970
6099
|
options.to.symbol,
|
|
5971
6100
|
BigInt(swap.received)
|
|
5972
6101
|
);
|
|
5973
|
-
const deposit = await this.
|
|
6102
|
+
const { deposit, deposited } = await this.depositSwapOutput({
|
|
5974
6103
|
amount,
|
|
5975
6104
|
asset: options.to.symbol,
|
|
5976
6105
|
...options.agentId ? { agentId: options.agentId } : {}
|
|
5977
6106
|
});
|
|
5978
|
-
return { swap, deposit, deposited
|
|
6107
|
+
return { swap, deposit, deposited };
|
|
5979
6108
|
} catch (error) {
|
|
5980
6109
|
const pending = {
|
|
5981
6110
|
id: `${quote.dst.chainId}-${options.to.symbol}-${Date.now()}`,
|
|
@@ -6079,6 +6208,7 @@ var OwneySDK = class {
|
|
|
6079
6208
|
walletAddress: state.walletAddress
|
|
6080
6209
|
});
|
|
6081
6210
|
await this.ensureSwapChain(quote.src.chainId);
|
|
6211
|
+
await this.checkSwapGas(quote);
|
|
6082
6212
|
const swap = await executeSwap(this.buildSwapDeps(quote), {
|
|
6083
6213
|
quote,
|
|
6084
6214
|
walletAddress: state.walletAddress,
|