Pyhmy
A Python library for interacting and working with the harmony blockchain.
Install / Use
/learn @harmony-one/PyhmyREADME
Pyhmy - Harmony's python utilities
This library only supports Python 3.6+
A Python library for interacting and working the Harmony blockchain and related codebases.
Full documentation is located on Harmony's GitBook (in progress).
Installation
pip install pyhmy
On MacOS: Make sure you have Python3 installed, and use python3 to install pyhmy
sudo pip3 install pathlib
sudo pip3 install pyhmy
Development
Clone the repository and then run the following:
make install
Running tests
Before you can run tests, you need the python dependencies (make install), docker and go installed to quickly run a local blockchain with staking enabled (detailed instructions here):
mkdir -p $(go env GOPATH)/src/github.com/harmony-one
cd $(go env GOPATH)/src/github.com/harmony-one
git clone https://github.com/harmony-one/mcl.git
git clone https://github.com/harmony-one/bls.git
git clone https://github.com/harmony-one/harmony.git
cd harmony
make clean debug-multi-bls-multi-ext-node
Once the terminal displays a couple of Started server lines, use another shell to run the following tests
make test
Or directly with pytest (reference here for more info):
pytest tests
Releasing
You can release this library with the following command (assuming you have the credentials to upload):
make release
Usage
test_net = 'https://api.s0.b.hmny.io' # this is shard 0
test_net_shard_1 = 'https://api.s1.b.hmny.io'
test_address = 'one18t4yj4fuutj83uwqckkvxp9gfa0568uc48ggj7'
main_net = 'https://rpc.s0.t.hmny.io'
main_net_shard_1 = 'https://rpc.s1.t.hmny.io'
utilities
Address conversion
from pyhmy import util
hex_addr = util.convert_one_to_hex('one155jp2y76nazx8uw5sa94fr0m4s5aj8e5xm6fu3')
one_addr = util.convert_hex_to_one('0xA5241513DA9F4463F1d4874b548dFBAC29D91f34')
Ether / Wei conversion
from pyhmy import numbers
one_ether_in_wei = numbers.convert_one_to_atto(1) # as a decimal.Decimal
wei_to_ether = numbers.convert_atto_to_one(int(1e18))
accounts
from pyhmy import account
Balance / account related information
balance = account.get_balance(test_address, endpoint=test_net) # on shard 0, in ATTO
total_balance = account.get_total_balance(test_address, endpoint=test_net) # on all shards, in ATTO
balance_by_shard = account.get_balance_on_all_shards(test_address, endpoint=test_net) # list of dictionaries with shard and balance as keys
genesis_balance = account.get_balance_by_block(test_address, block_num=0, endpoint=test_net)
latest_balance = account.get_balance_by_block(test_address, block_num='latest', endpoint=test_net) # block_num can be a string 'latest', or 'pending', if implemented at the RPC level
account_nonce = account.get_account_nonce(test_address, block_num='latest', endpoint=test_net)
Transaction counts
tx_count = account.get_transactions_count(test_address, tx_type='ALL', endpoint=test_net)
sent_tx_count = account.get_transactions_count(test_address, tx_type='SENT', endpoint=test_net)
received_tx_count = account.get_transactions_count(test_address, tx_type='RECEIVED', endpoint=test_net)
legacy_tx_count = account.get_transaction_count(test_address, block_num='latest', endpoint=test_net) # API is legacy
legacy_tx_count_pending = account.get_transaction_count(test_address, block_num='pending', endpoint=test_net)
Staking transaction counts
stx_count = account.get_staking_transactions_count(test_address, tx_type='ALL', endpoint=test_net)
sent_stx_count = account.get_staking_transactions_count(test_address, tx_type='SENT', endpoint=test_net)
received_stx_count = account.get_staking_transactions_count(test_address, tx_type='RECEIVED', endpoint=test_net)
Transaction history
To get a list of hashes, use include_full_tx=False
first_100_tx_hashes = account.get_transaction_history(test_address, page=0, page_size=100, include_full_tx=False, endpoint=test_net)
To get the next 100 transactions, change the page
next_100_tx_hashes = account.get_transaction_history(test_address, page=1, page_size=100, include_full_tx=False, endpoint=test_net)
To get a list of full transaction details, use include_full_tx=True (see get_transaction_by_hash for the reply structure
first_3_full_tx = account.get_transaction_history(test_address, page=0, page_size=3, include_full_tx=True, endpoint=test_net)
To get newest transactions, use order='DESC'
last_3_full_tx = account.get_transaction_history(test_address, page=0, page_size=3, include_full_tx=True, order='DESC', endpoint=test_net)
To change the transaction type (SENT / RECEIVED / ALL), pass the tx_type parameter
first_100_received_tx_hashes = account.get_transaction_history(test_address, page=0, page_size=100, include_full_tx=False, tx_type='RECEIVED', endpoint=test_net)
Staking transaction history
To get a list of staking hashes, use include_full_tx=False
first_100_stx_hashes = account.get_staking_transaction_history(test_address, page=0, page_size=100, include_full_tx=False, endpoint=test_net)
To get the next 100 staking transactions, change the page
next_100_stx_hashes = account.get_staking_transaction_history(test_address, page=1, page_size=100, include_full_tx=False, endpoint=test_net)
To get a list of full staking transaction details, use include_full_tx=True (see get_transaction_by_hash for the reply structure
first_3_full_stx = account.get_staking_transaction_history(test_address, page=0, page_size=3, include_full_tx=True, endpoint=test_net)
To get newest staking transactions, use order='DESC'
last_3_full_stx = account.get_staking_transaction_history(test_address, page=0, page_size=3, include_full_tx=True, order='DESC', endpoint=test_net)
To change the staking transaction type (SENT / RECEIVED / ALL), pass the tx_type parameter
first_100_received_stx_hashes = account.get_staking_transaction_history(test_address, page=0, page_size=100, include_full_tx=False, tx_type='RECEIVED', endpoint=test_net)
Blockchain
from pyhmy import blockchain
from decimal import Decimal
Node / network information
chain_id = blockchain.chain_id(test_net) # chain type, for example, mainnet or testnet
node_metadata = blockchain.get_node_metadata(test_net) # metadata about the endpoint
peer_info = blockchain.get_peer_info(test_net) # peers of the endpoint
protocol_version = blockchain.protocol_version(test_net) # protocol version being used
num_peers = blockchain.get_num_peers(test_net) # number of peers of the endpoin
version = blockchain.get_version(test_net) # EVM chain id, https://chainid.network
is_node_in_sync = blockchain.in_sync(test_net) # whether the node is in sync (not out of sync or not syncing)
is_beacon_in_sync = blockchain.beacon_in_sync(test_net) # whether the beacon node is in sync
prestaking_epoch_number = blockchain.get_prestaking_epoch(test_net)
staking_epoch_number = blockchain.get_staking_epoch(test_net)
Sharding information
shard_id = blockchain.get_shard(test_net) # get shard id of the endpoint
sharding_structure = blockchain.get_sharding_structure(test_net) # list of dictionaries, each representing a shard
last_cross_links = blockchain.get_last_cross_links(test_net) # list of dictionaries for each shard except test_net
Current network status
leader_address = blockchain.get_leader_address(test_net)
is_last_block = blockchain.is_last_block(block_num=0, test_net)
last_block_of_epoch5 = blockchain.epoch_last_block(block_num=5, test_net)
circulating_supply = Decimal(blockchain.get_circulating_supply(test_net))
premined = blockchain.get_total_supply(test_net) # should be None?
current_block_num = blockchain.get_block_number(test_net)
current_epoch = blockchain.get_current_epoch(test_net)
gas_price = blockchain.get_gas_price(test_net) # this returns 1 always
Block headers
latest_header = blockchain.get_latest_header(test_net) # header contains hash, number, cross links, signature, time, etc (see get_latest_header for a full list)
latest_hash = latest_header['blockHash']
latest_number = latest_header['blockNumber']
previous_header = blockchain.get_header_by_number(latest_number-1, test_net)
chain_headers = blockchain.get_latest_chain_headers(test_net_shard_1) # chain headers by beacon and shard
Blocks
By block number
Fetch the barebones information about the block as a dictionary
latest_block = blockchain.get_block_by_number(block_num='latest', endpoint=test_net)
Fetch a block with full information (full_tx=True) for each transaction in the block
block = blockchain.get_block_by_number(block_num=9017724, full_tx=True, include_tx=True, include_staking_tx=True, endpoint=test_net)
Fetch a block and only staking transactions (include_tx=False, include_staking_tx=True) for the block
block = blockchain.get_block_by_number(block_num='latest', include_tx=False, include_staking_tx=True, endpoint=test_net)
Fetch block signer addresses (include_signers=True) as a list
signers = blockchain.get_block_by_number(block_num=9017724, include_signers=True, endpoint=test_net)['signers']
Or, alternatively, use the direct get_block_signers method:
signers = blockchain.get_block_signers(block_num=9017724, endpoint=test_net)
Fetch the public keys for signers
signers_keys = blockchain.get_block_signers_keys(block_num=9017724, endpoint=test_net)
Check if an address is a signer for a block
is_block_signer = blockchain.is_block_signer(block_num=9017724, address='one1yc06ghr2p8xn
