Interacting with Public Testnet

The purpose of this tutorial is to demonstrate how EOSFactory can be used to deploy and test EOS smart-contracts on a public testnet, e.g. Jungle Testnet.

Prerequisites

  • This tutorial assumes that you have successfully installed EOSFactory. If it’s not the case, please refer to Installing EOSFactory.

  • We assume that you are familiar with the material covered in Interacting with EOS Contracts in EOSFactory and Building & Deploying EOS Contracts using EOSFactory.

  • We also assume you have Visual Studio Code installed. If you are on Windows and run VSC for the first time, in order to get access to Windows Subsystem for Linux bash terminal inside VSC, navigate to Preferences -> Settings and overwrite the default configuration for the terminal.integrated.shell.windows option:

    "terminal.integrated.shell.windows": "C:\\Windows\\sysnative\\bash.exe"
    

The problems with public testnet

To be able to create a new account on a public testnet you need an account name and two public keys (owner & active). The problem with account names is that they need to be unique and also comply with strict rules (e.g. [a-z1-5]{12} ).

Another problem is that you do not have full control of a public testnet (as is the case with a local private testnet), you cannot reset it any time you want and thus each time you use a public testnet for your smart-contract testing you need to either create a new set of accounts (which is ineffective and time consuming) or you need to carefully recycle the same set of accounts (each having a unique random name).

EOSFactory uses the latter approach and offers a built-in mechanism for mapping random account names to fixed names used in smart-contract testing. The mapping is stored in this location: ~/eosio-wallet/accounts.json.

Because of the above complexity we recommend sticking very strictly to the following procedure.

Create a new account on a public testnet

Open a bash terminal and run Python CLI:

python3

The prompt should change to >>> signifying that it’s ready for Python commands.

Then run the following set of commands.

import setup, eosf
setup.use_keosd(True)
setup.set_nodeos_URL("88.99.97.30:38888")
eosf.kill_keosd()
eosf.clear_account_mapping([])
wallet = eosf.Wallet("jungle_wallet")

NOTE: The 88.99.97.30:38888 URL is a CryptoLions endpoint to the Jungle Testnet. For public testnet we need to rely on the keosd toolset for wallet management, which means that your wallet will be stored in the ~/eosio-wallet folder. The name jungle_wallet can be replaced by any name you prefer - just make sure there is no naming conflict with any an existing wallet.

This is the outcome you should get:

Created wallet `jungle_wallet` with the `keosd` Wallet Manager.
Save password to use in the future to unlock this wallet.
Without password imported keys will not be retrievable.
PW5KDRWrMAev57rfJ8z9FXpRA1tEG4EJ6nsnpVAfYdHRe5WDMnnLz

NOTE: Your wallet password will obviously be different. Please store it in a secure place, as it will be needed in the subsequent step.

Next run this command:

account_master = eosf.AccountMaster()

Note the response containing the proposed values for the name of your primary testnet account and two public keys (owner and active):

Use the following data to register a new account on a public testnet:
Accout Name: zk3lmwma5fpb
Owner Public Key: EOS7MaUxbed3qVyFdh1xPDDEp8NygyFt2tNdMRs5JroPGWLfqJJej
Owner Private Key: 5JKMCuGQySyFaCUKorwoiKW1MHRFf1qH4daCo2Lmn36V8fBSF2D
Active Public Key: EOS7VmjcvCysaCBAPXy9UxSGtgsAEi79wd9cS4VrUN6iWGRemarE2
Active Private Key: 5KU4eMGPSw8z9UJfTc5pRBhkkXNEdVpKAQd9sCbeEFdVdXhBHAH

NOTE: As both the account name and it keys are generated randomly (to ensure their uniqueness on a public testnet) the above values will obviously be different each time you run the command.

Next, open the Jungle Testnet monitor in your web browser and create a new account there (select the Create Account menu option) using the above data for account name, owner public key and active public key. Then use the testnet faucet (select the Faucet menu option) to send some funds into the newly created account.

Next, navigate back to your Python terminal and run these commands:

wallet.unlock()
wallet.import_key(account_master)
wallet.restore_accounts(globals())

The outcome should look like this:

Restored accounts as global variables:
account_master (zk3lmwma5fpb)

What is happening here is the following: EOSFactory verifies that the given account exists on the public testnet and associates its random name (in this case zk3lmwma5fpb) with a variable name (in this case account_master).

Build the smart-contract

Open the eosfactory/contracts/tic_tac_toe_jungle folder in VS Code.

First, modify line 47 inside src/tic_tac_toe.hpp so that instead of the original tic.tac.toe account name it contains the name of the account you created on the testnet in the previous step:

static const account_name code_account = N(<your account name>);

For example:

static const account_name code_account = N(zk3lmwma5fpb);

NOTE: This is needed as the tic_tac_toe smart-contract example is bound to a specific account name defined in the header file. You cannot use the default account name tic.tac.toe, as it cannot be created on a public testnet, so you need to replace it with your own name.

Make sure you save the file after being modified.

Next, navigate to the tic_tac_toe_jungle/build folder and run CMake to build the contract:

cmake ..

And then:

make

Prepare unit tests

Edit the test/unittest1.py file and in lines 7 & 8 enter the name and password of the wallet created in the first step:

wallet_name = "<your wallet name>"
wallet_pass = "<your wallet password>"

For example:

wallet_name = "jungle_wallet"
wallet_pass = "PW5KDRWrMAev57rfJ8z9FXpRA1tEG4EJ6nsnpVAfYdHRe5WDMnnLz"

Perform similar amendments in the the test/test1.py file and make sure both files are saved after being modified.

Run unit tests

Finally, open a bash terminal, navigate to the tic_tac_toe_jungle/test folder and execute the content of the unittest1.py file:

python3 unittest1.py

This is what the final outcome should look like:

Ran 1 test in 2.223s
OK

Please note that line 9 of the unittest1.py file (as well as line 7 of the test1.py file) contains an important flag which determines whether contract deployment is included in the unit test setup phase:

deployment = True

In EOS contract deployment for a given account is allowed only once (unless the source code is changed and the contract is re-built). Therefore for a subsequent run remember to change this flag to False:

deployment = False

Otherwise you’ll get this error when trying to re-run the test:

assert(not contract.deploy().error)

Also, please note that during the initial run two additional accounts are created on the testnet. Their names are random (to ensure their uniqueness) but in the code they are referred to as account_alice and account_carol. During subsequent runs those two accounts are re-used.

You might also want to run the other (non-standard) test:

python3 test1.py

NOTE: If you’ve already run unittest1.py prior to that, please remember to set the deployment flag to False.

Run unit tests using CMake

You can also run both tests using the CMake utility.

To do that navigate to the tic_tac_toe_jungle/build folder and run:

ctest

This is the expected outcome:

Test project /mnt/d/Workspaces/EOS/eosfactory/contracts/tic_tac_toe_jungle/build
    Start 1: test
1/2 Test #1: test .............................   Passed    2.73 sec
    Start 2: unittest
2/2 Test #2: unittest .........................   Passed    5.51 sec

100% tests passed, 0 tests failed out of 2

Total Test time (real) =   8.25 sec

If you prefer more verbosity, use the -V flag:

ctest -V