py-near 1.1.13__py3-none-any.whl → 1.1.14__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.
py_near/account.py CHANGED
@@ -1,9 +1,6 @@
1
1
  import asyncio
2
- import base64
3
2
  import collections
4
- import hashlib
5
3
  import json
6
- import logging
7
4
  from typing import List, Union, Dict, Optional
8
5
 
9
6
  import base58
@@ -15,12 +12,8 @@ from py_near import constants
15
12
  from py_near import transactions
16
13
  from py_near import utils
17
14
  from py_near.dapps.ft.async_client import FT
18
- from py_near.dapps.phone.async_client import Phone
19
15
  from py_near.dapps.staking.async_client import Staking
20
16
  from py_near.exceptions.provider import (
21
- RPCTimeoutError,
22
- InternalError,
23
- TransactionError,
24
17
  JsonProviderError,
25
18
  )
26
19
  from py_near.models import (
@@ -455,14 +448,6 @@ class Account(object):
455
448
  return 0
456
449
  return int(data["amount"])
457
450
 
458
- @property
459
- def phone(self):
460
- """
461
- Get client for phone.herewallet.near
462
- :return: Phone(self)
463
- """
464
- return Phone(self)
465
-
466
451
  @property
467
452
  def ft(self):
468
453
  """
py_near/dapps/fts.py CHANGED
@@ -9,9 +9,8 @@ class FtModel:
9
9
 
10
10
  class FTS:
11
11
  USDTe = FtModel("dac17f958d2ee523a2206206994597c13d831ec7.factory.bridge.near", 6)
12
- DAIe = FtModel("6b175474e89094c44da98b954eedeac495271d0f.factory.bridge.near", 18)
13
12
  USDCe = FtModel("a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.factory.bridge.near", 6)
14
- USDC = FtModel("17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1", 6)
13
+ DAIe = FtModel("6b175474e89094c44da98b954eedeac495271d0f.factory.bridge.near", 18)
15
14
  AURORA = FtModel("aaaaaa20d9e0e2461697782ef11675f668207961.factory.bridge.near", 18)
16
15
  WBTCe = FtModel("2260fac5e5542a773aa44fbcfedf7c193bc2c599.factory.bridge.near", 8)
17
16
  ETH = FtModel("aurora", 18)
@@ -20,7 +19,9 @@ class FTS:
20
19
  stNEAR = FtModel("meta-pool.near", 24)
21
20
  LINEAR = FtModel("linear-protocol.near", 24)
22
21
  wNEAR = FtModel("wrap.near", 24)
23
-
24
22
  META = FtModel("meta-token.near", 24)
25
- USDT = FtModel("usdt.tether-token.near", 6)
26
23
 
24
+ USDT = FtModel("usdt.tether-token.near", 6)
25
+ USDC = FtModel(
26
+ "17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1", 6
27
+ )
@@ -183,6 +183,20 @@ class DelegateActionExpired(ActionErrorKind):
183
183
  pass
184
184
 
185
185
 
186
+ class DelegateActionInvalidNonce(ActionErrorKind):
187
+ """
188
+ Nonce must be greater sender[public_key].nonce
189
+ """
190
+ pass
191
+
192
+
193
+ class DelegateActionInvalidSignature(ActionErrorKind):
194
+ """
195
+ Signature does not match the provided actions and given signer public key
196
+ """
197
+ pass
198
+
199
+
186
200
  _ERROR_TYPE_TO_EXCEPTION = {
187
201
  "AccountAlreadyExists": AccountAlreadyExistsError,
188
202
  "AccountDoesNotExist": AccountDoesNotExistError,
@@ -200,6 +214,8 @@ _ERROR_TYPE_TO_EXCEPTION = {
200
214
  "NewReceiptValidationError": NewReceiptValidationError,
201
215
  "DelegateActionExpired": DelegateActionExpired,
202
216
  "LackBalanceForState": LackBalanceForState,
217
+ "DelegateActionInvalidNonce": DelegateActionInvalidNonce,
218
+ "DelegateActionInvalidSignature": DelegateActionInvalidSignature,
203
219
  }
204
220
 
205
221
 
@@ -119,10 +119,11 @@ class InvalidTransactionError(TransactionError):
119
119
 
120
120
 
121
121
  class TxExecutionError(InvalidTransactionError):
122
- def __init__(self, data, error_json=None):
122
+ def __init__(self, data, error_json=None, **kwargs):
123
123
  super().__init__(error_json=error_json)
124
124
  if isinstance(data, str):
125
125
  data = json.loads(data)
126
+ data.update(kwargs)
126
127
  for key, value in data.items():
127
128
  setattr(self, key, value)
128
129
 
py_near/models.py CHANGED
@@ -264,7 +264,7 @@ class TransactionData:
264
264
 
265
265
  @property
266
266
  def url(self):
267
- return f"https://explorer.near.org/transactions/{self.hash}"
267
+ return f"https://nearblocks.io/ru/txns/{self.hash}"
268
268
 
269
269
 
270
270
  class TransactionResult:
py_near/providers.py CHANGED
@@ -1,19 +1,14 @@
1
1
  import asyncio
2
2
  import base64
3
- import hashlib
4
3
  import json
5
4
  from typing import Optional
6
5
 
7
6
  import aiohttp
8
- import base58
9
7
  from aiohttp import ClientResponseError, ClientConnectorError, ServerDisconnectedError
10
8
  from loguru import logger
11
9
 
12
- from py_near.constants import TIMEOUT_WAIT_RPC
13
-
14
- from py_near.models import TransactionResult
15
-
16
10
  from py_near import constants
11
+ from py_near.constants import TIMEOUT_WAIT_RPC
17
12
  from py_near.exceptions.exceptions import RpcNotAvailableError
18
13
  from py_near.exceptions.provider import (
19
14
  UnknownBlockError,
@@ -30,7 +25,7 @@ from py_near.exceptions.provider import (
30
25
  UnknownAccessKeyError,
31
26
  ERROR_CODE_TO_EXCEPTION,
32
27
  )
33
-
28
+ from py_near.models import TransactionResult
34
29
 
35
30
  PROVIDER_CODE_TO_EXCEPTION = {
36
31
  "UNKNOWN_BLOCK": UnknownBlockError,
@@ -159,12 +154,31 @@ class JsonProvider(object):
159
154
  raise
160
155
 
161
156
  async def get_status(self):
162
- async with aiohttp.ClientSession() as session:
163
- r = await session.get(
164
- "%s/status" % self._rpc_addresses[0], timeout=TIMEOUT_WAIT_RPC
165
- )
166
- r.raise_for_status()
167
- return json.loads(await r.text())
157
+ for rpc_addr in self._rpc_addresses:
158
+ try:
159
+ async with aiohttp.ClientSession() as session:
160
+ r = await session.get(
161
+ "%s/status" % rpc_addr, timeout=TIMEOUT_WAIT_RPC
162
+ )
163
+ if r.status == 200:
164
+ data = json.loads(await r.text())
165
+ if not data["sync_info"][
166
+ "syncing"
167
+ ]: # RPC is not in syncing process
168
+ self._rpc_addresses.remove(rpc_addr)
169
+ self._rpc_addresses.insert(0, rpc_addr)
170
+ return data
171
+ except (
172
+ ClientResponseError,
173
+ ClientConnectorError,
174
+ ServerDisconnectedError,
175
+ ConnectionError,
176
+ ) as e:
177
+ logger.error(f"Rpc error: {e}")
178
+ except Exception as e:
179
+ logger.exception(e)
180
+
181
+ raise RpcNotAvailableError("RPC not available")
168
182
 
169
183
  async def get_validators(self):
170
184
  return await self.json_rpc("validators", [None])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py-near
3
- Version: 1.1.13
3
+ Version: 1.1.14
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
@@ -1,5 +1,5 @@
1
1
  py_near/__init__.py,sha256=t5fAxjaU8dN8xpQR2vz0ZGhfTkdVy2RCbkhJhZFglk4,50
2
- py_near/account.py,sha256=OhyBjpxNBaHgVMaJkpHxK-Eq20u4U-dlbq8zD0kgEkE,16643
2
+ py_near/account.py,sha256=k-bgn-VV6UIvqTuJpz-hnfn4uFXaabJRNgX--y_25kY,16325
3
3
  py_near/constants.py,sha256=inaWIuwmF1EB5JSB0ynnZY5rKY_QsxhF9KuCOhPsM6k,164
4
4
  py_near/dapps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  py_near/dapps/core.py,sha256=LtN9aW2gw2mvEdhzQcQJIidtjv-XL1xjb0LK8DzqtqE,231
@@ -7,27 +7,23 @@ py_near/dapps/ft/__init__.py,sha256=hx8qh4yEs37Ul_JhDWn8LHd-9lzsaATivxKOJPaUqTE,
7
7
  py_near/dapps/ft/async_client.py,sha256=Oir5EQOGueq0lsNn0ybe_1uvMnmV5K1m_mHFuFWIUu4,6717
8
8
  py_near/dapps/ft/exceptions.py,sha256=UjXLFsDQX0vDGS9CGO7HE9XpLD0vovFNUzCb11WKAtc,92
9
9
  py_near/dapps/ft/models.py,sha256=_URS8nXZvfuxjU7Ov2E-nteBak5qKtPKN3bLOR7sC9k,186
10
- py_near/dapps/fts.py,sha256=ViMoQx0h-sgVTozr-JZk3hUGdGxsVP3oP3sAY8i8g5Q,946
10
+ py_near/dapps/fts.py,sha256=MFe_wC96K_RfpFc7soeZr-ejuMWPl7SJqaX2mTbZHy0,959
11
11
  py_near/dapps/keypom/__init__.py,sha256=6fWGxsVr_lb_wTf_MHrbwBl1fgf78b5ezmsVa3JeFjI,32
12
12
  py_near/dapps/keypom/async_client.py,sha256=DS594S00xhcyvVtD1W0PjmtmT3YhvXTZZ3hskbn1-1w,1422
13
13
  py_near/dapps/keypom/exceptions.py,sha256=pGz0w1Ubh2A1aHEWvUX4dVaCcO9r2Y-h2JwhBY5KJbU,45
14
14
  py_near/dapps/keypom/models.py,sha256=NYcKnQw8X4HkvzAwS8qOmPrChT4-8UIM-eMY1r9RbWQ,2166
15
- py_near/dapps/phone/__init__.py,sha256=6fWGxsVr_lb_wTf_MHrbwBl1fgf78b5ezmsVa3JeFjI,32
16
- py_near/dapps/phone/async_client.py,sha256=VN25Knd5FfnzmwlXCXaO7XbyLFqUHQjwrdNfgz2zLDw,6849
17
- py_near/dapps/phone/exceptions.py,sha256=pGz0w1Ubh2A1aHEWvUX4dVaCcO9r2Y-h2JwhBY5KJbU,45
18
- py_near/dapps/phone/models.py,sha256=JbytZ2r18lCK6AXs8gL0hSZJR1Dsr0BuTFeRJvSQ3J0,332
19
15
  py_near/dapps/staking/__init__.py,sha256=1T2lj9DVp0FJ9IfnBtc5Qkx_nJMo1DRVX6L0ENyKugs,34
20
16
  py_near/dapps/staking/async_client.py,sha256=TYudiPwF4tQ03rZuWNL-PUQ2kKpx06BxWWmbvePxJjw,5203
21
17
  py_near/dapps/staking/exceptions.py,sha256=UjXLFsDQX0vDGS9CGO7HE9XpLD0vovFNUzCb11WKAtc,92
22
18
  py_near/dapps/staking/models.py,sha256=zC5M_pc1oMqHq4GaYif1uwFbW6acD2BsiA9rbyiaUTs,124
23
19
  py_near/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- py_near/exceptions/exceptions.py,sha256=OLoS-N97GPOk3eu0QKXMy2l_UPqDk4KtpfnJdM5VT4g,5040
25
- py_near/exceptions/provider.py,sha256=4RxQvO2ER7Bth1S0po0vBOE-gWkcYOZlrRhw2h-1Rig,7677
26
- py_near/models.py,sha256=QKQxL1wkTKZ4MWb5dprJZYalzrvd7bHSXC3WeBujuWE,9426
27
- py_near/providers.py,sha256=RVflvFx-ME1sh1anfO8DcV_g2KVfZk-ypAfdrTSi9Z0,9161
20
+ py_near/exceptions/exceptions.py,sha256=qG-aBYAsyCXcdzmZ84n9wVHCLkuWnd16XZTVprJfUVM,5462
21
+ py_near/exceptions/provider.py,sha256=RddgWbmwlXxrPuM7KtOjjJgtMR32ds2d3KxlnpMMC-A,7715
22
+ py_near/models.py,sha256=_JMpwtI6kP6740jaUPN1JRQIIDGXmL7tXLlR-JvRPXc,9417
23
+ py_near/providers.py,sha256=W1ttqR-dfl_Ists8FbUL7O5wARX92JgAqIPQ7uGz-7M,9915
28
24
  py_near/transactions.py,sha256=QAXegv2JpKISk92NaChtIH6-QPHrcWbrwdKH_lH4TsU,3186
29
25
  py_near/utils.py,sha256=FirRH93ydH1cwjn0-sNrZeIn3BRD6QHedrP2VkAdJ6g,126
30
- py_near-1.1.13.dist-info/LICENSE,sha256=I_GOA9xJ35FiL-KnYXZJdATkbO2KcV2dK2enRGVxzKM,1023
31
- py_near-1.1.13.dist-info/METADATA,sha256=efUQw7DKSFV-ZbQtTW-nNpbe-BROE7vq88lMd0vKolM,4662
32
- py_near-1.1.13.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
33
- py_near-1.1.13.dist-info/RECORD,,
26
+ py_near-1.1.14.dist-info/LICENSE,sha256=I_GOA9xJ35FiL-KnYXZJdATkbO2KcV2dK2enRGVxzKM,1023
27
+ py_near-1.1.14.dist-info/METADATA,sha256=dYh9HIxdTvtkZis5EbI--meZhJVl0NAW6XLC3DbQ1pc,4662
28
+ py_near-1.1.14.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
29
+ py_near-1.1.14.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- from .async_client import Phone
@@ -1,189 +0,0 @@
1
- import json
2
- import re
3
- from typing import List
4
-
5
- import aiohttp
6
-
7
- from py_near.constants import TGAS
8
- from py_near.dapps.core import DappClient, NEAR
9
- from py_near.dapps.fts import FtModel
10
- from py_near.dapps.phone.exceptions import RequestLimitError
11
- from py_near.dapps.phone.models import NearTrustTransaction, FtTrustTransaction
12
- from py_near.exceptions.exceptions import FunctionCallError
13
-
14
- _PHONE_CONTRACT_ID = "phone.herewallet.near"
15
-
16
-
17
- class Phone(DappClient):
18
- """
19
- Client to phone.herewallet.near contract
20
- With this contract you can send NEAR and fungible tokens to
21
- phone number. Reciver will get notification with link to claim tokens.
22
- """
23
-
24
- def __init__(self, account, api_key="default"):
25
- """
26
-
27
- :param account:
28
- :param api_key: there is limit for hash generator requests to provide spam,
29
- to make unlimited requests use api key. You can get it for free by contacting team@herewallet.app
30
- :param network: "mainnet" or "testnet"
31
- """
32
- if account.chain_id != "mainnet":
33
- raise ValueError("Only mainnet is supported")
34
- super().__init__(account)
35
- self._api_key = api_key
36
-
37
- async def _get_phone_hex(self, phone) -> str:
38
- """
39
- To calculate hash we need call herewallet api. This is necessary to prevent creation hash <> phone table.
40
- :param phone:
41
- :return: phone hash
42
- """
43
- if phone[0] != "+":
44
- raise ValueError("Phone number must start with +")
45
- phone = re.sub(r"\D", "", phone)
46
- async with aiohttp.ClientSession() as session:
47
- r = await session.get(
48
- f"https://api.herewallet.app/api/v1/phone/calc_phone_hash?phone={phone}",
49
- headers={
50
- "Content-Type": "application/json",
51
- "Authorization": self._api_key,
52
- },
53
- )
54
- if r.status == 403:
55
- raise RequestLimitError(
56
- "Too many hash generator requests, to make unlimited requests user api key."
57
- "Contact team@herewallet.app to get it for free"
58
- )
59
- if r.status != 200:
60
- raise Exception(
61
- f"Error while getting phone hash: {r.status}\n{await r.text()}"
62
- )
63
- content = json.loads(await r.text())
64
- return content["hash"]
65
-
66
- async def get_ft_transfers(self, phone: str) -> List[FtTrustTransaction]:
67
- """
68
- Get list of fungible token transfers to phone number
69
- :param phone: phone number
70
- :return: list of FtTrustTransaction
71
- """
72
- res = (
73
- await self._account.view_function(
74
- _PHONE_CONTRACT_ID,
75
- "get_ft_transfers",
76
- {"phone": await self._get_phone_hex(phone)},
77
- )
78
- ).result
79
- if res is None:
80
- return []
81
- return [FtTrustTransaction(**i) for i in res]
82
-
83
- async def get_near_transfers(self, phone: str) -> List[NearTrustTransaction]:
84
- """
85
- Get list of NEAR transfers to phone number
86
- :param phone: phone number
87
- :return: list of NEAR transfers
88
- """
89
- res = (
90
- await self._account.view_function(
91
- _PHONE_CONTRACT_ID,
92
- "get_transfers",
93
- {"phone": await self._get_phone_hex(phone)},
94
- )
95
- ).result
96
- if res is None:
97
- return []
98
- return [NearTrustTransaction(**i) for i in res]
99
-
100
- async def send_near_to_phone(
101
- self, phone: str, amount: float, comment: str = "", nowait: bool = False
102
- ):
103
- """
104
- Send NEAR to phone number. Receiver will get sms with link to claim tokens.
105
- :param phone: +X format phone number
106
- :param amount: number of NEAR which will be sent
107
- :param comment: any comment
108
- :param nowait if True, method will return before transaction is confirmed
109
- :return: transaction hash ot TransactionResult
110
- """
111
- if amount < 0.1:
112
- raise ValueError("Amount must be >= 0.1 NEAR")
113
- return await self._account.function_call(
114
- _PHONE_CONTRACT_ID,
115
- "send_near_to_phone",
116
- {"phone": await self._get_phone_hex(phone), "comment": comment},
117
- amount=int(amount * NEAR),
118
- nowait=nowait,
119
- gas=25 * TGAS,
120
- )
121
-
122
- async def send_ft_to_phone(
123
- self,
124
- ft: FtModel,
125
- phone: str,
126
- amount: float,
127
- comment: str = "",
128
- nowait: bool = False,
129
- ):
130
- """
131
- Send fungible token to phone number. Reciver will get sms with link to claim tokens.
132
- :param ft: Fungible token model
133
- :param phone: +X format phone number
134
- :param amount: number of FT which will be sent
135
- :param comment:
136
- :param nowait: if True, method will return before transaction is confirmed
137
- :return:
138
- """
139
- return await self._account.function_call(
140
- ft.contract_id,
141
- "ft_transfer_call",
142
- {
143
- "msg": await self._get_phone_hex(phone),
144
- "comment": comment,
145
- "receiver_id": _PHONE_CONTRACT_ID,
146
- "amount": str(int(amount * 10**ft.decimal)),
147
- },
148
- amount=1,
149
- gas=50 * TGAS,
150
- nowait=nowait,
151
- )
152
-
153
- async def cancel_near_transaction(self, phone: str, index: int):
154
- """
155
- Cancel NEAR transfer to phone number. Use index from get_near_transfers() method
156
- :param phone: phone number
157
- :param index: index in transaction list
158
- :return:
159
- """
160
- try:
161
- return await self._account.function_call(
162
- _PHONE_CONTRACT_ID,
163
- "cancel_near_transaction",
164
- {"phone": await self._get_phone_hex(phone), "index": index},
165
- amount=1,
166
- )
167
- except FunctionCallError as e:
168
- if "`None` value" in str(e.error):
169
- raise ValueError(f"Transaction with index {index} not found")
170
- raise e
171
-
172
- async def cancel_ft_transaction(self, phone: str, index: int):
173
- """
174
- Cancel fungible token transfer to phone number. Use index from get_ft_transfers() method
175
- :param phone: phone number
176
- :param index: index in transaction list
177
- :return:
178
- """
179
- try:
180
- return await self._account.function_call(
181
- _PHONE_CONTRACT_ID,
182
- "cancel_ft_transaction",
183
- {"phone": await self._get_phone_hex(phone), "index": index},
184
- amount=1,
185
- )
186
- except FunctionCallError as e:
187
- if "`None` value" in str(e):
188
- raise ValueError(f"Transaction with index {index} not found")
189
- raise e
@@ -1,2 +0,0 @@
1
- class RequestLimitError(Exception):
2
- pass
@@ -1,18 +0,0 @@
1
- from pydantic import BaseModel
2
-
3
-
4
- class NearTrustTransaction(BaseModel):
5
- from_account_id: str
6
- amount: str
7
-
8
-
9
- class FtTrustTransaction(BaseModel):
10
- from_account_id: str
11
- ft_contract_id: str
12
- ft_amount: str
13
-
14
-
15
- class NftTrustTransaction(BaseModel):
16
- from_account_id: str
17
- nft_contract_id: str
18
- nft_token_id: str