@guru-fund/sdk 0.2.3 → 0.2.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/router/constants.d.ts +1 -1
- package/dist/router/constants.js +1 -0
- package/dist/router/index.js +171 -22
- package/dist/router/pathCache.js +10 -2
- package/dist/router/poolHelper.js +6 -1
- package/dist/router/types.d.ts +2 -0
- package/dist/router/velora.d.ts +1 -0
- package/dist/router/velora.js +52 -8
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const VELORA_ENDPOINT = "https://api.velora.xyz/swap";
|
|
2
|
-
export declare const SUPPORTED_DEXS: readonly ["UniswapV2", "UniswapV3", "UniswapV4", "AerodromeV2", "PancakeSwapV2", "PancakeSwapV3"];
|
|
2
|
+
export declare const SUPPORTED_DEXS: readonly ["UniswapV2", "UniswapV3", "UniswapV4", "AerodromeV3", "AerodromeV2", "PancakeSwapV2", "PancakeSwapV3"];
|
|
3
3
|
export declare const VELORA_VERSION_BY_DEX: Partial<Record<SupportedDex, string>>;
|
|
4
4
|
export type SupportedDex = (typeof SUPPORTED_DEXS)[number];
|
|
5
5
|
export declare const INITIAL_SLIPPAGE_E3 = 500n;
|
package/dist/router/constants.js
CHANGED
package/dist/router/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseEther } from 'ethers';
|
|
1
|
+
import { Contract, parseEther, ZeroAddress } from 'ethers';
|
|
2
2
|
import { getGuruProtocolAddresses, } from '../addresses.js';
|
|
3
3
|
import compareAddresses from '../helpers/compareAddresses.js';
|
|
4
4
|
import { Token } from '../helpers/Token.js';
|
|
@@ -7,6 +7,33 @@ import getUniswapV4Route, { connectV4Quoter, toAdapterPathKeys, } from './getUni
|
|
|
7
7
|
import getVeloraRoute from './getVeloraRoute.js';
|
|
8
8
|
import PoolHelper from './poolHelper.js';
|
|
9
9
|
import { discoverV4Paths } from './v4PoolDiscovery.js';
|
|
10
|
+
const AERO_V3_FACTORY_ABI = [
|
|
11
|
+
'function getPool(address tokenA, address tokenB, int24 tickSpacing) view returns (address pool)',
|
|
12
|
+
];
|
|
13
|
+
const V2_FACTORY_ABI = [
|
|
14
|
+
'function getPair(address tokenA, address tokenB) view returns (address pair)',
|
|
15
|
+
];
|
|
16
|
+
const V2_ROUTER_ABI = [
|
|
17
|
+
'function getAmountsOut(uint256 amountIn, address[] memory path) view returns (uint256[] memory amounts)',
|
|
18
|
+
];
|
|
19
|
+
const AERO_V2_FACTORY_ABI = [
|
|
20
|
+
'function getPool(address tokenA, address tokenB, bool stable) view returns (address)',
|
|
21
|
+
];
|
|
22
|
+
const AERO_V2_ROUTER_ABI = [
|
|
23
|
+
'function getAmountsOut(uint256 amountIn, (address from, address to, bool stable, address factory)[] routes) view returns (uint256[] amounts)',
|
|
24
|
+
];
|
|
25
|
+
const V3_FACTORY_ABI = [
|
|
26
|
+
'function getPool(address tokenA, address tokenB, uint24 fee) view returns (address pool)',
|
|
27
|
+
];
|
|
28
|
+
const V3_QUOTER_ABI = [
|
|
29
|
+
'function quoteExactInputSingle((address tokenIn,address tokenOut,uint256 amountIn,uint24 fee,uint160 sqrtPriceLimitX96) params) returns (uint256 amountOut,uint160 sqrtPriceX96After,uint32 initializedTicksCrossed,uint256 gasEstimate)',
|
|
30
|
+
];
|
|
31
|
+
const AERO_V3_QUOTER_ABI = [
|
|
32
|
+
'function quoteExactInputSingle((address tokenIn, address tokenOut, uint256 amountIn, int24 tickSpacing, uint160 sqrtPriceLimitX96) params) returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)',
|
|
33
|
+
];
|
|
34
|
+
const UNISWAP_V3_FEES = [100, 500, 3000, 10000];
|
|
35
|
+
const PANCAKE_V3_FEES = [100, 500, 2500, 10000];
|
|
36
|
+
const AERODROME_V3_TICK_SPACINGS = [1, 50, 100, 200];
|
|
10
37
|
export async function veloraThenV4Discovery(velora, v4Discovery) {
|
|
11
38
|
try {
|
|
12
39
|
return await velora();
|
|
@@ -97,9 +124,7 @@ export async function getPriceUsd1e18(token, ctx) {
|
|
|
97
124
|
}
|
|
98
125
|
const { decimals } = await new Token(token, ctx.provider).metadata();
|
|
99
126
|
const oneToken = 10n ** BigInt(decimals);
|
|
100
|
-
const stableUsd = await _priceViaDirectStablePool(token, oneToken, poolHelper, stable, stableDecimals);
|
|
101
|
-
if (stableUsd !== null)
|
|
102
|
-
return stableUsd;
|
|
127
|
+
const stableUsd = await _priceViaDirectStablePool(token, oneToken, poolHelper, stable, stableDecimals, ctx.provider);
|
|
103
128
|
const WETH_UNIT = 10n ** 18n;
|
|
104
129
|
try {
|
|
105
130
|
const wethUsd = await getWethUsd();
|
|
@@ -108,33 +133,157 @@ export async function getPriceUsd1e18(token, ctx) {
|
|
|
108
133
|
path: [token, addresses.tokens.WETH],
|
|
109
134
|
requireSwappable: false,
|
|
110
135
|
});
|
|
111
|
-
|
|
136
|
+
const wethRouteUsd = (oneTokenInWeth * wethUsd) / WETH_UNIT;
|
|
137
|
+
return stableUsd !== null && stableUsd > wethRouteUsd
|
|
138
|
+
? stableUsd
|
|
139
|
+
: wethRouteUsd;
|
|
112
140
|
}
|
|
113
141
|
catch (error) {
|
|
114
142
|
const v4Usd = await _priceViaV4Pools(token, oneToken, getWethUsd, ctx);
|
|
143
|
+
if (stableUsd !== null && v4Usd !== null) {
|
|
144
|
+
return stableUsd > v4Usd ? stableUsd : v4Usd;
|
|
145
|
+
}
|
|
146
|
+
if (stableUsd !== null)
|
|
147
|
+
return stableUsd;
|
|
115
148
|
if (v4Usd !== null)
|
|
116
149
|
return v4Usd;
|
|
117
150
|
throw error;
|
|
118
151
|
}
|
|
119
152
|
}
|
|
120
|
-
async function _priceViaDirectStablePool(token, oneToken, poolHelper, stable, stableDecimals) {
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const amountToReceive = BigInt(route.data.amountToReceive);
|
|
135
|
-
if (amountToReceive === 0n)
|
|
153
|
+
async function _priceViaDirectStablePool(token, oneToken, poolHelper, stable, stableDecimals, provider) {
|
|
154
|
+
const stableUnit = Token.unitFor(stableDecimals);
|
|
155
|
+
const toUsd1e18 = (amount) => (amount * 10n ** 18n) / stableUnit;
|
|
156
|
+
const quotes = [];
|
|
157
|
+
const v2Amount = await _quoteDirectV2StablePools(token, stable, oneToken, poolHelper, provider);
|
|
158
|
+
if (v2Amount > 0n)
|
|
159
|
+
quotes.push(v2Amount);
|
|
160
|
+
const v3Amount = await _quoteDirectV3StablePools(token, stable, oneToken, poolHelper, provider);
|
|
161
|
+
if (v3Amount > 0n)
|
|
162
|
+
quotes.push(v3Amount);
|
|
163
|
+
const aeroV3Amount = await _quoteDirectAerodromeV3StablePool(token, stable, oneToken, poolHelper, provider);
|
|
164
|
+
if (aeroV3Amount > 0n)
|
|
165
|
+
quotes.push(aeroV3Amount);
|
|
166
|
+
if (quotes.length === 0)
|
|
136
167
|
return null;
|
|
137
|
-
|
|
168
|
+
const best = quotes.reduce((currentBest, amount) => amount > currentBest ? amount : currentBest);
|
|
169
|
+
return toUsd1e18(best);
|
|
170
|
+
}
|
|
171
|
+
async function _quoteDirectV2StablePools(token, stable, oneToken, poolHelper, provider) {
|
|
172
|
+
let best = 0n;
|
|
173
|
+
const quoteStandardV2 = async (factoryAddress, routerAddress) => {
|
|
174
|
+
if (!factoryAddress || !routerAddress)
|
|
175
|
+
return;
|
|
176
|
+
const factory = new Contract(factoryAddress, V2_FACTORY_ABI, provider);
|
|
177
|
+
const pairAddress = await factory
|
|
178
|
+
.getPair(token, stable)
|
|
179
|
+
.catch(() => ZeroAddress);
|
|
180
|
+
if (pairAddress === ZeroAddress)
|
|
181
|
+
return;
|
|
182
|
+
const router = new Contract(routerAddress, V2_ROUTER_ABI, provider);
|
|
183
|
+
const amounts = await router
|
|
184
|
+
.getAmountsOut(oneToken, [token, stable])
|
|
185
|
+
.catch(() => null);
|
|
186
|
+
const amountOut = amounts?.at(-1) ?? 0n;
|
|
187
|
+
if (amountOut > best)
|
|
188
|
+
best = amountOut;
|
|
189
|
+
};
|
|
190
|
+
const quoteAerodromeV2 = async (factoryAddress, routerAddress) => {
|
|
191
|
+
if (!factoryAddress || !routerAddress)
|
|
192
|
+
return;
|
|
193
|
+
const factory = new Contract(factoryAddress, AERO_V2_FACTORY_ABI, provider);
|
|
194
|
+
const router = new Contract(routerAddress, AERO_V2_ROUTER_ABI, provider);
|
|
195
|
+
await Promise.all([false, true].map(async (stablePool) => {
|
|
196
|
+
const poolAddress = await factory
|
|
197
|
+
.getPool(token, stable, stablePool)
|
|
198
|
+
.catch(() => ZeroAddress);
|
|
199
|
+
if (poolAddress === ZeroAddress)
|
|
200
|
+
return;
|
|
201
|
+
const amounts = await router
|
|
202
|
+
.getAmountsOut(oneToken, [
|
|
203
|
+
{
|
|
204
|
+
from: token,
|
|
205
|
+
to: stable,
|
|
206
|
+
stable: stablePool,
|
|
207
|
+
factory: factoryAddress,
|
|
208
|
+
},
|
|
209
|
+
])
|
|
210
|
+
.catch(() => null);
|
|
211
|
+
const amountOut = amounts?.at(-1) ?? 0n;
|
|
212
|
+
if (amountOut > best)
|
|
213
|
+
best = amountOut;
|
|
214
|
+
}));
|
|
215
|
+
};
|
|
216
|
+
await Promise.all([
|
|
217
|
+
quoteStandardV2(poolHelper.addresses.factories.uniswapV2, poolHelper.addresses.routers.uniswapV2),
|
|
218
|
+
quoteStandardV2(poolHelper.addresses.factories.pancakeV2, poolHelper.addresses.routers.pancakeV2),
|
|
219
|
+
quoteAerodromeV2(poolHelper.addresses.factories.aerodromeV2, poolHelper.addresses.routers.aerodromeV2),
|
|
220
|
+
]);
|
|
221
|
+
return best;
|
|
222
|
+
}
|
|
223
|
+
async function _quoteDirectV3StablePools(token, stable, oneToken, poolHelper, provider) {
|
|
224
|
+
let best = 0n;
|
|
225
|
+
const quoteFactory = async (factoryAddress, quoterAddress, fees) => {
|
|
226
|
+
if (!factoryAddress || !quoterAddress)
|
|
227
|
+
return;
|
|
228
|
+
const factory = new Contract(factoryAddress, V3_FACTORY_ABI, provider);
|
|
229
|
+
const quoter = new Contract(quoterAddress, V3_QUOTER_ABI, provider);
|
|
230
|
+
await Promise.all(fees.map(async (fee) => {
|
|
231
|
+
const poolAddress = await factory
|
|
232
|
+
.getPool(token, stable, fee)
|
|
233
|
+
.catch(() => ZeroAddress);
|
|
234
|
+
if (poolAddress === ZeroAddress)
|
|
235
|
+
return;
|
|
236
|
+
const quote = await quoter.quoteExactInputSingle.staticCall({
|
|
237
|
+
tokenIn: token,
|
|
238
|
+
tokenOut: stable,
|
|
239
|
+
amountIn: oneToken,
|
|
240
|
+
fee: BigInt(fee),
|
|
241
|
+
sqrtPriceLimitX96: 0n,
|
|
242
|
+
}).catch(() => null);
|
|
243
|
+
const amountOut = quote?.amountOut ?? 0n;
|
|
244
|
+
if (amountOut > best)
|
|
245
|
+
best = amountOut;
|
|
246
|
+
}));
|
|
247
|
+
};
|
|
248
|
+
await Promise.all([
|
|
249
|
+
quoteFactory(poolHelper.addresses.factories.uniswapV3, poolHelper.addresses.quoters.uniswapV3, UNISWAP_V3_FEES),
|
|
250
|
+
quoteFactory(poolHelper.addresses.factories.pancakeV3, poolHelper.addresses.quoters.pancakeV3, PANCAKE_V3_FEES),
|
|
251
|
+
]);
|
|
252
|
+
return best;
|
|
253
|
+
}
|
|
254
|
+
async function _quoteDirectAerodromeV3StablePool(token, stable, oneToken, poolHelper, provider) {
|
|
255
|
+
const quoterAddress = poolHelper.addresses.quoters.aerodromeV3;
|
|
256
|
+
if (!quoterAddress)
|
|
257
|
+
return 0n;
|
|
258
|
+
const factories = [
|
|
259
|
+
poolHelper.addresses.factories.aerodromeV3,
|
|
260
|
+
poolHelper.addresses.factories.aerodromeV3Bis,
|
|
261
|
+
].filter((factory) => Boolean(factory));
|
|
262
|
+
if (factories.length === 0)
|
|
263
|
+
return 0n;
|
|
264
|
+
const quoter = new Contract(quoterAddress, AERO_V3_QUOTER_ABI, provider);
|
|
265
|
+
let best = 0n;
|
|
266
|
+
await Promise.all(factories.flatMap((factoryAddress) => {
|
|
267
|
+
const factory = new Contract(factoryAddress, AERO_V3_FACTORY_ABI, provider);
|
|
268
|
+
return AERODROME_V3_TICK_SPACINGS.map(async (tickSpacing) => {
|
|
269
|
+
const poolAddress = await factory
|
|
270
|
+
.getPool(token, stable, tickSpacing)
|
|
271
|
+
.catch(() => ZeroAddress);
|
|
272
|
+
if (poolAddress === ZeroAddress)
|
|
273
|
+
return;
|
|
274
|
+
const quote = await quoter.quoteExactInputSingle.staticCall({
|
|
275
|
+
tokenIn: token,
|
|
276
|
+
tokenOut: stable,
|
|
277
|
+
amountIn: oneToken,
|
|
278
|
+
tickSpacing: BigInt(tickSpacing),
|
|
279
|
+
sqrtPriceLimitX96: 0n,
|
|
280
|
+
}).catch(() => null);
|
|
281
|
+
const amountOut = quote?.amountOut ?? 0n;
|
|
282
|
+
if (amountOut > best)
|
|
283
|
+
best = amountOut;
|
|
284
|
+
});
|
|
285
|
+
}));
|
|
286
|
+
return best;
|
|
138
287
|
}
|
|
139
288
|
async function _priceViaV4Pools(token, oneToken, getWethUsd, ctx) {
|
|
140
289
|
const addresses = getGuruProtocolAddresses(ctx.chainId);
|
package/dist/router/pathCache.js
CHANGED
|
@@ -32,10 +32,18 @@ export function extractPathFromResponse(dex, response) {
|
|
|
32
32
|
const swapPath = swap.swapExchanges[0].data.path;
|
|
33
33
|
if (!Array.isArray(swapPath) ||
|
|
34
34
|
typeof swapPath[0]?.tokenIn !== 'string' ||
|
|
35
|
-
|
|
35
|
+
swapPath[0]?.fee == null) {
|
|
36
36
|
throw new Error('Unexpected V3 path structure');
|
|
37
37
|
}
|
|
38
|
-
combinedPath.push(...swapPath)
|
|
38
|
+
combinedPath.push(...swapPath.map((hop) => ({
|
|
39
|
+
tokenIn: hop.tokenIn,
|
|
40
|
+
tokenOut: hop.tokenOut,
|
|
41
|
+
fee: String(dex === 'AerodromeV3'
|
|
42
|
+
? (hop.tickSpacing ?? hop.fee)
|
|
43
|
+
: hop.fee),
|
|
44
|
+
currentFee: hop.currentFee,
|
|
45
|
+
tickSpacing: hop.tickSpacing,
|
|
46
|
+
})));
|
|
39
47
|
}
|
|
40
48
|
return { type: 'v3', path: combinedPath, hops: combinedPath.length };
|
|
41
49
|
}
|
|
@@ -21,6 +21,9 @@ const V2_PAIR_ABI = [
|
|
|
21
21
|
const V3_FACTORY_ABI = [
|
|
22
22
|
'function getPool(address tokenA, address tokenB, uint24 fee) view returns (address pool)',
|
|
23
23
|
];
|
|
24
|
+
const AERO_V3_FACTORY_ABI = [
|
|
25
|
+
'function getPool(address tokenA, address tokenB, int24 tickSpacing) view returns (address pool)',
|
|
26
|
+
];
|
|
24
27
|
const V3_POOL_ABI = ['function fee() view returns (uint24)'];
|
|
25
28
|
const AERO_FACTORY_ABI = [
|
|
26
29
|
'function getPool(address tokenA, address tokenB, bool stable) view returns (address)',
|
|
@@ -260,7 +263,9 @@ export default class PoolHelper {
|
|
|
260
263
|
}
|
|
261
264
|
}
|
|
262
265
|
else {
|
|
263
|
-
const factory =
|
|
266
|
+
const factory = dex.kind === 'aerodrome'
|
|
267
|
+
? connect(factoryAddress, AERO_V3_FACTORY_ABI, this.provider)
|
|
268
|
+
: connect(factoryAddress, V3_FACTORY_ABI, this.provider);
|
|
264
269
|
await Promise.all(dex.feeTiers.map(async (feeTier) => {
|
|
265
270
|
try {
|
|
266
271
|
const poolAddress = await factory.getPool(token, weth, feeTier);
|
package/dist/router/types.d.ts
CHANGED
package/dist/router/velora.d.ts
CHANGED
package/dist/router/velora.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Contract, solidityPacked } from 'ethers';
|
|
2
2
|
import { TOLL_DIVISOR_20BPS } from '../constants.js';
|
|
3
|
-
import { AerodromeV2Adapter__factory, IPancakeQuoterV2__factory, UniswapV2Adapter__factory, UniswapV3Adapter__factory, UniswapV4Adapter__factory, } from '../typechain/index.js';
|
|
3
|
+
import { AerodromeV3Adapter__factory, AerodromeV2Adapter__factory, IPancakeQuoterV2__factory, UniswapV2Adapter__factory, UniswapV3Adapter__factory, UniswapV4Adapter__factory, } from '../typechain/index.js';
|
|
4
4
|
import { connectV4Quoter, toAdapterPathKeys } from './getUniswapV4Route.js';
|
|
5
5
|
import { SWAP_DEADLINE_SECONDS } from './constants.js';
|
|
6
6
|
import { finalizeRouteQuote } from './finalizeRoute.js';
|
|
@@ -10,12 +10,18 @@ const V2_ROUTER_ABI = [
|
|
|
10
10
|
const AERO_V2_ROUTER_ABI = [
|
|
11
11
|
'function getAmountsOut(uint256 amountIn, (address from, address to, bool stable, address factory)[] routes) external view returns (uint256[] amounts)',
|
|
12
12
|
];
|
|
13
|
+
const AERO_V3_QUOTER_ABI = [
|
|
14
|
+
'function quoteExactInputSingle((address tokenIn, address tokenOut, uint256 amountIn, int24 tickSpacing, uint160 sqrtPriceLimitX96) params) returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)',
|
|
15
|
+
];
|
|
13
16
|
function connectV2Router(address, provider) {
|
|
14
17
|
return new Contract(address, V2_ROUTER_ABI, provider);
|
|
15
18
|
}
|
|
16
19
|
function connectAeroV2Router(address, provider) {
|
|
17
20
|
return new Contract(address, AERO_V2_ROUTER_ABI, provider);
|
|
18
21
|
}
|
|
22
|
+
function connectAeroV3Quoter(address, provider) {
|
|
23
|
+
return new Contract(address, AERO_V3_QUOTER_ABI, provider);
|
|
24
|
+
}
|
|
19
25
|
function connectV3Quoter(address, provider) {
|
|
20
26
|
return IPancakeQuoterV2__factory.connect(address, provider);
|
|
21
27
|
}
|
|
@@ -33,6 +39,12 @@ export function buildVeloraDexConfig(addresses) {
|
|
|
33
39
|
routerAddress: addresses.routers.aerodromeV2,
|
|
34
40
|
};
|
|
35
41
|
}
|
|
42
|
+
if (addresses.adapters.aerodromeV3 && addresses.quoters.aerodromeV3) {
|
|
43
|
+
cfg.AerodromeV3 = {
|
|
44
|
+
adapter: addresses.adapters.aerodromeV3,
|
|
45
|
+
quoterAddress: addresses.quoters.aerodromeV3,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
36
48
|
if (addresses.adapters.pancakeV2 && addresses.routers.pancakeV2) {
|
|
37
49
|
cfg.PancakeSwapV2 = {
|
|
38
50
|
adapter: addresses.adapters.pancakeV2,
|
|
@@ -212,6 +224,7 @@ export async function getRouteFromPath({ chainId, addresses, provider, simulator
|
|
|
212
224
|
effectiveSlippageBps,
|
|
213
225
|
};
|
|
214
226
|
}
|
|
227
|
+
case 'AerodromeV3':
|
|
215
228
|
case 'PancakeSwapV3':
|
|
216
229
|
case 'UniswapV3': {
|
|
217
230
|
if (cachedPath.type !== 'v3') {
|
|
@@ -222,12 +235,40 @@ export async function getRouteFromPath({ chainId, addresses, provider, simulator
|
|
|
222
235
|
throw new Error(`DEX ${dex} not supported on chainId ${chainId}`);
|
|
223
236
|
}
|
|
224
237
|
const adapter = entry.adapter;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
238
|
+
let encodedPath;
|
|
239
|
+
let grossAmountToReceive;
|
|
240
|
+
let blockNumber;
|
|
241
|
+
if (dex === 'AerodromeV3') {
|
|
242
|
+
if (cachedPath.path.length !== 1) {
|
|
243
|
+
throw new Error('Aerodrome V3 multi-hop not supported');
|
|
244
|
+
}
|
|
245
|
+
const [hop] = cachedPath.path;
|
|
246
|
+
const tickSpacing = BigInt(hop.fee);
|
|
247
|
+
encodedPath = solidityPacked(['address', 'uint24', 'address'], [hop.tokenIn, Number(tickSpacing), hop.tokenOut]);
|
|
248
|
+
const quoter = connectAeroV3Quoter(entry.quoterAddress, provider);
|
|
249
|
+
const [quote, currentBlockNumber] = await Promise.all([
|
|
250
|
+
quoter.quoteExactInputSingle.staticCall({
|
|
251
|
+
tokenIn: hop.tokenIn,
|
|
252
|
+
tokenOut: hop.tokenOut,
|
|
253
|
+
amountIn,
|
|
254
|
+
tickSpacing,
|
|
255
|
+
sqrtPriceLimitX96: 0n,
|
|
256
|
+
}),
|
|
257
|
+
provider.getBlockNumber(),
|
|
258
|
+
]);
|
|
259
|
+
grossAmountToReceive = quote.amountOut;
|
|
260
|
+
blockNumber = currentBlockNumber;
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
const quoter = connectV3Quoter(entry.quoterAddress, provider);
|
|
264
|
+
encodedPath = encodeV3Path(cachedPath.path);
|
|
265
|
+
const [quote, currentBlockNumber] = await Promise.all([
|
|
266
|
+
quoter.quoteExactInput.staticCall(encodedPath, amountIn),
|
|
267
|
+
provider.getBlockNumber(),
|
|
268
|
+
]);
|
|
269
|
+
grossAmountToReceive = quote.amountOut;
|
|
270
|
+
blockNumber = currentBlockNumber;
|
|
271
|
+
}
|
|
231
272
|
let amountQuoted = grossAmountToReceive;
|
|
232
273
|
let amountToSend = amountIn;
|
|
233
274
|
if (toll.amount === 0n) {
|
|
@@ -238,7 +279,10 @@ export async function getRouteFromPath({ chainId, addresses, provider, simulator
|
|
|
238
279
|
amountToSend += toll.amount;
|
|
239
280
|
}
|
|
240
281
|
const deadline = Math.floor(Date.now() / 1000) + SWAP_DEADLINE_SECONDS;
|
|
241
|
-
const
|
|
282
|
+
const swapInterface = dex === 'AerodromeV3'
|
|
283
|
+
? AerodromeV3Adapter__factory.createInterface()
|
|
284
|
+
: UniswapV3Adapter__factory.createInterface();
|
|
285
|
+
const buildCallDataForAmount = (amountToReceive) => swapInterface.encodeFunctionData('executeSwap', [
|
|
242
286
|
{
|
|
243
287
|
amountToSend,
|
|
244
288
|
amountToReceive,
|