@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,420 +1,420 @@
|
|
|
1
|
-
import _ from 'lodash';
|
|
2
|
-
import { AsyncOrSync } from 'ts-essentials';
|
|
3
|
-
import {
|
|
4
|
-
Token,
|
|
5
|
-
Address,
|
|
6
|
-
ExchangePrices,
|
|
7
|
-
PoolPrices,
|
|
8
|
-
AdapterExchangeParam,
|
|
9
|
-
SimpleExchangeParam,
|
|
10
|
-
PoolLiquidity,
|
|
11
|
-
Logger,
|
|
12
|
-
NumberAsString,
|
|
13
|
-
DexExchangeParam,
|
|
14
|
-
} from '../../types';
|
|
15
|
-
import { SwapSide, Network } from '../../constants';
|
|
16
|
-
import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
|
|
17
|
-
import { getBigIntPow, getDexKeysWithNetwork, _require } from '../../utils';
|
|
18
|
-
import { IDex } from '../../dex/idex';
|
|
19
|
-
import { IDexHelper } from '../../dex-helper/idex-helper';
|
|
20
|
-
import { DexParams, SynthetixData } from './types';
|
|
21
|
-
import { SimpleExchange } from '../simple-exchange';
|
|
22
|
-
import { SynthetixConfig, Adapters } from './config';
|
|
23
|
-
import { Interface } from '@ethersproject/abi';
|
|
24
|
-
import {
|
|
25
|
-
STATE_TTL_IN_MS,
|
|
26
|
-
SYNTHETIX_GAS_COST_WITHOUT_SUSD,
|
|
27
|
-
SYNTHETIX_GAS_COST_WITH_SUSD,
|
|
28
|
-
} from './constants';
|
|
29
|
-
import { synthetixMath } from './contract-math/synthetix-math';
|
|
30
|
-
import { SynthetixState } from './synthetix-state';
|
|
31
|
-
// There are so many ABIs, where I need only one or two functions
|
|
32
|
-
// So, I decided to unite them into one combined interface
|
|
33
|
-
import CombinedSynthetixABI from '../../abi/synthetix/CombinedSynthetix.abi.json';
|
|
34
|
-
import { extractReturnAmountPosition } from '../../executor/utils';
|
|
35
|
-
|
|
36
|
-
export class Synthetix extends SimpleExchange implements IDex<SynthetixData> {
|
|
37
|
-
readonly hasConstantPriceLargeAmounts = false;
|
|
38
|
-
readonly needWrapNative = true;
|
|
39
|
-
readonly isFeeOnTransferSupported = false;
|
|
40
|
-
|
|
41
|
-
readonly combinedIface: Interface;
|
|
42
|
-
|
|
43
|
-
logger: Logger;
|
|
44
|
-
|
|
45
|
-
synthetixState: SynthetixState;
|
|
46
|
-
|
|
47
|
-
// It is intermediate measure before we have event base Oracles
|
|
48
|
-
statePollingTimer?: NodeJS.Timer;
|
|
49
|
-
|
|
50
|
-
public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
|
|
51
|
-
getDexKeysWithNetwork(SynthetixConfig);
|
|
52
|
-
|
|
53
|
-
constructor(
|
|
54
|
-
readonly network: Network,
|
|
55
|
-
dexKey: string,
|
|
56
|
-
readonly dexHelper: IDexHelper,
|
|
57
|
-
protected adapters = Adapters[network] || {},
|
|
58
|
-
readonly config = SynthetixConfig[dexKey][network],
|
|
59
|
-
) {
|
|
60
|
-
super(dexHelper, dexKey);
|
|
61
|
-
this.config = this.normalizeConfig(this.config);
|
|
62
|
-
this.logger = dexHelper.getLogger(dexKey);
|
|
63
|
-
this.combinedIface = new Interface(CombinedSynthetixABI);
|
|
64
|
-
this.synthetixState = new SynthetixState(
|
|
65
|
-
this.dexKey,
|
|
66
|
-
this.dexHelper,
|
|
67
|
-
this.combinedIface,
|
|
68
|
-
this.config,
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
get multiWrapper() {
|
|
73
|
-
return this.dexHelper.multiWrapper;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
private normalizeConfig(config: DexParams): DexParams {
|
|
77
|
-
return {
|
|
78
|
-
readProxyAddressResolver: config.readProxyAddressResolver.toLowerCase(),
|
|
79
|
-
flexibleStorage: config.flexibleStorage.toLowerCase(),
|
|
80
|
-
synths: config.synths.map(s => {
|
|
81
|
-
s.address = s.address.toLowerCase();
|
|
82
|
-
return s;
|
|
83
|
-
}),
|
|
84
|
-
sUSDAddress: config.sUSDAddress.toLowerCase(),
|
|
85
|
-
trackingCode: config.trackingCode.toLowerCase(),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
get onchainConfigValues() {
|
|
90
|
-
return this.synthetixState.onchainConfigValues;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async initializePricing(blockNumber: number) {
|
|
94
|
-
if (this.synthetixState.onchainConfigValuesWithUndefined === undefined) {
|
|
95
|
-
await this.synthetixState.updateOnchainConfigValues(blockNumber);
|
|
96
|
-
}
|
|
97
|
-
if (!this.statePollingTimer) {
|
|
98
|
-
await this.synthetixState.updateOnchainState();
|
|
99
|
-
this.statePollingTimer = setInterval(async () => {
|
|
100
|
-
try {
|
|
101
|
-
await this.synthetixState.updateOnchainState();
|
|
102
|
-
this.logger.info(
|
|
103
|
-
`${this.dexKey}: onchain state was updated for network=${this.network}`,
|
|
104
|
-
);
|
|
105
|
-
} catch (e) {
|
|
106
|
-
this.logger.error(
|
|
107
|
-
`${this.dexKey}: Failed to update onchain state: `,
|
|
108
|
-
e,
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
}, STATE_TTL_IN_MS);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
getAdapters(side: SwapSide): { name: string; index: number }[] | null {
|
|
116
|
-
return this.adapters[side] ? this.adapters[side] : null;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
getPoolIdentifier(src: Address, dest: Address) {
|
|
120
|
-
return `${this.dexKey}_${src}_${dest}`.toLowerCase();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async getPoolIdentifiers(
|
|
124
|
-
srcToken: Token,
|
|
125
|
-
destToken: Token,
|
|
126
|
-
side: SwapSide,
|
|
127
|
-
blockNumber: number,
|
|
128
|
-
): Promise<string[]> {
|
|
129
|
-
if (side === SwapSide.BUY) return [];
|
|
130
|
-
|
|
131
|
-
const _srcAddress = this.dexHelper.config
|
|
132
|
-
.wrapETH(srcToken)
|
|
133
|
-
.address.toLowerCase();
|
|
134
|
-
const _destAddress = this.dexHelper.config
|
|
135
|
-
.wrapETH(destToken)
|
|
136
|
-
.address.toLowerCase();
|
|
137
|
-
|
|
138
|
-
if (_srcAddress === _destAddress) return [];
|
|
139
|
-
|
|
140
|
-
if (
|
|
141
|
-
this.onchainConfigValues.addressToKey[_srcAddress] !== undefined &&
|
|
142
|
-
this.onchainConfigValues.addressToKey[_destAddress] !== undefined
|
|
143
|
-
) {
|
|
144
|
-
return [this.getPoolIdentifier(_srcAddress, _destAddress)];
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return [];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async getPricesVolume(
|
|
151
|
-
srcToken: Token,
|
|
152
|
-
destToken: Token,
|
|
153
|
-
amounts: bigint[],
|
|
154
|
-
side: SwapSide,
|
|
155
|
-
blockNumber: number,
|
|
156
|
-
limitPools?: string[],
|
|
157
|
-
): Promise<null | ExchangePrices<SynthetixData>> {
|
|
158
|
-
try {
|
|
159
|
-
const _srcToken = this.dexHelper.config.wrapETH(srcToken);
|
|
160
|
-
const _destToken = this.dexHelper.config.wrapETH(destToken);
|
|
161
|
-
|
|
162
|
-
const _srcAddress = _srcToken.address.toLowerCase();
|
|
163
|
-
const _destAddress = _destToken.address.toLowerCase();
|
|
164
|
-
|
|
165
|
-
if (_srcAddress === _destAddress) return null;
|
|
166
|
-
|
|
167
|
-
if (
|
|
168
|
-
this.onchainConfigValues.addressToKey[_srcAddress] === undefined ||
|
|
169
|
-
this.onchainConfigValues.addressToKey[_destAddress] === undefined
|
|
170
|
-
)
|
|
171
|
-
return null;
|
|
172
|
-
|
|
173
|
-
const currentIdentifier = this.getPoolIdentifier(
|
|
174
|
-
_srcAddress,
|
|
175
|
-
_destAddress,
|
|
176
|
-
);
|
|
177
|
-
|
|
178
|
-
// If we received limitPools, but there is not currentIdentifier, we should return null
|
|
179
|
-
// because we don't have that pool to fulfill the request
|
|
180
|
-
if (limitPools !== undefined && !limitPools.includes(currentIdentifier)) {
|
|
181
|
-
return null;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const unitVolume = getBigIntPow(_srcToken.decimals);
|
|
185
|
-
|
|
186
|
-
const _amounts = [unitVolume, ...amounts.slice(1)];
|
|
187
|
-
|
|
188
|
-
const isOptimism = this.network === Network.OPTIMISM;
|
|
189
|
-
|
|
190
|
-
let state = this.synthetixState.getState();
|
|
191
|
-
|
|
192
|
-
if (!state) {
|
|
193
|
-
this.logger.error(
|
|
194
|
-
`${this.dexKey} couldn't receive valid state. Pricing is not working. Check logs`,
|
|
195
|
-
);
|
|
196
|
-
return null;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
if (
|
|
200
|
-
state.isSystemSuspended ||
|
|
201
|
-
state.areSynthsSuspended[_srcAddress] ||
|
|
202
|
-
state.areSynthsSuspended[_destAddress]
|
|
203
|
-
) {
|
|
204
|
-
return null;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const prices = _amounts.map(amount =>
|
|
208
|
-
// For there is different pricing logic
|
|
209
|
-
isOptimism
|
|
210
|
-
? synthetixMath.getAmountsForExchange(
|
|
211
|
-
state!,
|
|
212
|
-
amount,
|
|
213
|
-
this.onchainConfigValues!.addressToKey[_srcAddress],
|
|
214
|
-
this.onchainConfigValues!.addressToKey[_destAddress],
|
|
215
|
-
)
|
|
216
|
-
: synthetixMath.getAmountsForAtomicExchange(
|
|
217
|
-
state!,
|
|
218
|
-
amount,
|
|
219
|
-
this.onchainConfigValues!.addressToKey[_srcAddress],
|
|
220
|
-
this.onchainConfigValues!.addressToKey[_destAddress],
|
|
221
|
-
),
|
|
222
|
-
);
|
|
223
|
-
|
|
224
|
-
const isSUSDInRoute =
|
|
225
|
-
_srcAddress === this.config.sUSDAddress ||
|
|
226
|
-
_destAddress === this.config.sUSDAddress;
|
|
227
|
-
|
|
228
|
-
return [
|
|
229
|
-
{
|
|
230
|
-
unit: prices[0],
|
|
231
|
-
prices: [0n, ...prices.slice(1)],
|
|
232
|
-
data: {
|
|
233
|
-
exchange: this.onchainConfigValues.synthetixAddress,
|
|
234
|
-
srcKey: this.onchainConfigValues.addressToKey[_srcAddress],
|
|
235
|
-
destKey: this.onchainConfigValues.addressToKey[_destAddress],
|
|
236
|
-
exchangeType: isOptimism ? 1 : 0,
|
|
237
|
-
},
|
|
238
|
-
poolIdentifier: currentIdentifier,
|
|
239
|
-
exchange: this.dexKey,
|
|
240
|
-
gasCost: isSUSDInRoute
|
|
241
|
-
? SYNTHETIX_GAS_COST_WITH_SUSD
|
|
242
|
-
: SYNTHETIX_GAS_COST_WITHOUT_SUSD,
|
|
243
|
-
poolAddresses: [this.onchainConfigValues.synthetixAddress],
|
|
244
|
-
},
|
|
245
|
-
];
|
|
246
|
-
} catch (e) {
|
|
247
|
-
this.logger.error(
|
|
248
|
-
`${this.dexKey} error: getPricesVolume ${
|
|
249
|
-
srcToken.symbol || srcToken.address
|
|
250
|
-
}, ${destToken.symbol || destToken.address}, ${side}: `,
|
|
251
|
-
e,
|
|
252
|
-
);
|
|
253
|
-
return null;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Returns estimated gas cost of calldata for this DEX in multiSwap
|
|
258
|
-
getCalldataGasCost(poolPrices: PoolPrices<SynthetixData>): number | number[] {
|
|
259
|
-
return (
|
|
260
|
-
CALLDATA_GAS_COST.DEX_OVERHEAD +
|
|
261
|
-
CALLDATA_GAS_COST.LENGTH_SMALL +
|
|
262
|
-
CALLDATA_GAS_COST.wordNonZeroBytes(8) +
|
|
263
|
-
CALLDATA_GAS_COST.FULL_WORD +
|
|
264
|
-
CALLDATA_GAS_COST.FULL_WORD +
|
|
265
|
-
CALLDATA_GAS_COST.wordNonZeroBytes(1)
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
getAdapterParam(
|
|
270
|
-
srcToken: string,
|
|
271
|
-
destToken: string,
|
|
272
|
-
srcAmount: string,
|
|
273
|
-
destAmount: string,
|
|
274
|
-
data: SynthetixData,
|
|
275
|
-
side: SwapSide,
|
|
276
|
-
): AdapterExchangeParam {
|
|
277
|
-
const { exchange, srcKey, destKey, exchangeType } = data;
|
|
278
|
-
|
|
279
|
-
const payload = this.abiCoder.encodeParameter(
|
|
280
|
-
'tuple(bytes32 trackingCode, bytes32 srcCurrencyKey, bytes32 destCurrencyKey, int8 exchangeType)',
|
|
281
|
-
[this.config.trackingCode, srcKey, destKey, exchangeType],
|
|
282
|
-
);
|
|
283
|
-
|
|
284
|
-
return {
|
|
285
|
-
targetExchange: exchange,
|
|
286
|
-
payload,
|
|
287
|
-
networkFee: '0',
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
async getSimpleParam(
|
|
292
|
-
srcToken: string,
|
|
293
|
-
destToken: string,
|
|
294
|
-
srcAmount: string,
|
|
295
|
-
destAmount: string,
|
|
296
|
-
data: SynthetixData,
|
|
297
|
-
side: SwapSide,
|
|
298
|
-
): Promise<SimpleExchangeParam> {
|
|
299
|
-
if (side === SwapSide.BUY) throw new Error(`Buy not supported`);
|
|
300
|
-
|
|
301
|
-
const { exchange, srcKey, destKey } = data;
|
|
302
|
-
|
|
303
|
-
const swapData =
|
|
304
|
-
this.network === Network.OPTIMISM
|
|
305
|
-
? this.combinedIface.encodeFunctionData('exchange', [
|
|
306
|
-
srcKey,
|
|
307
|
-
srcAmount,
|
|
308
|
-
destKey,
|
|
309
|
-
])
|
|
310
|
-
: this.combinedIface.encodeFunctionData('exchangeAtomically', [
|
|
311
|
-
srcKey,
|
|
312
|
-
srcAmount,
|
|
313
|
-
destKey,
|
|
314
|
-
this.config.trackingCode,
|
|
315
|
-
'1',
|
|
316
|
-
]);
|
|
317
|
-
|
|
318
|
-
return this.buildSimpleParamWithoutWETHConversion(
|
|
319
|
-
srcToken,
|
|
320
|
-
srcAmount,
|
|
321
|
-
destToken,
|
|
322
|
-
destAmount,
|
|
323
|
-
swapData,
|
|
324
|
-
exchange,
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
getDexParam(
|
|
329
|
-
srcToken: Address,
|
|
330
|
-
destToken: Address,
|
|
331
|
-
srcAmount: NumberAsString,
|
|
332
|
-
destAmount: NumberAsString,
|
|
333
|
-
recipient: Address,
|
|
334
|
-
data: SynthetixData,
|
|
335
|
-
side: SwapSide,
|
|
336
|
-
): DexExchangeParam {
|
|
337
|
-
if (side === SwapSide.BUY) throw new Error(`Buy not supported`);
|
|
338
|
-
|
|
339
|
-
const { exchange, srcKey, destKey } = data;
|
|
340
|
-
|
|
341
|
-
const swapData =
|
|
342
|
-
this.network === Network.OPTIMISM
|
|
343
|
-
? this.combinedIface.encodeFunctionData('exchange', [
|
|
344
|
-
srcKey,
|
|
345
|
-
srcAmount,
|
|
346
|
-
destKey,
|
|
347
|
-
])
|
|
348
|
-
: this.combinedIface.encodeFunctionData('exchangeAtomically', [
|
|
349
|
-
srcKey,
|
|
350
|
-
srcAmount,
|
|
351
|
-
destKey,
|
|
352
|
-
this.config.trackingCode,
|
|
353
|
-
'1',
|
|
354
|
-
]);
|
|
355
|
-
|
|
356
|
-
return {
|
|
357
|
-
needWrapNative: this.needWrapNative,
|
|
358
|
-
dexFuncHasRecipient: false,
|
|
359
|
-
exchangeData: swapData,
|
|
360
|
-
targetExchange: exchange,
|
|
361
|
-
returnAmountPos:
|
|
362
|
-
side === SwapSide.SELL
|
|
363
|
-
? extractReturnAmountPosition(
|
|
364
|
-
this.combinedIface,
|
|
365
|
-
this.network === Network.OPTIMISM
|
|
366
|
-
? 'exchange'
|
|
367
|
-
: 'exchangeAtomically',
|
|
368
|
-
'amountReceived',
|
|
369
|
-
)
|
|
370
|
-
: undefined,
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
async updatePoolState(): Promise<void> {
|
|
375
|
-
try {
|
|
376
|
-
this.synthetixState.onchainConfigValues;
|
|
377
|
-
} catch (e) {
|
|
378
|
-
if (
|
|
379
|
-
e instanceof Error &&
|
|
380
|
-
e.message.endsWith('onchain config values are not initialized')
|
|
381
|
-
) {
|
|
382
|
-
await this.synthetixState.updateOnchainConfigValues();
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
throw e;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
async getTopPoolsForToken(
|
|
390
|
-
tokenAddress: Address,
|
|
391
|
-
limit: number,
|
|
392
|
-
): Promise<PoolLiquidity[]> {
|
|
393
|
-
const _tokenAddress = tokenAddress.toLowerCase();
|
|
394
|
-
|
|
395
|
-
if (this.onchainConfigValues.addressToKey[_tokenAddress] === undefined) {
|
|
396
|
-
return [];
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
return [
|
|
400
|
-
{
|
|
401
|
-
exchange: this.dexKey,
|
|
402
|
-
address: this.onchainConfigValues.synthetixAddress,
|
|
403
|
-
connectorTokens: this.config.synths.filter(
|
|
404
|
-
s => s.address !== _tokenAddress,
|
|
405
|
-
),
|
|
406
|
-
liquidityUSD: this.onchainConfigValues.liquidityEstimationInUSD,
|
|
407
|
-
},
|
|
408
|
-
];
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
releaseResources(): AsyncOrSync<void> {
|
|
412
|
-
if (this.statePollingTimer) {
|
|
413
|
-
clearInterval(this.statePollingTimer);
|
|
414
|
-
this.statePollingTimer = undefined;
|
|
415
|
-
this.logger.info(
|
|
416
|
-
`${this.dexKey}: cleared statePollingTimer timer before shutting down`,
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import { AsyncOrSync } from 'ts-essentials';
|
|
3
|
+
import {
|
|
4
|
+
Token,
|
|
5
|
+
Address,
|
|
6
|
+
ExchangePrices,
|
|
7
|
+
PoolPrices,
|
|
8
|
+
AdapterExchangeParam,
|
|
9
|
+
SimpleExchangeParam,
|
|
10
|
+
PoolLiquidity,
|
|
11
|
+
Logger,
|
|
12
|
+
NumberAsString,
|
|
13
|
+
DexExchangeParam,
|
|
14
|
+
} from '../../types';
|
|
15
|
+
import { SwapSide, Network } from '../../constants';
|
|
16
|
+
import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
|
|
17
|
+
import { getBigIntPow, getDexKeysWithNetwork, _require } from '../../utils';
|
|
18
|
+
import { IDex } from '../../dex/idex';
|
|
19
|
+
import { IDexHelper } from '../../dex-helper/idex-helper';
|
|
20
|
+
import { DexParams, SynthetixData } from './types';
|
|
21
|
+
import { SimpleExchange } from '../simple-exchange';
|
|
22
|
+
import { SynthetixConfig, Adapters } from './config';
|
|
23
|
+
import { Interface } from '@ethersproject/abi';
|
|
24
|
+
import {
|
|
25
|
+
STATE_TTL_IN_MS,
|
|
26
|
+
SYNTHETIX_GAS_COST_WITHOUT_SUSD,
|
|
27
|
+
SYNTHETIX_GAS_COST_WITH_SUSD,
|
|
28
|
+
} from './constants';
|
|
29
|
+
import { synthetixMath } from './contract-math/synthetix-math';
|
|
30
|
+
import { SynthetixState } from './synthetix-state';
|
|
31
|
+
// There are so many ABIs, where I need only one or two functions
|
|
32
|
+
// So, I decided to unite them into one combined interface
|
|
33
|
+
import CombinedSynthetixABI from '../../abi/synthetix/CombinedSynthetix.abi.json';
|
|
34
|
+
import { extractReturnAmountPosition } from '../../executor/utils';
|
|
35
|
+
|
|
36
|
+
export class Synthetix extends SimpleExchange implements IDex<SynthetixData> {
|
|
37
|
+
readonly hasConstantPriceLargeAmounts = false;
|
|
38
|
+
readonly needWrapNative = true;
|
|
39
|
+
readonly isFeeOnTransferSupported = false;
|
|
40
|
+
|
|
41
|
+
readonly combinedIface: Interface;
|
|
42
|
+
|
|
43
|
+
logger: Logger;
|
|
44
|
+
|
|
45
|
+
synthetixState: SynthetixState;
|
|
46
|
+
|
|
47
|
+
// It is intermediate measure before we have event base Oracles
|
|
48
|
+
statePollingTimer?: NodeJS.Timer;
|
|
49
|
+
|
|
50
|
+
public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
|
|
51
|
+
getDexKeysWithNetwork(SynthetixConfig);
|
|
52
|
+
|
|
53
|
+
constructor(
|
|
54
|
+
readonly network: Network,
|
|
55
|
+
dexKey: string,
|
|
56
|
+
readonly dexHelper: IDexHelper,
|
|
57
|
+
protected adapters = Adapters[network] || {},
|
|
58
|
+
readonly config = SynthetixConfig[dexKey][network],
|
|
59
|
+
) {
|
|
60
|
+
super(dexHelper, dexKey);
|
|
61
|
+
this.config = this.normalizeConfig(this.config);
|
|
62
|
+
this.logger = dexHelper.getLogger(dexKey);
|
|
63
|
+
this.combinedIface = new Interface(CombinedSynthetixABI);
|
|
64
|
+
this.synthetixState = new SynthetixState(
|
|
65
|
+
this.dexKey,
|
|
66
|
+
this.dexHelper,
|
|
67
|
+
this.combinedIface,
|
|
68
|
+
this.config,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get multiWrapper() {
|
|
73
|
+
return this.dexHelper.multiWrapper;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private normalizeConfig(config: DexParams): DexParams {
|
|
77
|
+
return {
|
|
78
|
+
readProxyAddressResolver: config.readProxyAddressResolver.toLowerCase(),
|
|
79
|
+
flexibleStorage: config.flexibleStorage.toLowerCase(),
|
|
80
|
+
synths: config.synths.map(s => {
|
|
81
|
+
s.address = s.address.toLowerCase();
|
|
82
|
+
return s;
|
|
83
|
+
}),
|
|
84
|
+
sUSDAddress: config.sUSDAddress.toLowerCase(),
|
|
85
|
+
trackingCode: config.trackingCode.toLowerCase(),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get onchainConfigValues() {
|
|
90
|
+
return this.synthetixState.onchainConfigValues;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async initializePricing(blockNumber: number) {
|
|
94
|
+
if (this.synthetixState.onchainConfigValuesWithUndefined === undefined) {
|
|
95
|
+
await this.synthetixState.updateOnchainConfigValues(blockNumber);
|
|
96
|
+
}
|
|
97
|
+
if (!this.statePollingTimer) {
|
|
98
|
+
await this.synthetixState.updateOnchainState();
|
|
99
|
+
this.statePollingTimer = setInterval(async () => {
|
|
100
|
+
try {
|
|
101
|
+
await this.synthetixState.updateOnchainState();
|
|
102
|
+
this.logger.info(
|
|
103
|
+
`${this.dexKey}: onchain state was updated for network=${this.network}`,
|
|
104
|
+
);
|
|
105
|
+
} catch (e) {
|
|
106
|
+
this.logger.error(
|
|
107
|
+
`${this.dexKey}: Failed to update onchain state: `,
|
|
108
|
+
e,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
}, STATE_TTL_IN_MS);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
getAdapters(side: SwapSide): { name: string; index: number }[] | null {
|
|
116
|
+
return this.adapters[side] ? this.adapters[side] : null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
getPoolIdentifier(src: Address, dest: Address) {
|
|
120
|
+
return `${this.dexKey}_${src}_${dest}`.toLowerCase();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async getPoolIdentifiers(
|
|
124
|
+
srcToken: Token,
|
|
125
|
+
destToken: Token,
|
|
126
|
+
side: SwapSide,
|
|
127
|
+
blockNumber: number,
|
|
128
|
+
): Promise<string[]> {
|
|
129
|
+
if (side === SwapSide.BUY) return [];
|
|
130
|
+
|
|
131
|
+
const _srcAddress = this.dexHelper.config
|
|
132
|
+
.wrapETH(srcToken)
|
|
133
|
+
.address.toLowerCase();
|
|
134
|
+
const _destAddress = this.dexHelper.config
|
|
135
|
+
.wrapETH(destToken)
|
|
136
|
+
.address.toLowerCase();
|
|
137
|
+
|
|
138
|
+
if (_srcAddress === _destAddress) return [];
|
|
139
|
+
|
|
140
|
+
if (
|
|
141
|
+
this.onchainConfigValues.addressToKey[_srcAddress] !== undefined &&
|
|
142
|
+
this.onchainConfigValues.addressToKey[_destAddress] !== undefined
|
|
143
|
+
) {
|
|
144
|
+
return [this.getPoolIdentifier(_srcAddress, _destAddress)];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async getPricesVolume(
|
|
151
|
+
srcToken: Token,
|
|
152
|
+
destToken: Token,
|
|
153
|
+
amounts: bigint[],
|
|
154
|
+
side: SwapSide,
|
|
155
|
+
blockNumber: number,
|
|
156
|
+
limitPools?: string[],
|
|
157
|
+
): Promise<null | ExchangePrices<SynthetixData>> {
|
|
158
|
+
try {
|
|
159
|
+
const _srcToken = this.dexHelper.config.wrapETH(srcToken);
|
|
160
|
+
const _destToken = this.dexHelper.config.wrapETH(destToken);
|
|
161
|
+
|
|
162
|
+
const _srcAddress = _srcToken.address.toLowerCase();
|
|
163
|
+
const _destAddress = _destToken.address.toLowerCase();
|
|
164
|
+
|
|
165
|
+
if (_srcAddress === _destAddress) return null;
|
|
166
|
+
|
|
167
|
+
if (
|
|
168
|
+
this.onchainConfigValues.addressToKey[_srcAddress] === undefined ||
|
|
169
|
+
this.onchainConfigValues.addressToKey[_destAddress] === undefined
|
|
170
|
+
)
|
|
171
|
+
return null;
|
|
172
|
+
|
|
173
|
+
const currentIdentifier = this.getPoolIdentifier(
|
|
174
|
+
_srcAddress,
|
|
175
|
+
_destAddress,
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
// If we received limitPools, but there is not currentIdentifier, we should return null
|
|
179
|
+
// because we don't have that pool to fulfill the request
|
|
180
|
+
if (limitPools !== undefined && !limitPools.includes(currentIdentifier)) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const unitVolume = getBigIntPow(_srcToken.decimals);
|
|
185
|
+
|
|
186
|
+
const _amounts = [unitVolume, ...amounts.slice(1)];
|
|
187
|
+
|
|
188
|
+
const isOptimism = this.network === Network.OPTIMISM;
|
|
189
|
+
|
|
190
|
+
let state = this.synthetixState.getState();
|
|
191
|
+
|
|
192
|
+
if (!state) {
|
|
193
|
+
this.logger.error(
|
|
194
|
+
`${this.dexKey} couldn't receive valid state. Pricing is not working. Check logs`,
|
|
195
|
+
);
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (
|
|
200
|
+
state.isSystemSuspended ||
|
|
201
|
+
state.areSynthsSuspended[_srcAddress] ||
|
|
202
|
+
state.areSynthsSuspended[_destAddress]
|
|
203
|
+
) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const prices = _amounts.map(amount =>
|
|
208
|
+
// For there is different pricing logic
|
|
209
|
+
isOptimism
|
|
210
|
+
? synthetixMath.getAmountsForExchange(
|
|
211
|
+
state!,
|
|
212
|
+
amount,
|
|
213
|
+
this.onchainConfigValues!.addressToKey[_srcAddress],
|
|
214
|
+
this.onchainConfigValues!.addressToKey[_destAddress],
|
|
215
|
+
)
|
|
216
|
+
: synthetixMath.getAmountsForAtomicExchange(
|
|
217
|
+
state!,
|
|
218
|
+
amount,
|
|
219
|
+
this.onchainConfigValues!.addressToKey[_srcAddress],
|
|
220
|
+
this.onchainConfigValues!.addressToKey[_destAddress],
|
|
221
|
+
),
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
const isSUSDInRoute =
|
|
225
|
+
_srcAddress === this.config.sUSDAddress ||
|
|
226
|
+
_destAddress === this.config.sUSDAddress;
|
|
227
|
+
|
|
228
|
+
return [
|
|
229
|
+
{
|
|
230
|
+
unit: prices[0],
|
|
231
|
+
prices: [0n, ...prices.slice(1)],
|
|
232
|
+
data: {
|
|
233
|
+
exchange: this.onchainConfigValues.synthetixAddress,
|
|
234
|
+
srcKey: this.onchainConfigValues.addressToKey[_srcAddress],
|
|
235
|
+
destKey: this.onchainConfigValues.addressToKey[_destAddress],
|
|
236
|
+
exchangeType: isOptimism ? 1 : 0,
|
|
237
|
+
},
|
|
238
|
+
poolIdentifier: currentIdentifier,
|
|
239
|
+
exchange: this.dexKey,
|
|
240
|
+
gasCost: isSUSDInRoute
|
|
241
|
+
? SYNTHETIX_GAS_COST_WITH_SUSD
|
|
242
|
+
: SYNTHETIX_GAS_COST_WITHOUT_SUSD,
|
|
243
|
+
poolAddresses: [this.onchainConfigValues.synthetixAddress],
|
|
244
|
+
},
|
|
245
|
+
];
|
|
246
|
+
} catch (e) {
|
|
247
|
+
this.logger.error(
|
|
248
|
+
`${this.dexKey} error: getPricesVolume ${
|
|
249
|
+
srcToken.symbol || srcToken.address
|
|
250
|
+
}, ${destToken.symbol || destToken.address}, ${side}: `,
|
|
251
|
+
e,
|
|
252
|
+
);
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Returns estimated gas cost of calldata for this DEX in multiSwap
|
|
258
|
+
getCalldataGasCost(poolPrices: PoolPrices<SynthetixData>): number | number[] {
|
|
259
|
+
return (
|
|
260
|
+
CALLDATA_GAS_COST.DEX_OVERHEAD +
|
|
261
|
+
CALLDATA_GAS_COST.LENGTH_SMALL +
|
|
262
|
+
CALLDATA_GAS_COST.wordNonZeroBytes(8) +
|
|
263
|
+
CALLDATA_GAS_COST.FULL_WORD +
|
|
264
|
+
CALLDATA_GAS_COST.FULL_WORD +
|
|
265
|
+
CALLDATA_GAS_COST.wordNonZeroBytes(1)
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
getAdapterParam(
|
|
270
|
+
srcToken: string,
|
|
271
|
+
destToken: string,
|
|
272
|
+
srcAmount: string,
|
|
273
|
+
destAmount: string,
|
|
274
|
+
data: SynthetixData,
|
|
275
|
+
side: SwapSide,
|
|
276
|
+
): AdapterExchangeParam {
|
|
277
|
+
const { exchange, srcKey, destKey, exchangeType } = data;
|
|
278
|
+
|
|
279
|
+
const payload = this.abiCoder.encodeParameter(
|
|
280
|
+
'tuple(bytes32 trackingCode, bytes32 srcCurrencyKey, bytes32 destCurrencyKey, int8 exchangeType)',
|
|
281
|
+
[this.config.trackingCode, srcKey, destKey, exchangeType],
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
return {
|
|
285
|
+
targetExchange: exchange,
|
|
286
|
+
payload,
|
|
287
|
+
networkFee: '0',
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async getSimpleParam(
|
|
292
|
+
srcToken: string,
|
|
293
|
+
destToken: string,
|
|
294
|
+
srcAmount: string,
|
|
295
|
+
destAmount: string,
|
|
296
|
+
data: SynthetixData,
|
|
297
|
+
side: SwapSide,
|
|
298
|
+
): Promise<SimpleExchangeParam> {
|
|
299
|
+
if (side === SwapSide.BUY) throw new Error(`Buy not supported`);
|
|
300
|
+
|
|
301
|
+
const { exchange, srcKey, destKey } = data;
|
|
302
|
+
|
|
303
|
+
const swapData =
|
|
304
|
+
this.network === Network.OPTIMISM
|
|
305
|
+
? this.combinedIface.encodeFunctionData('exchange', [
|
|
306
|
+
srcKey,
|
|
307
|
+
srcAmount,
|
|
308
|
+
destKey,
|
|
309
|
+
])
|
|
310
|
+
: this.combinedIface.encodeFunctionData('exchangeAtomically', [
|
|
311
|
+
srcKey,
|
|
312
|
+
srcAmount,
|
|
313
|
+
destKey,
|
|
314
|
+
this.config.trackingCode,
|
|
315
|
+
'1',
|
|
316
|
+
]);
|
|
317
|
+
|
|
318
|
+
return this.buildSimpleParamWithoutWETHConversion(
|
|
319
|
+
srcToken,
|
|
320
|
+
srcAmount,
|
|
321
|
+
destToken,
|
|
322
|
+
destAmount,
|
|
323
|
+
swapData,
|
|
324
|
+
exchange,
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
getDexParam(
|
|
329
|
+
srcToken: Address,
|
|
330
|
+
destToken: Address,
|
|
331
|
+
srcAmount: NumberAsString,
|
|
332
|
+
destAmount: NumberAsString,
|
|
333
|
+
recipient: Address,
|
|
334
|
+
data: SynthetixData,
|
|
335
|
+
side: SwapSide,
|
|
336
|
+
): DexExchangeParam {
|
|
337
|
+
if (side === SwapSide.BUY) throw new Error(`Buy not supported`);
|
|
338
|
+
|
|
339
|
+
const { exchange, srcKey, destKey } = data;
|
|
340
|
+
|
|
341
|
+
const swapData =
|
|
342
|
+
this.network === Network.OPTIMISM
|
|
343
|
+
? this.combinedIface.encodeFunctionData('exchange', [
|
|
344
|
+
srcKey,
|
|
345
|
+
srcAmount,
|
|
346
|
+
destKey,
|
|
347
|
+
])
|
|
348
|
+
: this.combinedIface.encodeFunctionData('exchangeAtomically', [
|
|
349
|
+
srcKey,
|
|
350
|
+
srcAmount,
|
|
351
|
+
destKey,
|
|
352
|
+
this.config.trackingCode,
|
|
353
|
+
'1',
|
|
354
|
+
]);
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
needWrapNative: this.needWrapNative,
|
|
358
|
+
dexFuncHasRecipient: false,
|
|
359
|
+
exchangeData: swapData,
|
|
360
|
+
targetExchange: exchange,
|
|
361
|
+
returnAmountPos:
|
|
362
|
+
side === SwapSide.SELL
|
|
363
|
+
? extractReturnAmountPosition(
|
|
364
|
+
this.combinedIface,
|
|
365
|
+
this.network === Network.OPTIMISM
|
|
366
|
+
? 'exchange'
|
|
367
|
+
: 'exchangeAtomically',
|
|
368
|
+
'amountReceived',
|
|
369
|
+
)
|
|
370
|
+
: undefined,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
async updatePoolState(): Promise<void> {
|
|
375
|
+
try {
|
|
376
|
+
this.synthetixState.onchainConfigValues;
|
|
377
|
+
} catch (e) {
|
|
378
|
+
if (
|
|
379
|
+
e instanceof Error &&
|
|
380
|
+
e.message.endsWith('onchain config values are not initialized')
|
|
381
|
+
) {
|
|
382
|
+
await this.synthetixState.updateOnchainConfigValues();
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
throw e;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
async getTopPoolsForToken(
|
|
390
|
+
tokenAddress: Address,
|
|
391
|
+
limit: number,
|
|
392
|
+
): Promise<PoolLiquidity[]> {
|
|
393
|
+
const _tokenAddress = tokenAddress.toLowerCase();
|
|
394
|
+
|
|
395
|
+
if (this.onchainConfigValues.addressToKey[_tokenAddress] === undefined) {
|
|
396
|
+
return [];
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return [
|
|
400
|
+
{
|
|
401
|
+
exchange: this.dexKey,
|
|
402
|
+
address: this.onchainConfigValues.synthetixAddress,
|
|
403
|
+
connectorTokens: this.config.synths.filter(
|
|
404
|
+
s => s.address !== _tokenAddress,
|
|
405
|
+
),
|
|
406
|
+
liquidityUSD: this.onchainConfigValues.liquidityEstimationInUSD,
|
|
407
|
+
},
|
|
408
|
+
];
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
releaseResources(): AsyncOrSync<void> {
|
|
412
|
+
if (this.statePollingTimer) {
|
|
413
|
+
clearInterval(this.statePollingTimer);
|
|
414
|
+
this.statePollingTimer = undefined;
|
|
415
|
+
this.logger.info(
|
|
416
|
+
`${this.dexKey}: cleared statePollingTimer timer before shutting down`,
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|