From 2b1a69493c4f8c9a987756f400a64b3c3ab2d392 Mon Sep 17 00:00:00 2001 From: Doan Bui <bxdoan93@gmail.com> Date: Thu, 15 Dec 2022 17:28:24 +0700 Subject: [PATCH] fix some typo and create utils (#4) * fix some typo and create utils * add constants * add constants * change import code style --- src/pynear/account.py | 51 +++++++++++++------------- src/pynear/constants.py | 5 +++ src/pynear/dapps/phone/async_client.py | 2 +- src/pynear/providers.py | 6 ++- src/pynear/utils.py | 9 +++++ 5 files changed, 45 insertions(+), 28 deletions(-) create mode 100644 src/pynear/constants.py create mode 100644 src/pynear/utils.py diff --git a/src/pynear/account.py b/src/pynear/account.py index 3dad99c..43e5da8 100644 --- a/src/pynear/account.py +++ b/src/pynear/account.py @@ -1,5 +1,4 @@ import asyncio -import datetime import json from typing import List, Union @@ -8,6 +7,8 @@ from pyonear.crypto import InMemorySigner, ED25519SecretKey from pyonear.transaction import Action +from pynear import utils +from pynear import constants from pynear.dapps.ft.async_client import FT from pynear.dapps.phone.async_client import Phone from pynear.exceptions.exceptions import ( @@ -34,7 +35,6 @@ from pynear.providers import JsonProvider from pynear import transactions -DEFAULT_ATTACHED_GAS = 200000000000000 _ERROR_TYPE_TO_EXCEPTION = { @@ -70,7 +70,7 @@ class Account(object): chain_id: str = "mainnet" def __init__( - self, account_id, private_key, rpc_addr="https://rpc.mainnet.near.org" + self, account_id, private_key, rpc_addr=constants.RPC_MAINNET ): if isinstance(private_key, str): private_key = base58.b58decode(private_key.replace("ed25519:", "")) @@ -93,15 +93,15 @@ async def startup(self): async def _update_last_block_hash(self): """ - Update last block hash& If it's older than 100 block before, transaction will fail + Update last block hash& If it's older than 50 block before, transaction will fail :return: last block hash """ - if self._latest_block_hash_ts + 50 > datetime.datetime.utcnow().timestamp(): + if self._latest_block_hash_ts + 50 > utils.timestamp(): return self._latest_block_hash = (await self._provider.get_status())["sync_info"][ "latest_block_hash" ] - self._latest_block_hash_ts = datetime.datetime.utcnow().timestamp() + self._latest_block_hash_ts = utils.timestamp() async def _sign_and_submit_tx( self, receiver_id, actions: List[Action], nowait=False @@ -119,7 +119,7 @@ async def _sign_and_submit_tx( await self._update_last_block_hash() block_hash = base58.b58decode(self._latest_block_hash.encode("utf8")) - serialzed_tx = transactions.sign_and_serialize_transaction( + serialized_tx = transactions.sign_and_serialize_transaction( receiver_id, access_key.nonce + 1, actions, @@ -127,9 +127,9 @@ async def _sign_and_submit_tx( self._signer, ) if nowait: - return await self._provider.send_tx(serialzed_tx) + return await self._provider.send_tx(serialized_tx) - result = await self._provider.send_tx_and_wait(serialzed_tx) + result = await self._provider.send_tx_and_wait(serialized_tx) if "Failure" in result["status"]: error_type, args = list( result["status"]["Failure"]["ActionError"]["kind"].items() @@ -139,15 +139,15 @@ async def _sign_and_submit_tx( return TransactionResult(**result) @property - def account_id(self): + def account_id(self) -> AccountId: return self._account_id @property - def signer(self): + def signer(self) -> InMemorySigner: return self._signer @property - def provider(self): + def provider(self) -> JsonProvider: return self._provider async def get_access_key(self) -> AccountAccessKey: @@ -171,15 +171,16 @@ async def get_access_key_list(self, account_id: str = None) -> List[PublicKey]: account_id = self._account_id resp = await self._provider.get_access_key_list(account_id) result = [] - for key in resp["keys"]: - result.append(PublicKey.build(key)) + if "keys" in resp and isinstance(resp["keys"], list): + for key in resp["keys"]: + result.append(PublicKey(**key)) return result - async def fetch_state(self): + async def fetch_state(self) -> dict: """Fetch state for given account.""" return await self._provider.get_account(self._account_id) - async def send_money(self, account_id: str, amount: int, nowait=False): + async def send_money(self, account_id: str, amount: int, nowait: bool = False) -> TransactionResult: """ Send money to account_id :param account_id: receiver account id @@ -196,17 +197,17 @@ async def function_call( contract_id: str, method_name: str, args: dict, - gas=DEFAULT_ATTACHED_GAS, - amount=0, - nowait=False, + gas: int = constants.DEFAULT_ATTACHED_GAS, + amount: int = 0, + nowait: bool = False, ): """ Call function on smart contract - :param contract_id: smart contract adress + :param contract_id: smart contract address :param method_name: call method name :param args: json params for method - :param gas: amount of attachment gas - :param amount: amount of attachment NEAR + :param gas: amount of attachment gas. Default is 200000000000000 + :param amount: amount of attachment NEAR, Default is 0 :param nowait: if nowait is True, return transaction hash, else wait execution :return: transaction hash or TransactionResult """ @@ -225,7 +226,7 @@ async def create_account( nowait=False, ): """ - Create new account in subdomian of current account. For example, if current account is "test.near", + Create new account in subdomain of current account. For example, if current account is "test.near", you can create "wwww.test.near" :param account_id: new account id :param public_key: add public key to new account @@ -245,7 +246,7 @@ async def add_public_key( public_key: Union[str, bytes], receiver_id: str, method_names: List[str] = None, - allowance: int = 25000000000000000000000, + allowance: int = constants.ALLOWANCE, nowait=False, ): """ @@ -268,7 +269,7 @@ async def add_public_key( async def add_full_access_public_key( self, public_key: Union[str, bytes], nowait=False - ): + ) -> TransactionResult: """ Add public key to account with full access :param public_key: public_key to add diff --git a/src/pynear/constants.py b/src/pynear/constants.py new file mode 100644 index 0000000..278bd30 --- /dev/null +++ b/src/pynear/constants.py @@ -0,0 +1,5 @@ + +TIMEOUT_WAIT_RPC = 60 +DEFAULT_ATTACHED_GAS = 200000000000000 +ALLOWANCE = 25000000000000000000000 +RPC_MAINNET = "https://rpc.mainnet.near.org" \ No newline at end of file diff --git a/src/pynear/dapps/phone/async_client.py b/src/pynear/dapps/phone/async_client.py index 34a17af..1ffe816 100644 --- a/src/pynear/dapps/phone/async_client.py +++ b/src/pynear/dapps/phone/async_client.py @@ -97,7 +97,7 @@ async def send_near_to_phone( self, phone: str, amount: float, comment: str = "", nowait: bool = False ): """ - Send NEAR to phone number. Reciver will get sms with link to claim tokens. + Send NEAR to phone number. Receiver will get sms with link to claim tokens. :param phone: +X format phone number :param amount: number of NEAR which will be sent :param comment: any comment diff --git a/src/pynear/providers.py b/src/pynear/providers.py index 14930b4..1419cf8 100644 --- a/src/pynear/providers.py +++ b/src/pynear/providers.py @@ -3,7 +3,7 @@ import aiohttp from aiohttp import ClientResponseError, ClientConnectorError - +from pynear import constants from pynear.exceptions.exceptions import RpcNotAvailableError from pynear.exceptions.provider import ( UnknownBlockError, @@ -21,6 +21,7 @@ ERROR_CODE_TO_EXCEPTION, ) + _ERROR_CODE_TO_EXCEPTION = { "UNKNOWN_BLOCK": UnknownBlockError, "INVALID_ACCOUNT": InvalidAccount, @@ -96,10 +97,11 @@ async def send_tx(self, signed_tx: str): "broadcast_tx_async", [signed_tx] ) - async def send_tx_and_wait(self, signed_tx: str, timeout=60): + async def send_tx_and_wait(self, signed_tx: str, timeout: int = constants.TIMEOUT_WAIT_RPC): """ Send a signed transaction to the network and wait for it to be included in a block. :param signed_tx: base64 encoded signed transaction + :param timeout: timeout in seconds wait for RPC response :return: """ return await self.json_rpc( diff --git a/src/pynear/utils.py b/src/pynear/utils.py new file mode 100644 index 0000000..7eedbbb --- /dev/null +++ b/src/pynear/utils.py @@ -0,0 +1,9 @@ +from datetime import datetime + + +def utcnow(): + return datetime.utcnow() + + +def timestamp(): + return utcnow().timestamp() \ No newline at end of file