-
Notifications
You must be signed in to change notification settings - Fork 8
Sample Code for Exchange
We could create chain object like this:
# (TestNet)
import pyvsystems as pv
chain = pv.testnet_chain()
or
# (MainNet)
import pyvsystems as pv
m_wrapper = pv.create_api_wrapper('http://<full node ip>:9922')
chain = pv.Chain(chain_name='mainnet', chain_id='M', address_version=5, api_wrapper= m_wrapper)
Get transactions at block height
import pyvsystems as pv
chain = pv.testnet_chain()
print(chain.block(7937452))
Sample result:
{
'version': 1,
'timestamp': 1572342178010809171,
'reference': '4uaHS9eHGxxCEbBjmnfSmA6jFj1twJwHHbThocsp96dxhPWaEYi69rzm45fsghpidtpyTJQbKxiB9g7jSSe1Xcsu',
'SPOSConsensus': {
'mintTime': 1572342178000000000,
'mintBalance': 350858193805008
},
'resourcePricingData': {
'computation': 0,
'storage': 0,
'memory': 0,
'randomIO': 0,
'sequentialIO': 0
},
'TransactionMerkleRoot': 'CNMWF7N9HQUj22qW4oTDw8gpsuNh5ttaSuxctNf3nbtc',
'transactions': [
{
'type': 2,
'id': 'GwzuMwzn1iFBc6CogaxuNcxiiZXaaGeCSk5MCyCFj4Gi',
'fee': 10000000,
'feeScale': 100,
'timestamp': 1572342176723299072,
'proofs': [
{
'proofType': 'Curve25519',
'publicKey': '8PtidoeohqEyAyuqdBGudWfr7i1mUVrhNkQHNRfvaXvq',
'address': 'AU1vwC7C6CqV2q4oZYFNTbBJYNaakMBQyZV',
'signature': '67CUqt47cFWh38osURxn6wvLYW5hdmkPoVrddYH5HhRS2SDyDzVzihpffJEBqLEQwKmQeA7VJ5iWazBAmWGjcevS'
}
],
'recipient': 'AU18gPQDnhG3PqmdzLjUyRTM3t8bbffGPo8',
'amount': 100000000,
'attachment': '',
'status': 'Success',
'feeCharged': 10000000
},
{
'type': 5,
'id': 'Da2dRCXx6jUeV1ce1wVeEEAZhUUT6H89ywvf4vvThtpn',
'recipient': 'AUDRgBJjXM5zFMERzMML7pLPWikajTf8AKh',
'timestamp': 1572342178010809171,
'amount': 900000000,
'currentBlockHeight': 7937452,
'status': 'Success',
'feeCharged': 0
}
],
'generator': 'AUDRgBJjXM5zFMERzMML7pLPWikajTf8AKh',
'signature': 'SVeakw17ruk3v2DVRTcWYv35UHAE94R5BKBGHdBdR1rWiSNWMCgoDV4nuAfQMeoiDhaKyiWaYEVdq6fTiY6S7L4',
'fee': 10000000,
'blocksize': 500,
'height': 7937452,
'transaction count': 2
}
- Create new account with random seed
import pyvsystems as pv
from pyvsystems import Account
my_account = Account(chain=pv.testnet_chain())
print(my_account.get_info()) # show account info
print(my_account.privateKey) # show account private key
The account data is only stored in memory. It would be better to backup the private key into your database.
- Restore account by private key
import pyvsystems as pv
from pyvsystems import Account
pk = "28XHDwLzKaXRLspTBuxqurrah6apEfbJGh6Nnt914u2T"
restore_account = Account(chain=pv.testnet_chain(), private_key=pk)
- Get account V Coin balance
import pyvsystems as pv
from pyvsystems import Account
address = 'AU4mSZPtUwDD9sD3bT1TVBkgcZiq3SgE1n1'
my_account = Account(chain=pv.testnet_chain(), address=address)
print(my_account.get_info())
The detail explain of reponse JSON is:
{
'regular': 0, # regular balance
'available': 0, # available balance (regular - leased out)
'effective': 0, # effective balance (regular - leases out + leased in)
'mintingAverage': 0, # for minter used
'height': 643936,
'publicKey': '8PtidoeohqEyAyuqdBGudWfr7i1mUVrhNkQHNRfvaXvq',
'address': 'AU1vwC7C6CqV2q4oZYFNTbBJYNaakMBQyZV'
}
Among of these balances, available
is final balance which user could be used.
- Get Token info and account Token balance
import pyvsystems as pv
from pyvsystems import Account
from pyvsystems.contract import token_id_from_contract_id
custom_wrapper = pv.create_api_wrapper('https://test.v.systems/api')
chain = pv.Chain(chain_name='testnet', chain_id='T', address_version=5, api_wrapper=custom_wrapper)
account = Account(chain=chain, address='AU4mSZPtUwDD9sD3bT1TVBkgcZiq3SgE1n1')
contract_id = 'CFEBiQG3WtJNWFhtEj1CDDg6Wy7G6P7BPSy'
token_id = token_id_from_contract_id(contract_id, 0)
print("token_id: ", token_id)
print("token balance: ", account.token_balance(token_id))
Sample result:
token_id: TWurhe6uRbuUw566dKm89Jrc9whSkUMHSjNYtFEJn
token balance: 97675600000000
For example, send V Coins to address "AU18gPQDnhG3PqmdzLjUyRTM3t8bbffGPo8" (The default transaction fee is 0.1 VSYS, which is minimum transaction fee. fee_scale should be 100.)
import pyvsystems as pv
from pyvsystems import Account
if __name__ == "__main__":
pk = "28XHDwLzKaXRLspTBuxqurrah6apEfbJGh6Nnt914u2T"
my_account = Account(chain=pv.testnet_chain(), private_key=pk)
print(my_account.get_info())
recipient_address = "AU18gPQDnhG3PqmdzLjUyRTM3t8bbffGPo8"
recipient = Account(chain=chain, address=recipient_address)
# send payment (100000000 = 1 VSYS)
amount = 100000000
# For hot wallet sending transaction
resp = my_account.send_payment(recipient, amount=amount)
print(resp)
# For cold wallet signing transaction
pv.set_offline()
resp = my_account.send_payment(recipient, amount=amount)
print(resp)
Sample result:
{
'type': 2,
'id': 'GwzuMwzn1iFBc6CogaxuNcxiiZXaaGeCSk5MCyCFj4Gi',
'fee': 10000000,
'feeScale': 100,
'timestamp': 1572342176723299072,
'proofs': [
{
'proofType': 'Curve25519',
'publicKey': '8PtidoeohqEyAyuqdBGudWfr7i1mUVrhNkQHNRfvaXvq',
'address': 'AU1vwC7C6CqV2q4oZYFNTbBJYNaakMBQyZV',
'signature': '67CUqt47cFWh38osURxn6wvLYW5hdmkPoVrddYH5HhRS2SDyDzVzihpffJEBqLEQwKmQeA7VJ5iWazBAmWGjcevS'
}
],
'recipient': 'AU18gPQDnhG3PqmdzLjUyRTM3t8bbffGPo8',
'amount': 100000000,
'attachment': ''
}
import pyvsystems as pv
from pyvsystems import Account
from pyvsystems.contract_helper import *
token_without_split_helper = TokenWithoutSplitContractHelper()
token_with_split_helper = TokenWithSplitContractHelper()
SEND_NORMAL_TYPE_TOKEN_FUNC_INDEX = token_without_split_helper.send_function_index
SEND_SPLIT_TYPE_TOKEN_FUNC_INDEX = token_with_split_helper.send_function_index
# Known token info should store in DB
known_token_info = {
"CFEBiQG3WtJNWFhtEj1CDDg6Wy7G6P7BPSy": {
"token_id": "TWurhe6uRbuUw566dKm89Jrc9whSkUMHSjNYtFEJn",
"token_name": "Token A",
"contract_type": "TokenContract",
"unity": 100000000
},
"CF89wmAjkThqK4KzxSBYjeWe2mKaF61vzfF": {
"token_id": "TWuBEsV7iRc7qzZbeM2BWU4R5PhTWVBBbc6wdfQBs",
"token_name": "Token B",
"contract_type": "TokenContractWithSplit",
"unity": 1000000
}
}
def get_send_function_index(contract_id):
if known_token_info.get(contract_id):
if known_token_info[contract_id]["contract_type"] == "TokenContract":
return SEND_NORMAL_TYPE_TOKEN_FUNC_INDEX
elif known_token_info[contract_id]["contract_type"] == "TokenContractWithSplit":
return SEND_SPLIT_TYPE_TOKEN_FUNC_INDEX
return None
def send_data_stack_gen(contract_id, recipient, amount):
if known_token_info.get(contract_id):
if known_token_info[contract_id]["contract_type"] == "TokenContract":
return token_without_split_helper.send_data_stack_generator(recipient, amount)
elif known_token_info[contract_id]["contract_type"] == "TokenContractWithSplit":
return token_with_split_helper.send_data_stack_generator(recipient, amount)
return None
def send_token(account, contract_id, amount, recipient):
function_id = get_send_function_index(contract_id)
send_data = send_data_stack_gen(contract_id, recipient, amount)
info = account.execute_contract(contract_id, function_id, send_data)
return info
if __name__ == "__main__":
chain = pv.testnet_chain()
pk = "XXXXXXXXXXX"
contract_id = "CFEBiQG3WtJNWFhtEj1CDDg6Wy7G6P7BPSy"
my_account = Account(chain=chain, private_key=pk)
recipient = "AU18gPQDnhG3PqmdzLjUyRTM3t8bbffGPo8"
unity = known_token_info[contract_id]["unity"]
amount = int(0.2 * unity) # send 0.2 Token
# For hot wallet sending transaction
resp = send_token(my_account, contract_id, amount, recipient)
print(resp)
# For cold wallet signing transaction
pv.set_offline()
resp = send_token(my_account, contract_id, amount, recipient)
print(resp)
Sample result:
{
'type': 9,
'id': 'Abz3CgYtgQ7YEw7RGpCcSm8rZiLVNedGMRTpEovetcFX',
'fee': 30000000,
'feeScale': 100,
'timestamp': 1572345441719799040,
'proofs': [
{
'proofType': 'Curve25519',
'publicKey': 'FumkPwX7CLon6Jhbf7rY1J3K6To5rjWwwrfaKsS55Fza',
'address': 'AUCmDcp7BAwoc2DdWRwBcF4WJb1QWcrS9Mb',
'signature': '58MK4PoMLjFHYTL8xGCCjRz64gtJ6MN6CN4E59XA7yzeY6ghCLgfTwnepu5CtaivY24zyZseFbcDYxjgGYfhHCXm'
}
],
'contractId': 'CFEBiQG3WtJNWFhtEj1CDDg6Wy7G6P7BPSy',
'functionIndex': 3,
'functionData': '14uNyNaSUdkRdg2UzkyBz2QwKSe1GPh8gNpExZGdsL2vTYePVTD',
'attachment': ''
}
Call check_tx
method with transaction id to confirm. The confirmations
should set to M * super_node_num + 1 (M = max accept waiting minutes since transaction sent). As the short-term fork case would be happened, some blocks have chance to be rolled back. So the greater confirmations you set, the less false confirm in chain case will be occurred. Currently, super node num is 15. So we suggest the confirmations
set more than 15. For example, if you could wait 2 minutes to confirm a transaction, which just sent, in chain, then confirmations should be 2*15+1=31:
import pyvsystems as pv
from pyvsystems import Account
my_account = Account(chain=pv.testnet_chain())
tx_id = "dE4s1joxLqP1sSVRBB1KmEfB6a3vND2k3Uwsao12paG"
confirm_result = my_account.check_tx(tx_id, 31)
print(confirm_result)
If Transaction is fully confirmed, it will return True
.
If Transaction is sent but not confirmed or failed, it will return False
.
If Transaction does not exist, it will return None
.
import pyvsystems as pv
from pyvsystems import Account
import datetime
from pyvsystems.error import *
import base58
from pyvsystems.setting import EXECUTE_CONTRACT_FUNCTION_TX_TYPE
from pyvsystems.data_entry import data_entry_from_base58_str
SEND_NORMAL_TYPE_TOKEN_FUNC_INDEX = 3
SEND_SPLIT_TYPE_TOKEN_FUNC_INDEX = 4
# Known token info should store in DB
known_token_info = {
"CFEBiQG3WtJNWFhtEj1CDDg6Wy7G6P7BPSy": {
"token_id": "TWurhe6uRbuUw566dKm89Jrc9whSkUMHSjNYtFEJn",
"token_name": "Token A",
"contract_type": "TokenContract",
"unity": 100000000
},
"CF89wmAjkThqK4KzxSBYjeWe2mKaF61vzfF": {
"token_id": "TWuBEsV7iRc7qzZbeM2BWU4R5PhTWVBBbc6wdfQBs",
"token_name": "Token B",
"contract_type": "TokenContractWithSplit",
"unity": 1000000
}
}
def get_send_function_index(contract_id):
if known_token_info.get(contract_id):
if known_token_info[contract_id]["contract_type"] == "TokenContract":
return SEND_NORMAL_TYPE_TOKEN_FUNC_INDEX
elif known_token_info[contract_id]["contract_type"] == "TokenContractWithSplit":
return SEND_SPLIT_TYPE_TOKEN_FUNC_INDEX
return None
def check_v_coin_transfer_history(my_account, ts_chain):
try:
print("========Check V Coin transfer history===========")
history = my_account.get_tx_history(10)
print("JSON result: {}".format(history))
for record in history:
if not record.get('proofs'):
continue
sender_public_key = base58.b58decode(record['proofs'][0]['publicKey'])
sender_address = ts_chain.public_key_to_address(sender_public_key)
if sender_address == my_account.address:
print("####### Send #######")
else:
print("####### Received #######")
print("From: {}".format(sender_address))
print("To: {}".format(record['recipient']))
print("Transaction ID: {}".format(record['id']))
display_time = datetime.datetime.fromtimestamp(record['timestamp'] // 1000000000)
print("Time: {}".format(display_time))
print("Amount: {}".format(record['amount']))
print("Transaction fee: {}".format(record['fee']))
except InvalidParameterException as ex:
# Handle Invalid Parameter issue here
print("Invalid Parameter: {}".format(ex))
return False
except MissingAddressException:
# Handle Address issue here
print("No address for `my_account`")
return False
except NetworkException as ex:
# Handle Network issue here
print("Failed to get HTTP response: {}".format(ex))
return False
return True
def check_token_transfer_history(my_account, ts_chain):
try:
print("========Check token transfer history===========")
history = my_account.get_tx_history(10, EXECUTE_CONTRACT_FUNCTION_TX_TYPE)
print("JSON result: {}".format(history))
for record in history:
if not record.get('proofs') or not record.get('contractId') or not record.get('functionIndex'):
print("[Warning] Unexpected tx record: {}".format(record))
continue
send_func_idx = get_send_function_index(record['contractId'])
if not send_func_idx or record['functionIndex'] != send_func_idx:
continue
[recipient, amount] = data_entry_from_base58_str(record['functionData'])
sender_public_key = base58.b58decode(record['proofs'][0]['publicKey'])
sender_address = ts_chain.public_key_to_address(sender_public_key)
token_name = known_token_info[record['contractId']]["token_name"]
if sender_address == my_account.address:
print("####### Send {} #######".format(token_name))
else:
print("####### Received {} #######".format(token_name))
print("From: {}".format(sender_address))
print("To: {}".format(recipient.data))
print("Transaction ID: {}".format(record['id']))
display_time = datetime.datetime.fromtimestamp(record['timestamp'] // 1000000000)
print("Time: {}".format(display_time))
print("Amount: {}".format(amount.data))
print("Transaction fee: {}".format(record['fee']))
except InvalidParameterException as ex:
# Handle Invalid Parameter issue here
print("Invalid Parameter: {}".format(ex))
return False
except MissingAddressException:
# Handle Address issue here
print("No address for `my_account`")
return False
except NetworkException as ex:
# Handle Network issue here
print("Failed to get HTTP response: {}".format(ex))
return False
return True
if __name__ == "__main__":
address = 'AU4mSZPtUwDD9sD3bT1TVBkgcZiq3SgE1n1'
chain = pv.testnet_chain()
acc = Account(chain=chain, address=address)
check_v_coin_transfer_history(acc, chain)
check_token_transfer_history(acc, chain)