Basic IRC2 token

Initial Requirements

Initalize project

mkdir token-test
cd token-test
Then, use tbears init command to create a SCORE project.
tbears init sampletoken SampleToken
cd sampletoken
Boilerplate for your token will be initialized. The project tree is:
token-test
└── sampletoken
├── __init__.py
├── package.json
├── tests
│ ├── __init__.py
│ ├── test_integrate_token.py
│ └── test_unit_token.py
└── sampletoken.py
Remove tests directory from token as we will not be using it to test our token. Also, the imports in the files of tests directory causes problem while testing with jupyter notebook.
rm -rf tests
Now, install ODI Contracts library. Package import is prohibited except iconservice and the files in your deployed SCORE folder tree. So, the ODI Contracts library should be inside the directory, and cannot be imported from outside.
pip install odi-token-contracts -t .
ODIContracts library will be in sampletoken directory along with _init_.py, package.json and sampletoken.py. The tree structure is:
token-test
├── sampletoken
├── __init__.py
├── ODIContracts
│ ├── access
│ │ ├── __init__.py
│ │ ├── role
│ │ │ ├── BurnerRole.py
│ │ │ ├── __init__.py
│ │ │ ├── MinterRole.py
│ │ │ ├── PauserRole.py
│ │ └── roles.py
│ ├── __init__.py
│ ├── tokens
│ │ ├── IIRC2.py
│ │ ├── __init__.py
│ │ ├── IRC2burnable.py
│ │ ├── IRC2capped.py
│ │ ├── IRC2mintable.py
│ │ ├── IRC2pausable.py
│ │ ├── IRC2.py
│ │ ├── IRC2snapshot.py
│ └── utils
│ ├── checks.py
│ ├── consts.py
│ ├── __init__.py
│ ├── pausable.py
├── odi_token_contracts-0.0.3.dist-info
├── package.json
└── sampletoken.py
All __pycache__ folders and contents of odi_token_contracts-0.0.1.dist-info are ignored in this tree.
Then, change sampletoken.py to this.
from iconservice import *
from .ODIContracts.tokens.IRC2 import IRC2
TAG = 'SampleToken'
class SampleToken(IRC2):
pass
Then, go back to token-test directory.
cd ..
You'll need repeater module during testing. Run this command to get repeater module in the current directory.
wget https://raw.githubusercontent.com/OpenDevICON/opendevicon/master/repeater.py
Now, you have repeater.py module in token-test directory.
Now, download this notebook to test IRC2 tokens. Run this command to get this notebook in the current directory.
https://gist.githubusercontent.com/lilixac/4541fa7f80f7c40a2ac00a795c7b11d5/raw/6a553d9d37bfb7e0926c4e24b1db15fe01a26b8a/token-test.ipynb
Now, open jupyter-notebook in the this directory using the following command:
jupyter-notebook
Now you can see a Jupyter instance running in your browser.
Click on token-test.ipnyb file which will be our main Jupyter Notebook file to test IRC2 tokens.
Then, execute the blocks to import necessary packages, icon service, NID, Governance Address and create new wallet.
You now should have deployer_wallet and caller_wallet address. deployer_wallet will be used to send IRC2 Token. caller_wallet will be used as a random wallet to test methods.
Load test ICX to deployer_wallet address from the ibriz faucet.

Deploying the contract

DEPLOY_PARAMS = {
"_tokenName": "TestToken",
"_symbolName": "TK",
"_initialSupply": 1000,
"_decimals": 18
}
deploy_transaction = DeployTransactionBuilder()\
.from_(deployer_wallet.get_address())\
.to("cx0000000000000000000000000000000000000000")\
.nid(NID)\
.nonce(100)\
.content_type("application/zip")\
.content(gen_deploy_data_content('sampletoken'))\
.params(DEPLOY_PARAMS)\
.build()
estimate_step = icon_service.estimate_step(deploy_transaction)
step_limit = estimate_step + 100000
signed_transaction = SignedTransaction(deploy_transaction, deployer_wallet, step_limit)
tx_hash = icon_service.send_transaction(signed_transaction)
@retry(JSONRPCException, tries=10, delay=1, back_off=2)
def get_tx_result(_tx_hash):
tx_result = icon_service.get_transaction_result(_tx_hash)
return tx_result
tx_result = get_tx_result(tx_hash)
SCORE_ADDRESS = tx_result['scoreAddress']
The decorator @retry() is imported from the repeater module.
The scoreAddress of your deployed SCORE from the tx_result will be saved to the variable SCORE_ADDRESS as you will require it while moving forward.
You may encounter timeout and gaierror error. In that case re-execute the block again.

Check the name, symbol, decimals and total supply

external_methods = ["name", "symbol", "decimals", "totalSupply"]
for method in external_methods:
call = CallBuilder().from_(deployer_wallet.get_address())\
.to(SCORE_ADDRESS)\
.method(method)\
.build()
print(icon_service.call(call))
You have successfully created a token!

Check the total number of tokens of caller and deployer address

external_methods = [deployer_wallet.get_address(), caller_wallet.get_address()]
for address in external_methods:
call = CallBuilder().from_(deployer_wallet.get_address())\
.to(SCORE_ADDRESS)\
.method('balanceOf')\
.params({'account': address})\
.build()
print(icon_service.call(call))
Note the balance of deployer and caller address

Transfer of tokens

Now, we transfer the tokens from the deployer to the caller address.
params={
"_to": caller_wallet.get_address(),
"_value": 5,
}
call_transaction = CallTransactionBuilder()\
.from_(deployer_wallet.get_address())\
.to(SCORE_ADDRESS)\
.nid(3)\
.nonce(100)\
.method("transfer")\
.params(params)\
.build()
estimate_step = icon_service.estimate_step(call_transaction)
step_limit = estimate_step + 100000
signed_transaction = SignedTransaction(call_transaction, deployer_wallet, step_limit)
tx_hash = icon_service.send_transaction(signed_transaction)
tx_result = get_tx_result(tx_hash)
tx_result
Now re-execute the block to check the balance of deployer and caller address. 5 tokens will be transferred to the random address from deployer address.
CONGRATULATIONS! You have successfully created a token in ICON blockchain, and transferred fund from one address to another address!