@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.
Files changed (173) hide show
  1. package/.idea/copilot.data.migration.agent.xml +6 -0
  2. package/.idea/copilot.data.migration.ask.xml +6 -0
  3. package/.idea/copilot.data.migration.ask2agent.xml +6 -0
  4. package/.idea/copilot.data.migration.edit.xml +6 -0
  5. package/.idea/modules.xml +8 -0
  6. package/.idea/php.xml +19 -0
  7. package/.idea/ratex-sdk.iml +8 -0
  8. package/.idea/vcs.xml +6 -0
  9. package/LICENSE-MIT +21 -0
  10. package/README.md +209 -0
  11. package/contracts/abi/BalancerHelperAbi.ts +1 -0
  12. package/contracts/abi/CamelotHelperAbi.ts +1 -0
  13. package/contracts/abi/RateXAbi.ts +482 -0
  14. package/contracts/abi/SushiSwapHelperAbi.ts +1 -0
  15. package/contracts/abi/UniswapHelperAbi.ts +1 -0
  16. package/contracts/abi/UniswapV2HelperAbi.ts +1 -0
  17. package/contracts/addresses-arbitrum.ts +8 -0
  18. package/contracts/addresses-mainnet.ts +7 -0
  19. package/contracts/addresses-polkadot.ts +9 -0
  20. package/contracts/addresses-sei.ts +9 -0
  21. package/contracts/rateX/BalancerHelper.ts +13 -0
  22. package/contracts/rateX/CamelotHelper.ts +13 -0
  23. package/contracts/rateX/SushiSwapHelper.ts +13 -0
  24. package/contracts/rateX/UniswapHelper.ts +19 -0
  25. package/contracts/rateX/UniswapV2Helper.ts +19 -0
  26. package/dexes/dexIdsList.ts +9 -0
  27. package/dexes/graph_queries/BalancerV2.ts +150 -0
  28. package/dexes/graph_queries/CamelotV2.ts +202 -0
  29. package/dexes/graph_queries/SushiSwapV2.ts +283 -0
  30. package/dexes/graph_queries/UniswapV2.ts +252 -0
  31. package/dexes/graph_queries/UniswapV3.ts +229 -0
  32. package/dexes/graph_queries/graphQueryFilters.ts +41 -0
  33. package/dexes/graph_queries/x_template.ts +67 -0
  34. package/dexes/pools/Balancer/BalancerState.ts +34 -0
  35. package/dexes/pools/Balancer/BalancerWeightedPool.ts +96 -0
  36. package/dexes/pools/Camelot.ts +164 -0
  37. package/dexes/pools/SushiSwapV2.ts +35 -0
  38. package/dexes/pools/UniswapV2.ts +36 -0
  39. package/dexes/pools/uniswap/UniswapV3.ts +40 -0
  40. package/dexes/pools/uniswap/testUniswapOffchainQuoter.ts +169 -0
  41. package/dexes/pools/uniswap/types.ts +174 -0
  42. package/dexes/pools/uniswap/uniswapOffchainQuoter.ts +173 -0
  43. package/dexes/pools/uniswap/uniswapState.ts +56 -0
  44. package/dexes/pools/uniswap/utils.ts +71 -0
  45. package/dist/contracts/abi/BalancerHelperAbi.d.ts +25 -0
  46. package/dist/contracts/abi/BalancerHelperAbi.js +4 -0
  47. package/dist/contracts/abi/CamelotHelperAbi.d.ts +45 -0
  48. package/dist/contracts/abi/CamelotHelperAbi.js +4 -0
  49. package/dist/contracts/abi/RateXAbi.d.ts +71 -0
  50. package/dist/contracts/abi/RateXAbi.js +485 -0
  51. package/dist/contracts/abi/SushiSwapHelperAbi.d.ts +45 -0
  52. package/dist/contracts/abi/SushiSwapHelperAbi.js +4 -0
  53. package/dist/contracts/abi/UniswapHelperAbi.d.ts +39 -0
  54. package/dist/contracts/abi/UniswapHelperAbi.js +4 -0
  55. package/dist/contracts/abi/UniswapV2HelperAbi.d.ts +45 -0
  56. package/dist/contracts/abi/UniswapV2HelperAbi.js +4 -0
  57. package/dist/contracts/addresses-arbitrum.d.ts +6 -0
  58. package/dist/contracts/addresses-arbitrum.js +10 -0
  59. package/dist/contracts/addresses-mainnet.d.ts +6 -0
  60. package/dist/contracts/addresses-mainnet.js +10 -0
  61. package/dist/contracts/addresses-polkadot.d.ts +6 -0
  62. package/dist/contracts/addresses-polkadot.js +10 -0
  63. package/dist/contracts/addresses-sei.d.ts +6 -0
  64. package/dist/contracts/addresses-sei.js +10 -0
  65. package/dist/contracts/rateX/BalancerHelper.d.ts +26 -0
  66. package/dist/contracts/rateX/BalancerHelper.js +14 -0
  67. package/dist/contracts/rateX/CamelotHelper.d.ts +46 -0
  68. package/dist/contracts/rateX/CamelotHelper.js +14 -0
  69. package/dist/contracts/rateX/SushiSwapHelper.d.ts +46 -0
  70. package/dist/contracts/rateX/SushiSwapHelper.js +14 -0
  71. package/dist/contracts/rateX/UniswapHelper.d.ts +40 -0
  72. package/dist/contracts/rateX/UniswapHelper.js +22 -0
  73. package/dist/contracts/rateX/UniswapV2Helper.d.ts +46 -0
  74. package/dist/contracts/rateX/UniswapV2Helper.js +22 -0
  75. package/dist/dexes/dexIdsList.d.ts +9 -0
  76. package/dist/dexes/dexIdsList.js +12 -0
  77. package/dist/dexes/graph_queries/BalancerV2.d.ts +14 -0
  78. package/dist/dexes/graph_queries/BalancerV2.js +141 -0
  79. package/dist/dexes/graph_queries/CamelotV2.d.ts +14 -0
  80. package/dist/dexes/graph_queries/CamelotV2.js +183 -0
  81. package/dist/dexes/graph_queries/SushiSwapV2.d.ts +14 -0
  82. package/dist/dexes/graph_queries/SushiSwapV2.js +263 -0
  83. package/dist/dexes/graph_queries/UniswapV2.d.ts +14 -0
  84. package/dist/dexes/graph_queries/UniswapV2.js +217 -0
  85. package/dist/dexes/graph_queries/UniswapV3.d.ts +14 -0
  86. package/dist/dexes/graph_queries/UniswapV3.js +198 -0
  87. package/dist/dexes/graph_queries/graphQueryFilters.d.ts +19 -0
  88. package/dist/dexes/graph_queries/graphQueryFilters.js +40 -0
  89. package/dist/dexes/graph_queries/x_template.d.ts +12 -0
  90. package/dist/dexes/graph_queries/x_template.js +57 -0
  91. package/dist/dexes/pools/Balancer/BalancerState.d.ts +6 -0
  92. package/dist/dexes/pools/Balancer/BalancerState.js +32 -0
  93. package/dist/dexes/pools/Balancer/BalancerWeightedPool.d.ts +12 -0
  94. package/dist/dexes/pools/Balancer/BalancerWeightedPool.js +109 -0
  95. package/dist/dexes/pools/Camelot.d.ts +12 -0
  96. package/dist/dexes/pools/Camelot.js +135 -0
  97. package/dist/dexes/pools/SushiSwapV2.d.ts +9 -0
  98. package/dist/dexes/pools/SushiSwapV2.js +34 -0
  99. package/dist/dexes/pools/UniswapV2.d.ts +9 -0
  100. package/dist/dexes/pools/UniswapV2.js +34 -0
  101. package/dist/dexes/pools/uniswap/UniswapV3.d.ts +7 -0
  102. package/dist/dexes/pools/uniswap/UniswapV3.js +36 -0
  103. package/dist/dexes/pools/uniswap/types.d.ts +76 -0
  104. package/dist/dexes/pools/uniswap/types.js +111 -0
  105. package/dist/dexes/pools/uniswap/uniswapOffchainQuoter.d.ts +13 -0
  106. package/dist/dexes/pools/uniswap/uniswapOffchainQuoter.js +121 -0
  107. package/dist/dexes/pools/uniswap/uniswapState.d.ts +14 -0
  108. package/dist/dexes/pools/uniswap/uniswapState.js +51 -0
  109. package/dist/dexes/pools/uniswap/utils.d.ts +3 -0
  110. package/dist/dexes/pools/uniswap/utils.js +41 -0
  111. package/dist/index.d.ts +26 -0
  112. package/dist/index.js +41 -0
  113. package/dist/routes.d.ts +1 -0
  114. package/dist/routes.js +20 -0
  115. package/dist/routing/iterative_spliting/main.d.ts +3 -0
  116. package/dist/routing/iterative_spliting/main.js +104 -0
  117. package/dist/routing/iterative_spliting/multiHopSwap.d.ts +4 -0
  118. package/dist/routing/iterative_spliting/multiHopSwap.js +83 -0
  119. package/dist/routing/main.d.ts +2 -0
  120. package/dist/routing/main.js +22 -0
  121. package/dist/routing/uni_like_algo/algo_config.d.ts +2 -0
  122. package/dist/routing/uni_like_algo/algo_config.js +8 -0
  123. package/dist/routing/uni_like_algo/amount_distribution.d.ts +2 -0
  124. package/dist/routing/uni_like_algo/amount_distribution.js +17 -0
  125. package/dist/routing/uni_like_algo/compute_routes_backtrack.d.ts +3 -0
  126. package/dist/routing/uni_like_algo/compute_routes_backtrack.js +44 -0
  127. package/dist/routing/uni_like_algo/main.d.ts +2 -0
  128. package/dist/routing/uni_like_algo/main.js +49 -0
  129. package/dist/routing/uni_like_algo/routes_quoter.d.ts +21 -0
  130. package/dist/routing/uni_like_algo/routes_quoter.js +53 -0
  131. package/dist/routing/uni_like_algo/swap_finder.d.ts +25 -0
  132. package/dist/routing/uni_like_algo/swap_finder.js +154 -0
  133. package/dist/routing/uni_like_algo/types.d.ts +40 -0
  134. package/dist/routing/uni_like_algo/types.js +12 -0
  135. package/dist/swap/graph_communication.d.ts +5 -0
  136. package/dist/swap/graph_communication.js +187 -0
  137. package/dist/swap/my_local_storage.d.ts +8 -0
  138. package/dist/swap/my_local_storage.js +16 -0
  139. package/dist/utils/addresses.d.ts +24 -0
  140. package/dist/utils/addresses.js +60 -0
  141. package/dist/utils/math/fixed-points.d.ts +14 -0
  142. package/dist/utils/math/fixed-points.js +123 -0
  143. package/dist/utils/math/log-exp.d.ts +5 -0
  144. package/dist/utils/math/log-exp.js +385 -0
  145. package/dist/utils/math/math.d.ts +12 -0
  146. package/dist/utils/math/math.js +50 -0
  147. package/dist/utils/types/types.d.ts +51 -0
  148. package/dist/utils/types/types.js +25 -0
  149. package/dist/utils/utils.d.ts +20 -0
  150. package/dist/utils/utils.js +72 -0
  151. package/images/decenter_logo.png +0 -0
  152. package/index.ts +50 -0
  153. package/package.json +39 -0
  154. package/routes.ts +27 -0
  155. package/routing/iterative_spliting/main.ts +131 -0
  156. package/routing/iterative_spliting/multiHopSwap.ts +98 -0
  157. package/routing/main.ts +22 -0
  158. package/routing/uni_like_algo/algo_config.ts +7 -0
  159. package/routing/uni_like_algo/amount_distribution.ts +16 -0
  160. package/routing/uni_like_algo/compute_routes_backtrack.ts +81 -0
  161. package/routing/uni_like_algo/main.ts +65 -0
  162. package/routing/uni_like_algo/routes_quoter.ts +63 -0
  163. package/routing/uni_like_algo/swap_finder.ts +185 -0
  164. package/routing/uni_like_algo/types.ts +54 -0
  165. package/swap/graph_communication.ts +212 -0
  166. package/swap/my_local_storage.ts +27 -0
  167. package/tsconfig.json +26 -0
  168. package/utils/addresses.ts +64 -0
  169. package/utils/math/fixed-points.ts +88 -0
  170. package/utils/math/log-exp.ts +469 -0
  171. package/utils/math/math.ts +46 -0
  172. package/utils/types/types.ts +100 -0
  173. package/utils/utils.ts +125 -0
@@ -0,0 +1,185 @@
1
+ import {AlgoParams, QueueItem, TQuoteUniLike, TRouteWithQuote} from "./types";
2
+ import Queue from "mnemonist/queue";
3
+
4
+ export class SwapFinder {
5
+
6
+ private algoParams: AlgoParams;
7
+ private percentagesToSortedQuotes: Map<number, TRouteWithQuote[]>;
8
+ private percentages: number[];
9
+ private amountIn: bigint;
10
+ private bestQuote: bigint;
11
+ private bestSwap: TRouteWithQuote[];
12
+ private queue: Queue<QueueItem>;
13
+ private numOfSplits: number;
14
+
15
+ public constructor(algoParams: AlgoParams, routesWithQuotes: TRouteWithQuote[], percentages: number[], amountIn: bigint) {
16
+ this.algoParams = algoParams;
17
+ this.percentages = percentages;
18
+ this.amountIn = amountIn;
19
+ this.percentagesToSortedQuotes = this.getSortedQuotes(routesWithQuotes);
20
+
21
+ this.bestQuote = BigInt(0);
22
+ this.bestSwap = [];
23
+ this.queue = new Queue<QueueItem>();
24
+ this.numOfSplits = 1;
25
+ }
26
+
27
+ private readyToFinishSplitting() {
28
+ const maxSplitsReached: boolean = this.numOfSplits > this.algoParams.maxSplit;
29
+ const bestSwapNotImprovedWithNewSplit: boolean =
30
+ this.numOfSplits >= 3 && (this.bestSwap.length < this.numOfSplits - 1);
31
+
32
+ return maxSplitsReached || bestSwapNotImprovedWithNewSplit;
33
+ }
34
+
35
+ public findBestRoute(): TQuoteUniLike {
36
+ this.initBestQuoteAndSwapForFullAmount();
37
+ this.initQueueWithHighestQuotes();
38
+
39
+ while (this.queue.size > 0) {
40
+ let layer = this.queue.size;
41
+ this.numOfSplits++;
42
+ if (this.readyToFinishSplitting()) {
43
+ break;
44
+ }
45
+ this.processLayer(layer);
46
+ }
47
+
48
+ this.addMissingAmountIn();
49
+
50
+ return {
51
+ quote: this.bestQuote,
52
+ routes: this.bestSwap
53
+ };
54
+ }
55
+
56
+ private addMissingAmountIn() {
57
+ const totalAmountIn = this.bestSwap.reduce((acc, route) => acc + route.amount.amountIn, BigInt(0));
58
+ const diff = this.amountIn - totalAmountIn;
59
+ if (diff > BigInt(0)) {
60
+ this.bestSwap[this.bestSwap.length - 1].amount.amountIn += diff;
61
+ }
62
+ }
63
+
64
+ private processLayer(layer: number) {
65
+ while (layer > 0) {
66
+ layer--;
67
+ const q = this.queue.dequeue()!;
68
+ this.processPairedItemsInLayer(q);
69
+ }
70
+ }
71
+
72
+ private processPairedItemsInLayer(q: QueueItem) {
73
+ for (let i = q.percentageIndex; i >= 0; --i) {
74
+ const percentage = this.percentages[i];
75
+ if (percentage > q.ramainingPercentage || !this.percentagesToSortedQuotes.has(percentage)) {
76
+ continue;
77
+ }
78
+ this.processPairedItem(q, percentage, i);
79
+ }
80
+ }
81
+
82
+ private processPairedItem(q: QueueItem, percentage: number, index: number) {
83
+ const candidateRoutes = this.percentagesToSortedQuotes.get(percentage)!;
84
+ const routeWithQuote = this.findFirstRouteNotUsingUsedPools(q.currentRoutes, candidateRoutes);
85
+ if (!routeWithQuote) {
86
+ return;
87
+ }
88
+
89
+ const newRemainingPercentage = q.ramainingPercentage - percentage;
90
+ const newCurrentRoutes = [...q.currentRoutes, routeWithQuote];
91
+
92
+ if (newRemainingPercentage === 0) {
93
+ this.updateBestQuoteAndSwapIfBetter(newCurrentRoutes);
94
+ }
95
+ else {
96
+ this.queue.enqueue({
97
+ percentageIndex: index,
98
+ currentRoutes: newCurrentRoutes,
99
+ ramainingPercentage: newRemainingPercentage
100
+ });
101
+ }
102
+ }
103
+
104
+ private updateBestQuoteAndSwapIfBetter(currentRoutes: TRouteWithQuote[]) {
105
+ const quote = currentRoutes.reduce((acc, route) => acc + route.quote, BigInt(0));
106
+ if (quote > this.bestQuote) {
107
+ this.bestQuote = quote;
108
+ this.bestSwap = currentRoutes;
109
+ }
110
+ }
111
+
112
+ private initBestQuoteAndSwapForFullAmount() {
113
+ if (this.percentagesToSortedQuotes.has(100)) {
114
+ this.bestQuote = this.percentagesToSortedQuotes.get(100)![0].quote;
115
+ this.bestSwap = [this.percentagesToSortedQuotes.get(100)![0]];
116
+ }
117
+ }
118
+
119
+ private initQueueWithHighestQuotes() {
120
+ for (let i = this.percentages.length - 1; i >= 0; --i) {
121
+ this.insertHigestQuoteForPercentageIfExist(i);
122
+ this.insertSecondHigestQuoteForPercentageIfExist(i);
123
+ }
124
+ }
125
+
126
+ private insertHigestQuoteForPercentageIfExist(percentageIndex: number) {
127
+ const percentage = this.percentages[percentageIndex];
128
+ if (this.percentagesToSortedQuotes.has(percentage)) {
129
+ this.queue.enqueue({
130
+ percentageIndex: percentageIndex,
131
+ currentRoutes: [this.percentagesToSortedQuotes.get(percentage)![0]],
132
+ ramainingPercentage: 100 - percentage
133
+ });
134
+ }
135
+ }
136
+
137
+ private insertSecondHigestQuoteForPercentageIfExist(percentageIndex: number) {
138
+ const percentage = this.percentages[percentageIndex];
139
+ if (this.percentagesToSortedQuotes.get(percentage)![1]) {
140
+ this.queue.enqueue({
141
+ percentageIndex: percentageIndex,
142
+ currentRoutes: [this.percentagesToSortedQuotes.get(percentage)![1]],
143
+ ramainingPercentage: 100 - percentage
144
+ });
145
+ }
146
+ }
147
+
148
+ private getSortedQuotes(routeWithQuotes: TRouteWithQuote[]) {
149
+ const map = new Map<number, TRouteWithQuote[]>();
150
+ routeWithQuotes.forEach(routeWithQuote => {
151
+ const percentage = routeWithQuote.amount.percentage;
152
+ if (!map.has(percentage)) {
153
+ map.set(percentage, []);
154
+ }
155
+ map.get(percentage)?.push(routeWithQuote);
156
+ });
157
+ map.forEach((value, key) => {
158
+ value.sort((a, b) => {
159
+ return Number(b.quote - a.quote);
160
+ })
161
+ });
162
+
163
+ return map;
164
+ }
165
+
166
+ private findFirstRouteNotUsingUsedPools(
167
+ usedRoutes: TRouteWithQuote[],
168
+ candidateRoutes: TRouteWithQuote[]
169
+ ) {
170
+ const usedPoolsSet = new Set<string>();
171
+ usedRoutes.forEach(route => {
172
+ route.route.steps.forEach(step => usedPoolsSet.add(step.pool.poolId));
173
+ });
174
+
175
+ for (const candidateRoute of candidateRoutes) {
176
+ const candidatePools = candidateRoute.route.steps.map(step => step.pool.poolId);
177
+ if (candidatePools.some(pool => usedPoolsSet.has(pool))) {
178
+ continue;
179
+ }
180
+ return candidateRoute;
181
+ }
182
+ return null;
183
+ }
184
+
185
+ }
@@ -0,0 +1,54 @@
1
+ import {Pool} from "../../utils/types/types";
2
+
3
+ export interface TRouteStep {
4
+ pool: Pool,
5
+ tokenOut: string;
6
+ }
7
+
8
+ export interface TRoute {
9
+ steps: TRouteStep[],
10
+ tokenIn: string,
11
+ tokenOut: string
12
+ }
13
+
14
+ export interface TRouteWithQuote {
15
+ route: TRoute,
16
+ quote: bigint,
17
+ amount: AmountPercentage
18
+ }
19
+
20
+ export interface AmountPercentage {
21
+ amountIn: bigint,
22
+ percentage: number
23
+ }
24
+
25
+ export class ComputeRoutesParams {
26
+ tokenIn: string;
27
+ tokenOut: string;
28
+ pools: Pool[];
29
+ maxHops: number;
30
+
31
+ constructor(tokenIn: string, tokenOut: string, pools: Pool[], maxHops: number) {
32
+ this.tokenIn = tokenIn;
33
+ this.tokenOut = tokenOut;
34
+ this.pools = pools;
35
+ this.maxHops = maxHops;
36
+ }
37
+ }
38
+
39
+ export interface QueueItem {
40
+ percentageIndex: number,
41
+ currentRoutes: TRouteWithQuote[],
42
+ ramainingPercentage: number
43
+ }
44
+
45
+ export interface TQuoteUniLike {
46
+ routes: TRouteWithQuote[],
47
+ quote: bigint
48
+ }
49
+
50
+ export type AlgoParams = {
51
+ maxHops: number,
52
+ distributionPercentage: number,
53
+ maxSplit: number
54
+ }
@@ -0,0 +1,212 @@
1
+ import Web3 from 'web3';
2
+ import { Pool, PoolInfo, DEXGraphFunctionality } from '../utils/types/types'
3
+ import { Dexes } from '../index';
4
+ import { myLocalStorage } from './my_local_storage';
5
+ import UniswapV2 from '../dexes/graph_queries/UniswapV2';
6
+ import SushiSwapV2 from '../dexes/graph_queries/SushiSwapV2';
7
+ import UniswapV3 from '../dexes/graph_queries/UniswapV3';
8
+ import BalancerV2 from '../dexes/graph_queries/BalancerV2';
9
+ import CamelotV2 from '../dexes/graph_queries/CamelotV2';
10
+
11
+ let initializedMainnet = false
12
+ let initializedArbitrum = false
13
+ let initializedSei = false;
14
+ let initializedPas = false;
15
+
16
+ let initializedDexes: DEXGraphFunctionality[] = []
17
+ let dexesPools: Map<DEXGraphFunctionality, PoolInfo[]> = new Map<DEXGraphFunctionality, PoolInfo[]>()
18
+
19
+ async function initializeDexes(chainId: number, graphApiKey: string, dexes: Array<Dexes>): Promise<void> {
20
+ try {
21
+ // Clear Previous Dex Graph Mappings and Initialized DEX array
22
+ dexesPools.clear()
23
+ initializedDexes = []
24
+
25
+ for (const dex of dexes) {
26
+ let Dex;
27
+ switch (dex) {
28
+ case Dexes.BALANCER:
29
+ Dex = BalancerV2;
30
+ break;
31
+ case Dexes.CAMELOT:
32
+ if (chainId === 1)
33
+ continue;
34
+ Dex = CamelotV2;
35
+ break;
36
+ case Dexes.SUSHISWAP_V2:
37
+ Dex = SushiSwapV2;
38
+ break;
39
+ case Dexes.UNISWAP_V2:
40
+ if (chainId === 42161)
41
+ continue;
42
+ Dex = UniswapV2;
43
+ break;
44
+ case Dexes.UNISWAP_V3:
45
+ Dex = UniswapV3;
46
+ break;
47
+ default:
48
+ throw Error("Invalid Dex value")
49
+ }
50
+ const dexInstance: DEXGraphFunctionality = Dex.initialize(myLocalStorage)
51
+ dexInstance.setEndpoint(chainId, graphApiKey)
52
+ initializedDexes.push(dexInstance)
53
+ dexesPools.set(dexInstance, [])
54
+ }
55
+ } catch (err) {
56
+ console.error('Error reading directory dexes_graph:', err)
57
+ }
58
+ }
59
+
60
+ async function checkInitializedDexes(chainId: number, graphApiKey: string, dexes: Array<Dexes>) {
61
+ if (chainId === 1 && !initializedMainnet) {
62
+ await initializeDexes(chainId, graphApiKey, dexes)
63
+ initializedArbitrum = false
64
+ initializedSei = false
65
+ initializedPas = false
66
+ initializedMainnet = true
67
+ }
68
+ if (chainId === 42161 && !initializedArbitrum) {
69
+ await initializeDexes(chainId, graphApiKey, dexes)
70
+ initializedMainnet = false
71
+ initializedSei = false
72
+ initializedPas = false
73
+ initializedArbitrum = true
74
+ }
75
+
76
+ if (chainId === 1329 && !initializedSei)
77
+ {
78
+ await initializeDexes(chainId, graphApiKey, dexes)
79
+ initializedMainnet = false
80
+ initializedArbitrum = false
81
+ initializedPas = false
82
+ initializedSei = true
83
+ }
84
+
85
+ if (chainId === 420420417 && !initializedPas)
86
+ {
87
+ await initializeDexes(chainId, graphApiKey, dexes)
88
+ initializedMainnet = false
89
+ initializedArbitrum = false
90
+ initializedSei = false
91
+ initializedPas = true
92
+ }
93
+
94
+ }
95
+
96
+ /* Returns dictionary of dexes and their poolIds for token1 and token2:
97
+ * UniswapV3: [poolId1, poolId2, ...],
98
+ * SushiSwapV2: [poolId1, poolId2, ...]
99
+ */
100
+ async function getPoolIdsForTokenPairs(tokenA: string, tokenB: string, numPools: number = 3, chainId: number, graphApiKey: string, dexes: Array<Dexes>): Promise<void> {
101
+ await checkInitializedDexes(chainId, graphApiKey, dexes)
102
+
103
+ const allPoolsPromises = initializedDexes.map((dex) => dex.getPoolsWithTokenPair(tokenA, tokenB, numPools))
104
+ const allPoolsResults = await Promise.all(allPoolsPromises)
105
+
106
+ initializedDexes.forEach((dex, index) => {
107
+ const pools = allPoolsResults[index]
108
+ if (dexesPools.has(dex)) {
109
+ dexesPools.get(dex)?.push(...pools)
110
+ } else {
111
+ dexesPools.set(dex, pools)
112
+ }
113
+ })
114
+ }
115
+
116
+ /* Get pools from each dex in initializedDexes list that have token as one of the tokens in the pool
117
+ * @param token: token address to match (for now the chain is Arbitrum -> param for the future)
118
+ * @param numPools: number of pools to return from each dex
119
+ * @param amountIn: amount of token1 to swap (in wei) - currently unused
120
+ * @returns: list of poolIds
121
+ */
122
+ async function getPoolIdsForToken(token: string, numPools: number = 5, chainId: number, graphApiKey: string, dexes: Array<Dexes>): Promise<void> {
123
+ await checkInitializedDexes(chainId, graphApiKey, dexes)
124
+
125
+ const allPoolsPromises = initializedDexes.map((dex) => dex.getPoolsWithToken(token, numPools))
126
+ const allPoolsResults = await Promise.all(allPoolsPromises)
127
+
128
+ initializedDexes.forEach((dex, index) => {
129
+ const pools = allPoolsResults[index]
130
+ if (dexesPools.has(dex)) {
131
+ dexesPools.get(dex)?.push(...pools)
132
+ } else {
133
+ dexesPools.set(dex, pools)
134
+ }
135
+ })
136
+ }
137
+
138
+ /* Get top pools from each dex in initializedDexes list - returns a list of poolIds
139
+ * @param numPools: number of pools to return from each dex
140
+ * @param amountIn: amount of token1 to swap (in wei) - currently unused
141
+ * @returns: list of poolIds
142
+ */
143
+ async function getTopPools(numPools: number = 5, chainId: number, graphApiKey: string, dexes: Array<Dexes>): Promise<void> {
144
+ await checkInitializedDexes(chainId, graphApiKey, dexes)
145
+
146
+ const allPoolsPromises = initializedDexes.map((dex) => dex.getTopPools(numPools))
147
+ const allPoolsResults = await Promise.all(allPoolsPromises)
148
+
149
+ initializedDexes.forEach((dex, index) => {
150
+ const pools = allPoolsResults[index]
151
+ if (dexesPools.has(dex)) {
152
+ dexesPools.get(dex)?.push(...pools)
153
+ } else {
154
+ dexesPools.set(dex, pools)
155
+ }
156
+ })
157
+ }
158
+
159
+ /* We are fetching pools from multiple dexes, so we might get duplicate pools
160
+ * top numTopPools pools for tokenFrom and tokenTo are fetched from each DEX
161
+ * top numTopPools by TVL from each DEX
162
+ * top numTopPools that contain tokenFrom and tokenTo from each DEX (possible direct swap)
163
+ */
164
+ async function fetchPoolsData(
165
+ tokenFrom: string,
166
+ tokenTo: string,
167
+ numFromToPools: number = 5,
168
+ numTopPools: number = 5,
169
+ chainId: number,
170
+ rpcProvider: Web3,
171
+ graphApiKey: string,
172
+ dexes: Array<Dexes>
173
+ ): Promise<Pool[]> {
174
+ let pools: Pool[] = []
175
+ dexesPools.forEach((poolInfos: PoolInfo[], dex: DEXGraphFunctionality) => {
176
+ dexesPools.set(dex, [])
177
+ })
178
+
179
+ await checkInitializedDexes(chainId, graphApiKey, dexes)
180
+
181
+ // call Graph API
182
+ const promises: Promise<void>[] = []
183
+ promises.push(getPoolIdsForToken(tokenFrom, numFromToPools, chainId, graphApiKey, dexes))
184
+ promises.push(getPoolIdsForToken(tokenTo, numFromToPools, chainId, graphApiKey, dexes))
185
+ promises.push(getTopPools(numTopPools, chainId, graphApiKey, dexes))
186
+ promises.push(getPoolIdsForTokenPairs(tokenFrom, tokenTo, numFromToPools, chainId, graphApiKey, dexes))
187
+ await Promise.all(promises)
188
+ filterDuplicatePools()
189
+
190
+ // call Solidity for additional pool data
191
+ const dexPoolsPromises: Promise<Pool[]>[] = []
192
+ for (let [dex, poolInfos] of dexesPools.entries()) {
193
+ dexPoolsPromises.push(dex.getAdditionalPoolDataFromSolidity(poolInfos, rpcProvider))
194
+ }
195
+ const allPoolsData = await Promise.all(dexPoolsPromises)
196
+ allPoolsData.forEach((poolsData: Pool[]) => {
197
+ pools.push(...poolsData)
198
+ })
199
+
200
+ return pools
201
+ }
202
+
203
+ function filterDuplicatePools(): void {
204
+ dexesPools.forEach((poolInfos: PoolInfo[], dex: DEXGraphFunctionality, self) => {
205
+ const filteredPoolInfos = poolInfos.filter((poolInfo: PoolInfo, index: number, allPoolInfos: PoolInfo[]) => {
206
+ return allPoolInfos.findIndex((pool2) => pool2.poolId === poolInfo.poolId) === index
207
+ })
208
+ self.set(dex, filteredPoolInfos)
209
+ })
210
+ }
211
+
212
+ export { fetchPoolsData }
@@ -0,0 +1,27 @@
1
+ import { Pool } from "../utils/types/types";
2
+
3
+ interface ILocalStorage {
4
+ setItem(key: string, value: Pool): void;
5
+ getItem(key: string): Pool | null;
6
+ removeItem(key: string): void;
7
+ }
8
+
9
+ const values: { [key: string]: Pool } = {};
10
+
11
+ class MockLocalStorage implements ILocalStorage {
12
+
13
+
14
+ setItem(key: string, value: Pool): void {
15
+ values[key] = value;
16
+ }
17
+
18
+ getItem(key: string): Pool | null {
19
+ return values[key] || null;
20
+ }
21
+
22
+ removeItem(key: string): void {
23
+ delete values[key];
24
+ }
25
+ }
26
+
27
+ export const myLocalStorage: ILocalStorage = new MockLocalStorage();
package/tsconfig.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2019",
4
+ "module": "CommonJS",
5
+ "declaration": true,
6
+ "moduleResolution": "node",
7
+ "esModuleInterop": true,
8
+ "allowSyntheticDefaultImports": true,
9
+ "strict": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "outDir": "./dist",
13
+ "rootDir": ".",
14
+ "resolveJsonModule": true,
15
+ "isolatedModules": false,
16
+ "noEmitOnError": true
17
+ },
18
+ "include": [
19
+ "."
20
+ ],
21
+ "exclude": [
22
+ "node_modules",
23
+ "dist",
24
+ "./dexes/pools/uniswap/testUniswapOffchainQuoter.ts"
25
+ ]
26
+ }
@@ -0,0 +1,64 @@
1
+ // hardcode it like this for now
2
+ export const addresses = {
3
+
4
+ // Acutally used.
5
+ name: "sei",
6
+ uniQuoterV2: "0x38F759cf0Af1D0dcAEd723a3967A3B658738eDe9",
7
+
8
+ wethToken: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
9
+ daiToken: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
10
+ usdtToken: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
11
+ wbtcToken: "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f",
12
+ usdcToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
13
+ uniToken: "0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0",
14
+ linkToken: "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4",
15
+ usdceToken: "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8",
16
+ gmxToken: "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a",
17
+
18
+ sushiRouter: "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506",
19
+ sushiFactory: "0xc35DADB65012eC5796536bD9864eD8773aBc74C4",
20
+
21
+ // uniQuoter: "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
22
+ // uniQuoterV2: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
23
+ // uniRouter: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
24
+
25
+ univ3_wbtc_eth_pool_0_05: "0x2f5e87C9312fa29aed5c179E456625D79015299c", // 0.05 fee
26
+ univ3_wbtc_eth_pool_0_3: "0x149e36E72726e0BceA5c59d40df2c43F60f5A22D", // 0.3 fee
27
+ sushi_wbtc_eth_pool: "0x515e252b2b5c22b4b2b6Df66c2eBeeA871AA4d69", // 0.3 fee always
28
+ gmx_usdc_pool_0_1: "0x0A36952Fb8C8dc6daeFB2fADb07C5212f560880e",
29
+ uni_weth_pool: "0xC24f7d8E51A64dc1238880BD00bb961D54cbeb29",
30
+ weth_link_pool: "0x468b88941e7Cc0B88c1869d68ab6b570bCEF62Ff",
31
+ dai_usdce_pool_0_0_1: "0xF0428617433652c9dc6D1093A42AdFbF30D29f74",
32
+
33
+ impersonate_weth: "0x0df5dfd95966753f01cb80e76dc20ea958238c46",
34
+ impersonate_dai: "0xd85e038593d7a098614721eae955ec2022b9b91b"
35
+
36
+ // name: "arbitrum",
37
+ //
38
+ // wethToken: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
39
+ // daiToken: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
40
+ // usdtToken: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
41
+ // wbtcToken: "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f",
42
+ // usdcToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
43
+ // uniToken: "0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0",
44
+ // linkToken: "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4",
45
+ // usdceToken: "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8",
46
+ // gmxToken: "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a",
47
+ //
48
+ // sushiRouter: "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506",
49
+ // sushiFactory: "0xc35DADB65012eC5796536bD9864eD8773aBc74C4",
50
+ //
51
+ // uniQuoter: "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
52
+ // uniQuoterV2: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
53
+ // uniRouter: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
54
+ // univ3_wbtc_eth_pool_0_05: "0x2f5e87C9312fa29aed5c179E456625D79015299c", // 0.05 fee
55
+ // univ3_wbtc_eth_pool_0_3: "0x149e36E72726e0BceA5c59d40df2c43F60f5A22D", // 0.3 fee
56
+ // sushi_wbtc_eth_pool: "0x515e252b2b5c22b4b2b6Df66c2eBeeA871AA4d69", // 0.3 fee always
57
+ // gmx_usdc_pool_0_1: "0x0A36952Fb8C8dc6daeFB2fADb07C5212f560880e",
58
+ // uni_weth_pool: "0xC24f7d8E51A64dc1238880BD00bb961D54cbeb29",
59
+ // weth_link_pool: "0x468b88941e7Cc0B88c1869d68ab6b570bCEF62Ff",
60
+ // dai_usdce_pool_0_0_1: "0xF0428617433652c9dc6D1093A42AdFbF30D29f74",
61
+ //
62
+ // impersonate_weth: "0x0df5dfd95966753f01cb80e76dc20ea958238c46",
63
+ // impersonate_dai: "0xd85e038593d7a098614721eae955ec2022b9b91b"
64
+ }
@@ -0,0 +1,88 @@
1
+ // Ported from Solidity:
2
+ // https://github.com/balancer-labs/balancer-core-v2/blob/70843e6a61ad11208c1cfabf5cfe15be216ca8d3/pkg/solidity-utils/contracts/math/FixedPoint.sol
3
+
4
+ import BigNumber from "bignumber.js"
5
+ import * as logExp from "./log-exp"
6
+
7
+ export const ZERO = new BigNumber(0)
8
+ export const ONE = new BigNumber("1000000000000000000") // 10^18
9
+
10
+ export const MAX_POW_RELATIVE_ERROR = new BigNumber(10000) // 10^(-14)
11
+
12
+ // Minimum base for the power function when the exponent is 'free' (larger than ONE)
13
+ export const MIN_POW_BASE_FREE_EXPONENT = new BigNumber("700000000000000000") // 0.7e18
14
+
15
+ export const add = (a: BigNumber, b: BigNumber): BigNumber => {
16
+ // Fixed Point addition is the same as regular checked addition
17
+ return a.plus(b)
18
+ }
19
+
20
+ export const sub = (a: BigNumber, b: BigNumber): BigNumber => {
21
+ // Fixed Point subtraction is the same as regular checked subtraction
22
+ if (b.gt(a))
23
+ throw new Error("SUB_OVERFLOW")
24
+ return a.minus(b)
25
+ };
26
+
27
+ export const mulDown = (a: BigNumber, b: BigNumber): BigNumber => {
28
+ return a.times(b).idiv(ONE)
29
+ };
30
+
31
+ export const mulUp = (a: BigNumber, b: BigNumber): BigNumber => {
32
+ const product = a.times(b)
33
+ if (product.isZero()) {
34
+ return product
35
+ } else {
36
+ // The traditional divUp formula is:
37
+ // divUp(x, y) := (x + y - 1) / y
38
+ // To avoid intermediate overflow in the addition, we distribute the division and get:
39
+ // divUp(x, y) := (x - 1) / y + 1
40
+ // Note that this requires x != 0, which we already tested for
41
+ return product.minus(new BigNumber(1)).idiv(ONE).plus(new BigNumber(1))
42
+ }
43
+ }
44
+
45
+ export const divDown = (a: BigNumber, b: BigNumber): BigNumber => {
46
+ if (b.isZero())
47
+ throw new Error("ZERO_DIVISION");
48
+ if (a.isZero())
49
+ return a
50
+ else
51
+ return a.times(ONE).idiv(b);
52
+ }
53
+
54
+ export const divUp = (a: BigNumber, b: BigNumber): BigNumber => {
55
+ if (b.isZero())
56
+ throw new Error("ZERO_DIVISION");
57
+ if (a.isZero())
58
+ return a;
59
+ else {
60
+ // The traditional divUp formula is:
61
+ // divUp(x, y) := (x + y - 1) / y
62
+ // To avoid intermediate overflow in the addition, we distribute the division and get:
63
+ // divUp(x, y) := (x - 1) / y + 1
64
+ // Note that this requires x != 0, which we already tested for.
65
+ return a.times(ONE).minus(new BigNumber(1)).idiv(b).plus(new BigNumber(1));
66
+ }
67
+ };
68
+
69
+ export const powDown = (x: BigNumber, y: BigNumber): BigNumber => {
70
+
71
+ const raw = logExp.pow(x, y);
72
+ const maxError = add(mulUp(raw, MAX_POW_RELATIVE_ERROR), new BigNumber(1));
73
+ if (raw.lt(maxError))
74
+ return new BigNumber(0)
75
+ else {
76
+ return sub(raw, maxError)
77
+ }
78
+ }
79
+
80
+ export const powUp = (x: BigNumber, y: BigNumber): BigNumber => {
81
+ const raw = logExp.pow(x, y)
82
+ const maxError = add(mulUp(raw, MAX_POW_RELATIVE_ERROR), new BigNumber(1))
83
+ return add(raw, maxError)
84
+ }
85
+
86
+ export const complement = (x: BigNumber): BigNumber => {
87
+ return x.lt(ONE) ? ONE.minus(x) : new BigNumber(0)
88
+ }