py-near 1.1.46__tar.gz → 1.1.48__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.
Files changed (43) hide show
  1. {py_near-1.1.46 → py_near-1.1.48}/PKG-INFO +4 -4
  2. {py_near-1.1.46 → py_near-1.1.48}/pyproject.toml +6 -6
  3. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/providers.py +74 -60
  4. {py_near-1.1.46 → py_near-1.1.48}/LICENSE +0 -0
  5. {py_near-1.1.46 → py_near-1.1.48}/README.md +0 -0
  6. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/__init__.py +0 -0
  7. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/account.py +0 -0
  8. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/constants.py +0 -0
  9. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/__init__.py +0 -0
  10. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/__pycache__/__init__.cpython-311.pyc +0 -0
  11. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/__pycache__/core.cpython-311.pyc +0 -0
  12. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/__pycache__/fts.cpython-311.pyc +0 -0
  13. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/core.py +0 -0
  14. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/ft/__init__.py +0 -0
  15. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/ft/__pycache__/__init__.cpython-311.pyc +0 -0
  16. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/ft/__pycache__/async_client.cpython-311.pyc +0 -0
  17. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/ft/__pycache__/exceptions.cpython-311.pyc +0 -0
  18. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/ft/__pycache__/models.cpython-311.pyc +0 -0
  19. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/ft/async_client.py +0 -0
  20. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/ft/exceptions.py +0 -0
  21. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/ft/models.py +0 -0
  22. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/fts.py +0 -0
  23. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/keypom/__init__.py +0 -0
  24. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/keypom/async_client.py +0 -0
  25. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/keypom/exceptions.py +0 -0
  26. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/keypom/models.py +0 -0
  27. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/staking/__init__.py +0 -0
  28. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/staking/__pycache__/__init__.cpython-311.pyc +0 -0
  29. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/staking/__pycache__/async_client.cpython-311.pyc +0 -0
  30. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/staking/__pycache__/exceptions.cpython-311.pyc +0 -0
  31. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/staking/__pycache__/models.cpython-311.pyc +0 -0
  32. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/staking/async_client.py +0 -0
  33. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/staking/exceptions.py +0 -0
  34. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/dapps/staking/models.py +0 -0
  35. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/exceptions/__init__.py +0 -0
  36. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/exceptions/__pycache__/__init__.cpython-311.pyc +0 -0
  37. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/exceptions/__pycache__/exceptions.cpython-311.pyc +0 -0
  38. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/exceptions/__pycache__/provider.cpython-311.pyc +0 -0
  39. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/exceptions/exceptions.py +0 -0
  40. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/exceptions/provider.py +0 -0
  41. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/models.py +0 -0
  42. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/transactions.py +0 -0
  43. {py_near-1.1.46 → py_near-1.1.48}/src/py_near/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py-near
3
- Version: 1.1.46
3
+ Version: 1.1.48
4
4
  Summary: Pretty simple and fully asynchronous framework for working with NEAR blockchain
5
5
  Author: pvolnov
6
6
  Author-email: petr@herewallet.app
@@ -12,9 +12,9 @@ Classifier: Programming Language :: Python :: 3.9
12
12
  Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
- Requires-Dist: aiohttp (>=3.7.4,<4.0.0)
16
- Requires-Dist: ed25519 (>=1.5,<2.0)
17
- Requires-Dist: py-near-primitives (>=0.2.3,<0.3.0)
15
+ Requires-Dist: ed25519 (==1.5)
16
+ Requires-Dist: httpx (==0.26.0)
17
+ Requires-Dist: py-near-primitives (==0.2.3)
18
18
  Description-Content-Type: text/markdown
19
19
 
20
20
  # py-near
@@ -1,15 +1,15 @@
1
1
  [tool.poetry]
2
2
  name = "py-near"
3
- version = "1.1.46"
3
+ version = "1.1.48"
4
4
  description="Pretty simple and fully asynchronous framework for working with NEAR blockchain"
5
5
  authors = ["pvolnov <petr@herewallet.app>"]
6
6
  readme = "README.md"
7
7
 
8
8
  [tool.poetry.dependencies]
9
9
  python = "^3.7"
10
- ed25519 = "^1.5"
11
- aiohttp = "^3.7.4"
12
- py-near-primitives = "^0.2.3"
10
+ ed25519 = "1.5"
11
+ httpx = "0.26.0"
12
+ py-near-primitives = "0.2.3"
13
13
 
14
14
  [tool.poetry.dev-dependencies]
15
15
  black = "^21.12b0"
@@ -22,12 +22,12 @@ base58 = "^2.1.1"
22
22
 
23
23
  [project]
24
24
  name = "py-near"
25
- version = "1.1.46"
25
+ version = "1.1.48"
26
26
  description = "Pretty simple and fully asynchronous framework for working with NEAR blockchaink"
27
27
  authors = [ {name = "pvolnov", email = "petr@herewallet.app"} ]
28
28
  requires-python = ">=3.7"
29
29
  license = {file = "LICENSE"}
30
- dependencies=["base58", "ed25519", "aiohttp", "py-near-primitives", "pydantic"]
30
+ dependencies=["base58", "ed25519", "httpx", "py-near-primitives", "pydantic"]
31
31
  keywords = ["python", "near", "async"]
32
32
  classifiers = [
33
33
  "Programming Language :: Python :: 3",
@@ -5,8 +5,7 @@ import json
5
5
  from collections import Counter
6
6
  from typing import Optional
7
7
 
8
- import aiohttp
9
- from aiohttp import ClientResponseError, ClientConnectorError, ServerDisconnectedError
8
+ import httpx
10
9
  from loguru import logger
11
10
 
12
11
  from py_near.constants import TIMEOUT_WAIT_RPC
@@ -61,6 +60,7 @@ class JsonProvider(object):
61
60
  self._last_rpc_addr_check = 0
62
61
  self.allow_broadcast = allow_broadcast
63
62
  self._timeout = timeout
63
+ self._client: httpx.AsyncClient = httpx.AsyncClient()
64
64
 
65
65
  async def shutdown(self):
66
66
  pass
@@ -94,35 +94,41 @@ class JsonProvider(object):
94
94
  "id": 1,
95
95
  }
96
96
  auth_key = "py-near"
97
+ rpc_addr_url = rpc_addr
97
98
  if "@" in rpc_addr:
98
- auth_key = rpc_addr.split("//")[1].split("@")[0]
99
- rpc_addr = rpc_addr.replace(auth_key + "@", "")
100
- async with aiohttp.ClientSession() as session:
101
- async with session.post(rpc_addr, json=data, headers={
99
+ auth_key = rpc_addr_url.split("//")[1].split("@")[0]
100
+ rpc_addr_url = rpc_addr_url.replace(auth_key + "@", "")
101
+
102
+ r = await self._client.post(
103
+ rpc_addr_url,
104
+ json=data,
105
+ headers={
102
106
  "Referer": "https://tgapp.herewallet.app",
103
107
  "Authorization": f"Bearer {auth_key}",
104
- }) as r:
105
- if r.status == 200:
106
- data = json.loads(await r.text())["result"]
107
- if data["sync_info"]["syncing"]:
108
- last_block_ts = datetime.datetime.fromisoformat(
109
- data["sync_info"]["latest_block_time"]
110
- )
111
- diff = (
112
- datetime.datetime.utcnow().timestamp()
113
- - last_block_ts.timestamp()
114
- )
115
- is_syncing = diff > 60
116
- else:
117
- is_syncing = False
118
- if is_syncing:
119
- logger.error(f"Remove async RPC : {rpc_addr} ({diff})")
120
- continue
121
- available_rpcs.append(rpc_addr)
122
- else:
123
- logger.error(
124
- f"Remove rpc because of error {r.status}: {rpc_addr}"
125
- )
108
+ },
109
+ )
110
+ if r.status_code == 200:
111
+ data = json.loads(r.text)["result"]
112
+ diff = 0
113
+ if data["sync_info"]["syncing"]:
114
+ last_block_ts = datetime.datetime.fromisoformat(
115
+ data["sync_info"]["latest_block_time"]
116
+ )
117
+ diff = (
118
+ datetime.datetime.utcnow().timestamp()
119
+ - last_block_ts.timestamp()
120
+ )
121
+ is_syncing = diff > 60
122
+ else:
123
+ is_syncing = False
124
+ if is_syncing:
125
+ logger.error(f"Remove async RPC : {rpc_addr} ({diff})")
126
+ continue
127
+ available_rpcs.append(rpc_addr)
128
+ else:
129
+ logger.error(
130
+ f"Remove rpc because of error {r.status_code}: {rpc_addr}"
131
+ )
126
132
  except Exception as e:
127
133
  if rpc_addr in self._available_rpcs:
128
134
  logger.error(f"Remove rpc: {e}")
@@ -146,24 +152,26 @@ class JsonProvider(object):
146
152
  if "@" in rpc_call_addr:
147
153
  auth_key = rpc_call_addr.split("//")[1].split("@")[0]
148
154
  rpc_call_addr = rpc_call_addr.replace(auth_key + "@", "")
149
- async with aiohttp.ClientSession() as session:
150
- r = await session.post(
151
- rpc_call_addr,
152
- json=j,
153
- timeout=self._timeout,
154
- headers={
155
- "Referer": "https://tgapp.herewallet.app",
156
- "Authorization": f"Bearer {auth_key}",
157
- }, # NEAR RPC requires Referer header
158
- )
159
- if r.status == 200:
160
- return json.loads(await r.text())
161
- return {
162
- "error": {
163
- "cause": {"name": "RPC_ERROR", "message": f"Status: {r.status}"},
164
- "data": await r.text(),
165
- }
155
+ r = await self._client.post(
156
+ rpc_call_addr,
157
+ json=j,
158
+ timeout=self._timeout,
159
+ headers={
160
+ "Referer": "https://tgapp.herewallet.app",
161
+ "Authorization": f"Bearer {auth_key}",
162
+ },
163
+ )
164
+ if r.status_code == 200:
165
+ return json.loads(r.text)
166
+ return {
167
+ "error": {
168
+ "cause": {
169
+ "name": "RPC_ERROR",
170
+ "message": f"Status: {r.status_code}",
171
+ },
172
+ "data": r.text,
166
173
  }
174
+ }
167
175
 
168
176
  if broadcast or threshold:
169
177
  pending = [
@@ -190,14 +198,18 @@ class JsonProvider(object):
190
198
  array = [hash(json.dumps(x)) for x in responses]
191
199
  most_frequent_element = self.most_frequent_by_hash(array)
192
200
  correct_responses = [
193
- x for x in responses if hash(json.dumps(x)) == most_frequent_element
201
+ x
202
+ for x in responses
203
+ if hash(json.dumps(x)) == most_frequent_element
194
204
  ]
195
205
  if len(correct_responses) >= threshold:
196
206
  for task in pending:
197
207
  task.cancel()
198
- return most_frequent_element
208
+ return correct_responses[0]
199
209
  if threshold and threshold > 0:
200
- raise RpcEmptyResponse(f"Threshold not reached: {len(correct_responses)}/{threshold}")
210
+ raise RpcEmptyResponse(
211
+ f"Threshold not reached: {len(correct_responses)}/{threshold}"
212
+ )
201
213
  return result
202
214
  else:
203
215
  res = None
@@ -210,7 +222,6 @@ class JsonProvider(object):
210
222
  logger.error(f"Rpc error: {e}")
211
223
  continue
212
224
  return res
213
- raise RpcEmptyResponse("RPC returned empty response")
214
225
 
215
226
  @staticmethod
216
227
  def get_error_from_response(content: dict):
@@ -315,7 +326,7 @@ class JsonProvider(object):
315
326
 
316
327
  async def get_status(self):
317
328
  await self.check_available_rpcs()
318
- for rpc_addr in self._available_rpcs:
329
+ for rpc_addr in self._available_rpcs.copy():
319
330
  try:
320
331
  data = {
321
332
  "jsonrpc": "2.0",
@@ -323,16 +334,19 @@ class JsonProvider(object):
323
334
  "params": {"finality": "final"},
324
335
  "id": 1,
325
336
  }
326
- async with aiohttp.ClientSession() as session:
327
- async with session.post(rpc_addr, json=data) as r:
328
- if r.status == 200:
329
- return json.loads(await r.text())["result"]
330
- except (
331
- ClientResponseError,
332
- ClientConnectorError,
333
- ServerDisconnectedError,
334
- ConnectionError,
335
- ) as e:
337
+ headers = {
338
+ "Referer": "https://tgapp.herewallet.app",
339
+ }
340
+ if "@" in rpc_addr:
341
+ auth_key = rpc_addr.split("//")[1].split("@")[0]
342
+ rpc_addr = rpc_addr.replace(auth_key + "@", "")
343
+ headers = {
344
+ "Authorization": f"Bearer {auth_key}"
345
+ }
346
+ r = await self._client.post(rpc_addr, json=data, headers=headers)
347
+ if r.status_code == 200:
348
+ return json.loads(r.text)["result"]
349
+ except ConnectionError as e:
336
350
  logger.error(f"Rpc get status error: {e}")
337
351
  except Exception as e:
338
352
  logger.error(e)
File without changes
File without changes
File without changes
File without changes