@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,87 @@
1
+ import { Interface } from '@ethersproject/abi';
2
+ import { uint256ToBigInt } from '../../lib/decoders';
3
+ import CDO_ABI from '../../abi/idle-dao/idle-cdo.json';
4
+ import { IDexHelper } from '../../dex-helper/idex-helper';
5
+ import { PoolState, IdleToken, PoolsState } from './types';
6
+ import { MultiCallParams, MultiResult } from '../../lib/multi-wrapper';
7
+ import { pollingManagerCbExtractor } from '../../lib/stateful-rpc-poller/utils';
8
+ import { StatefulRpcPoller } from '../../lib/stateful-rpc-poller/stateful-rpc-poller';
9
+ import { StatePollingManager } from '../../lib/stateful-rpc-poller/state-polling-manager';
10
+ import { Logger } from '../../types';
11
+ import { ObjWithUpdateInfo } from '../../lib/stateful-rpc-poller/types';
12
+
13
+ type MulticallResultOutputs = bigint;
14
+
15
+ export class IdleDaoPollingPool extends StatefulRpcPoller<
16
+ PoolsState,
17
+ MulticallResultOutputs
18
+ > {
19
+ constructor(
20
+ dexKey: string,
21
+ poolIdentifier: string,
22
+ dexHelper: IDexHelper,
23
+ protected idleTokens: IdleToken[],
24
+ protected logger: Logger,
25
+ ) {
26
+ const callbacks = pollingManagerCbExtractor(
27
+ StatePollingManager.getInstance(dexHelper),
28
+ );
29
+
30
+ super(dexKey, poolIdentifier, dexHelper, 0, 0, false, callbacks);
31
+ }
32
+
33
+ async getAggregatedBlockData(
34
+ blockNumber: number,
35
+ ): Promise<ObjWithUpdateInfo<PoolsState> | null> {
36
+ const multiCalls = this.getFetchStateWithBlockInfoMultiCalls();
37
+ try {
38
+ const lastUpdatedAtMs = Date.now();
39
+ const aggregatedResults = (await this.dexHelper.multiWrapper.tryAggregate<
40
+ number | MulticallResultOutputs
41
+ >(
42
+ true,
43
+ multiCalls as MultiCallParams<MulticallResultOutputs | number>[],
44
+ blockNumber,
45
+ )) as [MultiResult<number>, ...MultiResult<MulticallResultOutputs>[]];
46
+
47
+ return this.parseStateFromMultiResultsWithBlockInfo(
48
+ aggregatedResults,
49
+ lastUpdatedAtMs,
50
+ );
51
+ } catch (e) {
52
+ // this.logger.debug('ERROR fetching multicall data', blockNumber, e)
53
+ }
54
+
55
+ return null;
56
+ }
57
+
58
+ protected _getFetchStateMultiCalls(): MultiCallParams<MulticallResultOutputs>[] {
59
+ const cdoInterface = new Interface(CDO_ABI);
60
+ return this.idleTokens.map(idleToken => ({
61
+ target: idleToken.cdoAddress,
62
+ callData: cdoInterface.encodeFunctionData('virtualPrice', [
63
+ idleToken.idleAddress,
64
+ ]),
65
+ decodeFunction: uint256ToBigInt,
66
+ })) as MultiCallParams<MulticallResultOutputs>[];
67
+ }
68
+
69
+ protected _parseStateFromMultiResults(
70
+ multiOutputs: MulticallResultOutputs[],
71
+ ): PoolsState {
72
+ const output: PoolsState = multiOutputs.reduce(
73
+ (acc: PoolsState, output: MulticallResultOutputs, index: number) => {
74
+ const tokenPrice = output as bigint;
75
+ const idleToken = this.idleTokens[index];
76
+ return {
77
+ ...acc,
78
+ [idleToken.idleAddress]: {
79
+ tokenPrice,
80
+ },
81
+ };
82
+ },
83
+ {},
84
+ );
85
+ return output;
86
+ }
87
+ }
@@ -0,0 +1,509 @@
1
+ import { assert } from 'ts-essentials';
2
+ import { Interface } from '@ethersproject/abi';
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, NULL_ADDRESS } from '../../constants';
16
+ import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
17
+ import { getDexKeysWithNetwork, isETHAddress, getBigIntPow } from '../../utils';
18
+ import { Context, IDex } from '../../dex/idex';
19
+ import { IDexHelper } from '../../dex-helper/idex-helper';
20
+ import {
21
+ IdleDaoData,
22
+ Param,
23
+ PoolFunctions,
24
+ IdleToken,
25
+ PoolState,
26
+ } from './types';
27
+ import { SimpleExchange } from '../simple-exchange';
28
+ import { Config, Adapters } from './config';
29
+ import { IdleDaoEventPool } from './idle-dao-pool';
30
+ import { fetchTokenList_api } from './utils';
31
+ import {
32
+ getIdleTokenIfIdleDaoPair,
33
+ setTokensOnNetwork,
34
+ getPoolsByTokenAddress,
35
+ getTokenFromIdleToken,
36
+ getTokensByNetwork,
37
+ } from './tokens';
38
+ import FACTORY_ABI from '../../abi/idle-dao/idle-cdo-factory.json';
39
+ import CDO_ABI from '../../abi/idle-dao/idle-cdo.json';
40
+ import { IdleDaoPollingPool } from './idle-dao-pooling-pool';
41
+ import { ObjWithUpdateInfo } from '../../lib/stateful-rpc-poller/types';
42
+ import { StatePollingManager } from '../../lib/stateful-rpc-poller/state-polling-manager';
43
+
44
+ export const TOKEN_LIST_CACHE_KEY = 'token-list';
45
+ const TOKEN_LIST_TTL_SECONDS = 24 * 60 * 60;
46
+ const TOKEN_LIST_LOCAL_TTL_SECONDS = 3 * 60 * 60;
47
+
48
+ export class IdleDao extends SimpleExchange implements IDex<IdleDaoData> {
49
+ protected eventPools: Record<string, IdleDaoEventPool> = {};
50
+
51
+ readonly hasConstantPriceLargeAmounts = false;
52
+ // TODO: set true here if protocols works only with wrapped asset
53
+ readonly needWrapNative = true;
54
+
55
+ readonly isFeeOnTransferSupported = false;
56
+
57
+ public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
58
+ getDexKeysWithNetwork(Config);
59
+
60
+ logger: Logger;
61
+
62
+ private cdo: Interface;
63
+ private factory: Interface;
64
+
65
+ private tokenList: IdleToken[] = [];
66
+ private idleDaoAuthToken: string;
67
+
68
+ protected pollingPool?: IdleDaoPollingPool;
69
+
70
+ protected pollingManager: StatePollingManager;
71
+
72
+ constructor(
73
+ readonly network: Network,
74
+ readonly dexKey: string,
75
+ readonly dexHelper: IDexHelper,
76
+ protected config = Config[dexKey][network],
77
+ protected adapters = Adapters[network] || {}, // TODO: add any additional optional params to support other fork DEXes
78
+ ) {
79
+ super(dexHelper, dexKey);
80
+ this.logger = dexHelper.getLogger(dexKey);
81
+ this.cdo = new Interface(CDO_ABI);
82
+ this.factory = new Interface(FACTORY_ABI);
83
+ this.pollingManager = StatePollingManager.getInstance(dexHelper);
84
+
85
+ const idleDaoAuthToken = dexHelper.config.data.idleDaoAuthToken;
86
+ assert(
87
+ idleDaoAuthToken !== undefined,
88
+ 'idleDaoAuthToken auth token is not specified with env variable',
89
+ );
90
+
91
+ this.idleDaoAuthToken = idleDaoAuthToken;
92
+ }
93
+
94
+ getEventPool(idleAddress: string): IdleDaoEventPool | null {
95
+ return this.eventPools[idleAddress] || null;
96
+ }
97
+
98
+ setEventPoolStateBlock(
99
+ idleAddress: string,
100
+ blockNumber: number,
101
+ state: PoolState,
102
+ ): void {
103
+ const eventPool = this.getEventPool(idleAddress);
104
+ if (!eventPool) return;
105
+ return eventPool.setBlockState(blockNumber, state);
106
+ }
107
+
108
+ async setupEventPool(
109
+ idleToken: IdleToken,
110
+ blockNumber: number,
111
+ ): Promise<IdleDaoEventPool> {
112
+ const idleDaoEventPool = new IdleDaoEventPool(
113
+ this.dexKey,
114
+ this.network,
115
+ this.dexHelper,
116
+ this.logger,
117
+ idleToken,
118
+ this,
119
+ );
120
+ await idleDaoEventPool.initialize(blockNumber);
121
+ this.eventPools[idleToken.idleAddress] = idleDaoEventPool;
122
+ return idleDaoEventPool;
123
+ }
124
+
125
+ async getTokensList(blockNumber: number): Promise<Record<string, IdleToken>> {
126
+ if (!this.tokenList) {
127
+ this.tokenList = await fetchTokenList_api(
128
+ this.network,
129
+ this.dexHelper,
130
+ blockNumber,
131
+ this.cdo,
132
+ this.erc20Interface,
133
+ this.dexHelper.multiWrapper,
134
+ this.idleDaoAuthToken,
135
+ );
136
+ }
137
+
138
+ return this.tokenList.reduce(
139
+ (acc: Record<string, IdleToken>, idleToken: IdleToken) => {
140
+ return {
141
+ ...acc,
142
+ [idleToken.idleAddress]: idleToken,
143
+ };
144
+ },
145
+ {},
146
+ );
147
+ }
148
+
149
+ // Initialize pricing is called once in the start of
150
+ // pricing service. It is intended to setup the integration
151
+ // for pricing requests. It is optional for a DEX to
152
+ // implement this function
153
+ async initializePricing(blockNumber: number) {
154
+ let cachedTokenList = await this.dexHelper.cache.getAndCacheLocally(
155
+ this.dexKey,
156
+ this.network,
157
+ TOKEN_LIST_CACHE_KEY,
158
+ TOKEN_LIST_LOCAL_TTL_SECONDS,
159
+ );
160
+
161
+ if (cachedTokenList !== null) {
162
+ const tokens: IdleToken[] = JSON.parse(cachedTokenList);
163
+ setTokensOnNetwork(this.network, tokens);
164
+
165
+ await Promise.all(
166
+ tokens.map((idleToken: IdleToken) =>
167
+ this.setupEventPool(idleToken, blockNumber),
168
+ ),
169
+ );
170
+
171
+ this.tokenList = tokens;
172
+
173
+ return;
174
+ }
175
+
176
+ this.tokenList = await fetchTokenList_api(
177
+ this.network,
178
+ this.dexHelper,
179
+ blockNumber,
180
+ this.cdo,
181
+ this.erc20Interface,
182
+ this.dexHelper.multiWrapper,
183
+ this.idleDaoAuthToken,
184
+ );
185
+
186
+ // console.log('api_tokenList', this.tokenList);
187
+
188
+ await this.dexHelper.cache.setex(
189
+ this.dexKey,
190
+ this.network,
191
+ TOKEN_LIST_CACHE_KEY,
192
+ TOKEN_LIST_TTL_SECONDS,
193
+ JSON.stringify(this.tokenList),
194
+ );
195
+
196
+ setTokensOnNetwork(this.network, this.tokenList);
197
+
198
+ await Promise.all(
199
+ this.tokenList.map((idleToken: IdleToken) =>
200
+ this.setupEventPool(idleToken, blockNumber),
201
+ ),
202
+ );
203
+
204
+ // Initialize polling pool
205
+ if (this.pollingPool === undefined) {
206
+ this._initializePollingPool(this.tokenList);
207
+ }
208
+ }
209
+
210
+ // Returns the list of contract adapters (name and index)
211
+ // for a buy/sell. Return null if there are no adapters.
212
+ getAdapters(side: SwapSide): { name: string; index: number }[] | null {
213
+ return this.adapters[side] ? this.adapters[side] : null;
214
+ }
215
+
216
+ getIdentifier() {
217
+ return `${this.dexKey}_idledaov1`;
218
+ }
219
+
220
+ private _initializePollingPool(idleTokens: IdleToken[]) {
221
+ this.pollingPool = new IdleDaoPollingPool(
222
+ this.dexKey,
223
+ this.getIdentifier(),
224
+ this.dexHelper,
225
+ idleTokens,
226
+ this.logger,
227
+ );
228
+
229
+ this.pollingManager.initializeAllPendingPools();
230
+ }
231
+
232
+ private _getPoolIdentifier(srcToken: Token, destToken: Token): string {
233
+ return (
234
+ this.dexKey +
235
+ [srcToken.address.toLowerCase(), destToken.address.toLowerCase()]
236
+ .sort((a, b) => (a > b ? 1 : -1))
237
+ .join('_')
238
+ );
239
+ }
240
+
241
+ // Returns list of pool identifiers that can be used
242
+ // for a given swap. poolIdentifiers must be unique
243
+ // across DEXes. It is recommended to use
244
+ // ${dexKey}_${poolAddress} as a poolIdentifier
245
+ async getPoolIdentifiers(
246
+ srcToken: Token,
247
+ destToken: Token,
248
+ side: SwapSide,
249
+ blockNumber: number,
250
+ ): Promise<string[]> {
251
+ const idleToken = getIdleTokenIfIdleDaoPair(
252
+ this.network,
253
+ this.dexHelper.config.wrapETH(srcToken),
254
+ this.dexHelper.config.wrapETH(destToken),
255
+ );
256
+
257
+ if (idleToken === null) return [];
258
+
259
+ return [this._getPoolIdentifier(srcToken, destToken)];
260
+ }
261
+
262
+ // Returns pool prices for amounts.
263
+ // If limitPools is defined only pools in limitPools
264
+ // should be used. If limitPools is undefined then
265
+ // any pools can be used.
266
+
267
+ async getPricesVolume(
268
+ srcToken: Token,
269
+ destToken: Token,
270
+ amounts: bigint[],
271
+ side: SwapSide,
272
+ blockNumber: number,
273
+ limitPools?: string[],
274
+ ): Promise<null | ExchangePrices<IdleDaoData>> {
275
+ try {
276
+ const _src = this.dexHelper.config.wrapETH(srcToken);
277
+ const _dst = this.dexHelper.config.wrapETH(destToken);
278
+
279
+ // Look for idleToken
280
+ const idleToken = getIdleTokenIfIdleDaoPair(this.network, _src, _dst);
281
+ if (!idleToken) {
282
+ // console.log(
283
+ // 'IdleToken NOT FOUND -',
284
+ // blockNumber,
285
+ // this.network,
286
+ // _src,
287
+ // _dst,
288
+ // );
289
+ return null;
290
+ }
291
+
292
+ const fromIdleToken =
293
+ idleToken.idleAddress.toLowerCase() == _src.address.toLowerCase();
294
+
295
+ // Cannot buy with IdleTokens
296
+ // if (fromIdleToken && side === SwapSide.BUY) return null
297
+
298
+ const eventPool: IdleDaoEventPool =
299
+ this.eventPools[idleToken.idleAddress];
300
+ const eventPoolState: PoolState | null = eventPool.getState(blockNumber);
301
+
302
+ // this.logger.debug(
303
+ // 'eventPoolState',
304
+ // blockNumber,
305
+ // idleToken.idleAddress,
306
+ // eventPoolState,
307
+ // );
308
+
309
+ if (!eventPoolState) {
310
+ // console.log('eventPoolState is NULL -', blockNumber, idleToken.idleAddress, eventPoolState)
311
+ return null;
312
+ }
313
+
314
+ const tokenPrice = eventPoolState.tokenPrice;
315
+
316
+ const unitVolume = getBigIntPow(
317
+ (side === SwapSide.SELL ? srcToken : destToken).decimals,
318
+ );
319
+
320
+ const prices = [unitVolume, ...amounts].map((amount: bigint) => {
321
+ let output = 0;
322
+ if (side === SwapSide.SELL) {
323
+ // SELL idleToken (amount = 1000000000000000000 AA_idle_cpPOR-USDC, output = 1000000000000000000*tokenPrice/1e18)
324
+ if (fromIdleToken) {
325
+ output = Math.round(
326
+ (parseFloat('' + tokenPrice) * parseFloat('' + amount)) /
327
+ parseFloat(`1e${idleToken.decimals}`),
328
+ );
329
+ // SELL underlyingToken (amount = 1000000 USDC), output = 1000000/tokenPrice*1e18
330
+ } else {
331
+ output = Math.round(
332
+ (parseFloat('' + amount) / parseFloat('' + tokenPrice)) *
333
+ parseFloat(`1e${idleToken.decimals}`),
334
+ );
335
+ }
336
+ } else {
337
+ // BUY idleToken (amount = 1000000 USDC, output = 1000000/tokenPrice*1e18)
338
+ if (fromIdleToken) {
339
+ output = Math.round(
340
+ (parseFloat('' + amount) / parseFloat('' + tokenPrice)) *
341
+ parseFloat(`1e${idleToken.decimals}`),
342
+ );
343
+ // BUY underlyingToken (amount = 1000000000000000000 AA_idle_cpPOR-USDC, output = 1000000000000000000*tokenPrice/1e18)
344
+ } else {
345
+ output = Math.round(
346
+ (parseFloat('' + tokenPrice) * parseFloat('' + amount)) /
347
+ parseFloat(`1e${idleToken.decimals}`),
348
+ );
349
+ }
350
+ }
351
+ return BigInt(output);
352
+ });
353
+
354
+ // console.log('getPricesVolume', srcToken.address, destToken.address, fromIdleToken, side, unitVolume, amounts, prices)
355
+
356
+ // const unit = side === SwapSide.SELL ? prices[0] : unitVolume;
357
+
358
+ return [
359
+ {
360
+ unit: prices[0],
361
+ prices: prices.slice(1),
362
+ gasCost: this.config.lendingGasCost,
363
+ exchange: this.dexKey,
364
+ data: {
365
+ idleToken,
366
+ fromIdleToken,
367
+ },
368
+ poolAddresses: [fromIdleToken ? srcToken.address : destToken.address],
369
+ },
370
+ ];
371
+ } catch (e) {
372
+ if (blockNumber === 0)
373
+ this.logger.error(
374
+ `Error_getPricesVolume: Aurelius block manager not yet instantiated`,
375
+ );
376
+ this.logger.error(`Error_getPrices:`, e);
377
+ return null;
378
+ }
379
+ }
380
+
381
+ // Returns estimated gas cost of calldata for this DEX in multiSwap
382
+ getCalldataGasCost(poolPrices: PoolPrices<IdleDaoData>): number | number[] {
383
+ // TODO: update if there is any payload in getAdapterParam
384
+ return CALLDATA_GAS_COST.DEX_NO_PAYLOAD;
385
+ }
386
+
387
+ // Encode params required by the exchange adapter
388
+ // Used for multiSwap, buy & megaSwap
389
+ // Hint: abiCoder.encodeParameter() could be useful
390
+ getAdapterParam(
391
+ srcToken: string,
392
+ destToken: string,
393
+ srcAmount: string,
394
+ destAmount: string,
395
+ data: IdleDaoData,
396
+ side: SwapSide,
397
+ ): AdapterExchangeParam {
398
+ const idleToken = data.fromIdleToken ? srcToken : destToken; // Warning
399
+ const payload = this.abiCoder.encodeParameter(
400
+ {
401
+ ParentStruct: {
402
+ idleToken: 'address',
403
+ },
404
+ },
405
+ { idleToken },
406
+ );
407
+
408
+ return {
409
+ // target exchange is not used by the contract
410
+ targetExchange: NULL_ADDRESS,
411
+ payload,
412
+ networkFee: '0',
413
+ };
414
+ }
415
+
416
+ getDexParam(
417
+ srcToken: Address,
418
+ destToken: Address,
419
+ srcAmount: NumberAsString,
420
+ destAmount: NumberAsString,
421
+ recipient: Address,
422
+ data: IdleDaoData,
423
+ side: SwapSide,
424
+ _: Context,
425
+ executorAddress: Address,
426
+ ): DexExchangeParam {
427
+ const [Interface, swapCallee, swapFunction, swapFunctionParams] = ((): [
428
+ Interface,
429
+ Address,
430
+ PoolFunctions,
431
+ Param,
432
+ ] => {
433
+ if (data.fromIdleToken) {
434
+ return [
435
+ this.cdo,
436
+ data.idleToken.cdoAddress,
437
+ PoolFunctions[`withdraw${data.idleToken.tokenType}`],
438
+ [srcAmount],
439
+ ];
440
+ }
441
+
442
+ return [
443
+ this.cdo,
444
+ data.idleToken.cdoAddress,
445
+ PoolFunctions[`deposit${data.idleToken.tokenType}`],
446
+ [srcAmount, recipient],
447
+ ];
448
+ })();
449
+
450
+ const exchangeData = Interface.encodeFunctionData(
451
+ swapFunction,
452
+ swapFunctionParams,
453
+ );
454
+
455
+ return {
456
+ needWrapNative: this.needWrapNative,
457
+ dexFuncHasRecipient: false,
458
+ exchangeData,
459
+ targetExchange: swapCallee,
460
+ returnAmountPos: undefined,
461
+ };
462
+ }
463
+
464
+ async updatePoolState(): Promise<void> {
465
+ const blockNumber = await this.dexHelper.web3Provider.eth.getBlockNumber();
466
+
467
+ let idleTokens = getTokensByNetwork(this.network);
468
+ if (!idleTokens) {
469
+ await this.initializePricing(blockNumber);
470
+ }
471
+ idleTokens = getTokensByNetwork(this.network);
472
+
473
+ const state = await this.pollingPool!.getState();
474
+
475
+ // this.logger.debug('updatePoolState', blockNumber, state)
476
+
477
+ if (!state) {
478
+ this.logger.error(`Failed to updatePoolState. State is null.`);
479
+ return;
480
+ }
481
+
482
+ Object.entries(state).forEach((state: any) => {
483
+ const idleAddress = state[0];
484
+ const poolState: ObjWithUpdateInfo<PoolState> = state[1];
485
+ const eventPool: IdleDaoEventPool = this.eventPools[idleAddress];
486
+ // this.logger.debug('Get eventPool', state, idleAddress, eventPool)
487
+ if (eventPool) {
488
+ // this.logger.debug('Set pool state', idleAddress, poolState.blockNumber, poolState.value)
489
+ eventPool.setBlockState(poolState.blockNumber, poolState.value);
490
+ }
491
+ });
492
+ }
493
+
494
+ async getTopPoolsForToken(
495
+ tokenAddress: Address,
496
+ limit: number,
497
+ ): Promise<PoolLiquidity[]> {
498
+ const idleTokens: IdleToken[] = getPoolsByTokenAddress(tokenAddress);
499
+
500
+ return idleTokens
501
+ .map((idleToken: IdleToken, i) => ({
502
+ liquidityUSD: 0,
503
+ exchange: this.dexKey,
504
+ address: idleToken.idleAddress,
505
+ connectorTokens: [getTokenFromIdleToken(idleToken)],
506
+ }))
507
+ .slice(0, limit);
508
+ }
509
+ }
@@ -0,0 +1,117 @@
1
+ import { Token } from '../../types';
2
+ import { Network } from '../../constants';
3
+
4
+ import { IdleToken } from './types';
5
+
6
+ export const Tokens: { [network: number]: { [symbol: string]: IdleToken } } =
7
+ {};
8
+
9
+ const poolsByTokenAddress: { [address: string]: IdleToken[] } = {};
10
+
11
+ const TokensByAddress: { [network: number]: { [address: string]: IdleToken } } =
12
+ {};
13
+
14
+ const TokensByCDO: { [address: string]: IdleToken[] } = {};
15
+
16
+ export const getPoolsByTokenAddress = (address: string): IdleToken[] => {
17
+ return poolsByTokenAddress[address] || [];
18
+ };
19
+
20
+ // return null if the pair does not exists otherwise return the idleToken
21
+ export function getIdleTokenIfIdleDaoPair(
22
+ network: number,
23
+ src: Token,
24
+ dst: Token,
25
+ ): IdleToken | null {
26
+ const srcAddr = src.address.toLowerCase();
27
+ const dstAddr = dst.address.toLowerCase();
28
+
29
+ if (srcAddr === dstAddr) {
30
+ return null;
31
+ }
32
+
33
+ const _src = TokensByAddress[network][srcAddr];
34
+ const _dst = TokensByAddress[network][dstAddr];
35
+
36
+ if (_src && _src.address.toLowerCase() == dstAddr) {
37
+ return _src;
38
+ }
39
+
40
+ if (_dst && _dst.address.toLowerCase() == srcAddr) {
41
+ return _dst;
42
+ }
43
+
44
+ return null;
45
+ }
46
+
47
+ export function getTokenFromIdleToken(idleToken: IdleToken): Token {
48
+ return {
49
+ address: idleToken.idleAddress,
50
+ decimals: idleToken.decimals,
51
+ symbol: idleToken.idleSymbol,
52
+ };
53
+ }
54
+
55
+ export function getTokenFromIdleSymbol(
56
+ network: number,
57
+ symbol: string,
58
+ ): Token | null {
59
+ const idleToken = Tokens[network][symbol];
60
+
61
+ // console.log('idleToken', network, symbol, idleToken)
62
+
63
+ if (!idleToken) return null;
64
+
65
+ return {
66
+ address: idleToken.idleAddress,
67
+ decimals: idleToken.decimals,
68
+ symbol: idleToken.idleSymbol,
69
+ };
70
+ }
71
+
72
+ export function getIdleTokenByAddress(
73
+ network: Network,
74
+ address: string,
75
+ ): IdleToken | undefined {
76
+ return TokensByAddress[network]?.[address];
77
+ }
78
+
79
+ export function getTokensByNetwork(network: Network): IdleToken[] | undefined {
80
+ return Object.values(Tokens[network]);
81
+ }
82
+
83
+ export function getTokensByCdoAddress(
84
+ cdoAddress: string,
85
+ ): IdleToken[] | undefined {
86
+ return TokensByCDO[cdoAddress];
87
+ }
88
+
89
+ export function setTokensOnNetwork(network: Network, tokens: IdleToken[]): any {
90
+ for (let token of tokens) {
91
+ token.address = token.address.toLowerCase();
92
+ token.idleAddress = token.idleAddress.toLowerCase();
93
+
94
+ if (Tokens[network] === undefined) {
95
+ Tokens[network] = {};
96
+ }
97
+ if (TokensByAddress[network] === undefined) {
98
+ TokensByAddress[network] = {};
99
+ }
100
+
101
+ if (poolsByTokenAddress[token.address] === undefined) {
102
+ poolsByTokenAddress[token.address] = [];
103
+ }
104
+
105
+ if (TokensByCDO[token.cdoAddress] === undefined) {
106
+ TokensByCDO[token.cdoAddress] = [];
107
+ }
108
+
109
+ Tokens[network][token.idleSymbol] = token;
110
+ TokensByCDO[token.cdoAddress].push(token);
111
+ TokensByAddress[network][token.idleAddress] = token;
112
+ TokensByAddress[network][token.address] = token;
113
+ poolsByTokenAddress[token.address].push(token);
114
+ }
115
+
116
+ return TokensByAddress[network];
117
+ }