Push a Transaction with delay on EOS blockchain

Push a Transaction with delay on EOS blockchain

Transaction EOS blockchain

Blockchain technology has a concept of transactions to store the data and make it immutable. The blockchain protocol EOS also transacts the data on blockchain but there are two types of transactions in EOS, Inline and transaction with delay. Inline transactions are those which get executed when you push them into blockchain and producers verify them whereas transactions with delay can be scheduled to get executed after a particular delay after which producers verify it and add them in the block.

 

In this article, we are gonna learn how to create a transaction with delay on EOS blockchain.

 

Smart contract

 

We will write a smart contract which contains a table to store the account holder name and summation of given numbers, our focus here is not to write complex actions so I choose simple addition action so that we can focus more on the transaction.

 

I am assuming that you know about the concept of public and private keys.

 

In this contract, we have two actions one is transfertxn that calls the main addition function after a given delay. Our addition action looks like:

 

//this action add two number a and b, save the sum in a table ttabs
//@param user account_name of person who sets the contract
//@param memo sender_id of transaction which will not be greater than 14 chars
//@param delay number of seconds by which you want to delay you transaction
//@param a integer number
//@param b integer number 

void addition(account_name user,std::string memo,uint64_t a , uint64_t b)
{
_table ttabs(_self,_self);
uint64_t sum = a+b;
auto iter=ttabs.find(user);
if(iter==ttabs.end()){
print(“now the sum is inserted _________________\t”);
ttabs.emplace(_self,[&](auto& sumtable){
sumtable.account = user;
sumtable.additionsum = sum;
});
}
else
{
ttabs.erase(iter);
print(“\n”);
}
}

 

Now, we need to create a table structure to store the data. Table structure looks like:

 

//this is a table structure that have two fields ,account and additionsum 

struct sumtable
{
account_name account;
uint64_t additionsum;
uint64_t primary_key() const {return account;}
EOSLIB_SERIALIZE(sumtable,(account)(additionsum))
};

 

Above table stores account and the addition of two numbers with primary key `account`. Now our transfertxn action looks like:

 

//transfertxn executes the transaction after the given delay
//@param from account_name of the person who set the contract //@param a integer number
//@param b integer number
//@param memo string sender_id what will you in future to cancel the transaction before given delay time
//@param delay, number of seconds(integer) 

void transfertxn(account_name from, uint64_t a, uint64_t b ,string memo, uint64_t delay)
{
eosio::transaction txn{};
txn.actions.emplace_back(
eosio::permission_level(from, N(active)),
N(testaccount),
N(addition),
std::make_tuple(from,memo,delay,a,b));
txn.delay_sec = delay;
txn.send(eosio::string_to_name(memo.c_str()), from);
print(“the transfertxn has been executed ___________\n”);
}

 

So let’s understand the transfertxn action.

 

Transaction struct

 

Now, we need to make a txn object of transaction which is defined in eosiolib/transaction.hpp. In this object, we add the action with appropriate parameters and set the delay as you can see in the above code. Now, let’s understand the action parameter one by one.

 

  • eosio::permission_level(from, N(active)): we set the permission of the account through which you want to push this transaction. Here it is `from`
  • N(testaccount): the account which was used to deploy the contract
  • N(addition): action to be called
  • std::make_tuple(from,memo,delay,a,b)): passing arguments to addition action

 

Finally, our tbsample.cpp file looks like:

 

#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
#include <eosiolib/transaction.hpp>
#include <eosiolib/print.hpp>
#include <string>

 

using namespace std;
using namespace eosio;

 

class benjamin: public eosio::contract
{
public:
using contract::contract;
/// @abi table sumtable i64
struct sumtable
{
account_name account;
uint64_t additionsum;
uint64_t primary_key() const { return account;
}
EOSLIB_SERIALIZE(sumtable, (account)(additionsum))
};

 

typedef multi_index<N(sumtable), sumtable> _table;
/// @abi action
void addition(account_name user, std::string memo, uint64_t delay, uint64_t a, uint64_t b)
{
_table ttabs(_self, _self);
uint64_t sum = a + b;
auto iter = ttabs.find(user);
if (iter == ttabs.end())
{
print(“now the sum is inserted _________\t”); ttabs.emplace(_self, [&](auto &sumtable) {
sumtable.account = user;
sumtable.additionsum = sum;
});
}
else
{
ttabs.erase(iter);
print(“\n”);
}
}

 

/// @abi action
void transfertxn(account_name from, uint64_t a, uint64_t b, string memo, uint64_t delay)
{
eosio::transaction txn{};
txn.actions.emplace_back(
eosio::permission_level(from, N(active)),
N(testaccount),
N(addition),
std::make_tuple(from, memo, delay, a, b));
txn.delay_sec = delay;
txn.send(eosio::string_to_name(memo.c_str()), from);
print(“the transaction has been executed _________________\n”);
}
};

 

EOSIO_ABI(benjamin, (addition)(transfertxn))

 

You can declare your actions in a separate .hpp file (header file) too. Now, let’s deploy and test it.

 

First, run the nodeos, below is the command to start nodeos

 

# nodeos -e -p eosio –plugin eosio::wallet_api_plugin –plugin eosio::chain_api_plugin contracts-console

 

Now, compile the wast and abi file for this contract.

 

# eosiocpp -o tbsample.wast tbsample.cpp
# eosiocpp -g tbsample.abi tbsample.cpp

 

Set the contract with account_name testaccount(my account name), before setting our contract our wallet must be unlocked. So let’s set the contract.

 

# cleos set contract testaccount tbsample ./tbsample/tbsample.wast ./tbsample/tbsample.abi

 

After setting the contract now it’s time to push our action to the blockchain nodes. For testing, I am passing a delay of 20 seconds.

 

# cleos push action testaccount transfertxn ‘[“testaccount”,10,20,”himessage”,20]’ -p testaccount

 

After execution of this command, you get a message similar to this.

 

executed transaction: 44203ea245cc95ffdb74e96643588b93c4df9b2a3ac08e222e5d38edb85d01df 184 bytes 1553 us
# testaccount <= testaccount::transfertxn {“from”:”testaccount”,”a”:10,”b”:20,”memo”:”himessage”,”delay”:20} >> the transfer has been executed ____________________________________________________
warning: transaction executed locally, but may not be confirmed by the network yet

 

Ignore the warnings if any, Now let’s come back to our contract, So we have pushed our action into the local blockchain, If you go to your nodeos terminal you can see your transaction running like this.

 

 

As we give the delay of 20 seconds in the transfertxn action, So after 20 seconds we added the two numbers and put them into the table. So after 20 seconds, your addition action will trigger and our nodeos window looks like this if works as intended.

 

 

To get the table data,

 

# cleos get table testaccount testaccount sumtable

 

So this is how transactions work. We also have a feature to cancel a transaction with delay

 

If you run into any issues getting the application working, feel free to write us on info@innoplexus.com.

 

Resources and references

 

1. EOS developers
2. EOS Stack Exchange

Author

Nirdesh Kumar

Blockchain Developer

Book a Free Consultation