@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.
- package/README.md +1 -1
- package/build/abi/fluid-dex/resolver.abi.json +0 -30
- package/build/abi/m-token/WrappedM.abi.json +1708 -0
- package/build/dex/aave-v3-stata-v2/config.js +0 -13
- package/build/dex/aave-v3-stata-v2/config.js.map +1 -1
- package/build/dex/algebra/config.js +1 -1
- package/build/dex/algebra/config.js.map +1 -1
- package/build/dex/balancer-v2/pools/gyro/GyroEPool.js.map +1 -1
- package/build/dex/balancer-v3/balancer-v3-pool.d.ts +1 -6
- package/build/dex/balancer-v3/balancer-v3-pool.js +17 -45
- package/build/dex/balancer-v3/balancer-v3-pool.js.map +1 -1
- package/build/dex/balancer-v3/balancer-v3.d.ts +0 -4
- package/build/dex/balancer-v3/balancer-v3.js +4 -30
- package/build/dex/balancer-v3/balancer-v3.js.map +1 -1
- package/build/dex/balancer-v3/config.js +0 -51
- package/build/dex/balancer-v3/config.js.map +1 -1
- package/build/dex/balancer-v3/getOnChainState.d.ts +2 -1
- package/build/dex/balancer-v3/getOnChainState.js +2 -0
- package/build/dex/balancer-v3/getOnChainState.js.map +1 -1
- package/build/dex/balancer-v3/getPoolsApi.d.ts +1 -2
- package/build/dex/balancer-v3/getPoolsApi.js +10 -17
- package/build/dex/balancer-v3/getPoolsApi.js.map +1 -1
- package/build/dex/balancer-v3/getTopPoolsApi.d.ts +1 -5
- package/build/dex/balancer-v3/getTopPoolsApi.js +3 -6
- package/build/dex/balancer-v3/getTopPoolsApi.js.map +1 -1
- package/build/dex/balancer-v3/types.d.ts +1 -4
- package/build/dex/cables/cables.d.ts +1 -1
- package/build/dex/cables/cables.js +7 -26
- package/build/dex/cables/cables.js.map +1 -1
- package/build/dex/fluid-dex/config.js +2 -2
- package/build/dex/fluid-dex/constants.d.ts +1 -1
- package/build/dex/fluid-dex/constants.js +1 -2
- package/build/dex/fluid-dex/constants.js.map +1 -1
- package/build/dex/fluid-dex/fluid-dex-liquidity-proxy.js +1 -3
- package/build/dex/fluid-dex/fluid-dex-liquidity-proxy.js.map +1 -1
- package/build/dex/fluid-dex/fluid-dex.d.ts +5 -4
- package/build/dex/fluid-dex/fluid-dex.js +59 -61
- package/build/dex/fluid-dex/fluid-dex.js.map +1 -1
- package/build/dex/fluid-dex/types.d.ts +0 -3
- package/build/dex/index.js +2 -0
- package/build/dex/index.js.map +1 -1
- package/build/dex/m-token/config.d.ts +3 -0
- package/build/dex/m-token/config.js +19 -0
- package/build/dex/m-token/config.js.map +1 -0
- package/build/dex/m-token/m-token.d.ts +29 -0
- package/build/dex/m-token/m-token.js +145 -0
- package/build/dex/m-token/m-token.js.map +1 -0
- package/build/dex/m-token/m-wrapped-m.d.ts +17 -0
- package/build/dex/m-token/m-wrapped-m.js +50 -0
- package/build/dex/m-token/m-wrapped-m.js.map +1 -0
- package/build/dex/m-token/types.d.ts +12 -0
- package/build/dex/m-token/types.js +3 -0
- package/build/dex/m-token/types.js.map +1 -0
- package/build/dex/pancakeswap-v3/pancakeswap-v3-pool.js +0 -1
- package/build/dex/pancakeswap-v3/pancakeswap-v3-pool.js.map +1 -1
- package/build/dex/uniswap-v3/constants.d.ts +0 -2
- package/build/dex/uniswap-v3/constants.js +1 -8
- package/build/dex/uniswap-v3/constants.js.map +1 -1
- package/build/dex/uniswap-v3/contract-math/TickBitMap.d.ts +2 -2
- package/build/dex/uniswap-v3/contract-math/TickBitMap.js +8 -10
- package/build/dex/uniswap-v3/contract-math/TickBitMap.js.map +1 -1
- package/build/dex/uniswap-v3/contract-math/uniswap-v3-math.js +3 -3
- package/build/dex/uniswap-v3/contract-math/uniswap-v3-math.js.map +1 -1
- package/build/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.js +0 -1
- package/build/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.js.map +1 -1
- package/build/dex/uniswap-v3/forks/velodrome-slipstream/velodrome-slipstream-pool.js +0 -1
- package/build/dex/uniswap-v3/forks/velodrome-slipstream/velodrome-slipstream-pool.js.map +1 -1
- package/build/dex/uniswap-v3/types.d.ts +0 -1
- package/build/dex/uniswap-v3/types.js.map +1 -1
- package/build/dex/uniswap-v3/uniswap-v3-pool.js +1 -5
- package/build/dex/uniswap-v3/uniswap-v3-pool.js.map +1 -1
- package/build/dex/wusdm/config.js +0 -6
- package/build/dex/wusdm/config.js.map +1 -1
- package/build/generic-swap-transaction-builder.d.ts +1 -1
- package/build/generic-swap-transaction-builder.js +1 -6
- package/build/generic-swap-transaction-builder.js.map +1 -1
- package/build/implementations/local-paraswap-sdk.js +1 -1
- package/build/implementations/local-paraswap-sdk.js.map +1 -1
- package/package.json +3 -3
- package/scripts/run-dex-integration-v3.ts +4 -4
- package/src/abi/fluid-dex/resolver.abi.json +0 -30
- package/src/abi/m-token/WrappedM.abi.json +1708 -0
- package/src/dex/aave-v3-stata-v2/aave-v3-stata-v2-e2e.test.ts +32 -11
- package/src/dex/aave-v3-stata-v2/config.ts +0 -16
- package/src/dex/algebra/config.ts +1 -1
- package/src/dex/balancer-v2/balancer-v2-integration.test.ts +12 -11
- package/src/dex/balancer-v2/pools/gyro/GyroEPool.ts +1 -0
- package/src/dex/balancer-v3/balancer-v3-e2e.test.ts +0 -130
- package/src/dex/balancer-v3/balancer-v3-events.test.ts +84 -157
- package/src/dex/balancer-v3/balancer-v3-integration.test.ts +202 -103
- package/src/dex/balancer-v3/balancer-v3-pool.ts +26 -85
- package/src/dex/balancer-v3/balancer-v3.ts +2 -43
- package/src/dex/balancer-v3/config.ts +0 -51
- package/src/dex/balancer-v3/getOnChainState.ts +4 -1
- package/src/dex/balancer-v3/getPoolsApi.ts +23 -42
- package/src/dex/balancer-v3/getTopPoolsApi.ts +2 -13
- package/src/dex/balancer-v3/types.ts +2 -4
- package/src/dex/cables/cables-e2e.test.ts +40 -40
- package/src/dex/cables/cables.ts +10 -37
- package/src/dex/fluid-dex/config.ts +2 -2
- package/src/dex/fluid-dex/constants.ts +1 -2
- package/src/dex/fluid-dex/fluid-dex-e2e.test.ts +117 -61
- package/src/dex/fluid-dex/fluid-dex-liquidity-proxy.ts +0 -3
- package/src/dex/fluid-dex/fluid-dex.ts +94 -96
- package/src/dex/fluid-dex/types.ts +0 -3
- package/src/dex/index.ts +2 -0
- package/src/dex/m-token/config.ts +18 -0
- package/src/dex/m-token/m-token-e2e.test.ts +93 -0
- package/src/dex/m-token/m-token-integration.test.ts +199 -0
- package/src/dex/m-token/m-token.ts +167 -0
- package/src/dex/m-token/m-wrapped-m.ts +68 -0
- package/src/dex/m-token/types.ts +10 -0
- package/src/dex/pancakeswap-v3/pancakeswap-v3-pool.ts +0 -1
- package/src/dex/uniswap-v3/constants.ts +0 -10
- package/src/dex/uniswap-v3/contract-math/TickBitMap.ts +9 -29
- package/src/dex/uniswap-v3/contract-math/uniswap-v3-math.ts +1 -3
- package/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts +0 -1
- package/src/dex/uniswap-v3/forks/velodrome-slipstream/velodrome-slipstream-pool.ts +0 -1
- package/src/dex/uniswap-v3/types.ts +0 -1
- package/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +302 -647
- package/src/dex/uniswap-v3/uniswap-v3-pool.ts +1 -11
- package/src/dex/wusdm/config.ts +0 -7
- package/src/dex/wusdm/wusdm-e2e.test.ts +0 -20
- package/src/generic-swap-transaction-builder.ts +2 -10
- package/src/implementations/local-paraswap-sdk.ts +1 -1
- package/tests/constants-e2e.ts +8 -63
- package/tests/tenderly-simulation.ts +0 -3
- package/tests/utils-e2e.ts +7 -4
- package/src/abi/balancer-v3/directionalFeeHook.json +0 -684
- package/src/abi/balancer-v3/stableSurgeHook.json +0 -976
- package/src/dex/balancer-v3/balancer-hooks-events.test.ts +0 -166
- package/src/dex/balancer-v3/balancer-stableSurge.test.ts +0 -110
- package/src/dex/balancer-v3/balancer-test-helpers.ts +0 -199
- package/src/dex/balancer-v3/hooks/balancer-hook-event-subscriber.ts +0 -212
- package/src/dex/balancer-v3/hooks/directionalFeeHook.ts +0 -51
- package/src/dex/balancer-v3/hooks/loadHooksConfig.ts +0 -12
- package/src/dex/balancer-v3/hooks/stableSurgeHook.ts +0 -198
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
dotenv.config();
|
|
4
|
+
|
|
5
|
+
import { testE2E } from '../../../tests/utils-e2e';
|
|
6
|
+
import { Tokens, Holders } from '../../../tests/constants-e2e';
|
|
7
|
+
import { Network, ContractMethod, SwapSide } from '../../constants';
|
|
8
|
+
import { StaticJsonRpcProvider } from '@ethersproject/providers';
|
|
9
|
+
import { generateConfig } from '../../config';
|
|
10
|
+
|
|
11
|
+
function testForNetwork(
|
|
12
|
+
network: Network,
|
|
13
|
+
dexKey: string,
|
|
14
|
+
tokenASymbol: string,
|
|
15
|
+
tokenBSymbol: string,
|
|
16
|
+
tokenAAmount: string,
|
|
17
|
+
tokenBAmount: 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
|
+
[SwapSide.SELL, [ContractMethod.swapExactAmountIn]],
|
|
28
|
+
[SwapSide.BUY, [ContractMethod.swapExactAmountOut]],
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
describe(`${network}`, () => {
|
|
32
|
+
sideToContractMethods.forEach((contractMethods, side) =>
|
|
33
|
+
describe(`${side}`, () => {
|
|
34
|
+
const isSell = side === SwapSide.SELL;
|
|
35
|
+
|
|
36
|
+
contractMethods.forEach((contractMethod: ContractMethod) => {
|
|
37
|
+
describe(`${contractMethod}`, () => {
|
|
38
|
+
it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => {
|
|
39
|
+
await testE2E(
|
|
40
|
+
tokens[tokenASymbol],
|
|
41
|
+
tokens[tokenBSymbol],
|
|
42
|
+
holders[tokenASymbol],
|
|
43
|
+
isSell ? tokenAAmount : tokenBAmount,
|
|
44
|
+
side,
|
|
45
|
+
dexKey,
|
|
46
|
+
contractMethod,
|
|
47
|
+
network,
|
|
48
|
+
provider,
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => {
|
|
53
|
+
await testE2E(
|
|
54
|
+
tokens[tokenBSymbol],
|
|
55
|
+
tokens[tokenASymbol],
|
|
56
|
+
holders[tokenBSymbol],
|
|
57
|
+
isSell ? tokenBAmount : tokenAAmount,
|
|
58
|
+
side,
|
|
59
|
+
dexKey,
|
|
60
|
+
contractMethod,
|
|
61
|
+
network,
|
|
62
|
+
provider,
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}),
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
describe('MWrappedM E2E', () => {
|
|
73
|
+
const dexKey = 'MWrappedM';
|
|
74
|
+
|
|
75
|
+
describe('Mainnet', () => {
|
|
76
|
+
const network = Network.MAINNET;
|
|
77
|
+
|
|
78
|
+
const tokenASymbol: string = 'M';
|
|
79
|
+
const tokenBSymbol: string = 'WrappedM';
|
|
80
|
+
|
|
81
|
+
const tokenAAmount: string = '1000000000';
|
|
82
|
+
const tokenBAmount: string = '1000000000';
|
|
83
|
+
|
|
84
|
+
testForNetwork(
|
|
85
|
+
network,
|
|
86
|
+
dexKey,
|
|
87
|
+
tokenASymbol,
|
|
88
|
+
tokenBSymbol,
|
|
89
|
+
tokenAAmount,
|
|
90
|
+
tokenBAmount,
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
dotenv.config();
|
|
4
|
+
|
|
5
|
+
import { DummyDexHelper } from '../../dex-helper/index';
|
|
6
|
+
import { Network, SwapSide } from '../../constants';
|
|
7
|
+
import { BI_POWS } from '../../bigint-constants';
|
|
8
|
+
import { MToken } from './m-token';
|
|
9
|
+
import { MWrappedM } from './m-wrapped-m';
|
|
10
|
+
import {
|
|
11
|
+
checkPoolPrices,
|
|
12
|
+
checkPoolsLiquidity,
|
|
13
|
+
checkConstantPoolPrices,
|
|
14
|
+
} from '../../../tests/utils';
|
|
15
|
+
import { Tokens } from '../../../tests/constants-e2e';
|
|
16
|
+
|
|
17
|
+
async function testPricingOnNetwork(
|
|
18
|
+
mWrappedM: MToken,
|
|
19
|
+
network: Network,
|
|
20
|
+
dexKey: string,
|
|
21
|
+
blockNumber: number,
|
|
22
|
+
srcTokenSymbol: string,
|
|
23
|
+
destTokenSymbol: string,
|
|
24
|
+
side: SwapSide,
|
|
25
|
+
amounts: bigint[],
|
|
26
|
+
funcNameToCheck: string,
|
|
27
|
+
) {
|
|
28
|
+
const networkTokens = Tokens[network];
|
|
29
|
+
|
|
30
|
+
const pools = await mWrappedM.getPoolIdentifiers(
|
|
31
|
+
networkTokens[srcTokenSymbol],
|
|
32
|
+
networkTokens[destTokenSymbol],
|
|
33
|
+
side,
|
|
34
|
+
blockNumber,
|
|
35
|
+
);
|
|
36
|
+
console.log(
|
|
37
|
+
`${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `,
|
|
38
|
+
pools,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
expect(pools.length).toBeGreaterThan(0);
|
|
42
|
+
|
|
43
|
+
const poolPrices = await mWrappedM.getPricesVolume(
|
|
44
|
+
networkTokens[srcTokenSymbol],
|
|
45
|
+
networkTokens[destTokenSymbol],
|
|
46
|
+
amounts,
|
|
47
|
+
side,
|
|
48
|
+
blockNumber,
|
|
49
|
+
pools,
|
|
50
|
+
);
|
|
51
|
+
console.log(
|
|
52
|
+
`${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `,
|
|
53
|
+
poolPrices,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expect(poolPrices).not.toBeNull();
|
|
57
|
+
if (mWrappedM.hasConstantPriceLargeAmounts) {
|
|
58
|
+
checkConstantPoolPrices(poolPrices!, amounts, dexKey);
|
|
59
|
+
} else {
|
|
60
|
+
checkPoolPrices(poolPrices!, amounts, side, dexKey);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Check if onchain pricing equals to calculated ones
|
|
64
|
+
checkPoolPrices(poolPrices!, amounts, side, dexKey);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
describe('MWrappedM', function () {
|
|
68
|
+
const dexKey = 'MWrappedM';
|
|
69
|
+
let blockNumber: number;
|
|
70
|
+
let mWrappedM: MWrappedM;
|
|
71
|
+
|
|
72
|
+
describe('Mainnet', () => {
|
|
73
|
+
const network = Network.MAINNET;
|
|
74
|
+
const dexHelper = new DummyDexHelper(network);
|
|
75
|
+
|
|
76
|
+
const tokens = Tokens[network];
|
|
77
|
+
|
|
78
|
+
const srcTokenSymbol = 'M';
|
|
79
|
+
const destTokenSymbol = 'WrappedM';
|
|
80
|
+
|
|
81
|
+
// Don't forget to update relevant tokens in constant-e2e.ts
|
|
82
|
+
|
|
83
|
+
const amounts = [
|
|
84
|
+
0n,
|
|
85
|
+
1n * BI_POWS[tokens[srcTokenSymbol].decimals],
|
|
86
|
+
2n * BI_POWS[tokens[srcTokenSymbol].decimals],
|
|
87
|
+
3n * BI_POWS[tokens[srcTokenSymbol].decimals],
|
|
88
|
+
4n * BI_POWS[tokens[srcTokenSymbol].decimals],
|
|
89
|
+
5n * BI_POWS[tokens[srcTokenSymbol].decimals],
|
|
90
|
+
6n * BI_POWS[tokens[srcTokenSymbol].decimals],
|
|
91
|
+
7n * BI_POWS[tokens[srcTokenSymbol].decimals],
|
|
92
|
+
8n * BI_POWS[tokens[srcTokenSymbol].decimals],
|
|
93
|
+
9n * BI_POWS[tokens[srcTokenSymbol].decimals],
|
|
94
|
+
10n * BI_POWS[tokens[srcTokenSymbol].decimals],
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
beforeAll(async () => {
|
|
98
|
+
blockNumber = await dexHelper.web3Provider.eth.getBlockNumber();
|
|
99
|
+
mWrappedM = new MWrappedM(network, dexKey, dexHelper);
|
|
100
|
+
if (mWrappedM.initializePricing) {
|
|
101
|
+
await mWrappedM.initializePricing();
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('getPoolIdentifiers and getPricesVolume SELL M -> WrappedM', async function () {
|
|
106
|
+
await testPricingOnNetwork(
|
|
107
|
+
mWrappedM,
|
|
108
|
+
network,
|
|
109
|
+
dexKey,
|
|
110
|
+
blockNumber,
|
|
111
|
+
srcTokenSymbol,
|
|
112
|
+
destTokenSymbol,
|
|
113
|
+
SwapSide.SELL,
|
|
114
|
+
amounts,
|
|
115
|
+
'',
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('getPoolIdentifiers and getPricesVolume SELL WrappedM -> M', async function () {
|
|
120
|
+
await testPricingOnNetwork(
|
|
121
|
+
mWrappedM,
|
|
122
|
+
network,
|
|
123
|
+
dexKey,
|
|
124
|
+
blockNumber,
|
|
125
|
+
destTokenSymbol,
|
|
126
|
+
srcTokenSymbol,
|
|
127
|
+
SwapSide.SELL,
|
|
128
|
+
amounts,
|
|
129
|
+
'',
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('getPoolIdentifiers and getPricesVolume BUY M -> WrappedM', async function () {
|
|
134
|
+
await testPricingOnNetwork(
|
|
135
|
+
mWrappedM,
|
|
136
|
+
network,
|
|
137
|
+
dexKey,
|
|
138
|
+
blockNumber,
|
|
139
|
+
srcTokenSymbol,
|
|
140
|
+
destTokenSymbol,
|
|
141
|
+
SwapSide.BUY,
|
|
142
|
+
amounts,
|
|
143
|
+
'',
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('getPoolIdentifiers and getPricesVolume BUY WrappedM -> M', async function () {
|
|
148
|
+
await testPricingOnNetwork(
|
|
149
|
+
mWrappedM,
|
|
150
|
+
network,
|
|
151
|
+
dexKey,
|
|
152
|
+
blockNumber,
|
|
153
|
+
destTokenSymbol,
|
|
154
|
+
srcTokenSymbol,
|
|
155
|
+
SwapSide.BUY,
|
|
156
|
+
amounts,
|
|
157
|
+
'',
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('getTopPoolsForToken: M', async function () {
|
|
162
|
+
const symbol = srcTokenSymbol;
|
|
163
|
+
|
|
164
|
+
const poolLiquidity = await mWrappedM.getTopPoolsForToken(
|
|
165
|
+
tokens[symbol].address,
|
|
166
|
+
10,
|
|
167
|
+
);
|
|
168
|
+
console.log(
|
|
169
|
+
`${symbol} Top Pools:`,
|
|
170
|
+
JSON.stringify(poolLiquidity, null, 2),
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
checkPoolsLiquidity(
|
|
174
|
+
poolLiquidity,
|
|
175
|
+
Tokens[network][symbol].address,
|
|
176
|
+
dexKey,
|
|
177
|
+
);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('getTopPoolsForToken: WrappedM', async function () {
|
|
181
|
+
const symbol = destTokenSymbol;
|
|
182
|
+
|
|
183
|
+
const poolLiquidity = await mWrappedM.getTopPoolsForToken(
|
|
184
|
+
tokens[symbol].address,
|
|
185
|
+
10,
|
|
186
|
+
);
|
|
187
|
+
console.log(
|
|
188
|
+
`${symbol} Top Pools:`,
|
|
189
|
+
JSON.stringify(poolLiquidity, null, 2),
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
checkPoolsLiquidity(
|
|
193
|
+
poolLiquidity,
|
|
194
|
+
Tokens[network][symbol].address,
|
|
195
|
+
dexKey,
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
});
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { AsyncOrSync } from 'ts-essentials';
|
|
2
|
+
import type {
|
|
3
|
+
Token,
|
|
4
|
+
Address,
|
|
5
|
+
ExchangePrices,
|
|
6
|
+
PoolPrices,
|
|
7
|
+
AdapterExchangeParam,
|
|
8
|
+
Logger,
|
|
9
|
+
PoolLiquidity,
|
|
10
|
+
} from '../../types';
|
|
11
|
+
import { SwapSide, Network } from '../../constants';
|
|
12
|
+
import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
|
|
13
|
+
import { IDex } from '../idex';
|
|
14
|
+
import { IDexHelper } from '../../dex-helper/idex-helper';
|
|
15
|
+
import type { MTokenData, DexParams } from './types';
|
|
16
|
+
import { SimpleExchange } from '../simple-exchange';
|
|
17
|
+
import { BI_POWS } from '../../bigint-constants';
|
|
18
|
+
|
|
19
|
+
export class MToken extends SimpleExchange implements IDex<MTokenData> {
|
|
20
|
+
readonly hasConstantPriceLargeAmounts = true;
|
|
21
|
+
|
|
22
|
+
readonly needWrapNative = false;
|
|
23
|
+
|
|
24
|
+
readonly isFeeOnTransferSupported = false;
|
|
25
|
+
|
|
26
|
+
logger: Logger;
|
|
27
|
+
|
|
28
|
+
constructor(
|
|
29
|
+
readonly network: Network,
|
|
30
|
+
readonly dexKey: string,
|
|
31
|
+
readonly dexHelper: IDexHelper,
|
|
32
|
+
readonly config: DexParams,
|
|
33
|
+
) {
|
|
34
|
+
super(dexHelper, dexKey);
|
|
35
|
+
this.logger = dexHelper.getLogger(dexKey);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// No initialization needed for constant price
|
|
39
|
+
async initializePricing() {}
|
|
40
|
+
|
|
41
|
+
// Legacy: was only used for V5
|
|
42
|
+
// Returns the list of contract adapters (name and index)
|
|
43
|
+
// for a buy/sell. Return null if there are no adapters.
|
|
44
|
+
getAdapters() {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Returns list of pool identifiers that can be used
|
|
49
|
+
// for a given swap. poolIdentifiers must be unique
|
|
50
|
+
// across DEXes. It is recommended to use
|
|
51
|
+
// ${dexKey}_${poolAddress} as a poolIdentifier
|
|
52
|
+
async getPoolIdentifiers(
|
|
53
|
+
from: Token,
|
|
54
|
+
to: Token,
|
|
55
|
+
side: SwapSide,
|
|
56
|
+
blockNumber: number,
|
|
57
|
+
): Promise<string[]> {
|
|
58
|
+
if (!this.ensureOrigin({ from, to })) {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return [`${this.dexKey}_${this.config.WrappedM.address}`];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Returns pool prices for amounts.
|
|
66
|
+
// If limitPools is defined only pools in limitPools
|
|
67
|
+
// should be used. If limitPools is undefined then
|
|
68
|
+
// any pools can be used.
|
|
69
|
+
async getPricesVolume(
|
|
70
|
+
from: Token,
|
|
71
|
+
to: Token,
|
|
72
|
+
amounts: bigint[],
|
|
73
|
+
side: SwapSide,
|
|
74
|
+
blockNumber: number,
|
|
75
|
+
limitPools?: string[],
|
|
76
|
+
): Promise<null | ExchangePrices<MTokenData>> {
|
|
77
|
+
if (!this.ensureOrigin({ from, to })) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 1:1 swap
|
|
82
|
+
// Amounts need no adjustment
|
|
83
|
+
const unitOut = BI_POWS[to.decimals];
|
|
84
|
+
|
|
85
|
+
return [
|
|
86
|
+
{
|
|
87
|
+
unit: unitOut,
|
|
88
|
+
prices: amounts,
|
|
89
|
+
data: {},
|
|
90
|
+
poolAddresses: [this.config.WrappedM.address],
|
|
91
|
+
exchange: this.dexKey,
|
|
92
|
+
gasCost: 70000,
|
|
93
|
+
poolIdentifier: this.dexKey,
|
|
94
|
+
},
|
|
95
|
+
];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Returns estimated gas cost of calldata for this DEX in multiSwap
|
|
99
|
+
getCalldataGasCost(poolPrices: PoolPrices<MTokenData>): number | number[] {
|
|
100
|
+
return CALLDATA_GAS_COST.DEX_NO_PAYLOAD;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Encode params required by the exchange adapter
|
|
104
|
+
// V5: Used for multiSwap, buy & megaSwap
|
|
105
|
+
// V6: Not used, can be left blank
|
|
106
|
+
// Hint: abiCoder.encodeParameter() could be useful
|
|
107
|
+
getAdapterParam(
|
|
108
|
+
srcToken: string,
|
|
109
|
+
destToken: string,
|
|
110
|
+
srcAmount: string,
|
|
111
|
+
destAmount: string,
|
|
112
|
+
data: MTokenData,
|
|
113
|
+
side: SwapSide,
|
|
114
|
+
): AdapterExchangeParam {
|
|
115
|
+
const exchange = this.config.WrappedM.address;
|
|
116
|
+
const payload = '0x';
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
targetExchange: exchange,
|
|
120
|
+
payload,
|
|
121
|
+
networkFee: '0',
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Returns list of top pools based on liquidity. Max
|
|
126
|
+
// limit number pools should be returned.
|
|
127
|
+
async getTopPoolsForToken(
|
|
128
|
+
tokenAddress: Address,
|
|
129
|
+
limit: number,
|
|
130
|
+
): Promise<PoolLiquidity[]> {
|
|
131
|
+
if (!this.isMOrWrappedM(tokenAddress)) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const isM =
|
|
136
|
+
tokenAddress.toLowerCase() === this.config.MToken.address.toLowerCase();
|
|
137
|
+
|
|
138
|
+
return [
|
|
139
|
+
{
|
|
140
|
+
exchange: this.dexKey,
|
|
141
|
+
address: this.config.WrappedM.address,
|
|
142
|
+
connectorTokens: [isM ? this.config.WrappedM : this.config.MToken],
|
|
143
|
+
liquidityUSD: 1000000000, // Returning a big number to prefer this DEX
|
|
144
|
+
},
|
|
145
|
+
];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Checks if the token addresses is M or WrappedM
|
|
149
|
+
isMOrWrappedM(tokenAddress: Address): boolean {
|
|
150
|
+
return (
|
|
151
|
+
tokenAddress.toLowerCase() === this.config.MToken.address.toLowerCase() ||
|
|
152
|
+
tokenAddress.toLowerCase() === this.config.WrappedM.address.toLowerCase()
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Ensures that the token addresses are correct
|
|
157
|
+
ensureOrigin(args: Partial<{ from: Token; to: Token }>): boolean {
|
|
158
|
+
const areDifferentAddresses =
|
|
159
|
+
args?.from?.address?.toLowerCase() !== args?.to?.address?.toLowerCase();
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
areDifferentAddresses &&
|
|
163
|
+
this.isMOrWrappedM(args?.from?.address || '') &&
|
|
164
|
+
this.isMOrWrappedM(args?.to?.address || '')
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Network, SwapSide } from '../../constants';
|
|
2
|
+
import { getDexKeysWithNetwork } from '../../utils';
|
|
3
|
+
import { IDexHelper } from '../../dex-helper/idex-helper';
|
|
4
|
+
import { MToken } from './m-token';
|
|
5
|
+
import type {
|
|
6
|
+
Address,
|
|
7
|
+
DexExchangeParam,
|
|
8
|
+
NumberAsString,
|
|
9
|
+
Token,
|
|
10
|
+
} from '../../types';
|
|
11
|
+
import { Interface } from '@ethersproject/abi';
|
|
12
|
+
import WRAPPED_M_ABI from '../../abi/m-token/WrappedM.abi.json';
|
|
13
|
+
import { Config } from './config';
|
|
14
|
+
|
|
15
|
+
export class MWrappedM extends MToken {
|
|
16
|
+
public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
|
|
17
|
+
getDexKeysWithNetwork(Config);
|
|
18
|
+
|
|
19
|
+
wrappedMInterface: Interface;
|
|
20
|
+
|
|
21
|
+
constructor(
|
|
22
|
+
readonly network: Network,
|
|
23
|
+
readonly dexKey: string,
|
|
24
|
+
readonly dexHelper: IDexHelper,
|
|
25
|
+
) {
|
|
26
|
+
const config = Config[dexKey][network];
|
|
27
|
+
super(network, dexKey, dexHelper, config);
|
|
28
|
+
|
|
29
|
+
this.wrappedMInterface = new Interface(WRAPPED_M_ABI);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async getDexParam(
|
|
33
|
+
from: Address,
|
|
34
|
+
to: Address,
|
|
35
|
+
srcAmount: NumberAsString,
|
|
36
|
+
destAmount: NumberAsString,
|
|
37
|
+
recipient: Address,
|
|
38
|
+
data: {},
|
|
39
|
+
side: SwapSide,
|
|
40
|
+
): Promise<DexExchangeParam> {
|
|
41
|
+
if (
|
|
42
|
+
!this.ensureOrigin({
|
|
43
|
+
from: { address: from } as Token,
|
|
44
|
+
to: { address: to } as Token,
|
|
45
|
+
})
|
|
46
|
+
) {
|
|
47
|
+
throw new Error('Unexpected token addresses');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const fn =
|
|
51
|
+
from.toLowerCase() === this.config.MToken.address.toLowerCase()
|
|
52
|
+
? 'wrap(address, uint256)'
|
|
53
|
+
: 'unwrap(address, uint256)';
|
|
54
|
+
|
|
55
|
+
const exchangeData = this.wrappedMInterface.encodeFunctionData(fn, [
|
|
56
|
+
recipient,
|
|
57
|
+
srcAmount,
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
needWrapNative: false,
|
|
62
|
+
dexFuncHasRecipient: true,
|
|
63
|
+
exchangeData,
|
|
64
|
+
targetExchange: this.config.WrappedM.address,
|
|
65
|
+
returnAmountPos: undefined,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Address } from '../../types';
|
|
2
|
+
|
|
3
|
+
// Data that returned by the API that can be used for
|
|
4
|
+
// tx building.
|
|
5
|
+
export type MTokenData = {};
|
|
6
|
+
|
|
7
|
+
export type DexParams = {
|
|
8
|
+
MToken: { address: Address; decimals: number };
|
|
9
|
+
WrappedM: { address: Address; decimals: number };
|
|
10
|
+
};
|
|
@@ -326,7 +326,6 @@ export class PancakeSwapV3EventPool extends StatefulEventSubscriber<PoolState> {
|
|
|
326
326
|
const requestedRange = this.getBitmapRangeToRequest();
|
|
327
327
|
|
|
328
328
|
return {
|
|
329
|
-
networkId: this.dexHelper.config.data.network,
|
|
330
329
|
pool: _state.pool,
|
|
331
330
|
blockTimestamp: bigIntify(_state.blockTimestamp),
|
|
332
331
|
slot0: {
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { Network } from '../../constants';
|
|
2
|
-
|
|
3
1
|
export const UNISWAPV3_TICK_GAS_COST = 24_000; // Ceiled
|
|
4
2
|
export const UNISWAPV3_TICK_BASE_OVERHEAD = 75_000;
|
|
5
3
|
export const UNISWAPV3_POOL_SEARCH_OVERHEAD = 10_000;
|
|
@@ -10,14 +8,6 @@ export const TICK_BITMAP_TO_USE = 4n;
|
|
|
10
8
|
// This is used to check if the state is still valid.
|
|
11
9
|
export const TICK_BITMAP_BUFFER = 8n;
|
|
12
10
|
|
|
13
|
-
export const TICK_BITMAP_TO_USE_BY_CHAIN: Record<number, bigint> = {
|
|
14
|
-
[Network.MAINNET]: 8n,
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export const TICK_BITMAP_BUFFER_BY_CHAIN: Record<number, bigint> = {
|
|
18
|
-
[Network.MAINNET]: 16n,
|
|
19
|
-
};
|
|
20
|
-
|
|
21
11
|
export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 128;
|
|
22
12
|
|
|
23
13
|
export const UNISWAPV3_SUBGRAPH_URL =
|
|
@@ -6,9 +6,7 @@ import { DeepReadonly } from 'ts-essentials';
|
|
|
6
6
|
import {
|
|
7
7
|
OUT_OF_RANGE_ERROR_POSTFIX,
|
|
8
8
|
TICK_BITMAP_BUFFER,
|
|
9
|
-
TICK_BITMAP_BUFFER_BY_CHAIN,
|
|
10
9
|
TICK_BITMAP_TO_USE,
|
|
11
|
-
TICK_BITMAP_TO_USE_BY_CHAIN,
|
|
12
10
|
} from '../constants';
|
|
13
11
|
|
|
14
12
|
function isWordPosOut(
|
|
@@ -17,24 +15,18 @@ function isWordPosOut(
|
|
|
17
15
|
// For pricing we use wider range to check price impact. If function called from event
|
|
18
16
|
// it must always be within buffer
|
|
19
17
|
isPriceQuery: boolean,
|
|
20
|
-
networkId: number,
|
|
21
18
|
) {
|
|
22
19
|
let lowerTickBitmapLimit;
|
|
23
20
|
let upperTickBitmapLimit;
|
|
24
21
|
|
|
25
|
-
const tickBitMapToUse =
|
|
26
|
-
TICK_BITMAP_TO_USE_BY_CHAIN[networkId] ?? TICK_BITMAP_TO_USE;
|
|
27
|
-
const tickBitMapBuffer =
|
|
28
|
-
TICK_BITMAP_BUFFER_BY_CHAIN[networkId] ?? TICK_BITMAP_BUFFER;
|
|
29
|
-
|
|
30
22
|
if (isPriceQuery) {
|
|
31
23
|
lowerTickBitmapLimit =
|
|
32
|
-
startTickBitmap - (
|
|
24
|
+
startTickBitmap - (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE);
|
|
33
25
|
upperTickBitmapLimit =
|
|
34
|
-
startTickBitmap + (
|
|
26
|
+
startTickBitmap + (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE);
|
|
35
27
|
} else {
|
|
36
|
-
lowerTickBitmapLimit = startTickBitmap -
|
|
37
|
-
upperTickBitmapLimit = startTickBitmap +
|
|
28
|
+
lowerTickBitmapLimit = startTickBitmap - TICK_BITMAP_BUFFER;
|
|
29
|
+
upperTickBitmapLimit = startTickBitmap + TICK_BITMAP_BUFFER;
|
|
38
30
|
}
|
|
39
31
|
|
|
40
32
|
_require(
|
|
@@ -51,7 +43,7 @@ export class TickBitMap {
|
|
|
51
43
|
}
|
|
52
44
|
|
|
53
45
|
static flipTick(
|
|
54
|
-
state: Pick<PoolState, 'startTickBitmap' | 'tickBitmap'
|
|
46
|
+
state: Pick<PoolState, 'startTickBitmap' | 'tickBitmap'>,
|
|
55
47
|
tick: bigint,
|
|
56
48
|
tickSpacing: bigint,
|
|
57
49
|
) {
|
|
@@ -66,7 +58,7 @@ export class TickBitMap {
|
|
|
66
58
|
|
|
67
59
|
// flipTick is used only in _updatePosition which is always state changing event
|
|
68
60
|
// Therefore it is never used in price query
|
|
69
|
-
isWordPosOut(wordPos, state.startTickBitmap, false
|
|
61
|
+
isWordPosOut(wordPos, state.startTickBitmap, false);
|
|
70
62
|
|
|
71
63
|
const stringWordPos = wordPos.toString();
|
|
72
64
|
if (state.tickBitmap[stringWordPos] === undefined) {
|
|
@@ -77,9 +69,7 @@ export class TickBitMap {
|
|
|
77
69
|
}
|
|
78
70
|
|
|
79
71
|
static nextInitializedTickWithinOneWord(
|
|
80
|
-
state: DeepReadonly<
|
|
81
|
-
Pick<PoolState, 'startTickBitmap' | 'tickBitmap' | 'networkId'>
|
|
82
|
-
>,
|
|
72
|
+
state: DeepReadonly<Pick<PoolState, 'startTickBitmap' | 'tickBitmap'>>,
|
|
83
73
|
tick: bigint,
|
|
84
74
|
tickSpacing: bigint,
|
|
85
75
|
lte: boolean,
|
|
@@ -95,12 +85,7 @@ export class TickBitMap {
|
|
|
95
85
|
const [wordPos, bitPos] = TickBitMap.position(compressed);
|
|
96
86
|
const mask = (1n << bitPos) - 1n + (1n << bitPos);
|
|
97
87
|
|
|
98
|
-
isWordPosOut(
|
|
99
|
-
wordPos,
|
|
100
|
-
state.startTickBitmap,
|
|
101
|
-
isPriceQuery,
|
|
102
|
-
state.networkId,
|
|
103
|
-
);
|
|
88
|
+
isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery);
|
|
104
89
|
let tickBitmapValue = state.tickBitmap[wordPos.toString()];
|
|
105
90
|
tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue;
|
|
106
91
|
|
|
@@ -117,12 +102,7 @@ export class TickBitMap {
|
|
|
117
102
|
const [wordPos, bitPos] = TickBitMap.position(compressed + 1n);
|
|
118
103
|
const mask = ~((1n << bitPos) - 1n);
|
|
119
104
|
|
|
120
|
-
isWordPosOut(
|
|
121
|
-
wordPos,
|
|
122
|
-
state.startTickBitmap,
|
|
123
|
-
isPriceQuery,
|
|
124
|
-
state.networkId,
|
|
125
|
-
);
|
|
105
|
+
isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery);
|
|
126
106
|
let tickBitmapValue = state.tickBitmap[wordPos.toString()];
|
|
127
107
|
tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue;
|
|
128
108
|
|
|
@@ -59,7 +59,6 @@ function _priceComputationCycles(
|
|
|
59
59
|
sqrtPriceLimitX96: bigint,
|
|
60
60
|
zeroForOne: boolean,
|
|
61
61
|
exactInput: boolean,
|
|
62
|
-
side: SwapSide,
|
|
63
62
|
): [
|
|
64
63
|
// result
|
|
65
64
|
PriceComputationState,
|
|
@@ -226,7 +225,7 @@ function _priceComputationCycles(
|
|
|
226
225
|
latestFullCycleCache.tickCount += i - 1;
|
|
227
226
|
}
|
|
228
227
|
|
|
229
|
-
if (state.amountSpecifiedRemaining !== 0n
|
|
228
|
+
if (state.amountSpecifiedRemaining !== 0n) {
|
|
230
229
|
state.amountSpecifiedRemaining = 0n;
|
|
231
230
|
state.amountCalculated = 0n;
|
|
232
231
|
}
|
|
@@ -326,7 +325,6 @@ class UniswapV3Math {
|
|
|
326
325
|
sqrtPriceLimitX96,
|
|
327
326
|
zeroForOne,
|
|
328
327
|
exactInput,
|
|
329
|
-
side,
|
|
330
328
|
);
|
|
331
329
|
if (
|
|
332
330
|
finalState.amountSpecifiedRemaining === 0n &&
|
|
@@ -123,7 +123,6 @@ export class RamsesV2EventPool extends UniswapV3EventPool {
|
|
|
123
123
|
const requestedRange = this.getBitmapRangeToRequest();
|
|
124
124
|
|
|
125
125
|
return {
|
|
126
|
-
networkId: this.dexHelper.config.data.network,
|
|
127
126
|
pool: _state.pool,
|
|
128
127
|
blockTimestamp: bigIntify(_state.blockTimestamp),
|
|
129
128
|
slot0: {
|
|
@@ -125,7 +125,6 @@ export class VelodromeSlipstreamEventPool extends UniswapV3EventPool {
|
|
|
125
125
|
const requestedRange = this.getBitmapRangeToRequest();
|
|
126
126
|
|
|
127
127
|
return {
|
|
128
|
-
networkId: this.dexHelper.config.data.network,
|
|
129
128
|
pool: _state.pool,
|
|
130
129
|
fee,
|
|
131
130
|
blockTimestamp: bigIntify(_state.blockTimestamp),
|