@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CURVE_POOLS,
|
|
3
3
|
curveProvider
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NW2OLRIK.js";
|
|
5
5
|
import {
|
|
6
6
|
CURVE_DEPLOYMENTS,
|
|
7
7
|
deploymentOf
|
|
@@ -35,4 +35,4 @@ var CurveSwap2Protocol = class extends SingleProviderSwap2 {
|
|
|
35
35
|
export {
|
|
36
36
|
CurveSwap2Protocol
|
|
37
37
|
};
|
|
38
|
-
//# sourceMappingURL=chunk-
|
|
38
|
+
//# sourceMappingURL=chunk-7AXQMAHJ.js.map
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
// src/provider.ts
|
|
21
21
|
import { getAddress as getAddress2 } from "viem";
|
|
22
22
|
import { evmRef, isEvm, sourceAssetOf as sourceAssetOf3 } from "@anywalletkit/protocol-swap2-core/util";
|
|
23
|
+
import { refusal as refusal3, refusalOf as refusalOf3 } from "@anywalletkit/protocol-swap2-core/errors";
|
|
23
24
|
|
|
24
25
|
// src/pools/1.ts
|
|
25
26
|
var POOLS_1 = {
|
|
@@ -179,6 +180,18 @@ var CURVE_POOLS = Object.freeze({
|
|
|
179
180
|
// src/routes.ts
|
|
180
181
|
import { getAddress } from "viem";
|
|
181
182
|
import { ccAssetByToken } from "@anywalletkit/swap2-assets";
|
|
183
|
+
|
|
184
|
+
// src/reasons.ts
|
|
185
|
+
import { refusalNotes, withReason } from "@anywalletkit/protocol-swap2-core/errors";
|
|
186
|
+
var notes = refusalNotes(256);
|
|
187
|
+
function noted(text, info) {
|
|
188
|
+
return info === void 0 ? text : notes.note(text, info);
|
|
189
|
+
}
|
|
190
|
+
function tagged(error, info) {
|
|
191
|
+
return info === void 0 ? error : withReason(error, info);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// src/routes.ts
|
|
182
195
|
var MAX_QUOTE_CANDIDATES = 30;
|
|
183
196
|
var MAX_EXPLORED = 2e4;
|
|
184
197
|
var lc = (a) => a.toLowerCase();
|
|
@@ -329,7 +342,7 @@ function routePools(args) {
|
|
|
329
342
|
}
|
|
330
343
|
function checkRoute(chainId, deployment, table, args, tokenIn, tokenOut) {
|
|
331
344
|
const cols = deployment.family === "ng5" ? 5 : 4;
|
|
332
|
-
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]
|
|
345
|
+
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");
|
|
333
346
|
const index = poolIndex(chainId, deployment, table);
|
|
334
347
|
const zero = lc(ZERO_ADDRESS);
|
|
335
348
|
const eth = lc(deployment.eth);
|
|
@@ -337,14 +350,14 @@ function checkRoute(chainId, deployment, table, args, tokenIn, tokenOut) {
|
|
|
337
350
|
const v = erc4626Of(deployment);
|
|
338
351
|
let steps = 0;
|
|
339
352
|
while (steps < 5 && lc(args.route[2 * steps + 1]) !== zero) steps++;
|
|
340
|
-
if (steps === 0) return "the route has no step";
|
|
341
|
-
if (steps > MAX_ROUTE_STEPS) return `the route has ${steps} steps, more than ${MAX_ROUTE_STEPS}
|
|
342
|
-
for (let k = 2 * steps + 1; k < 11; k++) if (lc(args.route[k]) !== zero) return "the route names addresses after its end";
|
|
343
|
-
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";
|
|
344
|
-
if (lc(args.route[0]) !== lc(tokenIn)) return `the route starts at ${args.route[0]}, not the source token
|
|
345
|
-
if (lc(args.route[2 * steps]) !== lc(tokenOut)) return `the route ends at ${args.route[2 * steps]}, not the destination token
|
|
353
|
+
if (steps === 0) return noted("the route has no step", "policy_refused");
|
|
354
|
+
if (steps > MAX_ROUTE_STEPS) return noted(`the route has ${steps} steps, more than ${MAX_ROUTE_STEPS}`, "policy_refused");
|
|
355
|
+
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");
|
|
356
|
+
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");
|
|
357
|
+
if (lc(args.route[0]) !== lc(tokenIn)) return noted(`the route starts at ${args.route[0]}, not the source token`, "policy_refused");
|
|
358
|
+
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");
|
|
346
359
|
for (let k = 1; k < steps; k++) {
|
|
347
|
-
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
|
|
360
|
+
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");
|
|
348
361
|
}
|
|
349
362
|
const pools = /* @__PURE__ */ new Set();
|
|
350
363
|
let wraps = 0;
|
|
@@ -355,49 +368,50 @@ function checkRoute(chainId, deployment, table, args, tokenIn, tokenOut) {
|
|
|
355
368
|
const b = lc(args.route[2 * k + 2]);
|
|
356
369
|
const row = args.params[k];
|
|
357
370
|
const type = row[2];
|
|
358
|
-
if (a === b) return `step ${k + 1} trades a token for itself
|
|
371
|
+
if (a === b) return noted(`step ${k + 1} trades a token for itself`, "policy_refused");
|
|
359
372
|
if (type === 1n || type === 2n) {
|
|
360
|
-
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)
|
|
373
|
+
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");
|
|
361
374
|
const pool = index.get(swap);
|
|
362
|
-
if (!pool) return `step ${k + 1} crosses ${args.route[2 * k + 1]}, which is not in the pool allowlist
|
|
363
|
-
if (pools.has(swap)) return `the route crosses ${args.route[2 * k + 1]} twice
|
|
375
|
+
if (!pool) return noted(`step ${k + 1} crosses ${args.route[2 * k + 1]}, which is not in the pool allowlist`, "vault_mismatch");
|
|
376
|
+
if (pools.has(swap)) return noted(`the route crosses ${args.route[2 * k + 1]} twice`, "policy_refused");
|
|
364
377
|
pools.add(swap);
|
|
365
|
-
if (!pool.swapTypes.includes(type === 1n ? 1 : 2)) return `step ${k + 1} uses swap_type ${type}, which pool ${pool.name} does not allow
|
|
366
|
-
if (row[3] !== BigInt(pool.poolType)) return `step ${k + 1} names pool_type ${row[3]}, not pool ${pool.name}'s ${pool.poolType}
|
|
367
|
-
if (type === 2n && deployment.family === "lite4" && pool.poolType !== 10) return `step ${k + 1}: exchange_underlying is for stable-ng metapools on this router
|
|
368
|
-
if (type === 2n && !underlyingAllowed(pool, index)) return `step ${k + 1}: exchange_underlying on pool ${pool.name} needs its base pool in the allowlist
|
|
378
|
+
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");
|
|
379
|
+
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");
|
|
380
|
+
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");
|
|
381
|
+
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");
|
|
369
382
|
const list = type === 1n ? pool.coins : pool.underlying;
|
|
370
|
-
if (!list) return `step ${k + 1}: pool ${pool.name} lists no underlying coins
|
|
383
|
+
if (!list) return noted(`step ${k + 1}: pool ${pool.name} lists no underlying coins`, "policy_refused");
|
|
371
384
|
const i = row[0], j = row[1];
|
|
372
|
-
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}
|
|
373
|
-
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
|
|
374
|
-
if (deployment.family === "ng5" && row[4] !== BigInt(list.length)) return `step ${k + 1} names ${row[4]} coins, not pool ${pool.name}'s ${list.length}
|
|
375
|
-
if (deployment.family === "lite4" && (a === eth || b === eth)) return `step ${k + 1}: this router does not pass the native coin to pools
|
|
376
|
-
if (STABLE_POOL_TYPES.has(pool.poolType) && (i > 127n || j > 127n)) return `step ${k + 1}: coin index out of range
|
|
385
|
+
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");
|
|
386
|
+
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");
|
|
387
|
+
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");
|
|
388
|
+
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");
|
|
389
|
+
if (STABLE_POOL_TYPES.has(pool.poolType) && (i > 127n || j > 127n)) return noted(`step ${k + 1}: coin index out of range`, "policy_refused");
|
|
377
390
|
} else if (type === 8n) {
|
|
378
|
-
if (weth === zero) return "this chain's router has no wrapped native";
|
|
379
|
-
if (swap !== weth) return `step ${k + 1} wraps through ${args.route[2 * k + 1]}, not the pinned wrapped native
|
|
380
|
-
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
|
|
381
|
-
if (row.some((x, c) => c !== 2 && x !== 0n)) return `step ${k + 1}: a wrap carries no other swap params
|
|
382
|
-
if (++wraps > 1) return "the route wraps more than once";
|
|
391
|
+
if (weth === zero) return noted("this chain's router has no wrapped native", "policy_refused");
|
|
392
|
+
if (swap !== weth) return noted(`step ${k + 1} wraps through ${args.route[2 * k + 1]}, not the pinned wrapped native`, "vault_mismatch");
|
|
393
|
+
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");
|
|
394
|
+
if (row.some((x, c) => c !== 2 && x !== 0n)) return noted(`step ${k + 1}: a wrap carries no other swap params`, "policy_refused");
|
|
395
|
+
if (++wraps > 1) return noted("the route wraps more than once", "policy_refused");
|
|
383
396
|
} else if (type === 9n) {
|
|
384
|
-
if (!v) return `swap_type 9 (ERC-4626) is not available on ${deployment.label}'s router ${deployment.version}
|
|
385
|
-
if (swap !== lc(v.vault)) return `step ${k + 1}: ERC-4626 hop through ${args.route[2 * k + 1]}, not the pinned vault
|
|
397
|
+
if (!v) return noted(`swap_type 9 (ERC-4626) is not available on ${deployment.label}'s router ${deployment.version}`, "policy_refused");
|
|
398
|
+
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");
|
|
386
399
|
const deposit = row[0] === 0n && a === lc(v.asset) && b === lc(v.vault);
|
|
387
400
|
const redeem = row[0] === 1n && a === lc(v.vault) && b === lc(v.asset);
|
|
388
|
-
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
|
|
389
|
-
if (row.some((x, c) => c > 0 && c !== 2 && x !== 0n)) return `step ${k + 1}: an ERC-4626 hop carries no other swap params
|
|
390
|
-
if (++vaults > 1) return "the route crosses the vault more than once";
|
|
401
|
+
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");
|
|
402
|
+
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");
|
|
403
|
+
if (++vaults > 1) return noted("the route crosses the vault more than once", "policy_refused");
|
|
391
404
|
} else {
|
|
392
|
-
return `step ${k + 1} uses swap_type ${type}, which this module never builds
|
|
405
|
+
return noted(`step ${k + 1} uses swap_type ${type}, which this module never builds`, "policy_refused");
|
|
393
406
|
}
|
|
394
407
|
}
|
|
395
|
-
if (pools.size > MAX_ROUTE_POOLS) return `the route crosses ${pools.size} pools, more than ${MAX_ROUTE_POOLS}
|
|
396
|
-
if (pools.size === 0 && vaults === 0) return "the route crosses no pool";
|
|
408
|
+
if (pools.size > MAX_ROUTE_POOLS) return noted(`the route crosses ${pools.size} pools, more than ${MAX_ROUTE_POOLS}`, "policy_refused");
|
|
409
|
+
if (pools.size === 0 && vaults === 0) return noted("the route crosses no pool", "policy_refused");
|
|
397
410
|
return null;
|
|
398
411
|
}
|
|
399
412
|
|
|
400
413
|
// src/rpc.ts
|
|
414
|
+
import { httpRefusal, refusal, refusalOf, withReason as withReason2 } from "@anywalletkit/protocol-swap2-core/errors";
|
|
401
415
|
import { redactUrls, timeoutSignal } from "@anywalletkit/protocol-swap2-core/util";
|
|
402
416
|
var RPC_BATCH_MAX = 10;
|
|
403
417
|
var RPC_RATE_LIMIT_PAUSE_MS = 1e3;
|
|
@@ -423,18 +437,18 @@ function rpcClient(rpcUrls) {
|
|
|
423
437
|
body: JSON.stringify(calls.map((c, id) => ({ jsonrpc: "2.0", id, ...c }))),
|
|
424
438
|
signal: signal ?? timeoutSignal(12e3)
|
|
425
439
|
});
|
|
426
|
-
if (!res.ok) throw Object.assign(new Error(`HTTP ${res.status}`), { limited: res.status === 429 });
|
|
440
|
+
if (!res.ok) throw withReason2(Object.assign(new Error(`HTTP ${res.status}`), { limited: res.status === 429 }), httpRefusal(res.status, res.headers?.get?.("retry-after")) ?? { reason: "upstream_unavailable", httpStatus: res.status });
|
|
427
441
|
const body = await res.json();
|
|
428
|
-
if (!Array.isArray(body)) throw Object.assign(new Error(body.error?.message ?? "batch refused"), { limited: isRateLimit(body.error) });
|
|
442
|
+
if (!Array.isArray(body)) throw withReason2(Object.assign(new Error(body.error?.message ?? "batch refused"), { limited: isRateLimit(body.error) }), isRateLimit(body.error) ? "rate_limited" : "upstream_unavailable");
|
|
429
443
|
const out = calls.map(() => null);
|
|
430
444
|
const answered = /* @__PURE__ */ new Set();
|
|
431
445
|
for (const r of body) {
|
|
432
446
|
if (typeof r.id !== "number" || r.id < 0 || r.id >= out.length) continue;
|
|
433
|
-
if (r.error !== void 0 && r.error !== null && !isExecutionError(r.error)) throw Object.assign(new Error(errorText(r.error)), { limited: isRateLimit(r.error) });
|
|
447
|
+
if (r.error !== void 0 && r.error !== null && !isExecutionError(r.error)) throw withReason2(Object.assign(new Error(errorText(r.error)), { limited: isRateLimit(r.error) }), isRateLimit(r.error) ? "rate_limited" : "upstream_unavailable");
|
|
434
448
|
answered.add(r.id);
|
|
435
449
|
if (r.error === void 0 || r.error === null) out[r.id] = r.result ?? null;
|
|
436
450
|
}
|
|
437
|
-
if (answered.size !== calls.length) throw
|
|
451
|
+
if (answered.size !== calls.length) throw refusal("upstream_unavailable", `answered ${answered.size} of ${calls.length} calls`);
|
|
438
452
|
return out;
|
|
439
453
|
}
|
|
440
454
|
async function batch(chainId, calls, signal) {
|
|
@@ -452,7 +466,9 @@ function rpcClient(rpcUrls) {
|
|
|
452
466
|
}
|
|
453
467
|
}
|
|
454
468
|
}
|
|
455
|
-
|
|
469
|
+
const error = new Error(`curve: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);
|
|
470
|
+
if (lastErr === void 0 || signal?.aborted) throw error;
|
|
471
|
+
throw withReason2(error, refusalOf(lastErr) ?? "upstream_unavailable");
|
|
456
472
|
}
|
|
457
473
|
return async function rpc(chainId, calls, signal) {
|
|
458
474
|
if (calls.length <= RPC_BATCH_MAX) return batch(chainId, calls, signal);
|
|
@@ -512,6 +528,7 @@ function curveIntentChain(intentId) {
|
|
|
512
528
|
import { decodeFunctionResult, encodeFunctionData, keccak256 } from "viem";
|
|
513
529
|
import { sourceAssetOf as sourceAssetOf2 } from "@anywalletkit/protocol-swap2-core/util";
|
|
514
530
|
import { slippageFloor } from "@anywalletkit/protocol-swap2-core/validate";
|
|
531
|
+
import { refusal as refusal2, refusalOf as refusalOf2 } from "@anywalletkit/protocol-swap2-core/errors";
|
|
515
532
|
var lc2 = (a) => a.toLowerCase();
|
|
516
533
|
var isAddress = (a) => /^0x[0-9a-fA-F]{40}$/.test(a);
|
|
517
534
|
var own = (o, k) => Object.prototype.hasOwnProperty.call(o, k) ? o[k] : void 0;
|
|
@@ -521,19 +538,19 @@ function curveQuoteCheck(tables = {}) {
|
|
|
521
538
|
return function verify(params, quote) {
|
|
522
539
|
const chainId = chainIdOf(params.sourceChain);
|
|
523
540
|
const d = deploymentOf(deployments, chainId);
|
|
524
|
-
if (!d || params.destChain !== params.sourceChain) return "not a same-chain swap on a pinned Curve router";
|
|
541
|
+
if (!d || params.destChain !== params.sourceChain) return noted("not a same-chain swap on a pinned Curve router", "unsupported_pair");
|
|
525
542
|
const tx = quote.txRequest;
|
|
526
|
-
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return "the quote carries no router call";
|
|
527
|
-
if (!isAddress(tx.to) || lc2(tx.to) !== lc2(d.router)) return `the call targets ${tx.to}, not the Curve router
|
|
528
|
-
if (tx.chainId !== void 0 && tx.chainId !== chainId) return `the call is for chain ${tx.chainId}
|
|
529
|
-
if (curveIntentChain(quote.intentId) !== chainId) return `the quote names ${String(quote.intentId).slice(0, 40)}, not a curve:${chainId} swap
|
|
543
|
+
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return noted("the quote carries no router call", "policy_refused");
|
|
544
|
+
if (!isAddress(tx.to) || lc2(tx.to) !== lc2(d.router)) return noted(`the call targets ${tx.to}, not the Curve router`, "vault_mismatch");
|
|
545
|
+
if (tx.chainId !== void 0 && tx.chainId !== chainId) return noted(`the call is for chain ${tx.chainId}`, "policy_refused");
|
|
546
|
+
if (curveIntentChain(quote.intentId) !== chainId) return noted(`the quote names ${String(quote.intentId).slice(0, 40)}, not a curve:${chainId} swap`, "policy_refused");
|
|
530
547
|
const src = sourceAssetOf2(params);
|
|
531
|
-
if (!src) return `unknown source token ${params.sourceToken}
|
|
548
|
+
if (!src) return noted(`unknown source token ${params.sourceToken}`, "unsupported_pair");
|
|
532
549
|
const nativeIn = !src.contract;
|
|
533
550
|
const nativeOut = /^0x0+$/.test(params.destToken);
|
|
534
|
-
if (!nativeOut && !isAddress(params.destToken)) return "destination token must be an EVM address";
|
|
535
|
-
if (!isAddress(params.destAddress)) return "recipient must be an EVM address";
|
|
536
|
-
if (!nativeIn && lc2(src.contract) === lc2(d.eth) || !nativeOut && lc2(params.destToken) === lc2(d.eth)) return "the router's native sentinel is not a token";
|
|
551
|
+
if (!nativeOut && !isAddress(params.destToken)) return noted("destination token must be an EVM address", "unsupported_pair");
|
|
552
|
+
if (!isAddress(params.destAddress)) return noted("recipient must be an EVM address", "recipient_mismatch");
|
|
553
|
+
if (!nativeIn && lc2(src.contract) === lc2(d.eth) || !nativeOut && lc2(params.destToken) === lc2(d.eth)) return noted("the router's native sentinel is not a token", "unsupported_pair");
|
|
537
554
|
const tokenIn = nativeIn ? d.eth : src.contract;
|
|
538
555
|
const tokenOut = nativeOut ? d.eth : params.destToken;
|
|
539
556
|
let amountIn, minOut, value;
|
|
@@ -542,20 +559,20 @@ function curveQuoteCheck(tables = {}) {
|
|
|
542
559
|
minOut = BigInt(quote.minDestAmount);
|
|
543
560
|
value = BigInt(tx.value ?? "0");
|
|
544
561
|
} catch {
|
|
545
|
-
return "the request does not name amounts";
|
|
562
|
+
return noted("the request does not name amounts", "policy_refused");
|
|
546
563
|
}
|
|
547
564
|
if (nativeIn ? value !== amountIn || tx.approvalAddress !== void 0 : value !== 0n || !tx.approvalAddress || !isAddress(tx.approvalAddress) || lc2(tx.approvalAddress) !== lc2(d.router)) {
|
|
548
|
-
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";
|
|
565
|
+
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");
|
|
549
566
|
}
|
|
550
567
|
const call = decodeExchange(d.family, tx.data);
|
|
551
|
-
if (!call) return "the router call is not exchange(route, params, amount, min, receiver)";
|
|
552
|
-
if (call.selector !== EXCHANGE_SELECTOR[d.family]) return `selector ${call.selector} is not the explicit-receiver exchange ${EXCHANGE_SELECTOR[d.family]}
|
|
553
|
-
if (!call.receiver || lc2(call.receiver) !== lc2(params.destAddress)) return `the swap pays ${call.receiver ?? "the sender"}, not the recipient
|
|
554
|
-
if (call.pools && call.pools.some((p) => lc2(p) !== lc2(ZERO_ADDRESS))) return "the call names zap pools this module never uses";
|
|
555
|
-
if (call.amount !== amountIn) return `the swap sells ${call.amount}, not the ${amountIn} input
|
|
556
|
-
if (call.minDy <= 0n) return "the swap has no minimum (min_dy 0)";
|
|
557
|
-
if (call.minDy !== minOut) return `the swap's minimum ${call.minDy} is not the quote's ${minOut}
|
|
558
|
-
if (quote.providerData?.minOut !== void 0 && quote.providerData.minOut !== minOut.toString()) return "the quote's facts disagree on the minimum";
|
|
568
|
+
if (!call) return noted("the router call is not exchange(route, params, amount, min, receiver)", "policy_refused");
|
|
569
|
+
if (call.selector !== EXCHANGE_SELECTOR[d.family]) return noted(`selector ${call.selector} is not the explicit-receiver exchange ${EXCHANGE_SELECTOR[d.family]}`, "policy_refused");
|
|
570
|
+
if (!call.receiver || lc2(call.receiver) !== lc2(params.destAddress)) return noted(`the swap pays ${call.receiver ?? "the sender"}, not the recipient`, "recipient_mismatch");
|
|
571
|
+
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");
|
|
572
|
+
if (call.amount !== amountIn) return noted(`the swap sells ${call.amount}, not the ${amountIn} input`, "policy_refused");
|
|
573
|
+
if (call.minDy <= 0n) return noted("the swap has no minimum (min_dy 0)", "price_check_failed");
|
|
574
|
+
if (call.minDy !== minOut) return noted(`the swap's minimum ${call.minDy} is not the quote's ${minOut}`, "price_check_failed");
|
|
575
|
+
if (quote.providerData?.minOut !== void 0 && quote.providerData.minOut !== minOut.toString()) return noted("the quote's facts disagree on the minimum", "price_check_failed");
|
|
559
576
|
return checkRoute(chainId, d, own(pools, chainId), call, tokenIn, tokenOut);
|
|
560
577
|
};
|
|
561
578
|
}
|
|
@@ -563,7 +580,9 @@ var curveVerifyQuote = curveQuoteCheck();
|
|
|
563
580
|
var curvePins = Object.freeze({
|
|
564
581
|
callTargets: (chain) => routerFor(CURVE_DEPLOYMENTS, chain),
|
|
565
582
|
spenders: (chain) => routerFor(CURVE_DEPLOYMENTS, chain),
|
|
566
|
-
verifyQuote: curveVerifyQuote
|
|
583
|
+
verifyQuote: curveVerifyQuote,
|
|
584
|
+
// The reason of each text verifyQuote returned (remoteProvider puts it on its refusal).
|
|
585
|
+
reasonOf: notes.reasonOf
|
|
567
586
|
});
|
|
568
587
|
function routerFor(deployments, chain) {
|
|
569
588
|
const d = deploymentOf(deployments, chainIdOf(chain));
|
|
@@ -580,21 +599,21 @@ function curveOnChain(opts) {
|
|
|
580
599
|
if (!p) {
|
|
581
600
|
const d = deploymentOf(deployments, chainId);
|
|
582
601
|
p = (async () => {
|
|
583
|
-
if (!d) throw
|
|
602
|
+
if (!d) throw refusal2("unsupported_pair", `curve: no pinned router on chain ${chainId}`);
|
|
584
603
|
const [code, version, listed] = await rpc(chainId, [
|
|
585
604
|
{ method: "eth_getCode", params: [d.router, "latest"] },
|
|
586
605
|
ethCall(d.router, encodeFunctionData({ abi: VERSION_ABI, functionName: "version" })),
|
|
587
606
|
ethCall(d.addressProvider, encodeFunctionData({ abi: ADDRESS_PROVIDER_ABI, functionName: "get_address", args: [2n] }))
|
|
588
607
|
]);
|
|
589
608
|
if (typeof code !== "string" || code.length <= 2 || lc2(keccak256(code)) !== lc2(d.codeHash)) {
|
|
590
|
-
throw
|
|
609
|
+
throw refusal2("vault_mismatch", `curve: the router on chain ${chainId} is not the pinned code (code hash mismatch) \u2014 refusing`);
|
|
591
610
|
}
|
|
592
611
|
let v = "";
|
|
593
612
|
try {
|
|
594
613
|
v = typeof version === "string" ? decodeFunctionResult({ abi: VERSION_ABI, functionName: "version", data: version }) : "";
|
|
595
614
|
} catch {
|
|
596
615
|
}
|
|
597
|
-
if (v !== d.version) throw
|
|
616
|
+
if (v !== d.version) throw refusal2("vault_mismatch", `curve: the router on chain ${chainId} reports version ${v || "none"}, not ${d.version} \u2014 refusing`);
|
|
598
617
|
const ap = wordAddress(listed);
|
|
599
618
|
if (ap && ap !== lc2(d.addressProviderRouter) && ap !== lc2(d.router)) {
|
|
600
619
|
warn(`curve: the AddressProvider on ${d.label} lists router ${ap} (id 2); this module keeps the pinned ${d.router}`);
|
|
@@ -612,17 +631,17 @@ function curveOnChain(opts) {
|
|
|
612
631
|
async function inspectSealed(quote, tx, probe) {
|
|
613
632
|
const chainId = curveIntentChain(quote.intentId);
|
|
614
633
|
const d = chainId === null ? void 0 : deploymentOf(deployments, chainId);
|
|
615
|
-
if (chainId === null || !d) return "the quote is not a Curve swap on a pinned chain";
|
|
634
|
+
if (chainId === null || !d) return noted("the quote is not a Curve swap on a pinned chain", "policy_refused");
|
|
616
635
|
const quoted = quote.txRequest;
|
|
617
|
-
if (!quoted?.data || !quoted.to || !tx.data) return "the quote or the transaction carries no router call";
|
|
618
|
-
if (tx.data.length !== quoted.data.length || lc2(tx.data) !== lc2(quoted.data)) return "the transaction is not the quoted router call";
|
|
619
|
-
if (!isAddress(tx.to) || lc2(tx.to) !== lc2(d.router) || lc2(quoted.to) !== lc2(d.router)) return `the transaction calls ${tx.to}, not the Curve router
|
|
620
|
-
if ((tx.value ?? "0") !== (quoted.value ?? "0")) return "the transaction's value is not the quote's";
|
|
621
|
-
if (tx.chainId !== void 0 && tx.chainId !== chainId || quoted.chainId !== void 0 && quoted.chainId !== chainId) return `the transaction is not for chain ${chainId}
|
|
622
|
-
if ((tx.approvalAddress ?? "").toLowerCase() !== (quoted.approvalAddress ?? "").toLowerCase()) return "the transaction's approval is not the quote's";
|
|
636
|
+
if (!quoted?.data || !quoted.to || !tx.data) return noted("the quote or the transaction carries no router call", "policy_refused");
|
|
637
|
+
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");
|
|
638
|
+
if (!isAddress(tx.to) || lc2(tx.to) !== lc2(d.router) || lc2(quoted.to) !== lc2(d.router)) return noted(`the transaction calls ${tx.to}, not the Curve router`, "vault_mismatch");
|
|
639
|
+
if ((tx.value ?? "0") !== (quoted.value ?? "0")) return noted("the transaction's value is not the quote's", "policy_refused");
|
|
640
|
+
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");
|
|
641
|
+
if ((tx.approvalAddress ?? "").toLowerCase() !== (quoted.approvalAddress ?? "").toLowerCase()) return noted("the transaction's approval is not the quote's", "vault_mismatch");
|
|
623
642
|
const call = decodeExchange(d.family, quoted.data);
|
|
624
|
-
if (!call || call.selector !== EXCHANGE_SELECTOR[d.family]) return "the quoted call is not the explicit-receiver exchange";
|
|
625
|
-
if (call.minDy <= 0n) return "the swap has no minimum (min_dy 0)";
|
|
643
|
+
if (!call || call.selector !== EXCHANGE_SELECTOR[d.family]) return noted("the quoted call is not the explicit-receiver exchange", "policy_refused");
|
|
644
|
+
if (call.minDy <= 0n) return noted("the swap has no minimum (min_dy 0)", "price_check_failed");
|
|
626
645
|
const last = lastToken(call);
|
|
627
646
|
const reason = checkRoute(chainId, d, own(pools, chainId), call, call.route[0], last);
|
|
628
647
|
if (reason) return reason;
|
|
@@ -638,8 +657,8 @@ function curveOnChain(opts) {
|
|
|
638
657
|
const poolReason = await poolsReason(chainId, hops, res.slice(1, 1 + reads.length));
|
|
639
658
|
if (poolReason) return poolReason;
|
|
640
659
|
const out = wordUint(res[0]);
|
|
641
|
-
if (out === null) return "the router no longer quotes this route";
|
|
642
|
-
if (out < call.minDy) return `price moved \u2014 the pools now pay ${out}, under your minimum ${call.minDy}
|
|
660
|
+
if (out === null) return noted("the router no longer quotes this route", "simulation_failed");
|
|
661
|
+
if (out < call.minDy) return noted(`price moved \u2014 the pools now pay ${out}, under your minimum ${call.minDy}`, "price_check_failed");
|
|
643
662
|
return { out, probeOut: probe && probeIn > 0n ? wordUint(res[probeAt]) : null, amount: call.amount, minDy: call.minDy };
|
|
644
663
|
}
|
|
645
664
|
function poolCalls(list) {
|
|
@@ -653,19 +672,19 @@ function curveOnChain(opts) {
|
|
|
653
672
|
const retry = [];
|
|
654
673
|
for (const pool of list) {
|
|
655
674
|
const code = res[at++];
|
|
656
|
-
if (typeof code !== "string") return `could not read pool ${pool.name} (${pool.address}) over RPC
|
|
657
|
-
if (code.length <= 2 || lc2(keccak256(code)) !== lc2(pool.codeHash)) return `pool ${pool.name} (${pool.address}) is not the pinned code
|
|
675
|
+
if (typeof code !== "string") return noted(`could not read pool ${pool.name} (${pool.address}) over RPC`, "upstream_unavailable");
|
|
676
|
+
if (code.length <= 2 || lc2(keccak256(code)) !== lc2(pool.codeHash)) return noted(`pool ${pool.name} (${pool.address}) is not the pinned code`, "vault_mismatch");
|
|
658
677
|
for (let k = 0; k < pool.coins.length; k++) {
|
|
659
678
|
const coin = wordAddress(res[at++]);
|
|
660
679
|
if (coin === null) retry.push({ pool, k });
|
|
661
|
-
else if (coin !== lc2(pool.coins[k])) return `pool ${pool.name} now reports coin ${k} = ${coin}, not the pinned ${pool.coins[k]}
|
|
680
|
+
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");
|
|
662
681
|
}
|
|
663
682
|
}
|
|
664
683
|
if (retry.length) {
|
|
665
684
|
const again = await rpc(chainId, retry.map(({ pool, k }) => ethCall(pool.address, `${COINS_INT}${k.toString(16).padStart(64, "0")}`)));
|
|
666
685
|
for (const [n, { pool, k }] of retry.entries()) {
|
|
667
686
|
const coin = wordAddress(again[n]);
|
|
668
|
-
if (coin !== lc2(pool.coins[k])) return `pool ${pool.name} does not report its pinned coin ${k}
|
|
687
|
+
if (coin !== lc2(pool.coins[k])) return noted(`pool ${pool.name} does not report its pinned coin ${k}`, "vault_mismatch");
|
|
669
688
|
}
|
|
670
689
|
}
|
|
671
690
|
return null;
|
|
@@ -691,8 +710,10 @@ function curveRemotePins(opts) {
|
|
|
691
710
|
callTargets: (c) => routerFor(deployments, c),
|
|
692
711
|
spenders: (c) => routerFor(deployments, c),
|
|
693
712
|
verifyQuote,
|
|
713
|
+
// The reason of each text verifyQuote / verifyBuild returned (remoteProvider puts it on its refusal).
|
|
714
|
+
reasonOf: notes.reasonOf,
|
|
694
715
|
async verifyBuild(quote, tx, params) {
|
|
695
|
-
if (!params) return "the request this quote answered is unknown";
|
|
716
|
+
if (!params) return noted("the request this quote answered is unknown", "policy_refused");
|
|
696
717
|
const reason = verifyQuote(params, quote);
|
|
697
718
|
if (reason) return reason;
|
|
698
719
|
try {
|
|
@@ -704,15 +725,15 @@ function curveRemotePins(opts) {
|
|
|
704
725
|
try {
|
|
705
726
|
dest = BigInt(quote.destAmount);
|
|
706
727
|
} catch {
|
|
707
|
-
return "the quote names no output";
|
|
728
|
+
return noted("the quote names no output", "upstream_unavailable");
|
|
708
729
|
}
|
|
709
730
|
const bps = params.slippageBps ?? fixedSlippage ?? Math.min(9999, curveAutoSlippageBps(params, curveImpactBps(amount, out, probeOut)) + CURVE_AUTO_SLIPPAGE_DRIFT_BPS);
|
|
710
|
-
if (slippageFloor(dest, bps) > out) return `the quote promises ${dest}, more than ${bps} bps above the ${out} the pools pay now
|
|
731
|
+
if (slippageFloor(dest, bps) > out) return noted(`the quote promises ${dest}, more than ${bps} bps above the ${out} the pools pay now`, "price_check_failed");
|
|
711
732
|
const fresh = dest < out ? dest : out;
|
|
712
|
-
if (minDy < slippageFloor(fresh, bps)) return `the swap's minimum ${minDy} is more than ${bps} bps under the ${fresh} the pools pay now
|
|
733
|
+
if (minDy < 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");
|
|
713
734
|
return null;
|
|
714
735
|
} catch (e) {
|
|
715
|
-
return e instanceof Error ? e.message.replace(/^curve: /, "") : String(e);
|
|
736
|
+
return noted(e instanceof Error ? e.message.replace(/^curve: /, "") : String(e), refusalOf2(e));
|
|
716
737
|
}
|
|
717
738
|
}
|
|
718
739
|
});
|
|
@@ -750,46 +771,47 @@ function curveProvider(config) {
|
|
|
750
771
|
return from.chain === to.chain && chainIdOf2(from.chain) !== null;
|
|
751
772
|
},
|
|
752
773
|
async getQuote(params, signal) {
|
|
753
|
-
const refuse = (why) => {
|
|
754
|
-
params.onRefusal?.(`curve: ${why}`);
|
|
774
|
+
const refuse = (why, info) => {
|
|
775
|
+
if (info === void 0) params.onRefusal?.(`curve: ${why}`);
|
|
776
|
+
else params.onRefusal?.(`curve: ${why}`, typeof info === "string" ? { reason: info } : info);
|
|
755
777
|
return null;
|
|
756
778
|
};
|
|
757
|
-
if (params.flex) return refuse("amount-flexible deposits are not supported");
|
|
758
|
-
if (params.sourceChain !== params.destChain) return refuse("same-chain swaps only");
|
|
779
|
+
if (params.flex) return refuse("amount-flexible deposits are not supported", "unsupported_pair");
|
|
780
|
+
if (params.sourceChain !== params.destChain) return refuse("same-chain swaps only", "unsupported_pair");
|
|
759
781
|
const chainId = chainIdOf2(params.sourceChain);
|
|
760
|
-
if (chainId === null) return refuse(`no Curve router, pool allowlist or RPC for ${params.sourceChain}
|
|
782
|
+
if (chainId === null) return refuse(`no Curve router, pool allowlist or RPC for ${params.sourceChain}`, "unsupported_pair");
|
|
761
783
|
const d = deploymentOf(deployments, chainId);
|
|
762
784
|
const src = sourceAssetOf3(params);
|
|
763
|
-
if (!src) return refuse(`unknown source token ${params.sourceToken}
|
|
785
|
+
if (!src) return refuse(`unknown source token ${params.sourceToken}`, "unsupported_pair");
|
|
764
786
|
const nativeIn = !src.contract;
|
|
765
787
|
const nativeOut = /^0x0+$/.test(params.destToken);
|
|
766
|
-
if (!nativeOut && !/^0x[0-9a-fA-F]{40}$/.test(params.destToken)) return refuse("destination token must be an EVM address");
|
|
767
|
-
if (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress)) return refuse("recipient must be an EVM address");
|
|
788
|
+
if (!nativeOut && !/^0x[0-9a-fA-F]{40}$/.test(params.destToken)) return refuse("destination token must be an EVM address", "unsupported_pair");
|
|
789
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress)) return refuse("recipient must be an EVM address", "recipient_mismatch");
|
|
768
790
|
let amountIn;
|
|
769
791
|
try {
|
|
770
792
|
amountIn = BigInt(params.amountIn);
|
|
771
793
|
} catch {
|
|
772
794
|
return refuse("amount is not an integer");
|
|
773
795
|
}
|
|
774
|
-
if (amountIn <= 0n) return refuse("amount must be positive");
|
|
796
|
+
if (amountIn <= 0n) return refuse("amount must be positive", "amount_too_small");
|
|
775
797
|
if (params.slippageBps !== void 0 && (!Number.isInteger(params.slippageBps) || params.slippageBps < 0 || params.slippageBps >= 1e4)) return refuse("slippage must be 0..9999 bps");
|
|
776
|
-
if (!nativeIn && src.contract.toLowerCase() === d.eth.toLowerCase()) return refuse("the native coin is named by the catalog, not by the router's 0xEeee sentinel");
|
|
777
|
-
if (!nativeOut && params.destToken.toLowerCase() === d.eth.toLowerCase()) return refuse("name a native output with the zero address, not the router's 0xEeee sentinel");
|
|
798
|
+
if (!nativeIn && src.contract.toLowerCase() === d.eth.toLowerCase()) return refuse("the native coin is named by the catalog, not by the router's 0xEeee sentinel", "unsupported_pair");
|
|
799
|
+
if (!nativeOut && params.destToken.toLowerCase() === d.eth.toLowerCase()) return refuse("name a native output with the zero address, not the router's 0xEeee sentinel", "unsupported_pair");
|
|
778
800
|
const tokenIn = getAddress2(nativeIn ? d.eth : src.contract);
|
|
779
801
|
const tokenOut = getAddress2(nativeOut ? d.eth : params.destToken);
|
|
780
|
-
if (tokenIn === tokenOut) return refuse("same token in and out");
|
|
802
|
+
if (tokenIn === tokenOut) return refuse("same token in and out", "unsupported_pair");
|
|
781
803
|
const wrapPair = [getAddress2(d.eth), getAddress2(d.weth)];
|
|
782
|
-
if (wrapPair.includes(tokenIn) && wrapPair.includes(tokenOut)) return refuse("that is a wrap/unwrap, not a swap");
|
|
804
|
+
if (wrapPair.includes(tokenIn) && wrapPair.includes(tokenOut)) return refuse("that is a wrap/unwrap, not a swap", "unsupported_pair");
|
|
783
805
|
try {
|
|
784
806
|
await chain.verifyDeployment(chainId);
|
|
785
807
|
const { routes, truncated } = findRoutes(chainId, d, tableOf(chainId), tokenIn, tokenOut);
|
|
786
|
-
if (!routes.length) return refuse("no allowlisted Curve pool route for this pair");
|
|
808
|
+
if (!routes.length) return refuse("no allowlisted Curve pool route for this pair", "no_route");
|
|
787
809
|
const outs = await price(chainId, d, routes, amountIn, signal);
|
|
788
810
|
let best = null;
|
|
789
811
|
outs.forEach((out2, i) => {
|
|
790
812
|
if (out2 !== null && out2 > 0n && (!best || out2 > best.out)) best = { route: routes[i], out: out2 };
|
|
791
813
|
});
|
|
792
|
-
if (!best) return refuse("no allowlisted Curve pool quotes this pair and amount");
|
|
814
|
+
if (!best) return refuse("no allowlisted Curve pool quotes this pair and amount", "no_route");
|
|
793
815
|
const { route, out } = best;
|
|
794
816
|
let priceImpactBps;
|
|
795
817
|
const probeIn = amountIn / 1000n;
|
|
@@ -802,9 +824,9 @@ function curveProvider(config) {
|
|
|
802
824
|
}
|
|
803
825
|
const bps = params.slippageBps ?? fixedSlippage ?? curveAutoSlippageBps(params, priceImpactBps);
|
|
804
826
|
const minOut = out * BigInt(1e4 - bps) / 10000n;
|
|
805
|
-
if (minOut <= 0n) return refuse("the minimum rounds to zero for this amount");
|
|
827
|
+
if (minOut <= 0n) return refuse("the minimum rounds to zero for this amount", "amount_too_small");
|
|
806
828
|
if (params.minAmountOut !== void 0 && minOut < BigInt(params.minAmountOut)) {
|
|
807
|
-
return refuse(`floor breach (min=${minOut} < floor=${params.minAmountOut})
|
|
829
|
+
return refuse(`floor breach (min=${minOut} < floor=${params.minAmountOut})`, "price_check_failed");
|
|
808
830
|
}
|
|
809
831
|
const args = routeArgs(d.family, route);
|
|
810
832
|
const recipient = getAddress2(params.destAddress);
|
|
@@ -846,10 +868,10 @@ function curveProvider(config) {
|
|
|
846
868
|
}
|
|
847
869
|
};
|
|
848
870
|
const why = selfCheck(params, quote);
|
|
849
|
-
if (why) return refuse(`built a call its own check refuses (${why})
|
|
871
|
+
if (why) return refuse(`built a call its own check refuses (${why})`, notes.reasonOf(why) ?? "policy_refused");
|
|
850
872
|
return quote;
|
|
851
873
|
} catch (e) {
|
|
852
|
-
return refuse(e instanceof Error ? e.message.replace(/^curve: /, "") : String(e));
|
|
874
|
+
return refuse(e instanceof Error ? e.message.replace(/^curve: /, "") : String(e), refusalOf3(e));
|
|
853
875
|
}
|
|
854
876
|
},
|
|
855
877
|
/**
|
|
@@ -859,11 +881,11 @@ function curveProvider(config) {
|
|
|
859
881
|
*/
|
|
860
882
|
async preflightDeposit(quote, tx) {
|
|
861
883
|
const reason = await chain.checkSealed(quote, tx);
|
|
862
|
-
if (reason) throw new Error(`curve: ${reason}. Nothing was sent; refresh the quote.`);
|
|
884
|
+
if (reason) throw tagged(new Error(`curve: ${reason}. Nothing was sent; refresh the quote.`), notes.reasonOf(reason));
|
|
863
885
|
},
|
|
864
886
|
async buildDeposit(quote) {
|
|
865
887
|
const tx = quote.txRequest;
|
|
866
|
-
if (!tx?.to || !tx.data) throw
|
|
888
|
+
if (!tx?.to || !tx.data) throw refusal3("policy_refused", "swap2: Curve quote has no transaction request");
|
|
867
889
|
return {
|
|
868
890
|
chain: "",
|
|
869
891
|
to: tx.to,
|
|
@@ -909,4 +931,4 @@ export {
|
|
|
909
931
|
curveRemotePins,
|
|
910
932
|
curveProvider
|
|
911
933
|
};
|
|
912
|
-
//# sourceMappingURL=chunk-
|
|
934
|
+
//# sourceMappingURL=chunk-NW2OLRIK.js.map
|