Hive Developer Portal
Delegate Power
Delegate power to other users using Hive Signer or Client-side signing.
Full, runnable src of Delegate Power can be downloaded as part of: tutorials/python (or download just this tutorial: devportal-master-tutorials-python-27_delegate_power.zip).
In this tutorial we show you how to delegate a portion of an accounts available HIVE Power on the Hive blockchain using the beem library.
Intro
The beem library has a built-in function to transmit transactions to the blockchain. We are using the delegate_vesting_shares
method found within the account instance. When you delegate power you make a portion of your HIVE Power available to another user. This can empower an application, author, or curator to make higher votes. Before we do the delegation, we use the Account
module to check the current HIVE Power balance of the account to see what is available. This is not strictly necessary but adds to the usability of the process. It should be noted that when a delegation is cancelled the HIVE Power will only be available again after 7 days.
Also see:
Steps
- App setup - Library install and import. Connection to testnet
- User information and Hive node - Input user information and connection to Hive node
- Check balance - Check current VESTS balance of user account
- Delegation amount and commit - Input delegation amount and commit to blockchain
1. App setup
In this tutorial we use the following packages:
beem
- hive library and interaction with Blockchainpick
- helps select the query type interactively
We import the libraries and connect to the testnet
.
from pick import pick
import getpass
from beem import Hive
from beem.account import Account
from beem.amount import Amount
Because this tutorial alters the blockchain we connect to a testnet so we don’t create spam on the production server.
2. User information and Hive node
We require the private active key
of the user in order for the transaction to be committed to the blockchain. This is why we are using a testnet. The values are supplied via the terminal/console before we initialize the beem class. We also check if the user name provided is active on the chain.
# capture user information
account = input('Enter username: ')
wif_active_key = getpass.getpass('Enter private ACTIVE key: ')
# node_url = 'https://testnet.openhive.network' # Public Testnet
node_url = 'http://127.0.0.1:8090' # Local Testnet
# connect node and private active key
client = Hive(node_url, keys=[wif_active_key])
# check valid user
account = Account(account, blockchain_instance=client)
3. Check balance
In order to give the user enough information to make the delegation we check the current HIVE Power balance of the account using the Account
module. We also display a list of currently active delegations should the user choose to remove a delegation. You can refer to tutorial Get Delegations by User to see how this is done.
balance = account['balance']
symbol = balance.symbol
# we need high precision because VESTS
denom = 1e6
delegated_vests = account['delegated_vesting_shares']
vesting_shares = account['vesting_shares']
vesting_symbol = vesting_shares.symbol
to_withdraw_vests = float(account['to_withdraw']) / denom
withdrawn_vests = float(account['withdrawn']) / denom
Here, we are gathering the current account details.
dgpo = client.get_dynamic_global_properties()
total_vesting_fund_hive = Amount(dgpo['total_vesting_fund_hive']).amount
total_vesting_shares_mvest = Amount(dgpo['total_vesting_shares']).amount / denom
base_per_mvest = total_vesting_fund_hive / total_vesting_shares_mvest
This block will help us convert VESTS to HIVE Power for display purposes. Best practice is to always allow the end-user to work with HIVE Power, not raw VESTS.
available_vests = (vesting_shares.amount - delegated_vests.amount - ((to_withdraw_vests - withdrawn_vests)))
available_base = (available_vests / denom) * base_per_mvest
The available vesting shares to delegate is not directly available from the user information and needs to be calculated. In order to find the total VESTS available to delegate we need to know how much is currently in power down, how much has been delegated and then the total amount of vesting shares. The values are assigned from the query directly as float
type to make the calculations a little simpler.
# display active delegations (refer to tutorial #29_get_delegations_by_user)
delegations = account.get_vesting_delegations()
if len(delegations) == 0:
print('No active delegations')
else:
print('Current delegations:')
for delegation in delegations:
delegated_vests = float(delegation['vesting_shares']['amount']) / denom
delegated_base = (delegated_vests / denom) * base_per_mvest
print('\t' + delegation['delegatee'] + ': ' + format(delegated_base, '.3f') + ' ' + symbol)
print('\n' + 'Available ' + symbol + ' Power: ' + format(available_base, '.3f') + ' ' + symbol)
input('Press enter to continue' + '\n')
The result of the query is displayed in the console/terminal.
4. Delegation amount and commit
Both the amount
and the delegatee
parameters are assigned via input from the terminal/console. The user is given the option to delegate power to or remove a currently active delegation from another user. We also check the delegatee
to make sure it’s a valid account name.
# choice of action
title = ('Please choose action')
options = ['DELEGATE POWER', 'UN-DELEGATE POWER', 'CANCEL']
# get index and selected permission choice
option, index = pick(options, title)
if (option == 'CANCEL'):
print('operation cancelled')
exit()
# get account to authorise and check if valid
delegatee = input('Please enter the account name to ADD / REMOVE delegation: ')
delegatee = Account(delegatee, blockchain_instance=client)
Any amount of HIVE Power delegated to a user will overwrite the amount of HIVE Power currently delegated to that user. This means that to cancel a delegation we transmit to the blockchain a value of zero. The inputs and function execution is based on the users choice.
if (option == 'DELEGATE POWER'):
amount = float(input('Please enter the amount of ' + symbol + ' you would like to delegate: ') or '0')
amount_vests = (amount * denom) / base_per_mvest
print(format(amount, '.3f') + ' ' + symbol + ' (' + format(amount_vests, '.6f') + ' ' + vesting_symbol + ') will be delegated to ' + delegatee.name)
else:
amount_vests = 0
print('Removing delegated VESTS from ' + delegatee.name)
account.delegate_vesting_shares(delegatee.name, amount_vests)
print('Success.')
Note that if the user decides to delegate a specific amount, we capture the amount they intend to delegate as HIVE Power, then convert that amount to VESTS behind the scenes, in keeping with the principle of only interacting with the end user in terms of HIVE Power, which is the recommended best practice.
A confirmation of the transaction is displayed on the UI.
Final code:
from pick import pick
import getpass
from beem import Hive
from beem.account import Account
from beem.amount import Amount
# capture user information
account = input('Enter username: ')
wif_active_key = getpass.getpass('Enter private ACTIVE key: ')
# node_url = 'https://testnet.openhive.network' # Public Testnet
node_url = 'http://127.0.0.1:8090' # Local Testnet
# connect node and private active key
client = Hive(node_url, keys=[wif_active_key])
# check valid user
account = Account(account, blockchain_instance=client)
balance = account['balance']
symbol = balance.symbol
# we need high precision because VESTS
denom = 1e6
delegated_vests = account['delegated_vesting_shares']
vesting_shares = account['vesting_shares']
vesting_symbol = vesting_shares.symbol
to_withdraw_vests = float(account['to_withdraw']) / denom
withdrawn_vests = float(account['withdrawn']) / denom
dgpo = client.get_dynamic_global_properties()
total_vesting_fund_hive = Amount(dgpo['total_vesting_fund_hive']).amount
total_vesting_shares_mvest = Amount(dgpo['total_vesting_shares']).amount / denom
base_per_mvest = total_vesting_fund_hive / total_vesting_shares_mvest
available_vests = (vesting_shares.amount - delegated_vests.amount - ((to_withdraw_vests - withdrawn_vests)))
available_base = (available_vests / denom) * base_per_mvest
# display active delegations (refer to tutorial #29_get_delegations_by_user)
delegations = account.get_vesting_delegations()
if len(delegations) == 0:
print('No active delegations')
else:
print('Current delegations:')
for delegation in delegations:
delegated_vests = float(delegation['vesting_shares']['amount']) / denom
delegated_base = (delegated_vests / denom) * base_per_mvest
print('\t' + delegation['delegatee'] + ': ' + format(delegated_base, '.3f') + ' ' + symbol)
print('\n' + 'Available ' + symbol + ' Power: ' + format(available_base, '.3f') + ' ' + symbol)
input('Press enter to continue' + '\n')
# choice of action
title = ('Please choose action')
options = ['DELEGATE POWER', 'UN-DELEGATE POWER', 'CANCEL']
# get index and selected permission choice
option, index = pick(options, title)
if (option == 'CANCEL'):
print('operation cancelled')
exit()
# get account to authorise and check if valid
delegatee = input('Please enter the account name to ADD / REMOVE delegation: ')
delegatee = Account(delegatee, blockchain_instance=client)
if (option == 'DELEGATE POWER'):
amount = float(input('Please enter the amount of ' + symbol + ' you would like to delegate: ') or '0')
amount_vests = (amount * denom) / base_per_mvest
print(format(amount, '.3f') + ' ' + symbol + ' (' + format(amount_vests, '.6f') + ' ' + vesting_symbol + ') will be delegated to ' + delegatee.name)
else:
amount_vests = 0
print('Removing delegated VESTS from ' + delegatee.name)
account.delegate_vesting_shares(delegatee.name, amount_vests)
print('Success.')
To Run the tutorial
You can launch a local testnet, with port 8090 mapped locally to the docker container:
docker run -d -p 8090:8090 inertia/tintoy:latest
For details on running a local testnet, see: Setting Up a Testnet
- review dev requirements
git clone https://gitlab.syncad.com/hive/devportal.git
cd devportal/tutorials/python/27_delegate_power
pip install -r requirements.txt
python index.py
- After a few moments, you should see a prompt for input in terminal screen.