abstract-solana 0.0.2.0__py3-none-any.whl → 0.0.2.1__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.

Potentially problematic release.


This version of abstract-solana might be problematic. Click here for more details.

@@ -0,0 +1,139 @@
1
+ import time,os,json
2
+ from abstract_utilities import *
3
+ from abstract_security import *
4
+ def getAbsFile():
5
+ return os.path.abspath(__file__)
6
+ def getAbsDir():
7
+ return os.path.dirname(getAbsFile())
8
+ def getAbsPath(path):
9
+ return os.path.join(getAbsDir(),path)
10
+ def getSaveStatePath():
11
+ return getAbsPath('rate_limiter_state.json')
12
+ def readSaveState():
13
+ path= getSaveStatePath()
14
+ if not os.path.isfile(path):
15
+ state = {'last_method':None,'rate_limit': [],'last_mb': {},'cooldown_time': False,'last_url':None}
16
+ safe_dump_to_file(file_path=path,data=state)
17
+ return safe_read_from_json(getSaveStatePath())
18
+ def is_time_interval(time_obj, interval):
19
+ print([time.time() - time_obj,interval-1])
20
+ return (time.time() - time_obj) < interval-1
21
+
22
+ def get_mb(sum_list, limit, last_mb):
23
+ return (sum_list + last_mb) > limit
24
+
25
+ def datasize(data):
26
+ if isinstance(data, str):
27
+ return len(data.encode('utf-8'))
28
+ elif isinstance(data, (bytes, bytearray)):
29
+ return len(data)
30
+ elif isinstance(data, list) or isinstance(data, dict):
31
+ return len(json.dumps(data).encode('utf-8'))
32
+ else:
33
+ return len(str(data).encode('utf-8'))
34
+
35
+ class RateLimiter(metaclass=SingletonMeta):
36
+ def __init__(self,rpc_url = None,fallback_rpc_url=None,env_directory=None):
37
+ self.rpc_url = rpc_url get_env_key(key="solana_primary_rpc_url",path=env_directory) or "https://api.mainnet-beta.solana.com"
38
+ self.fallback_rpc_url = fallback_rpc_url or get_env_key(key="solana_fallback_rpc_url",path=env_directory)
39
+ self.initialized = True
40
+ self.rate_limit = []
41
+ self.last_mb = {}
42
+ self.cooldown_time = False
43
+ self.url1 = self.rpc_url
44
+ self.url2 = self.fallback_rpc_url
45
+ self.state_file = getSaveStatePath()
46
+ self.last_url = None
47
+ self.last_method=None
48
+ self.load_state()
49
+ def get_url_2(self):
50
+ return self.url2
51
+
52
+ def save_state(self):
53
+ state = {
54
+ 'last_method':self.last_method,
55
+ 'rate_limit': self.rate_limit,
56
+ 'last_mb': self.last_mb,
57
+ 'cooldown_time': self.cooldown_time,
58
+ 'last_url': self.last_url
59
+ }
60
+ safe_dump_to_file(self.state_file, state)
61
+
62
+ def load_state(self):
63
+ state = readSaveState()
64
+ self.last_method = state.get('last_method')
65
+ self.rate_limit = state.get('rate_limit', [])
66
+ self.last_mb = state.get('last_mb', {})
67
+ self.last_url = state.get('last_url')
68
+ self.cooldown_time = state.get('cooldown_time', False)
69
+
70
+ def set_cooldown(self, add=False):
71
+ if add:
72
+ self.cooldown_time = time.time() + add
73
+ if self.cooldown_time and (time.time() > self.cooldown_time):
74
+ self.cooldown_time = False
75
+ return bool(self.cooldown_time)
76
+
77
+ def get_last_rate_limit(self):
78
+ if self.rate_limit:
79
+ return self.rate_limit[-1]
80
+ return {}
81
+
82
+ def is_all_limit(self, method):
83
+ if method not in self.last_mb:
84
+ self.last_mb[method] = 0
85
+
86
+ if self.set_cooldown():
87
+ return True
88
+
89
+ self.rate_limit = [query for query in self.rate_limit if is_time_interval(query.get('time') or 0, 30)]
90
+ last_rate_limit = self.get_last_rate_limit()
91
+
92
+ # Check if data size exceeds limit
93
+ if get_mb(sum(query.get('data', 0) for query in self.rate_limit), 100, self.last_mb[method]):
94
+ return True
95
+
96
+ # Check if the last request for the same method was within 10 seconds
97
+ if self.last_method == method and is_time_interval(last_rate_limit.get('time') or 0, 10):
98
+ return True
99
+
100
+ # Check if more than 100 requests in the last 10 seconds
101
+ time_rate = [query for query in self.rate_limit if is_time_interval(query.get('time') or 0, 10)]
102
+ if len(time_rate) > 100:
103
+ return True
104
+
105
+ # Check if more than 40 requests for the same method in the last 10 seconds
106
+ method_specific_time_rate = [query for query in time_rate if query['method'] == method]
107
+ if len(method_specific_time_rate) > 40:
108
+ return True
109
+
110
+ return False
111
+
112
+ def log_response(self, method=None, response_data=None):
113
+ method = method or 'default_method'
114
+ response_data = response_data or {}
115
+ data_size = datasize(response_data)
116
+ self.last_mb[method] = data_size
117
+
118
+ if self.last_url == self.url1:
119
+ self.rate_limit.append({'method': method, 'data': data_size, 'time': time.time()})
120
+
121
+ self.rate_limit = [query for query in self.rate_limit if is_time_interval(query['time'], 30)]
122
+ self.save_state()
123
+
124
+ def get_url(self, method=None):
125
+ method = method or 'default_method'
126
+ if self.url2 and method == 'get_url_2':
127
+ self.last_url = self.url2
128
+ return self.url2
129
+
130
+ if not self.is_all_limit(method):
131
+ self.last_method = method
132
+
133
+ self.last_url = self.url1
134
+ elif self.url2:
135
+ self.last_url = self.url2
136
+ else:
137
+ return {"rate_limited":"limit has been reached"}
138
+ return self.last_url
139
+
@@ -5,6 +5,8 @@ from ..abstract_utils.pubkey_utils import get_pubkey,get_sigkey
5
5
  import inspect,asyncio,json,requests
6
6
  from abstract_apis import get_url,make_endpoint,get_headers,asyncPostRequest,get_async_response,get_headers
7
7
  from abstract_utilities import is_number
8
+ from .rate_limiter import RateLimiter
9
+ rate_limiter = RateLimiter()
8
10
  def convert_to_lower(string_obj):
9
11
  return ''.join(f"_{char.lower()}" if char.isupper() else char for char in str(string_obj))
10
12
  def convert_to_upper(string_obj):
@@ -83,3 +85,10 @@ def get_rpc_dict(endpoint,*args,**kwargs):
83
85
  kwargs = get_conversions(variables,*args,**kwargs)
84
86
  kwargs = json.loads(str(call_function(function,**kwargs)))
85
87
  return kwargs
88
+ def abstract_solana_rate_limited_call(endpoint,*args,**kwargs):
89
+ rpc_dict = get_rpc_dict(endpoint,*args,**kwargs)
90
+ url = rate_limiter.get_url(rpc_dict.get('method')
91
+ is isinstance(url,dict):
92
+ return url
93
+ response = get_async_response(asyncPostRequest,url=url,endpoint=endpoint,data=rpc_dict)
94
+ return response
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: abstract_solana
3
- Version: 0.0.2.0
3
+ Version: 0.0.2.1
4
4
  Home-page: https://github.com/AbstractEndeavors/abstract_solana
5
5
  Author: putkoff
6
6
  Author-email: partners@abstractendeavors.com
@@ -3,7 +3,8 @@ abstract_solana/abstract_rpcs/__init__.py,sha256=s-nEoENWaeqd00GPEV9EvCb-QTAGKdQ
3
3
  abstract_solana/abstract_rpcs/db_templates.py,sha256=sjdHfHIq9bO6VuDm3hwzn46NUrXXrGnB0knYNeVU7k8,29839
4
4
  abstract_solana/abstract_rpcs/get_api_gui.py,sha256=OZ61HHb0gwdYjirwFFmnwk8z9x5np3cecCj9MdmuF8U,12372
5
5
  abstract_solana/abstract_rpcs/get_body.py,sha256=UV85217q7mIpYOhVZdnzfmgZxD3QM0w0J0oevXyYtdE,51272
6
- abstract_solana/abstract_rpcs/solana_rpc_client.py,sha256=9cFFpwr9Clhr7y3QbcFwH0-NSsOsglv54r228DrHs_g,3446
6
+ abstract_solana/abstract_rpcs/rate_limiter.py,sha256=c3viL1iyci5PsMmG4smt2Njs_QHKM4jBPtl1Lic9aFU,5129
7
+ abstract_solana/abstract_rpcs/solana_rpc_client.py,sha256=HqYzGPaBZcQu7XYD61awJ_jc_UAA2rMpjE-LiZDqqvQ,3844
7
8
  abstract_solana/abstract_utils/__init__.py,sha256=HCbBVQ5BIFCVkFqqTMHp1Y__YQAO4HTq_KHVdMCe89U,296
8
9
  abstract_solana/abstract_utils/account_key_utils.py,sha256=VMJd4GOTK1vn8UZsfXDnjxDOGoQWGY6fvflJqPZ7Xvs,877
9
10
  abstract_solana/abstract_utils/constants.py,sha256=cSmCKzQiNZocX1YkKYrdY-O449aYhi7BT_j-45HZN-E,1418
@@ -19,7 +20,7 @@ abstract_solana/pump_functions/__init__.py,sha256=BiRxwJd1JWwEft63zqYwZ_Xs6UDp4h
19
20
  abstract_solana/pump_functions/buy_sell_pump.py,sha256=gjv_1et20s1Li0ygcURofO29VPkO1v-a5G5Bo_sZs_c,7860
20
21
  abstract_solana/pump_functions/pump_fun_keys.py,sha256=BeWbV9_wd-c6ydF33drW-gZBDPWolbsMZL4cNhP3eOU,8537
21
22
  abstract_solana/pump_functions/token_utils.py,sha256=O-Fgj3L1NhND-k4INa3WvLAEXg2N9u1fVqyLFzn1PwM,2714
22
- abstract_solana-0.0.2.0.dist-info/METADATA,sha256=x2GffF8U4I1lJJll4xkkqjsUbn-J_PVZI3LKLUu1mZs,980
23
- abstract_solana-0.0.2.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
24
- abstract_solana-0.0.2.0.dist-info/top_level.txt,sha256=SsJYent8eZQ0FU2jmP8wTj7aFZFhNwxxP-5cCTQ2B-o,16
25
- abstract_solana-0.0.2.0.dist-info/RECORD,,
23
+ abstract_solana-0.0.2.1.dist-info/METADATA,sha256=ypGifYl7mZZ0z8S3Oo5z-emQBBb459DNrTVzVKU5gzI,980
24
+ abstract_solana-0.0.2.1.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
25
+ abstract_solana-0.0.2.1.dist-info/top_level.txt,sha256=SsJYent8eZQ0FU2jmP8wTj7aFZFhNwxxP-5cCTQ2B-o,16
26
+ abstract_solana-0.0.2.1.dist-info/RECORD,,