Interacting with EOS Contracts in EOSFactory

The purpose of this tutorial is to demonstrate how EOSFactory and its Python CLI can be used to make interacting with EOS easy & intuitive.

Prerequisites

  • This tutorial assumes that you have successfully installed EOSFactory. If it’s not the case, please refer to Installing EOSFactory.
  • We also assume that you are familiar with the official EOS tutorials, as they will give you a broader context and explain the rationale behind EOS smart-contracts.

Run Python CLI

Open a bash terminal (or if you are on Windows, open an Ubuntu bash terminal supplied by Windows Subsystem for Linux) and type python3 to run the Python CLI. The prompt should change to >>> signifying that it’s ready for Python commands.

Start Local Testnet

To start your own single-node local testnet:

import node
node.reset()

On MacOS the EOSIO process is run in the background with no visible interface. However in Ubuntu & Windows it’s launched in a separate window.

To verify the EOSIO node is running or to get information about the current state of the testnet:

node.info()

Manage Local Testnet

To stop the current testnet:

node.stop()

To continue running the same testnet:

node.run()

To stop the current testnet and start a new one:

node.reset()

Initialize Workspace

First, make sure a local testnet is running:

import node
node.reset()

Then you can initialize the workspace:

import sess
sess.init()

The initialization process does the following things:

  • deploys the Bios contract
  • creates a reference to the default eosio account, which can be accessed as sess.eosio,
  • creates several test accounts: alice, bob & carol, which can be accessed as sess.alice, sess.bob & sess.carol.
  • creates a wallet and imports into it the keys of all the above accounts

If you need to lock or unlock your wallet, use the wallet object to do it:

sess.wallet.lock()
sess.wallet.unlock()

NOTE: You don’t need to supply the password, as it’s kept for your convenience by Python. Obviously, this is only secure in a development environment.

Create test accounts

If you need additional test accounts different from the ones genereated by sess.init() , you can easily create them:

import eosf
charlie = eosf.account(sess.eosio)
sess.wallet.import_key(charlie)

You can print the details of an account, for example:

print(charlie.info())

NOTE: If you don’t specify the name parameter in eosf.account(), a random name will be applied (which is useful on a public testnet where extra restrictions apply). However if you want to assign a specific name to an account, you can still do it:

charlie = eosf.account(sess.eosio, name="charlie")

Create reference to the EOS Token Contract

We assume that a local testnet is running and it has been initialized:

import node, sess
node.reset()
sess.init()

To create a reference to an already compiled contract first create an account and import its key to a wallet:

import eosf
account = eosf.account(sess.eosio)
sess.wallet.import_key(account)

And then create the reference to an existing constract by supplying an account which will be holding the contract and the path to the folder where the contract is located:

contract = eosf.Contract(account, "/path/to/your/smart-contract/folder")

NOTE: You need to supply a valid path to the folder where your smart-contract is located, for example:

contract = eosf.Contract(account, "/mnt/d/Workspaces/EOS/eos/build/contracts/eosio.token")

Alternatively, supply just the name of the folder, if it can be found in a standard location, i.e. eos/build/contracts or eosfactory/contracts. This way you can have an easy access to all demo contracts that are shipped with both EOSIO and EOSFactory:

contract = eosf.Contract(account, "eosio.token")

Deploy the EOS Token Contract

At this stage the contract has no code deployed. You can check it by running its code() method:

contract.code()

To deploy the contract use its deploy() method:

contract.deploy()

And now you can verify that the hash of the deployed code is non-zero:

contract.code()

Create the EOS Token

To create a new token we call the create action on the eosio.token contract:

contract.push_action("create", '{"issuer":"' + str(sess.eosio) + '", "maximum_supply":"1000000000.0000 EOS", "can_freeze":0, "can_recall":0, "can_whitelist":0}')

NOTE: The push_action method takes two arguments: the action name and its arguments in JSON format. Optionally, you can also add a third argument, i.e. the account whose permission is needed, but in this case it’s not necessary, as the permission defaults to the account holding the contract.

NOTE: If you want to see the actual transaction without broadcasting it, use the show_action method instead of push_action.

Issue EOS Tokens

Now that we have created the token, the issuer can issue new tokens to alice:

contract.push_action("issue", '{"to":"' + str(sess.alice) + '", "quantity":"100.0000 EOS", "memo":"memo"}', sess.eosio)

NOTE: In this case the permission is assigned to the default eosio account.

Transfer EOS Tokens

Now that alice has tokens, we will transfer some of them to carol:

contract.push_action("transfer", '{"from":"' + str(sess.alice) + '", "to":"' + str(sess.carol) + '", "quantity":"25.0000 EOS", "memo":"memo"}', sess.alice)

NOTE: As the third argument we pass the reference to the alice account to indicate that she is the one who authorized this action.

Check the Contract Table

From the contract’s ABI we know that the table keeping track of the token balances is called accounts.

Let’s check the state of both accounts involved in the previous transaction:

contract.table("accounts", sess.alice)
contract.table("accounts", sess.carol)

NOTE: The table() method takes two arguments: the name of the table as specified by the contract ABI and the scope within the contract in which the table is found.

Exit Python CLI

To exit Python CLI:

exit()

Alternatively, use the ctrl-D shortcut.