@paraswap/dex-lib 3.4.1 → 3.4.2-idle

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 (179) hide show
  1. package/build/abi/Redstone.json +739 -0
  2. package/build/abi/angle-transmuter/MorphoOracle.json +193 -0
  3. package/build/abi/angle-transmuter/MorphoVault.json +2506 -0
  4. package/build/abi/angle-transmuter/Pyth.json +1534 -0
  5. package/build/abi/angle-transmuter/Transmuter.json +1711 -0
  6. package/build/abi/angle-transmuter/TransmuterSidechain.json +1798 -0
  7. package/build/abi/idle-dao/idle-cdo-factory.json +38 -0
  8. package/build/abi/idle-dao/idle-cdo.json +1245 -0
  9. package/build/abi/pharaoh/PharaohPool.abi.json +1582 -0
  10. package/build/abi/smardex/smardex-factory.json +185 -0
  11. package/build/abi/smardex/smardex-pool.json +578 -0
  12. package/build/abi/smardex/smardex-router.json +648 -0
  13. package/build/abi/trader-joe-v2_1/FactoryABI.json +1208 -0
  14. package/build/abi/trader-joe-v2_1/PairABI.json +1493 -0
  15. package/build/abi/trader-joe-v2_1/RouterABI.json +1489 -0
  16. package/build/abi/trader-joe-v2_1/StateMulticall.json +193 -0
  17. package/build/config.js +11 -5
  18. package/build/config.js.map +1 -1
  19. package/build/dex/aave-v1/aave-v1.js +0 -1
  20. package/build/dex/aave-v1/aave-v1.js.map +1 -1
  21. package/build/dex/angle-transmuter/angle-transmuter-pool.d.ts +61 -0
  22. package/build/dex/angle-transmuter/angle-transmuter-pool.js +424 -0
  23. package/build/dex/angle-transmuter/angle-transmuter-pool.js.map +1 -0
  24. package/build/dex/angle-transmuter/angle-transmuter.d.ts +60 -0
  25. package/build/dex/angle-transmuter/angle-transmuter.js +281 -0
  26. package/build/dex/angle-transmuter/angle-transmuter.js.map +1 -0
  27. package/build/dex/angle-transmuter/backedOracle.d.ts +19 -0
  28. package/build/dex/angle-transmuter/backedOracle.js +56 -0
  29. package/build/dex/angle-transmuter/backedOracle.js.map +1 -0
  30. package/build/dex/angle-transmuter/config.d.ts +4 -0
  31. package/build/dex/angle-transmuter/config.js +50 -0
  32. package/build/dex/angle-transmuter/config.js.map +1 -0
  33. package/build/dex/angle-transmuter/constants.d.ts +10 -0
  34. package/build/dex/angle-transmuter/constants.js +137 -0
  35. package/build/dex/angle-transmuter/constants.js.map +1 -0
  36. package/build/dex/angle-transmuter/morphoOracle.d.ts +42 -0
  37. package/build/dex/angle-transmuter/morphoOracle.js +179 -0
  38. package/build/dex/angle-transmuter/morphoOracle.js.map +1 -0
  39. package/build/dex/angle-transmuter/morphoVault.d.ts +20 -0
  40. package/build/dex/angle-transmuter/morphoVault.js +84 -0
  41. package/build/dex/angle-transmuter/morphoVault.js.map +1 -0
  42. package/build/dex/angle-transmuter/pyth.d.ts +19 -0
  43. package/build/dex/angle-transmuter/pyth.js +70 -0
  44. package/build/dex/angle-transmuter/pyth.js.map +1 -0
  45. package/build/dex/angle-transmuter/redstone.d.ts +20 -0
  46. package/build/dex/angle-transmuter/redstone.js +73 -0
  47. package/build/dex/angle-transmuter/redstone.js.map +1 -0
  48. package/build/dex/angle-transmuter/transmuter.d.ts +55 -0
  49. package/build/dex/angle-transmuter/transmuter.js +412 -0
  50. package/build/dex/angle-transmuter/transmuter.js.map +1 -0
  51. package/build/dex/angle-transmuter/types.d.ts +189 -0
  52. package/build/dex/angle-transmuter/types.js +33 -0
  53. package/build/dex/angle-transmuter/types.js.map +1 -0
  54. package/build/dex/angle-transmuter/utils.d.ts +9 -0
  55. package/build/dex/angle-transmuter/utils.js +257 -0
  56. package/build/dex/angle-transmuter/utils.js.map +1 -0
  57. package/build/dex/idle-dao/config.d.ts +7 -0
  58. package/build/dex/idle-dao/config.js +571 -0
  59. package/build/dex/idle-dao/config.js.map +1 -0
  60. package/build/dex/idle-dao/idle-dao-pool.d.ts +56 -0
  61. package/build/dex/idle-dao/idle-dao-pool.js +176 -0
  62. package/build/dex/idle-dao/idle-dao-pool.js.map +1 -0
  63. package/build/dex/idle-dao/idle-dao-pooling-pool.d.ts +16 -0
  64. package/build/dex/idle-dao/idle-dao-pooling-pool.js +57 -0
  65. package/build/dex/idle-dao/idle-dao-pooling-pool.js.map +1 -0
  66. package/build/dex/idle-dao/idle-dao.d.ts +52 -0
  67. package/build/dex/idle-dao/idle-dao.js +321 -0
  68. package/build/dex/idle-dao/idle-dao.js.map +1 -0
  69. package/build/dex/idle-dao/tokens.d.ts +16 -0
  70. package/build/dex/idle-dao/tokens.js +87 -0
  71. package/build/dex/idle-dao/tokens.js.map +1 -0
  72. package/build/dex/idle-dao/types.d.ts +37 -0
  73. package/build/dex/idle-dao/types.js +11 -0
  74. package/build/dex/idle-dao/types.js.map +1 -0
  75. package/build/dex/idle-dao/utils.d.ts +8 -0
  76. package/build/dex/idle-dao/utils.js +147 -0
  77. package/build/dex/idle-dao/utils.js.map +1 -0
  78. package/build/dex/index.js +2 -0
  79. package/build/dex/index.js.map +1 -1
  80. package/build/dex/platypus/platypus.js +3 -17
  81. package/build/dex/platypus/platypus.js.map +1 -1
  82. package/build/dex/smardex/subgraph-queries.d.ts +1 -0
  83. package/build/dex/smardex/subgraph-queries.js +17 -0
  84. package/build/dex/smardex/subgraph-queries.js.map +1 -0
  85. package/build/dex/smardex/usd-reserves.d.ts +23 -0
  86. package/build/dex/smardex/usd-reserves.js +86 -0
  87. package/build/dex/smardex/usd-reserves.js.map +1 -0
  88. package/build/dex/stable-pool.js +8 -1
  89. package/build/dex/stable-pool.js.map +1 -1
  90. package/build/dex/swaap-v1/swaap-v1.js +0 -4
  91. package/build/dex/swaap-v1/swaap-v1.js.map +1 -1
  92. package/build/dex/swaap-v2/config.js +15 -0
  93. package/build/dex/swaap-v2/config.js.map +1 -1
  94. package/build/dex/trader-joe-v2-1-2/config.d.ts +4 -0
  95. package/build/dex/trader-joe-v2-1-2/config.js +47 -0
  96. package/build/dex/trader-joe-v2-1-2/config.js.map +1 -0
  97. package/build/dex/trader-joe-v2-1-2/constants.d.ts +20 -0
  98. package/build/dex/trader-joe-v2-1-2/constants.js +22 -0
  99. package/build/dex/trader-joe-v2-1-2/constants.js.map +1 -0
  100. package/build/dex/trader-joe-v2-1-2/math/index.d.ts +37 -0
  101. package/build/dex/trader-joe-v2-1-2/math/index.js +291 -0
  102. package/build/dex/trader-joe-v2-1-2/math/index.js.map +1 -0
  103. package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2-pool.d.ts +60 -0
  104. package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2-pool.js +248 -0
  105. package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2-pool.js.map +1 -0
  106. package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2.d.ts +53 -0
  107. package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2.js +307 -0
  108. package/build/dex/trader-joe-v2-1-2/trader-joe-v2-1-2.js.map +1 -0
  109. package/build/dex/trader-joe-v2-1-2/types.d.ts +82 -0
  110. package/build/dex/trader-joe-v2-1-2/types.js +9 -0
  111. package/build/dex/trader-joe-v2-1-2/types.js.map +1 -0
  112. package/build/dex/trader-joe-v2_1/config.d.ts +4 -0
  113. package/build/dex/trader-joe-v2_1/config.js +47 -0
  114. package/build/dex/trader-joe-v2_1/config.js.map +1 -0
  115. package/build/dex/trader-joe-v2_1/constants.d.ts +20 -0
  116. package/build/dex/trader-joe-v2_1/constants.js +22 -0
  117. package/build/dex/trader-joe-v2_1/constants.js.map +1 -0
  118. package/build/dex/trader-joe-v2_1/math/index.d.ts +37 -0
  119. package/build/dex/trader-joe-v2_1/math/index.js +291 -0
  120. package/build/dex/trader-joe-v2_1/math/index.js.map +1 -0
  121. package/build/dex/trader-joe-v2_1/trader-joe-v2.1.d.ts +0 -0
  122. package/build/dex/trader-joe-v2_1/trader-joe-v2.1.js +384 -0
  123. package/build/dex/trader-joe-v2_1/trader-joe-v2.1.js.map +1 -0
  124. package/build/dex/trader-joe-v2_1/trader-joe-v2_1-pool.d.ts +60 -0
  125. package/build/dex/trader-joe-v2_1/trader-joe-v2_1-pool.js +247 -0
  126. package/build/dex/trader-joe-v2_1/trader-joe-v2_1-pool.js.map +1 -0
  127. package/build/dex/trader-joe-v2_1/trader-joe-v2_1.d.ts +53 -0
  128. package/build/dex/trader-joe-v2_1/trader-joe-v2_1.js +307 -0
  129. package/build/dex/trader-joe-v2_1/trader-joe-v2_1.js.map +1 -0
  130. package/build/dex/trader-joe-v2_1/types.d.ts +82 -0
  131. package/build/dex/trader-joe-v2_1/types.js +9 -0
  132. package/build/dex/trader-joe-v2_1/types.js.map +1 -0
  133. package/build/dex/wombat/wombat-pool-poller.d.ts +22 -0
  134. package/build/dex/wombat/wombat-pool-poller.js +164 -0
  135. package/build/dex/wombat/wombat-pool-poller.js.map +1 -0
  136. package/build/dex-helper/Cache.d.ts +31 -0
  137. package/build/dex-helper/Cache.js +106 -0
  138. package/build/dex-helper/Cache.js.map +1 -0
  139. package/build/dex-helper/RedisBatcher.d.ts +20 -0
  140. package/build/dex-helper/RedisBatcher.js +75 -0
  141. package/build/dex-helper/RedisBatcher.js.map +1 -0
  142. package/build/dex-helper/RedisWrapper.d.ts +37 -0
  143. package/build/dex-helper/RedisWrapper.js +165 -0
  144. package/build/dex-helper/RedisWrapper.js.map +1 -0
  145. package/build/types.d.ts +1 -0
  146. package/package.json +1 -1
  147. package/src/abi/idle-dao/idle-cdo-factory.json +38 -0
  148. package/src/abi/idle-dao/idle-cdo.json +1245 -0
  149. package/src/config.ts +12 -5
  150. package/src/dex/idle-dao/config.ts +574 -0
  151. package/src/dex/idle-dao/idle-dao-e2e.test.ts +113 -0
  152. package/src/dex/idle-dao/idle-dao-events.test.ts +133 -0
  153. package/src/dex/idle-dao/idle-dao-integration.test.ts +166 -0
  154. package/src/dex/idle-dao/idle-dao-pool.ts +304 -0
  155. package/src/dex/idle-dao/idle-dao-pooling-pool.ts +87 -0
  156. package/src/dex/idle-dao/idle-dao.ts +509 -0
  157. package/src/dex/idle-dao/tokens.ts +117 -0
  158. package/src/dex/idle-dao/types.ts +48 -0
  159. package/src/dex/idle-dao/utils.ts +216 -0
  160. package/src/dex/index.ts +2 -0
  161. package/src/dex/swaap-v2/config.ts +15 -0
  162. package/src/dex/swaap-v2/swaap-v2-e2e.test.ts +233 -17
  163. package/src/dex/swaap-v2/swaap-v2-integration.test.ts +1 -1
  164. package/src/types.ts +1 -0
  165. package/tests/constants-e2e.ts +82 -6
  166. package/.vscode/launch.json +0 -53
  167. package/.vscode/settings.json +0 -2
  168. package/.vscode/tasks.json +0 -15
  169. package/abis.txt +0 -92
  170. package/build/abi/uniswap-v3/AlienBaseV3Router.abi.json +0 -52
  171. package/build/dex/solidly-v3/scripts/check-event-pool-event.d.ts +0 -1
  172. package/build/dex/solidly-v3/scripts/check-event-pool-event.js +0 -53
  173. package/build/dex/solidly-v3/scripts/check-event-pool-event.js.map +0 -1
  174. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.d.ts +0 -17
  175. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js +0 -64
  176. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js.map +0 -1
  177. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.d.ts +0 -17
  178. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js +0 -79
  179. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js.map +0 -1
@@ -0,0 +1,113 @@
1
+ /* eslint-disable no-console */
2
+ import dotenv from 'dotenv';
3
+ dotenv.config();
4
+
5
+ import { testE2E } from '../../../tests/utils-e2e';
6
+ import { Tokens, Holders } from '../../../tests/constants-e2e';
7
+ import { Network, ContractMethod, SwapSide } from '../../constants';
8
+ import { StaticJsonRpcProvider } from '@ethersproject/providers';
9
+ import { generateConfig } from '../../config';
10
+
11
+ function testForNetwork(
12
+ network: Network,
13
+ dexKey: string,
14
+ tokenASymbol: string,
15
+ tokenBSymbol: string,
16
+ tokenAAmount: string,
17
+ tokenBAmount: string,
18
+ ) {
19
+ const provider = new StaticJsonRpcProvider(
20
+ generateConfig(network).privateHttpProvider,
21
+ network,
22
+ );
23
+ const tokens = Tokens[network];
24
+ const holders = Holders[network];
25
+
26
+ const sideToContractMethods = new Map([
27
+ [SwapSide.SELL, [ContractMethod.swapExactAmountIn]],
28
+ [SwapSide.BUY, [ContractMethod.swapExactAmountOut]],
29
+ ]);
30
+
31
+ describe(`${network}`, () => {
32
+ sideToContractMethods.forEach((contractMethods, side) =>
33
+ describe(`${side}`, () => {
34
+ contractMethods.forEach((contractMethod: ContractMethod) => {
35
+ describe(`${contractMethod}`, () => {
36
+ it(`${tokenASymbol} -> ${tokenBSymbol} - ${tokenAAmount}`, async () => {
37
+ await testE2E(
38
+ tokens[tokenASymbol],
39
+ tokens[tokenBSymbol],
40
+ holders[tokenASymbol],
41
+ side === SwapSide.SELL ? tokenAAmount : tokenBAmount,
42
+ side,
43
+ dexKey,
44
+ contractMethod,
45
+ network,
46
+ provider,
47
+ );
48
+ });
49
+
50
+ it(`${tokenBSymbol} -> ${tokenASymbol} - ${tokenBAmount}`, async () => {
51
+ await testE2E(
52
+ tokens[tokenBSymbol],
53
+ tokens[tokenASymbol],
54
+ holders[tokenBSymbol],
55
+ side === SwapSide.SELL ? tokenBAmount : tokenAAmount,
56
+ side,
57
+ dexKey,
58
+ contractMethod,
59
+ network,
60
+ provider,
61
+ );
62
+ });
63
+ });
64
+ });
65
+ }),
66
+ );
67
+ });
68
+ }
69
+
70
+ describe('IdleDao E2E', () => {
71
+ const dexKey = 'IdleDao';
72
+
73
+ describe('Mainnet', () => {
74
+ const network = Network.MAINNET;
75
+ const tests = [
76
+ {
77
+ tokenASymbol: 'STETH',
78
+ tokenBSymbol: 'AA_wstETH',
79
+ tokenAAmount: '1000000000000000000',
80
+ tokenBAmount: '1000000000000000000',
81
+ },
82
+ {
83
+ tokenASymbol: 'USDC',
84
+ tokenBSymbol: 'AA_idle_cpPOR-USDC',
85
+ tokenAAmount: '1000000',
86
+ tokenBAmount: '1000000000000000000',
87
+ },
88
+ {
89
+ tokenASymbol: 'USDT',
90
+ tokenBSymbol: 'BB_idle_cpFAS-USDT',
91
+ tokenAAmount: '1000000',
92
+ tokenBAmount: '1000000000000000000',
93
+ },
94
+ {
95
+ tokenASymbol: 'WETH',
96
+ tokenBSymbol: 'BB_Re7WETH',
97
+ tokenAAmount: '100000000000000',
98
+ tokenBAmount: '100000000000000',
99
+ },
100
+ ];
101
+
102
+ tests.forEach(testData => {
103
+ testForNetwork(
104
+ network,
105
+ dexKey,
106
+ testData.tokenASymbol,
107
+ testData.tokenBSymbol,
108
+ testData.tokenAAmount,
109
+ testData.tokenBAmount,
110
+ );
111
+ });
112
+ });
113
+ });
@@ -0,0 +1,133 @@
1
+ /* eslint-disable no-console */
2
+ import dotenv from 'dotenv';
3
+ dotenv.config();
4
+
5
+ import { IdleDao } from './idle-dao';
6
+ import { IdleDaoEventPool } from './idle-dao-pool';
7
+ import { Network } from '../../constants';
8
+ import { Address, Logger } from '../../types';
9
+ import { DummyDexHelper } from '../../dex-helper/index';
10
+ import { testEventSubscriber } from '../../../tests/utils-events';
11
+ import { PoolState, IdleToken } from './types';
12
+
13
+ jest.setTimeout(50 * 1000);
14
+
15
+ async function fetchPoolState(
16
+ idleDaoPool: IdleDaoEventPool,
17
+ blockNumber: number,
18
+ poolAddress: string,
19
+ logger: Logger,
20
+ ): Promise<PoolState> {
21
+ const state = await idleDaoPool.generateState(blockNumber);
22
+ return state;
23
+ }
24
+
25
+ type EventMappings = Record<string, number[]>;
26
+
27
+ describe('IdleDao EventPool Mainnet', function () {
28
+ const dexKey = 'IdleDao';
29
+ let latestBlockNumber: number;
30
+ const network = Network.MAINNET;
31
+ let tokensList: Record<string, IdleToken>;
32
+ const dexHelper = new DummyDexHelper(network);
33
+ const logger = dexHelper.getLogger(dexKey);
34
+ const idleDao: IdleDao = new IdleDao(network, dexKey, dexHelper);
35
+
36
+ beforeAll(async () => {
37
+ latestBlockNumber = await dexHelper.web3Provider.eth.getBlockNumber();
38
+ await idleDao.initializePricing(latestBlockNumber);
39
+ tokensList = await idleDao.getTokensList(latestBlockNumber);
40
+ });
41
+
42
+ // poolAddress -> EventMappings
43
+ const eventsToTest: Record<
44
+ Address,
45
+ { blockNumber: number; events: EventMappings }
46
+ > = {
47
+ // BB_dUSDCV3
48
+ '0x2a84a042db06222c486bcb815e961f26599d0df6': {
49
+ blockNumber: 19676846,
50
+ events: {
51
+ Transfer: [
52
+ 19676846, // DepositAA
53
+ 19676851, // DepositBB
54
+ 19681374, // Harvest
55
+ 19681547, // WithdrawBB
56
+ 20031918, // Harvest
57
+ 20036646,
58
+ ],
59
+ },
60
+ },
61
+ // BB_clearpool_fasanara_USDT
62
+ '0x3eb6318b8d9f362a0e1d99f6032edb1c4c602500': {
63
+ blockNumber: 18341913,
64
+ events: {
65
+ Transfer: [
66
+ 18341913, // DepositBB
67
+ 18357425, // WithdrawBB
68
+ 18646128, // DepositBB
69
+ 18804244, // WithdrawAA
70
+ 18908679, // Harvest
71
+ 20036646,
72
+ ],
73
+ },
74
+ },
75
+ '0x7b713b1cb6eafd4061064581579ffccf7df21545': {
76
+ blockNumber: 18985108,
77
+ events: {
78
+ Transfer: [
79
+ 18985108, // DepositBB
80
+ 18997082, // WithdrawBB
81
+ 19013537, // Harvest
82
+ 19346397, // DepositAA
83
+ 20036646,
84
+ ],
85
+ },
86
+ },
87
+ };
88
+
89
+ Object.entries(eventsToTest).forEach(
90
+ ([poolAddress, { blockNumber, events }]: [
91
+ string,
92
+ { blockNumber: number; events: EventMappings },
93
+ ]) => {
94
+ describe(`Events for ${poolAddress}`, () => {
95
+ let idleDaoPool: IdleDaoEventPool | null;
96
+
97
+ it(`idleDaoPool for ${network} - ${poolAddress} - ${blockNumber}`, async function () {
98
+ idleDaoPool = await idleDao.setupEventPool(
99
+ tokensList[poolAddress],
100
+ blockNumber,
101
+ );
102
+
103
+ expect(idleDaoPool).not.toBeNull();
104
+ });
105
+
106
+ Object.entries(events).forEach(
107
+ ([eventName, blockNumbers]: [string, number[]]) => {
108
+ describe(`${eventName}`, () => {
109
+ blockNumbers.forEach((blockNumber: number) => {
110
+ it(`State after ${blockNumber}`, async function () {
111
+ await testEventSubscriber(
112
+ idleDaoPool!,
113
+ idleDaoPool!.addressesSubscribed,
114
+ (_blockNumber: number) =>
115
+ fetchPoolState(
116
+ idleDaoPool!,
117
+ _blockNumber,
118
+ poolAddress,
119
+ logger,
120
+ ),
121
+ blockNumber,
122
+ `${dexKey}_${poolAddress}`,
123
+ dexHelper.provider,
124
+ );
125
+ });
126
+ });
127
+ });
128
+ },
129
+ );
130
+ });
131
+ },
132
+ );
133
+ });
@@ -0,0 +1,166 @@
1
+ import dotenv from 'dotenv';
2
+ dotenv.config();
3
+
4
+ import { DummyDexHelper } from '../../dex-helper/index';
5
+ import { Network, SwapSide } from '../../constants';
6
+ import { IdleDao } from './idle-dao';
7
+ import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils';
8
+ import { Tokens } from '../../../tests/constants-e2e';
9
+ import { BI_POWS } from '../../bigint-constants';
10
+
11
+ async function testForIntegration(
12
+ network: Network,
13
+ dexKey: string,
14
+ tokenASymbol: string,
15
+ tokenBSymbol: string,
16
+ tokenAAmount: string,
17
+ tokenBAmount: string,
18
+ ) {
19
+ const TokenA = Tokens[network][tokenASymbol];
20
+ const TokenB = Tokens[network][tokenBSymbol];
21
+ const tokenAAmounts = [
22
+ 0n,
23
+ BigInt(tokenAAmount),
24
+ BigInt(tokenAAmount) * BigInt(2),
25
+ ];
26
+ const tokenBAmounts = [
27
+ 0n,
28
+ BigInt(tokenBAmount),
29
+ BigInt(tokenBAmount) * BigInt(2),
30
+ ];
31
+
32
+ describe('IdleDao', function () {
33
+ it('getPoolIdentifiers and getPricesVolume SELL', async function () {
34
+ const dexHelper = new DummyDexHelper(network);
35
+ const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber();
36
+ const idleDao = new IdleDao(network, dexKey, dexHelper);
37
+
38
+ await idleDao.initializePricing(blocknumber);
39
+
40
+ const pools = await idleDao.getPoolIdentifiers(
41
+ TokenA,
42
+ TokenB,
43
+ SwapSide.SELL,
44
+ blocknumber,
45
+ );
46
+
47
+ expect(pools.length).toBeGreaterThan(0);
48
+
49
+ const poolPrices = await idleDao.getPricesVolume(
50
+ TokenA,
51
+ TokenB,
52
+ tokenAAmounts,
53
+ SwapSide.SELL,
54
+ blocknumber,
55
+ pools,
56
+ );
57
+
58
+ expect(poolPrices).not.toBeNull();
59
+ checkPoolPrices(poolPrices!, tokenAAmounts, SwapSide.SELL, dexKey);
60
+ });
61
+
62
+ it('getPoolIdentifiers and getPricesVolume BUY', async function () {
63
+ const dexHelper = new DummyDexHelper(network);
64
+ const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber();
65
+ const idleDao = new IdleDao(network, dexKey, dexHelper);
66
+
67
+ await idleDao.initializePricing(blocknumber);
68
+
69
+ const pools = await idleDao.getPoolIdentifiers(
70
+ TokenA,
71
+ TokenB,
72
+ SwapSide.BUY,
73
+ blocknumber,
74
+ );
75
+
76
+ expect(pools.length).toBeGreaterThan(0);
77
+
78
+ const poolPrices = await idleDao.getPricesVolume(
79
+ TokenA,
80
+ TokenB,
81
+ tokenBAmounts,
82
+ SwapSide.BUY,
83
+ blocknumber,
84
+ pools,
85
+ );
86
+
87
+ expect(poolPrices).not.toBeNull();
88
+ checkPoolPrices(poolPrices!, tokenBAmounts, SwapSide.BUY, dexKey);
89
+ });
90
+
91
+ it('getTopPoolsForToken', async function () {
92
+ const dexHelper = new DummyDexHelper(network);
93
+ const idleDao = new IdleDao(network, dexKey, dexHelper);
94
+
95
+ const poolLiquidity = await idleDao.getTopPoolsForToken(
96
+ TokenA.address,
97
+ 10,
98
+ );
99
+
100
+ checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey);
101
+ });
102
+ });
103
+ }
104
+
105
+ describe('IdleDao E2E', () => {
106
+ const dexKey = 'IdleDao';
107
+
108
+ describe('Mainnet', () => {
109
+ const network = Network.MAINNET;
110
+ const tests = [
111
+ {
112
+ tokenASymbol: 'STETH',
113
+ tokenBSymbol: 'AA_wstETH',
114
+ tokenAAmount: '1000000000000000000',
115
+ tokenBAmount: '1000000000000000000',
116
+ },
117
+ {
118
+ tokenASymbol: 'USDC',
119
+ tokenBSymbol: 'AA_idle_cpPOR-USDC',
120
+ tokenAAmount: '1000000',
121
+ tokenBAmount: '1000000000000000000',
122
+ },
123
+ {
124
+ tokenASymbol: 'USDT',
125
+ tokenBSymbol: 'BB_idle_cpFAS-USDT',
126
+ tokenAAmount: '1000000',
127
+ tokenBAmount: '1000000000000000000',
128
+ },
129
+ {
130
+ tokenASymbol: 'WETH',
131
+ tokenBSymbol: 'BB_Re7WETH',
132
+ tokenAAmount: '100000000000000',
133
+ tokenBAmount: '100000000000000',
134
+ },
135
+ {
136
+ tokenASymbol: 'WETH',
137
+ tokenBSymbol: 'AA_Re7WETH',
138
+ tokenAAmount: '1000000000000000',
139
+ tokenBAmount: '1000000000000000',
140
+ },
141
+ {
142
+ tokenASymbol: 'STETH',
143
+ tokenBSymbol: 'AA_iETHv2',
144
+ tokenAAmount: '1000000000000000',
145
+ tokenBAmount: '1000000000000000',
146
+ },
147
+ {
148
+ tokenASymbol: 'STETH',
149
+ tokenBSymbol: 'BB_iETHv2',
150
+ tokenAAmount: '1000000000000000',
151
+ tokenBAmount: '1000000000000000',
152
+ },
153
+ ];
154
+
155
+ tests.forEach(testData => {
156
+ testForIntegration(
157
+ network,
158
+ dexKey,
159
+ testData.tokenASymbol,
160
+ testData.tokenBSymbol,
161
+ testData.tokenAAmount,
162
+ testData.tokenBAmount,
163
+ );
164
+ });
165
+ });
166
+ });
@@ -0,0 +1,304 @@
1
+ import { AbiItem } from 'web3-utils';
2
+ import BigNumber from 'bignumber.js';
3
+ import { Contract } from 'web3-eth-contract';
4
+ import { Interface } from '@ethersproject/abi';
5
+ import { DeepReadonly } from 'ts-essentials';
6
+ import { Log, Logger } from '../../types';
7
+ import { catchParseLogError } from '../../utils';
8
+ import ERC20_ABI from '../../abi/erc20.json';
9
+ import CDO_ABI from '../../abi/idle-dao/idle-cdo.json';
10
+ import { StatefulEventSubscriber } from '../../stateful-event-subscriber';
11
+ import { IDexHelper } from '../../dex-helper/idex-helper';
12
+ import { PoolState, IdleToken, PoolsState } from './types';
13
+ import { IdleDaoPollingPool } from './idle-dao-pooling-pool';
14
+ import { getTokensByCdoAddress } from './tokens';
15
+ import { ObjWithUpdateInfo } from '../../lib/stateful-rpc-poller/types';
16
+ import { IdleDao } from './idle-dao';
17
+
18
+ type BlocksTransfers = Record<
19
+ number,
20
+ {
21
+ underlyingAmount: BigNumber;
22
+ idleAmount: BigNumber;
23
+ processed: boolean;
24
+ }
25
+ >;
26
+
27
+ export class IdleDaoEventPool extends StatefulEventSubscriber<PoolState> {
28
+ handlers: {
29
+ [event: string]: (
30
+ event: any,
31
+ state: DeepReadonly<PoolState>,
32
+ log: Readonly<Log>,
33
+ ) => Promise<DeepReadonly<PoolState> | null>;
34
+ } = {};
35
+
36
+ logDecoder: (log: Log) => any;
37
+
38
+ cdoContract: Contract;
39
+ poolInterface: Interface;
40
+ addressesSubscribed: string[];
41
+ blocksTransfers: BlocksTransfers = {};
42
+
43
+ constructor(
44
+ readonly parentName: string,
45
+ protected network: number,
46
+ protected dexHelper: IDexHelper,
47
+ protected logger: Logger,
48
+ protected idleToken: IdleToken,
49
+ protected IdleDao: IdleDao,
50
+ ) {
51
+ // TODO: Add pool name
52
+ super(parentName, idleToken.idleSymbol, dexHelper, logger);
53
+
54
+ this.poolInterface = new Interface(ERC20_ABI);
55
+
56
+ // TODO: make logDecoder decode logs that
57
+ this.logDecoder = (log: Log) => this.poolInterface.parseLog(log);
58
+
59
+ this.addressesSubscribed = [idleToken.address.toLowerCase()];
60
+
61
+ const cdoTokens = getTokensByCdoAddress(this.idleToken.cdoAddress);
62
+ if (cdoTokens) {
63
+ cdoTokens.forEach((idleToken: IdleToken) => {
64
+ if (
65
+ !this.addressesSubscribed.includes(
66
+ idleToken.idleAddress.toLowerCase(),
67
+ )
68
+ ) {
69
+ this.addressesSubscribed.push(idleToken.idleAddress.toLowerCase());
70
+ }
71
+ });
72
+ }
73
+
74
+ // this.logger.debug('addressesSubscribed', this.idleToken.idleAddress, this.addressesSubscribed)
75
+
76
+ // Add handlers
77
+ this.handlers['Transfer'] = this.handleCoinTransfer.bind(this);
78
+
79
+ this.idleToken = idleToken;
80
+ this.cdoContract = new dexHelper.web3Provider.eth.Contract(
81
+ CDO_ABI as AbiItem[],
82
+ this.idleToken.cdoAddress,
83
+ );
84
+ }
85
+
86
+ /**
87
+ * The function is called every time any of the subscribed
88
+ * addresses release log. The function accepts the current
89
+ * state, updates the state according to the log, and returns
90
+ * the updated state.
91
+ * @param state - Current state of event subscriber
92
+ * @param log - Log released by one of the subscribed addresses
93
+ * @returns Updates state of the event subscriber after the log
94
+ */
95
+ protected async processLog(
96
+ state: DeepReadonly<PoolState>,
97
+ log: Readonly<Log>,
98
+ ): Promise<DeepReadonly<PoolState> | null> {
99
+ try {
100
+ const event = this.logDecoder(log);
101
+ if (event.name in this.handlers) {
102
+ const result = await this.handlers[event.name](event, state, log);
103
+ return result;
104
+ }
105
+ } catch (e) {
106
+ catchParseLogError(e, this.logger);
107
+ }
108
+
109
+ return null;
110
+ }
111
+
112
+ /**
113
+ * The function generates state using on-chain calls. This
114
+ * function is called to regenerate state if the event based
115
+ * system fails to fetch events and the local state is no
116
+ * more correct.
117
+ * @param blockNumber - Blocknumber for which the state should
118
+ * should be generated
119
+ * @returns state of the event subscriber at blocknumber
120
+ */
121
+ async generateState(blockNumber: number): Promise<DeepReadonly<PoolState>> {
122
+ const tranchePrice = await this.cdoContract.methods['virtualPrice'](
123
+ this.idleToken.idleAddress,
124
+ ).call({}, blockNumber);
125
+ return {
126
+ tokenPrice: BigInt(tranchePrice),
127
+ };
128
+ }
129
+
130
+ setBlockState(blockNumber: number, state: PoolState): void {
131
+ this.logger.debug(
132
+ 'setBlockState',
133
+ blockNumber,
134
+ this.idleToken.idleAddress,
135
+ state,
136
+ );
137
+ return this._setState(state, blockNumber);
138
+ }
139
+
140
+ async handleCoinTransfer(
141
+ event: any,
142
+ state: PoolState,
143
+ log: Log,
144
+ ): Promise<DeepReadonly<PoolState> | null> {
145
+ const idleTokens = getTokensByCdoAddress(this.idleToken.cdoAddress);
146
+ if (!idleTokens) return null;
147
+
148
+ const pollingPool = new IdleDaoPollingPool(
149
+ this.parentName,
150
+ this.parentName,
151
+ this.dexHelper,
152
+ idleTokens,
153
+ this.logger,
154
+ );
155
+
156
+ const blockNumber = log.blockNumber;
157
+ let poolsState: ObjWithUpdateInfo<PoolsState> | null = null;
158
+
159
+ if (log.address.toLowerCase() === this.idleToken.address.toLowerCase()) {
160
+ if (
161
+ event.args.dst.toLowerCase() ===
162
+ this.idleToken.cdoAddress.toLowerCase() ||
163
+ event.args.src.toLowerCase() === this.idleToken.cdoAddress.toLowerCase()
164
+ ) {
165
+ poolsState = await pollingPool.getAggregatedBlockData(blockNumber);
166
+ }
167
+ } else if (this.addressesSubscribed.includes(log.address.toLowerCase())) {
168
+ poolsState = await pollingPool.getAggregatedBlockData(blockNumber);
169
+ }
170
+
171
+ // Update pools with the new state
172
+ if (poolsState) {
173
+ Object.keys(poolsState.value as PoolsState).forEach(
174
+ (idleAddress: string) => {
175
+ const poolState = poolsState?.value?.[idleAddress];
176
+ if (poolState) {
177
+ this.IdleDao.setEventPoolStateBlock(
178
+ idleAddress,
179
+ poolsState!.blockNumber,
180
+ poolState,
181
+ );
182
+
183
+ // Overwrite state
184
+ if (idleAddress === this.idleToken.idleAddress) {
185
+ state = poolState;
186
+ }
187
+ }
188
+ },
189
+ );
190
+ }
191
+
192
+ return state;
193
+ }
194
+
195
+ processBlockTransfer(blockNumber: number, state: PoolState): PoolState {
196
+ if (
197
+ !this.blocksTransfers[blockNumber] ||
198
+ this.blocksTransfers[blockNumber].processed
199
+ )
200
+ return state;
201
+ const idleAmount = this.blocksTransfers[blockNumber].idleAmount.div(1e18);
202
+ const underlyingAmount = this.blocksTransfers[
203
+ blockNumber
204
+ ].underlyingAmount.div(`1e${this.idleToken.decimals}`);
205
+ if (idleAmount.gt(0) && underlyingAmount.gt(0)) {
206
+ const tokenPrice = BigInt(
207
+ BigNumber.maximum(idleAmount, underlyingAmount)
208
+ .div(BigNumber.minimum(idleAmount, underlyingAmount))
209
+ .times(`1e${this.idleToken.decimals}`)
210
+ .toFixed(0),
211
+ );
212
+ this.logger.debug(
213
+ 'tokenPrice',
214
+ blockNumber,
215
+ this.idleToken.idleSymbol,
216
+ this.idleToken.decimals,
217
+ idleAmount.toString(),
218
+ underlyingAmount.toString(),
219
+ tokenPrice.toString(),
220
+ );
221
+ this.blocksTransfers[blockNumber].processed = true;
222
+ return {
223
+ tokenPrice,
224
+ };
225
+ }
226
+ return state;
227
+ }
228
+
229
+ async handleCoinTransfer_old(
230
+ event: any,
231
+ state: PoolState,
232
+ log: Log,
233
+ ): Promise<DeepReadonly<PoolState> | null> {
234
+ // Handle underlying token transfer
235
+ if (log.address.toLowerCase() === this.idleToken.address.toLowerCase()) {
236
+ if (
237
+ event.args.dst.toLowerCase() ===
238
+ this.idleToken.cdoAddress.toLowerCase() ||
239
+ event.args.src.toLowerCase() === this.idleToken.cdoAddress.toLowerCase()
240
+ ) {
241
+ if (!this.blocksTransfers[log.blockNumber]) {
242
+ this.blocksTransfers[log.blockNumber] = {
243
+ processed: false,
244
+ idleAmount: BigNumber(0),
245
+ underlyingAmount: BigNumber(0),
246
+ };
247
+ }
248
+ this.logger.debug(
249
+ 'UnderlyingAmount',
250
+ log.blockNumber,
251
+ 'event',
252
+ event,
253
+ 'log',
254
+ log,
255
+ BigNumber(BigInt(event.args.wad).toString()).toFixed(),
256
+ );
257
+ this.blocksTransfers[log.blockNumber].underlyingAmount = BigNumber(
258
+ BigInt(event.args.wad).toString(),
259
+ );
260
+ }
261
+ }
262
+ // Handle idle token transfer
263
+ else if (
264
+ log.address.toLowerCase() === this.idleToken.idleAddress.toLowerCase()
265
+ ) {
266
+ this.logger.debug(
267
+ 'IdleToken Transfer',
268
+ log.blockNumber,
269
+ 'event',
270
+ event,
271
+ 'log',
272
+ log,
273
+ );
274
+ if (
275
+ event.args.src.toLowerCase() ===
276
+ '0x0000000000000000000000000000000000000000' ||
277
+ event.args.dst.toLowerCase() ===
278
+ '0x0000000000000000000000000000000000000000'
279
+ ) {
280
+ if (!this.blocksTransfers[log.blockNumber]) {
281
+ this.blocksTransfers[log.blockNumber] = {
282
+ processed: false,
283
+ idleAmount: BigNumber(0),
284
+ underlyingAmount: BigNumber(0),
285
+ };
286
+ }
287
+ this.logger.debug(
288
+ 'IdleAmount',
289
+ log.blockNumber,
290
+ 'event',
291
+ event,
292
+ 'log',
293
+ log,
294
+ BigNumber(BigInt(event.args.wad).toString()).toFixed(),
295
+ );
296
+ this.blocksTransfers[log.blockNumber].idleAmount = BigNumber(
297
+ BigInt(event.args.wad).toString(),
298
+ );
299
+ }
300
+ }
301
+
302
+ return this.processBlockTransfer(log.blockNumber, state);
303
+ }
304
+ }