Skip to content
VeeSheldon edited this page Dec 10, 2018 · 7 revisions

Start VSYS client

Step 1: Prepare

Install Python and PIP in your machine. Both Python 2.7 and 3 are supported. In this instruction, we just use Python 3.6 as example.

$ sudo apt-get install python3.6 python3-dev
$ curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
$ python3 get-pip.py

Download vsys python library source code from GitHub. And then install the required library.

$ git clone https://github.com/virtualeconomy/pyvsys.git
$ pip3 install -r ./pyvsys/requirements.txt

Step 2: Run

Create new screen and start up Python console

$ screen -S vsys-client
$ python3
Python 3.6.0
[Clang 9.1.0 (clang-902.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 

First of all, import pyvsys package and Account class

>>> import pyvsys as pv
>>> from pyvsys import Account
>>> from pyvsys import Wrapper
>>> import datetime
>>> import base58

We could create chain object as this:

# (TestNet)
>>> chain = pv.testnet_chain()

or

# (MainNet)
>>> 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)

Chain related statement

  • Look up current block height of the chain:
>>> chain.height()
643306
  • Look up the last block info of the chain:
>>> chain.lastblock()
{u'SPOSConsensus': {u'mintTime': 1538055636000000000, u'mintBalance': 105251999961600}, u'fee': 0, u'resourcePricingData': {u'sequentialIO': 0, u'storage': 0, u'randomIO': 0, u'computation': 0, u'memory': 0}, u'reference': u'2THdUU3R7qCSs6Wq9VcD76EnZvVL7XjJsDNSLKteUDdFJmRLoJsGqNrkrDvopjhGeDvL84cqw1BTdKVY53scaaFZ', u'transactions': [{u'status': u'Success', u'type': 5, u'feeCharged': 0, u'amount': 900000000, u'timestamp': 1538055636000742434, u'currentBlockHeight': 643642, u'recipient': u'AUF4We2c4TAFr6KDsQy6WCwSYDx1VUih283', u'id': u'GfihGXgsf9Uu44uoGG2sp3yHktyGffxUcfijbA8CbBAB'}], u'timestamp': 1538055636000742434, u'generator': u'ATyLwDefhDnAaeaqtKhF3rWetkoYw1r4Gi6', u'signature': u'DAbYoJ4WJLZT25MC1ScFxwRv6Hv95TSKJ7XBsAzPzqvFaAij4Komx75zGTDakizZBQbmx9Nt2xHAAav6tdFFqZs', u'blocksize': 330, u'version': 1, u'TransactionMerkleRoot': u'4dBVqrH4hocfjNovDTWgLf2de42xVrxJjmNAXcqpWLeF', u'height': 643642, u'transaction count': 1}
  • Look up a block info at n in the chain:
>>> n = 1
>>> chain.block(n)
{u'SPOSConsensus': {u'mintTime': 1535356440000000000, u'mintBalance': 0}, u'fee': 0, u'resourcePricingData': {u'sequentialIO': 0, u'storage': 0, u'randomIO': 0, u'computation': 0, u'memory': 0}, u'reference': u'67rpwLCuS5DGA8KGZXKsVQ7dnPb9goRLoKfgGbLfQg9WoLUgNY77E2jT11fem3coV9nAkguBACzrU1iyZM4B8roQ', u'transactions': [{u'recipient': u'ATxpELPa3yhE5h4XELxtPrW9TfXPrmYE7ze', u'status': u'Success', u'fee': 0, u'timestamp': 1535356447650226656, u'slotId': 0, u'amount': 300000000000000000, u'feeCharged': 0, u'signature': u'4N1NnwqJ6MTF46VeQLnQDSvDqxnYetqd6t8WMfKp1ZTwG1RhboS9KV1tZ21xy6QujpbrArsYfYamizg2GU5UUoNz', u'type': 1, u'id': u'4JqUudiHYHkwCPvdZDTw59qBJpqmQgvVxMzS7Bfc1EJZ'}, {u'recipient': u'ATtRykARbyJS1RwNsA6Rn1Um3S7FuVSovHK', u'status': u'Success', u'fee': 0, u'timestamp': 1535356447650226656, u'slotId': 1, u'amount': 200000000000000000, u'feeCharged': 0, u'signature': u'5B5awtvy7U62vGAjPyM1nGCytG9mKN3Map7EZuetpBSFL9VsVCRW787ZwMTJuDnFj2mkWWgMvfq18xyCLYPseEpM', u'type': 1, u'id': u'A7mgwn98VyzcEC2hmrgt9sRPbFfyBvs44rjGPu7dHxbH'}, {u'recipient': u'ATtchuwHVQmNTsRA8ba19juGK9m1gNsUS1V', u'status': u'Success', u'fee': 0, u'timestamp': 1535356447650226656, u'slotId': 2, u'amount': 150000000000000000, u'feeCharged': 0, u'signature': u'3t3Dh49RmvrEnG3nQvNFQN4bLN1Jvkw1Ffa2u1AXQdU8jetngagdD2n3pWmUeXWXbVRYSNgQX8My3WEGteQTUVDy', u'type': 1, u'id': u'ZdpAvtegbnPSBTyRDD2xTvbQ5LxhAX6jrykuG7hxugB'}, {u'recipient': u'AU4AoB2WzeXiJvgDhCZmr6B7uDqAzGymG3L', u'status': u'Success', u'fee': 0, u'timestamp': 1535356447650226656, u'slotId': 3, u'amount': 50000000000000000, u'feeCharged': 0, u'signature': u'33EftL6giA2xYBkx9x4R2xdd3ikcDBb3aw3mDQAHt7Y3QkoEvozKKsnqGGTYiRVut8sexSE3EuDYxyviXA6hhkzT', u'type': 1, u'id': u'257QZpUxYRiKVRVQr8FgzTngbzF6MW7fMWqyxB7wFawq'}, {u'recipient': u'AUBHchRBY4mVNktgCgJdGNcYbwvmzPKgBgN', u'status': u'Success', u'fee': 0, u'timestamp': 1535356447650226656, u'slotId': 4, u'amount': 60000000000000000, u'feeCharged': 0, u'signature': u'2Thag4Lo4ixcyw9p2p4dMHRwoqs4LJ3Jwkjdf9qNT34FNk7sKRAGFbNUezgCc9XfVw6obTn1m4zRjx4kRLCYyWcz', u'type': 1, u'id': u'5G27tFPDFBXSmS6muMiXMDc3VuAyoA4TtSWtgJaWrfY7'}, {u'recipient': u'AU6qstXoazCHDK5dmuCqEnnTWgTqRugHwzm', u'status': u'Success', u'fee': 0, u'timestamp': 1535356447650226656, u'slotId': 5, u'amount': 60000000000000000, u'feeCharged': 0, u'signature': u'z7MzwmKLJQJLMu8Z2ivFCTBTwNKYyfomdxN65cdyCwy6YsL7UbBFciQXUo7u1W5Uikwwx8dePPzYfKokxBfaJn5', u'type': 1, u'id': u'GnLWJrk8cs9p8MzasEiAPmH77atNuCo2U58Yk46EBqvi'}, {u'recipient': u'AU9HYFXuPZPbFVw8vmp7mFmHb7qiaMmgEYE', u'status': u'Success', u'fee': 0, u'timestamp': 1535356447650226656, u'slotId': 6, u'amount': 60000000000000000, u'feeCharged': 0, u'signature': u'2PPHXX9UjwFxFBujqE2bMzqEYTbJy1ydS6b5BywAymrgUXhpsWQHa84uUpEdbh9PcFSjehbbSvw8b9Yt74S1W58W', u'type': 1, u'id': u'DXWZgR3KPXYuHccAXY6uLSrW3VWVT3uNVKkjqWmfFPeV'}, {u'recipient': u'AUBLPMpHVV74fHQD8D6KosA76nusw4FqRr1', u'status': u'Success', u'fee': 0, u'timestamp': 1535356447650226656, u'slotId': 7, u'amount': 60000000000000000, u'feeCharged': 0, u'signature': u'bBJ6eTAUgMP8TbmafSwLUT3vFvNY955ddpYuByk6v8CFn6VzeuMUz11veM9bGAuwki3gTevDYf9N8SVPy5AhA8N', u'type': 1, u'id': u'8JEe9ibrSajZXpQxhxNzxPZ81RRbXSBy4EpRpophFCvz'}, {u'recipient': u'AUBbpPbymsrM8QiXqS3NU7CrD1vy1EyonCa', u'status': u'Success', u'fee': 0, u'timestamp': 1535356447650226656, u'slotId': 8, u'amount': 40000000000000000, u'feeCharged': 0, u'signature': u'5fbpe2GsLHaGEATiEZL7EgsfxGTAsbTRg14UzGkRcQiTpHhzxdqx1CJ31nVr4ndBgkkkKG1xc9waVBtBKjagDF59', u'type': 1, u'id': u'3XECBDJVne2SwSnct48LE3fM8FEYVWgpLx3iSfqh9ABx'}, {u'recipient': u'AU7nJLcT1mThXGTT1KDkoAtfPzc82Sgay1V', u'status': u'Success', u'fee': 0, u'timestamp': 1535356447650226656, u'slotId': 9, u'amount': 20000000000000000, u'feeCharged': 0, u'signature': u'59k1YWqXgermPUocbS6JtJMmkSBsWSiyJtiGQd7Artkgddns6WdSmUPYezymSXPo9gpEpgbRGEKsFsxRC16pwoXz', u'type': 1, u'id': u'FMJd2cyYasRPm6jWqGi3CuMhwE5dF7LiNQCXbKAsAhPi'}], u'timestamp': 1535356447650226656, u'generator': u'ATrBur3QznqYo8kouKPgDYki7AtbHEsmVid', u'signature': u'5n4ewwZh9F4MMpSvtdxLCu5MUKnhEyUth2w3zEfpuiX3vwS1STNCdi51fmowJuLT1CfFg1DuodSvxwBZDANvGNej', u'blocksize': 870, u'version': 1, u'TransactionMerkleRoot': u'85w9jZL7o6evWqt3qpy4JGC3144ekGcSfxVnznMBwUAP', u'height': 1, u'transaction count': 10}
  • Get a transaction info by transacion id in the chain:
>>> tx_id = "EBuXG2y5yLa8j9QUaXK535sU7xUjokVuCkmgwFKAjJw6"
>>> resp = chain.tx(tx_id)
>>> resp
{u'status': u'Success', u'fee': 10000000, u'timestamp': 1536230749375858944, u'feeCharged': 10000000, u'feeScale': 100, u'height': 143985, u'amount': 100000000, u'attachment': u'', u'type': 2, u'proofs': [{u'publicKey': u'CbUPwcCJaMqYSjZGXy4LrkTfV2ncP27Chqyd2QKXfJxn', u'proofType': u'Curve25519', u'signature': u'64cyK8CdgaaNh199VghmrUieCF7XVQmiV5EmpwJaHRZ9mWbMBs87saPCrvrdWELBn9sqLpiJ5KicqBQMM77jYvpr'}], u'recipient': u'ATt6P4vSpBvBTHdV5V9PJEHMFp4msJ1fkkX', u'id': u'EBuXG2y5yLa8j9QUaXK535sU7xUjokVuCkmgwFKAjJw6'}

To show the transaction time from response,

>>> display_time = datetime.datetime.fromtimestamp(resp['timestamp'] // 1000000000)
>>> print("Time: {}".format(display_time))
Time: 2018-09-06 18:45:49

The sender address is hidden in public key in proofs. To show the sender from response,

>>> sender_public_key = base58.b58decode(resp['proofs'][0]['publicKey'])
>>> sender_address = ts_chain.public_key_to_address(sender_public_key)
>>> print("From: {}".format(sender_address))
AU6GsBinGPqW8zUuvmjgwpBNLfyyTU3p83Q

To show the recipient from response,

>>> print("To: {}".format(resp['recipient']))
ATt6P4vSpBvBTHdV5V9PJEHMFp4msJ1fkkX

To show the amount from response,

>>> print("Amount: {}".format(resp['amount']))
Amount: 100000000

To show the transaction fee from response,

>>> print("Transaction fee: {}".format(resp['fee']))
Transaction fee: 10000000
  • Validate an address of the chain:
>>> addr = "AUC63SmgmUNmie784Ld9CRjbecvPg2beShy"
>>> chain.validate_address(addr)
True
>>> addr = "An invalid address"
>>> chain.validate_address(addr)
False

Account related statement

  • Create new account
>>> my_account = Account(chain=chain)
  • Get account information
>>> my_account.get_info()
{u'available': 0, u'mintingAverage': 0, u'effective': 0, u'height': 643936, 'publicKey': '8PtidoeohqEyAyuqdBGudWfr7i1mUVrhNkQHNRfvaXvq', u'regular': 0, u'address': u'AU1vwC7C6CqV2q4oZYFNTbBJYNaakMBQyZV'}

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'
}

For security cosideration, the private key will not be shown in geranal account info. To get account private key, please use:

>>> my_account.privateKey
'28XHDwLzKaXRLspTBuxqurrah6apEfbJGh6Nnt914u2T'
  • Restore account by private key
>>> pk = "28XHDwLzKaXRLspTBuxqurrah6apEfbJGh6Nnt914u2T"
>>> restore_account = Account(chain=chain, private_key=pk)
  • Send payment transaction
>>> # For example, the address of recipient is "AU18gPQDnhG3PqmdzLjUyRTM3t8bbffGPo8"
>>> recipient_address = "AU18gPQDnhG3PqmdzLjUyRTM3t8bbffGPo8"
>>> recipient = Account(chain=chain, address=recipient_address)
>>> # send payment (100000000 = 1 VSYS)
>>> resp = my_account.send_payment(recipient, amount=100000000)
>>> resp
{u'fee': 10000000, u'timestamp': 1538059747188733952, u'feeScale': 100, u'amount': 100000000, u'attachment': u'', u'type': 2, u'proofs': [{u'publicKey': u'B2Khd89jtnpuzGdnyGRcnKycZMBCo6PsotFcWWi1wMDV', u'proofType': u'Curve25519', u'signature': u'4ZR6FW68YbwPUnxt18hx4df7Nrdx5th3YruHR672JGw3U4simXgXGSNvxodDV8q7H4cm4XwZCkGDF9ic1aPiExMh'}], u'recipient': u'AU18gPQDnhG3PqmdzLjUyRTM3t8bbffGPo8', u'id': u'ABgT8xs3EtR9spKopMdSmsdCE5pZRoZEqdnKX3nmD9fv'}

To show the transaction time from response,

>>> display_time = datetime.datetime.fromtimestamp(resp['timestamp'] // 1000000000)
>>> print("Time: {}".format(display_time))
Time: 2018-09-27 22:49:07

The sender address is hidden in public key in proofs. To show the sender from response,

>>> sender_public_key = base58.b58decode(resp['proofs'][0]['publicKey'])
>>> sender_address = ts_chain.public_key_to_address(sender_public_key)
>>> print("From: {}".format(sender_address))
ATt6P4vSpBvBTHdV5V9PJEHMFp4msJ1fkkX

To show the recipient from response,

>>> print("To: {}".format(resp['recipient']))
AU18gPQDnhG3PqmdzLjUyRTM3t8bbffGPo8

To show the amount from response,

>>> print("Amount: {}".format(resp['amount']))
Amount: 100000000

To show the transaction fee from response,

>>> print("Transaction fee: {}".format(resp['fee']))
Transaction fee: 10000000
  • Get transation history
>>> # For example, we get last 10 transations and show payment transations only:
>>> limit = 10
>>> tx_filter = pv.setting.PAYMENT_TX_TYPE
>>> my_account.get_tx_history(limit, tx_filter)
[{u'status': u'Success', u'fee': 10000000, u'timestamp': 1538059747188733952, u'feeCharged': 10000000, u'feeScale': 100, u'amount': 100000000, u'attachment': u'', u'type': 2, u'proofs': [{u'publicKey': u'B2Khd89jtnpuzGdnyGRcnKycZMBCo6PsotFcWWi1wMDV', u'proofType': u'Curve25519', u'signature': u'4ZR6FW68YbwPUnxt18hx4df7Nrdx5th3YruHR672JGw3U4simXgXGSNvxodDV8q7H4cm4XwZCkGDF9ic1aPiExMh'}], u'recipient': u'AU18gPQDnhG3PqmdzLjUyRTM3t8bbffGPo8', u'id': u'ABgT8xs3EtR9spKopMdSmsdCE5pZRoZEqdnKX3nmD9fv'}, {u'status': u'Success', u'fee': 10000000, u'timestamp': 1536663958559000000, u'feeCharged': 10000000, u'feeScale': 100, u'amount': 210000000000000, u'attachment': u'', u'type': 2, u'proofs': [{u'publicKey': u'B2Khd89jtnpuzGdnyGRcnKycZMBCo6PsotFcWWi1wMDV', u'proofType': u'Curve25519', u'signature': u'4VkfFztUQUPBTcKWBLrwcPfSgtHnAuHYYyWSMfVAu2Z1WZyWE2i5VPBghCkJCJCacqHjALKHr8qRGD9PW6WTBZU'}], u'recipient': u'AU7nJLcT1mThXGTT1KDkoAtfPzc82Sgay1V', u'id': u'Mv2WZyurYtKAMhdFazvPZy2Nt8NapmHuwvAR8KKrbog'}]

To exit the Python console, press Ctrl + D or type "exit()"

>>> exit()

Sample Code

import base58
import datetime
import pyvsys as pv
from pyvsys import Account
from pyvsys.error import *


def test_payment():
    # set chain
    ts_chain = pv.testnet_chain()

    # get block height
    try:
        height = ts_chain.height()
        print("The current block height of the chain: {}".format(height))
    except NetworkException as ex:
        # Handle Network issue here
        print("Failed to get block height: {}".format(ex))
        return False

    # create / restore account
    try:
        # retrieve account by private key
        private_key = "XXXXXXXXXX"
        my_account = Account(chain=ts_chain, private_key=private_key)
        # create recipient with address
        recipient_address = "XXXXXXXXXXXXXXXXX"
        recipient = Account(chain=ts_chain, address=recipient_address)
    except InvalidParameterException as ex:
        # Handle Invalid Parameter issue here
        print("Invalid Parameter: {}".format(ex))
        return False
    except InvalidAddressException as ex:
        # Handle Invalid Address issue here
        print("Invalid Address: {}".format(ex))
        return False

    # send payment (100000000 = 1 VSYS)
    try:
        print("========Do payment transaction===========")
        resp = my_account.send_payment(recipient, amount=100000000)
        print("Payment TX result: {}".format(resp))
        print("Transaction ID: {}".format(resp['id']))
        display_time = datetime.datetime.fromtimestamp(resp['timestamp'] // 1000000000)
        print("Time: {}".format(display_time))
        sender_public_key = base58.b58decode(resp['proofs'][0]['publicKey'])
        sender_address = ts_chain.public_key_to_address(sender_public_key)
        print("From: {}".format(sender_address))
        print("To: {}".format(resp['recipient']))
        print("Amount: {}".format(resp['amount']))
        print("Transaction fee: {}".format(resp['fee']))
    except InvalidParameterException as ex:
        # Handle Invalid Parameter issue here
        print("Invalid Parameter: {}".format(ex))
        return False
    except MissingPrivateKeyException:
        # Handle Missing Private Key issue here
        print("No private key for `my_account`")
        return False
    except InvalidAddressException as ex:
        # Handle Invalid Address issue here
        print("Invalid Address: {}".format(ex))
        return False
    except InsufficientBalanceException:
        # Handle Insufficient Balance issue here
        print("Insufficient Balance.")
        return False
    except NetworkException as ex:
        # Handle Network issue here
        print("Failed to get HTTP response: {}".format(ex))
        return False

    # check payment history
    try:
        print("========Check payment history===========")
        history = my_account.get_tx_history(10)
        print("Payment history: {}".format(history))
        for record in history:
            sender_public_key = base58.b58decode(resp['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(resp['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


if __name__ == "__main__":
    test_payment()

To run it, save above python script to your disk, for example, "sample.py". Finally, execute the command

$ python3 sample.py