@paraswap/dex-lib 3.6.3 → 3.6.4-transmuter.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.
Files changed (188) hide show
  1. package/build/abi/Redstone.json +739 -0
  2. package/build/abi/aavev3stata/Factory.json +128 -0
  3. package/build/abi/aavev3stata/Token.json +735 -0
  4. package/build/abi/angle-transmuter/MorphoOracle.json +193 -0
  5. package/build/abi/angle-transmuter/MorphoVault.json +2506 -0
  6. package/build/abi/angle-transmuter/Pyth.json +1534 -0
  7. package/build/abi/angle-transmuter/Transmuter.json +1711 -0
  8. package/build/abi/angle-transmuter/TransmuterSidechain.json +1798 -0
  9. package/build/abi/idle-dao/idle-cdo-factory.json +38 -0
  10. package/build/abi/idle-dao/idle-cdo.json +1245 -0
  11. package/build/dex/aave-v1/aave-v1.d.ts +2 -1
  12. package/build/dex/aave-v1/aave-v1.js +22 -0
  13. package/build/dex/aave-v1/aave-v1.js.map +1 -1
  14. package/build/dex/aave-v3-stata/aave-v3-stata.d.ts +40 -0
  15. package/build/dex/aave-v3-stata/aave-v3-stata.js +309 -0
  16. package/build/dex/aave-v3-stata/aave-v3-stata.js.map +1 -0
  17. package/build/dex/aave-v3-stata/config.d.ts +4 -0
  18. package/build/dex/aave-v3-stata/config.js +46 -0
  19. package/build/dex/aave-v3-stata/config.js.map +1 -0
  20. package/build/dex/aave-v3-stata/tokens.d.ts +9 -0
  21. package/build/dex/aave-v3-stata/tokens.js +37 -0
  22. package/build/dex/aave-v3-stata/tokens.js.map +1 -0
  23. package/build/dex/aave-v3-stata/types.d.ts +42 -0
  24. package/build/dex/aave-v3-stata/types.js +18 -0
  25. package/build/dex/aave-v3-stata/types.js.map +1 -0
  26. package/build/dex/aave-v3-stata/utils.d.ts +4 -0
  27. package/build/dex/aave-v3-stata/utils.js +67 -0
  28. package/build/dex/aave-v3-stata/utils.js.map +1 -0
  29. package/build/dex/angle-transmuter/angle-transmuter-pool.d.ts +61 -0
  30. package/build/dex/angle-transmuter/angle-transmuter-pool.js +419 -0
  31. package/build/dex/angle-transmuter/angle-transmuter-pool.js.map +1 -0
  32. package/build/dex/angle-transmuter/angle-transmuter.d.ts +60 -0
  33. package/build/dex/angle-transmuter/angle-transmuter.js +282 -0
  34. package/build/dex/angle-transmuter/angle-transmuter.js.map +1 -0
  35. package/build/dex/angle-transmuter/backedOracle.d.ts +19 -0
  36. package/build/dex/angle-transmuter/backedOracle.js +56 -0
  37. package/build/dex/angle-transmuter/backedOracle.js.map +1 -0
  38. package/build/dex/angle-transmuter/config.d.ts +4 -0
  39. package/build/dex/angle-transmuter/config.js +50 -0
  40. package/build/dex/angle-transmuter/config.js.map +1 -0
  41. package/build/dex/angle-transmuter/constants.d.ts +9 -0
  42. package/build/dex/angle-transmuter/constants.js +136 -0
  43. package/build/dex/angle-transmuter/constants.js.map +1 -0
  44. package/build/dex/angle-transmuter/morphoOracle.d.ts +42 -0
  45. package/build/dex/angle-transmuter/morphoOracle.js +179 -0
  46. package/build/dex/angle-transmuter/morphoOracle.js.map +1 -0
  47. package/build/dex/angle-transmuter/morphoVault.d.ts +20 -0
  48. package/build/dex/angle-transmuter/morphoVault.js +84 -0
  49. package/build/dex/angle-transmuter/morphoVault.js.map +1 -0
  50. package/build/dex/angle-transmuter/pyth.d.ts +19 -0
  51. package/build/dex/angle-transmuter/pyth.js +70 -0
  52. package/build/dex/angle-transmuter/pyth.js.map +1 -0
  53. package/build/dex/angle-transmuter/redstone.d.ts +20 -0
  54. package/build/dex/angle-transmuter/redstone.js +73 -0
  55. package/build/dex/angle-transmuter/redstone.js.map +1 -0
  56. package/build/dex/angle-transmuter/transmuter.d.ts +55 -0
  57. package/build/dex/angle-transmuter/transmuter.js +398 -0
  58. package/build/dex/angle-transmuter/transmuter.js.map +1 -0
  59. package/build/dex/angle-transmuter/types.d.ts +189 -0
  60. package/build/dex/angle-transmuter/types.js +33 -0
  61. package/build/dex/angle-transmuter/types.js.map +1 -0
  62. package/build/dex/angle-transmuter/utils.d.ts +9 -0
  63. package/build/dex/angle-transmuter/utils.js +257 -0
  64. package/build/dex/angle-transmuter/utils.js.map +1 -0
  65. package/build/dex/idle-dao/config.d.ts +6 -0
  66. package/build/dex/idle-dao/config.js +297 -0
  67. package/build/dex/idle-dao/config.js.map +1 -0
  68. package/build/dex/idle-dao/idle-dao-pool.d.ts +56 -0
  69. package/build/dex/idle-dao/idle-dao-pool.js +176 -0
  70. package/build/dex/idle-dao/idle-dao-pool.js.map +1 -0
  71. package/build/dex/idle-dao/idle-dao-pooling-pool.d.ts +16 -0
  72. package/build/dex/idle-dao/idle-dao-pooling-pool.js +57 -0
  73. package/build/dex/idle-dao/idle-dao-pooling-pool.js.map +1 -0
  74. package/build/dex/idle-dao/idle-dao.d.ts +41 -0
  75. package/build/dex/idle-dao/idle-dao.js +238 -0
  76. package/build/dex/idle-dao/idle-dao.js.map +1 -0
  77. package/build/dex/idle-dao/scripts.d.ts +9 -0
  78. package/build/dex/idle-dao/scripts.js +552 -0
  79. package/build/dex/idle-dao/scripts.js.map +1 -0
  80. package/build/dex/idle-dao/tokens.d.ts +9 -0
  81. package/build/dex/idle-dao/tokens.js +65 -0
  82. package/build/dex/idle-dao/tokens.js.map +1 -0
  83. package/build/dex/idle-dao/types.d.ts +34 -0
  84. package/build/dex/idle-dao/types.js +11 -0
  85. package/build/dex/idle-dao/types.js.map +1 -0
  86. package/build/dex/idle-dao/utils.d.ts +8 -0
  87. package/build/dex/idle-dao/utils.js +146 -0
  88. package/build/dex/idle-dao/utils.js.map +1 -0
  89. package/build/dex/index.js +2 -0
  90. package/build/dex/index.js.map +1 -1
  91. package/build/dex/maverick-v2/maverick-v2.js +1 -1
  92. package/build/dex/maverick-v2/maverick-v2.js.map +1 -1
  93. package/build/dex/maverick-v2/types.d.ts +1 -1
  94. package/build/dex/platypus/platypus.d.ts +2 -1
  95. package/build/dex/platypus/platypus.js +31 -0
  96. package/build/dex/platypus/platypus.js.map +1 -1
  97. package/build/dex/swaap-v1/swaap-v1.d.ts +2 -1
  98. package/build/dex/swaap-v1/swaap-v1.js +10 -0
  99. package/build/dex/swaap-v1/swaap-v1.js.map +1 -1
  100. package/build/lib/chainlink.d.ts +2 -0
  101. package/build/lib/chainlink.js +9 -0
  102. package/build/lib/chainlink.js.map +1 -1
  103. package/build/utils.d.ts +1 -1
  104. package/package.json +1 -1
  105. package/src/abi/Redstone.json +739 -0
  106. package/src/abi/angle-transmuter/ChainlinkAccessControlledOffchainAggregator.json +1246 -0
  107. package/src/abi/angle-transmuter/ChainlinkEACAggregatorProxy.json +509 -0
  108. package/src/abi/angle-transmuter/Getters.json +568 -0
  109. package/src/abi/angle-transmuter/MorphoOracle.json +193 -0
  110. package/src/abi/angle-transmuter/MorphoVault.json +2506 -0
  111. package/src/abi/angle-transmuter/Pyth.json +1534 -0
  112. package/src/abi/angle-transmuter/Swapper.json +329 -0
  113. package/src/abi/angle-transmuter/Transmuter.json +1711 -0
  114. package/src/abi/angle-transmuter/TransmuterSidechain.json +1798 -0
  115. package/src/dex/angle-transmuter/angle-transmuter-e2e.test.ts +156 -0
  116. package/src/dex/angle-transmuter/angle-transmuter-events.test.ts +365 -0
  117. package/src/dex/angle-transmuter/angle-transmuter-integration.test.ts +384 -0
  118. package/src/dex/angle-transmuter/angle-transmuter-pool.ts +856 -0
  119. package/src/dex/angle-transmuter/angle-transmuter.ts +443 -0
  120. package/src/dex/angle-transmuter/backedOracle.ts +91 -0
  121. package/src/dex/angle-transmuter/config.ts +50 -0
  122. package/src/dex/angle-transmuter/constants.ts +138 -0
  123. package/src/dex/angle-transmuter/morphoOracle.ts +335 -0
  124. package/src/dex/angle-transmuter/morphoVault.ts +134 -0
  125. package/src/dex/angle-transmuter/pyth.ts +105 -0
  126. package/src/dex/angle-transmuter/redstone.ts +114 -0
  127. package/src/dex/angle-transmuter/transmuter.ts +619 -0
  128. package/src/dex/angle-transmuter/types.ts +203 -0
  129. package/src/dex/angle-transmuter/utils.ts +358 -0
  130. package/src/dex/index.ts +2 -0
  131. package/src/dex/maverick-v2/maverick-v2.ts +1 -1
  132. package/src/dex/maverick-v2/types.ts +1 -1
  133. package/src/lib/chainlink.ts +15 -0
  134. package/tests/constants-e2e.ts +50 -5
  135. package/build/dex/bProtocol.d.ts +0 -18
  136. package/build/dex/bProtocol.js +0 -39
  137. package/build/dex/bProtocol.js.map +0 -1
  138. package/build/dex/bancor.d.ts +0 -26
  139. package/build/dex/bancor.js +0 -58
  140. package/build/dex/bancor.js.map +0 -1
  141. package/build/dex/compound.d.ts +0 -18
  142. package/build/dex/compound.js +0 -46
  143. package/build/dex/compound.js.map +0 -1
  144. package/build/dex/curve-v2.d.ts +0 -58
  145. package/build/dex/curve-v2.js +0 -180
  146. package/build/dex/curve-v2.js.map +0 -1
  147. package/build/dex/dodo-v1.d.ts +0 -33
  148. package/build/dex/dodo-v1.js +0 -63
  149. package/build/dex/dodo-v1.js.map +0 -1
  150. package/build/dex/etherfi/etherfi.d.ts +0 -26
  151. package/build/dex/etherfi/etherfi.js +0 -96
  152. package/build/dex/etherfi/etherfi.js.map +0 -1
  153. package/build/dex/lido.d.ts +0 -19
  154. package/build/dex/lido.js +0 -42
  155. package/build/dex/lido.js.map +0 -1
  156. package/build/dex/onebit.d.ts +0 -25
  157. package/build/dex/onebit.js +0 -42
  158. package/build/dex/onebit.js.map +0 -1
  159. package/build/dex/sdai/config.d.ts +0 -11
  160. package/build/dex/sdai/config.js +0 -21
  161. package/build/dex/sdai/config.js.map +0 -1
  162. package/build/dex/sdai/constants.d.ts +0 -2
  163. package/build/dex/sdai/constants.js +0 -6
  164. package/build/dex/sdai/constants.js.map +0 -1
  165. package/build/dex/sdai/scripts/validate-state.d.ts +0 -1
  166. package/build/dex/sdai/scripts/validate-state.js +0 -102
  167. package/build/dex/sdai/scripts/validate-state.js.map +0 -1
  168. package/build/dex/sdai/sdai-pool.d.ts +0 -16
  169. package/build/dex/sdai/sdai-pool.js +0 -85
  170. package/build/dex/sdai/sdai-pool.js.map +0 -1
  171. package/build/dex/sdai/sdai.d.ts +0 -51
  172. package/build/dex/sdai/sdai.js +0 -172
  173. package/build/dex/sdai/sdai.js.map +0 -1
  174. package/build/dex/sdai/types.d.ts +0 -21
  175. package/build/dex/sdai/types.js +0 -11
  176. package/build/dex/sdai/types.js.map +0 -1
  177. package/build/dex/sdai/utils.d.ts +0 -4
  178. package/build/dex/sdai/utils.js +0 -39
  179. package/build/dex/sdai/utils.js.map +0 -1
  180. package/build/dex/smoothy.d.ts +0 -26
  181. package/build/dex/smoothy.js +0 -48
  182. package/build/dex/smoothy.js.map +0 -1
  183. package/build/dex/stable-pool.d.ts +0 -28
  184. package/build/dex/stable-pool.js +0 -62
  185. package/build/dex/stable-pool.js.map +0 -1
  186. package/build/dex/trader-joe-v2.1.d.ts +0 -43
  187. package/build/dex/trader-joe-v2.1.js +0 -79
  188. package/build/dex/trader-joe-v2.1.js.map +0 -1
@@ -0,0 +1,443 @@
1
+ import { AsyncOrSync } from 'ts-essentials';
2
+ import {
3
+ Token,
4
+ Address,
5
+ ExchangePrices,
6
+ PoolPrices,
7
+ AdapterExchangeParam,
8
+ SimpleExchangeParam,
9
+ PoolLiquidity,
10
+ Logger,
11
+ NumberAsString,
12
+ DexExchangeParam,
13
+ } from '../../types';
14
+ import { SwapSide, Network } from '../../constants';
15
+ import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
16
+ import { getDexKeysWithNetwork } from '../../utils';
17
+ import { Context, IDex } from '../../dex/idex';
18
+ import { IDexHelper } from '../../dex-helper/idex-helper';
19
+ import { AngleTransmuterData, DexParams } from './types';
20
+ import { SimpleExchange } from '../simple-exchange';
21
+ import { AngleTransmuterConfig, Adapters } from './config';
22
+ import { AngleTransmuterEventPool } from './angle-transmuter-pool';
23
+ import { Interface, formatUnits, parseUnits } from 'ethers/lib/utils';
24
+ import { TransmuterSubscriber } from './transmuter';
25
+ import ERC20ABI from '../../abi/erc20.json';
26
+
27
+ const TransmuterGasCost = 0;
28
+
29
+ export class AngleTransmuter
30
+ extends SimpleExchange
31
+ implements IDex<AngleTransmuterData>
32
+ {
33
+ protected eventPools: { [key: string]: AngleTransmuterEventPool } = {};
34
+ protected supportedTokensMap: {
35
+ [key: string]: { [address: string]: boolean };
36
+ } = {};
37
+ protected supportedTokens: { [key: string]: Token[] } = {};
38
+ protected transmuterUSDLiquidity: { [key: string]: number } = {};
39
+ stablecoinList: string[];
40
+
41
+ public static erc20Interface = new Interface(ERC20ABI);
42
+
43
+ readonly hasConstantPriceLargeAmounts = false;
44
+ readonly needWrapNative = true;
45
+
46
+ readonly isFeeOnTransferSupported = false;
47
+
48
+ public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
49
+ getDexKeysWithNetwork(AngleTransmuterConfig);
50
+
51
+ logger: Logger;
52
+
53
+ constructor(
54
+ readonly network: Network,
55
+ readonly dexKey: string,
56
+ readonly dexHelper: IDexHelper,
57
+ protected adapters = Adapters[network] || {},
58
+ protected params: DexParams = AngleTransmuterConfig[dexKey][network],
59
+ ) {
60
+ super(dexHelper, dexKey);
61
+ this.logger = dexHelper.getLogger(dexKey);
62
+ this.stablecoinList = Object.keys(params);
63
+ this.stablecoinList.forEach(stablecoin => {
64
+ this.supportedTokensMap[stablecoin] = {};
65
+ this.supportedTokens[stablecoin] = [];
66
+ this.transmuterUSDLiquidity[stablecoin] = 0;
67
+ });
68
+ this.stablecoinList.forEach(stablecoin => {
69
+ this.supportedTokensMap[stablecoin][
70
+ params[stablecoin as keyof DexParams]!.stablecoin.address.toLowerCase()
71
+ ] = true;
72
+ });
73
+ }
74
+
75
+ // Initialize pricing is called once in the start of
76
+ // pricing service. It is intended to setup the integration
77
+ // for pricing requests. It is optional for a DEX to
78
+ // implement this function
79
+ async initializePricing(blockNumber: number) {
80
+ for (const stablecoin of this.stablecoinList) {
81
+ const config = await AngleTransmuterEventPool.getConfig(
82
+ this.params[stablecoin as keyof DexParams]!,
83
+ blockNumber,
84
+ this.dexHelper.multiContract,
85
+ );
86
+ config.collaterals.forEach(
87
+ (token: Address) =>
88
+ (this.supportedTokensMap[stablecoin][token.toLowerCase()] = true),
89
+ );
90
+ this.eventPools[stablecoin] = new AngleTransmuterEventPool(
91
+ this.dexKey,
92
+ this.network,
93
+ this.dexHelper,
94
+ this.logger,
95
+ config,
96
+ );
97
+ await this.eventPools[stablecoin].initialize(blockNumber);
98
+ }
99
+ }
100
+
101
+ // Returns the list of contract adapters (name and index)
102
+ // for a buy/sell. Return null if there are no adapters.
103
+ getAdapters(side: SwapSide): { name: string; index: number }[] | null {
104
+ return this.adapters[side] ? this.adapters[side] : null;
105
+ }
106
+
107
+ // Returns list of pool identifiers that can be used
108
+ // for a given swap. poolIdentifiers must be unique
109
+ // across DEXes. It is recommended to use
110
+ // ${dexKey}_${poolAddress} as a poolIdentifier
111
+ async getPoolIdentifiers(
112
+ srcToken: Token,
113
+ destToken: Token,
114
+ side: SwapSide,
115
+ blockNumber: number,
116
+ ): Promise<string[]> {
117
+ const knownInfo = this._knownAddress(srcToken, destToken);
118
+ if (!knownInfo.known) return [];
119
+ return [`${this.dexKey}_${knownInfo.agToken!.toLowerCase()}`];
120
+ }
121
+
122
+ // Returns pool prices for amounts.
123
+ // If limitPools is defined only pools in limitPools
124
+ // should be used. If limitPools is undefined then
125
+ // any pools can be used.
126
+ async getPricesVolume(
127
+ srcToken: Token,
128
+ destToken: Token,
129
+ amounts: bigint[],
130
+ side: SwapSide,
131
+ blockNumber: number,
132
+ limitPools?: string[],
133
+ ): Promise<null | ExchangePrices<AngleTransmuterData>> {
134
+ const knownInfo = this._knownAddress(srcToken, destToken);
135
+ const pool = `${this.dexKey}_${knownInfo.agToken!.toLowerCase()}`;
136
+ if (
137
+ !knownInfo.known ||
138
+ (limitPools && limitPools.length > 0 && !limitPools.includes(pool))
139
+ )
140
+ return null;
141
+
142
+ const fiat = knownInfo.fiatName! as keyof DexParams;
143
+ const preProcessDecimals =
144
+ side === SwapSide.SELL ? srcToken.decimals : destToken.decimals;
145
+ const postProcessDecimals =
146
+ side === SwapSide.SELL ? destToken.decimals : srcToken.decimals;
147
+ const unitVolume = 1;
148
+ const amountsFloat = amounts.map(amount =>
149
+ Number.parseFloat(formatUnits(amount.toString(), preProcessDecimals)),
150
+ );
151
+
152
+ const prices = await this.eventPools[fiat]!.getAmountOut(
153
+ srcToken.address,
154
+ destToken.address,
155
+ side,
156
+ [unitVolume, ...amountsFloat],
157
+ blockNumber,
158
+ );
159
+
160
+ if (!prices) return null;
161
+
162
+ const pricesBigInt = prices.map(price =>
163
+ BigInt(
164
+ parseUnits(
165
+ price.toFixed(postProcessDecimals).toString(),
166
+ postProcessDecimals,
167
+ ).toString(),
168
+ ),
169
+ );
170
+
171
+ return [
172
+ {
173
+ prices: pricesBigInt.slice(1),
174
+ unit: pricesBigInt[0],
175
+ gasCost: TransmuterGasCost,
176
+ exchange: this.dexKey,
177
+ data: { exchange: this.params[fiat]!.transmuter },
178
+ poolAddresses: [this.params[fiat]!.transmuter],
179
+ },
180
+ ];
181
+ }
182
+
183
+ // Returns estimated gas cost of calldata for this DEX in multiSwap
184
+ getCalldataGasCost(
185
+ poolPrices: PoolPrices<AngleTransmuterData>,
186
+ ): number | number[] {
187
+ return CALLDATA_GAS_COST.DEX_NO_PAYLOAD;
188
+ }
189
+
190
+ // Encode params required by the exchange adapter
191
+ // Used for multiSwap, buy & megaSwap
192
+ // Hint: abiCoder.encodeParameter() could be useful
193
+ getAdapterParam(
194
+ srcToken: string,
195
+ destToken: string,
196
+ srcAmount: string,
197
+ destAmount: string,
198
+ data: AngleTransmuterData,
199
+ side: SwapSide,
200
+ ): AdapterExchangeParam {
201
+ const { exchange } = data;
202
+
203
+ // Encode here the payload for adapter
204
+ const payload = '';
205
+
206
+ return {
207
+ targetExchange: exchange,
208
+ payload,
209
+ networkFee: '0',
210
+ };
211
+ }
212
+
213
+ // Encode call data used by simpleSwap like routers
214
+ // Used for simpleSwap & simpleBuy
215
+ // Hint: this.buildSimpleParamWithoutWETHConversion
216
+ // could be useful
217
+ async getSimpleParam(
218
+ srcToken: string,
219
+ destToken: string,
220
+ srcAmount: string,
221
+ destAmount: string,
222
+ data: AngleTransmuterData,
223
+ side: SwapSide,
224
+ ): Promise<SimpleExchangeParam> {
225
+ const { exchange } = data;
226
+
227
+ // Encode here the transaction arguments
228
+ const swapData =
229
+ TransmuterSubscriber.transmuterCrosschainInterface.encodeFunctionData(
230
+ side === SwapSide.SELL ? 'swapExactInput' : 'swapExactOutput',
231
+ [
232
+ side === SwapSide.SELL ? srcAmount : destAmount,
233
+ side === SwapSide.SELL ? destAmount : srcAmount,
234
+ srcToken,
235
+ destToken,
236
+ this.augustusAddress,
237
+ 0, // TODO no deadline?
238
+ ],
239
+ );
240
+
241
+ return this.buildSimpleParamWithoutWETHConversion(
242
+ srcToken,
243
+ srcAmount,
244
+ destToken,
245
+ destAmount,
246
+ swapData,
247
+ exchange,
248
+ );
249
+ }
250
+
251
+ getDexParam(
252
+ srcToken: Address,
253
+ destToken: Address,
254
+ srcAmount: NumberAsString,
255
+ destAmount: NumberAsString,
256
+ recipient: Address,
257
+ data: AngleTransmuterData,
258
+ side: SwapSide,
259
+ _: Context,
260
+ executorAddress: Address,
261
+ ): DexExchangeParam {
262
+ const { exchange } = data;
263
+
264
+ // Encode here the transaction arguments
265
+ const swapData =
266
+ TransmuterSubscriber.transmuterCrosschainInterface.encodeFunctionData(
267
+ side === SwapSide.SELL ? 'swapExactInput' : 'swapExactOutput',
268
+ [
269
+ side === SwapSide.SELL ? srcAmount : destAmount,
270
+ side === SwapSide.SELL ? destAmount : srcAmount,
271
+ srcToken,
272
+ destToken,
273
+ recipient,
274
+ 0,
275
+ ],
276
+ );
277
+
278
+ return {
279
+ needWrapNative: this.needWrapNative,
280
+ dexFuncHasRecipient: true,
281
+ exchangeData: swapData,
282
+ targetExchange: exchange,
283
+ returnAmountPos: undefined,
284
+ };
285
+ }
286
+
287
+ // This is called once before getTopPoolsForToken is
288
+ // called for multiple tokens. This can be helpful to
289
+ // update common state required for calculating
290
+ // getTopPoolsForToken. It is optional for a DEX
291
+ // to implement this
292
+ async updatePoolState(): Promise<void> {
293
+ for (const stablecoin of this.stablecoinList) {
294
+ const fiat = stablecoin as keyof DexParams;
295
+ const paramFiat = this.params[fiat]!;
296
+
297
+ if (!this.supportedTokens.length) {
298
+ let tokenAddresses = await AngleTransmuterEventPool.getCollateralsList(
299
+ paramFiat.transmuter,
300
+ 'latest',
301
+ this.dexHelper.multiContract,
302
+ );
303
+ tokenAddresses = tokenAddresses.concat([paramFiat.stablecoin.address]);
304
+
305
+ const decimalsCallData =
306
+ AngleTransmuter.erc20Interface.encodeFunctionData('decimals');
307
+ const tokenBalanceMultiCall = tokenAddresses.map(t => ({
308
+ target: t,
309
+ callData: decimalsCallData,
310
+ }));
311
+ const res = (
312
+ await this.dexHelper.multiContract.methods
313
+ .aggregate(tokenBalanceMultiCall)
314
+ .call()
315
+ ).returnData;
316
+
317
+ const tokenDecimals = res.map((r: any) =>
318
+ Number.parseInt(
319
+ AngleTransmuter.erc20Interface
320
+ .decodeFunctionResult('decimals', r)[0]
321
+ .toString(),
322
+ ),
323
+ );
324
+
325
+ this.supportedTokens[fiat] = tokenAddresses.map((t, i) => ({
326
+ address: t,
327
+ decimals: tokenDecimals[i],
328
+ }));
329
+ }
330
+
331
+ // Only work if there are no managers
332
+ const erc20BalanceCalldata =
333
+ AngleTransmuter.erc20Interface.encodeFunctionData('balanceOf', [
334
+ paramFiat.transmuter,
335
+ ]);
336
+ const tokenBalanceMultiCall = this.supportedTokens[fiat].map(t => ({
337
+ target: t.address,
338
+ callData: erc20BalanceCalldata,
339
+ }));
340
+ const res = (
341
+ await this.dexHelper.multiContract.methods
342
+ .aggregate(tokenBalanceMultiCall)
343
+ .call()
344
+ ).returnData;
345
+ const tokenBalances = res.map((r: any) =>
346
+ BigInt(
347
+ AngleTransmuter.erc20Interface
348
+ .decodeFunctionResult('balanceOf', r)[0]
349
+ .toString(),
350
+ ),
351
+ );
352
+
353
+ // TODO bC3M price not detected
354
+ const tokenBalancesUSD = await Promise.all(
355
+ this.supportedTokens[fiat].map((t, i) =>
356
+ this.dexHelper.getTokenUSDPrice(t, tokenBalances[i]),
357
+ ),
358
+ );
359
+ this.transmuterUSDLiquidity[fiat] = tokenBalancesUSD.reduce(
360
+ (sum: number, curr: number) => sum + curr,
361
+ );
362
+ }
363
+ }
364
+
365
+ // Returns list of top pools based on liquidity. Max
366
+ // limit number pools should be returned.
367
+ async getTopPoolsForToken(
368
+ tokenAddress: Address,
369
+ limit: number,
370
+ ): Promise<PoolLiquidity[]> {
371
+ for (const stablecoin of this.stablecoinList) {
372
+ const fiat = stablecoin as keyof DexParams;
373
+ const paramFiat = this.params[fiat]!;
374
+
375
+ // If not this stable let's check another one
376
+ if (
377
+ !this.supportedTokens[fiat].some(
378
+ t => t.address.toLowerCase() === tokenAddress.toLowerCase(),
379
+ )
380
+ )
381
+ continue;
382
+
383
+ const connectorTokens =
384
+ tokenAddress === paramFiat.stablecoin.address
385
+ ? this.supportedTokens[fiat].filter(
386
+ token =>
387
+ token.address.toLowerCase() !==
388
+ paramFiat.stablecoin.address.toLowerCase(),
389
+ )
390
+ : [paramFiat.stablecoin];
391
+
392
+ return [
393
+ {
394
+ exchange: this.dexKey,
395
+ address: paramFiat.transmuter,
396
+ connectorTokens: connectorTokens.slice(0, limit),
397
+ // liquidity is potentially infinite if swapping for agXXX, otherwise at most reserves value
398
+ liquidityUSD:
399
+ tokenAddress === paramFiat.stablecoin.address
400
+ ? this.transmuterUSDLiquidity[fiat]
401
+ : 1e9,
402
+ },
403
+ ];
404
+ }
405
+ return [];
406
+ }
407
+
408
+ // This is optional function in case if your implementation has acquired any resources
409
+ // you need to release for graceful shutdown. For example, it may be any interval timer
410
+ releaseResources(): AsyncOrSync<void> {}
411
+
412
+ _knownAddress(
413
+ srcToken: Token,
414
+ destToken: Token,
415
+ ): { known: boolean; agToken: string | null; fiatName: string | null } {
416
+ const srcAddress = this.dexHelper.config
417
+ .wrapETH(srcToken)
418
+ .address.toLowerCase();
419
+ const destAddress = this.dexHelper.config
420
+ .wrapETH(destToken)
421
+ .address.toLowerCase();
422
+
423
+ for (const stablecoin of this.stablecoinList) {
424
+ const fiat = stablecoin as keyof DexParams;
425
+ const paramFiat = this.params[fiat]!;
426
+ if (
427
+ srcAddress !== destAddress &&
428
+ this.supportedTokensMap[stablecoin][srcAddress] &&
429
+ this.supportedTokensMap[stablecoin][destAddress] &&
430
+ // check that at least one of the tokens is EURA
431
+ (srcAddress === paramFiat.stablecoin.address.toLowerCase() ||
432
+ destAddress === paramFiat.stablecoin.address.toLowerCase())
433
+ ) {
434
+ return {
435
+ known: true,
436
+ agToken: paramFiat.stablecoin.address.toLowerCase(),
437
+ fiatName: stablecoin,
438
+ };
439
+ }
440
+ }
441
+ return { known: false, agToken: null, fiatName: null };
442
+ }
443
+ }
@@ -0,0 +1,91 @@
1
+ import { DeepReadonly } from 'ts-essentials';
2
+ import { PartialEventSubscriber } from '../../composed-event-subscriber';
3
+ import {
4
+ Address,
5
+ BlockHeader,
6
+ Log,
7
+ Logger,
8
+ MultiCallInput,
9
+ MultiCallOutput,
10
+ } from '../../types';
11
+ import { Lens } from '../../lens';
12
+ import { Interface } from '@ethersproject/abi';
13
+ import ProxyABI from '../../abi/chainlink.json';
14
+ import { ChainLinkState } from '../../lib/chainlink';
15
+
16
+ export class BackedSubscriber<State> extends PartialEventSubscriber<
17
+ State,
18
+ ChainLinkState
19
+ > {
20
+ static readonly proxyInterface = new Interface(ProxyABI);
21
+ static readonly ANSWER_UPDATED_TOPIC =
22
+ BackedSubscriber.proxyInterface.getEventTopic('AnswerUpdated');
23
+
24
+ constructor(
25
+ private proxy: Address,
26
+ private aggregator: Address,
27
+ lens: Lens<DeepReadonly<State>, DeepReadonly<ChainLinkState>>,
28
+ logger: Logger,
29
+ ) {
30
+ super([aggregator], lens, logger);
31
+ }
32
+
33
+ static getReadDecimal(proxy: Address): MultiCallInput {
34
+ return {
35
+ target: proxy,
36
+ callData: BackedSubscriber.proxyInterface.encodeFunctionData('decimals'),
37
+ };
38
+ }
39
+
40
+ static readDecimals(multicallOutput: MultiCallOutput): Address {
41
+ return BackedSubscriber.proxyInterface.decodeFunctionResult(
42
+ 'decimals',
43
+ multicallOutput,
44
+ )[0];
45
+ }
46
+
47
+ public processLog(
48
+ state: DeepReadonly<ChainLinkState>,
49
+ log: Readonly<Log>,
50
+ blockHeader: Readonly<BlockHeader>,
51
+ ): DeepReadonly<ChainLinkState> | null {
52
+ if (log.topics[0] !== BackedSubscriber.ANSWER_UPDATED_TOPIC) return null; // Ignore other events
53
+ const decoded = BackedSubscriber.proxyInterface.decodeEventLog(
54
+ 'AnswerUpdated',
55
+ log.data,
56
+ log.topics,
57
+ );
58
+ return {
59
+ answer: BigInt(decoded.current.toString()),
60
+ timestamp: BigInt(decoded.updatedAt.toString()),
61
+ };
62
+ }
63
+
64
+ public getGenerateStateMultiCallInputs(): MultiCallInput[] {
65
+ return [
66
+ {
67
+ target: this.proxy,
68
+ callData:
69
+ BackedSubscriber.proxyInterface.encodeFunctionData('latestRoundData'),
70
+ },
71
+ ];
72
+ }
73
+
74
+ public generateState(
75
+ multicallOutputs: MultiCallOutput[],
76
+ blockNumber?: number | 'latest',
77
+ ): DeepReadonly<ChainLinkState> {
78
+ const decoded = BackedSubscriber.proxyInterface.decodeFunctionResult(
79
+ 'latestRoundData',
80
+ multicallOutputs[0],
81
+ );
82
+ return {
83
+ answer: BigInt(decoded.answer.toString()),
84
+ timestamp: BigInt(decoded.updatedAt.toString()),
85
+ };
86
+ }
87
+
88
+ public getLatestRoundData(state: DeepReadonly<State>): bigint {
89
+ return this.lens.get()(state).answer;
90
+ }
91
+ }
@@ -0,0 +1,50 @@
1
+ import { DexParams } from './types';
2
+ import { DexConfigMap, AdapterMappings } from '../../types';
3
+ import { Network, SwapSide } from '../../constants';
4
+
5
+ export const AngleTransmuterConfig: DexConfigMap<DexParams> = {
6
+ AngleTransmuter: {
7
+ [Network.MAINNET]: {
8
+ EUR: {
9
+ stablecoin: {
10
+ address: '0x1a7e4e63778B4f12a199C062f3eFdD288afCBce8',
11
+ decimals: 18,
12
+ },
13
+ transmuter: '0x00253582b2a3FE112feEC532221d9708c64cEFAb',
14
+ pyth: '0x4305FB66699C3B2702D4d05CF36551390A4c69C6',
15
+ },
16
+ USD: {
17
+ stablecoin: {
18
+ address: '0x0000206329b97DB379d5E1Bf586BbDB969C63274',
19
+ decimals: 18,
20
+ },
21
+ transmuter: '0x222222fD79264BBE280b4986F6FEfBC3524d0137',
22
+ pyth: '0x4305FB66699C3B2702D4d05CF36551390A4c69C6',
23
+ },
24
+ },
25
+ [Network.ARBITRUM]: {
26
+ USD: {
27
+ stablecoin: {
28
+ address: '0x0000206329b97DB379d5E1Bf586BbDB969C63274',
29
+ decimals: 18,
30
+ },
31
+ transmuter: '0xD253b62108d1831aEd298Fc2434A5A8e4E418053',
32
+ pyth: '0xff1a0f4744e8582DF1aE09D5611b887B6a12925C',
33
+ },
34
+ },
35
+ [Network.BASE]: {
36
+ USD: {
37
+ stablecoin: {
38
+ address: '0x0000206329b97DB379d5E1Bf586BbDB969C63274',
39
+ decimals: 18,
40
+ },
41
+ transmuter: '0x222222880e079445Df703c0604706E71a538Fd4f',
42
+ pyth: '0x8250f4aF4B972684F7b336503E2D6dFeDeB1487a',
43
+ },
44
+ },
45
+ },
46
+ };
47
+
48
+ export const Adapters: Record<number, AdapterMappings> = {
49
+ [Network.MAINNET]: { [SwapSide.SELL]: [{ name: '', index: 0 }] },
50
+ };