@paraswap/dex-lib 4.1.6 → 4.1.7-mwrappedm.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 (137) hide show
  1. package/README.md +1 -1
  2. package/build/abi/fluid-dex/resolver.abi.json +0 -30
  3. package/build/abi/m-token/WrappedM.abi.json +1708 -0
  4. package/build/dex/aave-v3-stata-v2/config.js +0 -13
  5. package/build/dex/aave-v3-stata-v2/config.js.map +1 -1
  6. package/build/dex/algebra/config.js +1 -1
  7. package/build/dex/algebra/config.js.map +1 -1
  8. package/build/dex/balancer-v2/pools/gyro/GyroEPool.js.map +1 -1
  9. package/build/dex/balancer-v3/balancer-v3-pool.d.ts +1 -6
  10. package/build/dex/balancer-v3/balancer-v3-pool.js +17 -45
  11. package/build/dex/balancer-v3/balancer-v3-pool.js.map +1 -1
  12. package/build/dex/balancer-v3/balancer-v3.d.ts +0 -4
  13. package/build/dex/balancer-v3/balancer-v3.js +4 -30
  14. package/build/dex/balancer-v3/balancer-v3.js.map +1 -1
  15. package/build/dex/balancer-v3/config.js +0 -51
  16. package/build/dex/balancer-v3/config.js.map +1 -1
  17. package/build/dex/balancer-v3/getOnChainState.d.ts +2 -1
  18. package/build/dex/balancer-v3/getOnChainState.js +2 -0
  19. package/build/dex/balancer-v3/getOnChainState.js.map +1 -1
  20. package/build/dex/balancer-v3/getPoolsApi.d.ts +1 -2
  21. package/build/dex/balancer-v3/getPoolsApi.js +10 -17
  22. package/build/dex/balancer-v3/getPoolsApi.js.map +1 -1
  23. package/build/dex/balancer-v3/getTopPoolsApi.d.ts +1 -5
  24. package/build/dex/balancer-v3/getTopPoolsApi.js +3 -6
  25. package/build/dex/balancer-v3/getTopPoolsApi.js.map +1 -1
  26. package/build/dex/balancer-v3/types.d.ts +1 -4
  27. package/build/dex/cables/cables.d.ts +1 -1
  28. package/build/dex/cables/cables.js +7 -26
  29. package/build/dex/cables/cables.js.map +1 -1
  30. package/build/dex/fluid-dex/config.js +2 -2
  31. package/build/dex/fluid-dex/constants.d.ts +1 -1
  32. package/build/dex/fluid-dex/constants.js +1 -2
  33. package/build/dex/fluid-dex/constants.js.map +1 -1
  34. package/build/dex/fluid-dex/fluid-dex-liquidity-proxy.js +1 -3
  35. package/build/dex/fluid-dex/fluid-dex-liquidity-proxy.js.map +1 -1
  36. package/build/dex/fluid-dex/fluid-dex.d.ts +5 -4
  37. package/build/dex/fluid-dex/fluid-dex.js +59 -61
  38. package/build/dex/fluid-dex/fluid-dex.js.map +1 -1
  39. package/build/dex/fluid-dex/types.d.ts +0 -3
  40. package/build/dex/index.js +2 -0
  41. package/build/dex/index.js.map +1 -1
  42. package/build/dex/m-token/config.d.ts +3 -0
  43. package/build/dex/m-token/config.js +19 -0
  44. package/build/dex/m-token/config.js.map +1 -0
  45. package/build/dex/m-token/m-token.d.ts +29 -0
  46. package/build/dex/m-token/m-token.js +145 -0
  47. package/build/dex/m-token/m-token.js.map +1 -0
  48. package/build/dex/m-token/m-wrapped-m.d.ts +17 -0
  49. package/build/dex/m-token/m-wrapped-m.js +50 -0
  50. package/build/dex/m-token/m-wrapped-m.js.map +1 -0
  51. package/build/dex/m-token/types.d.ts +12 -0
  52. package/build/dex/m-token/types.js +3 -0
  53. package/build/dex/m-token/types.js.map +1 -0
  54. package/build/dex/pancakeswap-v3/pancakeswap-v3-pool.js +0 -1
  55. package/build/dex/pancakeswap-v3/pancakeswap-v3-pool.js.map +1 -1
  56. package/build/dex/uniswap-v3/constants.d.ts +0 -2
  57. package/build/dex/uniswap-v3/constants.js +1 -8
  58. package/build/dex/uniswap-v3/constants.js.map +1 -1
  59. package/build/dex/uniswap-v3/contract-math/TickBitMap.d.ts +2 -2
  60. package/build/dex/uniswap-v3/contract-math/TickBitMap.js +8 -10
  61. package/build/dex/uniswap-v3/contract-math/TickBitMap.js.map +1 -1
  62. package/build/dex/uniswap-v3/contract-math/uniswap-v3-math.js +3 -3
  63. package/build/dex/uniswap-v3/contract-math/uniswap-v3-math.js.map +1 -1
  64. package/build/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.js +0 -1
  65. package/build/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.js.map +1 -1
  66. package/build/dex/uniswap-v3/forks/velodrome-slipstream/velodrome-slipstream-pool.js +0 -1
  67. package/build/dex/uniswap-v3/forks/velodrome-slipstream/velodrome-slipstream-pool.js.map +1 -1
  68. package/build/dex/uniswap-v3/types.d.ts +0 -1
  69. package/build/dex/uniswap-v3/types.js.map +1 -1
  70. package/build/dex/uniswap-v3/uniswap-v3-pool.js +1 -5
  71. package/build/dex/uniswap-v3/uniswap-v3-pool.js.map +1 -1
  72. package/build/dex/wusdm/config.js +0 -6
  73. package/build/dex/wusdm/config.js.map +1 -1
  74. package/build/generic-swap-transaction-builder.d.ts +1 -1
  75. package/build/generic-swap-transaction-builder.js +1 -6
  76. package/build/generic-swap-transaction-builder.js.map +1 -1
  77. package/build/implementations/local-paraswap-sdk.js +1 -1
  78. package/build/implementations/local-paraswap-sdk.js.map +1 -1
  79. package/package.json +3 -3
  80. package/scripts/run-dex-integration-v3.ts +4 -4
  81. package/src/abi/fluid-dex/resolver.abi.json +0 -30
  82. package/src/abi/m-token/WrappedM.abi.json +1708 -0
  83. package/src/dex/aave-v3-stata-v2/aave-v3-stata-v2-e2e.test.ts +32 -11
  84. package/src/dex/aave-v3-stata-v2/config.ts +0 -16
  85. package/src/dex/algebra/config.ts +1 -1
  86. package/src/dex/balancer-v2/balancer-v2-integration.test.ts +12 -11
  87. package/src/dex/balancer-v2/pools/gyro/GyroEPool.ts +1 -0
  88. package/src/dex/balancer-v3/balancer-v3-e2e.test.ts +0 -130
  89. package/src/dex/balancer-v3/balancer-v3-events.test.ts +84 -157
  90. package/src/dex/balancer-v3/balancer-v3-integration.test.ts +202 -103
  91. package/src/dex/balancer-v3/balancer-v3-pool.ts +26 -85
  92. package/src/dex/balancer-v3/balancer-v3.ts +2 -43
  93. package/src/dex/balancer-v3/config.ts +0 -51
  94. package/src/dex/balancer-v3/getOnChainState.ts +4 -1
  95. package/src/dex/balancer-v3/getPoolsApi.ts +23 -42
  96. package/src/dex/balancer-v3/getTopPoolsApi.ts +2 -13
  97. package/src/dex/balancer-v3/types.ts +2 -4
  98. package/src/dex/cables/cables-e2e.test.ts +40 -40
  99. package/src/dex/cables/cables.ts +10 -37
  100. package/src/dex/fluid-dex/config.ts +2 -2
  101. package/src/dex/fluid-dex/constants.ts +1 -2
  102. package/src/dex/fluid-dex/fluid-dex-e2e.test.ts +117 -61
  103. package/src/dex/fluid-dex/fluid-dex-liquidity-proxy.ts +0 -3
  104. package/src/dex/fluid-dex/fluid-dex.ts +94 -96
  105. package/src/dex/fluid-dex/types.ts +0 -3
  106. package/src/dex/index.ts +2 -0
  107. package/src/dex/m-token/config.ts +18 -0
  108. package/src/dex/m-token/m-token-e2e.test.ts +93 -0
  109. package/src/dex/m-token/m-token-integration.test.ts +199 -0
  110. package/src/dex/m-token/m-token.ts +167 -0
  111. package/src/dex/m-token/m-wrapped-m.ts +68 -0
  112. package/src/dex/m-token/types.ts +10 -0
  113. package/src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts +0 -1
  114. package/src/dex/uniswap-v3/constants.ts +0 -10
  115. package/src/dex/uniswap-v3/contract-math/TickBitMap.ts +9 -29
  116. package/src/dex/uniswap-v3/contract-math/uniswap-v3-math.ts +1 -3
  117. package/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts +0 -1
  118. package/src/dex/uniswap-v3/forks/velodrome-slipstream/velodrome-slipstream-pool.ts +0 -1
  119. package/src/dex/uniswap-v3/types.ts +0 -1
  120. package/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +302 -647
  121. package/src/dex/uniswap-v3/uniswap-v3-pool.ts +1 -11
  122. package/src/dex/wusdm/config.ts +0 -7
  123. package/src/dex/wusdm/wusdm-e2e.test.ts +0 -20
  124. package/src/generic-swap-transaction-builder.ts +2 -10
  125. package/src/implementations/local-paraswap-sdk.ts +1 -1
  126. package/tests/constants-e2e.ts +8 -63
  127. package/tests/tenderly-simulation.ts +0 -3
  128. package/tests/utils-e2e.ts +7 -4
  129. package/src/abi/balancer-v3/directionalFeeHook.json +0 -684
  130. package/src/abi/balancer-v3/stableSurgeHook.json +0 -976
  131. package/src/dex/balancer-v3/balancer-hooks-events.test.ts +0 -166
  132. package/src/dex/balancer-v3/balancer-stableSurge.test.ts +0 -110
  133. package/src/dex/balancer-v3/balancer-test-helpers.ts +0 -199
  134. package/src/dex/balancer-v3/hooks/balancer-hook-event-subscriber.ts +0 -212
  135. package/src/dex/balancer-v3/hooks/directionalFeeHook.ts +0 -51
  136. package/src/dex/balancer-v3/hooks/loadHooksConfig.ts +0 -12
  137. package/src/dex/balancer-v3/hooks/stableSurgeHook.ts +0 -198
@@ -1,166 +0,0 @@
1
- // npx jest src/dex/balancer-v3/balancer-hooks-events.test.ts
2
- /* eslint-disable no-console */
3
- import dotenv from 'dotenv';
4
- dotenv.config();
5
- import _ from 'lodash';
6
- import { Network } from '../../constants';
7
- import { Address } from '../../types';
8
- import { DummyDexHelper } from '../../dex-helper/index';
9
- import { testEventSubscriber } from '../../../tests/utils-events';
10
- import {
11
- BalancerEventHook,
12
- HookStateMap,
13
- } from './hooks/balancer-hook-event-subscriber';
14
-
15
- jest.setTimeout(50 * 1000);
16
-
17
- async function fetchHookState(
18
- balancerEventHook: BalancerEventHook,
19
- blockNumber: number,
20
- hookAddress: string,
21
- ): Promise<HookStateMap> {
22
- const hookStateMap = await balancerEventHook.generateState(blockNumber);
23
- // Filter to hook of interest
24
- return Object.entries(_.cloneDeep(hookStateMap) as HookStateMap)
25
- .filter(([address]) => {
26
- return address.toLowerCase() === hookAddress.toLowerCase();
27
- })
28
- .reduce((acc, [address, pool]) => {
29
- acc[address] = pool;
30
- return acc;
31
- }, {} as HookStateMap);
32
- }
33
-
34
- // eventName -> blockNumbers
35
- type EventMappings = Record<string, EventData>;
36
- type EventData = { blockNumbers: number[]; hookAddress: string[] };
37
-
38
- describe('BalancerEventHook', function () {
39
- const dexKey = 'BalancerV3';
40
-
41
- describe('Mainnet', () => {
42
- const network = Network.MAINNET;
43
- const dexHelper = new DummyDexHelper(network);
44
- const logger = dexHelper.getLogger(dexKey);
45
- let balancerEventHook: BalancerEventHook;
46
-
47
- // hook -> EventMappings
48
- const eventsToTest: Record<Address, EventMappings> = {
49
- ['StableSurgeHook']: {
50
- ThresholdSurgePercentageChanged: {
51
- blockNumbers: [
52
- 21824387, 21825432, 21825615, 21825831, 21830728, 21830728,
53
- ],
54
- hookAddress: ['0xb18fA0cb5DE8cecB8899AAE6e38b1B7ed77885dA'],
55
- },
56
- MaxSurgeFeePercentageChanged: {
57
- blockNumbers: [
58
- 21824387, 21825432, 21825615, 21825831, 21830728, 21830728,
59
- ],
60
- hookAddress: ['0xb18fA0cb5DE8cecB8899AAE6e38b1B7ed77885dA'],
61
- },
62
- },
63
- };
64
-
65
- beforeEach(async () => {
66
- balancerEventHook = new BalancerEventHook(
67
- dexKey,
68
- network,
69
- dexHelper,
70
- logger,
71
- );
72
- });
73
-
74
- Object.entries(eventsToTest).forEach(
75
- ([hookAddress, events]: [string, EventMappings]) => {
76
- describe(`Events for Hook: ${hookAddress}`, () => {
77
- Object.entries(events).forEach(
78
- ([eventName, eventData]: [string, EventData]) => {
79
- describe(`${eventName}`, () => {
80
- eventData.blockNumbers.forEach((blockNumber: number, i) => {
81
- it(`Hook: ${eventData.hookAddress[i]} State after ${blockNumber}`, async function () {
82
- await testEventSubscriber(
83
- balancerEventHook,
84
- balancerEventHook.addressesSubscribed,
85
- (_blockNumber: number) =>
86
- fetchHookState(
87
- balancerEventHook,
88
- _blockNumber,
89
- eventData.hookAddress[0],
90
- ),
91
- blockNumber,
92
- `${dexKey}_${hookAddress}`,
93
- dexHelper.provider,
94
- );
95
- });
96
- });
97
- });
98
- },
99
- );
100
- });
101
- },
102
- );
103
- });
104
-
105
- describe('SEPOLIA', () => {
106
- const network = Network.SEPOLIA;
107
- const dexHelper = new DummyDexHelper(network);
108
- const logger = dexHelper.getLogger(dexKey);
109
- let balancerEventHook: BalancerEventHook;
110
-
111
- // hook -> EventMappings
112
- const eventsToTest: Record<Address, EventMappings> = {
113
- ['StableSurgeHook']: {
114
- // https://sepolia.etherscan.io/tx/0xa8d363d9c78b7b66e6f93c4417de67e636c13691437aecf85a631987b200abd8
115
- ThresholdSurgePercentageChanged: {
116
- blockNumbers: [7596856],
117
- hookAddress: ['0xC0cbcdD6b823A4f22aA6BbDDe44C17e754266AEF'],
118
- },
119
- // https://sepolia.etherscan.io/tx/0xd1a9e40ed3c3d32bf8f2264daa4c66879ac5eae1f4029ae9993badd653b26bad
120
- MaxSurgeFeePercentageChanged: {
121
- blockNumbers: [7596855],
122
- hookAddress: ['0xC0cbcdD6b823A4f22aA6BbDDe44C17e754266AEF'],
123
- },
124
- },
125
- };
126
-
127
- beforeEach(async () => {
128
- balancerEventHook = new BalancerEventHook(
129
- dexKey,
130
- network,
131
- dexHelper,
132
- logger,
133
- );
134
- });
135
-
136
- Object.entries(eventsToTest).forEach(
137
- ([hookAddress, events]: [string, EventMappings]) => {
138
- describe(`Events for Hook: ${hookAddress}`, () => {
139
- Object.entries(events).forEach(
140
- ([eventName, eventData]: [string, EventData]) => {
141
- describe(`${eventName}`, () => {
142
- eventData.blockNumbers.forEach((blockNumber: number, i) => {
143
- it(`Hook: ${eventData.hookAddress[i]} State after ${blockNumber}`, async function () {
144
- await testEventSubscriber(
145
- balancerEventHook,
146
- balancerEventHook.addressesSubscribed,
147
- (_blockNumber: number) =>
148
- fetchHookState(
149
- balancerEventHook,
150
- _blockNumber,
151
- eventData.hookAddress[i],
152
- ),
153
- blockNumber,
154
- `${dexKey}_${hookAddress}`,
155
- dexHelper.provider,
156
- );
157
- });
158
- });
159
- });
160
- },
161
- );
162
- });
163
- },
164
- );
165
- });
166
- });
@@ -1,110 +0,0 @@
1
- // npx jest src/dex/balancer-v3/balancer-stableSurge.test.ts
2
- import dotenv from 'dotenv';
3
- dotenv.config();
4
- import { Tokens } from '../../../tests/constants-e2e';
5
- import { Network, SwapSide } from '../../constants';
6
- import { DummyDexHelper } from '../../dex-helper';
7
- import { BalancerV3 } from './balancer-v3';
8
- import { checkOnChainPricingNonMulti } from './balancer-test-helpers';
9
- import { ExchangePrices, Token } from '../../types';
10
- import { BalancerV3Data } from './types';
11
-
12
- const dexKey = 'BalancerV3';
13
- const blockNumber = 7651340;
14
- let balancerV3: BalancerV3;
15
- const network = Network.SEPOLIA;
16
- const dexHelper = new DummyDexHelper(network);
17
- const tokens = Tokens[network];
18
- const bal = tokens['bal'];
19
- const weth = tokens['WETH'];
20
- // https://sepolia.etherscan.io/address/0x132F4bAa39330d9062fC52d81dF72F601DF8C01f
21
- const stableSurgePool =
22
- '0x132F4bAa39330d9062fC52d81dF72F601DF8C01f'.toLowerCase();
23
-
24
- describe('BalancerV3 stableSurge hook tests', function () {
25
- beforeAll(async () => {
26
- balancerV3 = new BalancerV3(network, dexKey, dexHelper);
27
- if (balancerV3.initializePricing) {
28
- await balancerV3.initializePricing(blockNumber);
29
- }
30
- });
31
-
32
- describe('pool with stableSurge hook should be returned', function () {
33
- it('getPoolIdentifiers', async function () {
34
- const pools = await balancerV3.getPoolIdentifiers(
35
- bal,
36
- weth,
37
- SwapSide.SELL,
38
- blockNumber,
39
- );
40
- expect(pools.some(pool => pool === stableSurgePool)).toBe(true);
41
- });
42
-
43
- it('getTopPoolsForToken', async function () {
44
- const pools = await balancerV3.getTopPoolsForToken(weth.address, 10);
45
- expect(pools.some(pool => pool.address === stableSurgePool)).toBe(true);
46
- });
47
- });
48
-
49
- describe('should match onchain pricing', function () {
50
- describe('using staticFee', function () {
51
- it('SELL', async function () {
52
- const amounts = [0n, 10000000000000000n];
53
- const side = SwapSide.SELL;
54
- await testPricesVsOnchain(amounts, weth, bal, side, blockNumber, [
55
- stableSurgePool,
56
- ]);
57
- });
58
- it('BUY', async function () {
59
- const amounts = [0n, 500000000000000000n];
60
- const side = SwapSide.BUY;
61
- await testPricesVsOnchain(amounts, weth, bal, side, blockNumber, [
62
- stableSurgePool,
63
- ]);
64
- });
65
- });
66
- describe('using surge fee', function () {
67
- it('SELL', async function () {
68
- const amounts = [0n, 8000000000000000000n];
69
- const side = SwapSide.SELL;
70
- await testPricesVsOnchain(amounts, bal, weth, side, blockNumber, [
71
- stableSurgePool,
72
- ]);
73
- });
74
- it('BUY', async function () {
75
- const amounts = [0n, 4000000000000000n];
76
- const side = SwapSide.BUY;
77
- await testPricesVsOnchain(amounts, bal, weth, side, blockNumber, [
78
- stableSurgePool,
79
- ]);
80
- });
81
- });
82
- });
83
- });
84
-
85
- async function testPricesVsOnchain(
86
- amounts: bigint[],
87
- srcToken: Token,
88
- dstToken: Token,
89
- side: SwapSide,
90
- blockNumber: number,
91
- limitPools: string[],
92
- ) {
93
- const prices = await balancerV3.getPricesVolume(
94
- srcToken,
95
- dstToken,
96
- amounts,
97
- side,
98
- blockNumber,
99
- limitPools,
100
- );
101
- expect(prices).not.toBeNull();
102
- await checkOnChainPricingNonMulti(
103
- network,
104
- side,
105
- balancerV3,
106
- blockNumber,
107
- prices as ExchangePrices<BalancerV3Data>,
108
- amounts,
109
- );
110
- }
@@ -1,199 +0,0 @@
1
- /* eslint-disable no-console */
2
- // Note - this is currently needed because queries won't work with multicall but should be updated in future
3
- export async function checkOnChainPricingNonMulti(
4
- network: number,
5
- side: SwapSide,
6
- balancerV3: BalancerV3,
7
- blockNumber: number,
8
- prices: ExchangePrices<BalancerV3Data>,
9
- amounts: bigint[],
10
- ) {
11
- // test match for each returned price
12
- for (const price of prices) {
13
- let expectedPrices: bigint[] = [];
14
- if (price.data.steps.length === 1 && !price.data.steps[0].isBuffer)
15
- expectedPrices = await querySinglePathPrices(
16
- network,
17
- side,
18
- balancerV3,
19
- blockNumber,
20
- price,
21
- amounts,
22
- );
23
- else
24
- expectedPrices = await queryMultiPathPrices(
25
- network,
26
- side,
27
- balancerV3,
28
- blockNumber,
29
- price,
30
- amounts,
31
- );
32
- expect(price.prices).toEqual(expectedPrices);
33
- }
34
- }
35
-
36
- async function querySinglePathPrices(
37
- network: number,
38
- side: SwapSide,
39
- balancerV3: BalancerV3,
40
- blockNumber: number,
41
- price: PoolPrices<BalancerV3Data>,
42
- amounts: bigint[],
43
- ) {
44
- const balancerRouter = new Interface(balancerRouterAbi);
45
- const readerCallData = getQuerySwapSingleTokenCalldata(
46
- BalancerV3Config.BalancerV3[network].balancerRouterAddress,
47
- balancerRouter,
48
- amounts,
49
- price.data.steps[0],
50
- side,
51
- );
52
-
53
- const expectedPrices = [0n];
54
- for (const call of readerCallData) {
55
- try {
56
- const result = await balancerV3.dexHelper.provider.call(
57
- {
58
- to: call.target,
59
- data: call.callData,
60
- },
61
- blockNumber,
62
- );
63
- const parsed = balancerRouter.decodeFunctionResult(
64
- side === SwapSide.SELL
65
- ? `querySwapSingleTokenExactIn`
66
- : `querySwapSingleTokenExactOut`,
67
- result,
68
- );
69
- expectedPrices.push(BigInt(parsed[0]._hex));
70
- } catch (error) {
71
- console.log('Error in querySinglePathPrices', error);
72
- expectedPrices.push(0n);
73
- }
74
- }
75
- return expectedPrices;
76
- }
77
-
78
- async function queryMultiPathPrices(
79
- network: number,
80
- side: SwapSide,
81
- balancerV3: BalancerV3,
82
- blockNumber: number,
83
- price: PoolPrices<BalancerV3Data>,
84
- amounts: bigint[],
85
- ) {
86
- const balancerBatchRouter = new Interface(balancerBatchRouterAbi);
87
- const readerCallData = getQuerySwapMultiTokenCalldata(
88
- BalancerV3Config.BalancerV3[network].balancerBatchRouterAddress,
89
- balancerBatchRouter,
90
- amounts,
91
- price.data.steps,
92
- side,
93
- );
94
-
95
- const expectedPrices = [0n];
96
- for (const call of readerCallData) {
97
- try {
98
- const result = await balancerV3.dexHelper.provider.call(
99
- {
100
- to: call.target,
101
- data: call.callData,
102
- },
103
- blockNumber,
104
- );
105
- const parsed = balancerBatchRouter.decodeFunctionResult(
106
- side === SwapSide.SELL ? `querySwapExactIn` : `querySwapExactOut`,
107
- result,
108
- );
109
- expectedPrices.push(BigInt(parsed[2][0]._hex));
110
- } catch (error) {
111
- console.log('Error in queryMultiPathPrices', error);
112
- expectedPrices.push(0n);
113
- }
114
- }
115
- return expectedPrices;
116
- }
117
-
118
- function getQuerySwapSingleTokenCalldata(
119
- routerAddress: Address,
120
- routerInterface: Interface,
121
- amounts: bigint[],
122
- step: Step,
123
- side: SwapSide,
124
- ) {
125
- return amounts
126
- .filter(amount => amount !== 0n)
127
- .map(amount => {
128
- return {
129
- target: routerAddress,
130
- callData: routerInterface.encodeFunctionData(
131
- side === SwapSide.SELL
132
- ? `querySwapSingleTokenExactIn`
133
- : `querySwapSingleTokenExactOut`,
134
- [
135
- step.pool,
136
- step.swapInput.tokenIn,
137
- step.swapInput.tokenOut,
138
- amount,
139
- NULL_ADDRESS,
140
- '0x',
141
- ],
142
- ),
143
- };
144
- });
145
- }
146
- /* eslint-disable no-console */
147
- import { Interface } from '@ethersproject/abi';
148
- import { NULL_ADDRESS, SwapSide } from '../../constants';
149
- import { BalancerV3 } from './balancer-v3';
150
- import { BalancerV3Config } from './config';
151
- import { BalancerV3Data, Step } from './types';
152
- import { Address, ExchangePrices, PoolPrices } from '../../types';
153
- import balancerBatchRouterAbi from '../../abi/balancer-v3/batch-router.json';
154
- import balancerRouterAbi from '../../abi/balancer-v3/router.json';
155
-
156
- function getQuerySwapMultiTokenCalldata(
157
- routerAddress: Address,
158
- routerInterface: Interface,
159
- amounts: bigint[],
160
- steps: Step[],
161
- side: SwapSide,
162
- ) {
163
- const tokenIn = steps[0].swapInput.tokenIn;
164
- const stepsNew = steps.map(s => ({
165
- pool: s.pool,
166
- tokenOut: s.swapInput.tokenOut,
167
- isBuffer: s.isBuffer,
168
- }));
169
- return amounts
170
- .filter(amount => amount !== 0n)
171
- .map(amount => {
172
- let args: any[] = [];
173
- if (side === SwapSide.SELL)
174
- args = [
175
- {
176
- tokenIn,
177
- steps: stepsNew,
178
- exactAmountIn: amount,
179
- minAmountOut: 0n,
180
- },
181
- ];
182
- else
183
- args = [
184
- {
185
- tokenIn,
186
- steps: stepsNew,
187
- exactAmountOut: amount,
188
- maxAmountIn: 0n,
189
- },
190
- ];
191
- return {
192
- target: routerAddress,
193
- callData: routerInterface.encodeFunctionData(
194
- side === SwapSide.SELL ? `querySwapExactIn` : `querySwapExactOut`,
195
- [args, NULL_ADDRESS, '0x'],
196
- ),
197
- };
198
- });
199
- }
@@ -1,212 +0,0 @@
1
- import {
2
- EventFragment,
3
- Fragment,
4
- FunctionFragment,
5
- Interface,
6
- } from '@ethersproject/abi';
7
- import _ from 'lodash';
8
- import { DeepReadonly } from 'ts-essentials';
9
- import { Log, Logger } from '../../../types';
10
- import { catchParseLogError } from '../../../utils';
11
- import { StatefulEventSubscriber } from '../../../stateful-event-subscriber';
12
- import { IDexHelper } from '../../../dex-helper/idex-helper';
13
- import { loadHooksConfig } from './loadHooksConfig';
14
- import {
15
- DirectionalFee,
16
- DirectionalFeeConfig,
17
- DirectionalFeeHookState,
18
- getDirectionalFeeHookState,
19
- } from './directionalFeeHook';
20
- import directionalFeeHookAbi from '../../../abi/balancer-v3/directionalFeeHook.json';
21
- import {
22
- getStableSurgeHookState,
23
- maxSurgeFeePercentageChangedEvent,
24
- StableSurge,
25
- StableSurgeConfig,
26
- StableSurgeHookState,
27
- thresholdSurgePercentageChangedEvent,
28
- } from './stableSurgeHook';
29
- import stableSurgeHookAbi from '../../../abi/balancer-v3/stableSurgeHook.json';
30
-
31
- // Add each supported hook state here
32
- export type HookState = DirectionalFeeHookState | StableSurgeHookState;
33
-
34
- export type HookStateMap = {
35
- [address: string]: HookState;
36
- };
37
-
38
- export type HookConfig = DirectionalFeeConfig | StableSurgeConfig;
39
-
40
- export type HooksConfigMap = {
41
- [hookAddress: string]: HookConfig;
42
- };
43
-
44
- /**
45
- * This will handle events/state for each supported hook contract. State is used during swap calculations.
46
- * Each hook should have its own implementation file for state typing, fetching state and handling events.
47
- */
48
- export class BalancerEventHook extends StatefulEventSubscriber<HookStateMap> {
49
- handlers: {
50
- [event: string]: (
51
- event: any,
52
- state: DeepReadonly<HookStateMap>,
53
- log: Readonly<Log>,
54
- logger: Logger,
55
- ) => DeepReadonly<HookStateMap> | null;
56
- } = {};
57
-
58
- interfaces: Interface[];
59
- logDecoder: (log: Log) => any;
60
-
61
- addressesSubscribed: string[];
62
-
63
- hooksConfigMap: HooksConfigMap;
64
-
65
- constructor(
66
- readonly parentName: string,
67
- protected network: number,
68
- protected dexHelper: IDexHelper,
69
- logger: Logger,
70
- ) {
71
- super(parentName, 'Balancer_Hooks', dexHelper, logger);
72
-
73
- // Load supported hooks from config file
74
- this.hooksConfigMap = loadHooksConfig(network);
75
-
76
- // Add each hook ABI here
77
- this.interfaces = [
78
- new Interface(directionalFeeHookAbi),
79
- new Interface(stableSurgeHookAbi),
80
- ];
81
- this.logDecoder = (log: Log) =>
82
- this.combineInterfaces(this.interfaces).parseLog(log);
83
-
84
- // Subscribe to all hooks
85
- this.addressesSubscribed = Object.keys(this.hooksConfigMap);
86
-
87
- // StableSurgeHook events
88
- this.handlers['ThresholdSurgePercentageChanged'] =
89
- thresholdSurgePercentageChangedEvent.bind(this);
90
- this.handlers['MaxSurgeFeePercentageChanged'] =
91
- maxSurgeFeePercentageChangedEvent.bind(this);
92
- }
93
-
94
- /**
95
- * The function is called every time any of the subscribed
96
- * addresses release log. The function accepts the current
97
- * state, updates the state according to the log, and returns
98
- * the updated state.
99
- * @param state - Current state of event subscriber
100
- * @param log - Log released by one of the subscribed addresses
101
- * @returns Updates state of the event subscriber after the log
102
- */
103
- protected processLog(
104
- state: DeepReadonly<HookStateMap>,
105
- log: Readonly<Log>,
106
- ): DeepReadonly<HookStateMap> | null {
107
- try {
108
- const event = this.logDecoder(log);
109
- if (event.name in this.handlers) {
110
- return this.handlers[event.name](event, state, log, this.logger);
111
- }
112
- } catch (e) {
113
- catchParseLogError(e, this.logger);
114
- }
115
-
116
- return null;
117
- }
118
-
119
- /**
120
- * The function generates state using on-chain calls. This
121
- * function is called to regenerate state if the event based
122
- * system fails to fetch events and the local state is no
123
- * more correct.
124
- * @param blockNumber - Blocknumber for which the state should
125
- * should be generated
126
- * @returns state of the event subscriber at blocknumber
127
- */
128
- async generateState(
129
- blockNumber: number,
130
- ): Promise<DeepReadonly<HookStateMap>> {
131
- // Only hooks that are supported will be called
132
- const hookState: HookStateMap = {};
133
-
134
- await Promise.all(
135
- Object.keys(this.hooksConfigMap).map(async hookAddress => {
136
- const hookConfig = this.hooksConfigMap[hookAddress];
137
- if (hookConfig.type === DirectionalFee.type) {
138
- hookState[hookAddress] = await getDirectionalFeeHookState();
139
- } else if (hookConfig.type === StableSurge.type) {
140
- hookState[hookAddress] = await getStableSurgeHookState(
141
- this.interfaces[1],
142
- hookAddress,
143
- hookConfig.factory,
144
- this.dexHelper,
145
- blockNumber,
146
- );
147
- }
148
- }),
149
- );
150
-
151
- return hookState;
152
- }
153
-
154
- async updateHookState() {
155
- // Not all hooks need updated, only ones with settings/state that can't be handled by events
156
- const blockNumber = await this.dexHelper.provider.getBlockNumber();
157
- const currentState =
158
- (_.cloneDeep(this.getStaleState()) as HookStateMap) || {};
159
-
160
- await Promise.all(
161
- Object.keys(this.hooksConfigMap).map(async hookAddress => {
162
- const hookConfig = this.hooksConfigMap[hookAddress];
163
- // StableSurge can have new registered pools with associated hook state
164
- if (hookConfig.type === StableSurge.type) {
165
- currentState[hookAddress] = await getStableSurgeHookState(
166
- this.interfaces[1],
167
- hookAddress,
168
- hookConfig.factory,
169
- this.dexHelper,
170
- blockNumber,
171
- );
172
- }
173
- }),
174
- );
175
-
176
- this.setState(currentState, blockNumber);
177
- }
178
-
179
- combineInterfaces = (interfaces: Interface[]): Interface => {
180
- // Use a Map to store unique fragments, keyed by their string representation
181
- const uniqueFragments = new Map<string, Fragment>();
182
-
183
- interfaces.forEach((interfaceInstance: Interface) => {
184
- interfaceInstance.fragments.forEach((fragment: Fragment) => {
185
- let key: string;
186
-
187
- if (fragment instanceof FunctionFragment) {
188
- // For functions, use the signature as the key
189
- // This includes name and parameter types
190
- key = fragment.format();
191
- } else if (fragment instanceof EventFragment) {
192
- // For events, use the signature as the key
193
- key = fragment.format();
194
- } else {
195
- // For other fragment types (like errors), use their string representation
196
- key = fragment.toString();
197
- }
198
-
199
- // Only add if we haven't seen this signature before
200
- if (!uniqueFragments.has(key)) {
201
- uniqueFragments.set(key, fragment);
202
- }
203
- });
204
- });
205
-
206
- // Convert the Map values back to an array
207
- const dedupedFragments = Array.from(uniqueFragments.values());
208
-
209
- // Create a new interface with the deduped fragments
210
- return new Interface(dedupedFragments);
211
- };
212
- }