@paraswap/dex-lib 2.16.0 → 2.16.1-generate-state-latest.0

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 (220) hide show
  1. package/build/composed-event-subscriber.d.ts +2 -2
  2. package/build/composed-event-subscriber.js +9 -4
  3. package/build/composed-event-subscriber.js.map +1 -1
  4. package/build/dex/aave-v1/aave-v1.d.ts +1 -1
  5. package/build/dex/aave-v1/aave-v1.js +1 -1
  6. package/build/dex/aave-v1/aave-v1.js.map +1 -1
  7. package/build/dex/aave-v2/aave-v2.d.ts +1 -1
  8. package/build/dex/aave-v2/aave-v2.js +1 -1
  9. package/build/dex/aave-v2/aave-v2.js.map +1 -1
  10. package/build/dex/aave-v3/aave-v3.d.ts +1 -1
  11. package/build/dex/aave-v3/aave-v3.js +1 -1
  12. package/build/dex/aave-v3/aave-v3.js.map +1 -1
  13. package/build/dex/aave-v3/tokens/arbitrum.json +50 -0
  14. package/build/dex/aave-v3/tokens/avalanche.json +74 -0
  15. package/build/dex/aave-v3/tokens/fantom.json +62 -0
  16. package/build/dex/aave-v3/tokens/optimism.json +50 -0
  17. package/build/dex/aave-v3/tokens/polygon.json +116 -0
  18. package/build/dex/aave-v3/utils.d.ts +1 -1
  19. package/build/dex/aave-v3/utils.js.map +1 -1
  20. package/build/dex/balancer-v1/balancer-v1-pool.d.ts +2 -2
  21. package/build/dex/balancer-v1/balancer-v1-pool.js +5 -1
  22. package/build/dex/balancer-v1/balancer-v1-pool.js.map +1 -1
  23. package/build/dex/balancer-v1/balancer-v1.d.ts +1 -1
  24. package/build/dex/balancer-v1/balancer-v1.js +7 -4
  25. package/build/dex/balancer-v1/balancer-v1.js.map +1 -1
  26. package/build/dex/balancer-v1/utils.d.ts +3 -1
  27. package/build/dex/balancer-v1/utils.js +18 -5
  28. package/build/dex/balancer-v1/utils.js.map +1 -1
  29. package/build/dex/balancer-v2/balancer-v2.d.ts +10 -5
  30. package/build/dex/balancer-v2/balancer-v2.js +15 -10
  31. package/build/dex/balancer-v2/balancer-v2.js.map +1 -1
  32. package/build/dex/camelot/camelot.d.ts +2 -2
  33. package/build/dex/camelot/camelot.js +15 -6
  34. package/build/dex/camelot/camelot.js.map +1 -1
  35. package/build/dex/curve-v1/curve-v1.d.ts +1 -1
  36. package/build/dex/curve-v1/curve-v1.js +5 -8
  37. package/build/dex/curve-v1/curve-v1.js.map +1 -1
  38. package/build/dex/curve-v1/pools/curve-metapool.d.ts +2 -2
  39. package/build/dex/curve-v1/pools/curve-metapool.js +12 -4
  40. package/build/dex/curve-v1/pools/curve-metapool.js.map +1 -1
  41. package/build/dex/curve-v1/pools/curve-pool.d.ts +3 -3
  42. package/build/dex/curve-v1/pools/curve-pool.js +13 -4
  43. package/build/dex/curve-v1/pools/curve-pool.js.map +1 -1
  44. package/build/dex/curve-v1/pools/getstate-multicall.d.ts +6 -1
  45. package/build/dex/curve-v1/pools/getstate-multicall.js +32 -25
  46. package/build/dex/curve-v1/pools/getstate-multicall.js.map +1 -1
  47. package/build/dex/curve-v1-factory/curve-v1-factory.d.ts +3 -3
  48. package/build/dex/curve-v1-factory/curve-v1-factory.js +4 -4
  49. package/build/dex/curve-v1-factory/curve-v1-factory.js.map +1 -1
  50. package/build/dex/curve-v1-factory/curve-v1-pool-manager.d.ts +1 -1
  51. package/build/dex/curve-v1-factory/curve-v1-pool-manager.js +1 -1
  52. package/build/dex/curve-v1-factory/curve-v1-pool-manager.js.map +1 -1
  53. package/build/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.d.ts +1 -1
  54. package/build/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.js.map +1 -1
  55. package/build/dex/curve-v1-factory/state-polling-pools/factory-pool-polling.d.ts +1 -1
  56. package/build/dex/curve-v1-factory/state-polling-pools/factory-pool-polling.js.map +1 -1
  57. package/build/dex/curve-v1-factory/state-polling-pools/polling-manager.d.ts +4 -4
  58. package/build/dex/curve-v1-factory/state-polling-pools/polling-manager.js +5 -15
  59. package/build/dex/curve-v1-factory/state-polling-pools/polling-manager.js.map +1 -1
  60. package/build/dex/curve-v1-factory/state-polling-pools/pool-polling-base.d.ts +1 -1
  61. package/build/dex/curve-v1-factory/types.d.ts +1 -1
  62. package/build/dex/generic-rfq/generic-rfq.d.ts +1 -1
  63. package/build/dex/generic-rfq/generic-rfq.js +1 -1
  64. package/build/dex/generic-rfq/generic-rfq.js.map +1 -1
  65. package/build/dex/generic-rfq/utils.js +1 -1
  66. package/build/dex/generic-rfq/utils.js.map +1 -1
  67. package/build/dex/gmx/gmx.d.ts +1 -1
  68. package/build/dex/gmx/gmx.js +1 -1
  69. package/build/dex/gmx/gmx.js.map +1 -1
  70. package/build/dex/gmx/pool.js +5 -4
  71. package/build/dex/gmx/pool.js.map +1 -1
  72. package/build/dex/idex.d.ts +1 -1
  73. package/build/dex/jarvis-v6/jarvis-v6-events.d.ts +4 -3
  74. package/build/dex/jarvis-v6/jarvis-v6-events.js +8 -4
  75. package/build/dex/jarvis-v6/jarvis-v6-events.js.map +1 -1
  76. package/build/dex/jarvis-v6/jarvis-v6.d.ts +1 -1
  77. package/build/dex/jarvis-v6/jarvis-v6.js +12 -8
  78. package/build/dex/jarvis-v6/jarvis-v6.js.map +1 -1
  79. package/build/dex/jarvis-v6/utils.d.ts +2 -1
  80. package/build/dex/jarvis-v6/utils.js +15 -6
  81. package/build/dex/jarvis-v6/utils.js.map +1 -1
  82. package/build/dex/kyberdmm/kyberdmm.js +4 -1
  83. package/build/dex/kyberdmm/kyberdmm.js.map +1 -1
  84. package/build/dex/kyberdmm/pool.d.ts +2 -2
  85. package/build/dex/kyberdmm/pool.js +21 -20
  86. package/build/dex/kyberdmm/pool.js.map +1 -1
  87. package/build/dex/maker-psm/maker-psm.d.ts +3 -3
  88. package/build/dex/maker-psm/maker-psm.js +35 -27
  89. package/build/dex/maker-psm/maker-psm.js.map +1 -1
  90. package/build/dex/maverick-v1/maverick-v1-pool.d.ts +3 -5
  91. package/build/dex/maverick-v1/maverick-v1-pool.js +27 -38
  92. package/build/dex/maverick-v1/maverick-v1-pool.js.map +1 -1
  93. package/build/dex/maverick-v1/maverick-v1.d.ts +2 -2
  94. package/build/dex/maverick-v1/maverick-v1.js +8 -8
  95. package/build/dex/maverick-v1/maverick-v1.js.map +1 -1
  96. package/build/dex/nerve/nerve-pool.d.ts +2 -2
  97. package/build/dex/nerve/nerve-pool.js +28 -25
  98. package/build/dex/nerve/nerve-pool.js.map +1 -1
  99. package/build/dex/nerve/nerve.d.ts +2 -2
  100. package/build/dex/nerve/nerve.js +5 -5
  101. package/build/dex/nerve/nerve.js.map +1 -1
  102. package/build/dex/platypus/platypus.d.ts +3 -3
  103. package/build/dex/platypus/platypus.js +6 -5
  104. package/build/dex/platypus/platypus.js.map +1 -1
  105. package/build/dex/swaap-v1/config.d.ts +1 -1
  106. package/build/dex/swaap-v1/config.js +2 -2
  107. package/build/dex/swaap-v1/swaap-v1-pool.d.ts +3 -3
  108. package/build/dex/swaap-v1/swaap-v1-pool.js +15 -9
  109. package/build/dex/swaap-v1/swaap-v1-pool.js.map +1 -1
  110. package/build/dex/swaap-v1/swaap-v1.d.ts +2 -2
  111. package/build/dex/swaap-v1/swaap-v1.js +11 -8
  112. package/build/dex/swaap-v1/swaap-v1.js.map +1 -1
  113. package/build/dex/synthetix/synthetix-state.js +1 -1
  114. package/build/dex/synthetix/synthetix-state.js.map +1 -1
  115. package/build/dex/synthetix/synthetix.d.ts +1 -1
  116. package/build/dex/synthetix/synthetix.js +5 -4
  117. package/build/dex/synthetix/synthetix.js.map +1 -1
  118. package/build/dex/test-dex/config.d.ts +4 -0
  119. package/build/dex/test-dex/config.js +15 -0
  120. package/build/dex/test-dex/config.js.map +1 -0
  121. package/build/dex/test-dex/test-dex-pool.d.ts +39 -0
  122. package/build/dex/test-dex/test-dex-pool.js +63 -0
  123. package/build/dex/test-dex/test-dex-pool.js.map +1 -0
  124. package/build/dex/test-dex/test-dex.d.ts +37 -0
  125. package/build/dex/test-dex/test-dex.js +126 -0
  126. package/build/dex/test-dex/test-dex.js.map +1 -0
  127. package/build/dex/test-dex/types.d.ts +6 -0
  128. package/build/dex/test-dex/types.js +3 -0
  129. package/build/dex/test-dex/types.js.map +1 -0
  130. package/build/dex/uniswap-v2/uniswap-v2.d.ts +2 -2
  131. package/build/dex/uniswap-v2/uniswap-v2.js +15 -10
  132. package/build/dex/uniswap-v2/uniswap-v2.js.map +1 -1
  133. package/build/dex/uniswap-v3/uniswap-v3-pool.d.ts +3 -3
  134. package/build/dex/uniswap-v3/uniswap-v3-pool.js +33 -27
  135. package/build/dex/uniswap-v3/uniswap-v3-pool.js.map +1 -1
  136. package/build/dex/uniswap-v3/uniswap-v3.d.ts +2 -2
  137. package/build/dex/uniswap-v3/uniswap-v3.js +4 -3
  138. package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
  139. package/build/dex/woo-fi-v2/woo-fi-math.d.ts +16 -0
  140. package/build/dex/woo-fi-v2/woo-fi-math.js +137 -0
  141. package/build/dex/woo-fi-v2/woo-fi-math.js.map +1 -0
  142. package/build/dex/woo-fi-v2/woo-fi-v2.d.ts +1 -1
  143. package/build/dex/woo-fi-v2/woo-fi-v2.js +1 -1
  144. package/build/dex/woo-fi-v2/woo-fi-v2.js.map +1 -1
  145. package/build/implementations/local-paraswap-sdk.js +1 -2
  146. package/build/implementations/local-paraswap-sdk.js.map +1 -1
  147. package/build/lib/generics-events-subscribers/erc20-event-subscriber.d.ts +2 -2
  148. package/build/lib/generics-events-subscribers/erc20-event-subscriber.js +17 -12
  149. package/build/lib/generics-events-subscribers/erc20-event-subscriber.js.map +1 -1
  150. package/build/lib/multi-wrapper.d.ts +5 -1
  151. package/build/lib/multi-wrapper.js +21 -2
  152. package/build/lib/multi-wrapper.js.map +1 -1
  153. package/build/lib/tokens/balancer-fetcher.d.ts +5 -1
  154. package/build/lib/tokens/balancer-fetcher.js +7 -9
  155. package/build/lib/tokens/balancer-fetcher.js.map +1 -1
  156. package/build/pricing-helper.d.ts +1 -1
  157. package/build/pricing-helper.js +1 -1
  158. package/build/pricing-helper.js.map +1 -1
  159. package/build/stateful-event-subscriber.d.ts +7 -3
  160. package/build/stateful-event-subscriber.js +25 -22
  161. package/build/stateful-event-subscriber.js.map +1 -1
  162. package/build/utils.d.ts +2 -2
  163. package/build/utils.js +1 -1
  164. package/build/utils.js.map +1 -1
  165. package/dex-template/__DexName__.ts.template +3 -1
  166. package/package.json +1 -1
  167. package/src/composed-event-subscriber.ts +24 -13
  168. package/src/dex/aave-v1/aave-v1.ts +1 -1
  169. package/src/dex/aave-v2/aave-v2.ts +1 -1
  170. package/src/dex/aave-v3/aave-v3.ts +3 -1
  171. package/src/dex/aave-v3/utils.ts +3 -3
  172. package/src/dex/balancer-v1/balancer-v1-pool.ts +18 -9
  173. package/src/dex/balancer-v1/balancer-v1.ts +13 -8
  174. package/src/dex/balancer-v1/utils.ts +36 -7
  175. package/src/dex/balancer-v2/balancer-v2.ts +42 -25
  176. package/src/dex/camelot/camelot.ts +29 -10
  177. package/src/dex/curve-v1/curve-v1.ts +11 -11
  178. package/src/dex/curve-v1/pools/curve-metapool.ts +23 -7
  179. package/src/dex/curve-v1/pools/curve-pool.ts +29 -8
  180. package/src/dex/curve-v1/pools/getstate-multicall.ts +83 -56
  181. package/src/dex/curve-v1-factory/curve-v1-factory.ts +4 -4
  182. package/src/dex/curve-v1-factory/curve-v1-pool-manager.ts +1 -1
  183. package/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts +1 -1
  184. package/src/dex/curve-v1-factory/state-polling-pools/factory-pool-polling.ts +1 -1
  185. package/src/dex/curve-v1-factory/state-polling-pools/polling-manager.ts +5 -16
  186. package/src/dex/curve-v1-factory/state-polling-pools/pool-polling-base.ts +1 -1
  187. package/src/dex/curve-v1-factory/types.ts +1 -1
  188. package/src/dex/generic-rfq/generic-rfq.ts +3 -1
  189. package/src/dex/generic-rfq/utils.ts +1 -1
  190. package/src/dex/gmx/gmx.ts +1 -1
  191. package/src/dex/gmx/pool.ts +9 -4
  192. package/src/dex/idex.ts +1 -1
  193. package/src/dex/jarvis-v6/jarvis-v6-events.ts +17 -6
  194. package/src/dex/jarvis-v6/jarvis-v6.ts +17 -15
  195. package/src/dex/jarvis-v6/utils.ts +21 -9
  196. package/src/dex/kyberdmm/kyberdmm.ts +4 -1
  197. package/src/dex/kyberdmm/pool.ts +32 -24
  198. package/src/dex/maker-psm/maker-psm.ts +69 -47
  199. package/src/dex/maverick-v1/maverick-v1-pool.ts +50 -38
  200. package/src/dex/maverick-v1/maverick-v1.ts +12 -8
  201. package/src/dex/nerve/nerve-pool.ts +42 -30
  202. package/src/dex/nerve/nerve.ts +9 -5
  203. package/src/dex/platypus/platypus.ts +11 -7
  204. package/src/dex/swaap-v1/config.ts +1 -1
  205. package/src/dex/swaap-v1/swaap-v1-pool.ts +23 -14
  206. package/src/dex/swaap-v1/swaap-v1.ts +21 -14
  207. package/src/dex/synthetix/synthetix-state.ts +3 -3
  208. package/src/dex/synthetix/synthetix.ts +5 -4
  209. package/src/dex/uniswap-v2/uniswap-v2.ts +27 -13
  210. package/src/dex/uniswap-v3/uniswap-v3-pool.ts +43 -39
  211. package/src/dex/uniswap-v3/uniswap-v3.ts +5 -4
  212. package/src/dex/woo-fi-v2/woo-fi-v2.ts +3 -1
  213. package/src/implementations/local-paraswap-sdk.ts +1 -2
  214. package/src/lib/generics-events-subscribers/erc20-event-subscriber.ts +29 -18
  215. package/src/lib/multi-wrapper.ts +41 -2
  216. package/src/lib/tokens/balancer-fetcher.ts +23 -19
  217. package/src/pricing-helper.ts +5 -2
  218. package/src/stateful-event-subscriber.ts +35 -28
  219. package/src/utils.ts +3 -4
  220. package/tests/utils.test.ts +44 -0
@@ -113,7 +113,7 @@ export class UniswapV3
113
113
  // To receive revert reasons
114
114
  this.dexHelper.web3Provider.eth.handleRevert = false;
115
115
 
116
- // Normalise once all config addresses and use across all scenarios
116
+ // Normalize once all config addresses and use across all scenarios
117
117
  this.config = this._toLowerForAllConfigAddresses();
118
118
 
119
119
  this.notExistingPoolSetKey =
@@ -133,7 +133,7 @@ export class UniswapV3
133
133
  return `${this.dexKey}_${tokenAddresses}_${fee}`;
134
134
  }
135
135
 
136
- async initializePricing(blockNumber: number) {
136
+ async initializePricing(blockNumber: number | 'latest' = 'latest') {
137
137
  // This is only for testing, because cold pool fetching is goes out of
138
138
  // FETCH_POOL_INDENTIFIER_TIMEOUT range
139
139
  await Promise.all(
@@ -168,7 +168,7 @@ export class UniswapV3
168
168
  srcAddress: Address,
169
169
  destAddress: Address,
170
170
  fee: bigint,
171
- blockNumber: number,
171
+ blockNumber: number | 'latest',
172
172
  ): Promise<UniswapV3EventPool | null> {
173
173
  let pool =
174
174
  this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)];
@@ -350,7 +350,8 @@ export class UniswapV3
350
350
  [],
351
351
  );
352
352
 
353
- const balances = await getBalances(this.dexHelper.multiWrapper, requests);
353
+ const balances = (await getBalances(this.dexHelper.multiWrapper, requests))
354
+ .balances;
354
355
 
355
356
  pools = pools.filter((pool, index) => {
356
357
  const balance = balances[index].amounts[DEFAULT_ID_ERC20_AS_STRING];
@@ -106,7 +106,9 @@ export class WooFiV2 extends SimpleExchange implements IDex<WooFiV2Data> {
106
106
  return this._baseTokens;
107
107
  }
108
108
 
109
- async initializePricing(blockNumber: number) {
109
+ async initializePricing(
110
+ blockNumber: number | 'latest' = 'latest',
111
+ ): Promise<void> {
110
112
  await this.initializeTokensAndAddresses();
111
113
  this._initializePollingPool();
112
114
  }
@@ -76,8 +76,7 @@ export class LocalParaswapSDK implements IParaSwapSDK {
76
76
  }
77
77
 
78
78
  async initializePricing() {
79
- const blockNumber = await this.dexHelper.web3Provider.eth.getBlockNumber();
80
- await this.pricingHelper.initialize(blockNumber, [this.dexKey]);
79
+ await this.pricingHelper.initialize('latest', [this.dexKey]);
81
80
  }
82
81
 
83
82
  async releaseResources() {
@@ -2,7 +2,10 @@ import _ from 'lodash';
2
2
  import { LogDescription } from '@ethersproject/abi';
3
3
  import { DeepReadonly } from 'ts-essentials';
4
4
  import { IDexHelper } from '../../dex-helper';
5
- import { StatefulEventSubscriber } from '../../stateful-event-subscriber';
5
+ import {
6
+ StatefulEventSubscriber,
7
+ StateWithBlock,
8
+ } from '../../stateful-event-subscriber';
6
9
  import { Log, BlockHeader, Address } from '../../types';
7
10
  import { erc20Iface } from '../utils-interfaces';
8
11
  import {
@@ -108,10 +111,12 @@ export class ERC20EventSubscriber extends StatefulEventSubscriber<ERC20StateMap>
108
111
  blockHeader: Readonly<BlockHeader>,
109
112
  ): Promise<DeepReadonly<ERC20StateMap> | null> {
110
113
  const _state = _.cloneDeep(state);
111
- let newState = await super.processBlockLogs(_state, logs, blockHeader);
114
+ const newState = await super.processBlockLogs(_state, logs, blockHeader);
112
115
  if (!newState) {
113
116
  this.logger.warn('received empty state generate new one');
114
- newState = await this.generateState(blockHeader.number);
117
+ const newStateWithBn = await this.generateState('latest');
118
+ this.setState(newStateWithBn.state, newStateWithBn.blockNumber);
119
+ return newStateWithBn.state;
115
120
  }
116
121
 
117
122
  return newState;
@@ -153,7 +158,7 @@ export class ERC20EventSubscriber extends StatefulEventSubscriber<ERC20StateMap>
153
158
  blockNumber,
154
159
  );
155
160
 
156
- return balances[0];
161
+ return balances.balances[0];
157
162
  }
158
163
 
159
164
  async subscribeToWalletBalanceChange(
@@ -185,7 +190,9 @@ export class ERC20EventSubscriber extends StatefulEventSubscriber<ERC20StateMap>
185
190
  this.setState(state, blockNumber);
186
191
  }
187
192
 
188
- async generateState(blockNumber: number): Promise<Readonly<ERC20StateMap>> {
193
+ async generateState(
194
+ blockNumber: number | 'latest',
195
+ ): Promise<StateWithBlock<ERC20StateMap>> {
189
196
  const request = Array.from(this.walletAddresses).reduce((acc, wallet) => {
190
197
  acc.push({
191
198
  owner: wallet,
@@ -202,22 +209,26 @@ export class ERC20EventSubscriber extends StatefulEventSubscriber<ERC20StateMap>
202
209
  return acc;
203
210
  }, [] as BalanceRequest[]);
204
211
 
205
- const balances = await getBalances(
212
+ const balancesAndBn = await getBalances(
206
213
  this.dexHelper.multiWrapper,
207
214
  request,
208
215
  blockNumber,
209
216
  );
210
- return balances.reduce((acc, balance) => {
211
- acc[balance.owner] = {
212
- balance: balance.amounts[DEFAULT_ID_ERC20_AS_STRING],
213
- };
214
- this.dexHelper.cache.hset(
215
- this.mapKey,
216
- balance.owner,
217
- balance.amounts[DEFAULT_ID_ERC20_AS_STRING].toString(),
218
- );
219
- return acc;
220
- }, {} as ERC20StateMap);
217
+ return {
218
+ blockNumber: balancesAndBn.blockNumber,
219
+
220
+ state: balancesAndBn.balances.reduce((acc, balance) => {
221
+ acc[balance.owner] = {
222
+ balance: balance.amounts[DEFAULT_ID_ERC20_AS_STRING],
223
+ };
224
+ this.dexHelper.cache.hset(
225
+ this.mapKey,
226
+ balance.owner,
227
+ balance.amounts[DEFAULT_ID_ERC20_AS_STRING].toString(),
228
+ );
229
+ return acc;
230
+ }, {} as ERC20StateMap),
231
+ };
221
232
  }
222
233
 
223
234
  async getBalance(wallet: Address, blockNumber: number): Promise<bigint> {
@@ -249,7 +260,7 @@ export class ERC20EventSubscriber extends StatefulEventSubscriber<ERC20StateMap>
249
260
  );
250
261
  const balance = await this.getBalanceRPC(wallet, blockNumber);
251
262
 
252
- // this is ok because we don't modify readonly data
263
+ // this is not ok because blockNumber might differ from subscriber blockNumber
253
264
  state[wallet] = {
254
265
  balance: balance.amounts[DEFAULT_ID_ERC20_AS_STRING],
255
266
  };
@@ -2,6 +2,7 @@ import { BytesLike } from 'ethers';
2
2
  import _ from 'lodash';
3
3
  import { Logger } from 'log4js';
4
4
  import { Contract } from 'web3-eth-contract';
5
+ import { uint256DecodeToNumber } from './decoders';
5
6
 
6
7
  export type MultiResult<T> = {
7
8
  success: boolean;
@@ -54,10 +55,12 @@ export class MultiWrapper {
54
55
  async tryAggregate<T>(
55
56
  mandatory: boolean,
56
57
  calls: MultiCallParams<T>[],
57
- blockNumber?: number | string,
58
+ blockNumber: number | 'latest' = 'latest',
58
59
  batchSize: number = this.defaultBatchSize,
59
60
  reportFails: boolean = true,
60
61
  ): Promise<MultiResult<T>[]> {
62
+ const _blockNumber = blockNumber === undefined ? 'latest' : blockNumber;
63
+
61
64
  const allCalls = new Array(Math.ceil(calls.length / batchSize));
62
65
  for (let i = 0; i < calls.length; i += batchSize) {
63
66
  const batch = calls.slice(i, i + batchSize);
@@ -68,7 +71,7 @@ export class MultiWrapper {
68
71
  allCalls.map(batch =>
69
72
  this.multi.methods
70
73
  .tryAggregate(mandatory, batch)
71
- .call(undefined, blockNumber),
74
+ .call(undefined, _blockNumber),
72
75
  ),
73
76
  );
74
77
 
@@ -105,4 +108,40 @@ export class MultiWrapper {
105
108
 
106
109
  return results;
107
110
  }
111
+
112
+ // I removed here batching because it may give inconsistent blockNumber
113
+ // If we see that is a problem, we can add later
114
+ async blockTryAggregateWithoutBatching<T>(
115
+ mandatory: boolean,
116
+ calls: MultiCallParams<T>[],
117
+ requestedBlockNumber: number | 'latest' = 'latest',
118
+ reportFails: boolean = true,
119
+ ) {
120
+ const blockNumberCall: MultiCallParams<number> = {
121
+ target: this.multi.options.address,
122
+ callData: this.multi.methods.getBlockNumber().encodeABI() as string,
123
+ decodeFunction: uint256DecodeToNumber,
124
+ };
125
+
126
+ const callsWithBlockNumber: [
127
+ ...MultiCallParams<T>[],
128
+ MultiCallParams<number>,
129
+ ] = [...calls, blockNumberCall];
130
+
131
+ const results = await this.tryAggregate(
132
+ mandatory,
133
+ callsWithBlockNumber as MultiCallParams<T | number>[],
134
+ requestedBlockNumber,
135
+ callsWithBlockNumber.length,
136
+ reportFails,
137
+ );
138
+
139
+ // We guaranteed previously that at least one call is contained
140
+ const blockNumber = results.pop()!.returnData as number;
141
+
142
+ return {
143
+ blockNumber,
144
+ results: results as MultiResult<T>[],
145
+ };
146
+ }
108
147
  }
@@ -135,11 +135,6 @@ export const getAllowanceCallParams = (
135
135
  }
136
136
  default:
137
137
  throw new Error(`missing case for assetType ${req.assetType}`);
138
- return {
139
- calls: [],
140
- spenders: new Set(),
141
- length: 0,
142
- };
143
138
  }
144
139
  };
145
140
 
@@ -241,11 +236,16 @@ export const decodeBalanceAndAllowanceMultiResult = (
241
236
  return userBalance;
242
237
  };
243
238
 
239
+ type getBalancesResult = {
240
+ blockNumber: number;
241
+ balances: UserBalance[];
242
+ };
243
+
244
244
  export const getBalances = async (
245
245
  multiv2: MultiWrapper,
246
246
  reqs: BalanceRequest[],
247
247
  blockNumber: number | 'latest' = 'latest',
248
- ): Promise<UserBalance[]> => {
248
+ ): Promise<getBalancesResult> => {
249
249
  const calls: MultiCallParams<MultiCallParamsType>[] = []; // TODO: compute the size on advance
250
250
 
251
251
  const decodingInfo: MultiCallResultDecodeInfo[] = [];
@@ -257,27 +257,31 @@ export const getBalances = async (
257
257
  params.length += balancesCalls.length;
258
258
  decodingInfo.push(params);
259
259
  }
260
- const results = await multiv2.tryAggregate<MultiCallParamsType>(
261
- false,
262
- calls,
263
- blockNumber,
264
- );
260
+ const resultsAndBn =
261
+ await multiv2.blockTryAggregateWithoutBatching<MultiCallParamsType>(
262
+ false,
263
+ calls,
264
+ blockNumber,
265
+ );
265
266
 
266
267
  const chunks = [];
267
268
  let j = 0;
268
- for (let i = 0; i < results.length; ) {
269
+ for (let i = 0; i < resultsAndBn.results.length; ) {
269
270
  const batchSize = decodingInfo[j].length;
270
- const chunk = results.slice(i, i + batchSize);
271
+ const chunk = resultsAndBn.results.slice(i, i + batchSize);
271
272
  chunks.push(chunk);
272
273
  j++;
273
274
  i += batchSize;
274
275
  }
275
276
 
276
- return chunks.map((chunk, index) =>
277
- decodeBalanceAndAllowanceMultiResult(
278
- reqs[index],
279
- decodingInfo[index].spenders,
280
- chunk,
277
+ return {
278
+ blockNumber: resultsAndBn.blockNumber,
279
+ balances: chunks.map((chunk, index) =>
280
+ decodeBalanceAndAllowanceMultiResult(
281
+ reqs[index],
282
+ decodingInfo[index].spenders,
283
+ chunk,
284
+ ),
281
285
  ),
282
- );
286
+ };
283
287
  };
@@ -36,7 +36,10 @@ export class PricingHelper {
36
36
  );
37
37
  }
38
38
 
39
- private async initializeDex(dexKey: string, blockNumber: number) {
39
+ private async initializeDex(
40
+ dexKey: string,
41
+ blockNumber: number | 'latest' = 'latest',
42
+ ) {
40
43
  try {
41
44
  const dexInstance = this.dexAdapterService.getDexByKey(dexKey);
42
45
 
@@ -80,7 +83,7 @@ export class PricingHelper {
80
83
  }
81
84
  }
82
85
 
83
- public async initialize(blockNumber: number, dexKeys: string[]) {
86
+ public async initialize(blockNumber: number | 'latest', dexKeys: string[]) {
84
87
  return await Promise.all(
85
88
  dexKeys.map(key => this.initializeDex(key, blockNumber)),
86
89
  );
@@ -15,8 +15,13 @@ type StateCache<State> = {
15
15
  state: DeepReadonly<State>;
16
16
  };
17
17
 
18
+ export type StateWithBlock<State> = {
19
+ state: DeepReadonly<State>;
20
+ blockNumber: number;
21
+ };
22
+
18
23
  export type InitializeStateOptions<State> = {
19
- state?: DeepReadonly<State>;
24
+ stateWithBn?: StateWithBlock<State>;
20
25
  initCallback?: (state: DeepReadonly<State>) => void;
21
26
  };
22
27
 
@@ -83,12 +88,13 @@ export abstract class StatefulEventSubscriber<State>
83
88
  // will also publish a message to cache to tell one master version of dex-lib that this slave
84
89
  // instance subscribed to a pool from dex this.parentName and name this.name.
85
90
  async initialize(
86
- blockNumber: number,
91
+ blockNumber: number | 'latest',
87
92
  options?: InitializeStateOptions<State>,
88
93
  ) {
89
94
  let masterBn: undefined | number = undefined;
90
- if (options && options.state) {
91
- this.setState(options.state, blockNumber);
95
+ if (options && options.stateWithBn) {
96
+ this.setState(options.stateWithBn.state, options.stateWithBn.blockNumber);
97
+ masterBn = options.stateWithBn.blockNumber;
92
98
  } else {
93
99
  if (this.dexHelper.config.isSlave && this.masterPoolNeeded) {
94
100
  let stateAsString = await this.dexHelper.cache.hget(
@@ -104,37 +110,39 @@ export abstract class StatefulEventSubscriber<State>
104
110
  this.logger.warn(
105
111
  `${this.parentName}: ${this.name}: found null state in cache generate new one`,
106
112
  );
107
- state.state = await this.generateState(blockNumber);
113
+ const stateAndBn = await this.generateState(blockNumber);
114
+
115
+ state.state = stateAndBn.state;
116
+ state.bn = stateAndBn.blockNumber;
117
+ masterBn = state.bn;
118
+ this.setState(state.state, state.bn);
108
119
  } else {
109
- this.logger.info(
120
+ this.logger.trace(
110
121
  `${this.parentName}: ${this.name}: found state from cache`,
111
122
  );
112
- blockNumber = state.bn;
113
-
114
123
  const _masterBn = await this.dexHelper.cache.rawget(
115
124
  this.dexHelper.config.masterBlockNumberCacheKey,
116
125
  );
117
126
  if (_masterBn) {
118
127
  masterBn = parseInt(_masterBn, 10);
119
- this.logger.info(
120
- `${this.dexHelper.config.data.network} found master blockNumber ${blockNumber}`,
128
+ this.logger.trace(
129
+ `${this.dexHelper.config.data.network} found master blockNumber ${masterBn}`,
121
130
  );
131
+ this.setState(state.state, state.bn);
122
132
  } else {
123
- this.logger.error(
133
+ throw new Error(
124
134
  `${this.dexHelper.config.data.network} did not found blockNumber in cache`,
125
135
  );
126
136
  }
127
137
  }
128
- // set state and the according blockNumber. state.bn can be smaller, greater or equal
129
- // to blockNumber
130
- this.setState(state.state, blockNumber);
131
138
  } else {
132
139
  // if no state found in cache generate new state using rpc
133
140
  this.logger.info(
134
141
  `${this.parentName}: ${this.name}: did not found state on cache generating new one`,
135
142
  );
136
- const state = await this.generateState(blockNumber);
137
- this.setState(state, blockNumber);
143
+ const stateAndBn = await this.generateState(blockNumber);
144
+ masterBn = stateAndBn.blockNumber;
145
+ this.setState(stateAndBn.state, stateAndBn.blockNumber);
138
146
 
139
147
  // we should publish only if generateState succeeded
140
148
  this.dexHelper.cache.publish('new_pools', this.cacheName);
@@ -144,8 +152,9 @@ export abstract class StatefulEventSubscriber<State>
144
152
  this.logger.info(
145
153
  `${this.parentName}: ${this.name}: cache generating state`,
146
154
  );
147
- const state = await this.generateState(blockNumber);
148
- this.setState(state, blockNumber);
155
+ const stateAndBn = await this.generateState(blockNumber);
156
+ masterBn = stateAndBn.blockNumber;
157
+ this.setState(stateAndBn.state, stateAndBn.blockNumber);
149
158
  }
150
159
  }
151
160
 
@@ -160,7 +169,7 @@ export abstract class StatefulEventSubscriber<State>
160
169
  this.dexHelper.blockManager.subscribeToLogs(
161
170
  this,
162
171
  this.addressesSubscribed,
163
- masterBn || blockNumber,
172
+ masterBn,
164
173
  );
165
174
  this.isInitialized = true;
166
175
  }
@@ -203,7 +212,7 @@ export abstract class StatefulEventSubscriber<State>
203
212
  //generate one from scratch.
204
213
  abstract generateState(
205
214
  blockNumber?: number | 'latest',
206
- ): AsyncOrSync<DeepReadonly<State>>;
215
+ ): AsyncOrSync<StateWithBlock<State>>;
207
216
 
208
217
  restart(blockNumber: number): void {
209
218
  for (const _bn of Object.keys(this.stateHistory)) {
@@ -251,8 +260,8 @@ export abstract class StatefulEventSubscriber<State>
251
260
  ++indexBlockEnd;
252
261
  }
253
262
  if (!this.state) {
254
- const freshState = await this.generateState(blockNumber);
255
- this.setState(freshState, blockNumber);
263
+ const freshStateAndBn = await this.generateState('latest');
264
+ this.setState(freshStateAndBn.state, freshStateAndBn.blockNumber);
256
265
  }
257
266
  //Find the last state before the blockNumber of the logs
258
267
  let stateBeforeLog: DeepReadonly<State> | undefined;
@@ -285,18 +294,16 @@ export abstract class StatefulEventSubscriber<State>
285
294
  if (this.state !== null) {
286
295
  return true;
287
296
  }
288
- const latestBlockNumber =
289
- this.dexHelper.blockManager.getLatestBlockNumber();
290
297
  this.logger.warn(
291
- `${network}: ${this.parentName}: ${this.name}: master generate (latest: ${latestBlockNumber}) new state because state is null`,
298
+ `${network}: ${this.parentName}: ${this.name}: master generate (latest) new state because state is null`,
292
299
  );
293
300
  try {
294
- const state = await this.generateState(latestBlockNumber);
295
- this.setState(state, latestBlockNumber);
301
+ const stateAndBn = await this.generateState('latest');
302
+ this.setState(stateAndBn.state, stateAndBn.blockNumber);
296
303
  return true;
297
304
  } catch (e) {
298
305
  this.logger.error(
299
- `${network}: ${this.parentName} ${this.name}: (${latestBlockNumber}) failed fetch state:`,
306
+ `${network}: ${this.parentName} ${this.name}: (latest) failed fetch state:`,
300
307
  e,
301
308
  );
302
309
  }
package/src/utils.ts CHANGED
@@ -319,7 +319,7 @@ export class Utils {
319
319
  ): Promise<T> {
320
320
  return Promise.race([
321
321
  promise,
322
- new Promise<T>((resolve, reject) => {
322
+ new Promise<T>((_, reject) => {
323
323
  setTimeout(() => reject(message), timeout);
324
324
  }),
325
325
  ]);
@@ -353,8 +353,8 @@ export const isTruthy = <T>(x: T | undefined | null | '' | false | 0): x is T =>
353
353
  !!x;
354
354
 
355
355
  type MultiCallParams = {
356
- target: any;
357
- callData: any;
356
+ target: string;
357
+ callData: string;
358
358
  };
359
359
 
360
360
  type BlockAndTryAggregateResult = {
@@ -383,6 +383,5 @@ export const blockAndTryAggregate = async (
383
383
 
384
384
  export const isContractAddress = async (web3: Web3, addr: string) => {
385
385
  const contractCode = await web3.eth.getCode(addr);
386
-
387
386
  return contractCode !== '0x';
388
387
  };
@@ -0,0 +1,44 @@
1
+ import dotenv from 'dotenv';
2
+ dotenv.config();
3
+
4
+ import Web3 from 'web3';
5
+ import { AbiItem } from 'web3-utils';
6
+ import MultiAbi from '../src/abi/multi-v2.json';
7
+ import { generateConfig } from '../src/config';
8
+ import { Network } from '../src/constants';
9
+ import { getBalanceERC20 } from '../src/lib/tokens/utils';
10
+ import { blockAndTryAggregate } from '../src/utils';
11
+
12
+ describe('MultiCall with blockNumber', () => {
13
+ const config = generateConfig(Network.MAINNET);
14
+
15
+ const web3 = new Web3(config.privateHttpProvider);
16
+ const multiContract = new web3.eth.Contract(
17
+ MultiAbi as AbiItem[],
18
+ config.multicallV2Address,
19
+ );
20
+
21
+ it('MultiCall with blockNumber', async () => {
22
+ const res = await blockAndTryAggregate(
23
+ true,
24
+ multiContract,
25
+ [
26
+ {
27
+ target: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
28
+ callData: getBalanceERC20(
29
+ '0x05182e579fdfcf69e4390c3411d8fea1fb6467cf',
30
+ ),
31
+ },
32
+ {
33
+ target: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
34
+ callData: getBalanceERC20(
35
+ '0x05182e579fdfcf69e4390c3411d8fea1fb6467cf',
36
+ ),
37
+ },
38
+ ],
39
+ 'latest',
40
+ );
41
+
42
+ console.log(res);
43
+ });
44
+ });