@paraswap/dex-lib 2.14.0 → 2.14.1

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 (64) hide show
  1. package/build/config.js +23 -5
  2. package/build/config.js.map +1 -1
  3. package/build/dex/index.js +2 -2
  4. package/build/dex/index.js.map +1 -1
  5. package/build/dex/simple-exchange.d.ts +1 -0
  6. package/build/dex/simple-exchange.js +2 -0
  7. package/build/dex/simple-exchange.js.map +1 -1
  8. package/build/lib/decoders.d.ts +2 -1
  9. package/build/lib/decoders.js +8 -1
  10. package/build/lib/decoders.js.map +1 -1
  11. package/build/lib/multi-wrapper.d.ts +2 -1
  12. package/build/lib/multi-wrapper.js.map +1 -1
  13. package/build/lib/tokens/balancer-fetcher.js +4 -5
  14. package/build/lib/tokens/balancer-fetcher.js.map +1 -1
  15. package/build/lib/tokens/utils.d.ts +2 -2
  16. package/build/lib/tokens/utils.js +1 -1
  17. package/build/lib/tokens/utils.js.map +1 -1
  18. package/build/types.d.ts +3 -0
  19. package/dex-template/__DexName__-e2e.test.ts.template +1 -0
  20. package/dex-template/__DexName__-events.test.ts.template +1 -0
  21. package/dex-template/__DexName__-integration.test.ts.template +1 -0
  22. package/dex-template/__DexName__-pool.ts.template +8 -5
  23. package/package.json +1 -1
  24. package/scripts/generate-bytecode.ts +2 -0
  25. package/src/abi/woo-fi-v2/IntegrationHelper.abi.json +116 -0
  26. package/src/abi/{woo-fi/Wooracle.abi.json → woo-fi-v2/WooOracleV2.abi.json} +148 -50
  27. package/src/abi/{woo-fi/WooPP.abi.json → woo-fi-v2/WooPPV2.abi.json} +201 -169
  28. package/src/config.ts +27 -5
  29. package/src/dex/balancer-v2/balancer-v2-e2e.test.ts +0 -1
  30. package/src/dex/index.ts +2 -2
  31. package/src/dex/simple-exchange.ts +3 -0
  32. package/src/dex/woo-fi-v2/config.ts +87 -0
  33. package/src/dex/woo-fi-v2/constants.ts +22 -0
  34. package/src/dex/woo-fi-v2/decoders.ts +45 -0
  35. package/src/dex/woo-fi-v2/types.ts +63 -0
  36. package/src/dex/woo-fi-v2/utils.ts +19 -0
  37. package/src/dex/woo-fi-v2/woo-fi-v2-e2e.test.ts +216 -0
  38. package/src/dex/woo-fi-v2/woo-fi-v2-integration.test.ts +495 -0
  39. package/src/dex/woo-fi-v2/woo-fi-v2-math.ts +195 -0
  40. package/src/dex/woo-fi-v2/woo-fi-v2-pool.ts +112 -0
  41. package/src/dex/woo-fi-v2/woo-fi-v2.ts +487 -0
  42. package/src/lib/decoders.ts +12 -1
  43. package/src/lib/log-messages-suppressor.ts +173 -0
  44. package/src/lib/multi-wrapper.ts +2 -1
  45. package/src/lib/stateful-rpc-poller/state-polling-manager.ts +320 -0
  46. package/src/lib/stateful-rpc-poller/stateful-rpc-poller.ts +604 -0
  47. package/src/lib/stateful-rpc-poller/types.ts +66 -0
  48. package/src/lib/stateful-rpc-poller/utils.ts +23 -0
  49. package/src/lib/tokens/balancer-fetcher.ts +5 -6
  50. package/src/lib/tokens/utils.ts +5 -3
  51. package/src/types.ts +4 -0
  52. package/tests/constants-e2e.ts +8 -3
  53. package/tests/tenderly-simulation.ts +1 -1
  54. package/tests/utils-e2e.ts +2 -0
  55. package/tests/utils.ts +2 -0
  56. package/src/abi/woo-fi/WooFeeManager.abi.json +0 -318
  57. package/src/dex/woo-fi/config.ts +0 -141
  58. package/src/dex/woo-fi/constants.ts +0 -21
  59. package/src/dex/woo-fi/types.ts +0 -55
  60. package/src/dex/woo-fi/woo-fi-decimal-math.ts +0 -45
  61. package/src/dex/woo-fi/woo-fi-e2e.test.ts +0 -183
  62. package/src/dex/woo-fi/woo-fi-integration.test.ts +0 -416
  63. package/src/dex/woo-fi/woo-fi-math.ts +0 -527
  64. package/src/dex/woo-fi/woo-fi.ts +0 -693
package/src/config.ts CHANGED
@@ -25,6 +25,8 @@ type BaseConfig = {
25
25
  uniswapV2ExchangeRouterAddress: Address;
26
26
  uniswapV3EventLoggingSampleRate?: number;
27
27
  rfqConfigs: Record<string, RFQConfig>;
28
+ rpcPollingMaxAllowedStateDelayInBlocks: number;
29
+ rpcPollingBlocksBackToTriggerUpdate: number;
28
30
  hashFlowAuthToken?: string;
29
31
  hashFlowDisabledMMs: string[];
30
32
  };
@@ -52,6 +54,8 @@ const baseConfigs: { [network: number]: BaseConfig } = {
52
54
  },
53
55
  uniswapV2ExchangeRouterAddress:
54
56
  '0xF9234CB08edb93c0d4a4d4c70cC3FfD070e78e07',
57
+ rpcPollingMaxAllowedStateDelayInBlocks: 0,
58
+ rpcPollingBlocksBackToTriggerUpdate: 0,
55
59
  hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN,
56
60
  hashFlowDisabledMMs:
57
61
  process.env[`HASHFLOW_DISABLED_MMS_1`]?.split(',') || [],
@@ -134,6 +138,8 @@ const baseConfigs: { [network: number]: BaseConfig } = {
134
138
  uniswapV2ExchangeRouterAddress:
135
139
  '0x53e693c6C7FFC4446c53B205Cf513105Bf140D7b',
136
140
  rfqConfigs: {},
141
+ rpcPollingMaxAllowedStateDelayInBlocks: 5,
142
+ rpcPollingBlocksBackToTriggerUpdate: 3,
137
143
  },
138
144
  [Network.BSC]: {
139
145
  network: Network.BSC,
@@ -155,6 +161,8 @@ const baseConfigs: { [network: number]: BaseConfig } = {
155
161
  BscAdapter02: '0xe102429Ef7CAaBaAA3bc2C017aC784c5F665EE82',
156
162
  BscBuyAdapter: '0xA7f4fBCEB76a1B1c05C106a4289C28B3b91C17ca',
157
163
  },
164
+ rpcPollingMaxAllowedStateDelayInBlocks: 1,
165
+ rpcPollingBlocksBackToTriggerUpdate: 1,
158
166
  uniswapV2ExchangeRouterAddress:
159
167
  '0x53e693c6C7FFC4446c53B205Cf513105Bf140D7b',
160
168
  rfqConfigs: {},
@@ -177,13 +185,15 @@ const baseConfigs: { [network: number]: BaseConfig } = {
177
185
  process.env[`HASHFLOW_DISABLED_MMS_137`]?.split(',') || [],
178
186
  adapterAddresses: {
179
187
  PolygonAdapter01: '0xE44769f42E1e9592f86B82f206407a8f7C84b4ed',
180
- PolygonAdapter02: '0x72C851edA05915F4cbbeF27E3AFd3Bc87F86b001',
188
+ PolygonAdapter02: '0xfb2a3de6c7B8c77b520E3da16021f3D8A4E93168',
181
189
  PolygonBuyAdapter: '0xbE36ddfCDB6D60c1B20FfD73594540E5cc2c7E97',
182
190
  },
183
191
  uniswapV2ExchangeRouterAddress:
184
192
  '0xf3938337F7294fEf84e9B2c6D548A93F956Cc281',
185
193
  uniswapV3EventLoggingSampleRate: 0,
186
194
  rfqConfigs: {},
195
+ rpcPollingMaxAllowedStateDelayInBlocks: 2,
196
+ rpcPollingBlocksBackToTriggerUpdate: 1,
187
197
  },
188
198
  [Network.AVALANCHE]: {
189
199
  network: Network.AVALANCHE,
@@ -202,13 +212,15 @@ const baseConfigs: { [network: number]: BaseConfig } = {
202
212
  hashFlowDisabledMMs:
203
213
  process.env[`HASHFLOW_DISABLED_MMS_43114`]?.split(',') || [],
204
214
  adapterAddresses: {
205
- AvalancheAdapter01: '0x5b99094C3c2129F17b78cE5eBD1Cd8ADB887b340',
215
+ AvalancheAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9',
206
216
  AvalancheAdapter02: '0x3fd845dE49eBa45565d3b58CDEbf88d9bdA7aBf6',
207
217
  AvalancheBuyAdapter: '0xad2f7039B0F4c410654886D049ae8406F5aDe709',
208
218
  },
209
219
  uniswapV2ExchangeRouterAddress:
210
220
  '0x53e693c6C7FFC4446c53B205Cf513105Bf140D7b',
211
221
  rfqConfigs: {},
222
+ rpcPollingMaxAllowedStateDelayInBlocks: 2,
223
+ rpcPollingBlocksBackToTriggerUpdate: 1,
212
224
  },
213
225
  [Network.FANTOM]: {
214
226
  network: Network.FANTOM,
@@ -228,12 +240,14 @@ const baseConfigs: { [network: number]: BaseConfig } = {
228
240
  process.env[`HASHFLOW_DISABLED_MMS_250`]?.split(',') || [],
229
241
 
230
242
  adapterAddresses: {
231
- FantomAdapter01: '0xD9026Ca611EEC89dd4030ae86953F2d8D899535c',
243
+ FantomAdapter01: '0x66152A2a538644Ae125570De522ADEaC9E41D865',
232
244
  FantomBuyAdapter: '0x27eb327B7255a2bF666EBB4D60AB4752dA4611b9',
233
245
  },
234
246
  uniswapV2ExchangeRouterAddress:
235
247
  '0xAB86e2bC9ec5485a9b60E684BA6d49bf4686ACC2',
236
248
  rfqConfigs: {},
249
+ rpcPollingMaxAllowedStateDelayInBlocks: 2,
250
+ rpcPollingBlocksBackToTriggerUpdate: 1,
237
251
  },
238
252
  [Network.ARBITRUM]: {
239
253
  network: Network.ARBITRUM,
@@ -253,13 +267,15 @@ const baseConfigs: { [network: number]: BaseConfig } = {
253
267
  process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [],
254
268
  adapterAddresses: {
255
269
  ArbitrumAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9',
256
- ArbitrumAdapter02: '0xa003dFBA51C9e1e56C67ae445b852bdEd7aC5EEd',
270
+ ArbitrumAdapter02: '0xCBaeB06C2dF373c07A2Dc205266EC3bCd525DfB6',
257
271
  ArbitrumBuyAdapter: '0xfa072107a2CCfE5664794282EF36400735ABB70F',
258
272
  },
259
273
  uniswapV2ExchangeRouterAddress:
260
274
  '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC',
261
275
  uniswapV3EventLoggingSampleRate: 0,
262
276
  rfqConfigs: {},
277
+ rpcPollingMaxAllowedStateDelayInBlocks: 4,
278
+ rpcPollingBlocksBackToTriggerUpdate: 3,
263
279
  },
264
280
  [Network.OPTIMISM]: {
265
281
  network: Network.OPTIMISM,
@@ -279,13 +295,15 @@ const baseConfigs: { [network: number]: BaseConfig } = {
279
295
  process.env[`HASHFLOW_DISABLED_MMS_10`]?.split(',') || [],
280
296
 
281
297
  adapterAddresses: {
282
- OptimismAdapter01: '0xB6EBBB9f9957556Fd798927ae7c250759a235407',
298
+ OptimismAdapter01: '0x4669D27A649f5451e0D44C20a2b246431F1B0572',
283
299
  OptimismBuyAdapter: '0x4Ae8ad57912e207f5bFaFbF2e90486e5feab1634',
284
300
  },
285
301
  uniswapV2ExchangeRouterAddress:
286
302
  '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC',
287
303
  uniswapV3EventLoggingSampleRate: 0,
288
304
  rfqConfigs: {},
305
+ rpcPollingMaxAllowedStateDelayInBlocks: 5,
306
+ rpcPollingBlocksBackToTriggerUpdate: 3,
289
307
  },
290
308
  };
291
309
 
@@ -322,6 +340,10 @@ export function generateConfig(network: number): Config {
322
340
  uniswapV2ExchangeRouterAddress: baseConfig.uniswapV2ExchangeRouterAddress,
323
341
  uniswapV3EventLoggingSampleRate: baseConfig.uniswapV3EventLoggingSampleRate,
324
342
  rfqConfigs: baseConfig.rfqConfigs,
343
+ rpcPollingMaxAllowedStateDelayInBlocks:
344
+ baseConfig.rpcPollingMaxAllowedStateDelayInBlocks,
345
+ rpcPollingBlocksBackToTriggerUpdate:
346
+ baseConfig.rpcPollingBlocksBackToTriggerUpdate,
325
347
  hashFlowAuthToken: baseConfig.hashFlowAuthToken,
326
348
  hashFlowDisabledMMs: baseConfig.hashFlowDisabledMMs,
327
349
  };
@@ -78,7 +78,6 @@ describe('BalancerV2 E2E', () => {
78
78
  });
79
79
 
80
80
  describe('Simpleswap', () => {
81
-
82
81
  it('ETH -> TOKEN', async () => {
83
82
  await testE2E(
84
83
  tokens['ETH'],
package/src/dex/index.ts CHANGED
@@ -38,7 +38,7 @@ import { MakerPsm } from './maker-psm/maker-psm';
38
38
  import { KyberDmm } from './kyberdmm/kyberdmm';
39
39
  import { Platypus } from './platypus/platypus';
40
40
  import { GMX } from './gmx/gmx';
41
- // import { WooFi } from './woo-fi/woo-fi';
41
+ import { WooFiV2 } from './woo-fi-v2/woo-fi-v2';
42
42
  import { ParaSwapLimitOrders } from './paraswap-limit-orders/paraswap-limit-orders';
43
43
  import { AugustusRFQOrder } from './augustus-rfq';
44
44
  import { Solidly } from './solidly/solidly';
@@ -107,7 +107,7 @@ const Dexes = [
107
107
  Platypus,
108
108
  GMX,
109
109
  JarvisV6,
110
- // WooFi,
110
+ WooFiV2,
111
111
  ParaSwapLimitOrders,
112
112
  Solidly,
113
113
  SolidlyEthereum,
@@ -4,6 +4,7 @@ import { Address, SimpleExchangeParam, NumberAsString } from '../types';
4
4
  import { CACHE_PREFIX, ETHER_ADDRESS } from '../constants';
5
5
  import SimpleSwapHelperABI from '../abi/SimpleSwapHelperRouter.json';
6
6
  import ERC20ABI from '../abi/erc20.json';
7
+ import augustusABI from '../abi/augustus.json';
7
8
  import { isETHAddress } from '../utils';
8
9
  import { MAX_UINT } from '../constants';
9
10
  import Web3 from 'web3';
@@ -18,6 +19,7 @@ export class SimpleExchange {
18
19
  isFeeOnTransferSupported = false;
19
20
 
20
21
  protected augustusAddress: Address;
22
+ protected augustusInterface: Interface;
21
23
  private provider: Web3;
22
24
 
23
25
  protected network: number;
@@ -32,6 +34,7 @@ export class SimpleExchange {
32
34
 
33
35
  this.network = dexHelper.config.data.network;
34
36
  this.augustusAddress = dexHelper.config.data.augustusAddress;
37
+ this.augustusInterface = new Interface(augustusABI);
35
38
  this.provider = dexHelper.web3Provider;
36
39
 
37
40
  this.dexmapKey =
@@ -0,0 +1,87 @@
1
+ import { DexParams } from './types';
2
+ import { DexConfigMap, AdapterMappings } from '../../types';
3
+ import { Network, SwapSide } from '../../constants';
4
+
5
+ export const WooFiV2Config: DexConfigMap<DexParams> = {
6
+ WooFiV2: {
7
+ [Network.OPTIMISM]: {
8
+ wooPPV2Address: '0xd1778F9DF3eee5473A9640f13682e3846f61fEbC',
9
+ wooOracleV2Address: '0x464959aD46e64046B891F562cFF202a465D522F3',
10
+ integrationHelperAddress: '0x96329d66074EB8386Ae8bFD6698B2E3FDA87e15E',
11
+ // USDC
12
+ quoteToken: {
13
+ address: '0x7F5c764cBc14f9669B88837ca1490cCa17c31607',
14
+ decimals: 6,
15
+ },
16
+ },
17
+ [Network.BSC]: {
18
+ wooPPV2Address: '0xEc054126922a9a1918435c9072c32f1B60cB2B90',
19
+ wooOracleV2Address: '0x747f99D619D5612399010Ec5706F13e3345c4a9E',
20
+ integrationHelperAddress: '0xe12dC1F01ccB71ef00ADd1D8A5116b905261D879',
21
+ // BUSD
22
+ quoteToken: {
23
+ address: '0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56',
24
+ decimals: 18,
25
+ },
26
+ },
27
+ [Network.POLYGON]: {
28
+ wooPPV2Address: '0x7081A38158BD050Ae4a86e38E0225Bc281887d7E',
29
+ wooOracleV2Address: '0xeFF23B4bE1091b53205E35f3AfCD9C7182bf3062',
30
+ integrationHelperAddress: '0x7Ba560eB735AbDCf9a3a5692272652A0cc81850d',
31
+ // USDC
32
+ quoteToken: {
33
+ address: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
34
+ decimals: 6,
35
+ },
36
+ },
37
+ [Network.FANTOM]: {
38
+ wooPPV2Address: '0x286ab107c5E9083dBed35A2B5fb0242538F4f9bf',
39
+ wooOracleV2Address: '0x8840e26e0ebf7D100A0644DD8576DC62B03cbf04',
40
+ integrationHelperAddress: '0x6641959FE5EED7166F2254cF04b0d20c96776D9A',
41
+ // USDC
42
+ quoteToken: {
43
+ address: '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75',
44
+ decimals: 6,
45
+ },
46
+ },
47
+ [Network.ARBITRUM]: {
48
+ wooPPV2Address: '0xeFF23B4bE1091b53205E35f3AfCD9C7182bf3062',
49
+ wooOracleV2Address: '0x37a9dE70b6734dFCA54395D8061d9411D9910739',
50
+ integrationHelperAddress: '0x28D2B949024FE50627f1EbC5f0Ca3Ca721148E40',
51
+ // USDC
52
+ quoteToken: {
53
+ address: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8',
54
+ decimals: 6,
55
+ },
56
+ },
57
+ [Network.AVALANCHE]: {
58
+ wooPPV2Address: '0x3b3E4b4741e91aF52d0e9ad8660573E951c88524',
59
+ wooOracleV2Address: '0x9ACA557590F5020BDA4Ba63065Fc3A1253Bf8000',
60
+ integrationHelperAddress: '0x020630613E296c3E9b06186f630D1bF97A2B6Ad1',
61
+ // USDC
62
+ quoteToken: {
63
+ address: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
64
+ decimals: 6,
65
+ },
66
+ },
67
+ },
68
+ };
69
+
70
+ export const Adapters: Record<number, AdapterMappings> = {
71
+ [Network.OPTIMISM]: {
72
+ [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 11 }],
73
+ },
74
+ [Network.BSC]: { [SwapSide.SELL]: [{ name: 'BscAdapter01', index: 13 }] },
75
+ [Network.POLYGON]: {
76
+ [SwapSide.SELL]: [{ name: 'PolygonAdapter02', index: 4 }],
77
+ },
78
+ [Network.FANTOM]: {
79
+ [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 8 }],
80
+ },
81
+ [Network.ARBITRUM]: {
82
+ [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 3 }],
83
+ },
84
+ [Network.AVALANCHE]: {
85
+ [SwapSide.SELL]: [{ name: 'AvalancheAdapter01', index: 12 }],
86
+ },
87
+ };
@@ -0,0 +1,22 @@
1
+ import { PoolState } from './types';
2
+
3
+ export const WOO_FI_V2_GAS_COST = {
4
+ // https://dashboard.tenderly.co/paraswap/paraswap/fork/f5a6da2f-fec7-4d00-ac2c-b9c50f5c9554/simulation/25f3b378-632f-4beb-ba37-e21dd3722b5c/gas-usage
5
+ sellQuote: 145_000,
6
+ // https://dashboard.tenderly.co/paraswap/paraswap/fork/92f13a98-465d-409e-867d-e255e9f86cf1/simulation/09d5d06a-dd90-40fe-8ae6-a65097e804d4/gas-usage
7
+ sellBase: 159_000,
8
+ // https://dashboard.tenderly.co/paraswap/paraswap/fork/d5964ad1-f64f-42b7-8fac-976ad216f05f/simulation/49df18de-8046-463e-a904-5c9f621406d4/gas-usage
9
+ baseToBase: 204_000,
10
+ };
11
+
12
+ export const USD_PRECISION = 2;
13
+
14
+ export const MIN_CONVERSION_RATE = 1;
15
+
16
+ export const NULL_STATE: PoolState = {
17
+ tokenInfos: {},
18
+ tokenStates: {},
19
+ decimals: {},
20
+ oracleTimestamp: 0n,
21
+ isPaused: false,
22
+ };
@@ -0,0 +1,45 @@
1
+ import { BytesLike } from 'ethers';
2
+ import { defaultAbiCoder } from 'ethers/lib/utils';
3
+ import { extractSuccessAndValue, generalDecoder } from '../../lib/decoders';
4
+ import { MultiResult } from '../../lib/multi-wrapper';
5
+ import { DecimalInfo, TokenInfo, TokenState } from './types';
6
+
7
+ export function tokenInfoDecoder(
8
+ result: MultiResult<BytesLike> | BytesLike,
9
+ ): TokenInfo {
10
+ return generalDecoder(result, ['uint192', 'uint16'], undefined, value => ({
11
+ reserve: value[0].toBigInt(),
12
+ feeRate: BigInt(value[1].toString()),
13
+ }));
14
+ }
15
+
16
+ export function decimalInfoDecoder(
17
+ result: MultiResult<BytesLike> | BytesLike,
18
+ ): DecimalInfo {
19
+ return generalDecoder(
20
+ result,
21
+ ['tuple(uint64 priceDec, uint64 quoteDec, uint64 baseDec)'],
22
+ undefined,
23
+ value => ({
24
+ priceDec: value[0].priceDec.toBigInt(),
25
+ quoteDec: value[0].quoteDec.toBigInt(),
26
+ baseDec: value[0].baseDec.toBigInt(),
27
+ }),
28
+ );
29
+ }
30
+
31
+ // This is state from WooOracleV2 contract
32
+ export function stateDecoder(
33
+ result: MultiResult<BytesLike> | BytesLike,
34
+ ): TokenState {
35
+ return generalDecoder(
36
+ result,
37
+ ['tuple(uint128 price, uint64 spread, uint64 coeff, bool woFeasible)'],
38
+ undefined,
39
+ value => ({
40
+ price: value[0].price.toBigInt(),
41
+ spread: value[0].spread.toBigInt(),
42
+ coeff: value[0].coeff.toBigInt(),
43
+ }),
44
+ );
45
+ }
@@ -0,0 +1,63 @@
1
+ import { Interface } from 'ethers/lib/utils';
2
+ import { Address, Token } from '../../types';
3
+
4
+ export type PoolState = {
5
+ // fetched from WooPPV2.tokenInfos(address baseToken) :
6
+ // https://arbiscan.io/address/0x8693F9701D6DB361Fe9CC15Bc455Ef4366E39AE0
7
+ tokenInfos: Record<Address, TokenInfo>;
8
+
9
+ // fetched from WooracleV2.state(address baseToken)
10
+ // https://arbiscan.io/address/0x962d37fb9d75fe1af9aab323727183e4eae1322d
11
+ tokenStates: Record<Address, TokenState>;
12
+
13
+ // fetched from WooPPV2.decimalInfo(address baseToken)
14
+ // https://arbiscan.io/address/0x8693F9701D6DB361Fe9CC15Bc455Ef4366E39AE0
15
+ decimals: Record<Address, DecimalInfo>;
16
+ oracleTimestamp: bigint;
17
+ isPaused: boolean;
18
+ };
19
+
20
+ export type WooFiV2Data = {};
21
+
22
+ export type DexParams = {
23
+ wooPPV2Address: Address;
24
+ wooOracleV2Address: Address;
25
+ integrationHelperAddress: Address;
26
+ quoteToken: Token;
27
+ };
28
+
29
+ export type TokenInfo = {
30
+ reserve: bigint;
31
+ feeRate: bigint;
32
+ };
33
+
34
+ export type TokenState = {
35
+ price: bigint;
36
+ spread: bigint;
37
+ coeff: bigint;
38
+ };
39
+
40
+ export type DecimalInfo = {
41
+ priceDec: bigint;
42
+ quoteDec: bigint;
43
+ baseDec: bigint;
44
+ };
45
+
46
+ export type LatestRoundData = {
47
+ answer: bigint;
48
+ };
49
+
50
+ export type MulticallResultOutputs =
51
+ | boolean
52
+ | bigint
53
+ | TokenInfo
54
+ | DecimalInfo
55
+ | TokenState;
56
+
57
+ export type WooFiV2Interfaces = {
58
+ PPV2: Interface;
59
+ oracleV2: Interface;
60
+ integrationHelper: Interface;
61
+ chainlink: Interface;
62
+ erc20BalanceOf: Interface;
63
+ };
@@ -0,0 +1,19 @@
1
+ import { Interface } from 'ethers/lib/utils';
2
+ import wooPPV2ABI from '../../abi/woo-fi-v2/WooPPV2.abi.json';
3
+ import wooOracleV2ABI from '../../abi/woo-fi-v2/WooOracleV2.abi.json';
4
+ import wooIntegrationHelper from '../../abi/woo-fi-v2/IntegrationHelper.abi.json';
5
+ import { WooFiV2Interfaces } from './types';
6
+
7
+ export const ifaces: WooFiV2Interfaces = {
8
+ PPV2: new Interface(wooPPV2ABI),
9
+ oracleV2: new Interface(wooOracleV2ABI),
10
+ integrationHelper: new Interface(wooIntegrationHelper),
11
+ chainlink: new Interface([
12
+ 'function latestRoundData() view returns (tuple(uint80 roundId, ' +
13
+ 'int256 answer, uint256 startedAt, uint256 updatedAt, ' +
14
+ 'uint80 answeredInRound))',
15
+ ]),
16
+ erc20BalanceOf: new Interface([
17
+ 'function balanceOf(address) view returns (uint256)',
18
+ ]),
19
+ };
@@ -0,0 +1,216 @@
1
+ import dotenv from 'dotenv';
2
+ dotenv.config();
3
+
4
+ import { testE2E } from '../../../tests/utils-e2e';
5
+ import { Tokens, Holders } from '../../../tests/constants-e2e';
6
+ import { Network, ContractMethod, SwapSide } from '../../constants';
7
+ import { StaticJsonRpcProvider } from '@ethersproject/providers';
8
+ import { generateConfig } from '../../config';
9
+
10
+ function testForNetwork(
11
+ network: Network,
12
+ dexKey: string,
13
+ tokenBaseA: string,
14
+ tokenBaseB: string,
15
+ tokenQuote: string,
16
+ tokenBaseAAmount: string,
17
+ tokenQuoteAmount: string,
18
+ ) {
19
+ const provider = new StaticJsonRpcProvider(
20
+ generateConfig(network).privateHttpProvider,
21
+ network,
22
+ );
23
+ const tokens = Tokens[network];
24
+ const holders = Holders[network];
25
+
26
+ const sideToContractMethods = new Map([
27
+ [
28
+ SwapSide.SELL,
29
+ [
30
+ ContractMethod.simpleSwap,
31
+ ContractMethod.multiSwap,
32
+ ContractMethod.megaSwap,
33
+ ],
34
+ ],
35
+ ]);
36
+
37
+ describe(`${network}`, () => {
38
+ sideToContractMethods.forEach((contractMethods, side) =>
39
+ describe(`${side}`, () => {
40
+ contractMethods.forEach((contractMethod: ContractMethod) => {
41
+ describe(`${contractMethod}`, () => {
42
+ it(`${tokenBaseA} -> ${tokenQuote}`, async () => {
43
+ await testE2E(
44
+ tokens[tokenBaseA],
45
+ tokens[tokenQuote],
46
+ holders[tokenBaseA],
47
+ tokenBaseAAmount,
48
+ side,
49
+ dexKey,
50
+ contractMethod,
51
+ network,
52
+ provider,
53
+ );
54
+ });
55
+ it(`${tokenQuote} -> ${tokenBaseA}`, async () => {
56
+ await testE2E(
57
+ tokens[tokenQuote],
58
+ tokens[tokenBaseA],
59
+ holders[tokenQuote],
60
+ tokenQuoteAmount,
61
+ side,
62
+ dexKey,
63
+ contractMethod,
64
+ network,
65
+ provider,
66
+ );
67
+ });
68
+ it(`${tokenBaseA} -> ${tokenBaseB}`, async () => {
69
+ await testE2E(
70
+ tokens[tokenBaseA],
71
+ tokens[tokenBaseB],
72
+ holders[tokenBaseA],
73
+ tokenBaseAAmount,
74
+ side,
75
+ dexKey,
76
+ contractMethod,
77
+ network,
78
+ provider,
79
+ );
80
+ });
81
+ });
82
+ });
83
+ }),
84
+ );
85
+ });
86
+ }
87
+
88
+ describe('WooFiV2 E2E', () => {
89
+ const dexKey = 'WooFiV2';
90
+
91
+ describe('Optimism', () => {
92
+ const network = Network.OPTIMISM;
93
+
94
+ const baseATokenSymbol = 'WETH';
95
+ const baseBTokenSymbol = 'WBTC';
96
+ const quoteTokenSymbol = 'USDC';
97
+
98
+ const tokenBaseAAmount = '1000000000000000000';
99
+ const tokenQuoteAmount = '1000000';
100
+
101
+ testForNetwork(
102
+ network,
103
+ dexKey,
104
+ baseATokenSymbol,
105
+ baseBTokenSymbol,
106
+ quoteTokenSymbol,
107
+ tokenBaseAAmount,
108
+ tokenQuoteAmount,
109
+ );
110
+ });
111
+
112
+ describe('BSC', () => {
113
+ const network = Network.BSC;
114
+
115
+ const baseATokenSymbol = 'WBNB';
116
+ const baseBTokenSymbol = 'bBTC';
117
+ const quoteTokenSymbol = 'BUSD';
118
+
119
+ const tokenBaseAAmount = '1000000000000000000';
120
+ const tokenQuoteAmount = '1000000000000000000';
121
+
122
+ testForNetwork(
123
+ network,
124
+ dexKey,
125
+ baseATokenSymbol,
126
+ baseBTokenSymbol,
127
+ quoteTokenSymbol,
128
+ tokenBaseAAmount,
129
+ tokenQuoteAmount,
130
+ );
131
+ });
132
+
133
+ describe('Polygon', () => {
134
+ const network = Network.POLYGON;
135
+
136
+ const baseATokenSymbol = 'WMATIC';
137
+ const baseBTokenSymbol = 'WETH';
138
+ const quoteTokenSymbol = 'USDC';
139
+
140
+ const tokenBaseAAmount = '1000000000000000000';
141
+ const tokenQuoteAmount = '1000000';
142
+
143
+ testForNetwork(
144
+ network,
145
+ dexKey,
146
+ baseATokenSymbol,
147
+ baseBTokenSymbol,
148
+ quoteTokenSymbol,
149
+ tokenBaseAAmount,
150
+ tokenQuoteAmount,
151
+ );
152
+ });
153
+
154
+ describe('Fantom', () => {
155
+ const network = Network.FANTOM;
156
+
157
+ const baseATokenSymbol = 'WFTM';
158
+ const quoteTokenSymbol = 'USDC';
159
+ const baseBTokenSymbol = 'ETH';
160
+
161
+ const tokenBaseAAmount = '1000000000000000000';
162
+ const tokenQuoteAmount = '1000000';
163
+
164
+ testForNetwork(
165
+ network,
166
+ dexKey,
167
+ baseATokenSymbol,
168
+ baseBTokenSymbol,
169
+ quoteTokenSymbol,
170
+ tokenBaseAAmount,
171
+ tokenQuoteAmount,
172
+ );
173
+ });
174
+
175
+ describe('Arbitrum', () => {
176
+ const network = Network.ARBITRUM;
177
+
178
+ const baseATokenSymbol = 'WETH';
179
+ const baseBTokenSymbol = 'WBTC';
180
+ const quoteTokenSymbol = 'USDC';
181
+
182
+ const tokenBaseAAmount = '1000000000000000000';
183
+ const tokenQuoteAmount = '1000000';
184
+
185
+ testForNetwork(
186
+ network,
187
+ dexKey,
188
+ baseATokenSymbol,
189
+ baseBTokenSymbol,
190
+ quoteTokenSymbol,
191
+ tokenBaseAAmount,
192
+ tokenQuoteAmount,
193
+ );
194
+ });
195
+
196
+ describe('Avalanche', () => {
197
+ const network = Network.AVALANCHE;
198
+
199
+ const baseATokenSymbol = 'WAVAX';
200
+ const baseBTokenSymbol = 'BTCb';
201
+ const quoteTokenSymbol = 'USDC';
202
+
203
+ const tokenBaseAAmount = '1000000000000000000';
204
+ const tokenQuoteAmount = '1000000';
205
+
206
+ testForNetwork(
207
+ network,
208
+ dexKey,
209
+ baseATokenSymbol,
210
+ baseBTokenSymbol,
211
+ quoteTokenSymbol,
212
+ tokenBaseAAmount,
213
+ tokenQuoteAmount,
214
+ );
215
+ });
216
+ });