@paraswap/dex-lib 3.4.2-balancer-v2-single-swap.0 → 3.4.2
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/README.md +377 -377
- package/build/config.js +9 -5
- package/build/config.js.map +1 -1
- package/build/dex/algebra/algebra.js +25 -25
- package/build/dex/balancer-v1/balancer-v1.js +34 -34
- package/build/dex/balancer-v2/balancer-v2.d.ts +1 -1
- package/build/dex/balancer-v2/balancer-v2.js +65 -78
- package/build/dex/balancer-v2/balancer-v2.js.map +1 -1
- package/build/dex/camelot/camelot.js +27 -27
- package/build/dex/kyberdmm/kyberdmm.js +27 -27
- package/build/dex/pancakeswap-v3/pancakeswap-v3.js +25 -25
- package/build/dex/solidly/solidly.js +27 -27
- package/build/dex/solidly-v3/solidly-v3.js +25 -25
- package/build/dex/swaap-v2/config.js +15 -0
- package/build/dex/swaap-v2/config.js.map +1 -1
- package/build/dex/uniswap-v2/uniswap-v2.js +26 -26
- package/build/dex/uniswap-v3/uniswap-v3.js +25 -25
- package/funding.json +5 -5
- package/package.json +1 -1
- package/src/config.ts +500 -496
- package/src/constants.ts +67 -67
- package/src/dex/aave-v2/aave-v2.ts +409 -409
- package/src/dex/aave-v3/aave-v3.ts +320 -320
- package/src/dex/algebra/algebra.ts +1180 -1180
- package/src/dex/angle-staked-stable/angle-staked-stable.ts +347 -347
- package/src/dex/augustus-rfq.ts +180 -180
- package/src/dex/bProtocol/bProtocol.ts +108 -108
- package/src/dex/balancer-v1/balancer-v1.ts +572 -572
- package/src/dex/balancer-v2/balancer-v2-e2e.test.ts +1699 -1699
- package/src/dex/balancer-v2/balancer-v2.ts +1669 -1701
- package/src/dex/bancor/bancor.ts +128 -128
- package/src/dex/camelot/camelot.ts +873 -873
- package/src/dex/compound/compound.ts +107 -107
- package/src/dex/curve-v1/config.ts +1179 -1179
- package/src/dex/curve-v1/curve-v1-e2e.test.ts +507 -507
- package/src/dex/curve-v1/curve-v1.ts +1315 -1315
- package/src/dex/curve-v1-factory/config.ts +1018 -1018
- package/src/dex/curve-v1-factory/curve-v1-factory.ts +1288 -1288
- package/src/dex/curve-v2/curve-v2.ts +440 -440
- package/src/dex/dexalot/dexalot.ts +1100 -1100
- package/src/dex/dodo-v1/dodo-v1.ts +132 -132
- package/src/dex/dodo-v2.ts +266 -266
- package/src/dex/etherfi.ts +239 -239
- package/src/dex/generic-rfq/generic-rfq.ts +431 -431
- package/src/dex/gmx/gmx.ts +321 -321
- package/src/dex/hashflow/hashflow.ts +1135 -1135
- package/src/dex/idex.ts +254 -254
- package/src/dex/index.ts +357 -357
- package/src/dex/jarvis-v6/jarvis-v6.ts +509 -509
- package/src/dex/jarvis.ts +262 -262
- package/src/dex/kyberdmm/kyberdmm.ts +649 -649
- package/src/dex/lido/lido.ts +110 -110
- package/src/dex/maker-psm/maker-psm.ts +592 -592
- package/src/dex/maverick-v1/maverick-v1.ts +537 -537
- package/src/dex/nerve/config.ts +635 -635
- package/src/dex/nerve/nerve-e2e.test.ts +731 -731
- package/src/dex/nerve/nerve-events.test.ts +911 -911
- package/src/dex/nerve/nerve.ts +467 -467
- package/src/dex/onebit/onebit.ts +113 -113
- package/src/dex/pancakeswap-v3/pancakeswap-v3.ts +1150 -1150
- package/src/dex/paraswap-limit-orders/config.ts +60 -60
- package/src/dex/paraswap-limit-orders/paraswap-limit-orders-e2e.test.ts +137 -137
- package/src/dex/paraswap-limit-orders/paraswap-limit-orders-integration.test.ts +328 -328
- package/src/dex/paraswap-limit-orders/paraswap-limit-orders.ts +631 -631
- package/src/dex/polygon-migrator/polygon-migrator.ts +194 -194
- package/src/dex/quick-perps/quick-perps.ts +337 -337
- package/src/dex/quickswap/config.ts +16 -16
- package/src/dex/quickswap/quickswap-e2e.test.ts +384 -384
- package/src/dex/smoothy/smoothy.ts +110 -110
- package/src/dex/solidly/config.ts +225 -225
- package/src/dex/solidly/solidly-e2e.test.ts +1421 -1421
- package/src/dex/solidly/solidly-integration.test.ts +1753 -1753
- package/src/dex/solidly/solidly.ts +687 -687
- package/src/dex/solidly-v3/solidly-v3.ts +968 -968
- package/src/dex/spark/spark.ts +284 -284
- package/src/dex/stable-pool/stable-pool.ts +129 -129
- package/src/dex/swaap-v2/config.ts +15 -0
- package/src/dex/swaap-v2/swaap-v2-e2e.test.ts +233 -17
- package/src/dex/swaap-v2/swaap-v2-integration.test.ts +1 -1
- package/src/dex/swaap-v2/swaap-v2.ts +1056 -1056
- package/src/dex/swell/swell.ts +312 -312
- package/src/dex/synthetix/synthetix.ts +420 -420
- package/src/dex/trader-joe-v2.1/trader-joe-v2.1.ts +180 -180
- package/src/dex/uniswap-v2/config.ts +637 -637
- package/src/dex/uniswap-v2/constants.ts +58 -58
- package/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts +1257 -1257
- package/src/dex/uniswap-v2/uniswap-v2-e2e-base.test.ts +42 -42
- package/src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts +1295 -1295
- package/src/dex/uniswap-v2/uniswap-v2-e2e-mainnet.test.ts +1834 -1834
- package/src/dex/uniswap-v2/uniswap-v2-e2e-polygon.test.ts +871 -871
- package/src/dex/uniswap-v2/uniswap-v2.ts +1117 -1117
- package/src/dex/uniswap-v3/uniswap-v3.ts +1501 -1501
- package/src/dex/uniswap-v3.ts +242 -242
- package/src/dex/weth/config.ts +73 -73
- package/src/dex/weth/weth.ts +230 -230
- package/src/dex/wombat/wombat.ts +467 -467
- package/src/dex/woo-fi-v2/woo-fi-v2.ts +529 -529
- package/src/dex/wsteth/wsteth.ts +304 -304
- package/src/dex/zerox/index.ts +328 -328
- package/src/executor/Executor01BytecodeBuilder.ts +474 -474
- package/src/executor/Executor02BytecodeBuilder.ts +1392 -1392
- package/src/executor/ExecutorBytecodeBuilder.ts +390 -390
- package/src/executor/ExecutorDetector.ts +131 -131
- package/src/executor/constants.ts +66 -66
- package/src/executor/executor01-bytecode-builder-e2e.test.ts +1478 -1478
- package/src/executor/utils.ts +62 -62
- package/src/router/simpleswap.ts +366 -366
- package/src/types.ts +342 -342
- package/tests/constants-e2e.ts +1632 -1622
- package/tests/generate-new-limit-order.ts +107 -107
|
@@ -1,509 +1,509 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Token,
|
|
3
|
-
Address,
|
|
4
|
-
ExchangePrices,
|
|
5
|
-
AdapterExchangeParam,
|
|
6
|
-
SimpleExchangeParam,
|
|
7
|
-
PoolLiquidity,
|
|
8
|
-
Logger,
|
|
9
|
-
PoolPrices,
|
|
10
|
-
NumberAsString,
|
|
11
|
-
DexExchangeParam,
|
|
12
|
-
} from '../../types';
|
|
13
|
-
import { SwapSide, Network } from '../../constants';
|
|
14
|
-
import { getDexKeysWithNetwork, getBigIntPow } from '../../utils';
|
|
15
|
-
import { IDex } from '../../dex/idex';
|
|
16
|
-
import { IDexHelper } from '../../dex-helper/idex-helper';
|
|
17
|
-
import {
|
|
18
|
-
JarvisSwapFunctions,
|
|
19
|
-
JarvisV6Data,
|
|
20
|
-
JarvisV6Params,
|
|
21
|
-
JarvisV6SystemMaxVars,
|
|
22
|
-
PoolConfig,
|
|
23
|
-
PoolState,
|
|
24
|
-
} from './types';
|
|
25
|
-
import JarvisV6PoolABI from '../../abi/jarvis/jarvis-v6-pool.json';
|
|
26
|
-
import { SimpleExchange } from '../simple-exchange';
|
|
27
|
-
import { JarvisV6Config, Adapters } from './config';
|
|
28
|
-
import { JarvisV6EventPool } from './jarvis-v6-events';
|
|
29
|
-
import {
|
|
30
|
-
getJarvisPoolFromTokens,
|
|
31
|
-
getJarvisSwapFunction,
|
|
32
|
-
getOnChainState,
|
|
33
|
-
THIRTY_MINUTES,
|
|
34
|
-
convertToNewDecimals,
|
|
35
|
-
} from './utils';
|
|
36
|
-
import { Interface } from '@ethersproject/abi';
|
|
37
|
-
import { BI_POWS } from '../../bigint-constants';
|
|
38
|
-
import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
|
|
39
|
-
import { Contract } from 'web3-eth-contract';
|
|
40
|
-
import SynthereumPriceFeedABI from '../../abi/jarvis/SynthereumPriceFeed.json';
|
|
41
|
-
|
|
42
|
-
const POOL_CACHE_REFRESH_INTERVAL = 60 * 5; // 5 minutes
|
|
43
|
-
|
|
44
|
-
export class JarvisV6
|
|
45
|
-
extends SimpleExchange
|
|
46
|
-
implements IDex<JarvisV6Data, JarvisV6Params>
|
|
47
|
-
{
|
|
48
|
-
protected eventPools: { [poolAddress: string]: JarvisV6EventPool };
|
|
49
|
-
|
|
50
|
-
// opt out of pool allocation as dex allows for constant price swaps
|
|
51
|
-
readonly hasConstantPriceLargeAmounts = true;
|
|
52
|
-
readonly isFeeOnTransferSupported = false;
|
|
53
|
-
|
|
54
|
-
public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
|
|
55
|
-
getDexKeysWithNetwork(JarvisV6Config);
|
|
56
|
-
|
|
57
|
-
protected poolInterface: Interface = new Interface(JarvisV6PoolABI);
|
|
58
|
-
protected priceFeedContract: Contract;
|
|
59
|
-
|
|
60
|
-
logger: Logger;
|
|
61
|
-
constructor(
|
|
62
|
-
protected network: Network,
|
|
63
|
-
dexKey: string,
|
|
64
|
-
protected dexHelper: IDexHelper,
|
|
65
|
-
protected adapters = Adapters[network],
|
|
66
|
-
protected poolConfigs: PoolConfig[] = JarvisV6Config[dexKey][network].pools,
|
|
67
|
-
protected priceFeedAddress: Address = JarvisV6Config[dexKey][network]
|
|
68
|
-
.priceFeedAddress,
|
|
69
|
-
) {
|
|
70
|
-
super(dexHelper, dexKey);
|
|
71
|
-
this.logger = dexHelper.getLogger(dexKey);
|
|
72
|
-
this.eventPools = {};
|
|
73
|
-
|
|
74
|
-
this.priceFeedContract = new dexHelper.web3Provider.eth.Contract(
|
|
75
|
-
SynthereumPriceFeedABI as any,
|
|
76
|
-
priceFeedAddress,
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
poolConfigs.forEach(
|
|
80
|
-
pool =>
|
|
81
|
-
(this.eventPools[pool.address.toLowerCase()] = new JarvisV6EventPool(
|
|
82
|
-
dexKey,
|
|
83
|
-
network,
|
|
84
|
-
dexHelper,
|
|
85
|
-
this.logger,
|
|
86
|
-
pool,
|
|
87
|
-
this.priceFeedAddress,
|
|
88
|
-
this.poolInterface,
|
|
89
|
-
this.priceFeedContract,
|
|
90
|
-
)),
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Initialize pricing is called once in the start of
|
|
95
|
-
// pricing service. It is intended to setup the integration
|
|
96
|
-
// for pricing requests. It is optional for a DEX to
|
|
97
|
-
// implement this function
|
|
98
|
-
async initializePricing(blockNumber: number) {
|
|
99
|
-
const poolStates = await getOnChainState(
|
|
100
|
-
this.dexHelper,
|
|
101
|
-
this.poolConfigs,
|
|
102
|
-
blockNumber,
|
|
103
|
-
{
|
|
104
|
-
poolInterface: this.poolInterface,
|
|
105
|
-
priceFeedContract: this.priceFeedContract,
|
|
106
|
-
},
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
await Promise.all(
|
|
110
|
-
this.poolConfigs.map(async (pool, index) => {
|
|
111
|
-
const eventPool = this.eventPools[pool.address.toLowerCase()];
|
|
112
|
-
await eventPool.initialize(blockNumber, {
|
|
113
|
-
state: poolStates[index],
|
|
114
|
-
});
|
|
115
|
-
}),
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Returns the list of contract adapters (name and index)
|
|
120
|
-
// for a buy/sell. Return null if there are no adapters.
|
|
121
|
-
getAdapters(side: SwapSide): { name: string; index: number }[] | null {
|
|
122
|
-
return this.adapters[side];
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
getEventPool(srcToken: Token, destToken: Token): JarvisV6EventPool | null {
|
|
126
|
-
const pool = getJarvisPoolFromTokens(srcToken, destToken, this.poolConfigs);
|
|
127
|
-
return this.eventPools[pool?.address.toLowerCase()!];
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Returns list of pool identifiers that can be used
|
|
131
|
-
// for a given swap. poolIdentifiers must be unique
|
|
132
|
-
// across DEXes. It is recommended to use
|
|
133
|
-
// ${dexKey}_${poolAddress} as a poolIdentifier
|
|
134
|
-
async getPoolIdentifiers(
|
|
135
|
-
srcToken: Token,
|
|
136
|
-
destToken: Token,
|
|
137
|
-
side: SwapSide,
|
|
138
|
-
blockNumber: number,
|
|
139
|
-
): Promise<string[]> {
|
|
140
|
-
const eventPool = this.getEventPool(srcToken, destToken);
|
|
141
|
-
if (!eventPool) return [];
|
|
142
|
-
return [eventPool.getIdentifier()];
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
async getPoolState(
|
|
146
|
-
pool: JarvisV6EventPool,
|
|
147
|
-
blockNumber: number,
|
|
148
|
-
): Promise<PoolState> {
|
|
149
|
-
const eventState = pool.getState(blockNumber);
|
|
150
|
-
if (eventState) return eventState;
|
|
151
|
-
const onChainState = await pool.generateState(blockNumber);
|
|
152
|
-
pool.setState(onChainState, blockNumber);
|
|
153
|
-
return onChainState;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Returns pool prices for amounts.
|
|
157
|
-
// If limitPools is defined only pools in limitPools
|
|
158
|
-
// should be used. If limitPools is undefined then
|
|
159
|
-
// any pools can be used.
|
|
160
|
-
// Pair
|
|
161
|
-
async getPricesVolume(
|
|
162
|
-
srcToken: Token,
|
|
163
|
-
destToken: Token,
|
|
164
|
-
amounts: bigint[],
|
|
165
|
-
side: SwapSide,
|
|
166
|
-
blockNumber: number,
|
|
167
|
-
limitPools?: string[], // unusued since DEX is constant price, safe to reuse pools
|
|
168
|
-
): Promise<null | ExchangePrices<JarvisV6Data>> {
|
|
169
|
-
if (side !== SwapSide.SELL) return null;
|
|
170
|
-
|
|
171
|
-
const eventPool = this.getEventPool(srcToken, destToken);
|
|
172
|
-
if (!eventPool) return null;
|
|
173
|
-
|
|
174
|
-
const poolAddress = eventPool.poolConfig.address.toLowerCase();
|
|
175
|
-
const poolIdentifier = eventPool.getIdentifier();
|
|
176
|
-
|
|
177
|
-
const poolState = await this.getPoolState(eventPool, blockNumber);
|
|
178
|
-
|
|
179
|
-
const unitVolume = getBigIntPow(srcToken.decimals);
|
|
180
|
-
|
|
181
|
-
const swapFunction = getJarvisSwapFunction(srcToken, eventPool.poolConfig);
|
|
182
|
-
const systemMaxVars = await this.getSystemMaxVars(poolAddress, blockNumber);
|
|
183
|
-
|
|
184
|
-
const [unit, ...prices] = this.computePrices(
|
|
185
|
-
[unitVolume, ...amounts],
|
|
186
|
-
swapFunction,
|
|
187
|
-
systemMaxVars,
|
|
188
|
-
eventPool.poolConfig,
|
|
189
|
-
poolState,
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
return [
|
|
193
|
-
{
|
|
194
|
-
prices,
|
|
195
|
-
unit,
|
|
196
|
-
data: {
|
|
197
|
-
swapFunction,
|
|
198
|
-
poolAddress,
|
|
199
|
-
},
|
|
200
|
-
poolAddresses: [poolAddress],
|
|
201
|
-
exchange: this.dexKey,
|
|
202
|
-
gasCost: 475 * 1000, //between 450-500k gas
|
|
203
|
-
poolIdentifier,
|
|
204
|
-
},
|
|
205
|
-
];
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
async getSystemMaxVars(
|
|
209
|
-
poolAddress: Address,
|
|
210
|
-
blockNumber: number,
|
|
211
|
-
): Promise<JarvisV6SystemMaxVars> {
|
|
212
|
-
const cacheKey = `${this.dexKey}_systemMaxVars_${poolAddress}`;
|
|
213
|
-
const cachedSystemMaxVars = await this.dexHelper.cache.getAndCacheLocally(
|
|
214
|
-
this.dexKey,
|
|
215
|
-
this.network,
|
|
216
|
-
cacheKey,
|
|
217
|
-
POOL_CACHE_REFRESH_INTERVAL,
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
if (cachedSystemMaxVars) {
|
|
221
|
-
const { maxTokensCapacity, totalSyntheticTokens } =
|
|
222
|
-
JSON.parse(cachedSystemMaxVars);
|
|
223
|
-
|
|
224
|
-
return {
|
|
225
|
-
maxTokensCapacity: BigInt(maxTokensCapacity),
|
|
226
|
-
totalSyntheticTokens: BigInt(totalSyntheticTokens),
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const multiContract = this.dexHelper.multiContract;
|
|
231
|
-
const encodedResp = (await multiContract.methods
|
|
232
|
-
.aggregate([
|
|
233
|
-
{
|
|
234
|
-
target: poolAddress,
|
|
235
|
-
callData: this.poolInterface.encodeFunctionData(
|
|
236
|
-
'maxTokensCapacity',
|
|
237
|
-
[],
|
|
238
|
-
),
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
target: poolAddress,
|
|
242
|
-
callData: this.poolInterface.encodeFunctionData(
|
|
243
|
-
'totalSyntheticTokens',
|
|
244
|
-
[],
|
|
245
|
-
),
|
|
246
|
-
},
|
|
247
|
-
])
|
|
248
|
-
.call({}, blockNumber)) as { returnData: [string, string] };
|
|
249
|
-
|
|
250
|
-
const maxTokensCapacity = this.poolInterface
|
|
251
|
-
.decodeFunctionResult('maxTokensCapacity', encodedResp.returnData[0])[0]
|
|
252
|
-
.toString();
|
|
253
|
-
const totalSyntheticTokens = this.poolInterface
|
|
254
|
-
.decodeFunctionResult(
|
|
255
|
-
'totalSyntheticTokens',
|
|
256
|
-
encodedResp.returnData[1],
|
|
257
|
-
)[0]
|
|
258
|
-
.toString();
|
|
259
|
-
|
|
260
|
-
const systemMaxVarStr = JSON.stringify({
|
|
261
|
-
maxTokensCapacity,
|
|
262
|
-
totalSyntheticTokens,
|
|
263
|
-
});
|
|
264
|
-
this.dexHelper.cache.setexAndCacheLocally(
|
|
265
|
-
this.dexKey,
|
|
266
|
-
this.network,
|
|
267
|
-
cacheKey,
|
|
268
|
-
POOL_CACHE_REFRESH_INTERVAL,
|
|
269
|
-
systemMaxVarStr,
|
|
270
|
-
);
|
|
271
|
-
|
|
272
|
-
return {
|
|
273
|
-
maxTokensCapacity: BigInt(maxTokensCapacity),
|
|
274
|
-
totalSyntheticTokens: BigInt(totalSyntheticTokens),
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
computePrices(
|
|
279
|
-
amounts: bigint[],
|
|
280
|
-
swapFunction: JarvisSwapFunctions,
|
|
281
|
-
{ maxTokensCapacity, totalSyntheticTokens }: JarvisV6SystemMaxVars,
|
|
282
|
-
pool: PoolConfig,
|
|
283
|
-
poolState: PoolState,
|
|
284
|
-
): bigint[] {
|
|
285
|
-
return amounts.map(amount => {
|
|
286
|
-
if (swapFunction === JarvisSwapFunctions.MINT) {
|
|
287
|
-
return this.computePriceForMint(
|
|
288
|
-
amount,
|
|
289
|
-
maxTokensCapacity,
|
|
290
|
-
poolState,
|
|
291
|
-
pool.collateralToken.decimals,
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
if (swapFunction === JarvisSwapFunctions.REDEEM) {
|
|
295
|
-
if (amount > totalSyntheticTokens) return 0n;
|
|
296
|
-
|
|
297
|
-
return this.computePriceForRedeem(
|
|
298
|
-
amount,
|
|
299
|
-
poolState,
|
|
300
|
-
pool.collateralToken.decimals,
|
|
301
|
-
);
|
|
302
|
-
}
|
|
303
|
-
return 0n;
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
computePriceForMint(
|
|
308
|
-
amount: bigint,
|
|
309
|
-
maxTokensCapacity: bigint,
|
|
310
|
-
poolState: PoolState,
|
|
311
|
-
collateralDecimalsNumber: number,
|
|
312
|
-
) {
|
|
313
|
-
const feePercentage = poolState.pool.feesPercentage;
|
|
314
|
-
const UsdcPriceFeed = poolState.priceFeed.usdcPrice;
|
|
315
|
-
const syntheticAmount = this.getSyntheticAmountToReceive(
|
|
316
|
-
amount,
|
|
317
|
-
collateralDecimalsNumber,
|
|
318
|
-
UsdcPriceFeed,
|
|
319
|
-
feePercentage,
|
|
320
|
-
);
|
|
321
|
-
return syntheticAmount <= maxTokensCapacity ? syntheticAmount : 0n;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
computePriceForRedeem(
|
|
325
|
-
amount: bigint,
|
|
326
|
-
poolState: PoolState,
|
|
327
|
-
collateralDecimalsNumber: number,
|
|
328
|
-
) {
|
|
329
|
-
const feePercentage = poolState.pool.feesPercentage;
|
|
330
|
-
const UsdcPriceFeed = poolState.priceFeed.usdcPrice;
|
|
331
|
-
return this.getCollateralAmountToReceive(
|
|
332
|
-
amount,
|
|
333
|
-
collateralDecimalsNumber,
|
|
334
|
-
UsdcPriceFeed,
|
|
335
|
-
feePercentage,
|
|
336
|
-
);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
getSyntheticAmountToReceive(
|
|
340
|
-
collateralAmount: bigint,
|
|
341
|
-
collateralDecimals: number,
|
|
342
|
-
UsdcPriceFeed: bigint,
|
|
343
|
-
feePercentage: bigint,
|
|
344
|
-
) {
|
|
345
|
-
let collateralAmountIn18Decimals = convertToNewDecimals(
|
|
346
|
-
collateralAmount,
|
|
347
|
-
collateralDecimals,
|
|
348
|
-
18,
|
|
349
|
-
);
|
|
350
|
-
return (
|
|
351
|
-
((collateralAmountIn18Decimals -
|
|
352
|
-
(collateralAmountIn18Decimals * feePercentage) / BI_POWS[18]) *
|
|
353
|
-
BI_POWS[18]) /
|
|
354
|
-
UsdcPriceFeed
|
|
355
|
-
);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
getCollateralAmountToReceive(
|
|
359
|
-
syntheticAmount: bigint,
|
|
360
|
-
collateralDecimals: number,
|
|
361
|
-
UsdcPriceFeed: bigint,
|
|
362
|
-
feePercentage: bigint,
|
|
363
|
-
) {
|
|
364
|
-
const result =
|
|
365
|
-
(syntheticAmount * UsdcPriceFeed) / BI_POWS[18] -
|
|
366
|
-
(((syntheticAmount * UsdcPriceFeed) / BI_POWS[18]) * feePercentage) /
|
|
367
|
-
BI_POWS[18];
|
|
368
|
-
if (collateralDecimals === 18) return result;
|
|
369
|
-
return convertToNewDecimals(result, 18, collateralDecimals);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Encode params required by the exchange adapter
|
|
373
|
-
// Used for multiSwap, buy & megaSwap
|
|
374
|
-
// Hint: abiCoder.encodeParameter() could be useful
|
|
375
|
-
getAdapterParam(
|
|
376
|
-
srcToken: string,
|
|
377
|
-
destToken: string,
|
|
378
|
-
srcAmount: string,
|
|
379
|
-
destAmount: string,
|
|
380
|
-
data: JarvisV6Data,
|
|
381
|
-
side: SwapSide,
|
|
382
|
-
): AdapterExchangeParam {
|
|
383
|
-
const { swapFunction } = data;
|
|
384
|
-
const type = [JarvisSwapFunctions.MINT, JarvisSwapFunctions.REDEEM].indexOf(
|
|
385
|
-
swapFunction,
|
|
386
|
-
);
|
|
387
|
-
|
|
388
|
-
if (type === undefined) {
|
|
389
|
-
throw new Error(
|
|
390
|
-
`Jarvis: Invalid OpType ${swapFunction}, Should be one of ['mint', 'redeem']`,
|
|
391
|
-
);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const payload = this.abiCoder.encodeParameter(
|
|
395
|
-
{
|
|
396
|
-
ParentStruct: {
|
|
397
|
-
opType: 'uint',
|
|
398
|
-
expiration: 'uint128',
|
|
399
|
-
},
|
|
400
|
-
},
|
|
401
|
-
{
|
|
402
|
-
opType: type,
|
|
403
|
-
expiration: (Date.now() / 1000 + THIRTY_MINUTES).toFixed(0),
|
|
404
|
-
},
|
|
405
|
-
);
|
|
406
|
-
|
|
407
|
-
return {
|
|
408
|
-
targetExchange: data.poolAddress.toLowerCase(),
|
|
409
|
-
payload,
|
|
410
|
-
networkFee: '0',
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// Encode call data used by simpleSwap like routers
|
|
415
|
-
// Used for simpleSwap & simpleBuy
|
|
416
|
-
// Hint: this.buildSimpleParamWithoutWETHConversion
|
|
417
|
-
// could be useful
|
|
418
|
-
async getSimpleParam(
|
|
419
|
-
srcToken: string,
|
|
420
|
-
destToken: string,
|
|
421
|
-
srcAmount: string,
|
|
422
|
-
destAmount: string,
|
|
423
|
-
data: JarvisV6Data,
|
|
424
|
-
side: SwapSide,
|
|
425
|
-
): Promise<SimpleExchangeParam> {
|
|
426
|
-
const { swapFunction } = data;
|
|
427
|
-
const timestamp = (Date.now() / 1000 + THIRTY_MINUTES).toFixed(0);
|
|
428
|
-
|
|
429
|
-
let swapFunctionParams: JarvisV6Params;
|
|
430
|
-
switch (swapFunction) {
|
|
431
|
-
case JarvisSwapFunctions.MINT:
|
|
432
|
-
swapFunctionParams = ['1', srcAmount, timestamp, this.augustusAddress];
|
|
433
|
-
break;
|
|
434
|
-
case JarvisSwapFunctions.REDEEM:
|
|
435
|
-
swapFunctionParams = [srcAmount, '1', timestamp, this.augustusAddress];
|
|
436
|
-
break;
|
|
437
|
-
default:
|
|
438
|
-
throw new Error(`Unknown function ${swapFunction}`);
|
|
439
|
-
}
|
|
440
|
-
const swapData = this.poolInterface.encodeFunctionData(swapFunction, [
|
|
441
|
-
swapFunctionParams,
|
|
442
|
-
]);
|
|
443
|
-
|
|
444
|
-
return this.buildSimpleParamWithoutWETHConversion(
|
|
445
|
-
srcToken,
|
|
446
|
-
srcAmount,
|
|
447
|
-
destToken,
|
|
448
|
-
destAmount,
|
|
449
|
-
swapData,
|
|
450
|
-
data.poolAddress.toLowerCase(),
|
|
451
|
-
);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
getDexParam(
|
|
455
|
-
srcToken: Address,
|
|
456
|
-
destToken: Address,
|
|
457
|
-
srcAmount: NumberAsString,
|
|
458
|
-
destAmount: NumberAsString,
|
|
459
|
-
recipient: Address,
|
|
460
|
-
data: JarvisV6Data,
|
|
461
|
-
side: SwapSide,
|
|
462
|
-
): DexExchangeParam {
|
|
463
|
-
const { swapFunction } = data;
|
|
464
|
-
const timestamp = (Date.now() / 1000 + THIRTY_MINUTES).toFixed(0);
|
|
465
|
-
|
|
466
|
-
let swapFunctionParams: JarvisV6Params;
|
|
467
|
-
switch (swapFunction) {
|
|
468
|
-
case JarvisSwapFunctions.MINT:
|
|
469
|
-
swapFunctionParams = ['1', srcAmount, timestamp, recipient];
|
|
470
|
-
break;
|
|
471
|
-
case JarvisSwapFunctions.REDEEM:
|
|
472
|
-
swapFunctionParams = [srcAmount, '1', timestamp, recipient];
|
|
473
|
-
break;
|
|
474
|
-
default:
|
|
475
|
-
throw new Error(`Unknown function ${swapFunction}`);
|
|
476
|
-
}
|
|
477
|
-
const exchangeData = this.poolInterface.encodeFunctionData(swapFunction, [
|
|
478
|
-
swapFunctionParams,
|
|
479
|
-
]);
|
|
480
|
-
|
|
481
|
-
return {
|
|
482
|
-
needWrapNative: this.needWrapNative,
|
|
483
|
-
dexFuncHasRecipient: true,
|
|
484
|
-
exchangeData,
|
|
485
|
-
targetExchange: data.poolAddress.toLowerCase(),
|
|
486
|
-
returnAmountPos: undefined,
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
// Returns list of top pools based on liquidity. Max
|
|
491
|
-
// limit number pools should be returned.
|
|
492
|
-
async getTopPoolsForToken(
|
|
493
|
-
tokenAddress: Address,
|
|
494
|
-
limit: number,
|
|
495
|
-
): Promise<PoolLiquidity[]> {
|
|
496
|
-
return [];
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
getCalldataGasCost(poolPrices: PoolPrices<JarvisV6Data>): number | number[] {
|
|
500
|
-
return (
|
|
501
|
-
CALLDATA_GAS_COST.DEX_OVERHEAD +
|
|
502
|
-
CALLDATA_GAS_COST.LENGTH_SMALL +
|
|
503
|
-
// opType
|
|
504
|
-
CALLDATA_GAS_COST.INDEX +
|
|
505
|
-
// expiration
|
|
506
|
-
CALLDATA_GAS_COST.TIMESTAMP
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
Token,
|
|
3
|
+
Address,
|
|
4
|
+
ExchangePrices,
|
|
5
|
+
AdapterExchangeParam,
|
|
6
|
+
SimpleExchangeParam,
|
|
7
|
+
PoolLiquidity,
|
|
8
|
+
Logger,
|
|
9
|
+
PoolPrices,
|
|
10
|
+
NumberAsString,
|
|
11
|
+
DexExchangeParam,
|
|
12
|
+
} from '../../types';
|
|
13
|
+
import { SwapSide, Network } from '../../constants';
|
|
14
|
+
import { getDexKeysWithNetwork, getBigIntPow } from '../../utils';
|
|
15
|
+
import { IDex } from '../../dex/idex';
|
|
16
|
+
import { IDexHelper } from '../../dex-helper/idex-helper';
|
|
17
|
+
import {
|
|
18
|
+
JarvisSwapFunctions,
|
|
19
|
+
JarvisV6Data,
|
|
20
|
+
JarvisV6Params,
|
|
21
|
+
JarvisV6SystemMaxVars,
|
|
22
|
+
PoolConfig,
|
|
23
|
+
PoolState,
|
|
24
|
+
} from './types';
|
|
25
|
+
import JarvisV6PoolABI from '../../abi/jarvis/jarvis-v6-pool.json';
|
|
26
|
+
import { SimpleExchange } from '../simple-exchange';
|
|
27
|
+
import { JarvisV6Config, Adapters } from './config';
|
|
28
|
+
import { JarvisV6EventPool } from './jarvis-v6-events';
|
|
29
|
+
import {
|
|
30
|
+
getJarvisPoolFromTokens,
|
|
31
|
+
getJarvisSwapFunction,
|
|
32
|
+
getOnChainState,
|
|
33
|
+
THIRTY_MINUTES,
|
|
34
|
+
convertToNewDecimals,
|
|
35
|
+
} from './utils';
|
|
36
|
+
import { Interface } from '@ethersproject/abi';
|
|
37
|
+
import { BI_POWS } from '../../bigint-constants';
|
|
38
|
+
import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
|
|
39
|
+
import { Contract } from 'web3-eth-contract';
|
|
40
|
+
import SynthereumPriceFeedABI from '../../abi/jarvis/SynthereumPriceFeed.json';
|
|
41
|
+
|
|
42
|
+
const POOL_CACHE_REFRESH_INTERVAL = 60 * 5; // 5 minutes
|
|
43
|
+
|
|
44
|
+
export class JarvisV6
|
|
45
|
+
extends SimpleExchange
|
|
46
|
+
implements IDex<JarvisV6Data, JarvisV6Params>
|
|
47
|
+
{
|
|
48
|
+
protected eventPools: { [poolAddress: string]: JarvisV6EventPool };
|
|
49
|
+
|
|
50
|
+
// opt out of pool allocation as dex allows for constant price swaps
|
|
51
|
+
readonly hasConstantPriceLargeAmounts = true;
|
|
52
|
+
readonly isFeeOnTransferSupported = false;
|
|
53
|
+
|
|
54
|
+
public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
|
|
55
|
+
getDexKeysWithNetwork(JarvisV6Config);
|
|
56
|
+
|
|
57
|
+
protected poolInterface: Interface = new Interface(JarvisV6PoolABI);
|
|
58
|
+
protected priceFeedContract: Contract;
|
|
59
|
+
|
|
60
|
+
logger: Logger;
|
|
61
|
+
constructor(
|
|
62
|
+
protected network: Network,
|
|
63
|
+
dexKey: string,
|
|
64
|
+
protected dexHelper: IDexHelper,
|
|
65
|
+
protected adapters = Adapters[network],
|
|
66
|
+
protected poolConfigs: PoolConfig[] = JarvisV6Config[dexKey][network].pools,
|
|
67
|
+
protected priceFeedAddress: Address = JarvisV6Config[dexKey][network]
|
|
68
|
+
.priceFeedAddress,
|
|
69
|
+
) {
|
|
70
|
+
super(dexHelper, dexKey);
|
|
71
|
+
this.logger = dexHelper.getLogger(dexKey);
|
|
72
|
+
this.eventPools = {};
|
|
73
|
+
|
|
74
|
+
this.priceFeedContract = new dexHelper.web3Provider.eth.Contract(
|
|
75
|
+
SynthereumPriceFeedABI as any,
|
|
76
|
+
priceFeedAddress,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
poolConfigs.forEach(
|
|
80
|
+
pool =>
|
|
81
|
+
(this.eventPools[pool.address.toLowerCase()] = new JarvisV6EventPool(
|
|
82
|
+
dexKey,
|
|
83
|
+
network,
|
|
84
|
+
dexHelper,
|
|
85
|
+
this.logger,
|
|
86
|
+
pool,
|
|
87
|
+
this.priceFeedAddress,
|
|
88
|
+
this.poolInterface,
|
|
89
|
+
this.priceFeedContract,
|
|
90
|
+
)),
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Initialize pricing is called once in the start of
|
|
95
|
+
// pricing service. It is intended to setup the integration
|
|
96
|
+
// for pricing requests. It is optional for a DEX to
|
|
97
|
+
// implement this function
|
|
98
|
+
async initializePricing(blockNumber: number) {
|
|
99
|
+
const poolStates = await getOnChainState(
|
|
100
|
+
this.dexHelper,
|
|
101
|
+
this.poolConfigs,
|
|
102
|
+
blockNumber,
|
|
103
|
+
{
|
|
104
|
+
poolInterface: this.poolInterface,
|
|
105
|
+
priceFeedContract: this.priceFeedContract,
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
await Promise.all(
|
|
110
|
+
this.poolConfigs.map(async (pool, index) => {
|
|
111
|
+
const eventPool = this.eventPools[pool.address.toLowerCase()];
|
|
112
|
+
await eventPool.initialize(blockNumber, {
|
|
113
|
+
state: poolStates[index],
|
|
114
|
+
});
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Returns the list of contract adapters (name and index)
|
|
120
|
+
// for a buy/sell. Return null if there are no adapters.
|
|
121
|
+
getAdapters(side: SwapSide): { name: string; index: number }[] | null {
|
|
122
|
+
return this.adapters[side];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
getEventPool(srcToken: Token, destToken: Token): JarvisV6EventPool | null {
|
|
126
|
+
const pool = getJarvisPoolFromTokens(srcToken, destToken, this.poolConfigs);
|
|
127
|
+
return this.eventPools[pool?.address.toLowerCase()!];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Returns list of pool identifiers that can be used
|
|
131
|
+
// for a given swap. poolIdentifiers must be unique
|
|
132
|
+
// across DEXes. It is recommended to use
|
|
133
|
+
// ${dexKey}_${poolAddress} as a poolIdentifier
|
|
134
|
+
async getPoolIdentifiers(
|
|
135
|
+
srcToken: Token,
|
|
136
|
+
destToken: Token,
|
|
137
|
+
side: SwapSide,
|
|
138
|
+
blockNumber: number,
|
|
139
|
+
): Promise<string[]> {
|
|
140
|
+
const eventPool = this.getEventPool(srcToken, destToken);
|
|
141
|
+
if (!eventPool) return [];
|
|
142
|
+
return [eventPool.getIdentifier()];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async getPoolState(
|
|
146
|
+
pool: JarvisV6EventPool,
|
|
147
|
+
blockNumber: number,
|
|
148
|
+
): Promise<PoolState> {
|
|
149
|
+
const eventState = pool.getState(blockNumber);
|
|
150
|
+
if (eventState) return eventState;
|
|
151
|
+
const onChainState = await pool.generateState(blockNumber);
|
|
152
|
+
pool.setState(onChainState, blockNumber);
|
|
153
|
+
return onChainState;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Returns pool prices for amounts.
|
|
157
|
+
// If limitPools is defined only pools in limitPools
|
|
158
|
+
// should be used. If limitPools is undefined then
|
|
159
|
+
// any pools can be used.
|
|
160
|
+
// Pair
|
|
161
|
+
async getPricesVolume(
|
|
162
|
+
srcToken: Token,
|
|
163
|
+
destToken: Token,
|
|
164
|
+
amounts: bigint[],
|
|
165
|
+
side: SwapSide,
|
|
166
|
+
blockNumber: number,
|
|
167
|
+
limitPools?: string[], // unusued since DEX is constant price, safe to reuse pools
|
|
168
|
+
): Promise<null | ExchangePrices<JarvisV6Data>> {
|
|
169
|
+
if (side !== SwapSide.SELL) return null;
|
|
170
|
+
|
|
171
|
+
const eventPool = this.getEventPool(srcToken, destToken);
|
|
172
|
+
if (!eventPool) return null;
|
|
173
|
+
|
|
174
|
+
const poolAddress = eventPool.poolConfig.address.toLowerCase();
|
|
175
|
+
const poolIdentifier = eventPool.getIdentifier();
|
|
176
|
+
|
|
177
|
+
const poolState = await this.getPoolState(eventPool, blockNumber);
|
|
178
|
+
|
|
179
|
+
const unitVolume = getBigIntPow(srcToken.decimals);
|
|
180
|
+
|
|
181
|
+
const swapFunction = getJarvisSwapFunction(srcToken, eventPool.poolConfig);
|
|
182
|
+
const systemMaxVars = await this.getSystemMaxVars(poolAddress, blockNumber);
|
|
183
|
+
|
|
184
|
+
const [unit, ...prices] = this.computePrices(
|
|
185
|
+
[unitVolume, ...amounts],
|
|
186
|
+
swapFunction,
|
|
187
|
+
systemMaxVars,
|
|
188
|
+
eventPool.poolConfig,
|
|
189
|
+
poolState,
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
return [
|
|
193
|
+
{
|
|
194
|
+
prices,
|
|
195
|
+
unit,
|
|
196
|
+
data: {
|
|
197
|
+
swapFunction,
|
|
198
|
+
poolAddress,
|
|
199
|
+
},
|
|
200
|
+
poolAddresses: [poolAddress],
|
|
201
|
+
exchange: this.dexKey,
|
|
202
|
+
gasCost: 475 * 1000, //between 450-500k gas
|
|
203
|
+
poolIdentifier,
|
|
204
|
+
},
|
|
205
|
+
];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async getSystemMaxVars(
|
|
209
|
+
poolAddress: Address,
|
|
210
|
+
blockNumber: number,
|
|
211
|
+
): Promise<JarvisV6SystemMaxVars> {
|
|
212
|
+
const cacheKey = `${this.dexKey}_systemMaxVars_${poolAddress}`;
|
|
213
|
+
const cachedSystemMaxVars = await this.dexHelper.cache.getAndCacheLocally(
|
|
214
|
+
this.dexKey,
|
|
215
|
+
this.network,
|
|
216
|
+
cacheKey,
|
|
217
|
+
POOL_CACHE_REFRESH_INTERVAL,
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
if (cachedSystemMaxVars) {
|
|
221
|
+
const { maxTokensCapacity, totalSyntheticTokens } =
|
|
222
|
+
JSON.parse(cachedSystemMaxVars);
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
maxTokensCapacity: BigInt(maxTokensCapacity),
|
|
226
|
+
totalSyntheticTokens: BigInt(totalSyntheticTokens),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const multiContract = this.dexHelper.multiContract;
|
|
231
|
+
const encodedResp = (await multiContract.methods
|
|
232
|
+
.aggregate([
|
|
233
|
+
{
|
|
234
|
+
target: poolAddress,
|
|
235
|
+
callData: this.poolInterface.encodeFunctionData(
|
|
236
|
+
'maxTokensCapacity',
|
|
237
|
+
[],
|
|
238
|
+
),
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
target: poolAddress,
|
|
242
|
+
callData: this.poolInterface.encodeFunctionData(
|
|
243
|
+
'totalSyntheticTokens',
|
|
244
|
+
[],
|
|
245
|
+
),
|
|
246
|
+
},
|
|
247
|
+
])
|
|
248
|
+
.call({}, blockNumber)) as { returnData: [string, string] };
|
|
249
|
+
|
|
250
|
+
const maxTokensCapacity = this.poolInterface
|
|
251
|
+
.decodeFunctionResult('maxTokensCapacity', encodedResp.returnData[0])[0]
|
|
252
|
+
.toString();
|
|
253
|
+
const totalSyntheticTokens = this.poolInterface
|
|
254
|
+
.decodeFunctionResult(
|
|
255
|
+
'totalSyntheticTokens',
|
|
256
|
+
encodedResp.returnData[1],
|
|
257
|
+
)[0]
|
|
258
|
+
.toString();
|
|
259
|
+
|
|
260
|
+
const systemMaxVarStr = JSON.stringify({
|
|
261
|
+
maxTokensCapacity,
|
|
262
|
+
totalSyntheticTokens,
|
|
263
|
+
});
|
|
264
|
+
this.dexHelper.cache.setexAndCacheLocally(
|
|
265
|
+
this.dexKey,
|
|
266
|
+
this.network,
|
|
267
|
+
cacheKey,
|
|
268
|
+
POOL_CACHE_REFRESH_INTERVAL,
|
|
269
|
+
systemMaxVarStr,
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
maxTokensCapacity: BigInt(maxTokensCapacity),
|
|
274
|
+
totalSyntheticTokens: BigInt(totalSyntheticTokens),
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
computePrices(
|
|
279
|
+
amounts: bigint[],
|
|
280
|
+
swapFunction: JarvisSwapFunctions,
|
|
281
|
+
{ maxTokensCapacity, totalSyntheticTokens }: JarvisV6SystemMaxVars,
|
|
282
|
+
pool: PoolConfig,
|
|
283
|
+
poolState: PoolState,
|
|
284
|
+
): bigint[] {
|
|
285
|
+
return amounts.map(amount => {
|
|
286
|
+
if (swapFunction === JarvisSwapFunctions.MINT) {
|
|
287
|
+
return this.computePriceForMint(
|
|
288
|
+
amount,
|
|
289
|
+
maxTokensCapacity,
|
|
290
|
+
poolState,
|
|
291
|
+
pool.collateralToken.decimals,
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
if (swapFunction === JarvisSwapFunctions.REDEEM) {
|
|
295
|
+
if (amount > totalSyntheticTokens) return 0n;
|
|
296
|
+
|
|
297
|
+
return this.computePriceForRedeem(
|
|
298
|
+
amount,
|
|
299
|
+
poolState,
|
|
300
|
+
pool.collateralToken.decimals,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
return 0n;
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
computePriceForMint(
|
|
308
|
+
amount: bigint,
|
|
309
|
+
maxTokensCapacity: bigint,
|
|
310
|
+
poolState: PoolState,
|
|
311
|
+
collateralDecimalsNumber: number,
|
|
312
|
+
) {
|
|
313
|
+
const feePercentage = poolState.pool.feesPercentage;
|
|
314
|
+
const UsdcPriceFeed = poolState.priceFeed.usdcPrice;
|
|
315
|
+
const syntheticAmount = this.getSyntheticAmountToReceive(
|
|
316
|
+
amount,
|
|
317
|
+
collateralDecimalsNumber,
|
|
318
|
+
UsdcPriceFeed,
|
|
319
|
+
feePercentage,
|
|
320
|
+
);
|
|
321
|
+
return syntheticAmount <= maxTokensCapacity ? syntheticAmount : 0n;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
computePriceForRedeem(
|
|
325
|
+
amount: bigint,
|
|
326
|
+
poolState: PoolState,
|
|
327
|
+
collateralDecimalsNumber: number,
|
|
328
|
+
) {
|
|
329
|
+
const feePercentage = poolState.pool.feesPercentage;
|
|
330
|
+
const UsdcPriceFeed = poolState.priceFeed.usdcPrice;
|
|
331
|
+
return this.getCollateralAmountToReceive(
|
|
332
|
+
amount,
|
|
333
|
+
collateralDecimalsNumber,
|
|
334
|
+
UsdcPriceFeed,
|
|
335
|
+
feePercentage,
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
getSyntheticAmountToReceive(
|
|
340
|
+
collateralAmount: bigint,
|
|
341
|
+
collateralDecimals: number,
|
|
342
|
+
UsdcPriceFeed: bigint,
|
|
343
|
+
feePercentage: bigint,
|
|
344
|
+
) {
|
|
345
|
+
let collateralAmountIn18Decimals = convertToNewDecimals(
|
|
346
|
+
collateralAmount,
|
|
347
|
+
collateralDecimals,
|
|
348
|
+
18,
|
|
349
|
+
);
|
|
350
|
+
return (
|
|
351
|
+
((collateralAmountIn18Decimals -
|
|
352
|
+
(collateralAmountIn18Decimals * feePercentage) / BI_POWS[18]) *
|
|
353
|
+
BI_POWS[18]) /
|
|
354
|
+
UsdcPriceFeed
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
getCollateralAmountToReceive(
|
|
359
|
+
syntheticAmount: bigint,
|
|
360
|
+
collateralDecimals: number,
|
|
361
|
+
UsdcPriceFeed: bigint,
|
|
362
|
+
feePercentage: bigint,
|
|
363
|
+
) {
|
|
364
|
+
const result =
|
|
365
|
+
(syntheticAmount * UsdcPriceFeed) / BI_POWS[18] -
|
|
366
|
+
(((syntheticAmount * UsdcPriceFeed) / BI_POWS[18]) * feePercentage) /
|
|
367
|
+
BI_POWS[18];
|
|
368
|
+
if (collateralDecimals === 18) return result;
|
|
369
|
+
return convertToNewDecimals(result, 18, collateralDecimals);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Encode params required by the exchange adapter
|
|
373
|
+
// Used for multiSwap, buy & megaSwap
|
|
374
|
+
// Hint: abiCoder.encodeParameter() could be useful
|
|
375
|
+
getAdapterParam(
|
|
376
|
+
srcToken: string,
|
|
377
|
+
destToken: string,
|
|
378
|
+
srcAmount: string,
|
|
379
|
+
destAmount: string,
|
|
380
|
+
data: JarvisV6Data,
|
|
381
|
+
side: SwapSide,
|
|
382
|
+
): AdapterExchangeParam {
|
|
383
|
+
const { swapFunction } = data;
|
|
384
|
+
const type = [JarvisSwapFunctions.MINT, JarvisSwapFunctions.REDEEM].indexOf(
|
|
385
|
+
swapFunction,
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
if (type === undefined) {
|
|
389
|
+
throw new Error(
|
|
390
|
+
`Jarvis: Invalid OpType ${swapFunction}, Should be one of ['mint', 'redeem']`,
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const payload = this.abiCoder.encodeParameter(
|
|
395
|
+
{
|
|
396
|
+
ParentStruct: {
|
|
397
|
+
opType: 'uint',
|
|
398
|
+
expiration: 'uint128',
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
opType: type,
|
|
403
|
+
expiration: (Date.now() / 1000 + THIRTY_MINUTES).toFixed(0),
|
|
404
|
+
},
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
return {
|
|
408
|
+
targetExchange: data.poolAddress.toLowerCase(),
|
|
409
|
+
payload,
|
|
410
|
+
networkFee: '0',
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Encode call data used by simpleSwap like routers
|
|
415
|
+
// Used for simpleSwap & simpleBuy
|
|
416
|
+
// Hint: this.buildSimpleParamWithoutWETHConversion
|
|
417
|
+
// could be useful
|
|
418
|
+
async getSimpleParam(
|
|
419
|
+
srcToken: string,
|
|
420
|
+
destToken: string,
|
|
421
|
+
srcAmount: string,
|
|
422
|
+
destAmount: string,
|
|
423
|
+
data: JarvisV6Data,
|
|
424
|
+
side: SwapSide,
|
|
425
|
+
): Promise<SimpleExchangeParam> {
|
|
426
|
+
const { swapFunction } = data;
|
|
427
|
+
const timestamp = (Date.now() / 1000 + THIRTY_MINUTES).toFixed(0);
|
|
428
|
+
|
|
429
|
+
let swapFunctionParams: JarvisV6Params;
|
|
430
|
+
switch (swapFunction) {
|
|
431
|
+
case JarvisSwapFunctions.MINT:
|
|
432
|
+
swapFunctionParams = ['1', srcAmount, timestamp, this.augustusAddress];
|
|
433
|
+
break;
|
|
434
|
+
case JarvisSwapFunctions.REDEEM:
|
|
435
|
+
swapFunctionParams = [srcAmount, '1', timestamp, this.augustusAddress];
|
|
436
|
+
break;
|
|
437
|
+
default:
|
|
438
|
+
throw new Error(`Unknown function ${swapFunction}`);
|
|
439
|
+
}
|
|
440
|
+
const swapData = this.poolInterface.encodeFunctionData(swapFunction, [
|
|
441
|
+
swapFunctionParams,
|
|
442
|
+
]);
|
|
443
|
+
|
|
444
|
+
return this.buildSimpleParamWithoutWETHConversion(
|
|
445
|
+
srcToken,
|
|
446
|
+
srcAmount,
|
|
447
|
+
destToken,
|
|
448
|
+
destAmount,
|
|
449
|
+
swapData,
|
|
450
|
+
data.poolAddress.toLowerCase(),
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
getDexParam(
|
|
455
|
+
srcToken: Address,
|
|
456
|
+
destToken: Address,
|
|
457
|
+
srcAmount: NumberAsString,
|
|
458
|
+
destAmount: NumberAsString,
|
|
459
|
+
recipient: Address,
|
|
460
|
+
data: JarvisV6Data,
|
|
461
|
+
side: SwapSide,
|
|
462
|
+
): DexExchangeParam {
|
|
463
|
+
const { swapFunction } = data;
|
|
464
|
+
const timestamp = (Date.now() / 1000 + THIRTY_MINUTES).toFixed(0);
|
|
465
|
+
|
|
466
|
+
let swapFunctionParams: JarvisV6Params;
|
|
467
|
+
switch (swapFunction) {
|
|
468
|
+
case JarvisSwapFunctions.MINT:
|
|
469
|
+
swapFunctionParams = ['1', srcAmount, timestamp, recipient];
|
|
470
|
+
break;
|
|
471
|
+
case JarvisSwapFunctions.REDEEM:
|
|
472
|
+
swapFunctionParams = [srcAmount, '1', timestamp, recipient];
|
|
473
|
+
break;
|
|
474
|
+
default:
|
|
475
|
+
throw new Error(`Unknown function ${swapFunction}`);
|
|
476
|
+
}
|
|
477
|
+
const exchangeData = this.poolInterface.encodeFunctionData(swapFunction, [
|
|
478
|
+
swapFunctionParams,
|
|
479
|
+
]);
|
|
480
|
+
|
|
481
|
+
return {
|
|
482
|
+
needWrapNative: this.needWrapNative,
|
|
483
|
+
dexFuncHasRecipient: true,
|
|
484
|
+
exchangeData,
|
|
485
|
+
targetExchange: data.poolAddress.toLowerCase(),
|
|
486
|
+
returnAmountPos: undefined,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// Returns list of top pools based on liquidity. Max
|
|
491
|
+
// limit number pools should be returned.
|
|
492
|
+
async getTopPoolsForToken(
|
|
493
|
+
tokenAddress: Address,
|
|
494
|
+
limit: number,
|
|
495
|
+
): Promise<PoolLiquidity[]> {
|
|
496
|
+
return [];
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
getCalldataGasCost(poolPrices: PoolPrices<JarvisV6Data>): number | number[] {
|
|
500
|
+
return (
|
|
501
|
+
CALLDATA_GAS_COST.DEX_OVERHEAD +
|
|
502
|
+
CALLDATA_GAS_COST.LENGTH_SMALL +
|
|
503
|
+
// opType
|
|
504
|
+
CALLDATA_GAS_COST.INDEX +
|
|
505
|
+
// expiration
|
|
506
|
+
CALLDATA_GAS_COST.TIMESTAMP
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
}
|