@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,252 @@
|
|
|
1
|
+
import { parse } from 'graphql'
|
|
2
|
+
import { gql, request } from 'graphql-request'
|
|
3
|
+
import { TypedDocumentNode } from '@graphql-typed-document-node/core'
|
|
4
|
+
import { dexIds } from '../dexIdsList'
|
|
5
|
+
import { Pool, PoolInfo, Token, DEXGraphFunctionality } from '../../utils/types/types'
|
|
6
|
+
import { UniswapV2Pool } from '../pools/UniswapV2'
|
|
7
|
+
import Web3 from 'web3'
|
|
8
|
+
import { CreateUniswapV2HelperContract } from '../../contracts/rateX/UniswapV2Helper'
|
|
9
|
+
import { v2LiquidityCollection, whereDirectedTokenPair, whereTokenOnSide } from './graphQueryFilters'
|
|
10
|
+
|
|
11
|
+
export default class UniswapV2 implements DEXGraphFunctionality {
|
|
12
|
+
endpoint = ``
|
|
13
|
+
chainId = 1
|
|
14
|
+
dexId = dexIds.UNI_V2
|
|
15
|
+
myLocalStorage = null
|
|
16
|
+
|
|
17
|
+
static initialize(myLocalStorage: any): DEXGraphFunctionality {
|
|
18
|
+
const object = new UniswapV2();
|
|
19
|
+
object.myLocalStorage = myLocalStorage;
|
|
20
|
+
return object
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// @reminder add uniswapv2 real endpoint for arbitrum
|
|
24
|
+
setEndpoint(chainId: number, graphApiKey: string): void {
|
|
25
|
+
|
|
26
|
+
if (chainId == 1329) {
|
|
27
|
+
this.endpoint = `https://indexer.us.hyperindex.xyz/32230f9/converter`
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (chainId == 1) {
|
|
31
|
+
this.endpoint = `https://gateway-arbitrum.network.thegraph.com/api/${graphApiKey}/subgraphs/id/EYCKATKGBKLWvSfwvBjzfCBmGwYNdVkduYXVivCsLRFu`
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (chainId == 42161) {
|
|
35
|
+
this.endpoint = `https://gateway-arbitrum.network.thegraph.com/api/${graphApiKey}/subgraphs/id/CStW6CSQbHoXsgKuVCrk3uShGA4JX3CAzzv2x9zaGf8w`
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (chainId == 420420417) {
|
|
39
|
+
this.endpoint = `https://saphyre-service-dev.saphyre.xyz/api/graphql/v2`
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.chainId = chainId
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async getTopPools(numPools: number): Promise<PoolInfo[]> {
|
|
46
|
+
const poolsInfo: PoolInfo[] = []
|
|
47
|
+
const { resultKey } = v2LiquidityCollection(this.chainId)
|
|
48
|
+
const queryResult = await request(this.endpoint, queryTopPools(numPools, this.chainId))
|
|
49
|
+
|
|
50
|
+
queryResult[resultKey].forEach((pool: any) => {
|
|
51
|
+
poolsInfo.push(createPoolFromGraph(pool, this.dexId))
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
return poolsInfo
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async getPoolsWithTokenPair(tokenA: string, tokenB: string, numPools: number): Promise<PoolInfo[]> {
|
|
58
|
+
const a = tokenA.toLowerCase()
|
|
59
|
+
const b = tokenB.toLowerCase()
|
|
60
|
+
const { resultKey } = v2LiquidityCollection(this.chainId)
|
|
61
|
+
const [resAb, resBa] = await Promise.all([
|
|
62
|
+
request(this.endpoint, queryPairsWithTokenPairDirected(a, b, numPools, this.chainId)),
|
|
63
|
+
request(this.endpoint, queryPairsWithTokenPairDirected(b, a, numPools, this.chainId)),
|
|
64
|
+
])
|
|
65
|
+
return mergePairsByVolume([resAb[resultKey], resBa[resultKey]], numPools, this.dexId)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async getPoolsWithToken(token: string, numPools: number): Promise<PoolInfo[]> {
|
|
69
|
+
const t = token.toLowerCase()
|
|
70
|
+
const { resultKey } = v2LiquidityCollection(this.chainId)
|
|
71
|
+
const [res0, res1] = await Promise.all([
|
|
72
|
+
request(this.endpoint, queryPairsWithTokenOnSide0(t, numPools, this.chainId)),
|
|
73
|
+
request(this.endpoint, queryPairsWithTokenOnSide1(t, numPools, this.chainId)),
|
|
74
|
+
])
|
|
75
|
+
return mergePairsByVolume([res0[resultKey], res1[resultKey]], numPools, this.dexId)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async getAdditionalPoolDataFromSolidity(poolInfos: PoolInfo[], rpcProvider: Web3): Promise<Pool[]> {
|
|
79
|
+
//@ts-ignore
|
|
80
|
+
const UniswapV2HelperContract = CreateUniswapV2HelperContract(this.chainId, rpcProvider)
|
|
81
|
+
const rawData: any[][] = await UniswapV2HelperContract.methods.getPoolsData(poolInfos).call()
|
|
82
|
+
|
|
83
|
+
const pools: Pool[] = []
|
|
84
|
+
for (let pool of rawData) {
|
|
85
|
+
const poolId = pool[0]
|
|
86
|
+
const dexId = pool[1]
|
|
87
|
+
const tokensRaw1 = pool[2][0]
|
|
88
|
+
const tokensRaw2 = pool[2][1]
|
|
89
|
+
|
|
90
|
+
const token1: Token = {
|
|
91
|
+
_address: tokensRaw1[0],
|
|
92
|
+
decimals: Number(tokensRaw1[1]),
|
|
93
|
+
name: tokensRaw1[2],
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const token2: Token = {
|
|
97
|
+
_address: tokensRaw2[0],
|
|
98
|
+
decimals: Number(tokensRaw2[1]),
|
|
99
|
+
name: tokensRaw2[2],
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
pools.push(new UniswapV2Pool(pool[0], pool[1], [token1, token2], pool[3]))
|
|
103
|
+
}
|
|
104
|
+
for (const pool of pools)
|
|
105
|
+
// @ts-ignore
|
|
106
|
+
this.myLocalStorage.setItem(pool.poolId.toLowerCase(), pool)
|
|
107
|
+
return pools
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function queryTopPools(numPools: number, chainId: number): TypedDocumentNode<any, Record<string, unknown>> {
|
|
112
|
+
const { field } = v2LiquidityCollection(chainId)
|
|
113
|
+
return parse(gql`
|
|
114
|
+
{
|
|
115
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD) {
|
|
116
|
+
id,
|
|
117
|
+
volumeUSD,
|
|
118
|
+
token0 {
|
|
119
|
+
id,
|
|
120
|
+
name,
|
|
121
|
+
decimals,
|
|
122
|
+
},
|
|
123
|
+
token1 {
|
|
124
|
+
id,
|
|
125
|
+
name,
|
|
126
|
+
decimals,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
`)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function queryPairsWithTokenPairDirected(
|
|
134
|
+
token0Id: string,
|
|
135
|
+
token1Id: string,
|
|
136
|
+
numPools: number,
|
|
137
|
+
chainId: number
|
|
138
|
+
): TypedDocumentNode<any, Record<string, unknown>> {
|
|
139
|
+
const { field } = v2LiquidityCollection(chainId)
|
|
140
|
+
return parse(gql`
|
|
141
|
+
{
|
|
142
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD, where : {
|
|
143
|
+
${whereDirectedTokenPair(token0Id, token1Id, chainId)},
|
|
144
|
+
}) {
|
|
145
|
+
id,
|
|
146
|
+
volumeUSD,
|
|
147
|
+
token0 {
|
|
148
|
+
id,
|
|
149
|
+
name,
|
|
150
|
+
decimals,
|
|
151
|
+
},
|
|
152
|
+
token1 {
|
|
153
|
+
id,
|
|
154
|
+
name,
|
|
155
|
+
decimals,
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
}
|
|
159
|
+
`)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function queryPairsWithTokenOnSide0(
|
|
163
|
+
token: string,
|
|
164
|
+
numPools: number,
|
|
165
|
+
chainId: number
|
|
166
|
+
): TypedDocumentNode<any, Record<string, unknown>> {
|
|
167
|
+
const { field } = v2LiquidityCollection(chainId)
|
|
168
|
+
return parse(gql`
|
|
169
|
+
{
|
|
170
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD, where : {
|
|
171
|
+
${whereTokenOnSide('token0', token, chainId)},
|
|
172
|
+
}) {
|
|
173
|
+
id,
|
|
174
|
+
volumeUSD,
|
|
175
|
+
token0 {
|
|
176
|
+
id,
|
|
177
|
+
name,
|
|
178
|
+
decimals,
|
|
179
|
+
},
|
|
180
|
+
token1 {
|
|
181
|
+
id,
|
|
182
|
+
name,
|
|
183
|
+
decimals,
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
}
|
|
187
|
+
`)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function queryPairsWithTokenOnSide1(
|
|
191
|
+
token: string,
|
|
192
|
+
numPools: number,
|
|
193
|
+
chainId: number
|
|
194
|
+
): TypedDocumentNode<any, Record<string, unknown>> {
|
|
195
|
+
const { field } = v2LiquidityCollection(chainId)
|
|
196
|
+
return parse(gql`
|
|
197
|
+
{
|
|
198
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD, where : {
|
|
199
|
+
${whereTokenOnSide('token1', token, chainId)},
|
|
200
|
+
}) {
|
|
201
|
+
id,
|
|
202
|
+
volumeUSD,
|
|
203
|
+
token0 {
|
|
204
|
+
id,
|
|
205
|
+
name,
|
|
206
|
+
decimals,
|
|
207
|
+
},
|
|
208
|
+
token1 {
|
|
209
|
+
id,
|
|
210
|
+
name,
|
|
211
|
+
decimals,
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
}
|
|
215
|
+
`)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function mergePairsByVolume(pairLists: any[][], numPools: number, dexId: string): PoolInfo[] {
|
|
219
|
+
const byId = new Map<string, any>()
|
|
220
|
+
for (const list of pairLists) {
|
|
221
|
+
for (const pair of list) {
|
|
222
|
+
byId.set(String(pair.id).toLowerCase(), pair)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const merged = [...byId.values()]
|
|
226
|
+
merged.sort((a, b) => {
|
|
227
|
+
const va = parseFloat(a.volumeUSD) || 0
|
|
228
|
+
const vb = parseFloat(b.volumeUSD) || 0
|
|
229
|
+
return vb - va
|
|
230
|
+
})
|
|
231
|
+
return merged.slice(0, numPools).map((p) => createPoolFromGraph(p, dexId))
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function createPoolFromGraph(jsonData: any, dexId: string): PoolInfo {
|
|
235
|
+
const pool: PoolInfo = {
|
|
236
|
+
poolId: jsonData.id,
|
|
237
|
+
dexId: dexId,
|
|
238
|
+
tokens: [
|
|
239
|
+
{
|
|
240
|
+
_address: jsonData.token0.id,
|
|
241
|
+
decimals: Number(jsonData.token0.decimals),
|
|
242
|
+
name: jsonData.token0.name,
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
_address: jsonData.token1.id,
|
|
246
|
+
decimals: Number(jsonData.token1.decimals),
|
|
247
|
+
name: jsonData.token1.name,
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
}
|
|
251
|
+
return pool
|
|
252
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { parse } from 'graphql'
|
|
2
|
+
import { gql, request } from 'graphql-request'
|
|
3
|
+
import { TypedDocumentNode } from '@graphql-typed-document-node/core'
|
|
4
|
+
import { dexIds } from '../dexIdsList'
|
|
5
|
+
import { Pool, PoolInfo, DEXGraphFunctionality } from '../../utils/types/types'
|
|
6
|
+
import { UniswapState } from '../pools/uniswap/uniswapState'
|
|
7
|
+
import { UniswapV3Pool } from '../pools/uniswap/UniswapV3'
|
|
8
|
+
import Web3 from 'web3'
|
|
9
|
+
import { v3LiquidityCollection, whereDirectedTokenPair, whereTokenOnSide } from './graphQueryFilters'
|
|
10
|
+
|
|
11
|
+
export default class UniswapV3 implements DEXGraphFunctionality {
|
|
12
|
+
endpoint = ``
|
|
13
|
+
chainId = 1
|
|
14
|
+
dexId = dexIds.UNI_V3
|
|
15
|
+
myLocalStorage = null
|
|
16
|
+
|
|
17
|
+
static initialize(myLocalStorage: any): DEXGraphFunctionality {
|
|
18
|
+
const object = new UniswapV3();
|
|
19
|
+
object.myLocalStorage = myLocalStorage;
|
|
20
|
+
return object
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setEndpoint(chainId: number, graphApiKey: string): void {
|
|
24
|
+
|
|
25
|
+
if (chainId == 1329) {
|
|
26
|
+
this.endpoint = 'https://indexer.us.hyperindex.xyz/32230f9/converter'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (chainId == 1) {
|
|
30
|
+
this.endpoint = `https://gateway-arbitrum.network.thegraph.com/api/${graphApiKey}/subgraphs/id/5zvR82QoaXYFyDEKLZ9t6v9adgnptxYpKpSbxtgVENFV`
|
|
31
|
+
}
|
|
32
|
+
if (chainId == 42161) {
|
|
33
|
+
this.endpoint = `https://gateway-arbitrum.network.thegraph.com/api/${graphApiKey}/subgraphs/id/FbCGRftH4a3yZugY7TnbYgPJVEv2LvMT6oF1fxPe9aJM`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (chainId == 420420417) {
|
|
37
|
+
this.endpoint = `https://saphyre-service-dev.saphyre.xyz/api/graphql/v3`
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.chainId = chainId
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async getTopPools(numPools: number): Promise<PoolInfo[]> {
|
|
44
|
+
const poolsInfo: PoolInfo[] = []
|
|
45
|
+
const { resultKey } = v3LiquidityCollection(this.chainId)
|
|
46
|
+
const queryResult = await request(this.endpoint, queryTopPools(numPools, this.chainId))
|
|
47
|
+
|
|
48
|
+
queryResult[resultKey].forEach((pool: any) => {
|
|
49
|
+
poolsInfo.push(createPoolFromGraph(pool, this.dexId))
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
return poolsInfo
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async getPoolsWithTokenPair(tokenA: string, tokenB: string, numPools: number): Promise<PoolInfo[]> {
|
|
56
|
+
const a = tokenA.toLowerCase()
|
|
57
|
+
const b = tokenB.toLowerCase()
|
|
58
|
+
const { resultKey } = v3LiquidityCollection(this.chainId)
|
|
59
|
+
const [resAb, resBa] = await Promise.all([
|
|
60
|
+
request(this.endpoint, queryPoolsWithTokenPairDirected(a, b, numPools, this.chainId)),
|
|
61
|
+
request(this.endpoint, queryPoolsWithTokenPairDirected(b, a, numPools, this.chainId)),
|
|
62
|
+
])
|
|
63
|
+
return mergePoolsByVolume([resAb[resultKey], resBa[resultKey]], numPools, this.dexId)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async getPoolsWithToken(token: string, numPools: number): Promise<PoolInfo[]> {
|
|
67
|
+
const t = token.toLowerCase()
|
|
68
|
+
const { resultKey } = v3LiquidityCollection(this.chainId)
|
|
69
|
+
const [res0, res1] = await Promise.all([
|
|
70
|
+
request(this.endpoint, queryPoolsWithTokenOnSide0(t, numPools, this.chainId)),
|
|
71
|
+
request(this.endpoint, queryPoolsWithTokenOnSide1(t, numPools, this.chainId)),
|
|
72
|
+
])
|
|
73
|
+
return mergePoolsByVolume([res0[resultKey], res1[resultKey]], numPools, this.dexId)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async getAdditionalPoolDataFromSolidity(poolInfos: PoolInfo[], rpcProvider: Web3): Promise<Pool[]> {
|
|
77
|
+
const pools = poolInfos.map((poolInfo: PoolInfo) => poolInfo.poolId)
|
|
78
|
+
await UniswapState.initializeFreshPoolsData(pools, this.chainId, rpcProvider)
|
|
79
|
+
|
|
80
|
+
const pools2 = poolInfos.map((poolInfo: PoolInfo) => new UniswapV3Pool(poolInfo.poolId, this.dexId, poolInfo.tokens));
|
|
81
|
+
for (const pool of pools2)
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
this.myLocalStorage.setItem(pool.poolId.toLowerCase(), pool)
|
|
84
|
+
return pools2
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function queryTopPools(numPools: number, chainId: number): TypedDocumentNode<any, Record<string, unknown>> {
|
|
89
|
+
const { field } = v3LiquidityCollection(chainId)
|
|
90
|
+
return parse(gql`
|
|
91
|
+
{
|
|
92
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD) {
|
|
93
|
+
id,
|
|
94
|
+
volumeUSD,
|
|
95
|
+
token0 {
|
|
96
|
+
id,
|
|
97
|
+
name,
|
|
98
|
+
decimals,
|
|
99
|
+
},
|
|
100
|
+
token1 {
|
|
101
|
+
id,
|
|
102
|
+
name,
|
|
103
|
+
decimals,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
`)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function queryPoolsWithTokenPairDirected(
|
|
111
|
+
token0Id: string,
|
|
112
|
+
token1Id: string,
|
|
113
|
+
numPools: number,
|
|
114
|
+
chainId: number
|
|
115
|
+
): TypedDocumentNode<any, Record<string, unknown>> {
|
|
116
|
+
const { field } = v3LiquidityCollection(chainId)
|
|
117
|
+
return parse(gql`
|
|
118
|
+
{
|
|
119
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD, where : {
|
|
120
|
+
${whereDirectedTokenPair(token0Id, token1Id, chainId)},
|
|
121
|
+
}) {
|
|
122
|
+
id,
|
|
123
|
+
volumeUSD,
|
|
124
|
+
token0 {
|
|
125
|
+
id,
|
|
126
|
+
name,
|
|
127
|
+
decimals,
|
|
128
|
+
},
|
|
129
|
+
token1 {
|
|
130
|
+
id,
|
|
131
|
+
name,
|
|
132
|
+
decimals,
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
`)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function queryPoolsWithTokenOnSide0(
|
|
140
|
+
token: string,
|
|
141
|
+
numPools: number,
|
|
142
|
+
chainId: number
|
|
143
|
+
): TypedDocumentNode<any, Record<string, unknown>> {
|
|
144
|
+
const { field } = v3LiquidityCollection(chainId)
|
|
145
|
+
return parse(gql`
|
|
146
|
+
{
|
|
147
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD, where : {
|
|
148
|
+
${whereTokenOnSide('token0', token, chainId)},
|
|
149
|
+
}) {
|
|
150
|
+
id,
|
|
151
|
+
volumeUSD,
|
|
152
|
+
token0 {
|
|
153
|
+
id,
|
|
154
|
+
name,
|
|
155
|
+
decimals,
|
|
156
|
+
},
|
|
157
|
+
token1 {
|
|
158
|
+
id,
|
|
159
|
+
name,
|
|
160
|
+
decimals,
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
}
|
|
164
|
+
`)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function queryPoolsWithTokenOnSide1(
|
|
168
|
+
token: string,
|
|
169
|
+
numPools: number,
|
|
170
|
+
chainId: number
|
|
171
|
+
): TypedDocumentNode<any, Record<string, unknown>> {
|
|
172
|
+
const { field } = v3LiquidityCollection(chainId)
|
|
173
|
+
return parse(gql`
|
|
174
|
+
{
|
|
175
|
+
${field}(first : ${numPools}, orderDirection : desc, orderBy : volumeUSD, where : {
|
|
176
|
+
${whereTokenOnSide('token1', token, chainId)},
|
|
177
|
+
}) {
|
|
178
|
+
id,
|
|
179
|
+
volumeUSD,
|
|
180
|
+
token0 {
|
|
181
|
+
id,
|
|
182
|
+
name,
|
|
183
|
+
decimals,
|
|
184
|
+
},
|
|
185
|
+
token1 {
|
|
186
|
+
id,
|
|
187
|
+
name,
|
|
188
|
+
decimals,
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
}
|
|
192
|
+
`)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function mergePoolsByVolume(poolLists: any[][], numPools: number, dexId: string): PoolInfo[] {
|
|
196
|
+
const byId = new Map<string, any>()
|
|
197
|
+
for (const list of poolLists) {
|
|
198
|
+
for (const pool of list) {
|
|
199
|
+
byId.set(String(pool.id).toLowerCase(), pool)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const merged = [...byId.values()]
|
|
203
|
+
merged.sort((a, b) => {
|
|
204
|
+
const va = parseFloat(a.volumeUSD) || 0
|
|
205
|
+
const vb = parseFloat(b.volumeUSD) || 0
|
|
206
|
+
return vb - va
|
|
207
|
+
})
|
|
208
|
+
return merged.slice(0, numPools).map((p) => createPoolFromGraph(p, dexId))
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function createPoolFromGraph(jsonData: any, dexId: string): PoolInfo {
|
|
212
|
+
const pool: PoolInfo = {
|
|
213
|
+
poolId: jsonData.id,
|
|
214
|
+
dexId: dexId,
|
|
215
|
+
tokens: [
|
|
216
|
+
{
|
|
217
|
+
_address: jsonData.token0.id,
|
|
218
|
+
decimals: Number(jsonData.token0.decimals),
|
|
219
|
+
name: jsonData.token0.name,
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
_address: jsonData.token1.id,
|
|
223
|
+
decimals: Number(jsonData.token1.decimals),
|
|
224
|
+
name: jsonData.token1.name,
|
|
225
|
+
},
|
|
226
|
+
],
|
|
227
|
+
}
|
|
228
|
+
return pool
|
|
229
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Chains whose graph URL goes through HyperIndex → Hasura (Saphyre / Sei). */
|
|
2
|
+
export function usesHyperIndexConverter(chainId: number): boolean {
|
|
3
|
+
return chainId === 1329 || chainId === 420420417
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/** V2 liquidity collection: merged schema uses V2_Factory_Pair; The Graph uses pairs. */
|
|
7
|
+
export function v2LiquidityCollection(chainId: number): { field: string; resultKey: string } {
|
|
8
|
+
if (usesHyperIndexConverter(chainId)) {
|
|
9
|
+
return { field: 'V2_Factory_Pair', resultKey: 'V2_Factory_Pair' }
|
|
10
|
+
}
|
|
11
|
+
return { field: 'pairs', resultKey: 'pairs' }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** V3 liquidity collection: merged schema uses V3_Factory_Pool; The Graph uses pools. */
|
|
15
|
+
export function v3LiquidityCollection(chainId: number): { field: string; resultKey: string } {
|
|
16
|
+
if (usesHyperIndexConverter(chainId)) {
|
|
17
|
+
return { field: 'V3_Factory_Pool', resultKey: 'V3_Factory_Pool' }
|
|
18
|
+
}
|
|
19
|
+
return { field: 'pools', resultKey: 'pools' }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* `where` clause fragment for a pool/pair token side.
|
|
24
|
+
* - HyperIndex: `token0: { id: "0x..." }` (scalar address becomes invalid `token1: { _eq }` on Token_bool_exp)
|
|
25
|
+
* - The Graph: `token0: "0x..."`
|
|
26
|
+
*/
|
|
27
|
+
export function whereTokenOnSide(side: 'token0' | 'token1', address: string, chainId: number): string {
|
|
28
|
+
const id = address.toLowerCase()
|
|
29
|
+
if (usesHyperIndexConverter(chainId)) {
|
|
30
|
+
return `${side} : { id : "${id}" }`
|
|
31
|
+
}
|
|
32
|
+
return `${side} : "${id}"`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function whereDirectedTokenPair(
|
|
36
|
+
token0Id: string,
|
|
37
|
+
token1Id: string,
|
|
38
|
+
chainId: number
|
|
39
|
+
): string {
|
|
40
|
+
return `${whereTokenOnSide('token0', token0Id, chainId)}, ${whereTokenOnSide('token1', token1Id, chainId)}`
|
|
41
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { parse } from 'graphql'
|
|
2
|
+
import { gql, request } from 'graphql-request'
|
|
3
|
+
import { TypedDocumentNode } from '@graphql-typed-document-node/core'
|
|
4
|
+
import { Pool, PoolInfo, DEXGraphFunctionality } from '../../utils/types/types'
|
|
5
|
+
|
|
6
|
+
export default class NewDex implements DEXGraphFunctionality {
|
|
7
|
+
endpoint = ''
|
|
8
|
+
dexId = ''
|
|
9
|
+
chainId = 1
|
|
10
|
+
|
|
11
|
+
static initialize(): DEXGraphFunctionality {
|
|
12
|
+
return new NewDex()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
setEndpoint(chainId: number): void {
|
|
16
|
+
if (chainId == 42161) {
|
|
17
|
+
this.endpoint = ''
|
|
18
|
+
}
|
|
19
|
+
this.chainId = chainId
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async getTopPools(numPools: number): Promise<PoolInfo[]> {
|
|
23
|
+
const poolsInfo: PoolInfo[] = []
|
|
24
|
+
const queryResult = await request(this.endpoint, queryTopPools(numPools))
|
|
25
|
+
queryResult.pairs.forEach((pair: any) => {
|
|
26
|
+
poolsInfo.push(pair.id)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
return poolsInfo
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async getPoolsWithTokenPair(token1: string, token2: string, first: number): Promise<PoolInfo[]> {
|
|
33
|
+
const poolsInfo: PoolInfo[] = []
|
|
34
|
+
const queryResult = await request(this.endpoint, queryPoolsWithTokenPair(token1, token2, first))
|
|
35
|
+
queryResult.pairs.forEach((pair: any) => {
|
|
36
|
+
poolsInfo.push(pair.id)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
return poolsInfo
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async getPoolsWithToken(token: string, numPools: number): Promise<PoolInfo[]> {
|
|
43
|
+
const poolsInfo: PoolInfo[] = []
|
|
44
|
+
const queryResult = await request(this.endpoint, queryPoolsWithToken(token, numPools))
|
|
45
|
+
queryResult.pairs.forEach((pair: any) => {
|
|
46
|
+
poolsInfo.push(pair.id)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
return poolsInfo
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async getAdditionalPoolDataFromSolidity(poolInfos: PoolInfo[]): Promise<Pool[]> {
|
|
53
|
+
return []
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function queryTopPools(numPools: number): TypedDocumentNode<any, Record<string, unknown>> {
|
|
58
|
+
return parse(gql``)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function queryPoolsWithTokenPair(tokenA: string, tokenB: string, numPools: number): TypedDocumentNode<any, Record<string, unknown>> {
|
|
62
|
+
return parse(gql``)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function queryPoolsWithToken(token: string, numPools: number): TypedDocumentNode<any, Record<string, unknown>> {
|
|
66
|
+
return parse(gql``)
|
|
67
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Pool, PoolInfo } from '../../../utils/types/types';
|
|
2
|
+
import { BalancerWeightedPool } from './BalancerWeightedPool';
|
|
3
|
+
import { CreateBalancerHelperContract } from '../../../contracts/rateX/BalancerHelper';
|
|
4
|
+
import Web3 from 'web3';
|
|
5
|
+
|
|
6
|
+
export class BalancerState {
|
|
7
|
+
private constructor() {}
|
|
8
|
+
|
|
9
|
+
public static async getPoolDataFromContract(pools: PoolInfo[], chainId: number, rpcProvider: Web3): Promise<Pool[]> {
|
|
10
|
+
const promises = pools.map(async (pool) => {
|
|
11
|
+
// return token address after '-' split
|
|
12
|
+
pool.tokens.forEach((token) => token._address = token._address.split('-')[1]);
|
|
13
|
+
|
|
14
|
+
const BalancerHelperContract = CreateBalancerHelperContract(chainId, rpcProvider);
|
|
15
|
+
try {
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
const res: any[] = await BalancerHelperContract.methods
|
|
18
|
+
.getWeightedPoolInfo(pool.poolId)
|
|
19
|
+
.call();
|
|
20
|
+
|
|
21
|
+
const [decimals, tokens, balances, weights, swapFeePercentage] = [res[0], res[1], res[2], res[3], res[4]];
|
|
22
|
+
const weightedPool = new BalancerWeightedPool(pool.poolId, pool.dexId, pool.tokens, balances, weights, swapFeePercentage);
|
|
23
|
+
return weightedPool;
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.log('Weighted Get Pool Info Error: ', err);
|
|
26
|
+
return null; // Handle the error as needed
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const newPools = await Promise.all(promises);
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
return newPools.filter((pool) => pool !== null); // Filter out any null values
|
|
33
|
+
}
|
|
34
|
+
}
|