@paraswap/dex-lib 2.50.6 → 2.50.7-sdai

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.
Files changed (64) hide show
  1. package/build/abi/maker-psm/pot.json +322 -0
  2. package/build/abi/{wombat/pool.json → sdai/SavingsDai.abi.json} +289 -701
  3. package/build/config.js +5 -2
  4. package/build/config.js.map +1 -1
  5. package/build/dex/dexalot/config.js +7 -0
  6. package/build/dex/dexalot/config.js.map +1 -1
  7. package/build/dex/index.js +2 -0
  8. package/build/dex/index.js.map +1 -1
  9. package/build/dex/sdai/config.d.ts +11 -0
  10. package/build/dex/sdai/config.js +24 -0
  11. package/build/dex/sdai/config.js.map +1 -0
  12. package/build/dex/sdai/constants.d.ts +2 -0
  13. package/build/dex/sdai/constants.js +6 -0
  14. package/build/dex/sdai/constants.js.map +1 -0
  15. package/build/dex/sdai/scripts/validate-state.js +102 -0
  16. package/build/dex/sdai/scripts/validate-state.js.map +1 -0
  17. package/build/dex/sdai/sdai-pool.d.ts +16 -0
  18. package/build/dex/sdai/sdai-pool.js +85 -0
  19. package/build/dex/sdai/sdai-pool.js.map +1 -0
  20. package/build/dex/sdai/sdai.d.ts +51 -0
  21. package/build/dex/sdai/sdai.js +172 -0
  22. package/build/dex/sdai/sdai.js.map +1 -0
  23. package/build/dex/sdai/types.d.ts +21 -0
  24. package/build/dex/sdai/types.js +11 -0
  25. package/build/dex/sdai/types.js.map +1 -0
  26. package/build/dex/sdai/utils.d.ts +4 -0
  27. package/build/dex/sdai/utils.js +39 -0
  28. package/build/dex/sdai/utils.js.map +1 -0
  29. package/package.json +1 -1
  30. package/src/abi/maker-psm/pot.json +322 -0
  31. package/src/abi/sdai/SavingsDai.abi.json +877 -0
  32. package/src/config.ts +5 -2
  33. package/src/dex/dexalot/config.ts +7 -0
  34. package/src/dex/dexalot/dexalot-e2e.test.ts +23 -1
  35. package/src/dex/dexalot/dexalot-integration.test.ts +121 -0
  36. package/src/dex/index.ts +2 -0
  37. package/src/dex/sdai/config.ts +28 -0
  38. package/src/dex/sdai/constants.ts +2 -0
  39. package/src/dex/sdai/scripts/validate-state.ts +144 -0
  40. package/src/dex/sdai/sdai-e2e.test.ts +96 -0
  41. package/src/dex/sdai/sdai-events.test.ts +105 -0
  42. package/src/dex/sdai/sdai-integration.test.ts +148 -0
  43. package/src/dex/sdai/sdai-pool.ts +113 -0
  44. package/src/dex/sdai/sdai.ts +233 -0
  45. package/src/dex/sdai/types.ts +23 -0
  46. package/src/dex/sdai/utils.ts +48 -0
  47. package/tests/constants-e2e.ts +2 -2
  48. package/.vscode/launch.json +0 -53
  49. package/.vscode/settings.json +0 -2
  50. package/.vscode/tasks.json +0 -15
  51. package/build/abi/uniswap-v3/AlienBaseV3Router.abi.json +0 -52
  52. package/build/dex/aave-v2/tokens-avalanche.json +0 -44
  53. package/build/dex/aave-v2/tokens-mainnet.json +0 -188
  54. package/build/dex/aave-v2/tokens-polygon.json +0 -44
  55. package/build/dex/solidly-v3/scripts/check-event-pool-event.js +0 -53
  56. package/build/dex/solidly-v3/scripts/check-event-pool-event.js.map +0 -1
  57. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.d.ts +0 -17
  58. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js +0 -64
  59. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js.map +0 -1
  60. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.d.ts +0 -17
  61. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js +0 -79
  62. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js.map +0 -1
  63. package/main-config.ts +0 -4484
  64. /package/build/dex/{solidly-v3/scripts/check-event-pool-event.d.ts → sdai/scripts/validate-state.d.ts} +0 -0
package/src/config.ts CHANGED
@@ -55,8 +55,9 @@ const baseConfigs: { [network: number]: BaseConfig } = {
55
55
  Adapter03: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366',
56
56
  Adapter04: '0x369A2FDb910d432f0a07381a5E3d27572c876713',
57
57
  Adapter05: '0x3329dfa55A40B450952FBE0203167Ae6908E656d',
58
+ Adapter06: '0xe9166234DFB6d3ec05C82404109C02Ca82b16c22',
58
59
  BuyAdapter: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29',
59
- BuyAdapter02: '0xe53d24CD81cC81bbf271AD7B02D0d67f851D727c',
60
+ BuyAdapter02: '0x40dB7541b0c655a3a70c4713aD6879Ec3861c1FE',
60
61
  },
61
62
  uniswapV2ExchangeRouterAddress:
62
63
  '0xF9234CB08edb93c0d4a4d4c70cC3FfD070e78e07',
@@ -288,10 +289,12 @@ const baseConfigs: { [network: number]: BaseConfig } = {
288
289
  swaapV2AuthToken: process.env.API_KEY_SWAAP_V2_AUTH_TOKEN || '',
289
290
  hashFlowDisabledMMs:
290
291
  process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [],
292
+ dexalotAuthToken: process.env.API_KEY_DEXALOT_AUTH_TOKEN || '',
291
293
  adapterAddresses: {
292
294
  ArbitrumAdapter01: '0x369A2FDb910d432f0a07381a5E3d27572c876713',
293
295
  ArbitrumAdapter02: '0x58a5f0b73969800FAFf8556cD2187E3FCE71A6cb',
294
- ArbitrumBuyAdapter: '0x4483Ae378897eB9FbF7f15Df98Bf07233ffFEe8b',
296
+ ArbitrumAdapter03: '0x97bdD2B98D9802b0e387FefdB2882C1b2dc2c344',
297
+ ArbitrumBuyAdapter: '0x005213c48d4aafFcA0b6D1CbA8710F4D035C18f9',
295
298
  },
296
299
  uniswapV2ExchangeRouterAddress:
297
300
  '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC',
@@ -7,6 +7,9 @@ export const DexalotConfig: DexConfigMap<DexParams> = {
7
7
  [Network.AVALANCHE]: {
8
8
  mainnetRFQAddress: '0xEed3c159F3A96aB8d41c8B9cA49EE1e5071A7cdD',
9
9
  },
10
+ [Network.ARBITRUM]: {
11
+ mainnetRFQAddress: '0x010224949cCa211Fb5dDfEDD28Dc8Bf9D2990368',
12
+ },
10
13
  },
11
14
  };
12
15
 
@@ -15,4 +18,8 @@ export const Adapters: Record<number, AdapterMappings> = {
15
18
  [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 6 }],
16
19
  [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 8 }],
17
20
  },
21
+ [Network.ARBITRUM]: {
22
+ [SwapSide.SELL]: [{ name: 'ArbitrumAdapter03', index: 2 }],
23
+ [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 11 }],
24
+ },
18
25
  };
@@ -196,7 +196,7 @@ describe('Dexalot E2E', () => {
196
196
  const tokenASymbol: string = 'BTCb';
197
197
  const tokenBSymbol: string = 'USDC';
198
198
 
199
- const tokenAAmount: string = '100';
199
+ const tokenAAmount: string = '10000';
200
200
  const tokenBAmount: string = '9000000000';
201
201
  const nativeTokenAmount = '1000000000000000000';
202
202
 
@@ -211,4 +211,26 @@ describe('Dexalot E2E', () => {
211
211
  true,
212
212
  );
213
213
  });
214
+
215
+ describe('Arbitrum', () => {
216
+ const network = Network.ARBITRUM;
217
+
218
+ const tokenASymbol: string = 'USDT';
219
+ const tokenBSymbol: string = 'USDC';
220
+
221
+ const tokenAAmount: string = '1000000';
222
+ const tokenBAmount: string = '1000000';
223
+ const nativeTokenAmount = '1000000000000000000';
224
+
225
+ testForNetwork(
226
+ network,
227
+ dexKey,
228
+ tokenASymbol,
229
+ tokenBSymbol,
230
+ tokenAAmount,
231
+ tokenBAmount,
232
+ nativeTokenAmount,
233
+ true,
234
+ );
235
+ });
214
236
  });
@@ -185,4 +185,125 @@ describe('Dexalot', function () {
185
185
  }
186
186
  });
187
187
  });
188
+
189
+ describe('Arbitrum', () => {
190
+ const network = Network.ARBITRUM;
191
+ const dexHelper = new DummyDexHelper(network);
192
+
193
+ const tokens = Tokens[network];
194
+
195
+ const tokenASymbol = 'USDT';
196
+ const tokenBSymbol = 'USDC';
197
+
198
+ const amountsForTokenA = [
199
+ 0n,
200
+ 1n * BI_POWS[tokens[tokenASymbol].decimals],
201
+ 2n * BI_POWS[tokens[tokenASymbol].decimals],
202
+ 3n * BI_POWS[tokens[tokenASymbol].decimals],
203
+ 4n * BI_POWS[tokens[tokenASymbol].decimals],
204
+ 5n * BI_POWS[tokens[tokenASymbol].decimals],
205
+ 6n * BI_POWS[tokens[tokenASymbol].decimals],
206
+ 7n * BI_POWS[tokens[tokenASymbol].decimals],
207
+ 8n * BI_POWS[tokens[tokenASymbol].decimals],
208
+ 9n * BI_POWS[tokens[tokenASymbol].decimals],
209
+ 10n * BI_POWS[tokens[tokenASymbol].decimals],
210
+ ];
211
+
212
+ const amountsForTokenB = [
213
+ 0n,
214
+ 1n * BI_POWS[tokens[tokenBSymbol].decimals],
215
+ 2n * BI_POWS[tokens[tokenBSymbol].decimals],
216
+ 3n * BI_POWS[tokens[tokenBSymbol].decimals],
217
+ 4n * BI_POWS[tokens[tokenBSymbol].decimals],
218
+ 5n * BI_POWS[tokens[tokenBSymbol].decimals],
219
+ 6n * BI_POWS[tokens[tokenBSymbol].decimals],
220
+ 7n * BI_POWS[tokens[tokenBSymbol].decimals],
221
+ 8n * BI_POWS[tokens[tokenBSymbol].decimals],
222
+ 9n * BI_POWS[tokens[tokenBSymbol].decimals],
223
+ 10n * BI_POWS[tokens[tokenBSymbol].decimals],
224
+ ];
225
+
226
+ beforeEach(async () => {
227
+ blockNumber = await dexHelper.web3Provider.eth.getBlockNumber();
228
+ dexalot = new Dexalot(network, dexKey, dexHelper);
229
+ await dexalot.initializePricing(blockNumber);
230
+ await sleep(5000);
231
+ });
232
+
233
+ afterEach(async () => {
234
+ dexalot.releaseResources();
235
+ await sleep(5000);
236
+ });
237
+
238
+ it(`getPoolIdentifiers and getPricesVolume SELL ${tokenASymbol} ${tokenBSymbol}`, async function () {
239
+ await testPricingOnNetwork(
240
+ dexalot,
241
+ network,
242
+ dexKey,
243
+ blockNumber,
244
+ tokenASymbol,
245
+ tokenBSymbol,
246
+ SwapSide.SELL,
247
+ amountsForTokenA,
248
+ );
249
+ });
250
+
251
+ it(`getPoolIdentifiers and getPricesVolume BUY ${tokenASymbol} ${tokenBSymbol}`, async function () {
252
+ await testPricingOnNetwork(
253
+ dexalot,
254
+ network,
255
+ dexKey,
256
+ blockNumber,
257
+ tokenASymbol,
258
+ tokenBSymbol,
259
+ SwapSide.BUY,
260
+ amountsForTokenB,
261
+ );
262
+ });
263
+
264
+ it(`getPoolIdentifiers and getPricesVolume SELL ${tokenBSymbol} ${tokenASymbol}`, async function () {
265
+ await testPricingOnNetwork(
266
+ dexalot,
267
+ network,
268
+ dexKey,
269
+ blockNumber,
270
+ tokenBSymbol,
271
+ tokenASymbol,
272
+ SwapSide.SELL,
273
+ amountsForTokenB,
274
+ );
275
+ });
276
+
277
+ it(`getPoolIdentifiers and getPricesVolume BUY ${tokenBSymbol} ${tokenASymbol}`, async function () {
278
+ await testPricingOnNetwork(
279
+ dexalot,
280
+ network,
281
+ dexKey,
282
+ blockNumber,
283
+ tokenBSymbol,
284
+ tokenASymbol,
285
+ SwapSide.BUY,
286
+ amountsForTokenA,
287
+ );
288
+ });
289
+
290
+ it('getTopPoolsForToken', async function () {
291
+ // We have to check without calling initializePricing, because
292
+ // pool-tracker is not calling that function
293
+ const dexalot = new Dexalot(network, dexKey, dexHelper);
294
+ const poolLiquidity = await dexalot.getTopPoolsForToken(
295
+ tokens[tokenASymbol].address,
296
+ 10,
297
+ );
298
+ console.log(`${tokenASymbol} Top Pools:`, poolLiquidity);
299
+
300
+ if (!dexalot.hasConstantPriceLargeAmounts) {
301
+ checkPoolsLiquidity(
302
+ poolLiquidity,
303
+ Tokens[network][tokenASymbol].address,
304
+ dexKey,
305
+ );
306
+ }
307
+ });
308
+ });
188
309
  });
package/src/dex/index.ts CHANGED
@@ -87,6 +87,7 @@ import { Wombat } from './wombat/wombat';
87
87
  import { Swell } from './swell/swell';
88
88
  import { PharaohV1 } from './solidly/forks-override/pharaohV1';
89
89
  import { EtherFi } from './etherfi';
90
+ import { SDai } from './sdai/sdai';
90
91
 
91
92
  const LegacyDexes = [
92
93
  CurveV2,
@@ -170,6 +171,7 @@ const Dexes = [
170
171
  Wombat,
171
172
  Swell,
172
173
  PharaohV1,
174
+ SDai,
173
175
  ];
174
176
 
175
177
  export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder<
@@ -0,0 +1,28 @@
1
+ import { SDaiParams } from './types';
2
+ import { DexConfigMap } from '../../types';
3
+ import { Network } from '../../constants';
4
+ import { SwapSide } from '@paraswap/core';
5
+
6
+ export const SDaiConfig: DexConfigMap<SDaiParams> = {
7
+ SDai: {
8
+ [Network.MAINNET]: {
9
+ sdaiAddress: '0x83F20F44975D03b1b09e64809B757c47f942BEeA',
10
+ daiAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
11
+ potAddress: '0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7',
12
+ },
13
+ },
14
+ };
15
+
16
+ export const Adapters: {
17
+ [chainId: number]: {
18
+ [side: string]: { name: string; index: number }[];
19
+ };
20
+ } = {
21
+ [Network.MAINNET]: {
22
+ // TODO: uncomment this when SDAI integration got deployed
23
+ // [SwapSide.SELL]: [{ name: 'Adapter06', index: 2 }],
24
+ // [SwapSide.BUY]: [{ name: 'BuyAdapter02', index: 5 }],
25
+ [SwapSide.SELL]: [{ name: 'Adapter06', index: 1 }],
26
+ [SwapSide.BUY]: [{ name: 'BuyAdapter02', index: 4 }],
27
+ },
28
+ };
@@ -0,0 +1,2 @@
1
+ export const SDAI_DEPOSIT_GAS_COST = 165_000;
2
+ export const SDAI_REDEEM_GAS_COST = 90_000;
@@ -0,0 +1,144 @@
1
+ /* eslint-disable no-console */
2
+ import dotenv from 'dotenv';
3
+ dotenv.config();
4
+
5
+ import { Network } from '../../../constants';
6
+ import { DummyDexHelper } from '../../../dex-helper';
7
+ import { SDaiPoolState } from '../types';
8
+ import { BlockHeader } from 'web3-eth';
9
+ import { ethers } from 'ethers';
10
+ import { SDai } from '../sdai';
11
+ import { SDaiConfig } from '../config';
12
+ import { getOnChainState } from '../utils';
13
+ import { Interface } from '@ethersproject/abi';
14
+ import PotAbi from '../../../abi/maker-psm/pot.json';
15
+
16
+ const network = Network.MAINNET;
17
+ const dexKey = 'SDai';
18
+
19
+ const { potAddress } = SDaiConfig[dexKey][network];
20
+ const blockHeaders: Record<number, BlockHeader> = {};
21
+
22
+ const dexHelper = new DummyDexHelper(network);
23
+ const logger = dexHelper.getLogger(dexKey);
24
+
25
+ function preprocessField(value: any): string {
26
+ if (
27
+ typeof value === 'bigint' ||
28
+ typeof value === 'number' ||
29
+ ethers.BigNumber.isBigNumber(value)
30
+ ) {
31
+ return value.toString();
32
+ }
33
+ return value;
34
+ }
35
+
36
+ function compareAndLogDifferences<T extends object, Y extends object>(
37
+ obj1: T,
38
+ obj2: Y,
39
+ keyNames: Array<keyof T & keyof Y>,
40
+ checkEachKey = false,
41
+ ) {
42
+ let isValid = true;
43
+ let keys = keyNames;
44
+
45
+ if (checkEachKey) {
46
+ // find common keys
47
+ const keys1 = Object.keys(obj1);
48
+ const keys2 = new Set(Object.keys(obj2));
49
+ keys = keys1.filter(key => keys2.has(key)) as Array<keyof T & keyof Y>;
50
+ }
51
+
52
+ for (let fieldName of keys) {
53
+ const value1 = preprocessField(obj1[fieldName]);
54
+ const value2 = preprocessField(obj2[fieldName]);
55
+
56
+ if (value1 !== value2) {
57
+ console.log(
58
+ `${fieldName.toString()} mismatch: actual: ${value1} vs pool: ${value2}`,
59
+ );
60
+ isValid = false;
61
+ }
62
+ }
63
+
64
+ return isValid;
65
+ }
66
+
67
+ async function isPoolStateEqualToReal(
68
+ state: SDaiPoolState,
69
+ blockNumber: number,
70
+ ) {
71
+ const expected = await getOnChainState(
72
+ dexHelper.multiContract,
73
+ potAddress,
74
+ new Interface(PotAbi),
75
+ blockNumber,
76
+ );
77
+
78
+ const isValidState = compareAndLogDifferences(state, expected, [
79
+ 'rho',
80
+ 'dsr',
81
+ 'dsr',
82
+ ]);
83
+
84
+ return isValidState;
85
+ }
86
+
87
+ async function checkPoolStateForBlockRange(
88
+ startBlockNumber: number,
89
+ endBlockNumber: number,
90
+ ): Promise<boolean> {
91
+ const network = Network.MAINNET;
92
+ const dexKey = 'SDai';
93
+ const dexHelper = new DummyDexHelper(network);
94
+
95
+ const sdai = new SDai(network, dexKey, dexHelper);
96
+ const pool = await sdai.eventPool;
97
+
98
+ const logsToDispatch = await dexHelper.provider.getLogs({
99
+ fromBlock: startBlockNumber,
100
+ toBlock: endBlockNumber,
101
+ address: potAddress,
102
+ });
103
+
104
+ console.log(logsToDispatch.length);
105
+
106
+ // group logs by block number
107
+ const logsByBlockNumber: Record<number, any[]> = {};
108
+ for (let log of logsToDispatch) {
109
+ if (!logsByBlockNumber[log.blockNumber]) {
110
+ logsByBlockNumber[log.blockNumber] = [];
111
+ }
112
+ logsByBlockNumber[log.blockNumber].push(log);
113
+ }
114
+
115
+ const sortedBlocks = Object.keys(logsByBlockNumber)
116
+ .map(Number)
117
+ .sort((a, b) => Number(a) - Number(b));
118
+
119
+ for (let blockNumber of sortedBlocks) {
120
+ if (!blockHeaders[blockNumber]) {
121
+ blockHeaders[blockNumber] = await dexHelper.web3Provider.eth.getBlock(
122
+ blockNumber,
123
+ );
124
+ }
125
+
126
+ await pool?.update(logsByBlockNumber[blockNumber], {
127
+ [blockNumber]: blockHeaders[blockNumber],
128
+ });
129
+ }
130
+
131
+ const state = pool?.getState(startBlockNumber) as SDaiPoolState;
132
+ return isPoolStateEqualToReal(state, endBlockNumber);
133
+ }
134
+
135
+ async function main() {
136
+ // use findBreakingBlock to find the block where the state is broken
137
+ // console.log(await findBreakingBlock(startBlockNumber, endBlockNumber));
138
+ // previously broken block 150502863
139
+ console.log(await checkPoolStateForBlockRange(19199247 - 10000, 19199247));
140
+ }
141
+
142
+ main()
143
+ .then(() => console.log('Done'))
144
+ .catch(e => console.error(e));
@@ -0,0 +1,96 @@
1
+ import dotenv from 'dotenv';
2
+ dotenv.config();
3
+
4
+ import { testE2E } from '../../../tests/utils-e2e';
5
+ import { Tokens, Holders } from '../../../tests/constants-e2e';
6
+ import { Network, ContractMethod, SwapSide } from '../../constants';
7
+ import { StaticJsonRpcProvider } from '@ethersproject/providers';
8
+ import { generateConfig } from '../../config';
9
+
10
+ function testForNetwork(
11
+ network: Network,
12
+ dexKey: string,
13
+ tokenASymbol: string,
14
+ tokenBSymbol: string,
15
+ tokenAAmount: string,
16
+ tokenBAmount: string,
17
+ ) {
18
+ const provider = new StaticJsonRpcProvider(
19
+ generateConfig(network).privateHttpProvider,
20
+ network,
21
+ );
22
+ const tokens = Tokens[network];
23
+ const holders = Holders[network];
24
+
25
+ const sideToContractMethods = new Map([
26
+ [
27
+ SwapSide.SELL,
28
+ [
29
+ ContractMethod.simpleSwap,
30
+ ContractMethod.multiSwap,
31
+ ContractMethod.megaSwap,
32
+ ],
33
+ ],
34
+ [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]],
35
+ ]);
36
+
37
+ describe(`${network}`, () => {
38
+ sideToContractMethods.forEach((contractMethods, side) =>
39
+ describe(`${side}`, () => {
40
+ contractMethods.forEach((contractMethod: ContractMethod) => {
41
+ describe(`${contractMethod}`, () => {
42
+ it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => {
43
+ await testE2E(
44
+ tokens[tokenASymbol],
45
+ tokens[tokenBSymbol],
46
+ holders[tokenASymbol],
47
+ side === SwapSide.SELL ? tokenAAmount : tokenBAmount,
48
+ side,
49
+ dexKey,
50
+ contractMethod,
51
+ network,
52
+ provider,
53
+ );
54
+ });
55
+ it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => {
56
+ await testE2E(
57
+ tokens[tokenBSymbol],
58
+ tokens[tokenASymbol],
59
+ holders[tokenBSymbol],
60
+ side === SwapSide.SELL ? tokenBAmount : tokenAAmount,
61
+ side,
62
+ dexKey,
63
+ contractMethod,
64
+ network,
65
+ provider,
66
+ );
67
+ });
68
+ });
69
+ });
70
+ }),
71
+ );
72
+ });
73
+ }
74
+
75
+ describe('sDAI E2E', () => {
76
+ const dexKey = 'sdai';
77
+
78
+ describe('Mainnet', () => {
79
+ const network = Network.MAINNET;
80
+
81
+ const tokenASymbol: string = 'DAI';
82
+ const tokenBSymbol: string = 'sDAI';
83
+
84
+ const tokenAAmount: string = '1000000000000000000';
85
+ const tokenBAmount: string = '1000000000000000000';
86
+
87
+ testForNetwork(
88
+ network,
89
+ dexKey,
90
+ tokenASymbol,
91
+ tokenBSymbol,
92
+ tokenAAmount,
93
+ tokenBAmount,
94
+ );
95
+ });
96
+ });
@@ -0,0 +1,105 @@
1
+ import dotenv from 'dotenv';
2
+ dotenv.config();
3
+
4
+ import { SDaiEventPool } from './sdai-pool';
5
+ import { SDaiConfig } from './config';
6
+ import { Network } from '../../constants';
7
+ import { DummyDexHelper } from '../../dex-helper/index';
8
+ import { testEventSubscriber } from '../../../tests/utils-events';
9
+ import { SDaiPoolState } from './types';
10
+
11
+ import PotAbi from '../../abi/maker-psm/pot.json';
12
+ import { Interface } from '@ethersproject/abi';
13
+ import _ from 'lodash';
14
+
15
+ /*
16
+ README
17
+ ======
18
+
19
+ This test script adds unit tests for SDai event based
20
+ system. This is done by fetching the state on-chain before the
21
+ event block, manually pushing the block logs to the event-subscriber,
22
+ comparing the local state with on-chain state.
23
+
24
+ Most of the logic for testing is abstracted by `testEventSubscriber`.
25
+ You need to do two things to make the tests work:
26
+
27
+ 1. Fetch the block numbers where certain events were released. You
28
+ can modify the `./scripts/fetch-event-blocknumber.ts` to get the
29
+ block numbers for different events. Make sure to get sufficient
30
+ number of blockNumbers to cover all possible cases for the event
31
+ mutations.
32
+
33
+ 2. Complete the implementation for fetchPoolState function. The
34
+ function should fetch the on-chain state of the event subscriber
35
+ using just the blocknumber.
36
+
37
+ The template tests only include the test for a single event
38
+ subscriber. There can be cases where multiple event subscribers
39
+ exist for a single DEX. In such cases additional tests should be
40
+ added.
41
+
42
+ You can run this individual test script by running:
43
+ `npx jest src/dex/<dex-name>/<dex-name>-events.test.ts`
44
+
45
+ (This comment should be removed from the final implementation)
46
+ */
47
+
48
+ jest.setTimeout(50 * 1000);
49
+ const dexKey = 'SDai';
50
+ const network = Network.MAINNET;
51
+
52
+ async function fetchPoolState(
53
+ sdaiPool: SDaiEventPool,
54
+ blockNumber: number,
55
+ ): Promise<SDaiPoolState> {
56
+ return sdaiPool.generateState(blockNumber);
57
+ }
58
+
59
+ describe('SDai Event', function () {
60
+ const blockNumbers: { [eventName: string]: number[] } = {
61
+ drip: [19827559, 19827524, 19827163, 19827124, 19827000, 19826892],
62
+ // TODO: no matching logs, you have to manually call "file"
63
+ // from "0xbe8e3e3618f7474f8cb1d074a26affef007e98fb" address
64
+ // https://etherscan.io/advanced-filter?fadd=0x197e90f9fad81970ba7976f33cbd77088e5d7cf7&tadd=0x197e90f9fad81970ba7976f33cbd77088e5d7cf7&mtd=0x29ae8114%7eFile
65
+ // file: [19831086]
66
+ };
67
+
68
+ const addresses: { [contract: string]: string } = {
69
+ potAddress: SDaiConfig[dexKey][network].potAddress,
70
+ };
71
+
72
+ describe('SDaiPool', function () {
73
+ Object.keys(blockNumbers).forEach((event: string) => {
74
+ blockNumbers[event].forEach((blockNumber: number) => {
75
+ it(`Should return the correct state after the ${blockNumber}:${event}`, async function () {
76
+ const dexHelper = new DummyDexHelper(network);
77
+ const logger = dexHelper.getLogger(dexKey);
78
+
79
+ const sdaiPool = new SDaiEventPool(
80
+ dexKey,
81
+ dexHelper,
82
+ addresses.potAddress,
83
+ new Interface(PotAbi),
84
+ logger,
85
+ );
86
+
87
+ await sdaiPool.initialize(blockNumber);
88
+
89
+ await testEventSubscriber(
90
+ sdaiPool,
91
+ sdaiPool.addressesSubscribed,
92
+ (_blockNumber: number) => fetchPoolState(sdaiPool, _blockNumber),
93
+ blockNumber,
94
+ `${dexKey}_${sdaiPool}`,
95
+ dexHelper.provider,
96
+ (state, expected) => {
97
+ // TODO:
98
+ expect(_.omit(state, ['chi'])).toEqual(_.omit(expected, ['chi']));
99
+ },
100
+ );
101
+ });
102
+ });
103
+ });
104
+ });
105
+ });