ICON T-Bears

So far we have been using the SDK to perform basic operations directly on a testnet node using ICON Service. This isn’t ideal for obvious reasons, we should be testing locally under a test environment against our own SCORE and deploy when everything is ready. ICON has prepared a development suite called T-Bears with a set of CLI commands as well as a local emulated environment to a full node on the ICON network.

T-Bears Overview

T-Bears is a suite of development tools for SCORE. T-Bears provides a project template for SCORE to help you start right away. You can code and test your smart contract locally in an emulated environment, and when ready, deploy SCORE onto the ICON network from command-line interface.

ICON RPC Server

A module that handles ICON JSON-RPC API request and sends response back to the client. The API specifications are defined: ICON JSON-RPC API v3

ICON Service

A module that manages the lifecycle of SCORE and its execution. SCORE’s state transition is stored in a database (LevelDB). ICON Service also manages the state of ICX.

T-Bears CLI

T-Bears Command Line Interface. Supports following functions :

Manage T-Bears service

Deploy SCORE

Send transaction

Send query request

For full information visit: Command-line Interfaces (CLIs)

T-Bears Block Manager

LoopChain emulator for T-Bears Service. It does not have full ‘consensus’ and ‘peer management’ functions. This module handles transaction and emulates block generation.

Message queue

Message queue is used for inter-component communication.

No worries if you don’t understand what each of the above component does, we’ll learn through exercise shortly. First let’s get T-Bears service environment installed.

Installation Option 1: Docker Container (not recommended for this tutorial)

The team has prepared a docker image with every component already built inside, you can obtain the image with this command.

$ docker run -it --name tbears-container -p 9000:9000 iconloop/tbears

Installation Option 2: Install each component one by one (recommended for this tutorial)

This tutorial uses option 2, to install each component one by one, so we won’t be working inside a docker container.

# Install levelDB

$ apt-get install libleveldb-dev # Install libSecp256k

$ apt-get install libsecp256k1-dev



# install RabbitMQ and start service

$ apt-get install rabbitmq-server # Install ICON Service

$ pip3 install iconservice # Install ICON Commons (for T-Bears configurations and logs)

$ pip3 install iconcommons # Install ICON RPC Server

$ pip3 install iconrpcserver # Install T-Bears

$ pip3 install tbears

At this point we have a local emulated node ready to be spun up, we’ll need to start the message queue service first

$ sudo rabbitmq-server

Then we can start T-Bears

$ tbears start

Now let’s experiment T-Bears, remember our first query API to the ICON testnet? Let’s make the same API call, this time to our local emulated node,



$ python

>>> from iconsdk.icon_service import IconService

>>> from iconsdk.providers.http_provider import HTTPProvider

>>> icon_service = IconService(HTTPProvider("

>>> block = icon_service.get_block("latest")

>>> print(block)

>>> exit() # Enter interactive mode$ python>>> from iconsdk.icon_service import IconService>>> from iconsdk.providers.http_provider import HTTPProvider>>> icon_service = IconService(HTTPProvider(" http://localhost:9000/api/v3 "))>>> block = icon_service.get_block("latest")>>> print(block)>>> exit()

Notice this time instead of connecting to the testnet node bicon.net.solidwallet.io, we’re connecting to localhost instead.

T-Bears has 19 commands, init , start , stop , deploy , clear , samples , genconf , transfer , txresult , balance , totalsupply , scoreapi , txbyhash , lastblock , blockbyheight , blockbyhash , keystore , sendtx , call

You can run

tbears -h

To list the available commands, for usage of a particular command, you can run

tbears command -h

Let’s try a few T-Bears commands, remember the send_transaction.py script we experimented earlier via the SDK? We can achieve the same results via T-Bears, first run the help command to see what arguments are needed,

$ tbears transfer -h usage: tbears transfer [-h] [-f FROM] [-k KEYSTORE] [-n NID] [-u URI] [-p PASSWORD] [-s STEPLIMIT] [-c CONFIG] to value Transfer ICX coin. positional arguments: to Recipient value Amount of ICX coin in loop to transfer (1 icx = 1e18 loop) optional arguments: -h, --help show this help message and exit -f FROM, --from FROM From address. -k KEYSTORE, --key-store KEYSTORE Keystore file path. Used to generate "from" address and transaction signature -n NID, --nid NID Network ID (default: 0x3) -u URI, --node-uri URI URI of node (default: http://127.0.0.1:9000/api/v3) -p PASSWORD, --password PASSWORD Keystore file's password -s STEPLIMIT, --step-limit STEPLIMIT Step limit -c CONFIG, --config CONFIG Configuration file path. This file defines the default values for the properties "keyStore", "uri", "from" and "stepLimit". (default: ./tbears_cli_config.json)

We want to send from wallet 1 so we’ll need to provide the keystore/password via -k keystore and -p password. Since our balances are stored in the testnet node, we’ll need to specify the node-uri to perform the operation under, via -u URI, if you don’t specify the correct node (localhost by default), you’d get out of balance exception since you don’t have any ICX in these wallets locally. The very last argument is the value to send in ‘loops’, which is the smallest unit in ICX, the conversion rate is 1e18 loops = 1 ICX. (1e18 = 1,000,000,000,000,000,000)

$ tbears transfer -k ./iconkeystore -p "@icon111" hx4fbeb2879960248111e2006f12b8aba5173d1edd -u https://bicon.net.solidwallet.io/api/v3 1e18

Check the balance shortly via the SDK or ICONex, 1 ICX should’ve been transferred from wallet 1 to wallet 2.

Let’s inspect the most important features of T-Bears — SCORE related development and execution. tbears init to initialize a new SCORE project and tbears samples to generate sample SCORE projects. tbears deploy , tbears sendtx and tbears call commands are used to deploy the SCORE, send a transaction, and call a function.

*We’re going to initialize a brand new SCORE project, you can run tbears samples which will generate two sample SCORE projects automatically.

# Create a new directory to work under

$ mkdir SCORE && cd SCORE # Initialize a SCORE project

$ tbears init my_first_score FirstScore

This will initialize SCORE development environment and generate my_first_score.py and package.json in my_first_score directory. The name of the SCORE class is FirstScore. Default configuration files, “tbears_server_config.json” used when starting T-Bears and “tbears_cli_config.json” used when deploying SCORE, are also generated. A keystore_test1 is also created, this is the default wallet in all these configuration files, open the file and copy the wallet address

# Check how much ICX keystore_test1 has

$ tbears balance hxe7af5fcfd8dfc67530a01a0e403882687528dfcb

balance in decimal: 800460000000000000000000000

Great, they gave us the total supply, we have plenty of ICX to work with.

# Deploy the SCORE we just created

$ tbears deploy my_first_score/

You should see a similar message to this

If you want to check SCORE deployed successfully, execute txresult command

transaction hash: 0xb4563bc9994572ff4e9ca744628c388127b41f3072919a923a53f48f9f195085

Follow the instruction

$ tbears txresult 0xb4563bc9994572ff4e9ca744628c388127b41f3072919a923a53f48f9f195085

If you don’t see any error messages in the result JSON, the SCORE is successfully deployed to your localhost.

A convenient way to check which functions you can call on the SCORE is by querying its public methods through scoreapi ,

# Check SCORE API

$ tbears scoreapi cx4f1ac3681a51dbbca949c5b411e6a6dadcfd6d2b

You should see a ‘hello’ function

SCORE API: [

{

"type": "fallback",

"name": "fallback",

"inputs": []

},

{

"type": "function",

"name": "hello",

"inputs": [],

"outputs": [

{

"type": "str"

}

],

"readonly": "0x1"

}

]

This is a full list of external APIs in your SCORE, you can verify this by opening the my_first_score/my_first_score.py file, functions with @external decorator are exposed for public use.

Next we’ll make a call to this function through ICON JSON-RPC V3. First make a JSON file “call.json”, we’re going to call the hello function,

# call.json {

"jsonrpc": "2.0",

"method": "icx_call",

"params": {

"from": "hxe7af5fcfd8dfc67530a01a0e403882687528dfcb",

"to": "cx4f1ac3681a51dbbca949c5b411e6a6dadcfd6d2b",

"dataType": "call",

"data": {

"method": "hello"

}

},

"id": 1

}

Execute it with

$ tbears call call.json

The ‘hello’ function is executed and returns a string “Hello”.

response : {

"jsonrpc": "2.0",

"result": "Hello",

"id": 1

}

Next we’re going to try the tbears sendtx method, which invokes icx_sendTransaction ICON JSON-RPC method.

# Check SCORE balance first

$ tbears balance cx4f1ac3681a51dbbca949c5b411e6a6dadcfd6d2b

balance in decimal: 0

As expected, the contract has 0 balance. In the next exercise, we will purposely create some errors and fix them, you will learn a few more things that will be helpful when you debug your SCORE in the future. First create a new file send.json

Notice the value here takes hex format, you can use this tool to make the conversion from decimals. Unit Converter

# send.json {

"jsonrpc": "2.0",

"method": "icx_sendTransaction",

"params": {

"version": "0x3",

"from": "hxe7af5fcfd8dfc67530a01a0e403882687528dfcb",

"value": "0xde0b6b3a7640000",

"stepLimit": "0x200000",

"nid": "0x3",

"nonce": "0x1",

"to": "cx4f1ac3681a51dbbca949c5b411e6a6dadcfd6d2b",

"dataType": "call"

},

"id": 1

}

Now send this query through T-Bears CLI

$ tbears sendtx -k keystore_test1 send.json # default password is test1_Account

You should be prompted to enter your password for the keystore, the default password is: test1_Account

Now check the SCORE balance shortly, you probably expected to see 1 ICX

$ tbears balance cx4f1ac3681a51dbbca949c5b411e6a6dadcfd6d2b

balance in decimal: 0

Wait, something is wrong here. First thing to do in situation like this is to always check the transaction result first

$ tbears txresult 0x0c65bdb4de42cd773e22d07c92d5d80cf4bdaf2b6758535fe299fb40f5381914

which outputs

Transaction result: { ... "failure": {

"code": "0x7d64",

"message": "This is not payable"

}

the SCORE template by default has no payable methods to receive funds, let’s create a function in my_first_score/my_first_score.py

# my_first_score.py ... @external

@payable

def receive_funds(self) -> None:

Logger.debug(f'{self.msg.value} received from {self.msg.sender}', TAG)

Your file should look something like this

Then we’ll have to modify the method to call in the send.json file,

# send.json {

"jsonrpc": "2.0",

"method": "icx_sendTransaction",

"params": {

"version": "0x3",

"from": "hxe7af5fcfd8dfc67530a01a0e403882687528dfcb",

"value": "0xde0b6b3a7640000",

"stepLimit": "0x200000",

"nid": "0x3",

"nonce": "0x1",

"to": "cx4f1ac3681a51dbbca949c5b411e6a6dadcfd6d2b",

"dataType": "call",

"data": {

"method": "receive_funds"

}

},

"id": 1

}

Let’s try to send this request again,

$ tbears sendtx -k keystore_test1 send.json

Check the transaction result,

$tbears txresult 0xcbba1562a09adc6d8933812edd3d337ad8130d8cad89b154378a2ef2c1968174

Did it work?

"failure": {

"code": "0x7d00",

"message": "'FirstScore' object has no attribute 'receive_funds'"

}

Nope, the newly added function ‘receive_funds’ is not found. The reason is because we have already deployed the SCORE to our localhost node, making changes to SCORE definition will require an update to the smart contract (an unique feature in ICON, that is updatable smart contracts on the blockchain). We can do that by the ‘deploy’ command with specified deploy mode

$ tbears deploy my_first_score -m update -o cx4f1ac3681a51dbbca949c5b411e6a6dadcfd6d2b -k keystore_test1

Now the SCORE should be updated with our new receive_funds method, send the request again

$ tbears sendtx -k keystore_test1 send.json

now check the balance again,

$ tbears balance cx4f1ac3681a51dbbca949c5b411e6a6dadcfd6d2b

balance in decimal: 1000000000000000000

In this exercise we decided to implement a payable method to directly receive the funds, and making the JSON RPC API query with the ‘receive_funds’ method. Alternatively, if we do not specify

# send.json "data": {

"method": "receive_funds"

}

Without providing method to this query means no method is called, in this case, a fallback method will be called. This is designed to accept ICX transfers and other purposes (fallback cannot be decorated with @external so it cannot be queried from the outside). We could’ve implemented ‘fallback’ instead like so

# my_first_score.py @payable

def fallback(self):

...

Now if we make the JSON request without providing the method, this will be called and work similarly to ‘receive_funds’.

That’s it for T-Bears! We’ve learned how to use T-Bears CLI to create and deploy a SCORE, and perform various operations on it. We also learned how to make an ICON JSON-RPC API request to the RPC Server by invoking ICON Service methods. Message queue and block manager perform their operations behind the scenes so we won’t dive into those details in this tutorial. At this point we have all the necessarily tools to start building smart contracts on the ICON network. In the next tutorial, we’ll look into how to write a SCORE, how to deploy it to a remote testnet node(eventually mainnet), syntax, best practices and understand its limitations.