cherry-shared2 0.1.26__tar.gz
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_shared2-0.1.26/PKG-INFO +91 -0
- cherry_shared2-0.1.26/README.md +68 -0
- cherry_shared2-0.1.26/cherry_shared/InfoService.py +369 -0
- cherry_shared2-0.1.26/cherry_shared/__init__.py +5 -0
- cherry_shared2-0.1.26/cherry_shared/blockchains.py +265 -0
- cherry_shared2-0.1.26/cherry_shared/bot_strings.py +529 -0
- cherry_shared2-0.1.26/cherry_shared/constants.py +36 -0
- cherry_shared2-0.1.26/cherry_shared/emojis.py +63 -0
- cherry_shared2-0.1.26/cherry_shared/functions.py +511 -0
- cherry_shared2-0.1.26/cherry_shared/launchpads.py +193 -0
- cherry_shared2-0.1.26/cherry_shared/types/__init__.py +6 -0
- cherry_shared2-0.1.26/cherry_shared/types/blockchain.py +51 -0
- cherry_shared2-0.1.26/cherry_shared/types/dexscreener.py +376 -0
- cherry_shared2-0.1.26/cherry_shared/types/launchpad.py +72 -0
- cherry_shared2-0.1.26/cherry_shared/types/leaderboardEntry.py +62 -0
- cherry_shared2-0.1.26/cherry_shared/types/raid_info.py +92 -0
- cherry_shared2-0.1.26/cherry_shared/types/user_wallet.py +9 -0
- cherry_shared2-0.1.26/cherry_shared2.egg-info/PKG-INFO +91 -0
- cherry_shared2-0.1.26/cherry_shared2.egg-info/SOURCES.txt +22 -0
- cherry_shared2-0.1.26/cherry_shared2.egg-info/dependency_links.txt +1 -0
- cherry_shared2-0.1.26/cherry_shared2.egg-info/requires.txt +3 -0
- cherry_shared2-0.1.26/cherry_shared2.egg-info/top_level.txt +1 -0
- cherry_shared2-0.1.26/setup.cfg +4 -0
- cherry_shared2-0.1.26/setup.py +33 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cherry_shared2
|
|
3
|
+
Version: 0.1.26
|
|
4
|
+
Summary: Cherry Bot shared utilities
|
|
5
|
+
Author: headria
|
|
6
|
+
Classifier: Development Status :: 4 - Beta
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: web3
|
|
14
|
+
Requires-Dist: pyrogram
|
|
15
|
+
Requires-Dist: aiohttp
|
|
16
|
+
Dynamic: author
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: requires-dist
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
Dynamic: summary
|
|
23
|
+
|
|
24
|
+
# Cherry Shared
|
|
25
|
+
|
|
26
|
+
Cherry Bot shared utilities package.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
This is a private package. Install it directly from the Git repository:
|
|
31
|
+
|
|
32
|
+
### Using HTTPS (requires authentication)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install git+https://github.com/YOUR_USERNAME/cherry_shared.git@main#egg=cherry_shared
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
For private repositories, you'll need to authenticate. You can use a personal access token:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install git+https://YOUR_TOKEN@github.com/YOUR_USERNAME/cherry_shared.git@main#egg=cherry_shared
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Using SSH (recommended for private repos)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install git+ssh://git@github.com/YOUR_USERNAME/cherry_shared.git@main#egg=cherry_shared
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Installing a specific version/tag
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install git+ssh://git@github.com/YOUR_USERNAME/cherry_shared.git@v0.1.1#egg=cherry_shared
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Installing from a requirements.txt
|
|
57
|
+
|
|
58
|
+
Add this line to your `requirements.txt`:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
git+ssh://git@github.com/YOUR_USERNAME/cherry_shared.git@main#egg=cherry_shared
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then install with:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install -r requirements.txt
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Development Installation
|
|
71
|
+
|
|
72
|
+
For development, install in editable mode:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install -e git+ssh://git@github.com/YOUR_USERNAME/cherry_shared.git@main#egg=cherry_shared
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Or clone the repository and install locally:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
git clone git@github.com:YOUR_USERNAME/cherry_shared.git
|
|
82
|
+
cd cherry_shared
|
|
83
|
+
pip install -e .
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Usage
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from cherry_shared import Blockchains, BotStrings, Constants, Emojis, LaunchPads
|
|
90
|
+
```
|
|
91
|
+
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Cherry Shared
|
|
2
|
+
|
|
3
|
+
Cherry Bot shared utilities package.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
This is a private package. Install it directly from the Git repository:
|
|
8
|
+
|
|
9
|
+
### Using HTTPS (requires authentication)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install git+https://github.com/YOUR_USERNAME/cherry_shared.git@main#egg=cherry_shared
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
For private repositories, you'll need to authenticate. You can use a personal access token:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install git+https://YOUR_TOKEN@github.com/YOUR_USERNAME/cherry_shared.git@main#egg=cherry_shared
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Using SSH (recommended for private repos)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install git+ssh://git@github.com/YOUR_USERNAME/cherry_shared.git@main#egg=cherry_shared
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Installing a specific version/tag
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install git+ssh://git@github.com/YOUR_USERNAME/cherry_shared.git@v0.1.1#egg=cherry_shared
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Installing from a requirements.txt
|
|
34
|
+
|
|
35
|
+
Add this line to your `requirements.txt`:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
git+ssh://git@github.com/YOUR_USERNAME/cherry_shared.git@main#egg=cherry_shared
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then install with:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install -r requirements.txt
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Development Installation
|
|
48
|
+
|
|
49
|
+
For development, install in editable mode:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install -e git+ssh://git@github.com/YOUR_USERNAME/cherry_shared.git@main#egg=cherry_shared
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or clone the repository and install locally:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
git clone git@github.com:YOUR_USERNAME/cherry_shared.git
|
|
59
|
+
cd cherry_shared
|
|
60
|
+
pip install -e .
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from cherry_shared import Blockchains, BotStrings, Constants, Emojis, LaunchPads
|
|
67
|
+
```
|
|
68
|
+
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Any, Dict, Literal, Optional
|
|
4
|
+
import aiohttp
|
|
5
|
+
from cherry_shared.launchpads import LaunchPad
|
|
6
|
+
from cherry_shared.types.dexscreener import Pair
|
|
7
|
+
from cherry_shared.types.launchpad import LaunchpadToken
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class InfoService:
|
|
11
|
+
|
|
12
|
+
def __init__(self, info_url: str, helper_url: str, logger: logging.Logger = None):
|
|
13
|
+
self.info_url = info_url
|
|
14
|
+
self.helper_url = helper_url
|
|
15
|
+
if logger is None:
|
|
16
|
+
self._logger = logging.getLogger(__name__)
|
|
17
|
+
else:
|
|
18
|
+
self._logger = logger
|
|
19
|
+
|
|
20
|
+
async def process_request(
|
|
21
|
+
self,
|
|
22
|
+
url: str,
|
|
23
|
+
body: Dict[str, Any] = None,
|
|
24
|
+
method: str = "GET",
|
|
25
|
+
query: Dict[str, str] = None,
|
|
26
|
+
headers: Dict[str, str] = None,
|
|
27
|
+
timeout: int = 60,
|
|
28
|
+
):
|
|
29
|
+
if headers is None:
|
|
30
|
+
headers = {"Content-Type": "application/json"}
|
|
31
|
+
# Define a custom timeout
|
|
32
|
+
custom_timeout = aiohttp.ClientTimeout(total=timeout)
|
|
33
|
+
|
|
34
|
+
async with aiohttp.ClientSession(
|
|
35
|
+
headers=headers, timeout=custom_timeout
|
|
36
|
+
) as session:
|
|
37
|
+
try:
|
|
38
|
+
if method == "GET":
|
|
39
|
+
async with session.get(
|
|
40
|
+
url, params=query, data=json.dumps(body) if body else None
|
|
41
|
+
) as resp:
|
|
42
|
+
if resp.status >= 400:
|
|
43
|
+
return False, resp.reason
|
|
44
|
+
if "application/json" in resp.headers.get("Content-Type", ""):
|
|
45
|
+
res = await resp.json()
|
|
46
|
+
else:
|
|
47
|
+
res = await resp.text()
|
|
48
|
+
return (
|
|
49
|
+
False,
|
|
50
|
+
f"Unexpected Content-Type: {resp.headers.get('Content-Type')}, Response: {res}",
|
|
51
|
+
)
|
|
52
|
+
elif method == "POST":
|
|
53
|
+
async with session.post(url, data=json.dumps(body)) as resp:
|
|
54
|
+
if resp.status >= 400:
|
|
55
|
+
return False, resp.reason
|
|
56
|
+
if "application/json" in resp.headers.get("Content-Type", ""):
|
|
57
|
+
res = await resp.json()
|
|
58
|
+
else:
|
|
59
|
+
res = await resp.text()
|
|
60
|
+
return (
|
|
61
|
+
False,
|
|
62
|
+
f"Unexpected Content-Type: {resp.headers.get('Content-Type')}, Response: {res}",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
return True, res
|
|
66
|
+
except Exception as e:
|
|
67
|
+
self._logger.error(f"Error in InfoService.process_request(): {e}")
|
|
68
|
+
return False, "Exception: " + str(e)
|
|
69
|
+
|
|
70
|
+
async def search_address(self, address: str):
|
|
71
|
+
url = f"{self.info_url}/info/{address}"
|
|
72
|
+
success, data = await self.process_request(url)
|
|
73
|
+
if success:
|
|
74
|
+
return [Pair.from_dexsc_dict(item) for item in data["data"][:10]]
|
|
75
|
+
|
|
76
|
+
async def get_address_type(self, address: str):
|
|
77
|
+
url = f"{self.info_url}/address"
|
|
78
|
+
body = {"address": address}
|
|
79
|
+
success, res = await self.process_request(url, body)
|
|
80
|
+
if success:
|
|
81
|
+
return res["data"]
|
|
82
|
+
|
|
83
|
+
async def get_pair_by_pair_address(self, address: str, chainId: str):
|
|
84
|
+
url = f"{self.info_url}/info/pair"
|
|
85
|
+
success, res = await self.process_request(
|
|
86
|
+
url, {"address": address, "chainId": chainId}, "POST"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
if not success:
|
|
90
|
+
self._logger.error(res)
|
|
91
|
+
return None
|
|
92
|
+
return Pair.from_dexsc_dict(res["data"])
|
|
93
|
+
|
|
94
|
+
async def get_chains_data(self):
|
|
95
|
+
url = f"{self.info_url}/chains"
|
|
96
|
+
success, data = await self.process_request(url)
|
|
97
|
+
if success:
|
|
98
|
+
return data
|
|
99
|
+
|
|
100
|
+
async def get_total_supply(self, chain: str, address: str):
|
|
101
|
+
url = self.helper_url + "/totalsupply"
|
|
102
|
+
body = {"chain": chain, "address": address}
|
|
103
|
+
success, data = await self.process_request(url, body, "POST")
|
|
104
|
+
if success:
|
|
105
|
+
return data["supply"], data["decimals"]
|
|
106
|
+
return None, None
|
|
107
|
+
|
|
108
|
+
async def get_trending(self):
|
|
109
|
+
url = self.helper_url + "/trending"
|
|
110
|
+
success, data = await self.process_request(url)
|
|
111
|
+
if success:
|
|
112
|
+
return data
|
|
113
|
+
return None
|
|
114
|
+
|
|
115
|
+
async def send_confirm_req(
|
|
116
|
+
self, pair_address: str, contract_address: str, chain_id: str, chat_id: int
|
|
117
|
+
):
|
|
118
|
+
url = self.helper_url + "/confirm"
|
|
119
|
+
self._logger.debug(f"{pair_address}, {chain_id}, {chat_id}")
|
|
120
|
+
body = {
|
|
121
|
+
"pairAddress": pair_address,
|
|
122
|
+
"tokenAddress": contract_address,
|
|
123
|
+
"chainId": chain_id,
|
|
124
|
+
"chatId": chat_id,
|
|
125
|
+
}
|
|
126
|
+
self._logger.debug(f"send_confirm_req: {body}")
|
|
127
|
+
success, data = await self.process_request(url, body, "POST")
|
|
128
|
+
if not success:
|
|
129
|
+
self._logger.error(f"failed to send confirm req: {data}")
|
|
130
|
+
|
|
131
|
+
async def send_delete_req(self, tokenAddress: str, chat_id: int):
|
|
132
|
+
url = self.helper_url + "/delete"
|
|
133
|
+
body = {
|
|
134
|
+
"tokenAddress": tokenAddress,
|
|
135
|
+
"chatId": chat_id,
|
|
136
|
+
}
|
|
137
|
+
success, data = await self.process_request(url, body, "POST")
|
|
138
|
+
if not success:
|
|
139
|
+
self._logger.error(f"failed delete token req: {data}")
|
|
140
|
+
|
|
141
|
+
async def send_update_supply(self, tokenAddress: str, chat_id: int, supply: int):
|
|
142
|
+
self._logger.debug(f"{tokenAddress}, {chat_id}, {supply}")
|
|
143
|
+
url = self.helper_url + "/updatesupply"
|
|
144
|
+
body = {
|
|
145
|
+
"address": tokenAddress,
|
|
146
|
+
"chatId": chat_id,
|
|
147
|
+
"supply": supply,
|
|
148
|
+
}
|
|
149
|
+
success, data = await self.process_request(url, body, "POST")
|
|
150
|
+
if not success:
|
|
151
|
+
self._logger.error(f"failed update supply req: {data}")
|
|
152
|
+
|
|
153
|
+
async def generate_wallet(self, wallet_type: str):
|
|
154
|
+
wallet_endpoints = {
|
|
155
|
+
"solana": "/generatesolanawallet",
|
|
156
|
+
"tron": "/generatetronwallet",
|
|
157
|
+
"sui": "/generatesuiawallet",
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if wallet_type not in wallet_endpoints:
|
|
161
|
+
self._logger.error(f"wallet endpoint not provided: {wallet_type}")
|
|
162
|
+
return
|
|
163
|
+
|
|
164
|
+
url = self.helper_url + wallet_endpoints[wallet_type]
|
|
165
|
+
success, data = await self.process_request(url)
|
|
166
|
+
|
|
167
|
+
if not success:
|
|
168
|
+
self._logger.error(f"Failed {wallet_type} wallet request: {data}")
|
|
169
|
+
return
|
|
170
|
+
self._logger.debug(f"generated new wallet {data['publicKey'][:10]}")
|
|
171
|
+
return data["publicKey"], data["privateKey"]
|
|
172
|
+
|
|
173
|
+
async def get_balance(self, wallet_address: str, chain: str):
|
|
174
|
+
url = self.helper_url + "/balance"
|
|
175
|
+
success, data = await self.process_request(
|
|
176
|
+
url, query={"tokenAddress": wallet_address, "chain": chain}
|
|
177
|
+
)
|
|
178
|
+
if not success:
|
|
179
|
+
self._logger.error(f"failed to get balance: {data}")
|
|
180
|
+
return None
|
|
181
|
+
return float(data["balance"])
|
|
182
|
+
|
|
183
|
+
async def buyNburn(
|
|
184
|
+
self,
|
|
185
|
+
raid_id: int,
|
|
186
|
+
chat_id: int,
|
|
187
|
+
amount: float,
|
|
188
|
+
token_address: str,
|
|
189
|
+
pair_address: str,
|
|
190
|
+
chain: str,
|
|
191
|
+
pk: str,
|
|
192
|
+
):
|
|
193
|
+
url = self.helper_url + "/burn"
|
|
194
|
+
body = {
|
|
195
|
+
"raidId": raid_id,
|
|
196
|
+
"chatId": chat_id,
|
|
197
|
+
"amount": amount,
|
|
198
|
+
"tokenAddress": token_address,
|
|
199
|
+
"pairAddress": pair_address,
|
|
200
|
+
"chain": chain,
|
|
201
|
+
"privateKey": pk,
|
|
202
|
+
}
|
|
203
|
+
success, data = await self.process_request(url, body, "POST")
|
|
204
|
+
if not success:
|
|
205
|
+
self._logger.error(f"failed to send confirm req: {data}")
|
|
206
|
+
return False, data
|
|
207
|
+
|
|
208
|
+
status: bool = data["status"]
|
|
209
|
+
self._logger.debug(f"buyNburn status = {status}")
|
|
210
|
+
return status, None
|
|
211
|
+
|
|
212
|
+
async def check_status(self, raid_id: int):
|
|
213
|
+
try:
|
|
214
|
+
url = self.helper_url + f"/status?raidId={raid_id}"
|
|
215
|
+
success, data = await self.process_request(url)
|
|
216
|
+
if not success:
|
|
217
|
+
self._logger.error(f"failed to send confirm req: {data}")
|
|
218
|
+
return "error", data
|
|
219
|
+
res = data["status"], (
|
|
220
|
+
data["buyTx"],
|
|
221
|
+
data["burnTx"],
|
|
222
|
+
data["finalBountyAmount"],
|
|
223
|
+
)
|
|
224
|
+
return res
|
|
225
|
+
except Exception as e:
|
|
226
|
+
self._logger.error(
|
|
227
|
+
f"Error in InfoService.check_status(): {e}", exc_info=True
|
|
228
|
+
)
|
|
229
|
+
return "error", str(e)
|
|
230
|
+
|
|
231
|
+
async def withdraw(self, chain: str, toAddress: str, userId: int):
|
|
232
|
+
url = self.helper_url + "/withdraw"
|
|
233
|
+
query = {"chain": chain, "toAddress": toAddress, "userId": userId}
|
|
234
|
+
success, res = await self.process_request(url, query=query)
|
|
235
|
+
if not success:
|
|
236
|
+
self._logger.error(f"Info Withdraw: {res}")
|
|
237
|
+
return False, res
|
|
238
|
+
tx_hash = res["txHash"]
|
|
239
|
+
return True, tx_hash
|
|
240
|
+
|
|
241
|
+
async def validate_purchase(
|
|
242
|
+
self,
|
|
243
|
+
user_id: int,
|
|
244
|
+
value: float,
|
|
245
|
+
chain: str,
|
|
246
|
+
promo_code: str = None,
|
|
247
|
+
payout_value: float = None,
|
|
248
|
+
token_id: int = None,
|
|
249
|
+
trendingId: int = None,
|
|
250
|
+
volume_bot=0,
|
|
251
|
+
status: Literal["normal", "volume", "holder"] = "normal",
|
|
252
|
+
hours=None,
|
|
253
|
+
base_amount: float = 0.01,
|
|
254
|
+
**kwargs,
|
|
255
|
+
):
|
|
256
|
+
url = self.helper_url + "/trendingslot/verify"
|
|
257
|
+
body = {
|
|
258
|
+
"chain": chain,
|
|
259
|
+
"value": value,
|
|
260
|
+
"userId": user_id,
|
|
261
|
+
"promoCode": promo_code,
|
|
262
|
+
"payoutValue": payout_value,
|
|
263
|
+
"tokenId": token_id,
|
|
264
|
+
"trendingId": trendingId,
|
|
265
|
+
"volumeBot": 1 if status == "holder" else volume_bot,
|
|
266
|
+
"status": status,
|
|
267
|
+
"hours": hours,
|
|
268
|
+
"baseAmount": base_amount,
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
# Add any additional key-value arguments to the body
|
|
272
|
+
body.update(kwargs)
|
|
273
|
+
|
|
274
|
+
success, res = await self.process_request(url, body, "POST")
|
|
275
|
+
if not success:
|
|
276
|
+
self._logger.error(f"Info validate_purchase: {res}")
|
|
277
|
+
return -1, res
|
|
278
|
+
|
|
279
|
+
code = int(res["code"])
|
|
280
|
+
message = res["message"] if code == 0 else res["error"]
|
|
281
|
+
|
|
282
|
+
return code, message
|
|
283
|
+
|
|
284
|
+
async def get_token_info(self, address: str, chain: str):
|
|
285
|
+
url = self.info_url + "/info/tokeninfo"
|
|
286
|
+
body = {"address": address, "chain": chain}
|
|
287
|
+
success, res = await self.process_request(url, body=body, method="POST")
|
|
288
|
+
if not success:
|
|
289
|
+
self._logger.error(f"get_token_info: {res}")
|
|
290
|
+
return None
|
|
291
|
+
|
|
292
|
+
code = int(res["code"])
|
|
293
|
+
if code == 0:
|
|
294
|
+
self._logger.debug(f"get_token_info: {res['data']}")
|
|
295
|
+
return res["data"]
|
|
296
|
+
|
|
297
|
+
async def get_launchpad_data(self, launchpad: LaunchPad, address: str):
|
|
298
|
+
url = self.info_url + f"/{launchpad.info_route}"
|
|
299
|
+
body = {"address": address, "chatId": 0}
|
|
300
|
+
success, res = await self.process_request(url, body=body, method="POST")
|
|
301
|
+
if not success:
|
|
302
|
+
self._logger.error(f"get {launchpad.name} info: {res}")
|
|
303
|
+
return None
|
|
304
|
+
|
|
305
|
+
code = int(res["code"])
|
|
306
|
+
self._logger.debug(f"get_launchpad_data: {res['data']}")
|
|
307
|
+
if code == 0:
|
|
308
|
+
return LaunchpadToken.create_token_info(res["data"])
|
|
309
|
+
|
|
310
|
+
async def get_fees(self, address: str):
|
|
311
|
+
try:
|
|
312
|
+
url = self.helper_url + f"/getFees"
|
|
313
|
+
body = {"address": address}
|
|
314
|
+
success, res = await self.process_request(url, body=body, method="POST")
|
|
315
|
+
if not success:
|
|
316
|
+
self._logger.error(f"get_fees info for address {address}: {res}")
|
|
317
|
+
return None
|
|
318
|
+
self._logger.debug(f"get_fees: {res}")
|
|
319
|
+
return round(float(res.get("fee", 1)), 2)
|
|
320
|
+
except Exception as e:
|
|
321
|
+
self._logger.error(f"Error in InfoService.get_fees(): {e}", exc_info=True)
|
|
322
|
+
return 1
|
|
323
|
+
|
|
324
|
+
async def send_message(self, chat_id: int, message: str, thread_id: str = None):
|
|
325
|
+
url = self.helper_url + "/sendtrendingmessage"
|
|
326
|
+
body = {
|
|
327
|
+
"chat_id": chat_id,
|
|
328
|
+
"text": message,
|
|
329
|
+
"thread_id": thread_id,
|
|
330
|
+
}
|
|
331
|
+
success, res = await self.process_request(url, body=body, method="POST")
|
|
332
|
+
if not success:
|
|
333
|
+
self._logger.error(f"send_message: {res}")
|
|
334
|
+
return False, res
|
|
335
|
+
return True, res
|
|
336
|
+
|
|
337
|
+
async def edit_message(
|
|
338
|
+
self, chat_id: int, message_id: int, message: str, thread_id: str = None
|
|
339
|
+
):
|
|
340
|
+
url = self.helper_url + "/sendtrendingmessage"
|
|
341
|
+
body = {
|
|
342
|
+
"chat_id": chat_id,
|
|
343
|
+
"msg_id": message_id,
|
|
344
|
+
"text": message,
|
|
345
|
+
"thread_id": thread_id,
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
success, res = await self.process_request(url, body=body, method="POST")
|
|
349
|
+
if not success:
|
|
350
|
+
self._logger.error(f"edit_message: {res}")
|
|
351
|
+
return False, res
|
|
352
|
+
return True, res
|
|
353
|
+
|
|
354
|
+
async def check_rate_limit(
|
|
355
|
+
self,
|
|
356
|
+
chat_id: Optional[int] = None,
|
|
357
|
+
priority: Literal["high", "normal", "low"] = "normal",
|
|
358
|
+
):
|
|
359
|
+
url = self.helper_url + "/check-rate-limit"
|
|
360
|
+
body = {
|
|
361
|
+
"chat_id": chat_id,
|
|
362
|
+
"priority": priority,
|
|
363
|
+
}
|
|
364
|
+
success, res = await self.process_request(url, body=body, method="POST")
|
|
365
|
+
if not success:
|
|
366
|
+
self._logger.error(f"check_rate_limit: {res}")
|
|
367
|
+
return 0
|
|
368
|
+
delay = int(res.get("delay_ms", 0)) / 1000.0
|
|
369
|
+
return delay
|