@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,347 +1,347 @@
|
|
|
1
|
-
import { Interface } from '@ethersproject/abi';
|
|
2
|
-
import type { AsyncOrSync } from 'ts-essentials';
|
|
3
|
-
import type {
|
|
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 { getDexKeysWithNetwork } from '../../utils';
|
|
18
|
-
import type { Context, IDex } from '../../dex/idex';
|
|
19
|
-
import type { IDexHelper } from '../../dex-helper/idex-helper';
|
|
20
|
-
import type { AngleStakedStableData, DexParams } from './types';
|
|
21
|
-
import { SimpleExchange } from '../simple-exchange';
|
|
22
|
-
import { AngleStakedStableConfig, Adapters } from './config';
|
|
23
|
-
import { AngleStakedStableEventPool } from './angle-staked-stable-pool';
|
|
24
|
-
|
|
25
|
-
const AngleStakedGasCost = 80000;
|
|
26
|
-
|
|
27
|
-
export class AngleStakedStable
|
|
28
|
-
extends SimpleExchange
|
|
29
|
-
implements IDex<AngleStakedStableData>
|
|
30
|
-
{
|
|
31
|
-
protected config: DexParams;
|
|
32
|
-
|
|
33
|
-
readonly hasConstantPriceLargeAmounts = false;
|
|
34
|
-
readonly needWrapNative = true;
|
|
35
|
-
|
|
36
|
-
readonly isFeeOnTransferSupported = false;
|
|
37
|
-
|
|
38
|
-
public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
|
|
39
|
-
getDexKeysWithNetwork(AngleStakedStableConfig);
|
|
40
|
-
|
|
41
|
-
logger: Logger;
|
|
42
|
-
|
|
43
|
-
protected eventPools: { [key: string]: AngleStakedStableEventPool } = {};
|
|
44
|
-
protected isPaused: { [key: string]: boolean } = {};
|
|
45
|
-
|
|
46
|
-
constructor(
|
|
47
|
-
readonly network: Network,
|
|
48
|
-
readonly dexKey: string,
|
|
49
|
-
readonly dexHelper: IDexHelper,
|
|
50
|
-
protected adapters = Adapters[network] || {},
|
|
51
|
-
) {
|
|
52
|
-
super(dexHelper, dexKey);
|
|
53
|
-
const config = AngleStakedStableConfig[dexKey][network];
|
|
54
|
-
this.logger = dexHelper.getLogger(dexKey);
|
|
55
|
-
this.config = {
|
|
56
|
-
stakeToken: config.stakeToken.toLowerCase(),
|
|
57
|
-
agToken: config.agToken.toLowerCase(),
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async initializePricing(blockNumber: number) {
|
|
62
|
-
this.eventPools[this.config.stakeToken] = new AngleStakedStableEventPool(
|
|
63
|
-
this.dexKey,
|
|
64
|
-
this.network,
|
|
65
|
-
this.dexHelper,
|
|
66
|
-
this.config.stakeToken,
|
|
67
|
-
this.config.agToken,
|
|
68
|
-
this.logger,
|
|
69
|
-
);
|
|
70
|
-
await this.eventPools[this.config.stakeToken].initialize(blockNumber);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
getAdapters(side: SwapSide): { name: string; index: number }[] | null {
|
|
74
|
-
return this.adapters[side] ? this.adapters[side] : null;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async getPoolIdentifiers(
|
|
78
|
-
srcToken: Token,
|
|
79
|
-
destToken: Token,
|
|
80
|
-
side: SwapSide,
|
|
81
|
-
blockNumber: number,
|
|
82
|
-
): Promise<string[]> {
|
|
83
|
-
const knownInfo = this._knownAddress(srcToken, destToken);
|
|
84
|
-
if (!knownInfo.known) return [];
|
|
85
|
-
return [`${this.dexKey}_${knownInfo.stakeToken!.toLowerCase()}`];
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async getPricesVolume(
|
|
89
|
-
srcToken: Token,
|
|
90
|
-
destToken: Token,
|
|
91
|
-
amounts: bigint[],
|
|
92
|
-
side: SwapSide,
|
|
93
|
-
blockNumber: number,
|
|
94
|
-
limitPools?: string[],
|
|
95
|
-
): Promise<null | ExchangePrices<AngleStakedStableData>> {
|
|
96
|
-
const srcTokenAddress = srcToken.address.toLowerCase();
|
|
97
|
-
const destTokenAddress = destToken.address.toLowerCase();
|
|
98
|
-
const knownInfo = this._knownAddress(srcToken, destToken);
|
|
99
|
-
if (!knownInfo.known) return null;
|
|
100
|
-
|
|
101
|
-
const agToken = knownInfo.agToken!;
|
|
102
|
-
const stakeToken = knownInfo.stakeToken!;
|
|
103
|
-
const eventPool = this.eventPools[stakeToken];
|
|
104
|
-
const exchange = `${this.dexKey}`;
|
|
105
|
-
const state = await eventPool?.getOrGenerateState(blockNumber);
|
|
106
|
-
if (this.eventPools === null || state === undefined || state === null)
|
|
107
|
-
return null;
|
|
108
|
-
if (srcTokenAddress === agToken && side === SwapSide.SELL)
|
|
109
|
-
return [
|
|
110
|
-
{
|
|
111
|
-
prices: amounts.map(amount =>
|
|
112
|
-
eventPool.getRateDeposit(amount, state),
|
|
113
|
-
),
|
|
114
|
-
unit: eventPool.getRateDeposit(1n * BigInt(10 ** 18), state),
|
|
115
|
-
gasCost: AngleStakedGasCost,
|
|
116
|
-
exchange: exchange,
|
|
117
|
-
data: { exchange: stakeToken },
|
|
118
|
-
poolAddresses: [stakeToken],
|
|
119
|
-
},
|
|
120
|
-
];
|
|
121
|
-
if (destTokenAddress === agToken && side === SwapSide.SELL)
|
|
122
|
-
return [
|
|
123
|
-
{
|
|
124
|
-
prices: amounts.map(share => eventPool.getRateRedeem(share, state)),
|
|
125
|
-
unit: eventPool.getRateRedeem(1n * BigInt(10 ** 18), state),
|
|
126
|
-
gasCost: AngleStakedGasCost,
|
|
127
|
-
exchange: exchange,
|
|
128
|
-
data: { exchange: stakeToken },
|
|
129
|
-
poolAddresses: [stakeToken],
|
|
130
|
-
},
|
|
131
|
-
];
|
|
132
|
-
if (srcTokenAddress === agToken && side === SwapSide.BUY)
|
|
133
|
-
return [
|
|
134
|
-
{
|
|
135
|
-
prices: amounts.map(share => eventPool.getRateMint(share, state)),
|
|
136
|
-
unit: eventPool.getRateMint(1n * BigInt(10 ** 18), state),
|
|
137
|
-
gasCost: AngleStakedGasCost,
|
|
138
|
-
exchange: exchange,
|
|
139
|
-
data: { exchange: stakeToken },
|
|
140
|
-
poolAddresses: [stakeToken],
|
|
141
|
-
},
|
|
142
|
-
];
|
|
143
|
-
return [
|
|
144
|
-
{
|
|
145
|
-
prices: amounts.map(amount => eventPool.getRateWithdraw(amount, state)),
|
|
146
|
-
unit: eventPool.getRateWithdraw(1n * BigInt(10 ** 18), state),
|
|
147
|
-
gasCost: AngleStakedGasCost,
|
|
148
|
-
exchange: exchange,
|
|
149
|
-
data: { exchange: stakeToken },
|
|
150
|
-
poolAddresses: [stakeToken],
|
|
151
|
-
},
|
|
152
|
-
];
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Returns estimated gas cost of calldata for this DEX in multiSwap
|
|
156
|
-
getCalldataGasCost(
|
|
157
|
-
poolPrices: PoolPrices<AngleStakedStableData>,
|
|
158
|
-
): number | number[] {
|
|
159
|
-
return CALLDATA_GAS_COST.DEX_NO_PAYLOAD;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
getAdapterParam(
|
|
163
|
-
srcToken: string,
|
|
164
|
-
destToken: string,
|
|
165
|
-
srcAmount: string,
|
|
166
|
-
destAmount: string,
|
|
167
|
-
data: AngleStakedStableData,
|
|
168
|
-
side: SwapSide,
|
|
169
|
-
): AdapterExchangeParam {
|
|
170
|
-
const { exchange } = data;
|
|
171
|
-
|
|
172
|
-
const payload = this.abiCoder.encodeParameter(
|
|
173
|
-
{
|
|
174
|
-
ParentStruct: {
|
|
175
|
-
toStaked: 'bool',
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
toStaked: srcToken.toLowerCase() === this.config.agToken,
|
|
180
|
-
},
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
return {
|
|
184
|
-
targetExchange: exchange,
|
|
185
|
-
payload,
|
|
186
|
-
networkFee: '0',
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
async getSimpleParam(
|
|
191
|
-
srcToken: string,
|
|
192
|
-
destToken: string,
|
|
193
|
-
srcAmount: string,
|
|
194
|
-
destAmount: string,
|
|
195
|
-
data: AngleStakedStableData,
|
|
196
|
-
side: SwapSide,
|
|
197
|
-
): Promise<SimpleExchangeParam> {
|
|
198
|
-
const { exchange } = data;
|
|
199
|
-
|
|
200
|
-
// Encode here the transaction arguments
|
|
201
|
-
const swapData =
|
|
202
|
-
srcToken.toLowerCase() === this.config.agToken
|
|
203
|
-
? AngleStakedStableEventPool.angleStakedStableIface.encodeFunctionData(
|
|
204
|
-
side === SwapSide.SELL ? 'deposit' : 'mint',
|
|
205
|
-
[
|
|
206
|
-
side === SwapSide.SELL ? srcAmount : destAmount,
|
|
207
|
-
this.augustusAddress,
|
|
208
|
-
],
|
|
209
|
-
)
|
|
210
|
-
: AngleStakedStableEventPool.angleStakedStableIface.encodeFunctionData(
|
|
211
|
-
side === SwapSide.SELL ? 'redeem' : 'withdraw',
|
|
212
|
-
[
|
|
213
|
-
side === SwapSide.SELL ? srcAmount : destAmount,
|
|
214
|
-
this.augustusAddress,
|
|
215
|
-
this.augustusAddress,
|
|
216
|
-
],
|
|
217
|
-
);
|
|
218
|
-
|
|
219
|
-
return this.buildSimpleParamWithoutWETHConversion(
|
|
220
|
-
srcToken,
|
|
221
|
-
srcAmount,
|
|
222
|
-
destToken,
|
|
223
|
-
destAmount,
|
|
224
|
-
swapData,
|
|
225
|
-
exchange,
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
getDexParam(
|
|
230
|
-
srcToken: Address,
|
|
231
|
-
destToken: Address,
|
|
232
|
-
srcAmount: NumberAsString,
|
|
233
|
-
destAmount: NumberAsString,
|
|
234
|
-
recipient: Address,
|
|
235
|
-
data: AngleStakedStableData,
|
|
236
|
-
side: SwapSide,
|
|
237
|
-
_: Context,
|
|
238
|
-
executorAddress: Address,
|
|
239
|
-
): DexExchangeParam {
|
|
240
|
-
const { exchange } = data;
|
|
241
|
-
|
|
242
|
-
const swapData =
|
|
243
|
-
srcToken.toLowerCase() === this.config.agToken
|
|
244
|
-
? AngleStakedStableEventPool.angleStakedStableIface.encodeFunctionData(
|
|
245
|
-
side === SwapSide.SELL ? 'deposit' : 'mint',
|
|
246
|
-
[side === SwapSide.SELL ? srcAmount : destAmount, recipient],
|
|
247
|
-
)
|
|
248
|
-
: AngleStakedStableEventPool.angleStakedStableIface.encodeFunctionData(
|
|
249
|
-
side === SwapSide.SELL ? 'redeem' : 'withdraw',
|
|
250
|
-
[
|
|
251
|
-
side === SwapSide.SELL ? srcAmount : destAmount,
|
|
252
|
-
recipient,
|
|
253
|
-
executorAddress,
|
|
254
|
-
],
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
return {
|
|
258
|
-
needWrapNative: this.needWrapNative,
|
|
259
|
-
dexFuncHasRecipient: true,
|
|
260
|
-
exchangeData: swapData,
|
|
261
|
-
targetExchange: exchange,
|
|
262
|
-
returnAmountPos: undefined,
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// This is called once before getTopPoolsForToken is
|
|
267
|
-
// called for multiple tokens. This can be helpful to
|
|
268
|
-
// update common state required for calculating
|
|
269
|
-
// getTopPoolsForToken. It is optional for a DEX
|
|
270
|
-
// to implement this
|
|
271
|
-
async updatePoolState(): Promise<void> {
|
|
272
|
-
const tokenBalanceMultiCall = [
|
|
273
|
-
{
|
|
274
|
-
target: this.config.stakeToken,
|
|
275
|
-
callData:
|
|
276
|
-
AngleStakedStableEventPool.angleStakedStableIface.encodeFunctionData(
|
|
277
|
-
'paused',
|
|
278
|
-
),
|
|
279
|
-
},
|
|
280
|
-
];
|
|
281
|
-
const returnData = (
|
|
282
|
-
await this.dexHelper.multiContract.methods
|
|
283
|
-
.aggregate(tokenBalanceMultiCall)
|
|
284
|
-
.call()
|
|
285
|
-
).returnData;
|
|
286
|
-
|
|
287
|
-
this.isPaused[this.config.stakeToken] =
|
|
288
|
-
AngleStakedStableEventPool.angleStakedStableIface.decodeFunctionResult(
|
|
289
|
-
'paused',
|
|
290
|
-
returnData[0],
|
|
291
|
-
)[0] as boolean;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Returns list of top pools based on liquidity. Max
|
|
295
|
-
// limit number pools should be returned.
|
|
296
|
-
async getTopPoolsForToken(
|
|
297
|
-
tokenAddress: Address,
|
|
298
|
-
limit: number,
|
|
299
|
-
): Promise<PoolLiquidity[]> {
|
|
300
|
-
if (
|
|
301
|
-
this.isPaused[this.config.stakeToken] ||
|
|
302
|
-
(tokenAddress.toLowerCase() !== this.config.agToken &&
|
|
303
|
-
tokenAddress.toLowerCase() !== this.config.stakeToken)
|
|
304
|
-
) {
|
|
305
|
-
return [];
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
return [
|
|
309
|
-
{
|
|
310
|
-
exchange: this.dexKey,
|
|
311
|
-
address: this.config.stakeToken,
|
|
312
|
-
connectorTokens: [
|
|
313
|
-
tokenAddress.toLowerCase() === this.config.agToken
|
|
314
|
-
? ({ address: this.config.stakeToken, decimals: 18 } as Token)
|
|
315
|
-
: ({ address: this.config.agToken, decimals: 18 } as Token),
|
|
316
|
-
],
|
|
317
|
-
// liquidity is infinite as to have been able to mint stakeToken, you must have deposited agToken
|
|
318
|
-
liquidityUSD: 1e12,
|
|
319
|
-
},
|
|
320
|
-
];
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// This is optional function in case if your implementation has acquired any resources
|
|
324
|
-
// you need to release for graceful shutdown. For example, it may be any interval timer
|
|
325
|
-
releaseResources(): AsyncOrSync<void> {}
|
|
326
|
-
|
|
327
|
-
_knownAddress(
|
|
328
|
-
srcToken: Token,
|
|
329
|
-
destToken: Token,
|
|
330
|
-
): { known: boolean; agToken: string | null; stakeToken: string | null } {
|
|
331
|
-
const srcTokenAddress = srcToken.address.toLowerCase();
|
|
332
|
-
const destTokenAddress = destToken.address.toLowerCase();
|
|
333
|
-
if (
|
|
334
|
-
(srcTokenAddress === this.config.agToken &&
|
|
335
|
-
destTokenAddress === this.config.stakeToken) ||
|
|
336
|
-
(srcTokenAddress === this.config.stakeToken &&
|
|
337
|
-
destTokenAddress === this.config.agToken)
|
|
338
|
-
) {
|
|
339
|
-
return {
|
|
340
|
-
known: true,
|
|
341
|
-
agToken: this.config.agToken,
|
|
342
|
-
stakeToken: this.config.stakeToken,
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
return { known: false, agToken: null, stakeToken: null };
|
|
346
|
-
}
|
|
347
|
-
}
|
|
1
|
+
import { Interface } from '@ethersproject/abi';
|
|
2
|
+
import type { AsyncOrSync } from 'ts-essentials';
|
|
3
|
+
import type {
|
|
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 { getDexKeysWithNetwork } from '../../utils';
|
|
18
|
+
import type { Context, IDex } from '../../dex/idex';
|
|
19
|
+
import type { IDexHelper } from '../../dex-helper/idex-helper';
|
|
20
|
+
import type { AngleStakedStableData, DexParams } from './types';
|
|
21
|
+
import { SimpleExchange } from '../simple-exchange';
|
|
22
|
+
import { AngleStakedStableConfig, Adapters } from './config';
|
|
23
|
+
import { AngleStakedStableEventPool } from './angle-staked-stable-pool';
|
|
24
|
+
|
|
25
|
+
const AngleStakedGasCost = 80000;
|
|
26
|
+
|
|
27
|
+
export class AngleStakedStable
|
|
28
|
+
extends SimpleExchange
|
|
29
|
+
implements IDex<AngleStakedStableData>
|
|
30
|
+
{
|
|
31
|
+
protected config: DexParams;
|
|
32
|
+
|
|
33
|
+
readonly hasConstantPriceLargeAmounts = false;
|
|
34
|
+
readonly needWrapNative = true;
|
|
35
|
+
|
|
36
|
+
readonly isFeeOnTransferSupported = false;
|
|
37
|
+
|
|
38
|
+
public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
|
|
39
|
+
getDexKeysWithNetwork(AngleStakedStableConfig);
|
|
40
|
+
|
|
41
|
+
logger: Logger;
|
|
42
|
+
|
|
43
|
+
protected eventPools: { [key: string]: AngleStakedStableEventPool } = {};
|
|
44
|
+
protected isPaused: { [key: string]: boolean } = {};
|
|
45
|
+
|
|
46
|
+
constructor(
|
|
47
|
+
readonly network: Network,
|
|
48
|
+
readonly dexKey: string,
|
|
49
|
+
readonly dexHelper: IDexHelper,
|
|
50
|
+
protected adapters = Adapters[network] || {},
|
|
51
|
+
) {
|
|
52
|
+
super(dexHelper, dexKey);
|
|
53
|
+
const config = AngleStakedStableConfig[dexKey][network];
|
|
54
|
+
this.logger = dexHelper.getLogger(dexKey);
|
|
55
|
+
this.config = {
|
|
56
|
+
stakeToken: config.stakeToken.toLowerCase(),
|
|
57
|
+
agToken: config.agToken.toLowerCase(),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async initializePricing(blockNumber: number) {
|
|
62
|
+
this.eventPools[this.config.stakeToken] = new AngleStakedStableEventPool(
|
|
63
|
+
this.dexKey,
|
|
64
|
+
this.network,
|
|
65
|
+
this.dexHelper,
|
|
66
|
+
this.config.stakeToken,
|
|
67
|
+
this.config.agToken,
|
|
68
|
+
this.logger,
|
|
69
|
+
);
|
|
70
|
+
await this.eventPools[this.config.stakeToken].initialize(blockNumber);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
getAdapters(side: SwapSide): { name: string; index: number }[] | null {
|
|
74
|
+
return this.adapters[side] ? this.adapters[side] : null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async getPoolIdentifiers(
|
|
78
|
+
srcToken: Token,
|
|
79
|
+
destToken: Token,
|
|
80
|
+
side: SwapSide,
|
|
81
|
+
blockNumber: number,
|
|
82
|
+
): Promise<string[]> {
|
|
83
|
+
const knownInfo = this._knownAddress(srcToken, destToken);
|
|
84
|
+
if (!knownInfo.known) return [];
|
|
85
|
+
return [`${this.dexKey}_${knownInfo.stakeToken!.toLowerCase()}`];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async getPricesVolume(
|
|
89
|
+
srcToken: Token,
|
|
90
|
+
destToken: Token,
|
|
91
|
+
amounts: bigint[],
|
|
92
|
+
side: SwapSide,
|
|
93
|
+
blockNumber: number,
|
|
94
|
+
limitPools?: string[],
|
|
95
|
+
): Promise<null | ExchangePrices<AngleStakedStableData>> {
|
|
96
|
+
const srcTokenAddress = srcToken.address.toLowerCase();
|
|
97
|
+
const destTokenAddress = destToken.address.toLowerCase();
|
|
98
|
+
const knownInfo = this._knownAddress(srcToken, destToken);
|
|
99
|
+
if (!knownInfo.known) return null;
|
|
100
|
+
|
|
101
|
+
const agToken = knownInfo.agToken!;
|
|
102
|
+
const stakeToken = knownInfo.stakeToken!;
|
|
103
|
+
const eventPool = this.eventPools[stakeToken];
|
|
104
|
+
const exchange = `${this.dexKey}`;
|
|
105
|
+
const state = await eventPool?.getOrGenerateState(blockNumber);
|
|
106
|
+
if (this.eventPools === null || state === undefined || state === null)
|
|
107
|
+
return null;
|
|
108
|
+
if (srcTokenAddress === agToken && side === SwapSide.SELL)
|
|
109
|
+
return [
|
|
110
|
+
{
|
|
111
|
+
prices: amounts.map(amount =>
|
|
112
|
+
eventPool.getRateDeposit(amount, state),
|
|
113
|
+
),
|
|
114
|
+
unit: eventPool.getRateDeposit(1n * BigInt(10 ** 18), state),
|
|
115
|
+
gasCost: AngleStakedGasCost,
|
|
116
|
+
exchange: exchange,
|
|
117
|
+
data: { exchange: stakeToken },
|
|
118
|
+
poolAddresses: [stakeToken],
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
if (destTokenAddress === agToken && side === SwapSide.SELL)
|
|
122
|
+
return [
|
|
123
|
+
{
|
|
124
|
+
prices: amounts.map(share => eventPool.getRateRedeem(share, state)),
|
|
125
|
+
unit: eventPool.getRateRedeem(1n * BigInt(10 ** 18), state),
|
|
126
|
+
gasCost: AngleStakedGasCost,
|
|
127
|
+
exchange: exchange,
|
|
128
|
+
data: { exchange: stakeToken },
|
|
129
|
+
poolAddresses: [stakeToken],
|
|
130
|
+
},
|
|
131
|
+
];
|
|
132
|
+
if (srcTokenAddress === agToken && side === SwapSide.BUY)
|
|
133
|
+
return [
|
|
134
|
+
{
|
|
135
|
+
prices: amounts.map(share => eventPool.getRateMint(share, state)),
|
|
136
|
+
unit: eventPool.getRateMint(1n * BigInt(10 ** 18), state),
|
|
137
|
+
gasCost: AngleStakedGasCost,
|
|
138
|
+
exchange: exchange,
|
|
139
|
+
data: { exchange: stakeToken },
|
|
140
|
+
poolAddresses: [stakeToken],
|
|
141
|
+
},
|
|
142
|
+
];
|
|
143
|
+
return [
|
|
144
|
+
{
|
|
145
|
+
prices: amounts.map(amount => eventPool.getRateWithdraw(amount, state)),
|
|
146
|
+
unit: eventPool.getRateWithdraw(1n * BigInt(10 ** 18), state),
|
|
147
|
+
gasCost: AngleStakedGasCost,
|
|
148
|
+
exchange: exchange,
|
|
149
|
+
data: { exchange: stakeToken },
|
|
150
|
+
poolAddresses: [stakeToken],
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Returns estimated gas cost of calldata for this DEX in multiSwap
|
|
156
|
+
getCalldataGasCost(
|
|
157
|
+
poolPrices: PoolPrices<AngleStakedStableData>,
|
|
158
|
+
): number | number[] {
|
|
159
|
+
return CALLDATA_GAS_COST.DEX_NO_PAYLOAD;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
getAdapterParam(
|
|
163
|
+
srcToken: string,
|
|
164
|
+
destToken: string,
|
|
165
|
+
srcAmount: string,
|
|
166
|
+
destAmount: string,
|
|
167
|
+
data: AngleStakedStableData,
|
|
168
|
+
side: SwapSide,
|
|
169
|
+
): AdapterExchangeParam {
|
|
170
|
+
const { exchange } = data;
|
|
171
|
+
|
|
172
|
+
const payload = this.abiCoder.encodeParameter(
|
|
173
|
+
{
|
|
174
|
+
ParentStruct: {
|
|
175
|
+
toStaked: 'bool',
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
toStaked: srcToken.toLowerCase() === this.config.agToken,
|
|
180
|
+
},
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
targetExchange: exchange,
|
|
185
|
+
payload,
|
|
186
|
+
networkFee: '0',
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async getSimpleParam(
|
|
191
|
+
srcToken: string,
|
|
192
|
+
destToken: string,
|
|
193
|
+
srcAmount: string,
|
|
194
|
+
destAmount: string,
|
|
195
|
+
data: AngleStakedStableData,
|
|
196
|
+
side: SwapSide,
|
|
197
|
+
): Promise<SimpleExchangeParam> {
|
|
198
|
+
const { exchange } = data;
|
|
199
|
+
|
|
200
|
+
// Encode here the transaction arguments
|
|
201
|
+
const swapData =
|
|
202
|
+
srcToken.toLowerCase() === this.config.agToken
|
|
203
|
+
? AngleStakedStableEventPool.angleStakedStableIface.encodeFunctionData(
|
|
204
|
+
side === SwapSide.SELL ? 'deposit' : 'mint',
|
|
205
|
+
[
|
|
206
|
+
side === SwapSide.SELL ? srcAmount : destAmount,
|
|
207
|
+
this.augustusAddress,
|
|
208
|
+
],
|
|
209
|
+
)
|
|
210
|
+
: AngleStakedStableEventPool.angleStakedStableIface.encodeFunctionData(
|
|
211
|
+
side === SwapSide.SELL ? 'redeem' : 'withdraw',
|
|
212
|
+
[
|
|
213
|
+
side === SwapSide.SELL ? srcAmount : destAmount,
|
|
214
|
+
this.augustusAddress,
|
|
215
|
+
this.augustusAddress,
|
|
216
|
+
],
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
return this.buildSimpleParamWithoutWETHConversion(
|
|
220
|
+
srcToken,
|
|
221
|
+
srcAmount,
|
|
222
|
+
destToken,
|
|
223
|
+
destAmount,
|
|
224
|
+
swapData,
|
|
225
|
+
exchange,
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
getDexParam(
|
|
230
|
+
srcToken: Address,
|
|
231
|
+
destToken: Address,
|
|
232
|
+
srcAmount: NumberAsString,
|
|
233
|
+
destAmount: NumberAsString,
|
|
234
|
+
recipient: Address,
|
|
235
|
+
data: AngleStakedStableData,
|
|
236
|
+
side: SwapSide,
|
|
237
|
+
_: Context,
|
|
238
|
+
executorAddress: Address,
|
|
239
|
+
): DexExchangeParam {
|
|
240
|
+
const { exchange } = data;
|
|
241
|
+
|
|
242
|
+
const swapData =
|
|
243
|
+
srcToken.toLowerCase() === this.config.agToken
|
|
244
|
+
? AngleStakedStableEventPool.angleStakedStableIface.encodeFunctionData(
|
|
245
|
+
side === SwapSide.SELL ? 'deposit' : 'mint',
|
|
246
|
+
[side === SwapSide.SELL ? srcAmount : destAmount, recipient],
|
|
247
|
+
)
|
|
248
|
+
: AngleStakedStableEventPool.angleStakedStableIface.encodeFunctionData(
|
|
249
|
+
side === SwapSide.SELL ? 'redeem' : 'withdraw',
|
|
250
|
+
[
|
|
251
|
+
side === SwapSide.SELL ? srcAmount : destAmount,
|
|
252
|
+
recipient,
|
|
253
|
+
executorAddress,
|
|
254
|
+
],
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
needWrapNative: this.needWrapNative,
|
|
259
|
+
dexFuncHasRecipient: true,
|
|
260
|
+
exchangeData: swapData,
|
|
261
|
+
targetExchange: exchange,
|
|
262
|
+
returnAmountPos: undefined,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// This is called once before getTopPoolsForToken is
|
|
267
|
+
// called for multiple tokens. This can be helpful to
|
|
268
|
+
// update common state required for calculating
|
|
269
|
+
// getTopPoolsForToken. It is optional for a DEX
|
|
270
|
+
// to implement this
|
|
271
|
+
async updatePoolState(): Promise<void> {
|
|
272
|
+
const tokenBalanceMultiCall = [
|
|
273
|
+
{
|
|
274
|
+
target: this.config.stakeToken,
|
|
275
|
+
callData:
|
|
276
|
+
AngleStakedStableEventPool.angleStakedStableIface.encodeFunctionData(
|
|
277
|
+
'paused',
|
|
278
|
+
),
|
|
279
|
+
},
|
|
280
|
+
];
|
|
281
|
+
const returnData = (
|
|
282
|
+
await this.dexHelper.multiContract.methods
|
|
283
|
+
.aggregate(tokenBalanceMultiCall)
|
|
284
|
+
.call()
|
|
285
|
+
).returnData;
|
|
286
|
+
|
|
287
|
+
this.isPaused[this.config.stakeToken] =
|
|
288
|
+
AngleStakedStableEventPool.angleStakedStableIface.decodeFunctionResult(
|
|
289
|
+
'paused',
|
|
290
|
+
returnData[0],
|
|
291
|
+
)[0] as boolean;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Returns list of top pools based on liquidity. Max
|
|
295
|
+
// limit number pools should be returned.
|
|
296
|
+
async getTopPoolsForToken(
|
|
297
|
+
tokenAddress: Address,
|
|
298
|
+
limit: number,
|
|
299
|
+
): Promise<PoolLiquidity[]> {
|
|
300
|
+
if (
|
|
301
|
+
this.isPaused[this.config.stakeToken] ||
|
|
302
|
+
(tokenAddress.toLowerCase() !== this.config.agToken &&
|
|
303
|
+
tokenAddress.toLowerCase() !== this.config.stakeToken)
|
|
304
|
+
) {
|
|
305
|
+
return [];
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return [
|
|
309
|
+
{
|
|
310
|
+
exchange: this.dexKey,
|
|
311
|
+
address: this.config.stakeToken,
|
|
312
|
+
connectorTokens: [
|
|
313
|
+
tokenAddress.toLowerCase() === this.config.agToken
|
|
314
|
+
? ({ address: this.config.stakeToken, decimals: 18 } as Token)
|
|
315
|
+
: ({ address: this.config.agToken, decimals: 18 } as Token),
|
|
316
|
+
],
|
|
317
|
+
// liquidity is infinite as to have been able to mint stakeToken, you must have deposited agToken
|
|
318
|
+
liquidityUSD: 1e12,
|
|
319
|
+
},
|
|
320
|
+
];
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// This is optional function in case if your implementation has acquired any resources
|
|
324
|
+
// you need to release for graceful shutdown. For example, it may be any interval timer
|
|
325
|
+
releaseResources(): AsyncOrSync<void> {}
|
|
326
|
+
|
|
327
|
+
_knownAddress(
|
|
328
|
+
srcToken: Token,
|
|
329
|
+
destToken: Token,
|
|
330
|
+
): { known: boolean; agToken: string | null; stakeToken: string | null } {
|
|
331
|
+
const srcTokenAddress = srcToken.address.toLowerCase();
|
|
332
|
+
const destTokenAddress = destToken.address.toLowerCase();
|
|
333
|
+
if (
|
|
334
|
+
(srcTokenAddress === this.config.agToken &&
|
|
335
|
+
destTokenAddress === this.config.stakeToken) ||
|
|
336
|
+
(srcTokenAddress === this.config.stakeToken &&
|
|
337
|
+
destTokenAddress === this.config.agToken)
|
|
338
|
+
) {
|
|
339
|
+
return {
|
|
340
|
+
known: true,
|
|
341
|
+
agToken: this.config.agToken,
|
|
342
|
+
stakeToken: this.config.stakeToken,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
return { known: false, agToken: null, stakeToken: null };
|
|
346
|
+
}
|
|
347
|
+
}
|