cryptointerface 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,301 @@
1
+ {
2
+ "uniswap_v2": {
3
+ "1": {
4
+ "factory": "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f",
5
+ "router": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"
6
+ },
7
+ "10": {
8
+ "factory": "0x0c3c1c532F1e39EdF36BE9Fe0bE1410313E074Bf",
9
+ "router": "0x4a7b5da61326a6379179b40d00f57e5bbdc962c2"
10
+ },
11
+ "56": {
12
+ "factory": "0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6",
13
+ "router": "0x4752ba5dbc23f44d87826276bf6fd6b1c372ad24"
14
+ },
15
+ "137": {
16
+ "factory": "0x9e5A52f57b3038F1B8EeE45F28b3C1967e22799C",
17
+ "router": "0xedf6066a2b290c185783862c7f4776a2c8077ad1"
18
+ },
19
+ "8453": {
20
+ "factory": "0x8909dc15e40173ff4699343b6eb8132c65e18ec6",
21
+ "router": "0x4752ba5dbc23f44d87826276bf6fd6b1c372ad24"
22
+ },
23
+ "42161": {
24
+ "factory": "0xf1D7CC64Fb4452F05c498126312eBE29f30Fbcf9",
25
+ "router": "0x4752ba5dbc23f44d87826276bf6fd6b1c372ad24"
26
+ },
27
+ "42220": {
28
+ "factory": "0x79a530c8e2fA8748B7B40dd3629C0520c2cCf03f",
29
+ "router": null
30
+ },
31
+ "43114": {
32
+ "factory": "0x9e5A52f57b3038F1B8EeE45F28b3C1967e22799C",
33
+ "router": "0x4752ba5dbc23f44d87826276bf6fd6b1c372ad24"
34
+ },
35
+ "81457": {
36
+ "factory": "0x5C346464d33F90bABaf70dB6388507CC889C1070",
37
+ "router": "0xBB66Eb1c5e875933D44DAe661dbD80e5D9B03035"
38
+ },
39
+ "11155111": {
40
+ "factory": "0xF62c03E08ada871A0bEb309762E260a7a6a880E6",
41
+ "router": "0xeE567Fe1712Faf6149d80dA1E6934E354124CfE3"
42
+ }
43
+ },
44
+ "uniswap_v3": {
45
+ "1": {
46
+ "factory": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
47
+ "router": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
48
+ "quoter": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
49
+ "position_manager": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
50
+ "migrator": "0xA5644E29708357803b5A882D272c41cC0dF92B34"
51
+ },
52
+ "10": {
53
+ "factory": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
54
+ "router": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
55
+ "quoter": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
56
+ "position_manager": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
57
+ "migrator": "0xA5644E29708357803b5A882D272c41cC0dF92B34"
58
+ },
59
+ "30": {
60
+ "factory": "0xaF37EC98A00FD63689CF3060BF3B6784E00caD82",
61
+ "router": "0xFB7eF66a7e61224DD6FcD0D7d9C3be5C8B049b9f",
62
+ "quoter": "0xb5227F20f7c33A3f53E72E22f28bE7FAa01b7E6C",
63
+ "position_manager": "0x9d9386c042F194B460Ec424a1e57ACDE25f5C4b1",
64
+ "migrator": null
65
+ },
66
+ "56": {
67
+ "factory": "0xdB1d10011AD0Ff90774D0C6Bb92e5C5c8b4461F7",
68
+ "router": "0xB971eF87ede563556b2ED4b1C0b0019111Dd85d2",
69
+ "quoter": "0x78D78E420Da98ad378D7799bE8f4AF69033EB077",
70
+ "position_manager": "0x7b8A01B39D58278b5DE7e48c8449c9f4F5170613",
71
+ "migrator": "0x32681814957e0C13117ddc0c2aba232b5c9e760f"
72
+ },
73
+ "137": {
74
+ "factory": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
75
+ "router": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
76
+ "quoter": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
77
+ "position_manager": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
78
+ "migrator": "0xA5644E29708357803b5A882D272c41cC0dF92B34"
79
+ },
80
+ "8453": {
81
+ "factory": "0x33128a8fC17869897dcE68Ed026d694621f6FDfD",
82
+ "router": "0x2626664c2603336E57B271c5C0b26F421741e481",
83
+ "quoter": "0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a",
84
+ "position_manager": "0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1",
85
+ "migrator": "0x23cF10b1ee3AdfCA73B0eF17C07F7577e7ACd2d7"
86
+ },
87
+ "42161": {
88
+ "factory": "0x1F98431c8aD98523631AE4a59f267346ea31F984",
89
+ "router": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
90
+ "quoter": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
91
+ "position_manager": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
92
+ "migrator": "0xA5644E29708357803b5A882D272c41cC0dF92B34"
93
+ },
94
+ "43114": {
95
+ "factory": "0x740b1c1de25031C31FF4fC9A62f554A55cdC1baD",
96
+ "router": "0xbb00FF08d01D300023C629E8fFfFcb65A5a578cE",
97
+ "quoter": "0xbe0F5544EC67e9B3b2D979aaA43f18Fd87E6257F",
98
+ "position_manager": "0x655C406EBFa14EE2006250925e54ec43AD184f8B",
99
+ "migrator": "0x44f5f1f5E452ea8d29C890E8F6e893fC0f1f0f97"
100
+ },
101
+ "81457": {
102
+ "factory": "0x792edAdE80af5fC680d96a2eD80A44247D2Cf6Fd",
103
+ "router": "0x549FEB8c9bd4c12Ad2AB27022dA12492aC452B66",
104
+ "quoter": "0x6Cdcd65e03c1CEc3730AeeCd45bc140D57A25C77",
105
+ "position_manager": "0xB218e4f7cF0533d4696fDfC419A0023D33345F28",
106
+ "migrator": "0x15CA7043CD84C5D21Ae76Ba0A1A967d42c40ecE0"
107
+ },
108
+ "7777777": {
109
+ "factory": "0x7145F8aeef1f6510E92164038E1B6F8cB2c42Cbb",
110
+ "router": "0x7De04c96BE5159c3b5CeffC82aa176dc81281557",
111
+ "quoter": "0x11867e1b3348F3ce4FcC170BC5af3d23E07E64Df",
112
+ "position_manager": "0xbC91e8DfA3fF18De43853372A3d7dfe585137D78",
113
+ "migrator": null
114
+ },
115
+ "11155111": {
116
+ "factory": "0x0227628f3F023bb0B980b67D528571c95c6DaC1c",
117
+ "router": "0x3bFA4769FB09eefC5a80d6E87c3B9C650f7Ae48E",
118
+ "quoter": "0xEd1f6473345F45b75833fd55D191EaA8F5C33CD4",
119
+ "position_manager": "0x1238536071E1c677A632429e3655c799b22cDA52",
120
+ "migrator": null
121
+ }
122
+ },
123
+ "sushiswap_v2": {
124
+ "1": {
125
+ "factory": "0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac",
126
+ "router": "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F"
127
+ },
128
+ "10": {
129
+ "factory": "0xFbc12984689e5f15626Bad03Ad60160Fe98B303C",
130
+ "router": "0xa132DAB612dB5cB9fC9Ac426A0Cc215A3423F9c9"
131
+ },
132
+ "56": {
133
+ "factory": "0xc35DADB65012eC5796536bD9864eD8773aBc74C4",
134
+ "router": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506"
135
+ },
136
+ "137": {
137
+ "factory": "0xc35DADB65012eC5796536bD9864eD8773aBc74C4",
138
+ "router": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506"
139
+ },
140
+ "8453": {
141
+ "factory": "0x71524B4f93c58fcbF659783284E38825f0622859",
142
+ "router": "0x6BDED42c6DA8FBf0d2bA55B2fa120C5e0c8D7891"
143
+ },
144
+ "42161": {
145
+ "factory": "0xc35DADB65012eC5796536bD9864eD8773aBc74C4",
146
+ "router": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506"
147
+ },
148
+ "43114": {
149
+ "factory": "0xc35DADB65012eC5796536bD9864eD8773aBc74C4",
150
+ "router": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506"
151
+ },
152
+ "11155111": {
153
+ "factory": "0x734583f62Bb6ACe3c9bA9bd5A53143CA2Ce8C55A",
154
+ "router": "0xeaBcE3E74EF41FB40024a21Cc2ee2F5dDc615791"
155
+ }
156
+ },
157
+ "sushiswap_v3": {
158
+ "1": {
159
+ "factory": "0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F",
160
+ "router": "0x2c9a4Dc517f4Cb3E8dd1f4A78d0C6Fb793BC001",
161
+ "quoter": "0x64e8802FE490fa7cc61d3463958199161Bb608A7",
162
+ "position_manager": "0x2214A42d8e2A1d20635c2cb0664422c528B6A432"
163
+ },
164
+ "10": {
165
+ "factory": "0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0",
166
+ "router": "0xYourRouter",
167
+ "quoter": "0xYourQuoter",
168
+ "position_manager": "0x1af415a1EbA07a4986a52B6f2e7dE7003D82231e"
169
+ },
170
+ "56": {
171
+ "factory": "0x126555aa41B33402279070107F2393494E74110",
172
+ "router": "0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6",
173
+ "quoter": "0xb1E835Dc2785b52265711e17fCCb0fd018226a6e",
174
+ "position_manager": "0xF70c086618dcf2b1A461311275e00D6B722ef914"
175
+ },
176
+ "137": {
177
+ "factory": "0x917933899c6a5F8E37F31E19f92CdBFF7e8FF0e2",
178
+ "router": "0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6",
179
+ "quoter": "0xb1E835Dc2785b52265711e17fCCb0fd018226a6e",
180
+ "position_manager": "0xb7402ee99F0A008e461098AC3A27F4957Df89a40"
181
+ },
182
+ "8453": {
183
+ "factory": "0xc35DADB65012eC5796536bD9864eD8773aBc74C4",
184
+ "router": "0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6",
185
+ "quoter": "0xb1E835Dc2785b52265711e17fCCb0fd018226a6e",
186
+ "position_manager": "0x80C7DD17B01855a6D2347444a0FCC36136a314de"
187
+ },
188
+ "42161": {
189
+ "factory": "0x1af415a1EbA07a4986a52B6f2e7dE7003D82231e",
190
+ "router": "0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6",
191
+ "quoter": "0xb1E835Dc2785b52265711e17fCCb0fd018226a6e",
192
+ "position_manager": "0x717b7948AA264DeCf4D780aa6914482e5F46Da3e"
193
+ },
194
+ "43114": {
195
+ "factory": "0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715",
196
+ "router": "0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6",
197
+ "quoter": "0xb1E835Dc2785b52265711e17fCCb0fd018226a6e",
198
+ "position_manager": "0x18350b048AB366ed601f5AF36a0E4a4F63EFbBEd"
199
+ },
200
+ "11155111": {
201
+ "factory": "0x1f2FCf1d036b375b384012e61D3AA33F8C256bbE",
202
+ "router": "0x93c31c9C729A249b2877F7699e178F4720407733",
203
+ "quoter": "0x039e87AB90205F9d87c5b40d4B28e2Be45dA4a20",
204
+ "position_manager": "0x6CE4e3489aA4Ae7B7CcE1719De0Ef7F1c94eDC02"
205
+ }
206
+ },
207
+ "pancakeswap_v2": {
208
+ "1": {
209
+ "factory": "0x1097053Fd2ea711dad45caCcc45EfF7548fCB362",
210
+ "router": "0xEfF92A263d31888d860bD50809A8D171709b7b1c"
211
+ },
212
+ "56": {
213
+ "factory": "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73",
214
+ "router": "0x10ED43C718714eb63d5aA57B78B54704E256024E"
215
+ },
216
+ "8453": {
217
+ "factory": "0x02a84c1b3BBD7401a5f7a18a8bE6a2A4bFC99cce",
218
+ "router": "0x8cFe327CEc66d1C090Dd72bd0FF11d690C33a2Eb"
219
+ },
220
+ "42161": {
221
+ "factory": "0x02a84c1b3BBD7401a5f7a18a8bE6a2A4bFC99cce",
222
+ "router": "0x8cFe327CEc66d1C090Dd72bd0FF11d690C33a2Eb"
223
+ }
224
+ },
225
+ "pancakeswap_v3": {
226
+ "1": {
227
+ "factory": "0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865",
228
+ "router": "0x13f4EA83D0bd40E75C8222255bc855a974568Dd4",
229
+ "quoter": "0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997",
230
+ "position_manager": "0x46A15B0b27311cedF172AB29E4f4766fbE7F4364"
231
+ },
232
+ "56": {
233
+ "factory": "0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865",
234
+ "router": "0x13f4EA83D0bd40E75C8222255bc855a974568Dd4",
235
+ "quoter": "0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997",
236
+ "position_manager": "0x46A15B0b27311cedF172AB29E4f4766fbE7F4364"
237
+ },
238
+ "8453": {
239
+ "factory": "0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865",
240
+ "router": "0x678Aa4bF4E210cf2166753e054d5b7c31cc7fa86",
241
+ "quoter": "0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997",
242
+ "position_manager": "0x46A15B0b27311cedF172AB29E4f4766fbE7F4364"
243
+ },
244
+ "42161": {
245
+ "factory": "0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865",
246
+ "router": "0x32226588378236Fd0c7c4053999F88aC0e5cAC77",
247
+ "quoter": "0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997",
248
+ "position_manager": "0x46A15B0b27311cedF172AB29E4f4766fbE7F4364"
249
+ }
250
+ },
251
+ "quickswap_v2": {
252
+ "137": {
253
+ "factory": "0x5757371414417b8C6CAad45bAeF941aBc7d3Ab32",
254
+ "router": "0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff"
255
+ }
256
+ },
257
+ "quickswap_v3": {
258
+ "137": {
259
+ "factory": "0x411b0fAcC3489691f28ad58c47006AF5E3Ab3A28",
260
+ "router": "0xf5b509bB0909a69B1c207E495f687a596C168E12",
261
+ "quoter": "0xa15F0D7377B2A0C0c10db057f641beD21028FC89",
262
+ "position_manager": "0x8eF88E4c7CfbbaC1C163f7eddd4B578792201de6"
263
+ }
264
+ },
265
+ "camelot_v2": {
266
+ "42161": {
267
+ "factory": "0x6EcCab422D763aC031210895C81787E87B43A652",
268
+ "router": "0xc873fEcbd354f5A56E00E710B90EF4201db2448d"
269
+ }
270
+ },
271
+ "camelot_v3": {
272
+ "42161": {
273
+ "factory": "0x1a3c9B1d2F0529D97f2afC5136Cc23e58f1FD35d",
274
+ "router": "0x1F721E2E82F6676FCE4eA07A5958cF098D339e18",
275
+ "quoter": "0x0Fc73040b26E9bC8514fA028D998E73EB6D47088",
276
+ "position_manager": "0x00c7f3082833e796A5b3e4Bd59f6642FF44DCD15"
277
+ }
278
+ },
279
+ "traderjoe_v1": {
280
+ "43114": {
281
+ "factory": "0x9Ad6C38BE94206cA50bb0d90783181662f0Cfa10",
282
+ "router": "0x60aE616a2155Ee3d9A68541Ba4544862310933d4"
283
+ },
284
+ "42161": {
285
+ "factory": "0xaE4EC9901c3076D0DdBe76A520F9E90a6227aCB7",
286
+ "router": "0xbeE5c10Cf6E4F68f831E11C1D9E59B43560B3642"
287
+ }
288
+ },
289
+ "aerodrome": {
290
+ "8453": {
291
+ "factory": "0x420DD381b31aEf6683db6B902084cB0FFECe40Da",
292
+ "router": "0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43"
293
+ }
294
+ },
295
+ "velodrome": {
296
+ "10": {
297
+ "factory": "0x25CbdDb98b35ab1FF77413456B31EC81A6B6B746",
298
+ "router": "0xa062aE8A9c5e11aaA026fc2670B0D65cCc8B2858"
299
+ }
300
+ }
301
+ }
@@ -0,0 +1,56 @@
1
+ import json
2
+ from pathlib import Path
3
+
4
+ _JSON_PATH = Path(__file__).parent / "dex_contracts.json"
5
+ _ARCH_PATH = Path(__file__).parent / "dex_architecture.json"
6
+
7
+
8
+ def _load() -> dict:
9
+ with open(_JSON_PATH, "r") as f:
10
+ return json.load(f)
11
+
12
+
13
+ def _load_architecture() -> dict:
14
+ with open(_ARCH_PATH, "r") as f:
15
+ return json.load(f)
16
+
17
+
18
+ def get_dex_architecture(dex_name: str) -> dict | None:
19
+ return _load_architecture().get(dex_name)
20
+
21
+
22
+ def _save(data: dict) -> None:
23
+ with open(_JSON_PATH, "w") as f:
24
+ json.dump(data, f, indent=4)
25
+
26
+
27
+ def get_dex_contracts(dex: str, chain_id: int) -> dict[str, str] | None:
28
+ """Return the contract addresses for a given DEX and chain ID, or None if unsupported."""
29
+ return _load().get(dex, {}).get(str(chain_id))
30
+
31
+
32
+ def get_supported_dexes() -> list[str]:
33
+ return list(_load().keys())
34
+
35
+
36
+ def get_supported_chains(dex: str) -> list[int]:
37
+ return [int(k) for k in _load().get(dex, {}).keys()]
38
+
39
+
40
+ def add_dex_entry(dex: str, chain_id: int, contracts: dict[str, str | None]) -> None:
41
+ """
42
+ Add or update a chain entry for a DEX. Changes are written to dex_contracts.json.
43
+
44
+ Example:
45
+ add_dex_entry("sushiswap_v3", 1, {
46
+ "factory": "0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F",
47
+ "router": "0x...",
48
+ "quoter": "0x...",
49
+ "position_manager": "0x...",
50
+ })
51
+ """
52
+ data = _load()
53
+ if dex not in data:
54
+ data[dex] = {}
55
+ data[dex][str(chain_id)] = contracts
56
+ _save(data)
@@ -0,0 +1,31 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Network(Enum):
5
+ ETHEREUM = "1"
6
+ OPTIMISM = "10"
7
+ BSC = "56"
8
+ POLYGON = "137"
9
+ BASE = "8453"
10
+ ARBITRUM = "42161"
11
+ CELO = "42220"
12
+ AVALANCHE = "43114"
13
+ BLAST = "81457"
14
+ ZORA = "7777777"
15
+ SEPOLIA = "11155111"
16
+
17
+
18
+ class Platform(Enum):
19
+ UNISWAP_V2 = "uniswap_v2"
20
+ UNISWAP_V3 = "uniswap_v3"
21
+ SUSHISWAP_V2 = "sushiswap_v2"
22
+ SUSHISWAP_V3 = "sushiswap_v3"
23
+ PANCAKESWAP_V2 = "pancakeswap_v2"
24
+ PANCAKESWAP_V3 = "pancakeswap_v3"
25
+ QUICKSWAP_V2 = "quickswap_v2"
26
+ QUICKSWAP_V3 = "quickswap_v3"
27
+ CAMELOT_V2 = "camelot_v2"
28
+ CAMELOT_V3 = "camelot_v3"
29
+ TRADERJOE_V1 = "traderjoe_v1"
30
+ AERODROME = "aerodrome"
31
+ VELODROME = "velodrome"
@@ -0,0 +1,118 @@
1
+ # Maps CoinGecko platform/network slugs to EVM chain IDs.
2
+ # Non-EVM chains (Cosmos, Aptos, NEAR, Tron, etc.) are mapped to None.
3
+ COINGECKO_CHAIN_IDS: dict[str, int | None] = {
4
+ "ethereum": 1,
5
+ "arbitrum-one": 42161,
6
+ "arbitrum-nova": 42170,
7
+ "avalanche": 43114,
8
+ "binance-smart-chain": 56,
9
+ "polygon-pos": 137,
10
+ "polygon-zkevm": 1101,
11
+ "optimistic-ethereum": 10,
12
+ "base": 8453,
13
+ "blast": 81457,
14
+ "linea": 59144,
15
+ "mantle": 5000,
16
+ "zksync": 324,
17
+ "scroll": 534352,
18
+ "taiko": 167000,
19
+ "mode": 34443,
20
+ "zora-network": 7777777,
21
+ "metis-andromeda": 1088,
22
+ "fantom": 250,
23
+ "celo": 42220,
24
+ "moonbeam": 1284,
25
+ "moonriver": 1285,
26
+ "aurora": 1313161554,
27
+ "xdai": 100, # Gnosis Chain
28
+ "fuse": 122,
29
+ "cronos": 25,
30
+ "kava": 2222,
31
+ "conflux": 1030, # Conflux eSpace
32
+ "core": 1116,
33
+ "astar": 592,
34
+ "filecoin": 314,
35
+ "flare-network": 14,
36
+ "rootstock": 30,
37
+ "elastos": 20,
38
+ "telos": 40,
39
+ "meter": 82,
40
+ "tomochain": 88,
41
+ "kucoin-community-chain": 321,
42
+ "klay-token": 8217,
43
+ "theta": 361,
44
+ "velas": 106,
45
+ "energi": 39797,
46
+ "hedera-hashgraph": 295,
47
+ "xdc-network": 50,
48
+ "pulsechain": 369,
49
+ "ronin": 2020,
50
+ "x-layer": 196,
51
+ "manta-pacific": 169,
52
+ "lisk": 1135,
53
+ "mint": 185,
54
+ "sonic": 146,
55
+ "berachain": 80094,
56
+ "unichain": 130,
57
+ "soneium": 1868,
58
+ "swellchain": 1923,
59
+ "ink": 57073,
60
+ "abstract": 2741,
61
+ "world-chain": 480,
62
+ "zircuit": 48900,
63
+ "bob-network": 60808,
64
+ "morph-l2": 2818,
65
+ "hemi": 43111,
66
+ "funki": 33979,
67
+ "etherlink": 42793,
68
+ "sei-v2": 1329,
69
+ "apechain": 33139,
70
+ "degen": 666666666,
71
+ "iota-evm": 8822,
72
+ "peaq": 3338,
73
+ "flow-evm": 747,
74
+ "gravity-alpha": 1625,
75
+ "story": 1516,
76
+ "botanix": 3636,
77
+ "superseed": 5330,
78
+ "zero-network": 543210,
79
+ "milkomeda-cardano": 2001,
80
+ "pundi-aifx-omnilayer": 530,
81
+ "kardiachain": 24,
82
+ "cube": 1818,
83
+ "graphlinq-chain": 614,
84
+ "plume-network": 98866,
85
+ "nibiru": 6900,
86
+ "goat": 2345,
87
+ "plasma": 9745,
88
+ "0g": 16600,
89
+ "Superposition": 55244,
90
+ "monad": 143,
91
+ "megaeth": 6342,
92
+ "somnia": 50312,
93
+ "sepolia": 11155111,
94
+ # Non-EVM chains — no chain ID
95
+ "cosmos": None,
96
+ "aptos": None,
97
+ "near-protocol": None,
98
+ "tron": None,
99
+ "terra-2": None,
100
+ "massa": None,
101
+ "sora": None,
102
+ "solana": "solana:mainnet",
103
+ "glue": None,
104
+ }
105
+
106
+
107
+ def get_chain_id_by_name(network_name: str) -> int | None:
108
+ try:
109
+ return COINGECKO_CHAIN_IDS[network_name]
110
+ except KeyError:
111
+ return None
112
+
113
+
114
+ def get_network_name_by_chain_id(chain_id: int) -> str | None:
115
+ for name, cid in COINGECKO_CHAIN_IDS.items():
116
+ if cid == chain_id:
117
+ return name
118
+ return None
@@ -0,0 +1,6 @@
1
+ def to_wei(amount_in: float, decimals: int = 18) -> int:
2
+ return int(amount_in * 10**decimals)
3
+
4
+
5
+ def from_wei(amount_in_wei: int, decimals: int = 18) -> float:
6
+ return amount_in_wei / 10**decimals
@@ -0,0 +1,25 @@
1
+ {
2
+ "infura": {
3
+ "1": "https://mainnet.infura.io/v3/",
4
+ "10": "https://optimism-mainnet.infura.io/v3/",
5
+ "56": "https://bsc-mainnet.infura.io/v3/",
6
+ "130": "https://unichain-mainnet.infura.io/v3/",
7
+ "137": "https://polygon-mainnet.infura.io/v3/",
8
+ "143": "https://monad-mainnet.infura.io/v3/",
9
+ "204": "https://opbnb-mainnet.infura.io/v3/",
10
+ "324": "https://zksync-mainnet.infura.io/v3/",
11
+ "1329": "https://sei-mainnet.infura.io/v3/",
12
+ "1923": "https://swellchain-mainnet.infura.io/v3/",
13
+ "5000": "https://mantle-mainnet.infura.io/v3/",
14
+ "6342": "https://megaeth-mainnet.infura.io/v3/",
15
+ "8453": "https://base-mainnet.infura.io/v3/",
16
+ "42161": "https://arbitrum-mainnet.infura.io/v3/",
17
+ "42220": "https://celo-mainnet.infura.io/v3/",
18
+ "43111": "https://hemi-testnet.infura.io/v3/",
19
+ "43114": "https://avalanche-mainnet.infura.io/v3/",
20
+ "59144": "https://linea-mainnet.infura.io/v3/",
21
+ "81457": "https://blast-mainnet.infura.io/v3/",
22
+ "534352": "https://scroll-mainnet.infura.io/v3/",
23
+ "11155111": "https://sepolia.infura.io/v3/"
24
+ }
25
+ }
@@ -0,0 +1,36 @@
1
+ import json
2
+ from pathlib import Path
3
+
4
+ PARENT = Path(__file__).parent
5
+ ENDPOINTS = PARENT / Path("endpoints.json")
6
+
7
+
8
+ class Infura:
9
+ def __init__(self, api_key: str):
10
+ self.api_key = api_key
11
+
12
+ def get_url(self, chain_id: str) -> str:
13
+ return self._build_url(chain_id)
14
+
15
+ def _load_endpoints(self) -> dict:
16
+ with open(ENDPOINTS, "r") as file:
17
+ data = json.load(file)
18
+ return data
19
+
20
+ def add_endpoint(self, chain_id: int | str, endpoint: str) -> None:
21
+ data = self._load_endpoints()
22
+ data["infura"][str(chain_id)] = endpoint
23
+ with open(ENDPOINTS, "w") as file:
24
+ json.dump(data, file, indent=4)
25
+
26
+ def view_endpoints(self) -> list:
27
+ data = self._load_endpoints()
28
+ return data["infura"]
29
+
30
+ def _build_url(self, chain_id: str):
31
+ chain_id = str(chain_id)
32
+ data = self._load_endpoints()
33
+ try:
34
+ return data["infura"][chain_id] + self.api_key
35
+ except KeyError:
36
+ return None
@@ -0,0 +1,90 @@
1
+ from concurrent.futures import ThreadPoolExecutor, as_completed
2
+ from .dex import Dex
3
+ from .periphery.dex_contracts import get_dex_architecture
4
+
5
+
6
+ def _get_swap_fee_bps(dex_name: str, pool_fee_tier: int | None) -> int:
7
+ """
8
+ Return the swap fee in basis points for a given DEX.
9
+ For V3 DEXes the fee is per-pool (stored in pools_v3.fee), so pool_fee_tier is used.
10
+ For V2 DEXes the fee is fixed and comes from dex_architecture.json.
11
+ Returns 0 if unknown.
12
+ """
13
+ arch = get_dex_architecture(dex_name)
14
+ if arch is None:
15
+ return 0
16
+ if pool_fee_tier is not None:
17
+ # V3-style: fee tier is already in basis points (e.g. 500 = 0.05%, 3000 = 0.3%)
18
+ return pool_fee_tier // 100
19
+ return arch.get("swap_fee_bps") or 0
20
+
21
+
22
+ def get_prices(
23
+ dex_mapping: dict[str, Dex], token_0_address: str, token_1_address: str
24
+ ) -> dict[str, dict]:
25
+ """
26
+ Fetch prices and pool addresses for a token pair across all DEXes in parallel.
27
+ Returns {dex_name: {"price": float | None, "pool": str | None, "fee_bps": int}}.
28
+ """
29
+ def _fetch(dex_name: str, dex: Dex) -> tuple[str, dict]:
30
+ pool = dex.pool_address(token_0_address, token_1_address)
31
+ price = dex.get_price(token_0_address, token_1_address) if pool else None
32
+
33
+ # Retrieve cached fee tier for V3 pools (stored as 0 for algebra, actual tier for uniswap_v3)
34
+ fee_tier = None
35
+ if pool and dex.interface:
36
+ from .dex import _sort_tokens
37
+ t0, t1 = _sort_tokens(token_0_address, token_1_address)
38
+ cached = dex.interface.read_pool_v3(dex.name, dex.chain_id, t0, t1)
39
+ if not cached.is_empty():
40
+ fee_tier = int(cached["fee"][0])
41
+
42
+ fee_bps = _get_swap_fee_bps(dex_name, fee_tier)
43
+ return dex_name, {"price": price, "pool": pool, "fee_bps": fee_bps}
44
+
45
+ results = {}
46
+ with ThreadPoolExecutor() as executor:
47
+ futures = {
48
+ executor.submit(_fetch, name, dex): name
49
+ for name, dex in dex_mapping.items()
50
+ }
51
+ for future in as_completed(futures):
52
+ dex_name, data = future.result()
53
+ results[dex_name] = data
54
+
55
+ return results
56
+
57
+
58
+ def arbitrage_route(
59
+ dex_mapping: dict[str, Dex], token_0_address: str, token_1_address: str
60
+ ):
61
+ results = get_prices(dex_mapping, token_0_address, token_1_address)
62
+ available = {k: v for k, v in results.items() if v["price"] is not None}
63
+
64
+ if len(available) < 2:
65
+ return None
66
+
67
+ buy_dex = min(available, key=lambda k: available[k]["price"])
68
+ sell_dex = max(available, key=lambda k: available[k]["price"])
69
+
70
+ buy_price = available[buy_dex]["price"]
71
+ sell_price = available[sell_dex]["price"]
72
+
73
+ spread_abs = sell_price - buy_price
74
+ spread_pct = (spread_abs / buy_price) * 100
75
+
76
+ # Cost to buy on buy_dex then sell on sell_dex (both legs as % of trade)
77
+ total_fee_pct = (available[buy_dex]["fee_bps"] + available[sell_dex]["fee_bps"]) / 100
78
+ net_spread_pct = spread_pct - total_fee_pct
79
+ is_profitable = net_spread_pct > 0
80
+
81
+ return {
82
+ "buy": {"dex": buy_dex, "price": buy_price, "pool": available[buy_dex]["pool"], "fee_bps": available[buy_dex]["fee_bps"]},
83
+ "sell": {"dex": sell_dex, "price": sell_price, "pool": available[sell_dex]["pool"], "fee_bps": available[sell_dex]["fee_bps"]},
84
+ "spread_abs": round(spread_abs, 6),
85
+ "spread_pct": round(spread_pct, 4),
86
+ "total_fee_pct": round(total_fee_pct, 4),
87
+ "net_spread_pct": round(net_spread_pct, 4),
88
+ "profitable": is_profitable,
89
+ "all_prices": results,
90
+ }