@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,138 @@
1
+ import { ethers } from 'ethers';
2
+ import { bigIntify } from '../../utils';
3
+ import { ChainlinkConfig, MorphoConfig, PoolConfig, PythConfig } from './types';
4
+
5
+ export const CBETH = '0xBe9895146f7AF43049ca1c1AE358B0541Ea49704';
6
+ export const RETH = '0xae78736Cd615f374D3085123A210448E74Fc6393';
7
+ export const STETH = '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84';
8
+ export const SFRXETH = '0xac3E018457B222d93114458476f3E3416Abbe38F';
9
+
10
+ export const configEUR: PoolConfig = {
11
+ stablecoin: {
12
+ address: '0x1a7e4e63778B4f12a199C062f3eFdD288afCBce8',
13
+ decimals: 18,
14
+ },
15
+ transmuter: '0x00253582b2a3FE112feEC532221d9708c64cEFAb',
16
+ collaterals: [
17
+ '0x3f95AA88dDbB7D9D484aa3D482bf0a80009c52c9',
18
+ '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',
19
+ '0x2F123cF3F37CE3328CC9B5b8415f9EC5109b45e7',
20
+ ],
21
+ oracles: {
22
+ chainlink: {},
23
+ backed: {
24
+ '0x83Ec02059F686E747392A22ddfED7833bA0d7cE3': {
25
+ proxy: '0x83Ec02059F686E747392A22ddfED7833bA0d7cE3',
26
+ aggregator: '0x83Ec02059F686E747392A22ddfED7833bA0d7cE3',
27
+ decimals: 8,
28
+ },
29
+ '0x475855DAe09af1e3f2d380d766b9E630926ad3CE': {
30
+ proxy: '0x475855DAe09af1e3f2d380d766b9E630926ad3CE',
31
+ aggregator: '0x475855DAe09af1e3f2d380d766b9E630926ad3CE',
32
+ decimals: 8,
33
+ },
34
+ },
35
+ redstone: {
36
+ '0x6E27A25999B3C665E44D903B2139F5a4Be2B6C26': {
37
+ proxy: '0x6E27A25999B3C665E44D903B2139F5a4Be2B6C26',
38
+ aggregator: '0x5BeEFeFE23aecccC77d164AB8E9Ff74e056588f1',
39
+ decimals: 8,
40
+ },
41
+ },
42
+ morpho: {},
43
+ pyth: {
44
+ proxy: '0x4305FB66699C3B2702D4d05CF36551390A4c69C6',
45
+ ids: [
46
+ '0x76fa85158bf14ede77087fe3ae472f66213f6ea2f5b411cb2de472794990fa5c',
47
+ '0xa995d00bb36a63cef7fd2c287dc105fc8f3d93779f062f09551b0af3e81ec30b',
48
+ ],
49
+ },
50
+ },
51
+ };
52
+
53
+ export const configUSD: PoolConfig = {
54
+ stablecoin: {
55
+ address: '0x0000206329b97DB379d5E1Bf586BbDB969C63274',
56
+ decimals: 18,
57
+ },
58
+ transmuter: '0x222222fD79264BBE280b4986F6FEfBC3524d0137',
59
+ collaterals: [
60
+ '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
61
+ '0xCA30c93B02514f86d5C86a6e375E3A330B435Fb5',
62
+ '0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB',
63
+ ],
64
+ oracles: {
65
+ backed: {} as ChainlinkConfig,
66
+ chainlink: {
67
+ '0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6': {
68
+ proxy: '0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6',
69
+ aggregator: '0x789190466E21a8b78b8027866CBBDc151542A26C',
70
+ decimals: 8,
71
+ },
72
+ '0x32d1463EB53b73C095625719Afa544D5426354cB': {
73
+ proxy: '0x32d1463EB53b73C095625719Afa544D5426354cB',
74
+ aggregator: '0x5EE6Ee50c1cB3E8Da20eE83D57818184387433e8',
75
+ decimals: 8,
76
+ },
77
+ },
78
+ redstone: {} as ChainlinkConfig,
79
+ morpho: {
80
+ '0x025106374196586E8BC91eE8818dD7B0Efd2B78B': {
81
+ baseVault: '0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB',
82
+ baseVaultConversion: bigIntify('1000000000000000000'),
83
+ quoteVault: ethers.constants.AddressZero,
84
+ quoteVaultConversion: bigIntify('1'),
85
+ baseFeed1: '0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6',
86
+ baseFeed2: ethers.constants.AddressZero,
87
+ quoteFeed1: ethers.constants.AddressZero,
88
+ quoteFeed2: ethers.constants.AddressZero,
89
+ scaleFactor: bigIntify('1000000000000000000'),
90
+ },
91
+ },
92
+ pyth: {} as PythConfig,
93
+ },
94
+ };
95
+
96
+ export const configUSDBase: PoolConfig = {
97
+ stablecoin: {
98
+ address: '0x0000206329b97DB379d5E1Bf586BbDB969C63274',
99
+ decimals: 18,
100
+ },
101
+ transmuter: '0x222222880e079445Df703c0604706E71a538Fd4f',
102
+ collaterals: ['0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'],
103
+ oracles: {
104
+ backed: {} as ChainlinkConfig,
105
+ chainlink: {
106
+ '0x7e860098F58bBFC8648a4311b374B1D669a2bc6B': {
107
+ proxy: '0x7e860098F58bBFC8648a4311b374B1D669a2bc6B',
108
+ aggregator: '0x0Ee7145e1370653533e2F2E824424bE2AA95A4Aa',
109
+ decimals: 8,
110
+ },
111
+ },
112
+ redstone: {} as ChainlinkConfig,
113
+ morpho: {} as MorphoConfig,
114
+ pyth: {} as PythConfig,
115
+ },
116
+ };
117
+
118
+ export const configUSDArbitrum: PoolConfig = {
119
+ stablecoin: {
120
+ address: '0x0000206329b97DB379d5E1Bf586BbDB969C63274',
121
+ decimals: 18,
122
+ },
123
+ transmuter: '0xD253b62108d1831aEd298Fc2434A5A8e4E418053',
124
+ collaterals: ['0xaf88d065e77c8cC2239327C5EDb3A432268e5831'],
125
+ oracles: {
126
+ backed: {} as ChainlinkConfig,
127
+ chainlink: {
128
+ '0x50834F3163758fcC1Df9973b6e91f0F0F0434aD3': {
129
+ proxy: '0x50834F3163758fcC1Df9973b6e91f0F0F0434aD3',
130
+ aggregator: '0x2946220288DbBF77dF0030fCecc2a8348CbBE32C',
131
+ decimals: 8,
132
+ },
133
+ },
134
+ redstone: {} as ChainlinkConfig,
135
+ morpho: {} as MorphoConfig,
136
+ pyth: {} as PythConfig,
137
+ },
138
+ };
@@ -0,0 +1,335 @@
1
+ import { Interface } from '@ethersproject/abi';
2
+ import type { DeepReadonly } from 'ts-essentials';
3
+ import type {
4
+ BlockHeader,
5
+ Log,
6
+ Logger,
7
+ MultiCallInput,
8
+ MultiCallOutput,
9
+ } from '../../types';
10
+ import { bigIntify, catchParseLogError } from '../../utils';
11
+ import { StatefulEventSubscriber } from '../../stateful-event-subscriber';
12
+ import type { IDexHelper } from '../../dex-helper/idex-helper';
13
+ import type { MorphoOracleState } from './types';
14
+ import MorphoOracleABI from '../../abi/angle-transmuter/MorphoOracle.json';
15
+ import ERC20ABI from '../../abi/erc20.json';
16
+
17
+ export class MorphoOracleEventPool extends StatefulEventSubscriber<MorphoOracleState> {
18
+ handlers: {
19
+ [event: string]: (
20
+ event: any,
21
+ state: DeepReadonly<MorphoOracleState>,
22
+ log: Readonly<Log>,
23
+ blockHeader: Readonly<BlockHeader>,
24
+ ) => DeepReadonly<MorphoOracleState> | null;
25
+ } = {};
26
+
27
+ static morphoOracleIface = new Interface(MorphoOracleABI);
28
+ static erc20Iface = new Interface(ERC20ABI);
29
+
30
+ logDecoder: (log: Log) => any;
31
+
32
+ addressesSubscribed: string[];
33
+
34
+ constructor(
35
+ readonly parentName: string,
36
+ protected network: number,
37
+ protected dexHelper: IDexHelper,
38
+ public morphoOracle: string,
39
+ logger: Logger,
40
+ ) {
41
+ super(parentName, 'Morpho_Oracle', dexHelper, logger);
42
+
43
+ this.logDecoder = (log: Log) =>
44
+ MorphoOracleEventPool.morphoOracleIface.parseLog(log);
45
+ this.addressesSubscribed = [morphoOracle];
46
+ }
47
+
48
+ /**
49
+ * The function is called every time any of the subscribed
50
+ * addresses release log. The function accepts the current
51
+ * state, updates the state according to the log, and returns
52
+ * the updated state.
53
+ * @param state - Current state of event subscriber
54
+ * @param log - Log released by one of the subscribed addresses
55
+ * @returns Updates state of the event subscriber after the log
56
+ */
57
+ protected processLog(
58
+ state: DeepReadonly<MorphoOracleState>,
59
+ log: Readonly<Log>,
60
+ blockHeader: Readonly<BlockHeader>,
61
+ ): DeepReadonly<MorphoOracleState> | null {
62
+ try {
63
+ const event = this.logDecoder(log);
64
+ if (event.name in this.handlers) {
65
+ return this.handlers[event.name](event, state, log, blockHeader);
66
+ }
67
+ } catch (e) {
68
+ catchParseLogError(e, this.logger);
69
+ }
70
+
71
+ return null;
72
+ }
73
+
74
+ /**
75
+ * The function generates state using on-chain calls. This
76
+ * function is called to regenerate state if the event based
77
+ * system fails to fetch events and the local state is no
78
+ * more correct.
79
+ * @param blockNumber - Blocknumber for which the state should
80
+ * should be generated
81
+ * @returns state of the event subscriber at blocknumber
82
+ */
83
+ public async generateState(
84
+ blockNumber: number,
85
+ ): Promise<DeepReadonly<MorphoOracleState>> {
86
+ const poolState = {} as MorphoOracleState;
87
+
88
+ const multicall = [
89
+ {
90
+ target: this.morphoOracle,
91
+ callData:
92
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
93
+ 'BASE_VAULT',
94
+ ),
95
+ },
96
+ {
97
+ target: this.morphoOracle,
98
+ callData: MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
99
+ 'BASE_VAULT_CONVERSION_SAMPLE',
100
+ ),
101
+ },
102
+ {
103
+ target: this.morphoOracle,
104
+ callData:
105
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
106
+ 'QUOTE_VAULT',
107
+ ),
108
+ },
109
+ {
110
+ target: this.morphoOracle,
111
+ callData: MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
112
+ 'QUOTE_VAULT_CONVERSION_SAMPLE',
113
+ ),
114
+ },
115
+ {
116
+ target: this.morphoOracle,
117
+ callData:
118
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
119
+ 'BASE_FEED_1',
120
+ ),
121
+ },
122
+ {
123
+ target: this.morphoOracle,
124
+ callData:
125
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
126
+ 'BASE_FEED_2',
127
+ ),
128
+ },
129
+ {
130
+ target: this.morphoOracle,
131
+ callData:
132
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
133
+ 'QUOTE_FEED_1',
134
+ ),
135
+ },
136
+ {
137
+ target: this.morphoOracle,
138
+ callData:
139
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
140
+ 'QUOTE_FEED_1',
141
+ ),
142
+ },
143
+ {
144
+ target: this.morphoOracle,
145
+ callData:
146
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
147
+ 'SCALE_FACTOR',
148
+ ),
149
+ },
150
+ ];
151
+
152
+ // on chain call
153
+ const returnData = (
154
+ await this.dexHelper.multiContract.methods
155
+ .aggregate(multicall)
156
+ .call({}, blockNumber)
157
+ ).returnData;
158
+
159
+ // Decode
160
+ poolState.baseVault =
161
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
162
+ 'BASE_VAULT',
163
+ returnData[0],
164
+ )[0] as string;
165
+ poolState.baseVaultConversion = bigIntify(
166
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
167
+ 'BASE_VAULT_CONVERSION_SAMPLE',
168
+ returnData[1],
169
+ )[0],
170
+ );
171
+ poolState.quoteVault =
172
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
173
+ 'QUOTE_VAULT',
174
+ returnData[2],
175
+ )[0] as string;
176
+ poolState.quoteVaultConversion = bigIntify(
177
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
178
+ 'QUOTE_VAULT_CONVERSION_SAMPLE',
179
+ returnData[3],
180
+ )[0],
181
+ );
182
+ poolState.baseFeed1 =
183
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
184
+ 'BASE_FEED_1',
185
+ returnData[4],
186
+ )[0] as string;
187
+ poolState.baseFeed2 =
188
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
189
+ 'BASE_FEED_2',
190
+ returnData[5],
191
+ )[0] as string;
192
+ poolState.quoteFeed1 =
193
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
194
+ 'QUOTE_FEED_1',
195
+ returnData[6],
196
+ )[0] as string;
197
+ poolState.quoteFeed2 =
198
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
199
+ 'QUOTE_FEED_2',
200
+ returnData[7],
201
+ )[0] as string;
202
+ poolState.scaleFactor = bigIntify(
203
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
204
+ 'SCALE_FACTOR',
205
+ returnData[8],
206
+ )[0],
207
+ );
208
+
209
+ return poolState;
210
+ }
211
+
212
+ static getGenerateInfoMultiCallInput(morphoOracle: string): MultiCallInput[] {
213
+ return [
214
+ {
215
+ target: morphoOracle,
216
+ callData:
217
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
218
+ 'BASE_VAULT',
219
+ ),
220
+ },
221
+ {
222
+ target: morphoOracle,
223
+ callData: MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
224
+ 'BASE_VAULT_CONVERSION_SAMPLE',
225
+ ),
226
+ },
227
+ {
228
+ target: morphoOracle,
229
+ callData:
230
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
231
+ 'QUOTE_VAULT',
232
+ ),
233
+ },
234
+ {
235
+ target: morphoOracle,
236
+ callData: MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
237
+ 'QUOTE_VAULT_CONVERSION_SAMPLE',
238
+ ),
239
+ },
240
+ {
241
+ target: morphoOracle,
242
+ callData:
243
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
244
+ 'BASE_FEED_1',
245
+ ),
246
+ },
247
+ {
248
+ target: morphoOracle,
249
+ callData:
250
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
251
+ 'BASE_FEED_2',
252
+ ),
253
+ },
254
+ {
255
+ target: morphoOracle,
256
+ callData:
257
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
258
+ 'QUOTE_FEED_1',
259
+ ),
260
+ },
261
+ {
262
+ target: morphoOracle,
263
+ callData:
264
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
265
+ 'QUOTE_FEED_1',
266
+ ),
267
+ },
268
+ {
269
+ target: morphoOracle,
270
+ callData:
271
+ MorphoOracleEventPool.morphoOracleIface.encodeFunctionData(
272
+ 'SCALE_FACTOR',
273
+ ),
274
+ },
275
+ ];
276
+ }
277
+
278
+ static generateInfo(
279
+ multicallOutputs: MultiCallOutput[],
280
+ ): DeepReadonly<MorphoOracleState> {
281
+ const poolState = {} as MorphoOracleState;
282
+
283
+ // Decode
284
+ poolState.baseVault =
285
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
286
+ 'BASE_VAULT',
287
+ multicallOutputs[0],
288
+ )[0] as string;
289
+ poolState.baseVaultConversion = bigIntify(
290
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
291
+ 'BASE_VAULT_CONVERSION_SAMPLE',
292
+ multicallOutputs[1],
293
+ )[0],
294
+ );
295
+ poolState.quoteVault =
296
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
297
+ 'QUOTE_VAULT',
298
+ multicallOutputs[2],
299
+ )[0] as string;
300
+ poolState.quoteVaultConversion = bigIntify(
301
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
302
+ 'QUOTE_VAULT_CONVERSION_SAMPLE',
303
+ multicallOutputs[3],
304
+ )[0],
305
+ );
306
+ poolState.baseFeed1 =
307
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
308
+ 'BASE_FEED_1',
309
+ multicallOutputs[4],
310
+ )[0] as string;
311
+ poolState.baseFeed2 =
312
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
313
+ 'BASE_FEED_2',
314
+ multicallOutputs[5],
315
+ )[0] as string;
316
+ poolState.quoteFeed1 =
317
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
318
+ 'QUOTE_FEED_1',
319
+ multicallOutputs[6],
320
+ )[0] as string;
321
+ poolState.quoteFeed2 =
322
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
323
+ 'QUOTE_FEED_2',
324
+ multicallOutputs[7],
325
+ )[0] as string;
326
+ poolState.scaleFactor = bigIntify(
327
+ MorphoOracleEventPool.morphoOracleIface.decodeFunctionResult(
328
+ 'SCALE_FACTOR',
329
+ multicallOutputs[8],
330
+ )[0],
331
+ );
332
+
333
+ return poolState;
334
+ }
335
+ }
@@ -0,0 +1,134 @@
1
+ import { Interface } from '@ethersproject/abi';
2
+ import type { DeepReadonly } from 'ts-essentials';
3
+ import type {
4
+ BlockHeader,
5
+ Log,
6
+ Logger,
7
+ MultiCallInput,
8
+ MultiCallOutput,
9
+ } from '../../types';
10
+ import { bigIntify } from '../../utils';
11
+ import type { MorphoVaultState } from './types';
12
+ import MorphoVaultABI from '../../abi/angle-transmuter/MorphoVault.json';
13
+ import { PartialEventSubscriber } from '../../composed-event-subscriber';
14
+ import { Lens } from '../../lens';
15
+ import _ from 'lodash';
16
+ import { ethers } from 'ethers';
17
+
18
+ export class MorphoVaultSubscriber<State> extends PartialEventSubscriber<
19
+ State,
20
+ MorphoVaultState
21
+ > {
22
+ static interface = new Interface(MorphoVaultABI);
23
+
24
+ constructor(
25
+ public morphoVault: string,
26
+ lens: Lens<DeepReadonly<State>, DeepReadonly<MorphoVaultState>>,
27
+ logger: Logger,
28
+ ) {
29
+ super([morphoVault], lens, logger);
30
+ }
31
+
32
+ public processLog(
33
+ state: DeepReadonly<MorphoVaultState>,
34
+ log: Readonly<Log>,
35
+ blockHeader: Readonly<BlockHeader>,
36
+ ): DeepReadonly<MorphoVaultState> | null {
37
+ try {
38
+ const parsed = MorphoVaultSubscriber.interface.parseLog(log);
39
+ const _state: MorphoVaultState = _.cloneDeep(state) as MorphoVaultState;
40
+ switch (parsed.name) {
41
+ case 'UpdateLastTotalAssets':
42
+ return this.handleUpdateLastTotalAssets(parsed, _state);
43
+ case 'AccrueInterest':
44
+ return this.handleAccrueFee(parsed, _state);
45
+ case 'Deposit':
46
+ return this.handleDeposit(parsed, _state);
47
+ case 'Withdraw':
48
+ return this.handleWithdraw(parsed, _state);
49
+ default:
50
+ return null;
51
+ }
52
+ } catch (e) {
53
+ this.logger.error('Failed to parse log', e);
54
+ return null;
55
+ }
56
+ }
57
+
58
+ public getGenerateStateMultiCallInputs(): MultiCallInput[] {
59
+ return [
60
+ {
61
+ target: this.morphoVault,
62
+ callData:
63
+ MorphoVaultSubscriber.interface.encodeFunctionData('totalAssets'),
64
+ },
65
+ {
66
+ target: this.morphoVault,
67
+ callData:
68
+ MorphoVaultSubscriber.interface.encodeFunctionData('totalSupply'),
69
+ },
70
+ ];
71
+ }
72
+
73
+ public generateState(
74
+ multicallOutputs: MultiCallOutput[],
75
+ blockNumber?: number | 'latest',
76
+ ): DeepReadonly<MorphoVaultState> {
77
+ const morphoVaultState = {} as MorphoVaultState;
78
+
79
+ // Decode
80
+ morphoVaultState.totalAssets = bigIntify(
81
+ MorphoVaultSubscriber.interface.decodeFunctionResult(
82
+ 'totalAssets',
83
+ multicallOutputs[0],
84
+ )[0],
85
+ );
86
+ morphoVaultState.totalSupply = bigIntify(
87
+ MorphoVaultSubscriber.interface.decodeFunctionResult(
88
+ 'totalSupply',
89
+ multicallOutputs[1],
90
+ )[0],
91
+ );
92
+ return morphoVaultState;
93
+ }
94
+
95
+ getRate(amount: bigint, state: MorphoVaultState): bigint {
96
+ return amount === 0n || state.totalSupply === 0n
97
+ ? amount
98
+ : (amount * state.totalSupply) / state.totalAssets;
99
+ }
100
+
101
+ handleUpdateLastTotalAssets(
102
+ event: ethers.utils.LogDescription,
103
+ state: MorphoVaultState,
104
+ ): DeepReadonly<MorphoVaultState> | null {
105
+ state.totalAssets = bigIntify(event.args.updatedTotalAssets);
106
+ return state;
107
+ }
108
+
109
+ handleAccrueFee(
110
+ event: ethers.utils.LogDescription,
111
+ state: MorphoVaultState,
112
+ ): DeepReadonly<MorphoVaultState> | null {
113
+ state.totalSupply += bigIntify(event.args.feeShares);
114
+ return state;
115
+ }
116
+
117
+ handleDeposit(
118
+ event: ethers.utils.LogDescription,
119
+ state: MorphoVaultState,
120
+ ): DeepReadonly<MorphoVaultState> | null {
121
+ const shares = bigIntify(event.args.shares);
122
+ state.totalSupply += shares;
123
+ return state;
124
+ }
125
+
126
+ handleWithdraw(
127
+ event: ethers.utils.LogDescription,
128
+ state: MorphoVaultState,
129
+ ): DeepReadonly<MorphoVaultState> | null {
130
+ const shares = bigIntify(event.args.shares);
131
+ state.totalSupply -= shares;
132
+ return state;
133
+ }
134
+ }
@@ -0,0 +1,105 @@
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 PythABI from '../../abi/angle-transmuter/Pyth.json';
14
+ import _ from 'lodash';
15
+ import { formatUnits, parseUnits } from 'ethers/lib/utils';
16
+ import { BigNumber } from 'ethers';
17
+ import { PythState } from './types';
18
+
19
+ export class PythSubscriber<State> extends PartialEventSubscriber<
20
+ State,
21
+ PythState
22
+ > {
23
+ static readonly proxyInterface = new Interface(PythABI);
24
+ static readonly ANSWER_UPDATED_TOPIC =
25
+ PythSubscriber.proxyInterface.getEventTopic('PriceFeedUpdate');
26
+
27
+ constructor(
28
+ private proxy: Address,
29
+ private oracleIds: string[],
30
+ lens: Lens<DeepReadonly<State>, DeepReadonly<PythState>>,
31
+ logger: Logger,
32
+ ) {
33
+ super([proxy], lens, logger);
34
+ }
35
+
36
+ public processLog(
37
+ state: DeepReadonly<PythState>,
38
+ log: Readonly<Log>,
39
+ blockHeader: Readonly<BlockHeader>,
40
+ ): DeepReadonly<PythState> | null {
41
+ if (log.topics[0] !== PythSubscriber.ANSWER_UPDATED_TOPIC) return null; // Ignore other events
42
+ const decoded = PythSubscriber.proxyInterface.decodeEventLog(
43
+ 'PriceFeedUpdate',
44
+ log.data,
45
+ log.topics,
46
+ );
47
+ if (this.oracleIds.indexOf(decoded.id) === -1) return null;
48
+ const _state = _.cloneDeep(state) as PythState;
49
+ const expo = _state[decoded.id].expo;
50
+ _state[decoded.id] = {
51
+ answer: this._processPrice(decoded.price, expo),
52
+ expo: expo,
53
+ timestamp: Number(decoded.publishTime),
54
+ };
55
+ return _state;
56
+ }
57
+
58
+ public getGenerateStateMultiCallInputs(): MultiCallInput[] {
59
+ const oraclesMultiCalls = this.oracleIds.map(id => {
60
+ return {
61
+ target: this.proxy,
62
+ callData: PythSubscriber.proxyInterface.encodeFunctionData(
63
+ 'getPriceUnsafe',
64
+ [id],
65
+ ),
66
+ };
67
+ });
68
+ return oraclesMultiCalls;
69
+ }
70
+
71
+ public generateState(
72
+ multicallOutputs: MultiCallOutput[],
73
+ blockNumber?: number | 'latest',
74
+ ): DeepReadonly<PythState> {
75
+ const decodedOracle = multicallOutputs.map(call => {
76
+ return PythSubscriber.proxyInterface.decodeFunctionResult(
77
+ 'getPriceUnsafe',
78
+ call,
79
+ )[0];
80
+ });
81
+ const _state = {} as PythState;
82
+ this.oracleIds.map((id, index) => {
83
+ const expo = decodedOracle[index].expo;
84
+ _state[id] = {
85
+ answer: this._processPrice(decodedOracle[index].price, expo),
86
+ expo: expo,
87
+ timestamp: Number(decodedOracle[index].publishTime),
88
+ };
89
+ });
90
+ return _state;
91
+ }
92
+
93
+ public getLatestRoundData(
94
+ state: DeepReadonly<State>,
95
+ oracleId: string,
96
+ ): number {
97
+ return this.lens.get()(state)[oracleId].answer;
98
+ }
99
+
100
+ public _processPrice(price: BigNumber, expo: number): number {
101
+ const isNormalizerExpoNeg = expo < 0;
102
+ if (isNormalizerExpoNeg) return Number(formatUnits(price, -expo));
103
+ return Number(parseUnits(price.toString(), expo));
104
+ }
105
+ }