A Python library for interacting and working with the Woop blockchain.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
pywiki/pyhmy/account.py

364 lines
9.9 KiB

from .rpc.request import (
rpc_request
)
from .rpc.exceptions import (
RPCError,
RequestsError,
RequestsTimeoutError
)
from .exceptions import (
InvalidRPCReplyError
)
from .blockchain import (
get_sharding_structure
)
_default_endpoint = 'http://localhost:9500'
_default_timeout = 30
_address_length = 42
# TODO: Implement real address validity check
def is_valid_address(address) -> bool:
"""
Check if given string is valid one address
Parameters
----------
address: str
String to check if valid one address
Returns
-------
bool
Is valid address
"""
if not address.startswith('one1') and len(address) != _address_length:
return False
return True
def get_balance(address, endpoint=_default_endpoint, timeout=_default_timeout) -> int:
"""
Get current account balance
Parameters
----------
address: str
Address to get balance for
endpoint: :obj:`str`, optional
Endpoint to send request to
timeout: :obj:`int`, optional
Timeout in seconds
Returns
-------
int
Account balance in ATTO
Raises
------
InvalidRPCReplyError
If received unknown result from endpoint
"""
method = 'hmy_getBalance'
params = [
address,
'latest'
]
balance = rpc_request(method, params=params, endpoint=endpoint, timeout=timeout)['result']
try:
return int(balance, 16)
except TypeError as e:
raise InvalidRPCReplyError(method, endpoint) from e
def get_balance_by_block(address, block_num, endpoint=_default_endpoint, timeout=_default_timeout) -> int:
"""
Get account balance for address at a given block number
Parameters
----------
address: str
Address to get balance for
block_num: int
Block to get balance at
endpoint: :obj:`str`, optional
Endpoint to send request to
timeout: :obj:`int`, optional
Timeout in seconds
Returns
-------
int
Account balance in ATTO
Raises
------
InvalidRPCReplyError
If received unknown result from endpoint
"""
method = 'hmy_getBalanceByBlockNumber'
params = [
address,
str(hex(block_num))
]
balance = rpc_request(method, params=params, endpoint=endpoint, timeout=timeout)['result']
try:
return int(balance, 16)
except TypeError as e:
raise InvalidRPCReplyError(method, endpoint) from e
def get_account_nonce(address, true_nonce=False, endpoint=_default_endpoint, timeout=_default_timeout) -> int:
"""
Get the account nonce
Parameters
----------
address: str
Address to get transaction count for
true_nonce: :obj:`bool`, optional
True to get on-chain nonce
False to get nonce based on pending transaction pool
endpoint: :obj:`str`, optional
Endpoint to send request to
timeout: :obj:`int`, optional
Timeout in seconds
Returns
-------
int
Account nonce
Raises
------
InvalidRPCReplyError
If received unknown result from endpoint
"""
method = 'hmy_getTransactionCount'
params = [
address,
'latest' if true_nonce else 'pending'
]
nonce = rpc_request(method, params=params, endpoint=endpoint, timeout=timeout)['result']
try:
return int(nonce, 16)
except TypeError as e:
raise InvalidRPCReplyError(method, endpoint) from e
def get_transaction_count(address, endpoint=_default_endpoint, timeout=_default_timeout) -> int:
"""
Get number of transactions & staking transactions sent by an account
Parameters
----------
address: str
Address to get transaction count for
endpoint: :obj:`str`, optional
Endpoint to send request to
timeout: :obj:`int`, optional
Timeout in seconds
Returns
-------
int
Number of transactions sent by the account
See also
--------
get_account_nonce
"""
return get_account_nonce(address, true_nonce=True, endpoint=endpoint, timeout=timeout)
def get_transaction_history(address, page=0, page_size=1000, include_full_tx=False, tx_type='ALL',
order='ASC', endpoint=_default_endpoint, timeout=_default_timeout
) -> list:
"""
Get list of transactions sent and/or received by the account
Parameters
----------
address: str
Address to get transaction history for
page: :obj:`int`, optional
Page to request for pagination
page_size: :obj:`int`, optional
Size of page for pagination
include_full_tx: :obj:`bool`, optional
True to include full transaction data
False to just get the transaction hash
tx_type: :obj:`str`, optional
'ALL' to get all transactions send & received by the address
'SENT' to get all transactions sent by the address
'RECEIVED' to get all transactions received by the address
order: :obj:`str`, optional
'ASC' to sort transactions in ascending order based on timestamp
'DESC' to sort transactions in descending order based on timestamp
endpoint: :obj:`str`, optional
Endpoint to send request to
timeout: :obj:`int`, optional
Timeout in seconds
Returns
-------
list
# TODO: Add link to reference RPC documentation
Raises
------
InvalidRPCReplyError
If received unknown result from endpoint
"""
params = [
{
'address': address,
'pageIndex': page,
'pageSize': page_size,
'fullTx': include_full_tx,
'txType': tx_type,
'order': order
}
]
method = 'hmy_getTransactionsHistory'
tx_history = rpc_request(method, params=params, endpoint=endpoint, timeout=timeout)
try:
return tx_history['result']['transactions']
except KeyError as e:
raise InvalidRPCReplyError(method, endpoint) from e
def get_staking_transaction_history(address, page=0, page_size=1000, include_full_tx=False, tx_type='ALL',
order='ASC', endpoint=_default_endpoint, timeout=_default_timeout
) -> list:
"""
Get list of staking transactions sent by the account
Parameters
----------
address: str
Address to get staking transaction history for
page: :obj:`int`, optional
Page to request for pagination
page-size: :obj:`int`, optional
Size of page for pagination
include_full_tx: :obj:`bool`, optional
True to include full staking transaction data
False to just get the staking transaction hash
tx_type: :obj:`str`, optional
'ALL' to get all staking transactions
order: :obj:`str`, optional
'ASC' to sort transactions in ascending order based on timestamp
'DESC' to sort transactions in descending order based on timestamp
endpoint: :obj:`str`, optional
Endpoint to send request to
timeout: :obj:`int`, optional
Timeout in seconds
Returns
-------
list
# TODO: Add link to reference RPC documentation
Raises
------
InvalidRPCReplyError
If received unknown result from endpoint
"""
params = [
{
'address': address,
'pageIndex': page,
'pageSize': page_size,
'fullTx': include_full_tx,
'txType': tx_type,
'order': order
}
]
# Using v2 API, because getStakingTransactionHistory not implemented in v1
method = 'hmyv2_getStakingTransactionsHistory'
stx_history = rpc_request(method, params=params, endpoint=endpoint, timeout=timeout)['result']
try:
return stx_history['staking_transactions']
except KeyError as e:
raise InvalidRPCReplyError(method, endpoint) from e
def get_balance_on_all_shards(address, skip_error=True, endpoint=_default_endpoint, timeout=_default_timeout) -> list:
"""
Get current account balance in all shards & optionally report errors getting account balance for a shard
Parameters
----------
address: str
Address to get balance for
skip_error: :obj:`bool`, optional
True to ignore errors getting balance for shard
False to include errors when getting balance for shard
endpoint: :obj:`str`, optional
Endpoint to send request to
timeout: :obj:`int`, optional
Timeout in seconds per request
Returns
-------
list
Account balance per shard in ATTO
Example reply:
[
{
'shard': 0,
'balance': 0,
},
...
]
"""
balances = []
sharding_structure = get_sharding_structure(endpoint=endpoint, timeout=timeout)
for shard in sharding_structure:
try:
balances.append({
'shard': shard['shardID'],
'balance': get_balance(address, endpoint=shard['http'], timeout=timeout)
})
except (KeyError, RPCError, RequestsError, RequestsTimeoutError):
if not skip_error:
balances.append({
'shard': shard['shardID'],
'balance': None
})
return balances
def get_total_balance(address, endpoint=_default_endpoint, timeout=_default_timeout) -> int:
"""
Get total account balance on all shards
Parameters
----------
address: str
Address to get balance for
endpoint: :obj:`str`, optional
Endpoint to send request to
timeout: :obj:`int`, optional
Timeout in seconds per request
Returns
-------
int
Total account balance in ATTO
Raises
------
RuntimeError
If error occurred getting account balance for a shard
"""
try:
balances = get_balance_on_all_shards(address, skip_error=False, endpoint=endpoint, timeout=timeout)
return sum(b['balance'] for b in balances)
except TypeError as e:
raise RuntimeError from e