@paraswap/dex-lib 2.42.16 → 2.42.17-wombat.0
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/.vscode/launch.json +39 -0
- package/.vscode/settings.json +2 -0
- package/.vscode/tasks.json +15 -0
- package/build/abi/algebra/SwapRouter.json +281 -0
- package/build/abi/wombat/asset.json +769 -0
- package/build/abi/wombat/bmw.json +1247 -0
- package/build/abi/wombat/pool.json +1364 -0
- package/build/config.js +7 -6
- package/build/config.js.map +1 -1
- package/build/dex/index.js +2 -0
- package/build/dex/index.js.map +1 -1
- package/build/dex/swaap-v2/stable-coins.d.ts +5 -0
- package/build/dex/swaap-v2/stable-coins.js +26 -0
- package/build/dex/swaap-v2/stable-coins.js.map +1 -0
- package/build/dex/wombat/config.d.ts +4 -0
- package/build/dex/wombat/config.js +77 -0
- package/build/dex/wombat/config.js.map +1 -0
- package/build/dex/wombat/types.d.ts +33 -0
- package/build/dex/wombat/types.js +3 -0
- package/build/dex/wombat/types.js.map +1 -0
- package/build/dex/wombat/utils.d.ts +9 -0
- package/build/dex/wombat/utils.js +66 -0
- package/build/dex/wombat/utils.js.map +1 -0
- package/build/dex/wombat/wombat-bmw.d.ts +40 -0
- package/build/dex/wombat/wombat-bmw.js +147 -0
- package/build/dex/wombat/wombat-bmw.js.map +1 -0
- package/build/dex/wombat/wombat-pool.d.ts +22 -0
- package/build/dex/wombat/wombat-pool.js +161 -0
- package/build/dex/wombat/wombat-pool.js.map +1 -0
- package/build/dex/wombat/wombat-quoter.d.ts +16 -0
- package/build/dex/wombat/wombat-quoter.js +176 -0
- package/build/dex/wombat/wombat-quoter.js.map +1 -0
- package/build/dex/wombat/wombat.d.ts +55 -0
- package/build/dex/wombat/wombat.js +290 -0
- package/build/dex/wombat/wombat.js.map +1 -0
- package/build/rebase-tokens.json +17 -0
- package/package.json +1 -1
- package/src/abi/wombat/asset.json +769 -0
- package/src/abi/wombat/bmw.json +1247 -0
- package/src/abi/wombat/pool.json +1364 -0
- package/src/config.ts +7 -7
- package/src/dex/index.ts +2 -0
- package/src/dex/wombat/config.ts +77 -0
- package/src/dex/wombat/types.ts +55 -0
- package/src/dex/wombat/utils.ts +62 -0
- package/src/dex/wombat/wombat-bmw.ts +209 -0
- package/src/dex/wombat/wombat-e2e.test.ts +264 -0
- package/src/dex/wombat/wombat-integration.test.ts +258 -0
- package/src/dex/wombat/wombat-pool.ts +231 -0
- package/src/dex/wombat/wombat-quoter.ts +269 -0
- package/src/dex/wombat/wombat.ts +426 -0
- package/tests/constants-e2e.ts +20 -4
- package/tests/utils-e2e.ts +2 -1
- package/build/abi/algebra/AlgebraPool.abi.json +0 -727
- package/build/abi/uniswap-v3/UniswapV3Quoter.abi.json +0 -193
- package/build/dex/algebra/algebra-pool.d.ts +0 -46
- package/build/dex/algebra/algebra-pool.js +0 -336
- package/build/dex/algebra/algebra-pool.js.map +0 -1
- package/build/dex/quickswap/camelot-v3.d.ts +0 -6
- package/build/dex/quickswap/camelot-v3.js +0 -19
- package/build/dex/quickswap/camelot-v3.js.map +0 -1
- package/build/dex/quickswap/zyberswap-v3.d.ts +0 -6
- package/build/dex/quickswap/zyberswap-v3.js +0 -19
- package/build/dex/quickswap/zyberswap-v3.js.map +0 -1
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import { AsyncOrSync, DeepReadonly } from 'ts-essentials';
|
|
2
|
+
import { Interface } from '@ethersproject/abi';
|
|
3
|
+
import { SwapSide } from '@paraswap/core';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
AdapterExchangeParam,
|
|
7
|
+
Address,
|
|
8
|
+
ExchangePrices,
|
|
9
|
+
Logger,
|
|
10
|
+
PoolLiquidity,
|
|
11
|
+
PoolPrices,
|
|
12
|
+
SimpleExchangeParam,
|
|
13
|
+
Token,
|
|
14
|
+
} from '../../types';
|
|
15
|
+
import { Network } from '../../constants';
|
|
16
|
+
import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
|
|
17
|
+
import { getBigIntPow, getDexKeysWithNetwork, isETHAddress } from '../../utils';
|
|
18
|
+
import { IDex } from '../idex';
|
|
19
|
+
import { IDexHelper } from '../../dex-helper';
|
|
20
|
+
import { DexParams, PoolState, WombatData } from './types';
|
|
21
|
+
import {
|
|
22
|
+
getLocalDeadlineAsFriendlyPlaceholder,
|
|
23
|
+
SimpleExchange,
|
|
24
|
+
} from '../simple-exchange';
|
|
25
|
+
import { Adapters, WombatConfig } from './config';
|
|
26
|
+
import PoolABI from '../../abi/wombat/pool.json';
|
|
27
|
+
import AssetABI from '../../abi/wombat/asset.json';
|
|
28
|
+
import ERC20ABI from '../../abi/erc20.json';
|
|
29
|
+
import { WombatQuoter } from './wombat-quoter';
|
|
30
|
+
import { WombatBmw } from './wombat-bmw';
|
|
31
|
+
import { fromWad } from './utils';
|
|
32
|
+
import { WombatPool } from './wombat-pool';
|
|
33
|
+
|
|
34
|
+
export class Wombat extends SimpleExchange implements IDex<WombatData> {
|
|
35
|
+
// export class Wombat implements IDex<WombatData> {
|
|
36
|
+
// contract interfaces
|
|
37
|
+
static readonly erc20Interface = new Interface(ERC20ABI);
|
|
38
|
+
static readonly poolInterface = new Interface(PoolABI);
|
|
39
|
+
static readonly assetInterface = new Interface(AssetABI);
|
|
40
|
+
|
|
41
|
+
protected config: DexParams;
|
|
42
|
+
protected poolLiquidityUSD?: { [poolAddress: string]: number };
|
|
43
|
+
public bmw: WombatBmw;
|
|
44
|
+
public pools: { [poolAddress: string]: WombatPool } = {};
|
|
45
|
+
|
|
46
|
+
readonly hasConstantPriceLargeAmounts = false;
|
|
47
|
+
readonly needWrapNative = true;
|
|
48
|
+
|
|
49
|
+
readonly isFeeOnTransferSupported = false;
|
|
50
|
+
|
|
51
|
+
public static dexKeysWithNetwork: {
|
|
52
|
+
key: string;
|
|
53
|
+
networks: Network[];
|
|
54
|
+
}[] = getDexKeysWithNetwork(WombatConfig);
|
|
55
|
+
|
|
56
|
+
logger: Logger;
|
|
57
|
+
|
|
58
|
+
constructor(
|
|
59
|
+
readonly network: Network,
|
|
60
|
+
readonly dexKey: string,
|
|
61
|
+
readonly dexHelper: IDexHelper,
|
|
62
|
+
protected adapters = Adapters[network] || {}, // TODO: add any additional optional params to support other fork DEXes
|
|
63
|
+
) {
|
|
64
|
+
super(dexHelper, dexKey);
|
|
65
|
+
this.logger = dexHelper.getLogger(dexKey);
|
|
66
|
+
this.config = WombatConfig[dexKey][network];
|
|
67
|
+
this.bmw = new WombatBmw(
|
|
68
|
+
dexKey,
|
|
69
|
+
this.config.bmwAddress,
|
|
70
|
+
network,
|
|
71
|
+
dexHelper,
|
|
72
|
+
this.logger,
|
|
73
|
+
this.config.bmwAddress,
|
|
74
|
+
this.onAssetAdded.bind(this),
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async init(blockNumber: number) {
|
|
79
|
+
if (!this.bmw.isInitialized) {
|
|
80
|
+
await this.bmw.initialize(blockNumber);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Initialize pricing is called once in the start of
|
|
85
|
+
// pricing service. It is intended to setup the integration
|
|
86
|
+
// for pricing requests. It is optional for a DEX to
|
|
87
|
+
// implement this function
|
|
88
|
+
async initializePricing(blockNumber: number) {
|
|
89
|
+
await this.init(blockNumber);
|
|
90
|
+
const bmwState = this.bmw.getState(blockNumber);
|
|
91
|
+
if (!bmwState) {
|
|
92
|
+
throw new Error('initializePricing: bmwState still null after init');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
onAssetAdded = async (
|
|
97
|
+
pool: Address,
|
|
98
|
+
asset2TokenMap: Map<Address, Address>,
|
|
99
|
+
blockNumber: number,
|
|
100
|
+
): Promise<void> => {
|
|
101
|
+
if (!this.pools[pool]) {
|
|
102
|
+
this.pools[pool] = new WombatPool(
|
|
103
|
+
this.dexKey,
|
|
104
|
+
this.getPoolIdentifier(pool),
|
|
105
|
+
this.dexHelper,
|
|
106
|
+
pool,
|
|
107
|
+
asset2TokenMap,
|
|
108
|
+
);
|
|
109
|
+
await this.pools[pool].getState('latest', true);
|
|
110
|
+
} else {
|
|
111
|
+
this.pools[pool].addAssets(asset2TokenMap);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// Returns the list of contract adapters (name and index)
|
|
116
|
+
// for a buy/sell. Return null if there are no adapters.
|
|
117
|
+
getAdapters(side: SwapSide): { name: string; index: number }[] | null {
|
|
118
|
+
return this.adapters[side] ? this.adapters[side] : null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Returns list of pool identifiers that can be used
|
|
122
|
+
// for a given swap. poolIdentifiers must be unique
|
|
123
|
+
// across DEXes. It is recommended to use
|
|
124
|
+
// ${dexKey}_${poolAddress} as a poolIdentifier
|
|
125
|
+
async getPoolIdentifiers(
|
|
126
|
+
srcToken: Token,
|
|
127
|
+
destToken: Token,
|
|
128
|
+
side: SwapSide,
|
|
129
|
+
blockNumber: number,
|
|
130
|
+
): Promise<string[]> {
|
|
131
|
+
await this.updatePoolState();
|
|
132
|
+
return (
|
|
133
|
+
await this.findPools(
|
|
134
|
+
this.dexHelper.config.wrapETH(srcToken).address.toLowerCase(),
|
|
135
|
+
this.dexHelper.config.wrapETH(destToken).address.toLowerCase(),
|
|
136
|
+
blockNumber,
|
|
137
|
+
)
|
|
138
|
+
).map(p => this.getPoolIdentifier(p));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
protected getPoolIdentifier(poolAddress: Address): string {
|
|
142
|
+
return `${this.dexKey}_${poolAddress}`;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Returns pool prices for amounts.
|
|
146
|
+
// If limitPools is defined only pools in limitPools
|
|
147
|
+
// should be used. If limitPools is undefined then
|
|
148
|
+
// any pools can be used.
|
|
149
|
+
async getPricesVolume(
|
|
150
|
+
srcToken: Token,
|
|
151
|
+
destToken: Token,
|
|
152
|
+
amounts: bigint[],
|
|
153
|
+
side: SwapSide,
|
|
154
|
+
blockNumber: number,
|
|
155
|
+
limitPools?: string[],
|
|
156
|
+
): Promise<null | ExchangePrices<WombatData>> {
|
|
157
|
+
if (!this.pools) {
|
|
158
|
+
this.logger.error(`Missing pools for ${this.dexKey} in getPricesVolume`);
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
const srcTokenAddress = this.dexHelper.config
|
|
162
|
+
.wrapETH(srcToken)
|
|
163
|
+
.address.toLowerCase();
|
|
164
|
+
const destTokenAddress = this.dexHelper.config
|
|
165
|
+
.wrapETH(destToken)
|
|
166
|
+
.address.toLowerCase();
|
|
167
|
+
if (srcTokenAddress === destTokenAddress) return null;
|
|
168
|
+
|
|
169
|
+
const pools = (
|
|
170
|
+
await this.findPools(srcTokenAddress, destTokenAddress, blockNumber)
|
|
171
|
+
).filter(
|
|
172
|
+
poolAddress =>
|
|
173
|
+
!limitPools || limitPools.includes(this.getPoolIdentifier(poolAddress)),
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
const promises = [];
|
|
177
|
+
for (const poolAddress of pools) {
|
|
178
|
+
let state = await this.pools![poolAddress].getState(blockNumber);
|
|
179
|
+
if (!state) {
|
|
180
|
+
this.logger.warn(
|
|
181
|
+
`State of pool ${poolAddress} is null in getPricesVolume, skipping...`,
|
|
182
|
+
);
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
const [unit, ...prices] = this.computePrices(
|
|
186
|
+
srcTokenAddress,
|
|
187
|
+
destTokenAddress,
|
|
188
|
+
[getBigIntPow(srcToken.decimals), ...amounts],
|
|
189
|
+
side,
|
|
190
|
+
state.value,
|
|
191
|
+
);
|
|
192
|
+
promises.push({
|
|
193
|
+
prices,
|
|
194
|
+
unit,
|
|
195
|
+
data: {
|
|
196
|
+
exchange: poolAddress,
|
|
197
|
+
},
|
|
198
|
+
poolAddresses: [poolAddress],
|
|
199
|
+
exchange: this.dexKey,
|
|
200
|
+
/** @todo specify gas cost */
|
|
201
|
+
gasCost: 260 * 1000,
|
|
202
|
+
poolIdentifier: this.getPoolIdentifier(poolAddress),
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return await Promise.all(promises);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// take PoolState to compute price
|
|
210
|
+
protected computePrices(
|
|
211
|
+
srcTokenAddress: Address,
|
|
212
|
+
destTokenAddress: Address,
|
|
213
|
+
amounts: bigint[],
|
|
214
|
+
side: SwapSide,
|
|
215
|
+
state: DeepReadonly<PoolState>,
|
|
216
|
+
): bigint[] {
|
|
217
|
+
const srcAsset = state.asset[srcTokenAddress];
|
|
218
|
+
const destAsset = state.asset[destTokenAddress];
|
|
219
|
+
const quoter = new WombatQuoter(state.params);
|
|
220
|
+
|
|
221
|
+
return amounts.map(fromAmount => {
|
|
222
|
+
return side === SwapSide.SELL
|
|
223
|
+
? quoter.getQuote(srcAsset, destAsset, fromAmount)
|
|
224
|
+
: quoter.getQuote(destAsset, srcAsset, -fromAmount);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
protected async findPools(
|
|
229
|
+
srcTokenAddress: Address,
|
|
230
|
+
destTokenAddress: Address,
|
|
231
|
+
blockNumber: number,
|
|
232
|
+
): Promise<Address[]> {
|
|
233
|
+
const pools: Address[] = [];
|
|
234
|
+
for (const [poolAddress, pool] of Object.entries(this.pools)) {
|
|
235
|
+
let stateOj = await pool.getState(blockNumber);
|
|
236
|
+
if (!stateOj) {
|
|
237
|
+
this.logger.warn(
|
|
238
|
+
`State of pool ${poolAddress} is null in findPools, skipping...`,
|
|
239
|
+
);
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const state = stateOj.value;
|
|
244
|
+
if (
|
|
245
|
+
state &&
|
|
246
|
+
!state.params.paused &&
|
|
247
|
+
state.asset[srcTokenAddress] &&
|
|
248
|
+
state.asset[destTokenAddress]
|
|
249
|
+
) {
|
|
250
|
+
pools.push(poolAddress);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return pools;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Returns estimated gas cost of calldata for this DEX in multiSwap
|
|
258
|
+
getCalldataGasCost(poolPrices: PoolPrices<WombatData>): number | number[] {
|
|
259
|
+
// TODO: update if there is any payload in getAdapterParam
|
|
260
|
+
return CALLDATA_GAS_COST.DEX_NO_PAYLOAD;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
getAdapterParam(
|
|
264
|
+
srcToken: string,
|
|
265
|
+
destToken: string,
|
|
266
|
+
srcAmount: string,
|
|
267
|
+
destAmount: string,
|
|
268
|
+
data: WombatData,
|
|
269
|
+
side: SwapSide,
|
|
270
|
+
): AdapterExchangeParam {
|
|
271
|
+
const { exchange } = data;
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
targetExchange: exchange,
|
|
275
|
+
payload: '0x',
|
|
276
|
+
networkFee: '0',
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Encode call data used by simpleSwap like routers
|
|
281
|
+
// Used for simpleSwap & simpleBuy
|
|
282
|
+
// Hint: this.buildSimpleParamWithoutWETHConversion
|
|
283
|
+
// could be useful
|
|
284
|
+
async getSimpleParam(
|
|
285
|
+
srcToken: string,
|
|
286
|
+
destToken: string,
|
|
287
|
+
srcAmount: string,
|
|
288
|
+
destAmount: string,
|
|
289
|
+
data: WombatData,
|
|
290
|
+
side: SwapSide,
|
|
291
|
+
): Promise<SimpleExchangeParam> {
|
|
292
|
+
const { exchange } = data;
|
|
293
|
+
|
|
294
|
+
// Encode here the transaction arguments
|
|
295
|
+
const swapData = Wombat.poolInterface.encodeFunctionData('swap', [
|
|
296
|
+
srcToken,
|
|
297
|
+
destToken,
|
|
298
|
+
srcAmount,
|
|
299
|
+
destAmount,
|
|
300
|
+
this.augustusAddress,
|
|
301
|
+
getLocalDeadlineAsFriendlyPlaceholder(),
|
|
302
|
+
]);
|
|
303
|
+
|
|
304
|
+
return this.buildSimpleParamWithoutWETHConversion(
|
|
305
|
+
srcToken,
|
|
306
|
+
srcAmount,
|
|
307
|
+
destToken,
|
|
308
|
+
destAmount,
|
|
309
|
+
swapData,
|
|
310
|
+
exchange,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// This is called once before getTopPoolsForToken is
|
|
315
|
+
// called for multiple tokens. This can be helpful to
|
|
316
|
+
// update common state required for calculating
|
|
317
|
+
// getTopPoolsForToken. For example, poolLiquidityUSD.
|
|
318
|
+
async updatePoolState(): Promise<void> {
|
|
319
|
+
const blockNumber = await this.dexHelper.provider.getBlockNumber();
|
|
320
|
+
await this.init(blockNumber);
|
|
321
|
+
const bmwState = this.bmw.getState(blockNumber);
|
|
322
|
+
if (!bmwState) {
|
|
323
|
+
throw new Error('updatePoolState: bmwState still null after init');
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// All tokens are USD stablecoins so to estimate liquidity can just add
|
|
327
|
+
// the cash balances of all the tokens
|
|
328
|
+
const poolLiquidityUSD: { [poolAddress: string]: number } = {};
|
|
329
|
+
const usdPromises = [];
|
|
330
|
+
const poolStates: { [poolAddress: string]: DeepReadonly<PoolState> } = {};
|
|
331
|
+
const poolStateObjs = await Promise.all(
|
|
332
|
+
Object.values(this.pools).map(pool => pool.getState()),
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
for (const [poolAddress, pool] of Object.entries(this.pools)) {
|
|
336
|
+
const index = Object.keys(this.pools).indexOf(poolAddress);
|
|
337
|
+
let state = poolStateObjs[index];
|
|
338
|
+
if (!state) {
|
|
339
|
+
this.logger.warn(
|
|
340
|
+
`State of ${poolAddress} is null in updatePoolState, skipping...`,
|
|
341
|
+
);
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
poolStates[poolAddress] = state.value;
|
|
345
|
+
for (const [tokenAddress, assetState] of Object.entries(
|
|
346
|
+
state.value.asset,
|
|
347
|
+
)) {
|
|
348
|
+
usdPromises.push(
|
|
349
|
+
this.dexHelper.getTokenUSDPrice(
|
|
350
|
+
{
|
|
351
|
+
address: tokenAddress,
|
|
352
|
+
decimals: assetState.underlyingTokenDecimals,
|
|
353
|
+
},
|
|
354
|
+
fromWad(
|
|
355
|
+
assetState.cash,
|
|
356
|
+
BigInt(assetState.underlyingTokenDecimals),
|
|
357
|
+
),
|
|
358
|
+
),
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
const usdValues = await Promise.all(usdPromises);
|
|
363
|
+
|
|
364
|
+
for (const [poolAddress, poolState] of Object.entries(poolStates)) {
|
|
365
|
+
poolLiquidityUSD[poolAddress] = 0;
|
|
366
|
+
for (let i = 0; i < poolState.underlyingAddresses.length; i++) {
|
|
367
|
+
poolLiquidityUSD[poolAddress] += usdValues[i];
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
this.poolLiquidityUSD = poolLiquidityUSD;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Returns list of top pools based on liquidity. Max
|
|
375
|
+
// limit number pools should be returned.
|
|
376
|
+
async getTopPoolsForToken(
|
|
377
|
+
tokenAddress: Address,
|
|
378
|
+
limit: number,
|
|
379
|
+
): Promise<PoolLiquidity[]> {
|
|
380
|
+
if (!this.poolLiquidityUSD) await this.updatePoolState();
|
|
381
|
+
tokenAddress = (
|
|
382
|
+
isETHAddress(tokenAddress)
|
|
383
|
+
? this.dexHelper.config.data.wrappedNativeTokenAddress
|
|
384
|
+
: tokenAddress
|
|
385
|
+
).toLowerCase();
|
|
386
|
+
const pools: string[] = [];
|
|
387
|
+
const poolStates: { [poolAddress: string]: DeepReadonly<PoolState> } = {};
|
|
388
|
+
for (const [poolAddress, eventPool] of Object.entries(this.pools)) {
|
|
389
|
+
let state = await eventPool.getState();
|
|
390
|
+
if (!state) {
|
|
391
|
+
this.logger.warn(
|
|
392
|
+
`State of ${poolAddress} is null in getTopPoolsForToken, skipping...`,
|
|
393
|
+
);
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
if (
|
|
397
|
+
state.value.underlyingAddresses.includes(tokenAddress) &&
|
|
398
|
+
this.poolLiquidityUSD![poolAddress]
|
|
399
|
+
) {
|
|
400
|
+
poolStates[poolAddress] = state.value;
|
|
401
|
+
pools.push(poolAddress);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// sort by liquidity
|
|
406
|
+
pools.sort((a, b) => this.poolLiquidityUSD![b] - this.poolLiquidityUSD![a]);
|
|
407
|
+
return pools.slice(0, limit).map(poolAddress => ({
|
|
408
|
+
exchange: this.dexKey,
|
|
409
|
+
address: poolAddress,
|
|
410
|
+
// other tokens in the same pool
|
|
411
|
+
connectorTokens: poolStates[poolAddress].underlyingAddresses
|
|
412
|
+
.filter(t => t !== tokenAddress)
|
|
413
|
+
.map(t => ({
|
|
414
|
+
decimals: poolStates[poolAddress].asset[t].underlyingTokenDecimals,
|
|
415
|
+
address: t,
|
|
416
|
+
})),
|
|
417
|
+
liquidityUSD: this.poolLiquidityUSD![poolAddress],
|
|
418
|
+
}));
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// This is optional function in case if your implementation has acquired any resources
|
|
422
|
+
// you need to release for graceful shutdown. For example, it may be any interval timer
|
|
423
|
+
releaseResources(): AsyncOrSync<void> {
|
|
424
|
+
// TODO: complete me!
|
|
425
|
+
}
|
|
426
|
+
}
|
package/tests/constants-e2e.ts
CHANGED
|
@@ -550,6 +550,10 @@ export const Tokens: {
|
|
|
550
550
|
address: '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c',
|
|
551
551
|
decimals: 18,
|
|
552
552
|
},
|
|
553
|
+
BNBx: {
|
|
554
|
+
address: '0x1bdd3Cf7F79cfB8EdbB955f20ad99211551BA275',
|
|
555
|
+
decimals: 18,
|
|
556
|
+
},
|
|
553
557
|
BUSD: {
|
|
554
558
|
address: '0xe9e7cea3dedca5984780bafc599bd69add087d56',
|
|
555
559
|
decimals: 18,
|
|
@@ -764,6 +768,10 @@ export const Tokens: {
|
|
|
764
768
|
},
|
|
765
769
|
},
|
|
766
770
|
[Network.ARBITRUM]: {
|
|
771
|
+
SEN: {
|
|
772
|
+
address: '0x154388a4650D63acC823e06Ef9e47C1eDdD3cBb2',
|
|
773
|
+
decimals: 18,
|
|
774
|
+
},
|
|
767
775
|
DAI: {
|
|
768
776
|
address: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1',
|
|
769
777
|
decimals: 18,
|
|
@@ -849,6 +857,10 @@ export const Tokens: {
|
|
|
849
857
|
address: '0x3d9907f9a368ad0a51be60f7da3b97cf940982d8',
|
|
850
858
|
decimals: 18,
|
|
851
859
|
},
|
|
860
|
+
wstETH: {
|
|
861
|
+
address: '0x5979D7b546E38E414F7E9822514be443A4800529',
|
|
862
|
+
decimals: 18,
|
|
863
|
+
},
|
|
852
864
|
},
|
|
853
865
|
[Network.OPTIMISM]: {
|
|
854
866
|
DAI: {
|
|
@@ -1105,6 +1117,7 @@ export const Holders: {
|
|
|
1105
1117
|
FRAX: '0xEB4576fE753DAB07635c0Bb6c8f0A355e1Db5d31',
|
|
1106
1118
|
frxETH: '0xf324adC872005197A6f7DAE214d3b63aa0C3625F',
|
|
1107
1119
|
USDFI: '0x2E00D722e091836B39Db3e4dcE6eE51c90c5B221',
|
|
1120
|
+
BNBx: '0xFF4606bd3884554CDbDabd9B6e25E2faD4f6fc54',
|
|
1108
1121
|
},
|
|
1109
1122
|
[Network.AVALANCHE]: {
|
|
1110
1123
|
AVAX: '0xD6216fC19DB775Df9774a6E33526131dA7D19a2c',
|
|
@@ -1140,14 +1153,16 @@ export const Holders: {
|
|
|
1140
1153
|
BTCb: '0x84c06d3c27821d0136f66306f5028d43ceac268d',
|
|
1141
1154
|
},
|
|
1142
1155
|
[Network.ARBITRUM]: {
|
|
1156
|
+
SEN: '0xcb19b6b4971bd4206bab176c75b1efe3e28ee5a8',
|
|
1157
|
+
RDPX: '0x2fa6f21ecfe274f594f470c376f5bdd061e08a37',
|
|
1143
1158
|
ARB: '0xb65edba80a3d81903ecd499c8eb9cf0e19096bd0',
|
|
1144
1159
|
ETH: '0xF977814e90dA44bFA03b6295A0616a897441aceC',
|
|
1145
1160
|
DAI: '0x07d7f291e731a41d3f0ea4f1ae5b6d920ffb3fe0',
|
|
1146
1161
|
WETH: '0xc31e54c7a869b9fcbecc14363cf510d1c41fa443',
|
|
1147
1162
|
USDCe: '0x62383739d68dd0f844103db8dfb05a7eded5bbe6',
|
|
1148
|
-
USDC: '
|
|
1163
|
+
USDC: '0xb38e8c17e38363af6ebdcb3dae12e0243582891d',
|
|
1149
1164
|
OHM: '0xebce5f29ff5ca9aa330ebdf7ec6b5f474bff271e',
|
|
1150
|
-
USDT: '
|
|
1165
|
+
USDT: '0xf977814e90da44bfa03b6295a0616a897441acec',
|
|
1151
1166
|
POPS: '0x4b78b52e7de4d8b7d367297cb8a87c1875a9d591',
|
|
1152
1167
|
FRAX: '0x59bf0545fca0e5ad48e13da269facd2e8c886ba4',
|
|
1153
1168
|
nUSD: '0x9dd329f5411466d9e0c488ff72519ca9fef0cb40',
|
|
@@ -1162,14 +1177,15 @@ export const Holders: {
|
|
|
1162
1177
|
ZYB: '0x3ec0eddcd1e25025077327886a78133589082fb2',
|
|
1163
1178
|
WBTC: '0xd9d611c6943585bc0e18e51034af8fa28778f7da',
|
|
1164
1179
|
RDNT: '0x62383739d68dd0f844103db8dfb05a7eded5bbe6',
|
|
1180
|
+
wstETH: '0x916792f7734089470de27297903bed8a4630b26d',
|
|
1165
1181
|
},
|
|
1166
1182
|
[Network.OPTIMISM]: {
|
|
1167
1183
|
ETH: '0x9ef21bE1C270AA1c3c3d750F458442397fBFFCB6',
|
|
1168
1184
|
DAI: '0x1337bedc9d22ecbe766df105c9623922a27963ec',
|
|
1169
1185
|
WETH: '0x68F5C0A2DE713a54991E01858Fd27a3832401849',
|
|
1170
1186
|
POPS: '0x3cbd9044aaabef08ce93a68448e093cff405ad76',
|
|
1171
|
-
USDC: '
|
|
1172
|
-
USDT: '
|
|
1187
|
+
USDC: '0xdecc0c09c3b5f6e92ef4184125d5648a66e35298',
|
|
1188
|
+
USDT: '0xf977814e90da44bfa03b6295a0616a897441acec',
|
|
1173
1189
|
OP: '0xEBb8EA128BbdFf9a1780A4902A9380022371d466',
|
|
1174
1190
|
aOptWETH: '0x7B7D80C40415F744864f051B806b466e2fbB8E68',
|
|
1175
1191
|
aOptUSDC: '0x8c0Fcf914E90fF5d7f2D02c1576BF4245FaD2B7F',
|
package/tests/utils-e2e.ts
CHANGED
|
@@ -35,6 +35,7 @@ import { SmartToken, StateOverrides } from './smart-tokens';
|
|
|
35
35
|
import { GIFTER_ADDRESS } from './constants-e2e';
|
|
36
36
|
import { generateDeployBytecode, sleep } from './utils';
|
|
37
37
|
import { assert } from 'ts-essentials';
|
|
38
|
+
import * as util from 'util';
|
|
38
39
|
|
|
39
40
|
export const testingEndpoint = process.env.E2E_TEST_ENDPOINT;
|
|
40
41
|
|
|
@@ -84,7 +85,7 @@ const MULTISIG: { [nid: number]: string } = {
|
|
|
84
85
|
[Network.POLYGON]: '0x46DF4eb6f7A3B0AdF526f6955b15d3fE02c618b7',
|
|
85
86
|
[Network.FANTOM]: '0xECaB2dac955b94e49Ec09D6d68672d3B397BbdAd',
|
|
86
87
|
[Network.AVALANCHE]: '0x1e2ECA5e812D08D2A7F8664D69035163ff5BfEC2',
|
|
87
|
-
[Network.OPTIMISM]: '
|
|
88
|
+
[Network.OPTIMISM]: '0x3b28A6f6291f7e8277751f2911Ac49C585d049f6',
|
|
88
89
|
[Network.ARBITRUM]: '0x90DfD8a6454CFE19be39EaB42ac93CD850c7f339',
|
|
89
90
|
[Network.BASE]: '0x6C674c8Df1aC663b822c4B6A56B4E5e889379AE0',
|
|
90
91
|
};
|