@marko00/routing-finder-mare 1.0.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/.idea/copilot.data.migration.agent.xml +6 -0
- package/.idea/copilot.data.migration.ask.xml +6 -0
- package/.idea/copilot.data.migration.ask2agent.xml +6 -0
- package/.idea/copilot.data.migration.edit.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/php.xml +19 -0
- package/.idea/ratex-sdk.iml +8 -0
- package/.idea/vcs.xml +6 -0
- package/LICENSE-MIT +21 -0
- package/README.md +209 -0
- package/contracts/abi/BalancerHelperAbi.ts +1 -0
- package/contracts/abi/CamelotHelperAbi.ts +1 -0
- package/contracts/abi/RateXAbi.ts +482 -0
- package/contracts/abi/SushiSwapHelperAbi.ts +1 -0
- package/contracts/abi/UniswapHelperAbi.ts +1 -0
- package/contracts/abi/UniswapV2HelperAbi.ts +1 -0
- package/contracts/addresses-arbitrum.ts +8 -0
- package/contracts/addresses-mainnet.ts +7 -0
- package/contracts/addresses-polkadot.ts +9 -0
- package/contracts/addresses-sei.ts +9 -0
- package/contracts/rateX/BalancerHelper.ts +13 -0
- package/contracts/rateX/CamelotHelper.ts +13 -0
- package/contracts/rateX/SushiSwapHelper.ts +13 -0
- package/contracts/rateX/UniswapHelper.ts +19 -0
- package/contracts/rateX/UniswapV2Helper.ts +19 -0
- package/dexes/dexIdsList.ts +9 -0
- package/dexes/graph_queries/BalancerV2.ts +150 -0
- package/dexes/graph_queries/CamelotV2.ts +202 -0
- package/dexes/graph_queries/SushiSwapV2.ts +283 -0
- package/dexes/graph_queries/UniswapV2.ts +252 -0
- package/dexes/graph_queries/UniswapV3.ts +229 -0
- package/dexes/graph_queries/graphQueryFilters.ts +41 -0
- package/dexes/graph_queries/x_template.ts +67 -0
- package/dexes/pools/Balancer/BalancerState.ts +34 -0
- package/dexes/pools/Balancer/BalancerWeightedPool.ts +96 -0
- package/dexes/pools/Camelot.ts +164 -0
- package/dexes/pools/SushiSwapV2.ts +35 -0
- package/dexes/pools/UniswapV2.ts +36 -0
- package/dexes/pools/uniswap/UniswapV3.ts +40 -0
- package/dexes/pools/uniswap/testUniswapOffchainQuoter.ts +169 -0
- package/dexes/pools/uniswap/types.ts +174 -0
- package/dexes/pools/uniswap/uniswapOffchainQuoter.ts +173 -0
- package/dexes/pools/uniswap/uniswapState.ts +56 -0
- package/dexes/pools/uniswap/utils.ts +71 -0
- package/dist/contracts/abi/BalancerHelperAbi.d.ts +25 -0
- package/dist/contracts/abi/BalancerHelperAbi.js +4 -0
- package/dist/contracts/abi/CamelotHelperAbi.d.ts +45 -0
- package/dist/contracts/abi/CamelotHelperAbi.js +4 -0
- package/dist/contracts/abi/RateXAbi.d.ts +71 -0
- package/dist/contracts/abi/RateXAbi.js +485 -0
- package/dist/contracts/abi/SushiSwapHelperAbi.d.ts +45 -0
- package/dist/contracts/abi/SushiSwapHelperAbi.js +4 -0
- package/dist/contracts/abi/UniswapHelperAbi.d.ts +39 -0
- package/dist/contracts/abi/UniswapHelperAbi.js +4 -0
- package/dist/contracts/abi/UniswapV2HelperAbi.d.ts +45 -0
- package/dist/contracts/abi/UniswapV2HelperAbi.js +4 -0
- package/dist/contracts/addresses-arbitrum.d.ts +6 -0
- package/dist/contracts/addresses-arbitrum.js +10 -0
- package/dist/contracts/addresses-mainnet.d.ts +6 -0
- package/dist/contracts/addresses-mainnet.js +10 -0
- package/dist/contracts/addresses-polkadot.d.ts +6 -0
- package/dist/contracts/addresses-polkadot.js +10 -0
- package/dist/contracts/addresses-sei.d.ts +6 -0
- package/dist/contracts/addresses-sei.js +10 -0
- package/dist/contracts/rateX/BalancerHelper.d.ts +26 -0
- package/dist/contracts/rateX/BalancerHelper.js +14 -0
- package/dist/contracts/rateX/CamelotHelper.d.ts +46 -0
- package/dist/contracts/rateX/CamelotHelper.js +14 -0
- package/dist/contracts/rateX/SushiSwapHelper.d.ts +46 -0
- package/dist/contracts/rateX/SushiSwapHelper.js +14 -0
- package/dist/contracts/rateX/UniswapHelper.d.ts +40 -0
- package/dist/contracts/rateX/UniswapHelper.js +22 -0
- package/dist/contracts/rateX/UniswapV2Helper.d.ts +46 -0
- package/dist/contracts/rateX/UniswapV2Helper.js +22 -0
- package/dist/dexes/dexIdsList.d.ts +9 -0
- package/dist/dexes/dexIdsList.js +12 -0
- package/dist/dexes/graph_queries/BalancerV2.d.ts +14 -0
- package/dist/dexes/graph_queries/BalancerV2.js +141 -0
- package/dist/dexes/graph_queries/CamelotV2.d.ts +14 -0
- package/dist/dexes/graph_queries/CamelotV2.js +183 -0
- package/dist/dexes/graph_queries/SushiSwapV2.d.ts +14 -0
- package/dist/dexes/graph_queries/SushiSwapV2.js +263 -0
- package/dist/dexes/graph_queries/UniswapV2.d.ts +14 -0
- package/dist/dexes/graph_queries/UniswapV2.js +217 -0
- package/dist/dexes/graph_queries/UniswapV3.d.ts +14 -0
- package/dist/dexes/graph_queries/UniswapV3.js +198 -0
- package/dist/dexes/graph_queries/graphQueryFilters.d.ts +19 -0
- package/dist/dexes/graph_queries/graphQueryFilters.js +40 -0
- package/dist/dexes/graph_queries/x_template.d.ts +12 -0
- package/dist/dexes/graph_queries/x_template.js +57 -0
- package/dist/dexes/pools/Balancer/BalancerState.d.ts +6 -0
- package/dist/dexes/pools/Balancer/BalancerState.js +32 -0
- package/dist/dexes/pools/Balancer/BalancerWeightedPool.d.ts +12 -0
- package/dist/dexes/pools/Balancer/BalancerWeightedPool.js +109 -0
- package/dist/dexes/pools/Camelot.d.ts +12 -0
- package/dist/dexes/pools/Camelot.js +135 -0
- package/dist/dexes/pools/SushiSwapV2.d.ts +9 -0
- package/dist/dexes/pools/SushiSwapV2.js +34 -0
- package/dist/dexes/pools/UniswapV2.d.ts +9 -0
- package/dist/dexes/pools/UniswapV2.js +34 -0
- package/dist/dexes/pools/uniswap/UniswapV3.d.ts +7 -0
- package/dist/dexes/pools/uniswap/UniswapV3.js +36 -0
- package/dist/dexes/pools/uniswap/types.d.ts +76 -0
- package/dist/dexes/pools/uniswap/types.js +111 -0
- package/dist/dexes/pools/uniswap/uniswapOffchainQuoter.d.ts +13 -0
- package/dist/dexes/pools/uniswap/uniswapOffchainQuoter.js +121 -0
- package/dist/dexes/pools/uniswap/uniswapState.d.ts +14 -0
- package/dist/dexes/pools/uniswap/uniswapState.js +51 -0
- package/dist/dexes/pools/uniswap/utils.d.ts +3 -0
- package/dist/dexes/pools/uniswap/utils.js +41 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +41 -0
- package/dist/routes.d.ts +1 -0
- package/dist/routes.js +20 -0
- package/dist/routing/iterative_spliting/main.d.ts +3 -0
- package/dist/routing/iterative_spliting/main.js +104 -0
- package/dist/routing/iterative_spliting/multiHopSwap.d.ts +4 -0
- package/dist/routing/iterative_spliting/multiHopSwap.js +83 -0
- package/dist/routing/main.d.ts +2 -0
- package/dist/routing/main.js +22 -0
- package/dist/routing/uni_like_algo/algo_config.d.ts +2 -0
- package/dist/routing/uni_like_algo/algo_config.js +8 -0
- package/dist/routing/uni_like_algo/amount_distribution.d.ts +2 -0
- package/dist/routing/uni_like_algo/amount_distribution.js +17 -0
- package/dist/routing/uni_like_algo/compute_routes_backtrack.d.ts +3 -0
- package/dist/routing/uni_like_algo/compute_routes_backtrack.js +44 -0
- package/dist/routing/uni_like_algo/main.d.ts +2 -0
- package/dist/routing/uni_like_algo/main.js +49 -0
- package/dist/routing/uni_like_algo/routes_quoter.d.ts +21 -0
- package/dist/routing/uni_like_algo/routes_quoter.js +53 -0
- package/dist/routing/uni_like_algo/swap_finder.d.ts +25 -0
- package/dist/routing/uni_like_algo/swap_finder.js +154 -0
- package/dist/routing/uni_like_algo/types.d.ts +40 -0
- package/dist/routing/uni_like_algo/types.js +12 -0
- package/dist/swap/graph_communication.d.ts +5 -0
- package/dist/swap/graph_communication.js +187 -0
- package/dist/swap/my_local_storage.d.ts +8 -0
- package/dist/swap/my_local_storage.js +16 -0
- package/dist/utils/addresses.d.ts +24 -0
- package/dist/utils/addresses.js +60 -0
- package/dist/utils/math/fixed-points.d.ts +14 -0
- package/dist/utils/math/fixed-points.js +123 -0
- package/dist/utils/math/log-exp.d.ts +5 -0
- package/dist/utils/math/log-exp.js +385 -0
- package/dist/utils/math/math.d.ts +12 -0
- package/dist/utils/math/math.js +50 -0
- package/dist/utils/types/types.d.ts +51 -0
- package/dist/utils/types/types.js +25 -0
- package/dist/utils/utils.d.ts +20 -0
- package/dist/utils/utils.js +72 -0
- package/images/decenter_logo.png +0 -0
- package/index.ts +50 -0
- package/package.json +39 -0
- package/routes.ts +27 -0
- package/routing/iterative_spliting/main.ts +131 -0
- package/routing/iterative_spliting/multiHopSwap.ts +98 -0
- package/routing/main.ts +22 -0
- package/routing/uni_like_algo/algo_config.ts +7 -0
- package/routing/uni_like_algo/amount_distribution.ts +16 -0
- package/routing/uni_like_algo/compute_routes_backtrack.ts +81 -0
- package/routing/uni_like_algo/main.ts +65 -0
- package/routing/uni_like_algo/routes_quoter.ts +63 -0
- package/routing/uni_like_algo/swap_finder.ts +185 -0
- package/routing/uni_like_algo/types.ts +54 -0
- package/swap/graph_communication.ts +212 -0
- package/swap/my_local_storage.ts +27 -0
- package/tsconfig.json +26 -0
- package/utils/addresses.ts +64 -0
- package/utils/math/fixed-points.ts +88 -0
- package/utils/math/log-exp.ts +469 -0
- package/utils/math/math.ts +46 -0
- package/utils/types/types.ts +100 -0
- package/utils/utils.ts +125 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const graphql_1 = require("graphql");
|
|
4
|
+
const graphql_request_1 = require("graphql-request");
|
|
5
|
+
const dexIdsList_1 = require("../dexIdsList");
|
|
6
|
+
const uniswapState_1 = require("../pools/uniswap/uniswapState");
|
|
7
|
+
const UniswapV3_1 = require("../pools/uniswap/UniswapV3");
|
|
8
|
+
const graphQueryFilters_1 = require("./graphQueryFilters");
|
|
9
|
+
class UniswapV3 {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.endpoint = ``;
|
|
12
|
+
this.chainId = 1;
|
|
13
|
+
this.dexId = dexIdsList_1.dexIds.UNI_V3;
|
|
14
|
+
this.myLocalStorage = null;
|
|
15
|
+
}
|
|
16
|
+
static initialize(myLocalStorage) {
|
|
17
|
+
const object = new UniswapV3();
|
|
18
|
+
object.myLocalStorage = myLocalStorage;
|
|
19
|
+
return object;
|
|
20
|
+
}
|
|
21
|
+
setEndpoint(chainId, graphApiKey) {
|
|
22
|
+
if (chainId == 1329) {
|
|
23
|
+
this.endpoint = 'https://indexer.us.hyperindex.xyz/32230f9/converter';
|
|
24
|
+
}
|
|
25
|
+
if (chainId == 1) {
|
|
26
|
+
this.endpoint = `https://gateway-arbitrum.network.thegraph.com/api/${graphApiKey}/subgraphs/id/5zvR82QoaXYFyDEKLZ9t6v9adgnptxYpKpSbxtgVENFV`;
|
|
27
|
+
}
|
|
28
|
+
if (chainId == 42161) {
|
|
29
|
+
this.endpoint = `https://gateway-arbitrum.network.thegraph.com/api/${graphApiKey}/subgraphs/id/FbCGRftH4a3yZugY7TnbYgPJVEv2LvMT6oF1fxPe9aJM`;
|
|
30
|
+
}
|
|
31
|
+
if (chainId == 420420417) {
|
|
32
|
+
this.endpoint = `https://saphyre-service-dev.saphyre.xyz/api/graphql/v3`;
|
|
33
|
+
}
|
|
34
|
+
this.chainId = chainId;
|
|
35
|
+
}
|
|
36
|
+
async getTopPools(numPools) {
|
|
37
|
+
const poolsInfo = [];
|
|
38
|
+
const { resultKey } = (0, graphQueryFilters_1.v3LiquidityCollection)(this.chainId);
|
|
39
|
+
const queryResult = await (0, graphql_request_1.request)(this.endpoint, queryTopPools(numPools, this.chainId));
|
|
40
|
+
queryResult[resultKey].forEach((pool) => {
|
|
41
|
+
poolsInfo.push(createPoolFromGraph(pool, this.dexId));
|
|
42
|
+
});
|
|
43
|
+
return poolsInfo;
|
|
44
|
+
}
|
|
45
|
+
async getPoolsWithTokenPair(tokenA, tokenB, numPools) {
|
|
46
|
+
const a = tokenA.toLowerCase();
|
|
47
|
+
const b = tokenB.toLowerCase();
|
|
48
|
+
const { resultKey } = (0, graphQueryFilters_1.v3LiquidityCollection)(this.chainId);
|
|
49
|
+
const [resAb, resBa] = await Promise.all([
|
|
50
|
+
(0, graphql_request_1.request)(this.endpoint, queryPoolsWithTokenPairDirected(a, b, numPools, this.chainId)),
|
|
51
|
+
(0, graphql_request_1.request)(this.endpoint, queryPoolsWithTokenPairDirected(b, a, numPools, this.chainId)),
|
|
52
|
+
]);
|
|
53
|
+
return mergePoolsByVolume([resAb[resultKey], resBa[resultKey]], numPools, this.dexId);
|
|
54
|
+
}
|
|
55
|
+
async getPoolsWithToken(token, numPools) {
|
|
56
|
+
const t = token.toLowerCase();
|
|
57
|
+
const { resultKey } = (0, graphQueryFilters_1.v3LiquidityCollection)(this.chainId);
|
|
58
|
+
const [res0, res1] = await Promise.all([
|
|
59
|
+
(0, graphql_request_1.request)(this.endpoint, queryPoolsWithTokenOnSide0(t, numPools, this.chainId)),
|
|
60
|
+
(0, graphql_request_1.request)(this.endpoint, queryPoolsWithTokenOnSide1(t, numPools, this.chainId)),
|
|
61
|
+
]);
|
|
62
|
+
return mergePoolsByVolume([res0[resultKey], res1[resultKey]], numPools, this.dexId);
|
|
63
|
+
}
|
|
64
|
+
async getAdditionalPoolDataFromSolidity(poolInfos, rpcProvider) {
|
|
65
|
+
const pools = poolInfos.map((poolInfo) => poolInfo.poolId);
|
|
66
|
+
await uniswapState_1.UniswapState.initializeFreshPoolsData(pools, this.chainId, rpcProvider);
|
|
67
|
+
const pools2 = poolInfos.map((poolInfo) => new UniswapV3_1.UniswapV3Pool(poolInfo.poolId, this.dexId, poolInfo.tokens));
|
|
68
|
+
for (const pool of pools2)
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
this.myLocalStorage.setItem(pool.poolId.toLowerCase(), pool);
|
|
71
|
+
return pools2;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.default = UniswapV3;
|
|
75
|
+
function queryTopPools(numPools, chainId) {
|
|
76
|
+
const { field } = (0, graphQueryFilters_1.v3LiquidityCollection)(chainId);
|
|
77
|
+
return (0, graphql_1.parse)((0, graphql_request_1.gql) `
|
|
78
|
+
{
|
|
79
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD) {
|
|
80
|
+
id,
|
|
81
|
+
volumeUSD,
|
|
82
|
+
token0 {
|
|
83
|
+
id,
|
|
84
|
+
name,
|
|
85
|
+
decimals,
|
|
86
|
+
},
|
|
87
|
+
token1 {
|
|
88
|
+
id,
|
|
89
|
+
name,
|
|
90
|
+
decimals,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
`);
|
|
95
|
+
}
|
|
96
|
+
function queryPoolsWithTokenPairDirected(token0Id, token1Id, numPools, chainId) {
|
|
97
|
+
const { field } = (0, graphQueryFilters_1.v3LiquidityCollection)(chainId);
|
|
98
|
+
return (0, graphql_1.parse)((0, graphql_request_1.gql) `
|
|
99
|
+
{
|
|
100
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD, where : {
|
|
101
|
+
${(0, graphQueryFilters_1.whereDirectedTokenPair)(token0Id, token1Id, chainId)},
|
|
102
|
+
}) {
|
|
103
|
+
id,
|
|
104
|
+
volumeUSD,
|
|
105
|
+
token0 {
|
|
106
|
+
id,
|
|
107
|
+
name,
|
|
108
|
+
decimals,
|
|
109
|
+
},
|
|
110
|
+
token1 {
|
|
111
|
+
id,
|
|
112
|
+
name,
|
|
113
|
+
decimals,
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
}
|
|
117
|
+
`);
|
|
118
|
+
}
|
|
119
|
+
function queryPoolsWithTokenOnSide0(token, numPools, chainId) {
|
|
120
|
+
const { field } = (0, graphQueryFilters_1.v3LiquidityCollection)(chainId);
|
|
121
|
+
return (0, graphql_1.parse)((0, graphql_request_1.gql) `
|
|
122
|
+
{
|
|
123
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD, where : {
|
|
124
|
+
${(0, graphQueryFilters_1.whereTokenOnSide)('token0', token, chainId)},
|
|
125
|
+
}) {
|
|
126
|
+
id,
|
|
127
|
+
volumeUSD,
|
|
128
|
+
token0 {
|
|
129
|
+
id,
|
|
130
|
+
name,
|
|
131
|
+
decimals,
|
|
132
|
+
},
|
|
133
|
+
token1 {
|
|
134
|
+
id,
|
|
135
|
+
name,
|
|
136
|
+
decimals,
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
`);
|
|
141
|
+
}
|
|
142
|
+
function queryPoolsWithTokenOnSide1(token, numPools, chainId) {
|
|
143
|
+
const { field } = (0, graphQueryFilters_1.v3LiquidityCollection)(chainId);
|
|
144
|
+
return (0, graphql_1.parse)((0, graphql_request_1.gql) `
|
|
145
|
+
{
|
|
146
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD, where : {
|
|
147
|
+
${(0, graphQueryFilters_1.whereTokenOnSide)('token1', token, chainId)},
|
|
148
|
+
}) {
|
|
149
|
+
id,
|
|
150
|
+
volumeUSD,
|
|
151
|
+
token0 {
|
|
152
|
+
id,
|
|
153
|
+
name,
|
|
154
|
+
decimals,
|
|
155
|
+
},
|
|
156
|
+
token1 {
|
|
157
|
+
id,
|
|
158
|
+
name,
|
|
159
|
+
decimals,
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
}
|
|
163
|
+
`);
|
|
164
|
+
}
|
|
165
|
+
function mergePoolsByVolume(poolLists, numPools, dexId) {
|
|
166
|
+
const byId = new Map();
|
|
167
|
+
for (const list of poolLists) {
|
|
168
|
+
for (const pool of list) {
|
|
169
|
+
byId.set(String(pool.id).toLowerCase(), pool);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const merged = [...byId.values()];
|
|
173
|
+
merged.sort((a, b) => {
|
|
174
|
+
const va = parseFloat(a.volumeUSD) || 0;
|
|
175
|
+
const vb = parseFloat(b.volumeUSD) || 0;
|
|
176
|
+
return vb - va;
|
|
177
|
+
});
|
|
178
|
+
return merged.slice(0, numPools).map((p) => createPoolFromGraph(p, dexId));
|
|
179
|
+
}
|
|
180
|
+
function createPoolFromGraph(jsonData, dexId) {
|
|
181
|
+
const pool = {
|
|
182
|
+
poolId: jsonData.id,
|
|
183
|
+
dexId: dexId,
|
|
184
|
+
tokens: [
|
|
185
|
+
{
|
|
186
|
+
_address: jsonData.token0.id,
|
|
187
|
+
decimals: Number(jsonData.token0.decimals),
|
|
188
|
+
name: jsonData.token0.name,
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
_address: jsonData.token1.id,
|
|
192
|
+
decimals: Number(jsonData.token1.decimals),
|
|
193
|
+
name: jsonData.token1.name,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
};
|
|
197
|
+
return pool;
|
|
198
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Chains whose graph URL goes through HyperIndex → Hasura (Saphyre / Sei). */
|
|
2
|
+
export declare function usesHyperIndexConverter(chainId: number): boolean;
|
|
3
|
+
/** V2 liquidity collection: merged schema uses V2_Factory_Pair; The Graph uses pairs. */
|
|
4
|
+
export declare function v2LiquidityCollection(chainId: number): {
|
|
5
|
+
field: string;
|
|
6
|
+
resultKey: string;
|
|
7
|
+
};
|
|
8
|
+
/** V3 liquidity collection: merged schema uses V3_Factory_Pool; The Graph uses pools. */
|
|
9
|
+
export declare function v3LiquidityCollection(chainId: number): {
|
|
10
|
+
field: string;
|
|
11
|
+
resultKey: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* `where` clause fragment for a pool/pair token side.
|
|
15
|
+
* - HyperIndex: `token0: { id: "0x..." }` (scalar address becomes invalid `token1: { _eq }` on Token_bool_exp)
|
|
16
|
+
* - The Graph: `token0: "0x..."`
|
|
17
|
+
*/
|
|
18
|
+
export declare function whereTokenOnSide(side: 'token0' | 'token1', address: string, chainId: number): string;
|
|
19
|
+
export declare function whereDirectedTokenPair(token0Id: string, token1Id: string, chainId: number): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usesHyperIndexConverter = usesHyperIndexConverter;
|
|
4
|
+
exports.v2LiquidityCollection = v2LiquidityCollection;
|
|
5
|
+
exports.v3LiquidityCollection = v3LiquidityCollection;
|
|
6
|
+
exports.whereTokenOnSide = whereTokenOnSide;
|
|
7
|
+
exports.whereDirectedTokenPair = whereDirectedTokenPair;
|
|
8
|
+
/** Chains whose graph URL goes through HyperIndex → Hasura (Saphyre / Sei). */
|
|
9
|
+
function usesHyperIndexConverter(chainId) {
|
|
10
|
+
return chainId === 1329 || chainId === 420420417;
|
|
11
|
+
}
|
|
12
|
+
/** V2 liquidity collection: merged schema uses V2_Factory_Pair; The Graph uses pairs. */
|
|
13
|
+
function v2LiquidityCollection(chainId) {
|
|
14
|
+
if (usesHyperIndexConverter(chainId)) {
|
|
15
|
+
return { field: 'V2_Factory_Pair', resultKey: 'V2_Factory_Pair' };
|
|
16
|
+
}
|
|
17
|
+
return { field: 'pairs', resultKey: 'pairs' };
|
|
18
|
+
}
|
|
19
|
+
/** V3 liquidity collection: merged schema uses V3_Factory_Pool; The Graph uses pools. */
|
|
20
|
+
function v3LiquidityCollection(chainId) {
|
|
21
|
+
if (usesHyperIndexConverter(chainId)) {
|
|
22
|
+
return { field: 'V3_Factory_Pool', resultKey: 'V3_Factory_Pool' };
|
|
23
|
+
}
|
|
24
|
+
return { field: 'pools', resultKey: 'pools' };
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* `where` clause fragment for a pool/pair token side.
|
|
28
|
+
* - HyperIndex: `token0: { id: "0x..." }` (scalar address becomes invalid `token1: { _eq }` on Token_bool_exp)
|
|
29
|
+
* - The Graph: `token0: "0x..."`
|
|
30
|
+
*/
|
|
31
|
+
function whereTokenOnSide(side, address, chainId) {
|
|
32
|
+
const id = address.toLowerCase();
|
|
33
|
+
if (usesHyperIndexConverter(chainId)) {
|
|
34
|
+
return `${side} : { id : "${id}" }`;
|
|
35
|
+
}
|
|
36
|
+
return `${side} : "${id}"`;
|
|
37
|
+
}
|
|
38
|
+
function whereDirectedTokenPair(token0Id, token1Id, chainId) {
|
|
39
|
+
return `${whereTokenOnSide('token0', token0Id, chainId)}, ${whereTokenOnSide('token1', token1Id, chainId)}`;
|
|
40
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Pool, PoolInfo, DEXGraphFunctionality } from '../../utils/types/types';
|
|
2
|
+
export default class NewDex implements DEXGraphFunctionality {
|
|
3
|
+
endpoint: string;
|
|
4
|
+
dexId: string;
|
|
5
|
+
chainId: number;
|
|
6
|
+
static initialize(): DEXGraphFunctionality;
|
|
7
|
+
setEndpoint(chainId: number): void;
|
|
8
|
+
getTopPools(numPools: number): Promise<PoolInfo[]>;
|
|
9
|
+
getPoolsWithTokenPair(token1: string, token2: string, first: number): Promise<PoolInfo[]>;
|
|
10
|
+
getPoolsWithToken(token: string, numPools: number): Promise<PoolInfo[]>;
|
|
11
|
+
getAdditionalPoolDataFromSolidity(poolInfos: PoolInfo[]): Promise<Pool[]>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const graphql_1 = require("graphql");
|
|
4
|
+
const graphql_request_1 = require("graphql-request");
|
|
5
|
+
class NewDex {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.endpoint = '';
|
|
8
|
+
this.dexId = '';
|
|
9
|
+
this.chainId = 1;
|
|
10
|
+
}
|
|
11
|
+
static initialize() {
|
|
12
|
+
return new NewDex();
|
|
13
|
+
}
|
|
14
|
+
setEndpoint(chainId) {
|
|
15
|
+
if (chainId == 42161) {
|
|
16
|
+
this.endpoint = '';
|
|
17
|
+
}
|
|
18
|
+
this.chainId = chainId;
|
|
19
|
+
}
|
|
20
|
+
async getTopPools(numPools) {
|
|
21
|
+
const poolsInfo = [];
|
|
22
|
+
const queryResult = await (0, graphql_request_1.request)(this.endpoint, queryTopPools(numPools));
|
|
23
|
+
queryResult.pairs.forEach((pair) => {
|
|
24
|
+
poolsInfo.push(pair.id);
|
|
25
|
+
});
|
|
26
|
+
return poolsInfo;
|
|
27
|
+
}
|
|
28
|
+
async getPoolsWithTokenPair(token1, token2, first) {
|
|
29
|
+
const poolsInfo = [];
|
|
30
|
+
const queryResult = await (0, graphql_request_1.request)(this.endpoint, queryPoolsWithTokenPair(token1, token2, first));
|
|
31
|
+
queryResult.pairs.forEach((pair) => {
|
|
32
|
+
poolsInfo.push(pair.id);
|
|
33
|
+
});
|
|
34
|
+
return poolsInfo;
|
|
35
|
+
}
|
|
36
|
+
async getPoolsWithToken(token, numPools) {
|
|
37
|
+
const poolsInfo = [];
|
|
38
|
+
const queryResult = await (0, graphql_request_1.request)(this.endpoint, queryPoolsWithToken(token, numPools));
|
|
39
|
+
queryResult.pairs.forEach((pair) => {
|
|
40
|
+
poolsInfo.push(pair.id);
|
|
41
|
+
});
|
|
42
|
+
return poolsInfo;
|
|
43
|
+
}
|
|
44
|
+
async getAdditionalPoolDataFromSolidity(poolInfos) {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.default = NewDex;
|
|
49
|
+
function queryTopPools(numPools) {
|
|
50
|
+
return (0, graphql_1.parse)((0, graphql_request_1.gql) ``);
|
|
51
|
+
}
|
|
52
|
+
function queryPoolsWithTokenPair(tokenA, tokenB, numPools) {
|
|
53
|
+
return (0, graphql_1.parse)((0, graphql_request_1.gql) ``);
|
|
54
|
+
}
|
|
55
|
+
function queryPoolsWithToken(token, numPools) {
|
|
56
|
+
return (0, graphql_1.parse)((0, graphql_request_1.gql) ``);
|
|
57
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BalancerState = void 0;
|
|
4
|
+
const BalancerWeightedPool_1 = require("./BalancerWeightedPool");
|
|
5
|
+
const BalancerHelper_1 = require("../../../contracts/rateX/BalancerHelper");
|
|
6
|
+
class BalancerState {
|
|
7
|
+
constructor() { }
|
|
8
|
+
static async getPoolDataFromContract(pools, chainId, rpcProvider) {
|
|
9
|
+
const promises = pools.map(async (pool) => {
|
|
10
|
+
// return token address after '-' split
|
|
11
|
+
pool.tokens.forEach((token) => token._address = token._address.split('-')[1]);
|
|
12
|
+
const BalancerHelperContract = (0, BalancerHelper_1.CreateBalancerHelperContract)(chainId, rpcProvider);
|
|
13
|
+
try {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
const res = await BalancerHelperContract.methods
|
|
16
|
+
.getWeightedPoolInfo(pool.poolId)
|
|
17
|
+
.call();
|
|
18
|
+
const [decimals, tokens, balances, weights, swapFeePercentage] = [res[0], res[1], res[2], res[3], res[4]];
|
|
19
|
+
const weightedPool = new BalancerWeightedPool_1.BalancerWeightedPool(pool.poolId, pool.dexId, pool.tokens, balances, weights, swapFeePercentage);
|
|
20
|
+
return weightedPool;
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
console.log('Weighted Get Pool Info Error: ', err);
|
|
24
|
+
return null; // Handle the error as needed
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
const newPools = await Promise.all(promises);
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
return newPools.filter((pool) => pool !== null); // Filter out any null values
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.BalancerState = BalancerState;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Token, Pool } from '../../../utils/types/types';
|
|
2
|
+
import BigNumber from 'bignumber.js';
|
|
3
|
+
export declare class BalancerWeightedPool extends Pool {
|
|
4
|
+
reserves: BigNumber[];
|
|
5
|
+
startingReserves: BigNumber[];
|
|
6
|
+
weights: BigNumber[];
|
|
7
|
+
swapFeePercentage: BigNumber;
|
|
8
|
+
constructor(poolId: string, dexId: string, tokens: Token[], reserves: BigInt[], weights: BigInt[], swapFeePercentage: BigInt);
|
|
9
|
+
reset(): void;
|
|
10
|
+
calculateExpectedOutputAmount(tokenIn: string, tokenOut: string, amountIn: bigint): bigint;
|
|
11
|
+
update(tokenIn: string, tokenOut: string, amountIn: bigint, amountOut: bigint): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Ported from Solidity: https://github.com/balancer/balancer-v2-monorepo/blob/master/pkg/pool-weighted/contracts/WeightedMath.sol
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.BalancerWeightedPool = void 0;
|
|
41
|
+
const types_1 = require("../../../utils/types/types");
|
|
42
|
+
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
43
|
+
const fp = __importStar(require("../../../utils/math/fixed-points"));
|
|
44
|
+
const math = __importStar(require("../../../utils/math/math"));
|
|
45
|
+
// Swap limits: amounts swapped may not be larger than this percentage of total balance of the token being swapped
|
|
46
|
+
// Example - if the pool has 100 WETH, we can swap a maximum od 30 WETH
|
|
47
|
+
const _MAX_IN_RATIO = new bignumber_js_1.default(0.3e18);
|
|
48
|
+
class BalancerWeightedPool extends types_1.Pool {
|
|
49
|
+
constructor(poolId, dexId, tokens, reserves, weights, swapFeePercentage) {
|
|
50
|
+
super(poolId, dexId, tokens);
|
|
51
|
+
this.reserves = reserves.map((r) => new bignumber_js_1.default(r.toString()));
|
|
52
|
+
this.startingReserves = [...this.reserves];
|
|
53
|
+
this.weights = weights.map((r) => new bignumber_js_1.default(r.toString()));
|
|
54
|
+
this.swapFeePercentage = new bignumber_js_1.default(swapFeePercentage.toString());
|
|
55
|
+
}
|
|
56
|
+
reset() {
|
|
57
|
+
this.reserves = [...this.startingReserves];
|
|
58
|
+
}
|
|
59
|
+
calculateExpectedOutputAmount(tokenIn, tokenOut, amountIn) {
|
|
60
|
+
return calculateOutputAmount(this, tokenIn, tokenOut, (0, bignumber_js_1.default)(amountIn.toString()));
|
|
61
|
+
}
|
|
62
|
+
update(tokenIn, tokenOut, amountIn, amountOut) {
|
|
63
|
+
// CHECK ???
|
|
64
|
+
const i = this.tokens.findIndex((token) => token._address === tokenIn);
|
|
65
|
+
const j = this.tokens.findIndex((token) => token._address === tokenOut);
|
|
66
|
+
this.reserves[i] = fp.add(this.reserves[i], (0, bignumber_js_1.default)(amountIn.toString()));
|
|
67
|
+
this.reserves[j] = fp.sub(this.reserves[j], (0, bignumber_js_1.default)(amountOut.toString()));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.BalancerWeightedPool = BalancerWeightedPool;
|
|
71
|
+
function calculateOutputAmount(pool, tokenA, tokenB, tokenAmountIn, swapFeePercentage) {
|
|
72
|
+
// Subtract the fee from the amount in if requested
|
|
73
|
+
if (swapFeePercentage)
|
|
74
|
+
tokenAmountIn = fp.sub(tokenAmountIn, fp.mulUp(tokenAmountIn, swapFeePercentage));
|
|
75
|
+
// Get the index of the token we are swapping from and to
|
|
76
|
+
const i = pool.tokens.findIndex((token) => token._address === tokenA);
|
|
77
|
+
const j = pool.tokens.findIndex((token) => token._address === tokenB);
|
|
78
|
+
try {
|
|
79
|
+
const res = _calcOutGivenIn(pool.reserves[i], pool.weights[i], pool.reserves[j], pool.weights[j], tokenAmountIn);
|
|
80
|
+
return BigInt(res.toFixed());
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
return BigInt(0);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/* Computes how many tokens can be taken out of a pool if `amountIn` are sent, given the current balances and weights.
|
|
87
|
+
Amount out, so we round down overall:
|
|
88
|
+
**********************************************************************************************
|
|
89
|
+
// outGivenIn //
|
|
90
|
+
// aO = amountOut //
|
|
91
|
+
// bO = balanceOut //
|
|
92
|
+
// bI = balanceIn / / bI \ (wI / wO) \ //
|
|
93
|
+
// aI = amountIn aO = bO * | 1 - | -------------------------- | ^ | //
|
|
94
|
+
// wI = weightIn \ \ ( bI + aI ) / / //
|
|
95
|
+
// wO = weightOut //
|
|
96
|
+
**********************************************************************************************
|
|
97
|
+
The multiplication rounds down, and the subtrahend (power) runds up (so the base rounds up too).
|
|
98
|
+
Because bI / (bI + aI) <= 1, the exponent rounds down. */
|
|
99
|
+
// Ovde puca!!!!!!!!!!!!!!
|
|
100
|
+
function _calcOutGivenIn(balanceIn, weightIn, balanceOut, weightOut, amountIn) {
|
|
101
|
+
// Cannot exceed maximum in ratio (30% of tokenIn balance)
|
|
102
|
+
if (amountIn.gte(fp.mulDown(balanceIn, _MAX_IN_RATIO)))
|
|
103
|
+
throw new Error('MAX_IN_RATIO');
|
|
104
|
+
const denominator = math.add(balanceIn, amountIn);
|
|
105
|
+
const base = fp.divUp(balanceIn, denominator);
|
|
106
|
+
const exponent = fp.divDown(weightIn, weightOut);
|
|
107
|
+
const power = fp.powUp(base, exponent);
|
|
108
|
+
return fp.mulDown(balanceOut, fp.complement(power));
|
|
109
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Pool, Token } from '../../utils/types/types';
|
|
2
|
+
import BigNumber from "bignumber.js";
|
|
3
|
+
export declare class CamelotPool extends Pool {
|
|
4
|
+
fees: BigNumber[];
|
|
5
|
+
reserves: BigNumber[];
|
|
6
|
+
startingReserves: BigNumber[];
|
|
7
|
+
stableSwap: boolean;
|
|
8
|
+
constructor(poolId: string, dexId: string, tokens: Token[], reserves: bigint[], fees: bigint[], stableSwap: boolean);
|
|
9
|
+
reset(): void;
|
|
10
|
+
calculateExpectedOutputAmount(tokenIn: string, tokenOut: string, amountIn: bigint): bigint;
|
|
11
|
+
update(tokenIn: string, tokenOut: string, amountIn: bigint, amountOut: bigint): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CamelotPool = void 0;
|
|
7
|
+
const types_1 = require("../../utils/types/types");
|
|
8
|
+
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
9
|
+
// Camelot V2 pools have 2 tokens in the pool, and a fee
|
|
10
|
+
// Example contracts of one Camelot V2 pool: https://arbiscan.io/address/0xa6c5c7d189fa4eb5af8ba34e63dcdd3a635d433f#readContract
|
|
11
|
+
const feeDenominator = new bignumber_js_1.default(100000);
|
|
12
|
+
class CamelotPool extends types_1.Pool {
|
|
13
|
+
constructor(poolId, dexId, tokens, reserves, fees, stableSwap) {
|
|
14
|
+
super(poolId, dexId, tokens);
|
|
15
|
+
this.reserves = reserves.map((r) => (0, bignumber_js_1.default)(r.toString()));
|
|
16
|
+
this.startingReserves = [...this.reserves];
|
|
17
|
+
this.fees = fees.map((f) => (0, bignumber_js_1.default)(f.toString()));
|
|
18
|
+
this.stableSwap = stableSwap;
|
|
19
|
+
}
|
|
20
|
+
reset() {
|
|
21
|
+
this.reserves = [...this.startingReserves];
|
|
22
|
+
}
|
|
23
|
+
// function getAmountOut on Camelot V2 pools smart contracts
|
|
24
|
+
calculateExpectedOutputAmount(tokenIn, tokenOut, amountIn) {
|
|
25
|
+
// this function will be called by our routing algorithm which uses bigint values
|
|
26
|
+
const amountInBN = new bignumber_js_1.default(amountIn.toString());
|
|
27
|
+
if (this.stableSwap)
|
|
28
|
+
return calculateStableSwap(this, tokenIn, tokenOut, amountInBN);
|
|
29
|
+
else
|
|
30
|
+
return calculateRegularSwap(this, tokenIn, tokenOut, amountInBN);
|
|
31
|
+
}
|
|
32
|
+
update(tokenIn, tokenOut, amountIn, amountOut) {
|
|
33
|
+
const i = this.tokens.findIndex((token) => token._address === tokenIn);
|
|
34
|
+
const j = this.tokens.findIndex((token) => token._address === tokenOut);
|
|
35
|
+
this.reserves[i] = this.reserves[i].plus((0, bignumber_js_1.default)(amountIn.toString()));
|
|
36
|
+
this.reserves[j] = this.reserves[j].minus((0, bignumber_js_1.default)(amountOut.toString()));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.CamelotPool = CamelotPool;
|
|
40
|
+
function calculateStableSwap(pool, tokenIn, tokenOut, amountIn) {
|
|
41
|
+
const feePercent = tokenIn.toLowerCase() === pool.tokens[0]._address.toLowerCase() ? pool.fees[0] : pool.fees[1];
|
|
42
|
+
let reserve0 = pool.reserves[0];
|
|
43
|
+
let reserve1 = pool.reserves[1];
|
|
44
|
+
const precisionMultiplier0 = new bignumber_js_1.default(10 ** pool.tokens[0].decimals);
|
|
45
|
+
const precisionMultiplier1 = new bignumber_js_1.default(10 ** pool.tokens[1].decimals);
|
|
46
|
+
amountIn = amountIn.minus(amountIn.times(feePercent).div(feeDenominator)); // remove fee from amount received
|
|
47
|
+
const xy = _k(pool);
|
|
48
|
+
reserve0 = reserve0.times(1e18).div(precisionMultiplier0);
|
|
49
|
+
reserve1 = reserve1.times(1e18).div(precisionMultiplier1);
|
|
50
|
+
const [reserveA, reserveB] = tokenIn.toLowerCase() === pool.tokens[0]._address.toLowerCase()
|
|
51
|
+
? [reserve0, reserve1]
|
|
52
|
+
: [reserve1, reserve0];
|
|
53
|
+
// amountIn = tokenIn == token0 ? amountIn * 1e18 / precisionMultiplier0 : amountIn * 1e18 / precisionMultiplier1;
|
|
54
|
+
amountIn = tokenIn.toLowerCase() === pool.tokens[0]._address.toLowerCase()
|
|
55
|
+
? amountIn.times(1e18).div(precisionMultiplier0)
|
|
56
|
+
: amountIn.times(1e18).div(precisionMultiplier1);
|
|
57
|
+
// uint y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);
|
|
58
|
+
const y = reserveB.minus(_get_y(amountIn.plus(reserveA), xy, reserveB));
|
|
59
|
+
// return y * (tokenIn == token0 ? precisionMultiplier1 : precisionMultiplier0) / 1e18;
|
|
60
|
+
let result = tokenIn.toLowerCase() === pool.tokens[0]._address.toLowerCase()
|
|
61
|
+
? y.times(precisionMultiplier1).div(1e18)
|
|
62
|
+
: y.times(precisionMultiplier0).div(1e18);
|
|
63
|
+
result = floor(result);
|
|
64
|
+
return BigInt(result.toFixed());
|
|
65
|
+
}
|
|
66
|
+
// named the same as in Camelot V2 pools smart contracts
|
|
67
|
+
function _k(pool) {
|
|
68
|
+
// for simplicity extract values
|
|
69
|
+
let reserve0 = pool.reserves[0];
|
|
70
|
+
let reserve1 = pool.reserves[1];
|
|
71
|
+
if (pool.stableSwap) {
|
|
72
|
+
const precisionMultiplier0 = new bignumber_js_1.default(10 ** pool.tokens[0].decimals);
|
|
73
|
+
const precisionMultiplier1 = new bignumber_js_1.default(10 ** pool.tokens[1].decimals);
|
|
74
|
+
const x = reserve0.times(1e18).div(precisionMultiplier0);
|
|
75
|
+
const y = reserve1.times(1e18).div(precisionMultiplier1);
|
|
76
|
+
const a = x.times(y).div(1e18);
|
|
77
|
+
const b = x.times(x).div(1e18).plus(y.times(y).div(1e18));
|
|
78
|
+
let res = a.times(b).div(1e18);
|
|
79
|
+
return floor(res); // x3y+y3x >= k
|
|
80
|
+
}
|
|
81
|
+
return reserve0.times(reserve1);
|
|
82
|
+
}
|
|
83
|
+
// named the same as in Camelot V2 pools smart contracts
|
|
84
|
+
function _get_y(x0, xy, y) {
|
|
85
|
+
for (let i = 0; i < 255; i++) {
|
|
86
|
+
const y_prev = y;
|
|
87
|
+
const k = _f(x0, y);
|
|
88
|
+
if (k.lt(xy)) {
|
|
89
|
+
let dy = xy.minus(k).times(1e18).dividedToIntegerBy(_d(x0, y));
|
|
90
|
+
y = y.plus(dy);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
let dy = k.minus(xy).times(1e18).dividedToIntegerBy(_d(x0, y));
|
|
94
|
+
y = y.minus(dy);
|
|
95
|
+
}
|
|
96
|
+
const diff = y.minus(y_prev).abs();
|
|
97
|
+
if (diff.lte(1))
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
return floor(y);
|
|
101
|
+
}
|
|
102
|
+
function _f(x0, y) {
|
|
103
|
+
// return x0 * (y * y / 1e18 * y / 1e18) / 1e18 + (x0 * x0 / 1e18 * x0 / 1e18) * y / 1e18;
|
|
104
|
+
const ySquared = y.times(y).dividedToIntegerBy(1e18);
|
|
105
|
+
const x0Squared = x0.times(x0).dividedToIntegerBy(1e18);
|
|
106
|
+
const term1 = x0.times((ySquared).times(y).dividedToIntegerBy(1e18)).dividedToIntegerBy(1e18);
|
|
107
|
+
const term2 = y.times(x0Squared.times(x0).dividedToIntegerBy(1e18)).dividedToIntegerBy(1e18);
|
|
108
|
+
return term1.plus(term2);
|
|
109
|
+
}
|
|
110
|
+
function _d(x0, y) {
|
|
111
|
+
// return 3 * x0 * (y * y / 1e18) / 1e18 + (x0 * x0 / 1e18 * x0 / 1e18);
|
|
112
|
+
const ySquared = y.times(y).dividedToIntegerBy(1e18);
|
|
113
|
+
const x0Squared = x0.times(x0).dividedToIntegerBy(1e18);
|
|
114
|
+
const term1 = x0.times(ySquared).times(3).dividedToIntegerBy(1e18);
|
|
115
|
+
const term2 = x0Squared.times(x0).dividedToIntegerBy(1e18);
|
|
116
|
+
return term1.plus(term2);
|
|
117
|
+
}
|
|
118
|
+
function calculateRegularSwap(pool, tokenIn, tokenOut, amountIn) {
|
|
119
|
+
const feePercent = tokenIn.toLowerCase() === pool.tokens[0]._address.toLowerCase() ? pool.fees[0] : pool.fees[1];
|
|
120
|
+
const [reserveA, reserveB] = tokenIn.toLowerCase() === pool.tokens[0]._address.toLowerCase()
|
|
121
|
+
? [pool.reserves[0], pool.reserves[1]]
|
|
122
|
+
: [pool.reserves[1], pool.reserves[0]];
|
|
123
|
+
amountIn = amountIn.times(feeDenominator.minus(feePercent));
|
|
124
|
+
const numerator = amountIn.times(reserveB);
|
|
125
|
+
const denominator = reserveA.times(feeDenominator).plus(amountIn);
|
|
126
|
+
const result = floor(numerator.div(denominator));
|
|
127
|
+
return BigInt(result.toFixed());
|
|
128
|
+
}
|
|
129
|
+
/* Custom floor function because BigNumber library does not implement it
|
|
130
|
+
@param num: the BigNumber number to be floored
|
|
131
|
+
*/
|
|
132
|
+
function floor(num) {
|
|
133
|
+
const whole = num.toFixed().toString().split('.')[0];
|
|
134
|
+
return new bignumber_js_1.default(whole);
|
|
135
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Pool, Token } from '../../utils/types/types';
|
|
2
|
+
export declare class SushiSwapV2Pool extends Pool {
|
|
3
|
+
reserves: bigint[];
|
|
4
|
+
startingReserves: bigint[];
|
|
5
|
+
constructor(poolId: string, dexId: string, tokens: Token[], reserves: bigint[]);
|
|
6
|
+
reset(): void;
|
|
7
|
+
calculateExpectedOutputAmount(tokenIn: string, tokenOut: string, amountIn: bigint): bigint;
|
|
8
|
+
update(tokenIn: string, tokenOut: string, amountIn: bigint, amountOut: bigint): void;
|
|
9
|
+
}
|