@anywalletkit/protocol-swap2-curve 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-JCWXGKPJ.js → chunk-7AXQMAHJ.js} +2 -2
- package/dist/{chunk-IFREGXMV.js → chunk-NW2OLRIK.js} +127 -105
- package/dist/chunk-NW2OLRIK.js.map +1 -0
- package/dist/index.cjs +126 -104
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/protocol.cjs +119 -99
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.js +2 -2
- package/dist/provider.cjs +119 -99
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-IFREGXMV.js.map +0 -1
- /package/dist/{chunk-JCWXGKPJ.js.map → chunk-7AXQMAHJ.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -222,6 +222,18 @@ function decodeExchange(family, data) {
|
|
|
222
222
|
// src/routes.ts
|
|
223
223
|
var import_viem2 = require("viem");
|
|
224
224
|
var import_swap2_assets = require("@anywalletkit/swap2-assets");
|
|
225
|
+
|
|
226
|
+
// src/reasons.ts
|
|
227
|
+
var import_errors = require("@anywalletkit/protocol-swap2-core/errors");
|
|
228
|
+
var notes = (0, import_errors.refusalNotes)(256);
|
|
229
|
+
function noted(text, info) {
|
|
230
|
+
return info === void 0 ? text : notes.note(text, info);
|
|
231
|
+
}
|
|
232
|
+
function tagged(error, info) {
|
|
233
|
+
return info === void 0 ? error : (0, import_errors.withReason)(error, info);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/routes.ts
|
|
225
237
|
var MAX_QUOTE_CANDIDATES = 30;
|
|
226
238
|
var MAX_EXPLORED = 2e4;
|
|
227
239
|
var lc = (a) => a.toLowerCase();
|
|
@@ -372,7 +384,7 @@ function routePools(args) {
|
|
|
372
384
|
}
|
|
373
385
|
function checkRoute(chainId, deployment, table, args, tokenIn, tokenOut) {
|
|
374
386
|
const cols = deployment.family === "ng5" ? 5 : 4;
|
|
375
|
-
if (args.route.length !== 11 || args.params.length !== 5 || args.params.some((r) => r.length !== cols)) return `the route is not address[11] with uint256[${cols}][5]
|
|
387
|
+
if (args.route.length !== 11 || args.params.length !== 5 || args.params.some((r) => r.length !== cols)) return noted(`the route is not address[11] with uint256[${cols}][5]`, "policy_refused");
|
|
376
388
|
const index = poolIndex(chainId, deployment, table);
|
|
377
389
|
const zero = lc(ZERO_ADDRESS);
|
|
378
390
|
const eth = lc(deployment.eth);
|
|
@@ -380,14 +392,14 @@ function checkRoute(chainId, deployment, table, args, tokenIn, tokenOut) {
|
|
|
380
392
|
const v = erc4626Of(deployment);
|
|
381
393
|
let steps = 0;
|
|
382
394
|
while (steps < 5 && lc(args.route[2 * steps + 1]) !== zero) steps++;
|
|
383
|
-
if (steps === 0) return "the route has no step";
|
|
384
|
-
if (steps > MAX_ROUTE_STEPS) return `the route has ${steps} steps, more than ${MAX_ROUTE_STEPS}
|
|
385
|
-
for (let k = 2 * steps + 1; k < 11; k++) if (lc(args.route[k]) !== zero) return "the route names addresses after its end";
|
|
386
|
-
for (let k = steps; k < 5; k++) if (args.params[k].some((x) => x !== 0n)) return "the swap params carry rows after the route's end";
|
|
387
|
-
if (lc(args.route[0]) !== lc(tokenIn)) return `the route starts at ${args.route[0]}, not the source token
|
|
388
|
-
if (lc(args.route[2 * steps]) !== lc(tokenOut)) return `the route ends at ${args.route[2 * steps]}, not the destination token
|
|
395
|
+
if (steps === 0) return noted("the route has no step", "policy_refused");
|
|
396
|
+
if (steps > MAX_ROUTE_STEPS) return noted(`the route has ${steps} steps, more than ${MAX_ROUTE_STEPS}`, "policy_refused");
|
|
397
|
+
for (let k = 2 * steps + 1; k < 11; k++) if (lc(args.route[k]) !== zero) return noted("the route names addresses after its end", "policy_refused");
|
|
398
|
+
for (let k = steps; k < 5; k++) if (args.params[k].some((x) => x !== 0n)) return noted("the swap params carry rows after the route's end", "policy_refused");
|
|
399
|
+
if (lc(args.route[0]) !== lc(tokenIn)) return noted(`the route starts at ${args.route[0]}, not the source token`, "policy_refused");
|
|
400
|
+
if (lc(args.route[2 * steps]) !== lc(tokenOut)) return noted(`the route ends at ${args.route[2 * steps]}, not the destination token`, "price_check_failed");
|
|
389
401
|
for (let k = 1; k < steps; k++) {
|
|
390
|
-
if (!intermediateAllowed(chainId, deployment, args.route[2 * k])) return `step ${k} hands the swap through ${args.route[2 * k]}, a token the catalog does not list on this chain
|
|
402
|
+
if (!intermediateAllowed(chainId, deployment, args.route[2 * k])) return noted(`step ${k} hands the swap through ${args.route[2 * k]}, a token the catalog does not list on this chain`, "policy_refused");
|
|
391
403
|
}
|
|
392
404
|
const pools = /* @__PURE__ */ new Set();
|
|
393
405
|
let wraps = 0;
|
|
@@ -398,51 +410,52 @@ function checkRoute(chainId, deployment, table, args, tokenIn, tokenOut) {
|
|
|
398
410
|
const b = lc(args.route[2 * k + 2]);
|
|
399
411
|
const row = args.params[k];
|
|
400
412
|
const type = row[2];
|
|
401
|
-
if (a === b) return `step ${k + 1} trades a token for itself
|
|
413
|
+
if (a === b) return noted(`step ${k + 1} trades a token for itself`, "policy_refused");
|
|
402
414
|
if (type === 1n || type === 2n) {
|
|
403
|
-
if (CURVE_DENIED_POOLS[chainId]?.has(swap)) return `step ${k + 1} crosses ${args.route[2 * k + 1]}, a pool this module refuses (fake coin, drained in 2023, or over a dead venue)
|
|
415
|
+
if (CURVE_DENIED_POOLS[chainId]?.has(swap)) return noted(`step ${k + 1} crosses ${args.route[2 * k + 1]}, a pool this module refuses (fake coin, drained in 2023, or over a dead venue)`, "vault_mismatch");
|
|
404
416
|
const pool = index.get(swap);
|
|
405
|
-
if (!pool) return `step ${k + 1} crosses ${args.route[2 * k + 1]}, which is not in the pool allowlist
|
|
406
|
-
if (pools.has(swap)) return `the route crosses ${args.route[2 * k + 1]} twice
|
|
417
|
+
if (!pool) return noted(`step ${k + 1} crosses ${args.route[2 * k + 1]}, which is not in the pool allowlist`, "vault_mismatch");
|
|
418
|
+
if (pools.has(swap)) return noted(`the route crosses ${args.route[2 * k + 1]} twice`, "policy_refused");
|
|
407
419
|
pools.add(swap);
|
|
408
|
-
if (!pool.swapTypes.includes(type === 1n ? 1 : 2)) return `step ${k + 1} uses swap_type ${type}, which pool ${pool.name} does not allow
|
|
409
|
-
if (row[3] !== BigInt(pool.poolType)) return `step ${k + 1} names pool_type ${row[3]}, not pool ${pool.name}'s ${pool.poolType}
|
|
410
|
-
if (type === 2n && deployment.family === "lite4" && pool.poolType !== 10) return `step ${k + 1}: exchange_underlying is for stable-ng metapools on this router
|
|
411
|
-
if (type === 2n && !underlyingAllowed(pool, index)) return `step ${k + 1}: exchange_underlying on pool ${pool.name} needs its base pool in the allowlist
|
|
420
|
+
if (!pool.swapTypes.includes(type === 1n ? 1 : 2)) return noted(`step ${k + 1} uses swap_type ${type}, which pool ${pool.name} does not allow`, "policy_refused");
|
|
421
|
+
if (row[3] !== BigInt(pool.poolType)) return noted(`step ${k + 1} names pool_type ${row[3]}, not pool ${pool.name}'s ${pool.poolType}`, "policy_refused");
|
|
422
|
+
if (type === 2n && deployment.family === "lite4" && pool.poolType !== 10) return noted(`step ${k + 1}: exchange_underlying is for stable-ng metapools on this router`, "policy_refused");
|
|
423
|
+
if (type === 2n && !underlyingAllowed(pool, index)) return noted(`step ${k + 1}: exchange_underlying on pool ${pool.name} needs its base pool in the allowlist`, "policy_refused");
|
|
412
424
|
const list = type === 1n ? pool.coins : pool.underlying;
|
|
413
|
-
if (!list) return `step ${k + 1}: pool ${pool.name} lists no underlying coins
|
|
425
|
+
if (!list) return noted(`step ${k + 1}: pool ${pool.name} lists no underlying coins`, "policy_refused");
|
|
414
426
|
const i = row[0], j = row[1];
|
|
415
|
-
if (i >= BigInt(list.length) || j >= BigInt(list.length) || i === j) return `step ${k + 1}: coin indexes ${i}/${j} are not two coins of pool ${pool.name}
|
|
416
|
-
if (lc(list[Number(i.toString())]) !== a || lc(list[Number(j.toString())]) !== b) return `step ${k + 1}: pool ${pool.name}'s coins ${i}/${j} are not the hop's tokens
|
|
417
|
-
if (deployment.family === "ng5" && row[4] !== BigInt(list.length)) return `step ${k + 1} names ${row[4]} coins, not pool ${pool.name}'s ${list.length}
|
|
418
|
-
if (deployment.family === "lite4" && (a === eth || b === eth)) return `step ${k + 1}: this router does not pass the native coin to pools
|
|
419
|
-
if (STABLE_POOL_TYPES.has(pool.poolType) && (i > 127n || j > 127n)) return `step ${k + 1}: coin index out of range
|
|
427
|
+
if (i >= BigInt(list.length) || j >= BigInt(list.length) || i === j) return noted(`step ${k + 1}: coin indexes ${i}/${j} are not two coins of pool ${pool.name}`, "policy_refused");
|
|
428
|
+
if (lc(list[Number(i.toString())]) !== a || lc(list[Number(j.toString())]) !== b) return noted(`step ${k + 1}: pool ${pool.name}'s coins ${i}/${j} are not the hop's tokens`, "policy_refused");
|
|
429
|
+
if (deployment.family === "ng5" && row[4] !== BigInt(list.length)) return noted(`step ${k + 1} names ${row[4]} coins, not pool ${pool.name}'s ${list.length}`, "policy_refused");
|
|
430
|
+
if (deployment.family === "lite4" && (a === eth || b === eth)) return noted(`step ${k + 1}: this router does not pass the native coin to pools`, "policy_refused");
|
|
431
|
+
if (STABLE_POOL_TYPES.has(pool.poolType) && (i > 127n || j > 127n)) return noted(`step ${k + 1}: coin index out of range`, "policy_refused");
|
|
420
432
|
} else if (type === 8n) {
|
|
421
|
-
if (weth === zero) return "this chain's router has no wrapped native";
|
|
422
|
-
if (swap !== weth) return `step ${k + 1} wraps through ${args.route[2 * k + 1]}, not the pinned wrapped native
|
|
423
|
-
if (!(a === eth && b === weth || a === weth && b === eth)) return `step ${k + 1}: swap_type 8 is only native \u2194 the pinned wrapped native here
|
|
424
|
-
if (row.some((x, c) => c !== 2 && x !== 0n)) return `step ${k + 1}: a wrap carries no other swap params
|
|
425
|
-
if (++wraps > 1) return "the route wraps more than once";
|
|
433
|
+
if (weth === zero) return noted("this chain's router has no wrapped native", "policy_refused");
|
|
434
|
+
if (swap !== weth) return noted(`step ${k + 1} wraps through ${args.route[2 * k + 1]}, not the pinned wrapped native`, "vault_mismatch");
|
|
435
|
+
if (!(a === eth && b === weth || a === weth && b === eth)) return noted(`step ${k + 1}: swap_type 8 is only native \u2194 the pinned wrapped native here`, "policy_refused");
|
|
436
|
+
if (row.some((x, c) => c !== 2 && x !== 0n)) return noted(`step ${k + 1}: a wrap carries no other swap params`, "policy_refused");
|
|
437
|
+
if (++wraps > 1) return noted("the route wraps more than once", "policy_refused");
|
|
426
438
|
} else if (type === 9n) {
|
|
427
|
-
if (!v) return `swap_type 9 (ERC-4626) is not available on ${deployment.label}'s router ${deployment.version}
|
|
428
|
-
if (swap !== lc(v.vault)) return `step ${k + 1}: ERC-4626 hop through ${args.route[2 * k + 1]}, not the pinned vault
|
|
439
|
+
if (!v) return noted(`swap_type 9 (ERC-4626) is not available on ${deployment.label}'s router ${deployment.version}`, "policy_refused");
|
|
440
|
+
if (swap !== lc(v.vault)) return noted(`step ${k + 1}: ERC-4626 hop through ${args.route[2 * k + 1]}, not the pinned vault`, "vault_mismatch");
|
|
429
441
|
const deposit = row[0] === 0n && a === lc(v.asset) && b === lc(v.vault);
|
|
430
442
|
const redeem = row[0] === 1n && a === lc(v.vault) && b === lc(v.asset);
|
|
431
|
-
if (!deposit && !redeem) return `step ${k + 1}: the ERC-4626 hop is not a deposit of the vault's asset or a redeem of its shares
|
|
432
|
-
if (row.some((x, c) => c > 0 && c !== 2 && x !== 0n)) return `step ${k + 1}: an ERC-4626 hop carries no other swap params
|
|
433
|
-
if (++vaults > 1) return "the route crosses the vault more than once";
|
|
443
|
+
if (!deposit && !redeem) return noted(`step ${k + 1}: the ERC-4626 hop is not a deposit of the vault's asset or a redeem of its shares`, "policy_refused");
|
|
444
|
+
if (row.some((x, c) => c > 0 && c !== 2 && x !== 0n)) return noted(`step ${k + 1}: an ERC-4626 hop carries no other swap params`, "policy_refused");
|
|
445
|
+
if (++vaults > 1) return noted("the route crosses the vault more than once", "policy_refused");
|
|
434
446
|
} else {
|
|
435
|
-
return `step ${k + 1} uses swap_type ${type}, which this module never builds
|
|
447
|
+
return noted(`step ${k + 1} uses swap_type ${type}, which this module never builds`, "policy_refused");
|
|
436
448
|
}
|
|
437
449
|
}
|
|
438
|
-
if (pools.size > MAX_ROUTE_POOLS) return `the route crosses ${pools.size} pools, more than ${MAX_ROUTE_POOLS}
|
|
439
|
-
if (pools.size === 0 && vaults === 0) return "the route crosses no pool";
|
|
450
|
+
if (pools.size > MAX_ROUTE_POOLS) return noted(`the route crosses ${pools.size} pools, more than ${MAX_ROUTE_POOLS}`, "policy_refused");
|
|
451
|
+
if (pools.size === 0 && vaults === 0) return noted("the route crosses no pool", "policy_refused");
|
|
440
452
|
return null;
|
|
441
453
|
}
|
|
442
454
|
|
|
443
455
|
// src/provider.ts
|
|
444
456
|
var import_viem4 = require("viem");
|
|
445
457
|
var import_util5 = require("@anywalletkit/protocol-swap2-core/util");
|
|
458
|
+
var import_errors4 = require("@anywalletkit/protocol-swap2-core/errors");
|
|
446
459
|
|
|
447
460
|
// src/activity.ts
|
|
448
461
|
var import_activity = require("@anywalletkit/protocol-swap2-core/activity");
|
|
@@ -642,6 +655,7 @@ var CURVE_POOLS = Object.freeze({
|
|
|
642
655
|
});
|
|
643
656
|
|
|
644
657
|
// src/rpc.ts
|
|
658
|
+
var import_errors2 = require("@anywalletkit/protocol-swap2-core/errors");
|
|
645
659
|
var import_util2 = require("@anywalletkit/protocol-swap2-core/util");
|
|
646
660
|
var RPC_BATCH_MAX = 10;
|
|
647
661
|
var RPC_RATE_LIMIT_PAUSE_MS = 1e3;
|
|
@@ -667,18 +681,18 @@ function rpcClient(rpcUrls) {
|
|
|
667
681
|
body: JSON.stringify(calls.map((c, id) => ({ jsonrpc: "2.0", id, ...c }))),
|
|
668
682
|
signal: signal ?? (0, import_util2.timeoutSignal)(12e3)
|
|
669
683
|
});
|
|
670
|
-
if (!res.ok) throw Object.assign(new Error(`HTTP ${res.status}`), { limited: res.status === 429 });
|
|
684
|
+
if (!res.ok) throw (0, import_errors2.withReason)(Object.assign(new Error(`HTTP ${res.status}`), { limited: res.status === 429 }), (0, import_errors2.httpRefusal)(res.status, res.headers?.get?.("retry-after")) ?? { reason: "upstream_unavailable", httpStatus: res.status });
|
|
671
685
|
const body = await res.json();
|
|
672
|
-
if (!Array.isArray(body)) throw Object.assign(new Error(body.error?.message ?? "batch refused"), { limited: isRateLimit(body.error) });
|
|
686
|
+
if (!Array.isArray(body)) throw (0, import_errors2.withReason)(Object.assign(new Error(body.error?.message ?? "batch refused"), { limited: isRateLimit(body.error) }), isRateLimit(body.error) ? "rate_limited" : "upstream_unavailable");
|
|
673
687
|
const out = calls.map(() => null);
|
|
674
688
|
const answered = /* @__PURE__ */ new Set();
|
|
675
689
|
for (const r of body) {
|
|
676
690
|
if (typeof r.id !== "number" || r.id < 0 || r.id >= out.length) continue;
|
|
677
|
-
if (r.error !== void 0 && r.error !== null && !isExecutionError(r.error)) throw Object.assign(new Error(errorText(r.error)), { limited: isRateLimit(r.error) });
|
|
691
|
+
if (r.error !== void 0 && r.error !== null && !isExecutionError(r.error)) throw (0, import_errors2.withReason)(Object.assign(new Error(errorText(r.error)), { limited: isRateLimit(r.error) }), isRateLimit(r.error) ? "rate_limited" : "upstream_unavailable");
|
|
678
692
|
answered.add(r.id);
|
|
679
693
|
if (r.error === void 0 || r.error === null) out[r.id] = r.result ?? null;
|
|
680
694
|
}
|
|
681
|
-
if (answered.size !== calls.length) throw
|
|
695
|
+
if (answered.size !== calls.length) throw (0, import_errors2.refusal)("upstream_unavailable", `answered ${answered.size} of ${calls.length} calls`);
|
|
682
696
|
return out;
|
|
683
697
|
}
|
|
684
698
|
async function batch(chainId, calls, signal) {
|
|
@@ -696,7 +710,9 @@ function rpcClient(rpcUrls) {
|
|
|
696
710
|
}
|
|
697
711
|
}
|
|
698
712
|
}
|
|
699
|
-
|
|
713
|
+
const error = new Error(`curve: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);
|
|
714
|
+
if (lastErr === void 0 || signal?.aborted) throw error;
|
|
715
|
+
throw (0, import_errors2.withReason)(error, (0, import_errors2.refusalOf)(lastErr) ?? "upstream_unavailable");
|
|
700
716
|
}
|
|
701
717
|
return async function rpc(chainId, calls, signal) {
|
|
702
718
|
if (calls.length <= RPC_BATCH_MAX) return batch(chainId, calls, signal);
|
|
@@ -756,6 +772,7 @@ function curveIntentChain(intentId) {
|
|
|
756
772
|
var import_viem3 = require("viem");
|
|
757
773
|
var import_util4 = require("@anywalletkit/protocol-swap2-core/util");
|
|
758
774
|
var import_validate = require("@anywalletkit/protocol-swap2-core/validate");
|
|
775
|
+
var import_errors3 = require("@anywalletkit/protocol-swap2-core/errors");
|
|
759
776
|
var lc2 = (a) => a.toLowerCase();
|
|
760
777
|
var isAddress = (a) => /^0x[0-9a-fA-F]{40}$/.test(a);
|
|
761
778
|
var own = (o, k) => Object.prototype.hasOwnProperty.call(o, k) ? o[k] : void 0;
|
|
@@ -765,19 +782,19 @@ function curveQuoteCheck(tables = {}) {
|
|
|
765
782
|
return function verify(params, quote) {
|
|
766
783
|
const chainId = chainIdOf(params.sourceChain);
|
|
767
784
|
const d2 = deploymentOf(deployments, chainId);
|
|
768
|
-
if (!d2 || params.destChain !== params.sourceChain) return "not a same-chain swap on a pinned Curve router";
|
|
785
|
+
if (!d2 || params.destChain !== params.sourceChain) return noted("not a same-chain swap on a pinned Curve router", "unsupported_pair");
|
|
769
786
|
const tx = quote.txRequest;
|
|
770
|
-
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return "the quote carries no router call";
|
|
771
|
-
if (!isAddress(tx.to) || lc2(tx.to) !== lc2(d2.router)) return `the call targets ${tx.to}, not the Curve router
|
|
772
|
-
if (tx.chainId !== void 0 && tx.chainId !== chainId) return `the call is for chain ${tx.chainId}
|
|
773
|
-
if (curveIntentChain(quote.intentId) !== chainId) return `the quote names ${String(quote.intentId).slice(0, 40)}, not a curve:${chainId} swap
|
|
787
|
+
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return noted("the quote carries no router call", "policy_refused");
|
|
788
|
+
if (!isAddress(tx.to) || lc2(tx.to) !== lc2(d2.router)) return noted(`the call targets ${tx.to}, not the Curve router`, "vault_mismatch");
|
|
789
|
+
if (tx.chainId !== void 0 && tx.chainId !== chainId) return noted(`the call is for chain ${tx.chainId}`, "policy_refused");
|
|
790
|
+
if (curveIntentChain(quote.intentId) !== chainId) return noted(`the quote names ${String(quote.intentId).slice(0, 40)}, not a curve:${chainId} swap`, "policy_refused");
|
|
774
791
|
const src = (0, import_util4.sourceAssetOf)(params);
|
|
775
|
-
if (!src) return `unknown source token ${params.sourceToken}
|
|
792
|
+
if (!src) return noted(`unknown source token ${params.sourceToken}`, "unsupported_pair");
|
|
776
793
|
const nativeIn = !src.contract;
|
|
777
794
|
const nativeOut = /^0x0+$/.test(params.destToken);
|
|
778
|
-
if (!nativeOut && !isAddress(params.destToken)) return "destination token must be an EVM address";
|
|
779
|
-
if (!isAddress(params.destAddress)) return "recipient must be an EVM address";
|
|
780
|
-
if (!nativeIn && lc2(src.contract) === lc2(d2.eth) || !nativeOut && lc2(params.destToken) === lc2(d2.eth)) return "the router's native sentinel is not a token";
|
|
795
|
+
if (!nativeOut && !isAddress(params.destToken)) return noted("destination token must be an EVM address", "unsupported_pair");
|
|
796
|
+
if (!isAddress(params.destAddress)) return noted("recipient must be an EVM address", "recipient_mismatch");
|
|
797
|
+
if (!nativeIn && lc2(src.contract) === lc2(d2.eth) || !nativeOut && lc2(params.destToken) === lc2(d2.eth)) return noted("the router's native sentinel is not a token", "unsupported_pair");
|
|
781
798
|
const tokenIn = nativeIn ? d2.eth : src.contract;
|
|
782
799
|
const tokenOut = nativeOut ? d2.eth : params.destToken;
|
|
783
800
|
let amountIn, minOut, value;
|
|
@@ -786,20 +803,20 @@ function curveQuoteCheck(tables = {}) {
|
|
|
786
803
|
minOut = BigInt(quote.minDestAmount);
|
|
787
804
|
value = BigInt(tx.value ?? "0");
|
|
788
805
|
} catch {
|
|
789
|
-
return "the request does not name amounts";
|
|
806
|
+
return noted("the request does not name amounts", "policy_refused");
|
|
790
807
|
}
|
|
791
808
|
if (nativeIn ? value !== amountIn || tx.approvalAddress !== void 0 : value !== 0n || !tx.approvalAddress || !isAddress(tx.approvalAddress) || lc2(tx.approvalAddress) !== lc2(d2.router)) {
|
|
792
|
-
return nativeIn ? "a native input is paid as exactly the input in value, with no approval" : "a token input attaches no value and approves exactly the Curve router";
|
|
809
|
+
return noted(nativeIn ? "a native input is paid as exactly the input in value, with no approval" : "a token input attaches no value and approves exactly the Curve router", "policy_refused");
|
|
793
810
|
}
|
|
794
811
|
const call = decodeExchange(d2.family, tx.data);
|
|
795
|
-
if (!call) return "the router call is not exchange(route, params, amount, min, receiver)";
|
|
796
|
-
if (call.selector !== EXCHANGE_SELECTOR[d2.family]) return `selector ${call.selector} is not the explicit-receiver exchange ${EXCHANGE_SELECTOR[d2.family]}
|
|
797
|
-
if (!call.receiver || lc2(call.receiver) !== lc2(params.destAddress)) return `the swap pays ${call.receiver ?? "the sender"}, not the recipient
|
|
798
|
-
if (call.pools && call.pools.some((p) => lc2(p) !== lc2(ZERO_ADDRESS))) return "the call names zap pools this module never uses";
|
|
799
|
-
if (call.amount !== amountIn) return `the swap sells ${call.amount}, not the ${amountIn} input
|
|
800
|
-
if (call.minDy <= 0n) return "the swap has no minimum (min_dy 0)";
|
|
801
|
-
if (call.minDy !== minOut) return `the swap's minimum ${call.minDy} is not the quote's ${minOut}
|
|
802
|
-
if (quote.providerData?.minOut !== void 0 && quote.providerData.minOut !== minOut.toString()) return "the quote's facts disagree on the minimum";
|
|
812
|
+
if (!call) return noted("the router call is not exchange(route, params, amount, min, receiver)", "policy_refused");
|
|
813
|
+
if (call.selector !== EXCHANGE_SELECTOR[d2.family]) return noted(`selector ${call.selector} is not the explicit-receiver exchange ${EXCHANGE_SELECTOR[d2.family]}`, "policy_refused");
|
|
814
|
+
if (!call.receiver || lc2(call.receiver) !== lc2(params.destAddress)) return noted(`the swap pays ${call.receiver ?? "the sender"}, not the recipient`, "recipient_mismatch");
|
|
815
|
+
if (call.pools && call.pools.some((p) => lc2(p) !== lc2(ZERO_ADDRESS))) return noted("the call names zap pools this module never uses", "policy_refused");
|
|
816
|
+
if (call.amount !== amountIn) return noted(`the swap sells ${call.amount}, not the ${amountIn} input`, "policy_refused");
|
|
817
|
+
if (call.minDy <= 0n) return noted("the swap has no minimum (min_dy 0)", "price_check_failed");
|
|
818
|
+
if (call.minDy !== minOut) return noted(`the swap's minimum ${call.minDy} is not the quote's ${minOut}`, "price_check_failed");
|
|
819
|
+
if (quote.providerData?.minOut !== void 0 && quote.providerData.minOut !== minOut.toString()) return noted("the quote's facts disagree on the minimum", "price_check_failed");
|
|
803
820
|
return checkRoute(chainId, d2, own(pools, chainId), call, tokenIn, tokenOut);
|
|
804
821
|
};
|
|
805
822
|
}
|
|
@@ -807,7 +824,9 @@ var curveVerifyQuote = curveQuoteCheck();
|
|
|
807
824
|
var curvePins = Object.freeze({
|
|
808
825
|
callTargets: (chain) => routerFor(CURVE_DEPLOYMENTS, chain),
|
|
809
826
|
spenders: (chain) => routerFor(CURVE_DEPLOYMENTS, chain),
|
|
810
|
-
verifyQuote: curveVerifyQuote
|
|
827
|
+
verifyQuote: curveVerifyQuote,
|
|
828
|
+
// The reason of each text verifyQuote returned (remoteProvider puts it on its refusal).
|
|
829
|
+
reasonOf: notes.reasonOf
|
|
811
830
|
});
|
|
812
831
|
function routerFor(deployments, chain) {
|
|
813
832
|
const d2 = deploymentOf(deployments, chainIdOf(chain));
|
|
@@ -824,21 +843,21 @@ function curveOnChain(opts) {
|
|
|
824
843
|
if (!p) {
|
|
825
844
|
const d2 = deploymentOf(deployments, chainId);
|
|
826
845
|
p = (async () => {
|
|
827
|
-
if (!d2) throw
|
|
846
|
+
if (!d2) throw (0, import_errors3.refusal)("unsupported_pair", `curve: no pinned router on chain ${chainId}`);
|
|
828
847
|
const [code, version, listed] = await rpc(chainId, [
|
|
829
848
|
{ method: "eth_getCode", params: [d2.router, "latest"] },
|
|
830
849
|
ethCall(d2.router, (0, import_viem3.encodeFunctionData)({ abi: VERSION_ABI, functionName: "version" })),
|
|
831
850
|
ethCall(d2.addressProvider, (0, import_viem3.encodeFunctionData)({ abi: ADDRESS_PROVIDER_ABI, functionName: "get_address", args: [2n] }))
|
|
832
851
|
]);
|
|
833
852
|
if (typeof code !== "string" || code.length <= 2 || lc2((0, import_viem3.keccak256)(code)) !== lc2(d2.codeHash)) {
|
|
834
|
-
throw
|
|
853
|
+
throw (0, import_errors3.refusal)("vault_mismatch", `curve: the router on chain ${chainId} is not the pinned code (code hash mismatch) \u2014 refusing`);
|
|
835
854
|
}
|
|
836
855
|
let v = "";
|
|
837
856
|
try {
|
|
838
857
|
v = typeof version === "string" ? (0, import_viem3.decodeFunctionResult)({ abi: VERSION_ABI, functionName: "version", data: version }) : "";
|
|
839
858
|
} catch {
|
|
840
859
|
}
|
|
841
|
-
if (v !== d2.version) throw
|
|
860
|
+
if (v !== d2.version) throw (0, import_errors3.refusal)("vault_mismatch", `curve: the router on chain ${chainId} reports version ${v || "none"}, not ${d2.version} \u2014 refusing`);
|
|
842
861
|
const ap = wordAddress(listed);
|
|
843
862
|
if (ap && ap !== lc2(d2.addressProviderRouter) && ap !== lc2(d2.router)) {
|
|
844
863
|
warn(`curve: the AddressProvider on ${d2.label} lists router ${ap} (id 2); this module keeps the pinned ${d2.router}`);
|
|
@@ -856,17 +875,17 @@ function curveOnChain(opts) {
|
|
|
856
875
|
async function inspectSealed(quote, tx, probe) {
|
|
857
876
|
const chainId = curveIntentChain(quote.intentId);
|
|
858
877
|
const d2 = chainId === null ? void 0 : deploymentOf(deployments, chainId);
|
|
859
|
-
if (chainId === null || !d2) return "the quote is not a Curve swap on a pinned chain";
|
|
878
|
+
if (chainId === null || !d2) return noted("the quote is not a Curve swap on a pinned chain", "policy_refused");
|
|
860
879
|
const quoted = quote.txRequest;
|
|
861
|
-
if (!quoted?.data || !quoted.to || !tx.data) return "the quote or the transaction carries no router call";
|
|
862
|
-
if (tx.data.length !== quoted.data.length || lc2(tx.data) !== lc2(quoted.data)) return "the transaction is not the quoted router call";
|
|
863
|
-
if (!isAddress(tx.to) || lc2(tx.to) !== lc2(d2.router) || lc2(quoted.to) !== lc2(d2.router)) return `the transaction calls ${tx.to}, not the Curve router
|
|
864
|
-
if ((tx.value ?? "0") !== (quoted.value ?? "0")) return "the transaction's value is not the quote's";
|
|
865
|
-
if (tx.chainId !== void 0 && tx.chainId !== chainId || quoted.chainId !== void 0 && quoted.chainId !== chainId) return `the transaction is not for chain ${chainId}
|
|
866
|
-
if ((tx.approvalAddress ?? "").toLowerCase() !== (quoted.approvalAddress ?? "").toLowerCase()) return "the transaction's approval is not the quote's";
|
|
880
|
+
if (!quoted?.data || !quoted.to || !tx.data) return noted("the quote or the transaction carries no router call", "policy_refused");
|
|
881
|
+
if (tx.data.length !== quoted.data.length || lc2(tx.data) !== lc2(quoted.data)) return noted("the transaction is not the quoted router call", "policy_refused");
|
|
882
|
+
if (!isAddress(tx.to) || lc2(tx.to) !== lc2(d2.router) || lc2(quoted.to) !== lc2(d2.router)) return noted(`the transaction calls ${tx.to}, not the Curve router`, "vault_mismatch");
|
|
883
|
+
if ((tx.value ?? "0") !== (quoted.value ?? "0")) return noted("the transaction's value is not the quote's", "policy_refused");
|
|
884
|
+
if (tx.chainId !== void 0 && tx.chainId !== chainId || quoted.chainId !== void 0 && quoted.chainId !== chainId) return noted(`the transaction is not for chain ${chainId}`, "policy_refused");
|
|
885
|
+
if ((tx.approvalAddress ?? "").toLowerCase() !== (quoted.approvalAddress ?? "").toLowerCase()) return noted("the transaction's approval is not the quote's", "vault_mismatch");
|
|
867
886
|
const call = decodeExchange(d2.family, quoted.data);
|
|
868
|
-
if (!call || call.selector !== EXCHANGE_SELECTOR[d2.family]) return "the quoted call is not the explicit-receiver exchange";
|
|
869
|
-
if (call.minDy <= 0n) return "the swap has no minimum (min_dy 0)";
|
|
887
|
+
if (!call || call.selector !== EXCHANGE_SELECTOR[d2.family]) return noted("the quoted call is not the explicit-receiver exchange", "policy_refused");
|
|
888
|
+
if (call.minDy <= 0n) return noted("the swap has no minimum (min_dy 0)", "price_check_failed");
|
|
870
889
|
const last = lastToken(call);
|
|
871
890
|
const reason = checkRoute(chainId, d2, own(pools, chainId), call, call.route[0], last);
|
|
872
891
|
if (reason) return reason;
|
|
@@ -882,8 +901,8 @@ function curveOnChain(opts) {
|
|
|
882
901
|
const poolReason = await poolsReason(chainId, hops, res.slice(1, 1 + reads.length));
|
|
883
902
|
if (poolReason) return poolReason;
|
|
884
903
|
const out = wordUint(res[0]);
|
|
885
|
-
if (out === null) return "the router no longer quotes this route";
|
|
886
|
-
if (out < call.minDy) return `price moved \u2014 the pools now pay ${out}, under your minimum ${call.minDy}
|
|
904
|
+
if (out === null) return noted("the router no longer quotes this route", "simulation_failed");
|
|
905
|
+
if (out < call.minDy) return noted(`price moved \u2014 the pools now pay ${out}, under your minimum ${call.minDy}`, "price_check_failed");
|
|
887
906
|
return { out, probeOut: probe && probeIn > 0n ? wordUint(res[probeAt]) : null, amount: call.amount, minDy: call.minDy };
|
|
888
907
|
}
|
|
889
908
|
function poolCalls(list) {
|
|
@@ -897,19 +916,19 @@ function curveOnChain(opts) {
|
|
|
897
916
|
const retry = [];
|
|
898
917
|
for (const pool of list) {
|
|
899
918
|
const code = res[at++];
|
|
900
|
-
if (typeof code !== "string") return `could not read pool ${pool.name} (${pool.address}) over RPC
|
|
901
|
-
if (code.length <= 2 || lc2((0, import_viem3.keccak256)(code)) !== lc2(pool.codeHash)) return `pool ${pool.name} (${pool.address}) is not the pinned code
|
|
919
|
+
if (typeof code !== "string") return noted(`could not read pool ${pool.name} (${pool.address}) over RPC`, "upstream_unavailable");
|
|
920
|
+
if (code.length <= 2 || lc2((0, import_viem3.keccak256)(code)) !== lc2(pool.codeHash)) return noted(`pool ${pool.name} (${pool.address}) is not the pinned code`, "vault_mismatch");
|
|
902
921
|
for (let k = 0; k < pool.coins.length; k++) {
|
|
903
922
|
const coin = wordAddress(res[at++]);
|
|
904
923
|
if (coin === null) retry.push({ pool, k });
|
|
905
|
-
else if (coin !== lc2(pool.coins[k])) return `pool ${pool.name} now reports coin ${k} = ${coin}, not the pinned ${pool.coins[k]}
|
|
924
|
+
else if (coin !== lc2(pool.coins[k])) return noted(`pool ${pool.name} now reports coin ${k} = ${coin}, not the pinned ${pool.coins[k]}`, "vault_mismatch");
|
|
906
925
|
}
|
|
907
926
|
}
|
|
908
927
|
if (retry.length) {
|
|
909
928
|
const again = await rpc(chainId, retry.map(({ pool, k }) => ethCall(pool.address, `${COINS_INT}${k.toString(16).padStart(64, "0")}`)));
|
|
910
929
|
for (const [n, { pool, k }] of retry.entries()) {
|
|
911
930
|
const coin = wordAddress(again[n]);
|
|
912
|
-
if (coin !== lc2(pool.coins[k])) return `pool ${pool.name} does not report its pinned coin ${k}
|
|
931
|
+
if (coin !== lc2(pool.coins[k])) return noted(`pool ${pool.name} does not report its pinned coin ${k}`, "vault_mismatch");
|
|
913
932
|
}
|
|
914
933
|
}
|
|
915
934
|
return null;
|
|
@@ -935,8 +954,10 @@ function curveRemotePins(opts) {
|
|
|
935
954
|
callTargets: (c) => routerFor(deployments, c),
|
|
936
955
|
spenders: (c) => routerFor(deployments, c),
|
|
937
956
|
verifyQuote,
|
|
957
|
+
// The reason of each text verifyQuote / verifyBuild returned (remoteProvider puts it on its refusal).
|
|
958
|
+
reasonOf: notes.reasonOf,
|
|
938
959
|
async verifyBuild(quote, tx, params) {
|
|
939
|
-
if (!params) return "the request this quote answered is unknown";
|
|
960
|
+
if (!params) return noted("the request this quote answered is unknown", "policy_refused");
|
|
940
961
|
const reason = verifyQuote(params, quote);
|
|
941
962
|
if (reason) return reason;
|
|
942
963
|
try {
|
|
@@ -948,15 +969,15 @@ function curveRemotePins(opts) {
|
|
|
948
969
|
try {
|
|
949
970
|
dest = BigInt(quote.destAmount);
|
|
950
971
|
} catch {
|
|
951
|
-
return "the quote names no output";
|
|
972
|
+
return noted("the quote names no output", "upstream_unavailable");
|
|
952
973
|
}
|
|
953
974
|
const bps = params.slippageBps ?? fixedSlippage ?? Math.min(9999, curveAutoSlippageBps(params, curveImpactBps(amount, out, probeOut)) + CURVE_AUTO_SLIPPAGE_DRIFT_BPS);
|
|
954
|
-
if ((0, import_validate.slippageFloor)(dest, bps) > out) return `the quote promises ${dest}, more than ${bps} bps above the ${out} the pools pay now
|
|
975
|
+
if ((0, import_validate.slippageFloor)(dest, bps) > out) return noted(`the quote promises ${dest}, more than ${bps} bps above the ${out} the pools pay now`, "price_check_failed");
|
|
955
976
|
const fresh = dest < out ? dest : out;
|
|
956
|
-
if (minDy < (0, import_validate.slippageFloor)(fresh, bps)) return `the swap's minimum ${minDy} is more than ${bps} bps under the ${fresh} the pools pay now
|
|
977
|
+
if (minDy < (0, import_validate.slippageFloor)(fresh, bps)) return noted(`the swap's minimum ${minDy} is more than ${bps} bps under the ${fresh} the pools pay now`, "price_check_failed");
|
|
957
978
|
return null;
|
|
958
979
|
} catch (e) {
|
|
959
|
-
return e instanceof Error ? e.message.replace(/^curve: /, "") : String(e);
|
|
980
|
+
return noted(e instanceof Error ? e.message.replace(/^curve: /, "") : String(e), (0, import_errors3.refusalOf)(e));
|
|
960
981
|
}
|
|
961
982
|
}
|
|
962
983
|
});
|
|
@@ -994,46 +1015,47 @@ function curveProvider(config) {
|
|
|
994
1015
|
return from.chain === to.chain && chainIdOf2(from.chain) !== null;
|
|
995
1016
|
},
|
|
996
1017
|
async getQuote(params, signal) {
|
|
997
|
-
const refuse = (why) => {
|
|
998
|
-
params.onRefusal?.(`curve: ${why}`);
|
|
1018
|
+
const refuse = (why, info) => {
|
|
1019
|
+
if (info === void 0) params.onRefusal?.(`curve: ${why}`);
|
|
1020
|
+
else params.onRefusal?.(`curve: ${why}`, typeof info === "string" ? { reason: info } : info);
|
|
999
1021
|
return null;
|
|
1000
1022
|
};
|
|
1001
|
-
if (params.flex) return refuse("amount-flexible deposits are not supported");
|
|
1002
|
-
if (params.sourceChain !== params.destChain) return refuse("same-chain swaps only");
|
|
1023
|
+
if (params.flex) return refuse("amount-flexible deposits are not supported", "unsupported_pair");
|
|
1024
|
+
if (params.sourceChain !== params.destChain) return refuse("same-chain swaps only", "unsupported_pair");
|
|
1003
1025
|
const chainId = chainIdOf2(params.sourceChain);
|
|
1004
|
-
if (chainId === null) return refuse(`no Curve router, pool allowlist or RPC for ${params.sourceChain}
|
|
1026
|
+
if (chainId === null) return refuse(`no Curve router, pool allowlist or RPC for ${params.sourceChain}`, "unsupported_pair");
|
|
1005
1027
|
const d2 = deploymentOf(deployments, chainId);
|
|
1006
1028
|
const src = (0, import_util5.sourceAssetOf)(params);
|
|
1007
|
-
if (!src) return refuse(`unknown source token ${params.sourceToken}
|
|
1029
|
+
if (!src) return refuse(`unknown source token ${params.sourceToken}`, "unsupported_pair");
|
|
1008
1030
|
const nativeIn = !src.contract;
|
|
1009
1031
|
const nativeOut = /^0x0+$/.test(params.destToken);
|
|
1010
|
-
if (!nativeOut && !/^0x[0-9a-fA-F]{40}$/.test(params.destToken)) return refuse("destination token must be an EVM address");
|
|
1011
|
-
if (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress)) return refuse("recipient must be an EVM address");
|
|
1032
|
+
if (!nativeOut && !/^0x[0-9a-fA-F]{40}$/.test(params.destToken)) return refuse("destination token must be an EVM address", "unsupported_pair");
|
|
1033
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress)) return refuse("recipient must be an EVM address", "recipient_mismatch");
|
|
1012
1034
|
let amountIn;
|
|
1013
1035
|
try {
|
|
1014
1036
|
amountIn = BigInt(params.amountIn);
|
|
1015
1037
|
} catch {
|
|
1016
1038
|
return refuse("amount is not an integer");
|
|
1017
1039
|
}
|
|
1018
|
-
if (amountIn <= 0n) return refuse("amount must be positive");
|
|
1040
|
+
if (amountIn <= 0n) return refuse("amount must be positive", "amount_too_small");
|
|
1019
1041
|
if (params.slippageBps !== void 0 && (!Number.isInteger(params.slippageBps) || params.slippageBps < 0 || params.slippageBps >= 1e4)) return refuse("slippage must be 0..9999 bps");
|
|
1020
|
-
if (!nativeIn && src.contract.toLowerCase() === d2.eth.toLowerCase()) return refuse("the native coin is named by the catalog, not by the router's 0xEeee sentinel");
|
|
1021
|
-
if (!nativeOut && params.destToken.toLowerCase() === d2.eth.toLowerCase()) return refuse("name a native output with the zero address, not the router's 0xEeee sentinel");
|
|
1042
|
+
if (!nativeIn && src.contract.toLowerCase() === d2.eth.toLowerCase()) return refuse("the native coin is named by the catalog, not by the router's 0xEeee sentinel", "unsupported_pair");
|
|
1043
|
+
if (!nativeOut && params.destToken.toLowerCase() === d2.eth.toLowerCase()) return refuse("name a native output with the zero address, not the router's 0xEeee sentinel", "unsupported_pair");
|
|
1022
1044
|
const tokenIn = (0, import_viem4.getAddress)(nativeIn ? d2.eth : src.contract);
|
|
1023
1045
|
const tokenOut = (0, import_viem4.getAddress)(nativeOut ? d2.eth : params.destToken);
|
|
1024
|
-
if (tokenIn === tokenOut) return refuse("same token in and out");
|
|
1046
|
+
if (tokenIn === tokenOut) return refuse("same token in and out", "unsupported_pair");
|
|
1025
1047
|
const wrapPair = [(0, import_viem4.getAddress)(d2.eth), (0, import_viem4.getAddress)(d2.weth)];
|
|
1026
|
-
if (wrapPair.includes(tokenIn) && wrapPair.includes(tokenOut)) return refuse("that is a wrap/unwrap, not a swap");
|
|
1048
|
+
if (wrapPair.includes(tokenIn) && wrapPair.includes(tokenOut)) return refuse("that is a wrap/unwrap, not a swap", "unsupported_pair");
|
|
1027
1049
|
try {
|
|
1028
1050
|
await chain.verifyDeployment(chainId);
|
|
1029
1051
|
const { routes, truncated } = findRoutes(chainId, d2, tableOf(chainId), tokenIn, tokenOut);
|
|
1030
|
-
if (!routes.length) return refuse("no allowlisted Curve pool route for this pair");
|
|
1052
|
+
if (!routes.length) return refuse("no allowlisted Curve pool route for this pair", "no_route");
|
|
1031
1053
|
const outs = await price(chainId, d2, routes, amountIn, signal);
|
|
1032
1054
|
let best = null;
|
|
1033
1055
|
outs.forEach((out2, i) => {
|
|
1034
1056
|
if (out2 !== null && out2 > 0n && (!best || out2 > best.out)) best = { route: routes[i], out: out2 };
|
|
1035
1057
|
});
|
|
1036
|
-
if (!best) return refuse("no allowlisted Curve pool quotes this pair and amount");
|
|
1058
|
+
if (!best) return refuse("no allowlisted Curve pool quotes this pair and amount", "no_route");
|
|
1037
1059
|
const { route, out } = best;
|
|
1038
1060
|
let priceImpactBps;
|
|
1039
1061
|
const probeIn = amountIn / 1000n;
|
|
@@ -1046,9 +1068,9 @@ function curveProvider(config) {
|
|
|
1046
1068
|
}
|
|
1047
1069
|
const bps = params.slippageBps ?? fixedSlippage ?? curveAutoSlippageBps(params, priceImpactBps);
|
|
1048
1070
|
const minOut = out * BigInt(1e4 - bps) / 10000n;
|
|
1049
|
-
if (minOut <= 0n) return refuse("the minimum rounds to zero for this amount");
|
|
1071
|
+
if (minOut <= 0n) return refuse("the minimum rounds to zero for this amount", "amount_too_small");
|
|
1050
1072
|
if (params.minAmountOut !== void 0 && minOut < BigInt(params.minAmountOut)) {
|
|
1051
|
-
return refuse(`floor breach (min=${minOut} < floor=${params.minAmountOut})
|
|
1073
|
+
return refuse(`floor breach (min=${minOut} < floor=${params.minAmountOut})`, "price_check_failed");
|
|
1052
1074
|
}
|
|
1053
1075
|
const args = routeArgs(d2.family, route);
|
|
1054
1076
|
const recipient = (0, import_viem4.getAddress)(params.destAddress);
|
|
@@ -1090,10 +1112,10 @@ function curveProvider(config) {
|
|
|
1090
1112
|
}
|
|
1091
1113
|
};
|
|
1092
1114
|
const why = selfCheck(params, quote);
|
|
1093
|
-
if (why) return refuse(`built a call its own check refuses (${why})
|
|
1115
|
+
if (why) return refuse(`built a call its own check refuses (${why})`, notes.reasonOf(why) ?? "policy_refused");
|
|
1094
1116
|
return quote;
|
|
1095
1117
|
} catch (e) {
|
|
1096
|
-
return refuse(e instanceof Error ? e.message.replace(/^curve: /, "") : String(e));
|
|
1118
|
+
return refuse(e instanceof Error ? e.message.replace(/^curve: /, "") : String(e), (0, import_errors4.refusalOf)(e));
|
|
1097
1119
|
}
|
|
1098
1120
|
},
|
|
1099
1121
|
/**
|
|
@@ -1103,11 +1125,11 @@ function curveProvider(config) {
|
|
|
1103
1125
|
*/
|
|
1104
1126
|
async preflightDeposit(quote, tx) {
|
|
1105
1127
|
const reason = await chain.checkSealed(quote, tx);
|
|
1106
|
-
if (reason) throw new Error(`curve: ${reason}. Nothing was sent; refresh the quote.`);
|
|
1128
|
+
if (reason) throw tagged(new Error(`curve: ${reason}. Nothing was sent; refresh the quote.`), notes.reasonOf(reason));
|
|
1107
1129
|
},
|
|
1108
1130
|
async buildDeposit(quote) {
|
|
1109
1131
|
const tx = quote.txRequest;
|
|
1110
|
-
if (!tx?.to || !tx.data) throw
|
|
1132
|
+
if (!tx?.to || !tx.data) throw (0, import_errors4.refusal)("policy_refused", "swap2: Curve quote has no transaction request");
|
|
1111
1133
|
return {
|
|
1112
1134
|
chain: "",
|
|
1113
1135
|
to: tx.to,
|