cherry-shared2 0.1.26__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.
- cherry_shared/InfoService.py +369 -0
- cherry_shared/__init__.py +5 -0
- cherry_shared/blockchains.py +265 -0
- cherry_shared/bot_strings.py +529 -0
- cherry_shared/constants.py +36 -0
- cherry_shared/emojis.py +63 -0
- cherry_shared/functions.py +511 -0
- cherry_shared/launchpads.py +193 -0
- cherry_shared/types/__init__.py +6 -0
- cherry_shared/types/blockchain.py +51 -0
- cherry_shared/types/dexscreener.py +376 -0
- cherry_shared/types/launchpad.py +72 -0
- cherry_shared/types/leaderboardEntry.py +62 -0
- cherry_shared/types/raid_info.py +92 -0
- cherry_shared/types/user_wallet.py +9 -0
- cherry_shared2-0.1.26.dist-info/METADATA +91 -0
- cherry_shared2-0.1.26.dist-info/RECORD +19 -0
- cherry_shared2-0.1.26.dist-info/WHEEL +5 -0
- cherry_shared2-0.1.26.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from typing import Any, Dict, List
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SupportedFeatures:
|
|
5
|
+
def __init__(self, custom_token: bool, wallet: bool, payment: bool):
|
|
6
|
+
self.custom_token = custom_token
|
|
7
|
+
self.wallet = wallet
|
|
8
|
+
self.payment = payment
|
|
9
|
+
|
|
10
|
+
def __repr__(self):
|
|
11
|
+
return (
|
|
12
|
+
f"SupportedFeatures(custom_token={self.custom_token}, wallet={self.wallet}, "
|
|
13
|
+
f"trend={self.payment})"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Blockchain:
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
id: str,
|
|
21
|
+
symbol: str,
|
|
22
|
+
name: str,
|
|
23
|
+
native_token: str,
|
|
24
|
+
explorer: str,
|
|
25
|
+
evm: bool,
|
|
26
|
+
trending_prices: Dict[str, Dict[int, float]],
|
|
27
|
+
quote_tokens: List[str],
|
|
28
|
+
boost_price: Dict[int, float],
|
|
29
|
+
supported_features: SupportedFeatures,
|
|
30
|
+
min_bounty: float = 0.0,
|
|
31
|
+
extras: Dict[str, Any] = {}
|
|
32
|
+
):
|
|
33
|
+
self.id = id
|
|
34
|
+
self.symbol = symbol
|
|
35
|
+
self.name = name
|
|
36
|
+
self.native_token = native_token
|
|
37
|
+
self.explorer = explorer
|
|
38
|
+
self.evm = evm
|
|
39
|
+
self.min_bounty = min_bounty
|
|
40
|
+
self.trending_prices = trending_prices
|
|
41
|
+
self.quote_tokens = quote_tokens
|
|
42
|
+
self.boost_price = boost_price
|
|
43
|
+
self.supported_features = supported_features
|
|
44
|
+
self.extras = extras.copy()
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def chain_type(self):
|
|
48
|
+
return "evm" if self.evm else self.id
|
|
49
|
+
|
|
50
|
+
def __repr__(self):
|
|
51
|
+
return f"{self.name}"
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
import aiohttp
|
|
3
|
+
from typing import Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class API:
|
|
7
|
+
DEXSC = "DexScreener"
|
|
8
|
+
GECKO = "GeckoTerminal"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Token:
|
|
12
|
+
def __init__(self, address: str, name: str, symbol: str) -> None:
|
|
13
|
+
self.address = address
|
|
14
|
+
self.name = name
|
|
15
|
+
self.symbol = symbol
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
def from_dict(cls, token_dict: Dict[str, str]) -> "Token":
|
|
19
|
+
return cls(token_dict["address"], token_dict["name"], token_dict["symbol"])
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Transaction:
|
|
23
|
+
def __init__(self, buys: int, sells: int) -> None:
|
|
24
|
+
self.buys = buys
|
|
25
|
+
self.sells = sells
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def from_dict(cls, txn_dict: Dict[str, int]) -> "Transaction":
|
|
29
|
+
return cls(txn_dict["buys"], txn_dict["sells"])
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Volume:
|
|
33
|
+
def __init__(self, h1: int, h24: int) -> None:
|
|
34
|
+
self.h1 = h1
|
|
35
|
+
self.h24 = h24
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def from_dict(cls, volume_dict: Dict[str, int]) -> "Volume":
|
|
39
|
+
return cls(volume_dict["h1"], volume_dict["h24"])
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class PriceChange:
|
|
43
|
+
def __init__(self, h1: int, h24: int) -> None:
|
|
44
|
+
self.h1 = h1
|
|
45
|
+
self.h24 = h24
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def from_dict(cls, price_change_dict: Dict[str, int]) -> "PriceChange":
|
|
49
|
+
return cls(
|
|
50
|
+
price_change_dict["h1"],
|
|
51
|
+
price_change_dict["h24"],
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class Pair:
|
|
56
|
+
def __init__(
|
|
57
|
+
self,
|
|
58
|
+
api: str,
|
|
59
|
+
chainId: str,
|
|
60
|
+
dexId: str,
|
|
61
|
+
url: str,
|
|
62
|
+
pairAddress: str,
|
|
63
|
+
baseToken: Token,
|
|
64
|
+
quoteToken: Token,
|
|
65
|
+
priceNative: str,
|
|
66
|
+
txns: Dict[str, Transaction],
|
|
67
|
+
volume: Volume,
|
|
68
|
+
priceChange: PriceChange,
|
|
69
|
+
labels: List[str] = [],
|
|
70
|
+
priceUsd: Optional[str] = None,
|
|
71
|
+
liquidity: Optional[float] = None,
|
|
72
|
+
fdv: Optional[int] = None,
|
|
73
|
+
telegram: Optional[str] = None,
|
|
74
|
+
twitter: Optional[str] = None,
|
|
75
|
+
website: Optional[str] = None,
|
|
76
|
+
) -> None:
|
|
77
|
+
self.api = api
|
|
78
|
+
self.chainId = chainId
|
|
79
|
+
self.dexId = dexId
|
|
80
|
+
self.url = url
|
|
81
|
+
self.pairAddress = pairAddress
|
|
82
|
+
self.baseToken = baseToken
|
|
83
|
+
self.quoteToken = quoteToken
|
|
84
|
+
# self.priceNative = priceNative
|
|
85
|
+
self.priceNative = None
|
|
86
|
+
self.priceUsd = priceUsd
|
|
87
|
+
self.txns = None
|
|
88
|
+
self.volume = volume
|
|
89
|
+
self.priceChange = priceChange
|
|
90
|
+
self.labels = labels
|
|
91
|
+
self.liquidity = liquidity
|
|
92
|
+
self.fdv = fdv
|
|
93
|
+
self.telegram = telegram
|
|
94
|
+
self.twitter = twitter
|
|
95
|
+
self.website = website
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def from_dict(cls, pair_dict: dict) -> "Pair":
|
|
99
|
+
base_token = Token(
|
|
100
|
+
pair_dict["baseToken"]["address"],
|
|
101
|
+
pair_dict["baseToken"]["name"],
|
|
102
|
+
pair_dict["baseToken"]["symbol"],
|
|
103
|
+
)
|
|
104
|
+
quote_token = Token(
|
|
105
|
+
pair_dict["quoteToken"]["address"],
|
|
106
|
+
pair_dict["quoteToken"]["name"],
|
|
107
|
+
pair_dict["quoteToken"]["symbol"],
|
|
108
|
+
)
|
|
109
|
+
# txns = (
|
|
110
|
+
# {
|
|
111
|
+
# key: Transaction(value["buys"], value["sells"])
|
|
112
|
+
# for key, value in pair_dict["txns"].items()
|
|
113
|
+
# }
|
|
114
|
+
# if pair_dict["txns"]
|
|
115
|
+
# else None
|
|
116
|
+
# )
|
|
117
|
+
txns = None
|
|
118
|
+
# volume = (
|
|
119
|
+
# Volume(pair_dict["volume"]["h1"], pair_dict["volume"]["h24"])
|
|
120
|
+
# if pair_dict["volume"]
|
|
121
|
+
# else None
|
|
122
|
+
# )
|
|
123
|
+
volume = None
|
|
124
|
+
# price_change = (
|
|
125
|
+
# PriceChange(pair_dict["priceChange"]["h1"], pair_dict["priceChange"]["h24"])
|
|
126
|
+
# if pair_dict["priceChange"]
|
|
127
|
+
# else None
|
|
128
|
+
# )
|
|
129
|
+
price_change = None
|
|
130
|
+
liquidity = pair_dict.get("liquidity", 0)
|
|
131
|
+
|
|
132
|
+
return Pair(
|
|
133
|
+
pair_dict["api"],
|
|
134
|
+
pair_dict["chainId"],
|
|
135
|
+
pair_dict["dexId"],
|
|
136
|
+
pair_dict["url"],
|
|
137
|
+
pair_dict["pairAddress"],
|
|
138
|
+
base_token,
|
|
139
|
+
quote_token,
|
|
140
|
+
# pair_dict["priceNative"],
|
|
141
|
+
0,
|
|
142
|
+
txns,
|
|
143
|
+
volume,
|
|
144
|
+
price_change,
|
|
145
|
+
pair_dict["labels"],
|
|
146
|
+
pair_dict["priceUsd"],
|
|
147
|
+
liquidity,
|
|
148
|
+
pair_dict["fdv"],
|
|
149
|
+
pair_dict["telegram"],
|
|
150
|
+
pair_dict["twitter"],
|
|
151
|
+
pair_dict["website"],
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
@staticmethod
|
|
155
|
+
def from_dexsc_dict(pair_dict: Dict):
|
|
156
|
+
try:
|
|
157
|
+
base_token = Token.from_dict(pair_dict["baseToken"])
|
|
158
|
+
quote_token = Token.from_dict(pair_dict["quoteToken"])
|
|
159
|
+
# txns = (
|
|
160
|
+
# {
|
|
161
|
+
# key: Transaction.from_dict(value)
|
|
162
|
+
# for key, value in pair_dict["txns"].items()
|
|
163
|
+
# if key not in ["m5", "h6"]
|
|
164
|
+
# }
|
|
165
|
+
# if pair_dict["txns"]
|
|
166
|
+
# else None
|
|
167
|
+
# )
|
|
168
|
+
txns = None
|
|
169
|
+
# volume = (
|
|
170
|
+
# Volume.from_dict(pair_dict["volume"]) if pair_dict["volume"] else None
|
|
171
|
+
# )
|
|
172
|
+
volume = None
|
|
173
|
+
# price_change = (
|
|
174
|
+
# PriceChange.from_dict(pair_dict["priceChange"])
|
|
175
|
+
# if pair_dict["priceChange"]
|
|
176
|
+
# else None
|
|
177
|
+
# )
|
|
178
|
+
price_change = None
|
|
179
|
+
liquidity_info = pair_dict.get("liquidity", {})
|
|
180
|
+
liquidity = liquidity_info.get("usd", 0) if liquidity_info else 0
|
|
181
|
+
|
|
182
|
+
# Handle fdv more safely, ensuring it is converted to an int
|
|
183
|
+
fdv = pair_dict.get("fdv")
|
|
184
|
+
fdv = int(fdv) if fdv is not None else 0
|
|
185
|
+
|
|
186
|
+
return Pair(
|
|
187
|
+
API.DEXSC,
|
|
188
|
+
pair_dict.get("chainId"),
|
|
189
|
+
pair_dict.get("dexId"),
|
|
190
|
+
pair_dict.get("url"),
|
|
191
|
+
pair_dict.get("pairAddress"),
|
|
192
|
+
base_token,
|
|
193
|
+
quote_token,
|
|
194
|
+
pair_dict["priceNative"],
|
|
195
|
+
txns,
|
|
196
|
+
volume,
|
|
197
|
+
price_change,
|
|
198
|
+
pair_dict.get("labels") or [],
|
|
199
|
+
pair_dict.get("priceUsd"),
|
|
200
|
+
liquidity,
|
|
201
|
+
fdv,
|
|
202
|
+
pair_dict.get("telegram"),
|
|
203
|
+
pair_dict.get("twitter"),
|
|
204
|
+
pair_dict.get("website"),
|
|
205
|
+
)
|
|
206
|
+
except Exception as e:
|
|
207
|
+
print(f"from_dexsc_dict: {e}")
|
|
208
|
+
|
|
209
|
+
@staticmethod
|
|
210
|
+
def from_gecko_dict(data: dict):
|
|
211
|
+
relationships = data["relationships"]
|
|
212
|
+
base_token_data = relationships["base_token"]["data"]
|
|
213
|
+
quote_token_data = relationships["quote_token"]["data"]
|
|
214
|
+
dex = relationships["dex"]["data"]["id"].split("_")
|
|
215
|
+
dexId = dex[0]
|
|
216
|
+
labels = dex[1] if len(dex) > 1 else []
|
|
217
|
+
attrs = data["attributes"]
|
|
218
|
+
symbols = attrs["name"].split(" / ")
|
|
219
|
+
liquidity = float(attrs["reserve_in_usd"])
|
|
220
|
+
base_token_address = base_token_data["id"].split("_")[1]
|
|
221
|
+
base_token = Token(
|
|
222
|
+
base_token_address,
|
|
223
|
+
symbols[0],
|
|
224
|
+
symbols[0],
|
|
225
|
+
)
|
|
226
|
+
quote_token = Token(
|
|
227
|
+
quote_token_data["id"].split("_")[1],
|
|
228
|
+
symbols[1],
|
|
229
|
+
symbols[1],
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
# txns_data = attrs["transactions"]
|
|
233
|
+
# txns = {
|
|
234
|
+
# "h1": Transaction(
|
|
235
|
+
# int(txns_data["h1"]["buys"]), int(txns_data["h1"]["sells"])
|
|
236
|
+
# ),
|
|
237
|
+
# "h24": Transaction(
|
|
238
|
+
# int(txns_data["h24"]["buys"]), int(txns_data["h24"]["sells"])
|
|
239
|
+
# ),
|
|
240
|
+
# }
|
|
241
|
+
txns = None
|
|
242
|
+
pairAddress = attrs["address"]
|
|
243
|
+
|
|
244
|
+
# volume_data = attrs["volume_usd"]
|
|
245
|
+
# volume = Volume(float(volume_data["h1"]), float(volume_data["h24"]))
|
|
246
|
+
volume = None
|
|
247
|
+
|
|
248
|
+
price_change_data = attrs["price_change_percentage"]
|
|
249
|
+
price_change = PriceChange(
|
|
250
|
+
float(price_change_data["h1"]), float(price_change_data["h24"])
|
|
251
|
+
)
|
|
252
|
+
chainId = data["id"].split("_")[0]
|
|
253
|
+
url = f"https://www.geckoterminal.com/{chainId}/pools/{pairAddress}"
|
|
254
|
+
return Pair(
|
|
255
|
+
API.GECKO,
|
|
256
|
+
chainId,
|
|
257
|
+
dexId,
|
|
258
|
+
url,
|
|
259
|
+
pairAddress,
|
|
260
|
+
base_token,
|
|
261
|
+
quote_token,
|
|
262
|
+
float(attrs["base_token_price_quote_token"]),
|
|
263
|
+
txns,
|
|
264
|
+
volume,
|
|
265
|
+
price_change,
|
|
266
|
+
labels,
|
|
267
|
+
float(attrs.get("base_token_price_usd")),
|
|
268
|
+
liquidity,
|
|
269
|
+
float(attrs.get("fdv_usd")),
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
def to_dict(self) -> Dict:
|
|
273
|
+
pair_dict = {
|
|
274
|
+
"api": self.api,
|
|
275
|
+
"chainId": self.chainId,
|
|
276
|
+
"dexId": self.dexId,
|
|
277
|
+
"url": self.url,
|
|
278
|
+
"pairAddress": self.pairAddress,
|
|
279
|
+
"baseToken": {
|
|
280
|
+
"address": self.baseToken.address,
|
|
281
|
+
"name": self.baseToken.name,
|
|
282
|
+
"symbol": self.baseToken.symbol,
|
|
283
|
+
},
|
|
284
|
+
"quoteToken": {
|
|
285
|
+
"address": self.quoteToken.address,
|
|
286
|
+
"name": self.quoteToken.name,
|
|
287
|
+
"symbol": self.quoteToken.symbol,
|
|
288
|
+
},
|
|
289
|
+
# "priceNative": self.priceNative,
|
|
290
|
+
# "txns": (
|
|
291
|
+
# {
|
|
292
|
+
# key: {"buys": value.buys, "sells": value.sells}
|
|
293
|
+
# for key, value in self.txns.items()
|
|
294
|
+
# }
|
|
295
|
+
# if self.txns
|
|
296
|
+
# else None
|
|
297
|
+
# ),
|
|
298
|
+
# "volume": {
|
|
299
|
+
# "h1": self.volume.h1,
|
|
300
|
+
# "h24": self.volume.h24,
|
|
301
|
+
# },
|
|
302
|
+
# "priceChange": {
|
|
303
|
+
# "h1": self.priceChange.h1,
|
|
304
|
+
# "h24": self.priceChange.h24,
|
|
305
|
+
# },
|
|
306
|
+
"labels": self.labels,
|
|
307
|
+
"priceUsd": self.priceUsd,
|
|
308
|
+
"fdv": self.fdv,
|
|
309
|
+
"liquidity": self.liquidity,
|
|
310
|
+
"telegram": self.telegram,
|
|
311
|
+
"twitter": self.twitter,
|
|
312
|
+
"website": self.website,
|
|
313
|
+
}
|
|
314
|
+
return pair_dict
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class DEXScreener:
|
|
318
|
+
async def get_pair_by_token(
|
|
319
|
+
token_address: str, chain_id: str, dex_id: str = None, ver: str = None
|
|
320
|
+
):
|
|
321
|
+
url = f"https://api.dexscreener.com/latest/dex/tokens/{token_address}"
|
|
322
|
+
try:
|
|
323
|
+
async with aiohttp.ClientSession() as session:
|
|
324
|
+
async with session.get(url) as response:
|
|
325
|
+
if response.status != 200:
|
|
326
|
+
raise Exception(response.status)
|
|
327
|
+
|
|
328
|
+
data = await response.json()
|
|
329
|
+
if not data["pairs"]:
|
|
330
|
+
return None
|
|
331
|
+
for pair in data["pairs"]:
|
|
332
|
+
if (
|
|
333
|
+
pair["chainId"] == chain_id
|
|
334
|
+
and (dex_id is None or pair.get("dexId") == dex_id)
|
|
335
|
+
and (ver is None or ver in pair.get("labels", []))
|
|
336
|
+
):
|
|
337
|
+
return Pair.from_dexsc_dict(pair)
|
|
338
|
+
except Exception as err:
|
|
339
|
+
print(f"failed to get pair by token address from dexscreener: {err}")
|
|
340
|
+
|
|
341
|
+
async def get_pair_by_pairAddress(pair_address: str, chain_id: str):
|
|
342
|
+
url = f"https://api.dexscreener.com/latest/dex/pairs/{chain_id}/{pair_address}"
|
|
343
|
+
try:
|
|
344
|
+
async with aiohttp.ClientSession() as session:
|
|
345
|
+
async with session.get(url) as response:
|
|
346
|
+
if response.status != 200:
|
|
347
|
+
raise Exception(response.status)
|
|
348
|
+
data = await response.json()
|
|
349
|
+
if not data["pairs"]:
|
|
350
|
+
return None
|
|
351
|
+
for pair in data["pairs"]:
|
|
352
|
+
if pair["pairAddress"].lower() == pair_address.lower():
|
|
353
|
+
return Pair.from_dexsc_dict(pair)
|
|
354
|
+
|
|
355
|
+
except Exception as err:
|
|
356
|
+
print(f"failed to get pair address from dexscreener: {err}")
|
|
357
|
+
|
|
358
|
+
async def search_address(token_address: str):
|
|
359
|
+
url = f"https://api.dexscreener.com/latest/dex/search/?q={token_address}"
|
|
360
|
+
try:
|
|
361
|
+
async with aiohttp.ClientSession() as session:
|
|
362
|
+
async with session.get(url) as response:
|
|
363
|
+
if response.status != 200:
|
|
364
|
+
raise Exception(response.status)
|
|
365
|
+
data = await response.json()
|
|
366
|
+
if not data["pairs"]:
|
|
367
|
+
return None
|
|
368
|
+
pairs: List[Pair] = []
|
|
369
|
+
for pair in data["pairs"]:
|
|
370
|
+
try:
|
|
371
|
+
pairs.append(Pair.from_dexsc_dict(pair))
|
|
372
|
+
except:
|
|
373
|
+
pass
|
|
374
|
+
return pairs
|
|
375
|
+
except Exception as err:
|
|
376
|
+
print(f"failed to search address from dexscreener: {err}")
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
class LaunchpadToken:
|
|
2
|
+
def __init__(
|
|
3
|
+
self,
|
|
4
|
+
token_address: str,
|
|
5
|
+
decimals: str,
|
|
6
|
+
total_supply: str,
|
|
7
|
+
token_name: str,
|
|
8
|
+
token_symbol: str,
|
|
9
|
+
chain: str,
|
|
10
|
+
pair_address: str,
|
|
11
|
+
telegram: str,
|
|
12
|
+
twitter: str,
|
|
13
|
+
website: str,
|
|
14
|
+
):
|
|
15
|
+
self.token_address = token_address
|
|
16
|
+
self.decimals = int(decimals)
|
|
17
|
+
self.total_supply = int(float(total_supply))
|
|
18
|
+
self.token_name = token_name
|
|
19
|
+
self.token_symbol = token_symbol
|
|
20
|
+
self.chain = chain
|
|
21
|
+
self.pair_address = pair_address
|
|
22
|
+
self.telegram = telegram
|
|
23
|
+
self.twitter = twitter
|
|
24
|
+
self.website = website
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def create_token_info(data_dict):
|
|
28
|
+
# Defensive copy to avoid mutating input
|
|
29
|
+
data = dict(data_dict) if data_dict else {}
|
|
30
|
+
|
|
31
|
+
# Handle totalSupply safely
|
|
32
|
+
total_supply = data.get("totalSupply", 0)
|
|
33
|
+
try:
|
|
34
|
+
if str(total_supply).lower() == "nan":
|
|
35
|
+
total_supply = 0
|
|
36
|
+
total_supply = int(float(total_supply))
|
|
37
|
+
except (ValueError, TypeError):
|
|
38
|
+
total_supply = 0
|
|
39
|
+
|
|
40
|
+
# Handle decimals safely
|
|
41
|
+
decimals = data.get("decimals", 0)
|
|
42
|
+
try:
|
|
43
|
+
decimals = int(decimals)
|
|
44
|
+
except (ValueError, TypeError):
|
|
45
|
+
decimals = 0
|
|
46
|
+
|
|
47
|
+
return LaunchpadToken(
|
|
48
|
+
token_address=data.get("tokenAddress", ""),
|
|
49
|
+
decimals=decimals,
|
|
50
|
+
total_supply=total_supply,
|
|
51
|
+
token_name=data.get("name", ""),
|
|
52
|
+
token_symbol=data.get("symbol", ""),
|
|
53
|
+
chain=data.get("chain", ""),
|
|
54
|
+
pair_address=data.get("pairAddress", ""),
|
|
55
|
+
telegram=data.get("telegram", ""),
|
|
56
|
+
twitter=data.get("twitter", ""),
|
|
57
|
+
website=data.get("website", ""),
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def to_dict(self):
|
|
61
|
+
return {
|
|
62
|
+
"tokenAddress": self.token_address,
|
|
63
|
+
"decimals": self.decimals,
|
|
64
|
+
"totalSupply": self.total_supply,
|
|
65
|
+
"name": self.token_name,
|
|
66
|
+
"symbol": self.token_symbol,
|
|
67
|
+
"chain": self.chain,
|
|
68
|
+
"pairAddress": self.pair_address,
|
|
69
|
+
"telegram": self.telegram,
|
|
70
|
+
"twitter": self.twitter,
|
|
71
|
+
"website": self.website,
|
|
72
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
class LeaderboardEntry:
|
|
2
|
+
def __init__(
|
|
3
|
+
self,
|
|
4
|
+
chat_id: int,
|
|
5
|
+
chat_name: str = None,
|
|
6
|
+
chat_link: str = None,
|
|
7
|
+
token_link: str = None,
|
|
8
|
+
boosted_score: int = 0,
|
|
9
|
+
raid_score: int = 0,
|
|
10
|
+
):
|
|
11
|
+
self.chat_id = chat_id
|
|
12
|
+
self.chat_name = chat_name
|
|
13
|
+
self.chat_link = chat_link
|
|
14
|
+
self.token_link = token_link
|
|
15
|
+
self.boosted_score = boosted_score
|
|
16
|
+
self.raid_score = raid_score
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def boosted(self):
|
|
20
|
+
return self.boosted_score > 0
|
|
21
|
+
|
|
22
|
+
@boosted.setter
|
|
23
|
+
def boosted(self, value):
|
|
24
|
+
pass # Prevent setting boosted directly
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def score(self):
|
|
28
|
+
return int((self.boosted_score or 0) + (self.raid_score or 0))
|
|
29
|
+
|
|
30
|
+
@score.setter
|
|
31
|
+
def score(self, value):
|
|
32
|
+
pass # Prevent setting score directly
|
|
33
|
+
|
|
34
|
+
def to_dict(self):
|
|
35
|
+
return {
|
|
36
|
+
"chat_id": str(self.chat_id),
|
|
37
|
+
"chat_name": self.chat_name,
|
|
38
|
+
"chat_link": self.chat_link,
|
|
39
|
+
"token_link": self.token_link,
|
|
40
|
+
"boosted": int(self.boosted),
|
|
41
|
+
"score": str(self.score),
|
|
42
|
+
"boosted_score": (str(int(self.boosted_score or 0))),
|
|
43
|
+
"raid_score": (str(int(self.raid_score or 0))),
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
def __repr__(self):
|
|
47
|
+
return (
|
|
48
|
+
f"LeaderboardEntry(chat_id={self.chat_id}, chat_name={self.chat_name}, "
|
|
49
|
+
f"chat_link={self.chat_link}, token_link={self.token_link}, score={self.score}), boosted={self.boosted}, "
|
|
50
|
+
f"boosted_score={self.boosted_score}, raid_score={self.raid_score})"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def from_dict(cls, data: dict):
|
|
55
|
+
return cls(
|
|
56
|
+
chat_id=int(data.get("chat_id")),
|
|
57
|
+
chat_name=data.get("chat_name"),
|
|
58
|
+
chat_link=data.get("chat_link"),
|
|
59
|
+
token_link=data.get("token_link"),
|
|
60
|
+
boosted_score=int(data.get("boosted_score", 0)),
|
|
61
|
+
raid_score=int(data.get("raid_score", 0)),
|
|
62
|
+
)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
class PostInfo:
|
|
2
|
+
def __init__(
|
|
3
|
+
self, link: str, likes: int, comments: int, shares: int = 0, bookmarks: int = 0
|
|
4
|
+
):
|
|
5
|
+
self.link = link
|
|
6
|
+
self.likes = likes
|
|
7
|
+
self.shares = shares
|
|
8
|
+
self.comments = comments
|
|
9
|
+
self.bookmarks = bookmarks
|
|
10
|
+
|
|
11
|
+
def __str__(self):
|
|
12
|
+
return (
|
|
13
|
+
f"{self.link},{self.likes},{self.comments},{self.shares},{self.bookmarks}"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
def __repr__(self):
|
|
17
|
+
return self.__str__()
|
|
18
|
+
|
|
19
|
+
def log(self):
|
|
20
|
+
return f"Post info likes={self.likes}, comments={self.comments}, shares={self.shares}, bookmarks={self.bookmarks}"
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def from_string(cls, string: str):
|
|
24
|
+
parts = string.split(",")
|
|
25
|
+
link = parts[0] if parts[0] != "None" else None
|
|
26
|
+
likes, shares, comments, bookmarks = map(int, parts[1:])
|
|
27
|
+
return cls(link, likes, shares, comments, bookmarks)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class RaidInfo:
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
post: PostInfo,
|
|
34
|
+
started_by: int,
|
|
35
|
+
bounty: float,
|
|
36
|
+
message_id: int,
|
|
37
|
+
lock: bool = False,
|
|
38
|
+
platform: str = None,
|
|
39
|
+
bounty_type: int = None,
|
|
40
|
+
):
|
|
41
|
+
self.post = post
|
|
42
|
+
self.started_by = started_by
|
|
43
|
+
self.bounty = bounty
|
|
44
|
+
self.message_id = message_id
|
|
45
|
+
self.lock = lock
|
|
46
|
+
self.platform = platform
|
|
47
|
+
self.bounty_type = bounty_type
|
|
48
|
+
|
|
49
|
+
def make(
|
|
50
|
+
started_by: int,
|
|
51
|
+
message_id: int,
|
|
52
|
+
link: str = None,
|
|
53
|
+
likes: int = 0,
|
|
54
|
+
shares: int = 0,
|
|
55
|
+
comments: int = 0,
|
|
56
|
+
bookmarks: int = 0,
|
|
57
|
+
bounty: float = 0,
|
|
58
|
+
lock: bool = False,
|
|
59
|
+
platform: str = None,
|
|
60
|
+
bounty_type: int = None,
|
|
61
|
+
):
|
|
62
|
+
post = PostInfo(link, likes, comments, shares, bookmarks)
|
|
63
|
+
return RaidInfo(
|
|
64
|
+
post, started_by, bounty, message_id, lock, platform, bounty_type
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def __str__(self):
|
|
68
|
+
return f"{str(self.post)}|{self.started_by},{self.bounty},{self.message_id},{int(self.lock)},{self.platform},{self.bounty_type}"
|
|
69
|
+
|
|
70
|
+
def __repr__(self):
|
|
71
|
+
return self.__str__()
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def from_string(cls, string: str):
|
|
75
|
+
|
|
76
|
+
post_string, raid_string = string.split("|")
|
|
77
|
+
parts = raid_string.split(",")
|
|
78
|
+
started_by = int(parts[0])
|
|
79
|
+
bounty = float(parts[1])
|
|
80
|
+
message_id = int(parts[2])
|
|
81
|
+
lock = bool(int(parts[3]))
|
|
82
|
+
platform = parts[4] if parts[4] != "None" else None
|
|
83
|
+
bounty_type = int(parts[5]) if parts[5] != "None" else None
|
|
84
|
+
post = PostInfo.from_string(post_string)
|
|
85
|
+
return cls(post, started_by, bounty, message_id, lock, platform, bounty_type)
|
|
86
|
+
|
|
87
|
+
def log(self) -> str:
|
|
88
|
+
return (
|
|
89
|
+
f"Raid info: started_by={self.started_by}, bounty={self.bounty}, "
|
|
90
|
+
f"message_id={self.message_id}, bounty_type={self.bounty_type}, "
|
|
91
|
+
f"lock={self.lock}, platform={self.platform}, post={self.post.log()}"
|
|
92
|
+
)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
class UserWallet:
|
|
2
|
+
def __init__(self, user_id: int, address: str, pk: str, chain: str):
|
|
3
|
+
self.user_id = user_id
|
|
4
|
+
self.address = address
|
|
5
|
+
self.pk = pk
|
|
6
|
+
self.chain = chain
|
|
7
|
+
|
|
8
|
+
def __repr__(self):
|
|
9
|
+
return f"Wallet(user_id={self.user_id}, address={self.address}, pk={self.pk}, chain={self.chain})"
|