@anywalletkit/protocol-swap2-curve 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,1177 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ ADDRESS_PROVIDER_ABI: () => ADDRESS_PROVIDER_ABI,
24
+ COINS_INT: () => COINS_INT,
25
+ COINS_UINT: () => COINS_UINT,
26
+ CRVUSD_ETHEREUM: () => CRVUSD_ETHEREUM,
27
+ CURVE_AUTO_SLIPPAGE_DRIFT_BPS: () => CURVE_AUTO_SLIPPAGE_DRIFT_BPS,
28
+ CURVE_DENIED_POOLS: () => CURVE_DENIED_POOLS,
29
+ CURVE_DEPLOYMENTS: () => CURVE_DEPLOYMENTS,
30
+ CURVE_ETH: () => CURVE_ETH,
31
+ CURVE_LEGACY_ROUTERS: () => CURVE_LEGACY_ROUTERS,
32
+ CURVE_MODULE: () => CURVE_MODULE,
33
+ CURVE_POOLS: () => CURVE_POOLS,
34
+ CurveSwap2Protocol: () => CurveSwap2Protocol,
35
+ EXCHANGE_SELECTOR: () => EXCHANGE_SELECTOR,
36
+ EXCHANGE_TOPIC: () => EXCHANGE_TOPIC,
37
+ GET_DY_SELECTOR: () => GET_DY_SELECTOR,
38
+ MAX_QUOTE_CANDIDATES: () => MAX_QUOTE_CANDIDATES,
39
+ MAX_ROUTE_POOLS: () => MAX_ROUTE_POOLS,
40
+ MAX_ROUTE_STEPS: () => MAX_ROUTE_STEPS,
41
+ ROUTER_LITE4_ABI: () => ROUTER_LITE4_ABI,
42
+ ROUTER_NG5_ABI: () => ROUTER_NG5_ABI,
43
+ ROUTER_SELECTORS: () => ROUTER_SELECTORS,
44
+ SCRVUSD: () => SCRVUSD,
45
+ VERSION_ABI: () => VERSION_ABI,
46
+ ZERO_ADDRESS: () => ZERO_ADDRESS,
47
+ chainIdOf: () => chainIdOf,
48
+ checkRoute: () => checkRoute,
49
+ curveKnownContracts: () => curveKnownContracts,
50
+ curveOnChain: () => curveOnChain,
51
+ curvePins: () => curvePins,
52
+ curveProvider: () => curveProvider,
53
+ curveQuoteCheck: () => curveQuoteCheck,
54
+ curveRemotePins: () => curveRemotePins,
55
+ curveVerifyQuote: () => curveVerifyQuote,
56
+ decodeExchange: () => decodeExchange,
57
+ default: () => CurveSwap2Protocol,
58
+ deploymentOf: () => deploymentOf,
59
+ describeCurveActivity: () => describeCurveActivity,
60
+ encodeExchange: () => encodeExchange,
61
+ encodeGetDy: () => encodeGetDy,
62
+ findRoutes: () => findRoutes,
63
+ intermediateAllowed: () => intermediateAllowed,
64
+ poolIndex: () => poolIndex,
65
+ poolTypeAllowed: () => poolTypeAllowed,
66
+ routeArgs: () => routeArgs,
67
+ routePools: () => routePools,
68
+ underlyingAllowed: () => underlyingAllowed
69
+ });
70
+ module.exports = __toCommonJS(src_exports);
71
+
72
+ // src/deployments.ts
73
+ var CURVE_ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
74
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
75
+ var MAX_ROUTE_POOLS = 2;
76
+ var MAX_ROUTE_STEPS = 4;
77
+ var SCRVUSD = "0x0655977FEb2f289A4aB78af67BAB0d17aAb84367";
78
+ var CRVUSD_ETHEREUM = "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E";
79
+ var AP = "0x5ffe7FB82894076ECB99A30D6A32e969e6e35E98";
80
+ var R_OP_POLY_GNO_AVAX = "0x0DCDED3545D565bA3B19E683431381007245d983";
81
+ var R_UNI_HYPER = "0xd2002373543Ce3527023C75e7518C274A51ce712";
82
+ var R_MONAD_PLASMA_RH = "0xFF5Cb29241F002fFeD2eAa224e3e996D24A6E8d1";
83
+ var R_BASE_MANTLE = "0x4f37A9d177470499A2dD084621020b023fcffc1F";
84
+ var AP_UNI_HYPER = "0x1764ee18e8B3ccA4787249Ceb249356192594585";
85
+ var AP_MONAD_PLASMA_RH = "0x4574921eb950d3Fd5B01562162EC566Cb8bc3648";
86
+ var OP_WETH = "0x4200000000000000000000000000000000000006";
87
+ var d = (o) => Object.freeze({ eth: CURVE_ETH, ...o });
88
+ var CURVE_DEPLOYMENTS = Object.freeze({
89
+ // [5][5] routers. Ethereum runs v1.2 (the router Curve's UI, curve-js and the curve-router-ng README use; the only one
90
+ // with the ERC-4626 hop) — the AddressProvider still lists v1.1 there.
91
+ 1: d({ label: "Ethereum", family: "ng5", router: "0x45312ea0eFf7E09C83CBE249fa1d7598c4C8cd4e", version: "1.2.0", codeHash: "0xbe5f7301254e95d27c6aa1be0fedc0aa04d6c36097e089bc9d2cccaa9d26b164", weth: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", addressProvider: AP, addressProviderRouter: "0x16C6521Dff6baB339122a0FE25a9116693265353", erc4626: { vault: SCRVUSD, asset: CRVUSD_ETHEREUM } }),
92
+ 42161: d({ label: "Arbitrum", family: "ng5", router: "0x2191718CD32d02B8E60BAdFFeA33E4B5DD9A0A0D", version: "1.1.0", codeHash: "0x9b387b5dc8fe161c7af8e850a67662e93d7116b0e66ab6bc7761d5910093bcef", weth: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", addressProvider: AP, addressProviderRouter: "0x2191718CD32d02B8E60BAdFFeA33E4B5DD9A0A0D" }),
93
+ 8453: d({ label: "Base", family: "ng5", router: R_BASE_MANTLE, version: "1.1.0", codeHash: "0x3abb7fe467b6c925ab1b25771cf1c75cc507aec2f873a8d03ee95160c5a83579", weth: OP_WETH, addressProvider: AP, addressProviderRouter: R_BASE_MANTLE }),
94
+ 10: d({ label: "OP Mainnet", family: "ng5", router: R_OP_POLY_GNO_AVAX, version: "1.1.0", codeHash: "0x12ae037c1e9a21aeb6ba1b08863217de2babebbee58dbe8860a01ded6a974825", weth: OP_WETH, addressProvider: AP, addressProviderRouter: R_OP_POLY_GNO_AVAX }),
95
+ 137: d({ label: "Polygon", family: "ng5", router: R_OP_POLY_GNO_AVAX, version: "1.1.0", codeHash: "0x340f3ba3f30181c50e694f1a4da2f6ec670fc7eb0adce50d66a733f17ab150f4", weth: "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", addressProvider: AP, addressProviderRouter: R_OP_POLY_GNO_AVAX }),
96
+ 100: d({ label: "Gnosis", family: "ng5", router: R_OP_POLY_GNO_AVAX, version: "1.1.0", codeHash: "0x38dc1cc456be010539e596d2ee0aa82c271316bdc6daaaffea7990a0c47176ee", weth: "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d", addressProvider: AP, addressProviderRouter: R_OP_POLY_GNO_AVAX }),
97
+ 43114: d({ label: "Avalanche", family: "ng5", router: R_OP_POLY_GNO_AVAX, version: "1.1.0", codeHash: "0xf1f679ec6382cd9c0138870e320e6128193f75144501691e67dcd5831edaed2b", weth: "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", addressProvider: AP, addressProviderRouter: R_OP_POLY_GNO_AVAX }),
98
+ 56: d({ label: "BNB Chain", family: "ng5", router: "0xA72C85C258A81761433B4e8da60505Fe3Dd551CC", version: "1.1.0", codeHash: "0x19db989a1cca08711ff68049326a5a7a8d1f64d87f356d35243150215c722120", weth: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", addressProvider: AP, addressProviderRouter: "0xA72C85C258A81761433B4e8da60505Fe3Dd551CC" }),
99
+ // [4][5] routers (curve-core, NG pools only, no swap_type 9).
100
+ 146: d({ label: "Sonic", family: "lite4", router: "0x5eeE3091f747E60a045a2E715a4c71e600e31F6E", version: "1.1.0", codeHash: "0xc5f238aee45c18efc927708fe57821cca4a84ec1bff4f22e778dfcd108411b99", weth: "0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38", addressProvider: "0x87FE17697D0f14A222e8bEf386a0860eCffDD617", addressProviderRouter: "0x5eeE3091f747E60a045a2E715a4c71e600e31F6E" }),
101
+ 130: d({ label: "Unichain", family: "lite4", router: R_UNI_HYPER, version: "1.1.0", codeHash: "0xe911928fab7efb72e10ee3a918dcdfb44ac5bae1c4d46eb5534bea0259d2594c", weth: OP_WETH, addressProvider: AP_UNI_HYPER, addressProviderRouter: R_UNI_HYPER }),
102
+ 999: d({ label: "HyperEVM", family: "lite4", router: R_UNI_HYPER, version: "1.1.0", codeHash: "0x1040124f623348643d919029ed513670cdb825bd0135f846ce9028329d8eb77d", weth: "0x5555555555555555555555555555555555555555", addressProvider: AP_UNI_HYPER, addressProviderRouter: R_UNI_HYPER }),
103
+ 5e3: d({ label: "Mantle", family: "lite4", router: R_BASE_MANTLE, version: "1.1.0", codeHash: "0xe76d585fb4163cd886c99f1c12361c5644e18b8dab2d86e3fe223307e7a16f29", weth: "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8", addressProvider: AP, addressProviderRouter: R_BASE_MANTLE }),
104
+ 143: d({ label: "Monad", family: "lite4", router: R_MONAD_PLASMA_RH, version: "1.1.0", codeHash: "0x7668fc406894fb811ab7f9a1099f2e33ef8d80f58327e623bbe4c4d51e406f58", weth: "0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A", addressProvider: AP_MONAD_PLASMA_RH, addressProviderRouter: R_MONAD_PLASMA_RH }),
105
+ 9745: d({ label: "Plasma", family: "lite4", router: R_MONAD_PLASMA_RH, version: "1.1.0", codeHash: "0xeede894a379cb95c73ece834e836ff9bbaa1ff613fb7913d0cbc3a48b2897120", weth: "0x6100E367285b01F48D07953803A2d8dCA5D19873", addressProvider: AP_MONAD_PLASMA_RH, addressProviderRouter: R_MONAD_PLASMA_RH }),
106
+ // v1.1.1: ETH_ADDRESS is a constructor immutable — 0xEeee… here, read from the code tail with WETH_ADDRESS.
107
+ 4663: d({ label: "Robinhood Chain", family: "lite4", router: R_MONAD_PLASMA_RH, version: "1.1.1", codeHash: "0x716ad3720f54c96effe415598d3a62b9907e53c58c7e3d3004cba6cdb5c297a6", weth: "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73", eth: CURVE_ETH, addressProvider: AP_MONAD_PLASMA_RH, addressProviderRouter: R_MONAD_PLASMA_RH }),
108
+ 57073: d({ label: "Ink", family: "lite4", router: "0xd7E72f3615aa65b92A4DBdC211E296a35512988B", version: "1.1.0", codeHash: "0x511c1733063263ba386b0e6b01b51d777deb02ea1b6e75fcde1e572e47f22436", weth: OP_WETH, addressProvider: "0x604388Bb1159AFd21eB5191cE22b4DeCdEE2Ae22", addressProviderRouter: "0xd7E72f3615aa65b92A4DBdC211E296a35512988B" }),
109
+ 196: d({ label: "X Layer", family: "lite4", router: "0xBFab8ebc836E1c4D81837798FC076D219C9a1855", version: "1.1.0", codeHash: "0xfc0a3b12868c10a8a46e33f17504f8751c83d3842f715c665c3d827bfc4ed625", weth: "0xe538905cf8410324e03A5A23C1c177a474D59b2b", addressProvider: AP, addressProviderRouter: "0xBFab8ebc836E1c4D81837798FC076D219C9a1855" }),
110
+ 98866: d({ label: "Plume", family: "lite4", router: "0x3F5A41B922a76759b9C77D36b3d337E88cD1dc5e", version: "1.1.0", codeHash: "0x0819b95039f1e0ac56aefffc8a727e996b3afa831fd3bb2047a3737bf23ab5e4", weth: "0xEa237441c92CAe6FC17Caaf9a7acB3f953be4bd1", addressProvider: "0x907CE289E9Ee0BBcb0F69132B1C28A9Affc29FCA", addressProviderRouter: "0x3F5A41B922a76759b9C77D36b3d337E88cD1dc5e" })
111
+ });
112
+ var CURVE_LEGACY_ROUTERS = Object.freeze({
113
+ 1: Object.freeze([
114
+ { router: "0x16C6521Dff6baB339122a0FE25a9116693265353", version: "1.1.0", codeHash: "0xf041e5b17dc8b2c417a9561eb265145e442ab25b789d9bd3527c6b68a840577b" },
115
+ { router: "0xF0d4c12A5768D806021F80a262B4d39d26C58b8D", version: "1.0.0", codeHash: "0xdfc206a29f04b4cee5b7b8d5b60ffcd2574fc9ff17cc5ec00c58b17013ea3f3b" }
116
+ ])
117
+ });
118
+ var CURVE_DENIED_POOLS = Object.freeze({
119
+ 1: /* @__PURE__ */ new Set([
120
+ "0xa6d9f4f3a67b35e81dfa560b0fcde9b0751f1f53",
121
+ "0xc4c319e2d4d66cca4464c0c2b32c9bd23ebe784e",
122
+ "0x9848482da3ee3076165ce6497eda906e66bb85c5",
123
+ "0xc897b98272aa23714464ea2a0bd5180f1b8c0025",
124
+ "0x8301ae4fc9c624d1d396cbdaa1ed877821d7c511",
125
+ "0x2dded6da1bf5dbdf597c45fcfaa3194e53ecfeaf"
126
+ ]),
127
+ 137: /* @__PURE__ */ new Set([
128
+ "0xc2d95eef97ec6c17551d45e77b590dc1f9117c67"
129
+ ])
130
+ });
131
+ function chainIdOf(caip2) {
132
+ return /^eip155:[0-9]+$/.test(caip2) ? Number(caip2.slice(7)) : NaN;
133
+ }
134
+ function deploymentOf(table, chainId) {
135
+ return Object.prototype.hasOwnProperty.call(table, chainId) ? table[chainId] : void 0;
136
+ }
137
+
138
+ // src/abi.ts
139
+ var import_viem = require("viem");
140
+ var ROUTER_NG5_ABI = (0, import_viem.parseAbi)([
141
+ "function exchange(address[11] _route, uint256[5][5] _swap_params, uint256 _amount, uint256 _min_dy) payable returns (uint256)",
142
+ "function exchange(address[11] _route, uint256[5][5] _swap_params, uint256 _amount, uint256 _min_dy, address[5] _pools) payable returns (uint256)",
143
+ "function exchange(address[11] _route, uint256[5][5] _swap_params, uint256 _amount, uint256 _min_dy, address[5] _pools, address _receiver) payable returns (uint256)",
144
+ "function get_dy(address[11] _route, uint256[5][5] _swap_params, uint256 _amount) view returns (uint256)",
145
+ "function version() view returns (string)"
146
+ ]);
147
+ var ROUTER_LITE4_ABI = (0, import_viem.parseAbi)([
148
+ "function exchange(address[11] _route, uint256[4][5] _swap_params, uint256 _amount, uint256 _min_dy) payable returns (uint256)",
149
+ "function exchange(address[11] _route, uint256[4][5] _swap_params, uint256 _amount, uint256 _min_dy, address _receiver) payable returns (uint256)",
150
+ "function get_dy(address[11] _route, uint256[4][5] _swap_params, uint256 _amount) view returns (uint256)",
151
+ "function version() view returns (string)"
152
+ ]);
153
+ var VERSION_ABI = (0, import_viem.parseAbi)(["function version() view returns (string)"]);
154
+ var COINS_UINT = "0xc6610657";
155
+ var COINS_INT = "0x23746eb8";
156
+ var ADDRESS_PROVIDER_ABI = (0, import_viem.parseAbi)(["function get_address(uint256 _id) view returns (address)"]);
157
+ var EXCHANGE_SELECTOR = Object.freeze({ ng5: "0xc872a3c5", lite4: "0xfd44959c" });
158
+ var GET_DY_SELECTOR = Object.freeze({ ng5: "0x81889a2c", lite4: "0x11e21386" });
159
+ var ROUTER_SELECTORS = Object.freeze({
160
+ ng5: /* @__PURE__ */ new Set(["0x371dc447", "0x5c9c18e2", "0xc872a3c5"]),
161
+ lite4: /* @__PURE__ */ new Set(["0xaad348a2", "0xfd44959c"])
162
+ });
163
+ var EXCHANGE_TOPIC = Object.freeze({
164
+ ng5: "0x56d0661e240dfb199ef196e16e6f42473990366314f0226ac978f7be3cd9ee83",
165
+ lite4: "0x6324485a21bc5138ec352d4949d0adc75d8e1382a687e1aa1ce6863f40c9e463"
166
+ });
167
+ var ZERO_POOLS = Object.freeze([ZERO_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS]);
168
+ var tuple11 = (a) => a;
169
+ var rows5 = (p) => p;
170
+ var rows4 = (p) => p;
171
+ var pools5 = (a) => a;
172
+ function checkShape(family, args) {
173
+ const cols = family === "ng5" ? 5 : 4;
174
+ if (args.route.length !== 11 || args.params.length !== 5 || args.params.some((r) => r.length !== cols)) {
175
+ throw new Error(`curve: a ${family} route is address[11] and uint256[${cols}][5]`);
176
+ }
177
+ }
178
+ function encodeExchange(family, args, amount, minDy, receiver) {
179
+ checkShape(family, args);
180
+ return family === "ng5" ? (0, import_viem.encodeFunctionData)({ abi: ROUTER_NG5_ABI, functionName: "exchange", args: [tuple11(args.route), rows5(args.params), amount, minDy, pools5(ZERO_POOLS), receiver] }) : (0, import_viem.encodeFunctionData)({ abi: ROUTER_LITE4_ABI, functionName: "exchange", args: [tuple11(args.route), rows4(args.params), amount, minDy, receiver] });
181
+ }
182
+ function encodeGetDy(family, args, amount) {
183
+ checkShape(family, args);
184
+ return family === "ng5" ? (0, import_viem.encodeFunctionData)({ abi: ROUTER_NG5_ABI, functionName: "get_dy", args: [tuple11(args.route), rows5(args.params), amount] }) : (0, import_viem.encodeFunctionData)({ abi: ROUTER_LITE4_ABI, functionName: "get_dy", args: [tuple11(args.route), rows4(args.params), amount] });
185
+ }
186
+ function decodeExchange(family, data) {
187
+ if (!/^0x[0-9a-fA-F]*$/.test(data) || data.length < 10) return null;
188
+ const selector = data.slice(0, 10).toLowerCase();
189
+ if (!ROUTER_SELECTORS[family].has(selector)) return null;
190
+ try {
191
+ if (family === "ng5") {
192
+ const c2 = (0, import_viem.decodeFunctionData)({ abi: ROUTER_NG5_ABI, data });
193
+ if (c2.functionName !== "exchange") return null;
194
+ const a2 = c2.args;
195
+ return {
196
+ selector,
197
+ route: a2[0],
198
+ params: a2[1],
199
+ amount: a2[2],
200
+ minDy: a2[3],
201
+ pools: a2.length >= 5 ? a2[4] : null,
202
+ receiver: a2.length >= 6 ? a2[5] : null
203
+ };
204
+ }
205
+ const c = (0, import_viem.decodeFunctionData)({ abi: ROUTER_LITE4_ABI, data });
206
+ if (c.functionName !== "exchange") return null;
207
+ const a = c.args;
208
+ return {
209
+ selector,
210
+ route: a[0],
211
+ params: a[1],
212
+ amount: a[2],
213
+ minDy: a[3],
214
+ pools: null,
215
+ receiver: a.length >= 5 ? a[4] : null
216
+ };
217
+ } catch {
218
+ return null;
219
+ }
220
+ }
221
+
222
+ // src/routes.ts
223
+ var import_viem2 = require("viem");
224
+ var import_swap2_assets = require("@anywalletkit/swap2-assets");
225
+ var MAX_QUOTE_CANDIDATES = 30;
226
+ var MAX_EXPLORED = 2e4;
227
+ var lc = (a) => a.toLowerCase();
228
+ var STABLE_POOL_TYPES = /* @__PURE__ */ new Set([1, 10]);
229
+ function intermediateAllowed(chainId, deployment, token) {
230
+ const t = lc(token);
231
+ if (t === lc(deployment.eth)) return true;
232
+ if (t === lc(deployment.weth)) return t !== lc(ZERO_ADDRESS);
233
+ if (!/^0x[0-9a-f]{40}$/.test(t) || t === lc(ZERO_ADDRESS)) return false;
234
+ const listed = (0, import_swap2_assets.ccAssetByToken)(`eip155:${chainId}`, t);
235
+ return !!listed?.contract && lc(listed.contract) === t;
236
+ }
237
+ function underlyingAllowed(pool, index) {
238
+ const under = pool.underlying;
239
+ if (!under || under.length < 2 || !pool.swapTypes.includes(2)) return false;
240
+ if (!pool.basePool) return false;
241
+ const base = index.get(lc(pool.basePool));
242
+ if (!base || base === pool) return false;
243
+ const meta = pool.coins.length - 1;
244
+ if (under.length !== meta + base.coins.length) return false;
245
+ return under.every((c, k) => lc(c) === lc(k < meta ? pool.coins[k] : base.coins[k - meta]));
246
+ }
247
+ function poolTypeAllowed(family, poolType) {
248
+ return family === "ng5" ? [1, 2, 3, 10, 20, 30].includes(poolType) : [10, 20, 30].includes(poolType);
249
+ }
250
+ var graphs = /* @__PURE__ */ new WeakMap();
251
+ function poolIndex(chainId, deployment, table) {
252
+ return graphFor(chainId, deployment, table).byAddress;
253
+ }
254
+ function graphFor(chainId, deployment, table) {
255
+ if (!table) return { edges: /* @__PURE__ */ new Map(), byAddress: /* @__PURE__ */ new Map() };
256
+ let perDeployment = graphs.get(table);
257
+ if (!perDeployment) graphs.set(table, perDeployment = /* @__PURE__ */ new WeakMap());
258
+ let g = perDeployment.get(deployment);
259
+ if (g) return g;
260
+ g = { edges: /* @__PURE__ */ new Map(), byAddress: /* @__PURE__ */ new Map() };
261
+ const denied = CURVE_DENIED_POOLS[chainId];
262
+ const eth = lc(deployment.eth);
263
+ const add = (s) => {
264
+ const k = lc(s.tokenIn);
265
+ const list = g.edges.get(k);
266
+ if (list) list.push(s);
267
+ else g.edges.set(k, [s]);
268
+ };
269
+ for (const pool of table.chainId === chainId ? table.pools : []) {
270
+ const key = lc(pool.address);
271
+ if (denied?.has(key) || g.byAddress.has(key) || !poolTypeAllowed(deployment.family, pool.poolType)) continue;
272
+ if (!/^0x[0-9a-fA-F]{40}$/.test(pool.address) || pool.coins.length < 2 || pool.coins.length > 8) continue;
273
+ if (deployment.family === "lite4" && [...pool.coins, ...pool.underlying ?? []].some((c) => lc(c) === eth)) continue;
274
+ g.byAddress.set(key, pool);
275
+ }
276
+ for (const pool of g.byAddress.values()) {
277
+ const pairs = /* @__PURE__ */ new Set();
278
+ if (pool.swapTypes.includes(1)) {
279
+ pool.coins.forEach((a, i) => pool.coins.forEach((b, j) => {
280
+ if (i === j || lc(a) === lc(b)) return;
281
+ pairs.add(`${lc(a)}>${lc(b)}`);
282
+ add({ kind: "pool", pool, swapType: 1, i, j, tokenIn: (0, import_viem2.getAddress)(a), tokenOut: (0, import_viem2.getAddress)(b) });
283
+ }));
284
+ }
285
+ const under = pool.underlying;
286
+ if (under && underlyingAllowed(pool, g.byAddress) && (deployment.family === "ng5" || pool.poolType === 10)) {
287
+ under.forEach((a, i) => under.forEach((b, j) => {
288
+ if (i === j || lc(a) === lc(b) || pairs.has(`${lc(a)}>${lc(b)}`)) return;
289
+ add({ kind: "pool", pool, swapType: 2, i, j, tokenIn: (0, import_viem2.getAddress)(a), tokenOut: (0, import_viem2.getAddress)(b) });
290
+ }));
291
+ }
292
+ }
293
+ if (lc(deployment.weth) !== lc(ZERO_ADDRESS)) {
294
+ add({ kind: "wrap", weth: (0, import_viem2.getAddress)(deployment.weth), tokenIn: (0, import_viem2.getAddress)(deployment.eth), tokenOut: (0, import_viem2.getAddress)(deployment.weth) });
295
+ add({ kind: "wrap", weth: (0, import_viem2.getAddress)(deployment.weth), tokenIn: (0, import_viem2.getAddress)(deployment.weth), tokenOut: (0, import_viem2.getAddress)(deployment.eth) });
296
+ }
297
+ const v = erc4626Of(deployment);
298
+ if (v) {
299
+ add({ kind: "erc4626", vault: (0, import_viem2.getAddress)(v.vault), deposit: true, tokenIn: (0, import_viem2.getAddress)(v.asset), tokenOut: (0, import_viem2.getAddress)(v.vault) });
300
+ add({ kind: "erc4626", vault: (0, import_viem2.getAddress)(v.vault), deposit: false, tokenIn: (0, import_viem2.getAddress)(v.vault), tokenOut: (0, import_viem2.getAddress)(v.asset) });
301
+ }
302
+ perDeployment.set(deployment, g);
303
+ return g;
304
+ }
305
+ function erc4626Of(d2) {
306
+ return d2.erc4626 && d2.family === "ng5" && d2.version === "1.2.0" ? d2.erc4626 : void 0;
307
+ }
308
+ var minTvl = (r) => r.reduce((m, s) => s.kind === "pool" ? Math.min(m, s.pool.tvlUsd) : m, Number.POSITIVE_INFINITY);
309
+ var poolCount = (r) => r.filter((s) => s.kind === "pool").length;
310
+ function findRoutes(chainId, deployment, table, tokenIn, tokenOut, limit = MAX_QUOTE_CANDIDATES) {
311
+ const g = graphFor(chainId, deployment, table);
312
+ const want = lc(tokenOut);
313
+ const found = [];
314
+ let explored = 0;
315
+ let exhausted = false;
316
+ const walk = (at, path, seenTokens, seenPools) => {
317
+ if (exhausted) return;
318
+ for (const s of g.edges.get(at) ?? []) {
319
+ if (++explored > MAX_EXPLORED) {
320
+ exhausted = true;
321
+ return;
322
+ }
323
+ const next = lc(s.tokenOut);
324
+ if (seenTokens.has(next)) continue;
325
+ if (next !== want && !intermediateAllowed(chainId, deployment, next)) continue;
326
+ if (s.kind === "pool" && (seenPools.has(lc(s.pool.address)) || poolCount(path) >= MAX_ROUTE_POOLS)) continue;
327
+ if (s.kind !== "pool" && path.some((p) => p.kind === s.kind)) continue;
328
+ const steps = [...path, s];
329
+ if (next === want) {
330
+ if (poolCount(steps) > 0 || steps.some((x) => x.kind === "erc4626")) found.push(steps);
331
+ continue;
332
+ }
333
+ if (steps.length >= MAX_ROUTE_STEPS) continue;
334
+ seenTokens.add(next);
335
+ if (s.kind === "pool") seenPools.add(lc(s.pool.address));
336
+ walk(next, steps, seenTokens, seenPools);
337
+ seenTokens.delete(next);
338
+ if (s.kind === "pool") seenPools.delete(lc(s.pool.address));
339
+ }
340
+ };
341
+ walk(lc(tokenIn), [], /* @__PURE__ */ new Set([lc(tokenIn)]), /* @__PURE__ */ new Set());
342
+ found.sort((a, b) => poolCount(a) - poolCount(b) || minTvl(b) - minTvl(a) || a.length - b.length);
343
+ return { routes: found.slice(0, limit).map((steps) => ({ steps, label: labelOf(steps) })), truncated: exhausted || found.length > limit };
344
+ }
345
+ function labelOf(steps) {
346
+ return steps.map((s) => s.kind === "pool" ? `${s.pool.name}${s.swapType === 2 ? " (underlying)" : ""}` : s.kind === "wrap" ? s.tokenOut === s.weth ? "wrap" : "unwrap" : s.deposit ? "scrvUSD deposit" : "scrvUSD redeem").join(" \u2192 ");
347
+ }
348
+ function routeArgs(family, route) {
349
+ if (route.steps.length < 1 || route.steps.length > MAX_ROUTE_STEPS) throw new Error(`curve: a route has 1\u2013${MAX_ROUTE_STEPS} steps`);
350
+ const path = [route.steps[0].tokenIn];
351
+ const params = [];
352
+ for (const s of route.steps) {
353
+ const swap = s.kind === "pool" ? s.pool.address : s.kind === "wrap" ? s.weth : s.vault;
354
+ path.push((0, import_viem2.getAddress)(swap), s.tokenOut);
355
+ const row = s.kind === "pool" ? [BigInt(s.i), BigInt(s.j), BigInt(s.swapType), BigInt(s.pool.poolType), BigInt((s.swapType === 2 ? s.pool.underlying : s.pool.coins).length)] : s.kind === "wrap" ? [0n, 0n, 8n, 0n, 0n] : [s.deposit ? 0n : 1n, 0n, 9n, 0n, 0n];
356
+ params.push(family === "ng5" ? row : row.slice(0, 4));
357
+ }
358
+ while (path.length < 11) path.push(ZERO_ADDRESS);
359
+ const cols = family === "ng5" ? 5 : 4;
360
+ while (params.length < 5) params.push(new Array(cols).fill(0n));
361
+ return { route: path, params };
362
+ }
363
+ function routePools(args) {
364
+ const out = [];
365
+ for (let k = 0; k < 5; k++) {
366
+ const swap = args.route[2 * k + 1];
367
+ const t = args.params[k]?.[2];
368
+ if (!swap || lc(swap) === lc(ZERO_ADDRESS)) break;
369
+ if (t === 1n || t === 2n) out.push(swap);
370
+ }
371
+ return out;
372
+ }
373
+ function checkRoute(chainId, deployment, table, args, tokenIn, tokenOut) {
374
+ 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]`;
376
+ const index = poolIndex(chainId, deployment, table);
377
+ const zero = lc(ZERO_ADDRESS);
378
+ const eth = lc(deployment.eth);
379
+ const weth = lc(deployment.weth);
380
+ const v = erc4626Of(deployment);
381
+ let steps = 0;
382
+ 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`;
389
+ 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`;
391
+ }
392
+ const pools = /* @__PURE__ */ new Set();
393
+ let wraps = 0;
394
+ let vaults = 0;
395
+ for (let k = 0; k < steps; k++) {
396
+ const a = lc(args.route[2 * k]);
397
+ const swap = lc(args.route[2 * k + 1]);
398
+ const b = lc(args.route[2 * k + 2]);
399
+ const row = args.params[k];
400
+ const type = row[2];
401
+ if (a === b) return `step ${k + 1} trades a token for itself`;
402
+ 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)`;
404
+ 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`;
407
+ 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`;
412
+ const list = type === 1n ? pool.coins : pool.underlying;
413
+ if (!list) return `step ${k + 1}: pool ${pool.name} lists no underlying coins`;
414
+ 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`;
420
+ } 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";
426
+ } 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`;
429
+ const deposit = row[0] === 0n && a === lc(v.asset) && b === lc(v.vault);
430
+ 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";
434
+ } else {
435
+ return `step ${k + 1} uses swap_type ${type}, which this module never builds`;
436
+ }
437
+ }
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";
440
+ return null;
441
+ }
442
+
443
+ // src/provider.ts
444
+ var import_viem4 = require("viem");
445
+ var import_util5 = require("@anywalletkit/protocol-swap2-core/util");
446
+
447
+ // src/activity.ts
448
+ var import_activity = require("@anywalletkit/protocol-swap2-core/activity");
449
+ var import_util = require("@anywalletkit/protocol-swap2-core/util");
450
+ var CURVE_MODULE = "@anywalletkit/protocol-swap2-curve";
451
+ function familyOf(deployments, chainId, to) {
452
+ const d2 = deploymentOf(deployments, chainId);
453
+ if (d2 && d2.router.toLowerCase() === to) return d2.family;
454
+ const legacy = Object.prototype.hasOwnProperty.call(CURVE_LEGACY_ROUTERS, chainId) ? CURVE_LEGACY_ROUTERS[chainId] : [];
455
+ return legacy.some((r) => r.router.toLowerCase() === to) ? "ng5" : null;
456
+ }
457
+ function receiverOf(tx, family) {
458
+ const data = tx.call?.data;
459
+ if (data) {
460
+ const call = decodeExchange(family, data);
461
+ if (call?.receiver) return call.receiver.toLowerCase();
462
+ if (call) return tx.from.toLowerCase();
463
+ }
464
+ const logs = tx.raw?.logs ?? tx.raw?.receipt?.logs;
465
+ if (Array.isArray(logs)) {
466
+ const to = (0, import_activity.calledContract)(tx);
467
+ for (const l of logs) {
468
+ if (l?.address?.toLowerCase() !== to || l.topics?.[0]?.toLowerCase() !== EXCHANGE_TOPIC[family]) continue;
469
+ const t = l.topics[2];
470
+ if (typeof t === "string" && /^0x[0-9a-fA-F]{64}$/.test(t)) return `0x${t.slice(-40)}`.toLowerCase();
471
+ }
472
+ }
473
+ return tx.from.toLowerCase();
474
+ }
475
+ function describeCurveActivity(tx, ctx, deployments = CURVE_DEPLOYMENTS) {
476
+ if (!(0, import_util.isEvm)(tx.chain)) return null;
477
+ const to = (0, import_activity.calledContract)(tx);
478
+ if (!to) return null;
479
+ const family = familyOf(deployments, (0, import_util.evmRef)(tx.chain), to);
480
+ if (!family) return null;
481
+ const sel = tx.call?.selector?.toLowerCase() ?? tx.call?.data?.slice(0, 10).toLowerCase();
482
+ if (!sel || !ROUTER_SELECTORS[family].has(sel)) return null;
483
+ const receiver = receiverOf(tx, family);
484
+ const ownReceiver = ctx.own.has(receiver) || [...ctx.own].some((a) => a.toLowerCase() === receiver);
485
+ const subtitle = `Curve \xB7 ${(0, import_activity.chainLabel)(tx.chain)}${ownReceiver ? "" : ` \xB7 paid to ${(0, import_activity.shortAddress)(receiver)}`}`;
486
+ return (0, import_activity.describeSwapLike)(tx, ctx, { protocol: CURVE_MODULE, subtitle, kind: "swap", ...ownReceiver ? {} : { counterparty: receiver } });
487
+ }
488
+
489
+ // src/pools/1.ts
490
+ var POOLS_1 = {
491
+ chainId: 1,
492
+ builtAt: "2026-11-05",
493
+ block: 26350656,
494
+ pools: [
495
+ { address: "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", name: "Curve.fi DAI/USDC/USDT", coins: ["0x6B175474E89094C44Da98b954EedeAC495271d0F", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xdAC17F958D2ee523a2206206994597C13D831ec7"], decimals: [18, 6, 6], poolType: 1, swapTypes: [1], codeHash: "0x954a1e212c557c85043985931498ffa3e2fcbe7dfe9cd61513f36eb47d6f4dfc", tvlUsd: 161890942, createdAt: 1599422178 },
496
+ { address: "0xDC24316b9AE028F1497c275EB9192a3Ea0f67022", name: "Curve.fi ETH/stETH", coins: ["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84"], decimals: [18, 18], poolType: 1, swapTypes: [1], codeHash: "0xe2c45ce8268580c40b4c12c574f8a210375ab92998c1555451fef63630e96b35", tvlUsd: 85454194, createdAt: 1609827515 },
497
+ { address: "0x862CB4E988FB66E72f128d1183829f8c05B6c6A0", name: "Yield Basis cbBTC", coins: ["0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E", "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf"], decimals: [18, 8], poolType: 20, swapTypes: [1], codeHash: "0xd19e3a232367411c825df98165c95898c08e181fe2e0f9211445f48eb4c0dc62", tvlUsd: 54490963, createdAt: 1779393887 },
498
+ { address: "0x313698667d7FDD6789a9BC70821309ff891E729A", name: "Yield Basis WBTC", coins: ["0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E", "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"], decimals: [18, 8], poolType: 20, swapTypes: [1], codeHash: "0xe4ac67017f888827e6efe22cd8edc37bf562166368f6eb62837bff2e4a4a23e8", tvlUsd: 48858088, createdAt: 1779393875 },
499
+ { address: "0xD001aE433f254283FeCE51d4ACcE8c53263aa186", name: "RLUSD/USDC", coins: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0x8292Bb45bf1Ee4d140127049757C2E0fF06317eD"], decimals: [6, 18], poolType: 10, swapTypes: [1], codeHash: "0x0e07a882cbde1fe43a2023b573596d0688cd4511bb04cbff49f1d9cceab84888", tvlUsd: 39310146, createdAt: 1734614699 },
500
+ { address: "0xcc7d5785AD5755B6164e21495E07aDb0Ff11C2A8", name: "OETH/WETH", coins: ["0x856c4Efb76C1D1AE02e20CEB03A2A6a08b0b8dC3", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"], decimals: [18, 18], poolType: 10, swapTypes: [1], codeHash: "0x8b33e4c54cca2b340c5ac61ac287ecd06cfab84979e63c1260683abcc06f8138", tvlUsd: 38072502, createdAt: 1742850227 },
501
+ { address: "0x4F52C3a81E33521e5a9A47FD9D3BE475D2279c2e", name: "Yield Basis tBTC", coins: ["0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E", "0x18084fbA666a33d37592fA2633fD49a74DD93a88"], decimals: [18, 18], poolType: 20, swapTypes: [1], codeHash: "0xaefafc4c0157bc496db238fc46d730a140174f3fb542527bb86443974ed4f7a6", tvlUsd: 35972318, createdAt: 1779393911 },
502
+ { address: "0x656341Ef90b622c6634e0573772FfB7f3669b9f3", name: "Yield Basis WETH", coins: ["0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"], decimals: [18, 18], poolType: 20, swapTypes: [1], codeHash: "0x116eeee684882885cda3ddf0287d0979f71d64030fbec90f1f52924cf0e7643a", tvlUsd: 29312833, createdAt: 1779393923 },
503
+ { address: "0x21E27a5E5513D6e65C4f830167390997aA84843a", name: "Curve.fi Factory Pool: stETH-ng", coins: ["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84"], decimals: [18, 18], poolType: 1, swapTypes: [1], codeHash: "0x9e28a09452d2354fc4e15e3244dde27cbc4d52f12a10b91f2ca755b672bfa9be", tvlUsd: 21919007, createdAt: 1684243259 },
504
+ { address: "0xc061caa073f3d95F80f8e5428d32D2d76F5e1622", name: "USDG/USDC", coins: ["0xe343167631d89B6Ffc58B88d6b7fB0228795491D", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], decimals: [6, 6], poolType: 10, swapTypes: [1], codeHash: "0x1c7b77a94bb42408ab6d5cfd76223f0c794db9b119bb6035db91d8b09da65512", tvlUsd: 20042556, createdAt: 1757337995 },
505
+ { address: "0xC2921134073151490193AC7369313c8e0b08e1E7", name: "USDtb-USDC", coins: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xC139190F447e929f090Edeb554D95AbB8b18aC1C"], decimals: [6, 18], poolType: 10, swapTypes: [1], codeHash: "0x003569f063c00de15be2ce5934449342555e009ef7ba9894ef84d302602b186f", tvlUsd: 19974424, createdAt: 1733348927 },
506
+ { address: "0x83f24023d15d835a213df24fd309c47dAb5BEb32", name: "YB cbBTC", coins: ["0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E", "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf"], decimals: [18, 8], poolType: 20, swapTypes: [1], codeHash: "0xb00ba7467a75fffe15d018cc822a09b282a285f4012f857b19966046b3191b3a", tvlUsd: 17762242, createdAt: 1758723599 },
507
+ { address: "0x5dc1BF6f1e983C0b21EfB003c105133736fA0743", name: "FRAXUSDe", coins: ["0x853d955aCEf822Db058eb8505911ED77F175b99e", "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3"], decimals: [18, 18], poolType: 10, swapTypes: [1], codeHash: "0x6aa12bb9b18854a3f453e240d7e960190a32f1c16a8e268a90a66c8a95fe3a86", tvlUsd: 16042488, createdAt: 1702770299 },
508
+ { address: "0x13e12BB0E6A2f1A3d6901a59a9d585e89A6243e1", name: "crvUSD/frxUSD", coins: ["0xCAcd6fd266aF91b8AeD52aCCc382b4e165586E29", "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E"], decimals: [18, 18], poolType: 10, swapTypes: [1], codeHash: "0x6de2b24d7a8852d96955f6873f16402e61b5d9f3aff037f62a2004fecf31ce83", tvlUsd: 13934470, createdAt: 1752006431 },
509
+ { address: "0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E", name: "Curve.fi Factory Plain Pool: crvUSD/USDC", coins: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E"], decimals: [6, 18], poolType: 1, swapTypes: [1], codeHash: "0x06a0d9fefe2940f35a5e0b347ff8e2f8085c76ce487b5b234b2e3c831160e34f", tvlUsd: 13078629, createdAt: 1684066067 },
510
+ { address: "0xEd279fDD11cA84bEef15AF5D39BB4d4bEE23F0cA", name: "Curve.fi Factory USD Metapool: Liquity", coins: ["0x5f98805A4E8be255a32880FDeC7F6728C6568bA0", "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"], decimals: [18, 18], underlying: ["0x5f98805A4E8be255a32880FDeC7F6728C6568bA0", "0x6B175474E89094C44Da98b954EedeAC495271d0F", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xdAC17F958D2ee523a2206206994597C13D831ec7"], underlyingDecimals: [18, 18, 6, 6], basePool: "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", poolType: 1, swapTypes: [1, 2], codeHash: "0x156700a4060f3d62786914b50cc60b2b840e6440401bea9a99c0acce0b58beda", tvlUsd: 12967284, createdAt: 1617702355 },
511
+ { address: "0xf5f5B97624542D72A9E06f04804Bf81baA15e2B4", name: "TricryptoUSDT", coins: ["0xdAC17F958D2ee523a2206206994597C13D831ec7", "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"], decimals: [6, 8, 18], poolType: 30, swapTypes: [1], codeHash: "0xe5a06bd0c8f12bc66b551b99a34cdd7d2a286a53b778244c930a8f6db01fef40", tvlUsd: 12898e3, createdAt: 1685482703 },
512
+ { address: "0x4d9f9D15101EEC665F77210cB999639f760F831E", name: "Curve.fi Factory Plain Pool: stETH/frxETH", coins: ["0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84", "0x5E8422345238F34275888049021821E8E08CAa1f"], decimals: [18, 18], poolType: 1, swapTypes: [1], codeHash: "0x8d287c58712fcd24b18f60f4a77a4a4d1a7a8bd10e3cb4c9d4752296b307aa51", tvlUsd: 12880550, createdAt: 1677059567 },
513
+ { address: "0x383E6b4437b59fff47B619CBA855CA29342A8559", name: "PayPool", coins: ["0x6c3ea9036406852006290770BEdFcAbA0e23A0e8", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], decimals: [6, 6], poolType: 10, swapTypes: [1], codeHash: "0x36356aefa486ac281df5aa3efb601b135b95da2c266bc4bf627aa6f4b4b22703", tvlUsd: 12266641, createdAt: 1703113055 },
514
+ { address: "0xD51a44d3FaE010294C616388b506AcdA1bfAAE46", name: "Curve.fi USD-BTC-ETH", coins: ["0xdAC17F958D2ee523a2206206994597C13D831ec7", "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"], decimals: [6, 8, 18], poolType: 3, swapTypes: [1], codeHash: "0x9cb858c1d8e8ab8ba7dc273f146d428965b0ca686d05fb02cb4ffc62149ec928", tvlUsd: 10625171, createdAt: 1626218283 },
515
+ { address: "0x390f3595bCa2Df7d23783dFd126427CCeb997BF4", name: "Curve.fi Factory Plain Pool: crvUSD/USDT", coins: ["0xdAC17F958D2ee523a2206206994597C13D831ec7", "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E"], decimals: [6, 18], poolType: 1, swapTypes: [1], codeHash: "0x06a0d9fefe2940f35a5e0b347ff8e2f8085c76ce487b5b234b2e3c831160e34f", tvlUsd: 9808682, createdAt: 1684066103 },
516
+ { address: "0xDB74dfDD3BB46bE8Ce6C33dC9D82777BCFc3dEd5", name: "weETH/WETH-ng", coins: ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee"], decimals: [18, 18], poolType: 10, swapTypes: [1], codeHash: "0xf9b0b2342e2132b069f65bb801081a730df7cf80b2ef5a8b9a3fc7a6324724f3", tvlUsd: 9757307, createdAt: 1713832907 },
517
+ { address: "0xB7ECB2AA52AA64a717180E030241bC75Cd946726", name: "Curve.fi Factory Plain Pool: tBTC/WBTC", coins: ["0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", "0x18084fbA666a33d37592fA2633fD49a74DD93a88"], decimals: [8, 18], poolType: 1, swapTypes: [1], codeHash: "0x06a0d9fefe2940f35a5e0b347ff8e2f8085c76ce487b5b234b2e3c831160e34f", tvlUsd: 8360462, createdAt: 1692136331 },
518
+ { address: "0x5018BE882DccE5E3F2f3B0913AE2096B9b3fB61f", name: "USDC/fxUSD", coins: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0x085780639CC2cACd35E474e71f4d000e2405d8f6"], decimals: [6, 18], poolType: 10, swapTypes: [1], codeHash: "0x4a0e13c96d5dddf3d9a22d3ad7b65e6735199e857996056cbc4718ef4869bb48", tvlUsd: 7959448, createdAt: 1719632039 },
519
+ { address: "0xB576491F1E6e5E62f1d8F26062Ee822B40B0E0d4", name: "Curve CVX-ETH", coins: ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B"], decimals: [18, 18], poolType: 2, swapTypes: [1], codeHash: "0x56ba0e921b89ed274e747d68fb8e49ba91fcc6fc4f7c1aaa5294c74b6a4b4d72", tvlUsd: 5926700, createdAt: 1639223635 },
520
+ { address: "0xEFc6516323FbD28e80B85A497B65A86243a54B3E", name: "BOLD/USDC Pool", coins: ["0x6440f144b7e50D6a8439336510312d2F54beB01D", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], decimals: [18, 6], poolType: 10, swapTypes: [1], codeHash: "0xd2c72b78d7d96bb962fa6429c4bb2e5dce6d92a5bc6712541ab76fe8e4570f07", tvlUsd: 5611794, createdAt: 1747597079 },
521
+ { address: "0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B", name: "TricryptoUSDC", coins: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"], decimals: [6, 8, 18], poolType: 30, swapTypes: [1], codeHash: "0xffceb70c60b48d7d02df8305161e44ec2454c1bc23fabc528e9a9ec71e4e7806", tvlUsd: 4972786, createdAt: 1685446211 },
522
+ { address: "0x0Bdb2c3AF83EE1d3196FA64d3162e54624B5f6b0", name: "USAT/USDT", coins: ["0x07041776f5007ACa2A54844F50503a18A72A8b68", "0xdAC17F958D2ee523a2206206994597C13D831ec7"], decimals: [6, 6], poolType: 10, swapTypes: [1], codeHash: "0x9d0252403d580a95341bbddbecea09bbe280bd4d87f28ee8531a01d33119ba01", tvlUsd: 4647056, createdAt: 1772798639 },
523
+ { address: "0xC09e82f81Cb811DB0922dD48206fc2e212322caf", name: "World Liberty USD1 Pool", coins: ["0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d", "0x4f493B7dE8aAC7d55F71853688b1F7C8F0243C85"], decimals: [18, 18], underlying: ["0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xdAC17F958D2ee523a2206206994597C13D831ec7"], underlyingDecimals: [18, 6, 6], basePool: "0x4f493B7dE8aAC7d55F71853688b1F7C8F0243C85", poolType: 10, swapTypes: [1, 2], codeHash: "0x25478b25c12a81937ddb75e0c5ed8ca8ab248a102316873d092f49ca870b8cca", tvlUsd: 4343338, createdAt: 1756668467 },
524
+ { address: "0x9c3B46C0Ceb5B9e304FCd6D88Fc50f7DD24B31Bc", name: "Curve.fi Factory Plain Pool: frxETH/WETH", coins: ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "0x5E8422345238F34275888049021821E8E08CAa1f"], decimals: [18, 18], poolType: 1, swapTypes: [1], codeHash: "0x06a0d9fefe2940f35a5e0b347ff8e2f8085c76ce487b5b234b2e3c831160e34f", tvlUsd: 4279560, createdAt: 1692135095 },
525
+ { address: "0x4f493B7dE8aAC7d55F71853688b1F7C8F0243C85", name: "Curve.fi Strategic USD Reserves", coins: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xdAC17F958D2ee523a2206206994597C13D831ec7"], decimals: [6, 6], poolType: 10, swapTypes: [1], codeHash: "0x5f0f1709fa823592ad75b27e32af00a8715d620dcb269be7c26fd5c873c1ce0e", tvlUsd: 4252884, createdAt: 1737825647 },
526
+ { address: "0x2889302a794dA87fBF1D6Db415C1492194663D13", name: "TricryptoLLAMA", coins: ["0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E", "0x18084fbA666a33d37592fA2633fD49a74DD93a88", "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"], decimals: [18, 18, 18], poolType: 30, swapTypes: [1], codeHash: "0x0c6780573f9c77a247365e2cbeae61fe0af7ea94ded696b5ee5e6462ce51b02e", tvlUsd: 4217439, createdAt: 1686845315 },
527
+ { address: "0x98a7F18d4E56Cfe84E3D081B40001B3d5bD3eB8B", name: "Curve EURS-USDC", coins: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xdB25f211AB05b1c97D595516F45794528a807ad8"], decimals: [6, 2], poolType: 2, swapTypes: [1], codeHash: "0x6c0b789b9f2ee0cbb53935cbe4f88e7d66401e1b4508514c097e7bd81e8ea931", tvlUsd: 3939896, createdAt: 1635766643 },
528
+ { address: "0x66039342C66760874047c36943B1e2d8300363BB", name: "HemiBTC/cbBTC/WBTC", coins: ["0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", "0x06ea695B91700071B161A434fED42D1DcbAD9f00"], decimals: [8, 8, 8], poolType: 10, swapTypes: [1], codeHash: "0x54a9f7fe4f6e0880c3e7f886d1a0500619b0539dd9d9067221a526ece460e6f7", tvlUsd: 3547580, createdAt: 1764180299 },
529
+ { address: "0xE521BA88837B2726E5343ccA91adA6f19F356C45", name: "USDx/USDT", coins: ["0xa1fA7777974312f7d801A8880714a218F76233f8", "0xdAC17F958D2ee523a2206206994597C13D831ec7"], decimals: [18, 6], poolType: 10, swapTypes: [1], codeHash: "0x74bb764c9dffe15ac160f6d01f6bdc1e4b03d39722083e674476ed6843c11d33", tvlUsd: 3020901, createdAt: 1788328955 },
530
+ { address: "0x6F63deEDc9870D6c16FC644C6654748352cdc87c", name: "apxUSD-USDC v3", coins: ["0x98A878b1Cd98131B271883B390f68D2c90674665", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], decimals: [18, 6], poolType: 10, swapTypes: [1], codeHash: "0xe511d7fa636d58614f82e35f2f333d1ed931f75baed8b7b89d2b1ef09825ef26", tvlUsd: 2796538, createdAt: 1785427007 },
531
+ { address: "0x4eBdF703948ddCEA3B11f675B4D1Fba9d2414A14", name: "TriCRV", coins: ["0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "0xD533a949740bb3306d119CC777fa900bA034cd52"], decimals: [18, 18, 18], poolType: 30, swapTypes: [1], codeHash: "0xf29fb95ca44fe2f979303e309cbaba61d44dd503fddeb111caae94e1b0857154", tvlUsd: 2439038, createdAt: 1690291775 },
532
+ { address: "0x04710a7B238386Da58EfAd8b65E150e5E17AA522", name: "USDC/sUSDat", coins: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xD166337499E176bbC38a1FBd113Ab144e5bd2Df7"], decimals: [6, 18], poolType: 20, swapTypes: [1], codeHash: "0x11ecb979f7468e539cb2ee92b8cf7c59d56b1c97b9fdce333fe1d35ac5c8e110", tvlUsd: 2187783, createdAt: 1785550511 },
533
+ { address: "0xE47E8Ced9D94AA43C922627782E29b41a93202AF", name: "FIDD/USDC", coins: ["0x7C135549504245B5eAe64fc0E99Fa5ebabb8e35D", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], decimals: [18, 6], poolType: 10, swapTypes: [1], codeHash: "0x11743a6ed542b23b65182e0c5a7b7d90b668a189f287b7c0c367b2f910d46c10", tvlUsd: 2074444, createdAt: 1770210611 },
534
+ { address: "0x8273Cb2cF9AF3228fD14AF25B5B1De2A9676C372", name: "FIDD/USDT", coins: ["0x7C135549504245B5eAe64fc0E99Fa5ebabb8e35D", "0xdAC17F958D2ee523a2206206994597C13D831ec7"], decimals: [18, 6], poolType: 10, swapTypes: [1], codeHash: "0xb1b0592d31b5fc1b46f56ffaecca522725e94a0e56facab038cb92d8b5e0f2e5", tvlUsd: 1750912, createdAt: 1770210935 },
535
+ { address: "0x839d6bDeDFF886404A6d7a788ef241e4e28F4802", name: "cbBTC/wBTC", coins: ["0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"], decimals: [8, 8], poolType: 10, swapTypes: [1], codeHash: "0x5270c4f3873d43de1babb9754a903f0de33054dfb7d562c3a3fcadbb8fd3fbca", tvlUsd: 1688187, createdAt: 1725600707 },
536
+ { address: "0xa4c567c662349BeC3D0fB94C4e7f85bA95E208e4", name: "Curve.fi Factory Plain Pool: msETH/WETH", coins: ["0x64351fC9810aDAd17A690E4e1717Df5e7e085160", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"], decimals: [18, 18], poolType: 1, swapTypes: [1], codeHash: "0x148d1345059482faa8834aff0630c9a4b47393df8edf9d99605b8f2f04752f62", tvlUsd: 1672158, createdAt: 1690864487 },
537
+ { address: "0xbcb91E689114B9Cc865AD7871845C95241Df4105", name: "Curve.fi Factory USD Metapool: PWRD Metapool", coins: ["0xF0a93d4994B3d98Fb5e3A2F90dBc2d69073Cb86b", "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"], decimals: [18, 18], underlying: ["0xF0a93d4994B3d98Fb5e3A2F90dBc2d69073Cb86b", "0x6B175474E89094C44Da98b954EedeAC495271d0F", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xdAC17F958D2ee523a2206206994597C13D831ec7"], underlyingDecimals: [18, 18, 6, 6], basePool: "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", poolType: 1, swapTypes: [1, 2], codeHash: "0xf6083ac638c10e3ca56ad0183f22c4bb24fda0f4c180165327954b3dfae28541", tvlUsd: 1438819, createdAt: 1632839676 },
538
+ { address: "0x635EF0056A597D13863B73825CcA297236578595", name: "GHO/crvUSD", coins: ["0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f", "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E"], decimals: [18, 18], poolType: 10, swapTypes: [1], codeHash: "0x1517d1f4caa802ab0ddf9032274a7ff3781a1453ef7b278fc63245b492154ce2", tvlUsd: 1377020, createdAt: 1709732591 },
539
+ { address: "0xC15F285679a1Ef2d25F53D4CbD0265E1D02F2A92", name: "Curve.fi Factory Crypto Pool: FXN/ETH", coins: ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "0x365AccFCa291e7D3914637ABf1F7635dB165Bb09"], decimals: [18, 18], poolType: 2, swapTypes: [1], codeHash: "0x6dfb9f924888fe0d10b50c35ced3f2cf372073a7e524450f1ebe491415db66e0", tvlUsd: 1244529, createdAt: 1695111311 },
540
+ { address: "0x625E92624Bc2D88619ACCc1788365A69767f6200", name: "pyUSD/crvUSD", coins: ["0x6c3ea9036406852006290770BEdFcAbA0e23A0e8", "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E"], decimals: [6, 18], poolType: 10, swapTypes: [1], codeHash: "0x9c3b1c5ac877c1719736bb325d05eb2806f292776a2121a6f1e8a54d31960dbe", tvlUsd: 1175516, createdAt: 1703109587 },
541
+ { address: "0xD9FF8396554A0d18B2CFbeC53e1979b7ecCe8373", name: "YB WBTC", coins: ["0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E", "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"], decimals: [18, 8], poolType: 20, swapTypes: [1], codeHash: "0x1578c5a836891e466a1fa5879bc7f0e36bfd9fc625586765541191d8cd3880ae", tvlUsd: 1167762, createdAt: 1758723347 },
542
+ { address: "0x971add32Ea87f10bD192671630be3BE8A11b8623", name: "Curve.fi Factory Plain Pool: cvxCrv/Crv", coins: ["0xD533a949740bb3306d119CC777fa900bA034cd52", "0x62B9c7356A2Dc64a1969e19C23e4f579F9810Aa7"], decimals: [18, 18], poolType: 1, swapTypes: [1], codeHash: "0x148d1345059482faa8834aff0630c9a4b47393df8edf9d99605b8f2f04752f62", tvlUsd: 1151010, createdAt: 1678280183 },
543
+ { address: "0xF4d0CF32908b2C7f1021339c43Df0F77f06896d7", name: "USDC/USDat", coins: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0x23238f20b894f29041f48D88eE91131C395Aaa71"], decimals: [6, 6], poolType: 10, swapTypes: [1], codeHash: "0x3c0abdd2996e01d3bff6d4430c231f8dd9f539985066729c28fbb2596ecd6e99", tvlUsd: 1107886, createdAt: 1775403179 },
544
+ { address: "0x5B03CcCAb7BA3010fA5CAd23746cbf0794938e96", name: "Curve Strategic Ethena Reserves", coins: ["0xdAC17F958D2ee523a2206206994597C13D831ec7", "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3"], decimals: [6, 18], poolType: 10, swapTypes: [1], codeHash: "0xbe6391aadd1d4d306c76728d664997ab7a1ef56c16565ca0d1526050b9c93890", tvlUsd: 1084518, createdAt: 1739457767 },
545
+ { address: "0x4f062658EaAF2C1ccf8C8e36D6824CDf41167956", name: "Curve.fi GUSD/3Crv", coins: ["0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd", "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"], decimals: [2, 18], underlying: ["0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd", "0x6B175474E89094C44Da98b954EedeAC495271d0F", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xdAC17F958D2ee523a2206206994597C13D831ec7"], underlyingDecimals: [2, 18, 6, 6], basePool: "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", poolType: 1, swapTypes: [1, 2], codeHash: "0xce79330162abf07fc163331f9d9d1553b93dbf509eeafa1215fafa6113c5088e", tvlUsd: 1068354, createdAt: 1602040124 },
546
+ { address: "0xD6937eA8D33B0C21348F36F7895FdE3054bA4927", name: "frxUSD/USDT", coins: ["0xCAcd6fd266aF91b8AeD52aCCc382b4e165586E29", "0xdAC17F958D2ee523a2206206994597C13D831ec7"], decimals: [18, 6], poolType: 10, swapTypes: [1], codeHash: "0xadf65a4e5ed895c5c85762d0b52d482664f1e26976e8401b39e95cd838e25998", tvlUsd: 1005528, createdAt: 1789499843 }
547
+ ]
548
+ };
549
+
550
+ // src/pools/10.ts
551
+ var POOLS_10 = {
552
+ chainId: 10,
553
+ builtAt: "2026-11-05",
554
+ block: 159152475,
555
+ pools: [
556
+ { address: "0xD1b30BA128573fcd7D141C8A987961b40e047BB6", name: "crvUSD/USDT", coins: ["0xC52D7F23a2e460248Db6eE192Cb23dD12bDDCbf6", "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58"], decimals: [18, 6], poolType: 10, swapTypes: [1], codeHash: "0xde251e17bf12e902d51f15ea5c2658888801dbb5f6c5095e226bdb808084bd98", tvlUsd: 250955, createdAt: 1703088383 }
557
+ ]
558
+ };
559
+
560
+ // src/pools/100.ts
561
+ var POOLS_100 = {
562
+ chainId: 100,
563
+ builtAt: "2026-11-05",
564
+ block: 49126652,
565
+ pools: [
566
+ { address: "0x7f90122BF0700F9E7e1F688fe926940E8839F353", name: "Curve.fi wxDAI/USDC/USDT", coins: ["0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d", "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83", "0x4ECaBa5870353805a9F068101A40E0f32ed605C6"], decimals: [18, 6, 6], poolType: 1, swapTypes: [1], codeHash: "0x855fc847a134dc1d35593a59c460e334938f53cb115b2befa8174138a1bb3df6", tvlUsd: 447779, createdAt: 1625016390 },
567
+ { address: "0x0eCEC6F5276d2Ec6bB864F063D2b76393d6A1A74", name: "USDCe/EURe", coins: ["0x2a22f9c3b484c3629090FeED35F17Ff8F88f76F0", "0x420CA0f9B9b604cE0fd9C18EF134C705e5Fa3430"], decimals: [6, 18], poolType: 20, swapTypes: [1], codeHash: "0x0287322b54143499eae6ce611f7895d7f37426f60565a7d1e228dac396ad1a89", tvlUsd: 360118, createdAt: 1786365280 }
568
+ ]
569
+ };
570
+
571
+ // src/pools/143.ts
572
+ var POOLS_143 = {
573
+ chainId: 143,
574
+ builtAt: "2026-11-05",
575
+ block: 119683641,
576
+ pools: [
577
+ { address: "0xFd945d71D4E9609a1FAb0aE9c30dA8088E7AEE1E", name: "USDat/USDC", coins: ["0x0Bb150DFa86EA5d7742F07FEfCD8E8edA81D64eF", "0x754704Bc059F8C67012fEd69BC8A327a5aafb603"], decimals: [6, 6], poolType: 10, swapTypes: [1], codeHash: "0xd5d05317249e8e17bd8c67a05048a7115ec719e3f4198ddfa560b7c0b3b620f6", tvlUsd: 2005448, createdAt: 1784210436 },
578
+ { address: "0x942644106B073E30D72c2C5D7529D5C296ea91ab", name: "3pool", coins: ["0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a", "0x754704Bc059F8C67012fEd69BC8A327a5aafb603", "0xe7cd86e13AC4309349F30B3435a9d337750fC82D"], decimals: [6, 6, 6], poolType: 10, swapTypes: [1], codeHash: "0x93a67dae1693a9327ff151167502f6785ac856025182eebd61150f4e0ea92ffa", tvlUsd: 1442204, createdAt: 1763939652 },
579
+ { address: "0xD665CaAD68ACb093AFF27eC6c71Ccc4F29c28147", name: "AUSD/trUSD", coins: ["0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a", "0x770a579Ea200784723B31b8668b0773ba80393c9"], decimals: [6, 18], poolType: 10, swapTypes: [1], codeHash: "0xb7af5a0364e252d950458f28c2d14434dd2961cef09ca1e2f90d7b1a96403a00", tvlUsd: 683014, createdAt: 1790778034 }
580
+ ]
581
+ };
582
+
583
+ // src/pools/196.ts
584
+ var POOLS_196 = {
585
+ chainId: 196,
586
+ builtAt: "2026-11-05",
587
+ block: 75134757,
588
+ pools: [
589
+ { address: "0x5B3f7F05b79f3cCBe8F33374A578e14dBBb28478", name: "USDC/USDT0", coins: ["0xB6CEceAB302E2E4948951eE7843FC24E92933061", "0x779Ded0c9e1022225f8E0630b35a9b54bE713736"], decimals: [6, 6], poolType: 10, swapTypes: [1], codeHash: "0x78281e9e5a691fe225a5c246be69cc35d48e81f4e1c0bcca178121fa41612961", tvlUsd: 300301, createdAt: 1786522937 },
590
+ { address: "0x31F066aA0A687d4F383F96a514984AF727Eb8e38", name: "USDG/USD0", coins: ["0x4ae46a509F6b1D9056937BA4500cb143933D2dc8", "0x779Ded0c9e1022225f8E0630b35a9b54bE713736"], decimals: [6, 6], poolType: 10, swapTypes: [1], codeHash: "0x855800c63268949eadd5206e5729c69e768f017722f275e90c4185b1fb0733bc", tvlUsd: 300095, createdAt: 1758717026 }
591
+ ]
592
+ };
593
+
594
+ // src/pools/8453.ts
595
+ var POOLS_8453 = {
596
+ chainId: 8453,
597
+ builtAt: "2026-11-05",
598
+ block: 53566756,
599
+ pools: [
600
+ { address: "0x302A94E3C28c290EAF2a4605FC52e11Eb915f378", name: "superOETHb/WETH", coins: ["0x4200000000000000000000000000000000000006", "0xDBFeFD2e8460a6Ee4955A68582F85708BAEA60A3"], decimals: [18, 18], poolType: 10, swapTypes: [1], codeHash: "0xd77abce9f34194324a3f8633aa5132f90aaa293ce9b1d7cfe9616bfaff0b9794", tvlUsd: 5842454, createdAt: 1737744997 },
601
+ { address: "0x11C1fBd4b3De66bC0565779b35171a6CF3E71f59", name: "Curve.fi Factory Crypto Pool: cbETH/WETH", coins: ["0x4200000000000000000000000000000000000006", "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22"], decimals: [18, 18], poolType: 2, swapTypes: [1], codeHash: "0xbba8650811de0f6d2cc92316e9826589443d72feebb6805b2655e81073abe834", tvlUsd: 1016724, createdAt: 1693260297 },
602
+ { address: "0xfac15A759d0F887Bc7F5ab874491258CF6EC8acE", name: "TriBitcoin", coins: ["0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", "0x0555E30da8f98308EdB960aa94C0Db47230d2B9c"], decimals: [8, 18, 8], poolType: 10, swapTypes: [1], codeHash: "0x51b2520df586800fd89a56f3a098e1a50e175f72b28088201682deb31bec0022", tvlUsd: 563901, createdAt: 1760081729 },
603
+ { address: "0x6e53131F68a034873b6bFA15502aF094Ef0c5854", name: "tricrypto", coins: ["0x417Ac0e078398C154EdFadD9Ef675d30Be60Af93", "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", "0x4200000000000000000000000000000000000006"], decimals: [18, 18, 18], poolType: 30, swapTypes: [1], codeHash: "0x437ca50fd4d25807efaa7d45077d247057a5e16b90609fcfde0b51f3673426d3", tvlUsd: 270418, createdAt: 1693263329 },
604
+ { address: "0xf6C5F01C7F3148891ad0e19DF78743D31E390D1f", name: "Curve.fi Factory Plain Pool: 4pool", coins: ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA", "0xEB466342C4d449BC9f53A865D5Cb90586f405215", "0x417Ac0e078398C154EdFadD9Ef675d30Be60Af93"], decimals: [6, 6, 6, 18], poolType: 1, swapTypes: [1], codeHash: "0xca87b5689cf421c7b6a160ea2b22bd23ef9267477918f39a2bbdf3cb838a987d", tvlUsd: 254106, createdAt: 1693751021 }
605
+ ]
606
+ };
607
+
608
+ // src/pools/9745.ts
609
+ var POOLS_9745 = {
610
+ chainId: 9745,
611
+ builtAt: "2026-11-05",
612
+ block: 36960466,
613
+ pools: [
614
+ { address: "0x2D84D79C852f6842AbE0304b70bBaA1506AdD457", name: "USDT0/USDe", coins: ["0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb", "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34"], decimals: [6, 18], poolType: 10, swapTypes: [1], codeHash: "0xc001cdbdd189f52d922cba4eec3137b5698c715d2370d67a41b937e7793b8bd2", tvlUsd: 719322, createdAt: 1758191172 },
615
+ { address: "0x085BaD2C28Bdd4A40396072D3eb2636BF7Afa39c", name: "yzUSD/USDT0", coins: ["0x6695c0f8706C5ACe3Bdf8995073179cCA47926dc", "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb"], decimals: [18, 6], poolType: 10, swapTypes: [1], codeHash: "0x8714b6160e5494b54383f64ebd4c8607093175dd697e48655cfd21df80b81804", tvlUsd: 596466, createdAt: 1762342995 }
616
+ ]
617
+ };
618
+
619
+ // src/pools/42161.ts
620
+ var POOLS_42161 = {
621
+ chainId: 42161,
622
+ builtAt: "2026-11-05",
623
+ block: 521558965,
624
+ pools: [
625
+ { address: "0x7f90122BF0700F9E7e1F688fe926940E8839F353", name: "Curve.fi USDC/USDT", coins: ["0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9"], decimals: [6, 6], poolType: 1, swapTypes: [1], codeHash: "0xc9c2956ac40175996b15ae3a750b84226736322c5c1aef3e6815b77aab3cb27e", tvlUsd: 630740, createdAt: 1631439440 },
626
+ { address: "0x186cF879186986A20aADFb7eAD50e3C20cb26CeC", name: "2BTC-ng", coins: ["0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f", "0x6c84a8f1c29108F47a79964b5Fe888D4f4D0dE40"], decimals: [8, 18], poolType: 10, swapTypes: [1], codeHash: "0xaeb505d765c57572cafa881bfcae2cba4e39f933fa7eea85e952ca3b5e1e6a7d", tvlUsd: 509842, createdAt: 1718829260 },
627
+ { address: "0x82670f35306253222F8a165869B28c64739ac62e", name: "Tricrypto-crvUSD", coins: ["0x498Bf2B1e120FeD3ad3D42EA2165E9b73f99C1e5", "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f", "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"], decimals: [18, 8, 18], poolType: 30, swapTypes: [1], codeHash: "0x35da327ca48b6e428478467c3996176d71855383e82d30664f95886822fd507d", tvlUsd: 328993, createdAt: 1704150579 },
628
+ { address: "0x49b720F1Aab26260BEAec93A7BeB5BF2925b2A8F", name: "Strategic USD Reserves", coins: ["0xaf88d065e77c8cC2239327C5EDb3A432268e5831", "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9"], decimals: [6, 6], poolType: 10, swapTypes: [1], codeHash: "0x27724587b6447859a96567a97e5bf015b8e5ae3d90ffdbe97a098c30b268703c", tvlUsd: 257764, createdAt: 1739092049 }
629
+ ]
630
+ };
631
+
632
+ // src/pools/index.ts
633
+ var CURVE_POOLS = Object.freeze({
634
+ 1: POOLS_1,
635
+ 10: POOLS_10,
636
+ 100: POOLS_100,
637
+ 143: POOLS_143,
638
+ 196: POOLS_196,
639
+ 8453: POOLS_8453,
640
+ 9745: POOLS_9745,
641
+ 42161: POOLS_42161
642
+ });
643
+
644
+ // src/rpc.ts
645
+ var import_util2 = require("@anywalletkit/protocol-swap2-core/util");
646
+ var RPC_BATCH_MAX = 10;
647
+ var RPC_RATE_LIMIT_PAUSE_MS = 1e3;
648
+ function isExecutionError(error) {
649
+ if (!error || typeof error !== "object") return false;
650
+ const { code, message } = error;
651
+ return code === 3 || typeof message === "string" && /revert|invalid opcode|out of gas/i.test(message);
652
+ }
653
+ function isRateLimit(error) {
654
+ if (!error || typeof error !== "object") return false;
655
+ const { code, message } = error;
656
+ return code === -32005 || code === -32007 || code === 429 || typeof message === "string" && /rate|limit|too many/i.test(message);
657
+ }
658
+ var errorText = (error) => {
659
+ const m = error && typeof error === "object" ? error.message : void 0;
660
+ return (0, import_util2.redactUrls)(typeof m === "string" ? m : JSON.stringify(error) ?? String(error)).slice(0, 160);
661
+ };
662
+ function rpcClient(rpcUrls) {
663
+ async function once(url, calls, signal) {
664
+ const res = await fetch(url, {
665
+ method: "POST",
666
+ headers: { "content-type": "application/json" },
667
+ body: JSON.stringify(calls.map((c, id) => ({ jsonrpc: "2.0", id, ...c }))),
668
+ signal: signal ?? (0, import_util2.timeoutSignal)(12e3)
669
+ });
670
+ if (!res.ok) throw Object.assign(new Error(`HTTP ${res.status}`), { limited: res.status === 429 });
671
+ const body = await res.json();
672
+ if (!Array.isArray(body)) throw Object.assign(new Error(body.error?.message ?? "batch refused"), { limited: isRateLimit(body.error) });
673
+ const out = calls.map(() => null);
674
+ const answered = /* @__PURE__ */ new Set();
675
+ for (const r of body) {
676
+ 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) });
678
+ answered.add(r.id);
679
+ if (r.error === void 0 || r.error === null) out[r.id] = r.result ?? null;
680
+ }
681
+ if (answered.size !== calls.length) throw new Error(`answered ${answered.size} of ${calls.length} calls`);
682
+ return out;
683
+ }
684
+ async function batch(chainId, calls, signal) {
685
+ let lastErr;
686
+ for (let pass = 0; pass < 2; pass++) {
687
+ if (pass > 0) {
688
+ if (!lastErr?.limited || signal?.aborted) break;
689
+ await new Promise((r) => setTimeout(r, RPC_RATE_LIMIT_PAUSE_MS));
690
+ }
691
+ for (const url of rpcUrls[chainId] ?? []) {
692
+ try {
693
+ return await once(url, calls, signal);
694
+ } catch (e) {
695
+ lastErr = e;
696
+ }
697
+ }
698
+ }
699
+ throw new Error(`curve: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);
700
+ }
701
+ return async function rpc(chainId, calls, signal) {
702
+ if (calls.length <= RPC_BATCH_MAX) return batch(chainId, calls, signal);
703
+ const chunks = [];
704
+ for (let i = 0; i < calls.length; i += RPC_BATCH_MAX) chunks.push(calls.slice(i, i + RPC_BATCH_MAX));
705
+ return (await Promise.all(chunks.map((c) => batch(chainId, c, signal)))).flat();
706
+ };
707
+ }
708
+ var ethCall = (to, data) => ({ method: "eth_call", params: [{ to, data }, "latest"] });
709
+ function firstWord(raw) {
710
+ return typeof raw === "string" && raw.length >= 66 && /^0x(?:[0-9a-fA-F]{64})+$/.test(raw) ? raw.slice(2, 66).toLowerCase() : null;
711
+ }
712
+ function wordAddress(raw) {
713
+ const w = firstWord(raw);
714
+ return w !== null && /^0{24}/.test(w) ? `0x${w.slice(24)}` : null;
715
+ }
716
+ function wordUint(raw) {
717
+ const w = firstWord(raw);
718
+ return w === null ? null : BigInt(`0x${w}`);
719
+ }
720
+
721
+ // src/slippage.ts
722
+ var import_core = require("@anywalletkit/core");
723
+ var import_swap2_assets2 = require("@anywalletkit/swap2-assets");
724
+ var import_slippage = require("@anywalletkit/protocol-swap2-core/slippage");
725
+ var import_util3 = require("@anywalletkit/protocol-swap2-core/util");
726
+ function curveImpactBps(amountIn, out, probeOut) {
727
+ const probeIn = amountIn / 1000n;
728
+ if (probeIn <= 0n || probeOut === null || probeOut === void 0 || probeOut <= 0n) return void 0;
729
+ const ratioBps = out * probeIn * 10000n / (probeOut * amountIn);
730
+ return Math.max(0, (0, import_core.bigintToNumber)(10000n - ratioBps));
731
+ }
732
+ function curveAutoSlippageBps(params, priceImpactBps) {
733
+ const nativeOut = /^0x0+$/.test(params.destToken);
734
+ return (0, import_slippage.suggestSlippage)({
735
+ fromChain: params.sourceChain,
736
+ toChain: params.destChain,
737
+ fromSymbol: (0, import_util3.sourceAssetOf)(params)?.symbol ?? "",
738
+ toSymbol: (0, import_swap2_assets2.ccAssetByToken)(params.destChain, nativeOut ? "" : params.destToken)?.symbol ?? "",
739
+ ...priceImpactBps !== void 0 ? { priceImpactBps } : {}
740
+ }).bps;
741
+ }
742
+
743
+ // src/intent.ts
744
+ var INTENT_ID = /^curve:([1-9][0-9]{0,15}):[0-9a-f]{16}(?:~[0-9a-f]{32})?$/;
745
+ function mintCurveIntentId(chainId) {
746
+ const nonce = globalThis.crypto.getRandomValues(new Uint8Array(8));
747
+ return `curve:${chainId}:${Array.from(nonce, (b) => b.toString(16).padStart(2, "0")).join("")}`;
748
+ }
749
+ function curveIntentChain(intentId) {
750
+ const m = typeof intentId === "string" ? INTENT_ID.exec(intentId) : null;
751
+ const id = m ? Number(m[1]) : NaN;
752
+ return Number.isSafeInteger(id) ? id : null;
753
+ }
754
+
755
+ // src/verify.ts
756
+ var import_viem3 = require("viem");
757
+ var import_util4 = require("@anywalletkit/protocol-swap2-core/util");
758
+ var import_validate = require("@anywalletkit/protocol-swap2-core/validate");
759
+ var lc2 = (a) => a.toLowerCase();
760
+ var isAddress = (a) => /^0x[0-9a-fA-F]{40}$/.test(a);
761
+ var own = (o, k) => Object.prototype.hasOwnProperty.call(o, k) ? o[k] : void 0;
762
+ function curveQuoteCheck(tables = {}) {
763
+ const deployments = tables.deployments ?? CURVE_DEPLOYMENTS;
764
+ const pools = tables.pools ?? CURVE_POOLS;
765
+ return function verify(params, quote) {
766
+ const chainId = chainIdOf(params.sourceChain);
767
+ const d2 = deploymentOf(deployments, chainId);
768
+ if (!d2 || params.destChain !== params.sourceChain) return "not a same-chain swap on a pinned Curve router";
769
+ 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`;
774
+ const src = (0, import_util4.sourceAssetOf)(params);
775
+ if (!src) return `unknown source token ${params.sourceToken}`;
776
+ const nativeIn = !src.contract;
777
+ 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";
781
+ const tokenIn = nativeIn ? d2.eth : src.contract;
782
+ const tokenOut = nativeOut ? d2.eth : params.destToken;
783
+ let amountIn, minOut, value;
784
+ try {
785
+ amountIn = BigInt(params.amountIn);
786
+ minOut = BigInt(quote.minDestAmount);
787
+ value = BigInt(tx.value ?? "0");
788
+ } catch {
789
+ return "the request does not name amounts";
790
+ }
791
+ 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";
793
+ }
794
+ 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";
803
+ return checkRoute(chainId, d2, own(pools, chainId), call, tokenIn, tokenOut);
804
+ };
805
+ }
806
+ var curveVerifyQuote = curveQuoteCheck();
807
+ var curvePins = Object.freeze({
808
+ callTargets: (chain) => routerFor(CURVE_DEPLOYMENTS, chain),
809
+ spenders: (chain) => routerFor(CURVE_DEPLOYMENTS, chain),
810
+ verifyQuote: curveVerifyQuote
811
+ });
812
+ function routerFor(deployments, chain) {
813
+ const d2 = deploymentOf(deployments, chainIdOf(chain));
814
+ return d2 ? [d2.router] : [];
815
+ }
816
+ function curveOnChain(opts) {
817
+ const deployments = opts.deployments ?? CURVE_DEPLOYMENTS;
818
+ const pools = opts.pools ?? CURVE_POOLS;
819
+ const rpc = rpcClient(opts.rpcUrls);
820
+ const warn = opts.onWarning ?? ((m) => console.warn(m));
821
+ const verified = /* @__PURE__ */ new Map();
822
+ function verifyDeployment(chainId) {
823
+ let p = verified.get(chainId);
824
+ if (!p) {
825
+ const d2 = deploymentOf(deployments, chainId);
826
+ p = (async () => {
827
+ if (!d2) throw new Error(`curve: no pinned router on chain ${chainId}`);
828
+ const [code, version, listed] = await rpc(chainId, [
829
+ { method: "eth_getCode", params: [d2.router, "latest"] },
830
+ ethCall(d2.router, (0, import_viem3.encodeFunctionData)({ abi: VERSION_ABI, functionName: "version" })),
831
+ ethCall(d2.addressProvider, (0, import_viem3.encodeFunctionData)({ abi: ADDRESS_PROVIDER_ABI, functionName: "get_address", args: [2n] }))
832
+ ]);
833
+ if (typeof code !== "string" || code.length <= 2 || lc2((0, import_viem3.keccak256)(code)) !== lc2(d2.codeHash)) {
834
+ throw new Error(`curve: the router on chain ${chainId} is not the pinned code (code hash mismatch) \u2014 refusing`);
835
+ }
836
+ let v = "";
837
+ try {
838
+ v = typeof version === "string" ? (0, import_viem3.decodeFunctionResult)({ abi: VERSION_ABI, functionName: "version", data: version }) : "";
839
+ } catch {
840
+ }
841
+ if (v !== d2.version) throw new Error(`curve: the router on chain ${chainId} reports version ${v || "none"}, not ${d2.version} \u2014 refusing`);
842
+ const ap = wordAddress(listed);
843
+ if (ap && ap !== lc2(d2.addressProviderRouter) && ap !== lc2(d2.router)) {
844
+ warn(`curve: the AddressProvider on ${d2.label} lists router ${ap} (id 2); this module keeps the pinned ${d2.router}`);
845
+ }
846
+ })();
847
+ p.catch(() => verified.delete(chainId));
848
+ verified.set(chainId, p);
849
+ }
850
+ return p;
851
+ }
852
+ async function checkSealed(quote, tx) {
853
+ const r = await inspectSealed(quote, tx, false);
854
+ return typeof r === "string" ? r : null;
855
+ }
856
+ async function inspectSealed(quote, tx, probe) {
857
+ const chainId = curveIntentChain(quote.intentId);
858
+ 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";
860
+ 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";
867
+ 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)";
870
+ const last = lastToken(call);
871
+ const reason = checkRoute(chainId, d2, own(pools, chainId), call, call.route[0], last);
872
+ if (reason) return reason;
873
+ await verifyDeployment(chainId);
874
+ const index = poolIndex(chainId, d2, own(pools, chainId));
875
+ const hops = routePools(call).map((a) => index.get(lc2(a)));
876
+ const reads = poolCalls(hops);
877
+ const calls = [ethCall(d2.router, encodeGetDy(d2.family, call, call.amount)), ...reads];
878
+ const probeIn = call.amount / 1000n;
879
+ const probeAt = calls.length;
880
+ if (probe && probeIn > 0n) calls.push(ethCall(d2.router, encodeGetDy(d2.family, call, probeIn)));
881
+ const res = await rpc(chainId, calls);
882
+ const poolReason = await poolsReason(chainId, hops, res.slice(1, 1 + reads.length));
883
+ if (poolReason) return poolReason;
884
+ 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}`;
887
+ return { out, probeOut: probe && probeIn > 0n ? wordUint(res[probeAt]) : null, amount: call.amount, minDy: call.minDy };
888
+ }
889
+ function poolCalls(list) {
890
+ return list.flatMap((pool) => [
891
+ { method: "eth_getCode", params: [pool.address, "latest"] },
892
+ ...pool.coins.map((_, k) => ethCall(pool.address, `${COINS_UINT}${k.toString(16).padStart(64, "0")}`))
893
+ ]);
894
+ }
895
+ async function poolsReason(chainId, list, res) {
896
+ let at = 0;
897
+ const retry = [];
898
+ for (const pool of list) {
899
+ 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`;
902
+ for (let k = 0; k < pool.coins.length; k++) {
903
+ const coin = wordAddress(res[at++]);
904
+ 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]}`;
906
+ }
907
+ }
908
+ if (retry.length) {
909
+ const again = await rpc(chainId, retry.map(({ pool, k }) => ethCall(pool.address, `${COINS_INT}${k.toString(16).padStart(64, "0")}`)));
910
+ for (const [n, { pool, k }] of retry.entries()) {
911
+ const coin = wordAddress(again[n]);
912
+ if (coin !== lc2(pool.coins[k])) return `pool ${pool.name} does not report its pinned coin ${k}`;
913
+ }
914
+ }
915
+ return null;
916
+ }
917
+ async function checkPools(chainId, list) {
918
+ return list.length ? poolsReason(chainId, list, await rpc(chainId, poolCalls(list))) : null;
919
+ }
920
+ return { rpc, verifyDeployment, checkSealed, inspectSealed, checkPools };
921
+ }
922
+ function lastToken(call) {
923
+ let k = 0;
924
+ while (k < 5 && lc2(call.route[2 * k + 1]) !== lc2(ZERO_ADDRESS)) k++;
925
+ return call.route[2 * k];
926
+ }
927
+ var CURVE_AUTO_SLIPPAGE_DRIFT_BPS = 5;
928
+ function curveRemotePins(opts) {
929
+ const deployments = opts.deployments ?? CURVE_DEPLOYMENTS;
930
+ const fixedSlippage = opts.defaultSlippageBps;
931
+ if (fixedSlippage !== void 0 && (!Number.isInteger(fixedSlippage) || fixedSlippage <= 0 || fixedSlippage >= 5e3)) throw new Error("curve: defaultSlippageBps must be 1..4999");
932
+ const verifyQuote = curveQuoteCheck(opts);
933
+ const chain = curveOnChain(opts);
934
+ return Object.freeze({
935
+ callTargets: (c) => routerFor(deployments, c),
936
+ spenders: (c) => routerFor(deployments, c),
937
+ verifyQuote,
938
+ async verifyBuild(quote, tx, params) {
939
+ if (!params) return "the request this quote answered is unknown";
940
+ const reason = verifyQuote(params, quote);
941
+ if (reason) return reason;
942
+ try {
943
+ const auto = params.slippageBps === void 0 && fixedSlippage === void 0;
944
+ const seen = await chain.inspectSealed(quote, tx, auto);
945
+ if (typeof seen === "string") return seen;
946
+ const { out, probeOut, amount, minDy } = seen;
947
+ let dest;
948
+ try {
949
+ dest = BigInt(quote.destAmount);
950
+ } catch {
951
+ return "the quote names no output";
952
+ }
953
+ 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`;
955
+ 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`;
957
+ return null;
958
+ } catch (e) {
959
+ return e instanceof Error ? e.message.replace(/^curve: /, "") : String(e);
960
+ }
961
+ }
962
+ });
963
+ }
964
+
965
+ // src/provider.ts
966
+ var DEFAULT_TTL_MS = 18e4;
967
+ function curveProvider(config) {
968
+ const deployments = config.deployments ?? CURVE_DEPLOYMENTS;
969
+ const pools = config.pools ?? CURVE_POOLS;
970
+ const ttl = config.quoteTtlMs ?? DEFAULT_TTL_MS;
971
+ const fixedSlippage = config.defaultSlippageBps;
972
+ if (fixedSlippage !== void 0 && (!Number.isInteger(fixedSlippage) || fixedSlippage <= 0 || fixedSlippage >= 5e3)) throw new Error("curve: defaultSlippageBps must be 1..4999");
973
+ const chain = curveOnChain({ rpcUrls: config.rpcUrls, deployments, pools, ...config.onWarning ? { onWarning: config.onWarning } : {} });
974
+ const rpc = chain.rpc;
975
+ const selfCheck = curveQuoteCheck({ deployments, pools });
976
+ const tableOf = (chainId) => Object.prototype.hasOwnProperty.call(pools, chainId) ? pools[chainId] : void 0;
977
+ const chainIdOf2 = (caip2) => {
978
+ if (!(0, import_util5.isEvm)(caip2)) return null;
979
+ const id = (0, import_util5.evmRef)(caip2);
980
+ return deploymentOf(deployments, id) && config.rpcUrls[id]?.length && tableOf(id)?.pools.length ? id : null;
981
+ };
982
+ async function price(chainId, d2, routes, amount, signal) {
983
+ const raw = await rpc(chainId, routes.map((r) => ethCall(d2.router, encodeGetDy(d2.family, routeArgs(d2.family, r), amount))), signal);
984
+ return raw.map(wordUint);
985
+ }
986
+ return {
987
+ name: "curve",
988
+ describeActivity: (tx, ctx) => describeCurveActivity(tx, ctx, deployments),
989
+ supportsSameChain: true,
990
+ enabled: () => config.enabled ?? true,
991
+ supportsChain: (caip2) => chainIdOf2(caip2) !== null,
992
+ supportsChainPair: (from, to) => from === to && chainIdOf2(from) !== null,
993
+ supportsRoute(from, to) {
994
+ return from.chain === to.chain && chainIdOf2(from.chain) !== null;
995
+ },
996
+ async getQuote(params, signal) {
997
+ const refuse = (why) => {
998
+ params.onRefusal?.(`curve: ${why}`);
999
+ return null;
1000
+ };
1001
+ if (params.flex) return refuse("amount-flexible deposits are not supported");
1002
+ if (params.sourceChain !== params.destChain) return refuse("same-chain swaps only");
1003
+ const chainId = chainIdOf2(params.sourceChain);
1004
+ if (chainId === null) return refuse(`no Curve router, pool allowlist or RPC for ${params.sourceChain}`);
1005
+ const d2 = deploymentOf(deployments, chainId);
1006
+ const src = (0, import_util5.sourceAssetOf)(params);
1007
+ if (!src) return refuse(`unknown source token ${params.sourceToken}`);
1008
+ const nativeIn = !src.contract;
1009
+ 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");
1012
+ let amountIn;
1013
+ try {
1014
+ amountIn = BigInt(params.amountIn);
1015
+ } catch {
1016
+ return refuse("amount is not an integer");
1017
+ }
1018
+ if (amountIn <= 0n) return refuse("amount must be positive");
1019
+ 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");
1022
+ const tokenIn = (0, import_viem4.getAddress)(nativeIn ? d2.eth : src.contract);
1023
+ const tokenOut = (0, import_viem4.getAddress)(nativeOut ? d2.eth : params.destToken);
1024
+ if (tokenIn === tokenOut) return refuse("same token in and out");
1025
+ 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");
1027
+ try {
1028
+ await chain.verifyDeployment(chainId);
1029
+ const { routes, truncated } = findRoutes(chainId, d2, tableOf(chainId), tokenIn, tokenOut);
1030
+ if (!routes.length) return refuse("no allowlisted Curve pool route for this pair");
1031
+ const outs = await price(chainId, d2, routes, amountIn, signal);
1032
+ let best = null;
1033
+ outs.forEach((out2, i) => {
1034
+ if (out2 !== null && out2 > 0n && (!best || out2 > best.out)) best = { route: routes[i], out: out2 };
1035
+ });
1036
+ if (!best) return refuse("no allowlisted Curve pool quotes this pair and amount");
1037
+ const { route, out } = best;
1038
+ let priceImpactBps;
1039
+ const probeIn = amountIn / 1000n;
1040
+ if (probeIn > 0n) {
1041
+ try {
1042
+ const [probeOut] = await price(chainId, d2, [route], probeIn, signal);
1043
+ priceImpactBps = curveImpactBps(amountIn, out, probeOut);
1044
+ } catch {
1045
+ }
1046
+ }
1047
+ const bps = params.slippageBps ?? fixedSlippage ?? curveAutoSlippageBps(params, priceImpactBps);
1048
+ const minOut = out * BigInt(1e4 - bps) / 10000n;
1049
+ if (minOut <= 0n) return refuse("the minimum rounds to zero for this amount");
1050
+ if (params.minAmountOut !== void 0 && minOut < BigInt(params.minAmountOut)) {
1051
+ return refuse(`floor breach (min=${minOut} < floor=${params.minAmountOut})`);
1052
+ }
1053
+ const args = routeArgs(d2.family, route);
1054
+ const recipient = (0, import_viem4.getAddress)(params.destAddress);
1055
+ const data = encodeExchange(d2.family, args, amountIn, minOut, recipient);
1056
+ const quote = {
1057
+ provider: "curve",
1058
+ // One id per quote: a remote stub keys the request a build is checked against by it.
1059
+ intentId: mintCurveIntentId(chainId),
1060
+ depositAddress: "",
1061
+ depositMemo: null,
1062
+ txRequest: {
1063
+ to: d2.router,
1064
+ data,
1065
+ value: nativeIn ? amountIn.toString() : "0",
1066
+ chainId,
1067
+ ...nativeIn ? {} : { approvalAddress: d2.router }
1068
+ },
1069
+ sourceAmount: amountIn.toString(),
1070
+ destAmount: out.toString(),
1071
+ minDestAmount: minOut.toString(),
1072
+ feeUsd: 0,
1073
+ etaSeconds: 15,
1074
+ reliability: 0.97,
1075
+ validUntilMs: Date.now() + ttl,
1076
+ // Pool fees are inside the router-priced output; nothing is added on top.
1077
+ providerData: {
1078
+ route: route.label,
1079
+ poolFee: "pools",
1080
+ router: d2.router,
1081
+ family: d2.family,
1082
+ tokenIn,
1083
+ tokenOut,
1084
+ amountIn: amountIn.toString(),
1085
+ minOut: minOut.toString(),
1086
+ slippageBps: String(bps),
1087
+ pools: routePools(args).join(","),
1088
+ candidates: `${routes.length}${truncated ? "+" : ""}`,
1089
+ ...priceImpactBps !== void 0 ? { priceImpactBps: String(priceImpactBps) } : {}
1090
+ }
1091
+ };
1092
+ const why = selfCheck(params, quote);
1093
+ if (why) return refuse(`built a call its own check refuses (${why})`);
1094
+ return quote;
1095
+ } catch (e) {
1096
+ return refuse(e instanceof Error ? e.message.replace(/^curve: /, "") : String(e));
1097
+ }
1098
+ },
1099
+ /**
1100
+ * Right before broadcast (after any approval): the transaction is byte for byte the sealed quote, each hop pool is
1101
+ * still the pinned code with the pinned coins (the immutable router's code and version were checked once for the
1102
+ * chain), and the exact route still pays at least the signed minimum. Refuse with the reason instead of sending a swap that would revert or was altered.
1103
+ */
1104
+ async preflightDeposit(quote, tx) {
1105
+ const reason = await chain.checkSealed(quote, tx);
1106
+ if (reason) throw new Error(`curve: ${reason}. Nothing was sent; refresh the quote.`);
1107
+ },
1108
+ async buildDeposit(quote) {
1109
+ const tx = quote.txRequest;
1110
+ if (!tx?.to || !tx.data) throw new Error("swap2: Curve quote has no transaction request");
1111
+ return {
1112
+ chain: "",
1113
+ to: tx.to,
1114
+ value: tx.value ?? "0",
1115
+ data: tx.data,
1116
+ ...tx.chainId !== void 0 ? { chainId: tx.chainId } : {},
1117
+ ...tx.gasLimit ? { gasLimit: tx.gasLimit } : {},
1118
+ ...tx.approvalAddress ? { approvalAddress: tx.approvalAddress } : {}
1119
+ };
1120
+ },
1121
+ /** Same-chain: the swap is done when its transaction is mined successfully. */
1122
+ async trackIntent(ref) {
1123
+ if (!ref.sourceTxHash) return { state: "pending" };
1124
+ const chainId = curveIntentChain(ref.intentId);
1125
+ if (chainId === null || !deploymentOf(deployments, chainId) || !config.rpcUrls[chainId]?.length) return { state: "pending" };
1126
+ try {
1127
+ const [receipt] = await rpc(chainId, [{ method: "eth_getTransactionReceipt", params: [ref.sourceTxHash] }]);
1128
+ if (!receipt) return { state: "pending" };
1129
+ return receipt.status === "0x1" ? { state: "completed", destTxHash: ref.sourceTxHash } : { state: "failed" };
1130
+ } catch {
1131
+ return { state: "pending" };
1132
+ }
1133
+ }
1134
+ };
1135
+ }
1136
+
1137
+ // src/known.ts
1138
+ function curveKnownContracts(chainId, tables = {}) {
1139
+ const d2 = deploymentOf(tables.deployments ?? CURVE_DEPLOYMENTS, chainId);
1140
+ if (!d2) return {};
1141
+ const out = { [d2.router]: `Curve Router NG ${d2.version} \xB7 ${d2.label}` };
1142
+ if (!tables.deployments) {
1143
+ for (const r of Object.prototype.hasOwnProperty.call(CURVE_LEGACY_ROUTERS, chainId) ? CURVE_LEGACY_ROUTERS[chainId] : []) out[r.router] = `Curve Router NG ${r.version} (older) \xB7 ${d2.label}`;
1144
+ }
1145
+ const pools = tables.pools ?? CURVE_POOLS;
1146
+ const table = Object.prototype.hasOwnProperty.call(pools, chainId) ? pools[chainId] : void 0;
1147
+ for (const p of table?.chainId === chainId ? table.pools : []) out[p.address] = `Curve pool \xB7 ${p.name}`;
1148
+ if (d2.weth.toLowerCase() !== ZERO_ADDRESS) out[d2.weth] = `Wrapped native (Curve router wrap hop) \xB7 ${d2.label}`;
1149
+ if (d2.erc4626) out[d2.erc4626.vault] = "Savings crvUSD (scrvUSD vault)";
1150
+ return out;
1151
+ }
1152
+
1153
+ // src/protocol.ts
1154
+ var import_single = require("@anywalletkit/protocol-swap2-core/swap2/single");
1155
+ var import_util6 = require("@anywalletkit/protocol-swap2-core/util");
1156
+ var CurveSwap2Protocol = class extends import_single.SingleProviderSwap2 {
1157
+ provider;
1158
+ _rpcUrls;
1159
+ _deployments;
1160
+ _pools;
1161
+ constructor(account, config) {
1162
+ super(account, config);
1163
+ this.provider = curveProvider(config);
1164
+ this._rpcUrls = config.rpcUrls ?? {};
1165
+ this._deployments = config.deployments ?? CURVE_DEPLOYMENTS;
1166
+ this._pools = config.pools ?? CURVE_POOLS;
1167
+ }
1168
+ chainSupported(caip2) {
1169
+ if (!(0, import_util6.isEvm)(caip2)) return false;
1170
+ const id = (0, import_util6.evmRef)(caip2);
1171
+ return !!deploymentOf(this._deployments, id) && !!this._rpcUrls[id]?.length && !!(Object.prototype.hasOwnProperty.call(this._pools, id) && this._pools[id].pools.length);
1172
+ }
1173
+ pairSupported(fromChain, toChain) {
1174
+ return fromChain === toChain && this.chainSupported(fromChain);
1175
+ }
1176
+ };
1177
+ //# sourceMappingURL=index.cjs.map