-
Notifications
You must be signed in to change notification settings - Fork 8
Sample Code for Token Contract
To generate and broadcast transactions, we can use pyvsystems
to test contract functionalities on vsys chain.
pyvsystems can be installed by first cloning the github repository
git clone https://github.com/virtualeconomy/pyvsystems.git
Then using pip, we can install the repository as a package
pip3 install pyvsystems/.
Then we can simply import pyvsystems
in your own workplace
Import package pyvystems
import pyvsystems as pv
from pyvsystems import Account
from pyvsystems.contract_helper import *
Initialize API connection
To register a VSYS contract on chain, we must first initialize API parameters to a full node.
# Initialize API connection. API key is needed if you intend to interact with the node's database.
custom_wrapper = pv.create_api_wrapper("<your_node_address>", api_key="<your_node_api_key (optional)>")
# chain = pv.Chain(chain_name='mainnet', chain_id='M', address_version=5, api_wrapper=custom_wrapper)
chain = pv.Chain(chain_name='testnet', chain_id='T', address_version=5, api_wrapper=custom_wrapper)
sender = Account(chain=chain, seed="<your_sender_seed>")
VSYS contracts are defined by an encoded byte string that contains the information of the contract functions. We can get this information by the use of the contract helper classes.
# Contract object to be registered
token_without_split_contract_helper = TokenWithoutSplitContractHelper()
token_with_split_contract_helper = TokenWithSplitContractHelper()
token_contract_without_split_object = token_without_split_contract_helper.contract_object
token_contract_with_split_object = token_with_split_contract_helper.contract_object
Note that smart contracts in VSYS take in something called DataEntry, which specifies the value and type of the input. The functions in contracts have specific types of inputs, and the types must match in order to utilise the contract.
When we register a token contract, the availability of the split function depends on the encoded byte string we use. We must then specify the maximum supply, the unity and the description of the token.
Register a token contract with split
Token with split Contract ByteString:
3dPGAWbTw4srh5hmMiRUhHtcxmXXLUooKGAfnmz11j5NruyJpBzZpgvADMdZS7Mevy5MAHqFbfHYdfqaAe1JEpLWt1pJWLHZBV62zUhLGmVLXUP5UDvSs24jsBRHqZMC71ciE1uYtgydKxCoFJ3rAgsYqp7GDeTU2PXS5ygDmL6WXmbAYPS8jE4sfNUbJVwpvL1cTw4nnjnJvmLET8VmQybxFt415RemV3MFPeYZay5i5gMmyZa63bjzK1uMZAVWA9TpF5YQ1NTZjPaRPvQGYVY4kY9L4LFJvUG2bib1QaNh7wUAQnTzJfRYJoy1aegFGFZFnBGp9GugH4fHAY69vGmZQnhDw3jU45G9odFyXo3T5Ww4R5szegbjCUKdUGpXf9vY2cKEMJ7i8eCkFVG1dDFZeVov1KMjkVNV8rDBDYfcp3oSGNWQQvGSUT5iGUvDRN8phy1UpR3A9uMVebvjLnVzPx9RyqQ8HaXLM8vPhLuWLoh5hk1Zi1n9nwz55XvKDYjP6eeB55yK5vpg8xjaYDnw9bjYV7ZmS7LAsHvXfnwi8y2W6vk2hGvs4rtR1vNRZSQMPGRRSuwCRJL1yngH6uHWwm2ajWxc684jApuoLdyjZomfCtdpabSyU3kp9Lrn8zT8BVY332sJPQU6gTQi8ke9s9dBxCae4cfSQM6HhuBmFc5KKWHCVG4bm4KZRYbMtidw8ZZnjaAMtcGq7k3Se6GXaTxdS3GcuttB3VB7njypyzuqAcfCdYb9ht8Y1WuTCZ1aLsXsL6eydfk2WLJVrqYpbTk6AchV5gMAEopvc3qXvzrDCedjtNsDmA56Lh6PxrrKr8aV8Wzz8aMaQ88YsVBpE8J4cDkxzo31AojhzEGVBKLmpb3bjmsaw9VkpB6yL8ngYs8eJMSPdM289TSMaEmG4eHt1jezpHTKxkuB9cwqcvhGNLWuv8KXQkik5pRMXV67Qs2FvjpzeJ81z2hnVh1wCtsa6M6qAG1gsqLHa1AVMRzsowafC99uDexwWMBS2RqsZWZBXJcUiNVULjApSnoBREYfHYEpjJ152hnTYZCAwpZMWEkVdBQpZ3zk8gbfLxB4fWMfKgJJucbKPGp1K56u7P8MHQu9aNb9dEof2mwX8rTHjk8jSQ7kXVX4Mf1JqMRWWftkV3GmU1nqYhxRGu4FjDNAomwTr5epHpcMF6P5oiXcLWh5BFQVmGYKz129oizAyUJBsZdxr2WZEGDieLxUg8cve25g28oTuCVENST4z1ZsFAN9wTa1
Triggers | Inputs | Input Types | Description |
---|---|---|---|
Init | ("max", "unity", "tokenDescription") | (amount, amount, short_text) | Triggered when you register a Token With Split Contract |
token_with_split_contract_helper = TokenWithSplitContractHelper()
token_contract_with_split_object = token_with_split_contract_helper.contract_object
register_token_contract_with_split_data_stack = token_with_split_contract_helper.register_data_stack_generator(<your_max_supply>, <your_unity>, "<your_description>")
sender.register_contract(token_contract_with_split_object, register_token_contract_with_split_data_stack)
Register a token contract without split
Token without split Contract ByteString:
3GQnJtxDQc3zFuUwXKbrev1TL7VGxk5XNZ7kUveKK6BsneC1zTSTRjgBTdDrksHtVMv6nwy9Wy6MHRgydAJgEegDmL4yx7tdNjdnU38b8FrCzFhA1aRNxhEC3ez7JCi3a5dgVPr93hS96XmSDnHYvyiCuL6dggahs2hKXjdz4SGgyiUUP4246xnELkjhuCF4KqRncUDcZyWQA8UrfNCNSt9MRKTj89sKsV1hbcGaTcX2qqqSU841HyokLcoQSgmaP3uBBMdgSYVtovPLEFmpXFMoHWXAxQZDaEtZcHPkrhJyG6CdTgkNLUQKWtQdYzjxCc9AsUGMJvWrxWMi6RQpcqYk3aszbEyAh4r4fcszHHAJg64ovDgMNUDnWQWJerm5CjvN76J2MVN6FqQkS9YrM3FoHFTj1weiRbtuTc3mCR4iMcu2eoxcGYRmUHxKiRoZcWnWMX2mzDw31SbvHqqRbF3t44kouJznTyJM6z1ruiyQW6LfFZuV6VxsKLX3KQ46SxNsaJoUpvaXmVj2hULoGKHpwPrTVzVpzKvYQJmz19vXeZiqQ2J3tVcSFH17ahSzwRkXYJ5HP655FHqTr6Vvt8pBt8N5vixJdYtfx7igfKX4aViHgWkreAqBK3trH4VGJ36e28RJP8Xrt6NYG2icsHsoERqHik7GdjPAmXpnffDL6P7NBfyKWtp9g9C289TDGUykS8CNiW9L4sbUabdrqsdkdPRjJHzzrb2gKTf2vB56rZmreTUbJ53KsvpZht5bixZ59VbCNZaHfZyprvzzhyTAudAmhp8Nrks7SV1wTySZdmfLyw7vsNmTEi3hmuPmYqExp4PoLPUwT4TYt2doYUX1ds3CesnRSjFqMhXnLmTgYXsAXvvT2E6PWTY5nPCycQv5pozvQuw1onFtGwY9n5s2VFjxS9W6FkCiqyyZAhCXP5o44wkmD5SVqyqoL5HmgNc8SJL7uMMMDDwecy7Sh9vvt3RXirH7F7bpUv3VsaepVGCHLfDp9GMG59ZiWK9Rmzf66e8Tw4unphu7gFNZuqeBk2YjCBj3i4eXbJvBEgCRB51FATRQY9JUzdMv9Mbkaq4DW69AgdqbES8aHeoax1UDDBi3raM8WpP2cKVEqoeeCGYM2vfN6zBAh7Tu3M4NcNFJmkNtd8Mpc2Md1kxRsusVzHiYxnsZjo
Triggers | Inputs | Input Types | Description |
---|---|---|---|
Init | ("max", "unity", "tokenDescription") | (amount, amount, short_text) | Triggered when you register a Token Without Split Contract |
token_without_split_contract_helper = TokenWithoutSplitContractHelper()
token_contract_without_split_object = token_without_split_contract_helper.contract_object
register_token_contract_without_split_data_stack = token_without_split_contract_helper.register_data_stack_generator(<your_max_supply>, <your_unity>, "<your_description>")
sender.register_contract(token_contract_without_split_object, register_token_contract_without_split_data_stack)
Once a token contract has been registered, its token can be used by executing the functions of the contract. Note that the function id of each function may be different depending on whether the contract allows split or doesn't.
With Split:
Executable Functions | Function ID | Inputs | Input Types | Description |
---|---|---|---|---|
Supersede | 0 | ("newIssuer") | (address) | Transfer issuing rights of Contract |
Issue | 1 | ("amount") | (amount) | Issue new Tokens (only address with issuing rights can execute this function) |
Destroy | 2 | ("amount") | (amout) | Destroy an amount of tokens (only address with issuing rights can execute this function) |
Split | 3 | ("newUnity") | (amount) | Change the number each token can be split into (only address with issuing rights can execute this function) |
Send | 4 | ("recipient", "amount") | (address, amount) | Send tokens |
Transfer | 5 | ("sender", "recipient", "amount") | (address, address, amount) | Transfer tokens from sender to recipient |
Deposit | 6 | ("sender", "contract", "amount") | (address, contract_account, amount) | Deposit tokens into another contract |
Withdraw | 7 | ("contract", "recipient", "amount") | (contract_account, address, amount) | Withdraw tokens from another contract |
TotalSupply | 8 | () | () | Currently not used |
MaxSupply | 9 | () | () | Currently not used |
BalanceOf | 10 | ("address") | (address) | Currently not used |
GetIssuer | 11 | () | () | Currently not used |
Without Split:
Executable Functions | Function ID | Inputs | Input Types | Description |
---|---|---|---|---|
Supersede | 0 | ("newIssuer") | (address) | Transfer issuing rights of Contract |
Issue | 1 | ("amount") | (amount) | Issue new Tokens (only address with issuing rights can execute this function) |
Destroy | 2 | ("amount") | (amout) | Destroy an amount of tokens (only address with issuing rights can execute this function) |
Send | 3 | ("recipient", "amount") | (address, amount) | Send tokens |
Transfer | 4 | ("sender", "recipient", "amount") | (address, address, amount) | Transfer tokens from sender to recipient |
Deposit | 5 | ("sender", "contract", "amount") | (address, contract_account, amount) | Deposit tokens into another contract |
Withdraw | 6 | ("contract", "recipient", "amount") | (contract_account, address, amount) | Withdraw tokens from another contract |
TotalSupply | 7 | () | () | Currently not used |
MaxSupply | 8 | () | () | Currently not used |
BalanceOf | 9 | ("address") | (address) | Currently not used |
GetIssuer | 10 | () | () | Currently not used |
Supersede the issuing rights to another address
token_with_split_contract_id = "<your_token_with_split_contract_id>"
recipient_address = "<your_recipient_address>"
supersede_function_id = token_with_split_contract_helper.supersede_function_index
supersede_data_stack = token_with_split_contract_helper.supersede_data_stack_generator(recipient_address)
sender.execute_contract(token_with_split_contract_id, supersede_function_id, supersede_data_stack)
Issue tokens to owner of contract
issue_function_id = token_with_split_contract_helper.issue_function_index
issue_data_stack = token_with_split_contract_helper.issue_data_stack_generator(<your_issue_amount>)
sender.execute_contract(token_with_split_contract_id, issue_function_id, issue_data_stack)
Destroy a number of tokens from owner of contract
destroy_function_id = token_with_split_contract_helper.destroy_function_index
destroy_data_stack = token_with_split_contract_helper.destroy_data_stack_generator(<your_destroy_amount>)
sender.execute_contract(token_with_split_contract_id, destroy_function_id, destroy_data_stack)
Split the token and give it a new unity value
split_function_id = token_with_split_contract_helper.split_function_index
split_data_stack = token_with_split_contract_helper.destroy_data_stack_generator(<your_new_unity>)
sender.execute_contract(token_with_split_contract_id, split_function_id, split_data_stack)
Send tokens to other wallets
recipient_address = "<your_recipient_address>"
send_function_id = token_with_split_contract_helper.send_function_index
send_data_stack = token_with_split_contract_helper.send_data_stack_generator(recipient_address, <your_send_amount>)
sender.execute_contract(token_with_split_contract_id, send_function_id, send_data_stack)
Transfer tokens from one wallet to another
recipient_address = "<your_recipient_address>"
transfer_function_id = token_with_split_contract_helper.transfer_function_index
transfer_data_stack = token_with_split_contract_helper.transfer_data_stack_generator(sender.address, recipient_address, <your_transfer_amount>)
sender.execute_contract(token_with_split_contract_id, transfer_function_id, transfer_data_stack)
Deposit tokens into VSYS contracts (this example uses a payment channel contract)
payment_channel_contract_id = "<your_payment_channel_contract_id>"
deposit_function_id = token_with_split_contract_helper.deposit_function_index
deposit_data_stack = token_with_split_contract_helper.deposit_data_stack_generator(sender.address, payment_channel_contract_id, <your_deposit_amount>)
sender.execute_contract(token_with_split_contract_id, deposit_function_id, deposit_data_stack)
Withdraw tokens from VSYS contracts (this example uses a payment channel contract)
payment_channel_contract_id = "<your_payment_channel_contract_id>"
withdraw_function_id = token_with_split_contract_helper.withdraw_function_index
withdraw_data_stack = token_with_split_contract_helper.withdraw_data_stack_generator(payment_channel_contract_id, sender.address, <your_withdraw_amount>)
sender.execute_contract(token_with_split_contract_id, withdraw_function_id, withdraw_data_stack)
In order for the contract to do anything, it has to store some information within the database. This information can be queried by using the correct database key within the full node. The contract helper objects contain the corresponding database keys for each stored variable.
Both with split and without split token contracts have the same databases.
State Variable | State Variable Index | Description |
---|---|---|
issuer | 0 | The address of the issuer of the token contract |
maker | 1 | The address of the creator of the token contract |
State Map | State Map Index | State Map Key | Description |
---|---|---|---|
N/A | N/A | N/A | N/A |
Get the issuer of the token contract
token_with_split_contract_id = "<your_token_with_split_contract_id>"
issuer_db_key = token_with_split_contract_helper.issuer_db_key_generator()
print(chain.contract_db_query(token_with_split_contract_id, issuer_db_key))
Get the maker of the token contract
token_with_split_contract_id = "<your_token_with_split_contract_id>"
maker_db_key = token_with_split_contract_helper.maker_db_key_generator()
print(chain.contract_db_query(token_with_split_contract_id, maker_db_key))