Eos Smart Contract Part 2, listening apply function, add and remove row from table
Hello Steemit friends so this is part 2 of the Eos smart contract tutorial, this time, we will be creating an "apply function" that will listen to any transaction or action that interact with the smart contract
for example
let say user A send 0.01 EOS into our smart contract "helloworld11", upon receiving EOS, our smart contract should automatically add one row of data into our table
the syntax should be like below
#undef EOSIO_ABI
#define EOSIO_ABI( TYPE, MEMBERS ) \
extern "C" { \
void apply( uint64_t receiver, uint64_t code, uint64_t action ) { \
auto self = receiver; \
TYPE thiscontract( self ); \
if( action == N(onerror)) { \
/* onerror is only valid if it is for the "eosio" code account and authorized by "eosio"'s "active permission */ \
eosio_assert(code == N(eosio), "onerror action's are only valid from the \"eosio\" system account"); \
} \
if( code == self ) { \
if (action != N(transfer)) {\
switch( action ) { \
EOSIO_API( TYPE, MEMBERS ) \
} \
/* does not allow destructor of thiscontract to run: eosio_exit(0); */ \
}\
} \
else if (code == N(eosio.token) && action == N(transfer) ) {\
execute_action(&thiscontract, &testtable2::droptable);\
}\
} \
}
the code must start with extern "C" because we want to makes a function-name in C++ have 'C' linkage
As you can see, when listening, we get 3 parameter which is the receiver, code and action
- Receiver = who get the money, which is us "helloworld11"
- Code = which smart contract the money belong to? the real EOS token belong to "EOSIO.TOKEN"
- action = what action ? for this case, we check if the action is "TRANSFER"
so upon receiving 0.01 EOS, our add function should look like below
[[eosio::action]]
void add()
{
auto transfer_data = eosio::unpack_action_data<st_transfer>();
std::string mymemo = transfer_data.memo;
std::string haha = "lalala";
datastore mystore(_self, _self);
//first param = who pay, second param = constructor
mystore.emplace(get_self(),[&](auto& p)
{
p.key =mystore.available_primary_key();
p.secondid = mystore.available_primary_key();
p.name = mymemo;
p.account = haha;
});
}
first we must have [[eosio::action]] on top of the function so ABI file can recognise this function,
then we have "auto transfer_data = eosio::unpack_action_data<st_transfer>();" this will unpack the transaction data into "transfer_data"
the "st_transfer" is the structure that we must declare and match, as we know when receiving 0.01 EOS, the sender must send 4 parameter which is "sender, receiver, amount, memo" so the "st_transfer" struct look like below
struct st_transfer {
account_name from;
account_name to;
asset quantity;
std::string memo;
};
then we can get the memo using syntax std::string mymemo = transfer_data.memo;
finally we add one row into the table using syntax emplace
full code is below
#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
#include <eosiolib/asset.hpp>
using namespace eosio;
class testtable2 : public eosio::contract {
public:
using contract::contract;
[[eosio::action]]
void hi( account_name user ) {
print( "Hello,STUPID ", name{user} );
}
[[eosio::action]]
void droptable()
{ datastore example(_self, _self); // code, scope
for(auto itr = example.begin(); itr != example.end();) {
itr = example.erase(itr);
}
}
[[eosio::action]]
void add()
{
auto transfer_data = eosio::unpack_action_data<st_transfer>();
std::string mymemo = transfer_data.memo;
std::string haha = "lalala";
datastore mystore(_self, _self);
//first param = who pay, second param = constructor
mystore.emplace(get_self(),[&](auto& p)
{
p.key =mystore.available_primary_key();
p.secondid = mystore.available_primary_key();
p.name = mymemo;
p.account = haha;
});
}
private:
struct st_transfer {
account_name from;
account_name to;
asset quantity;
std::string memo;
};
struct [[eosio::table]] mystruct
{
uint64_t key;
uint64_t secondid;
std::string name;
std::string account;
uint64_t primary_key() const { return key; } // getter for primary key
uint64_t by_id() const {return secondid; } // getter for additional key
EOSLIB_SERIALIZE(mystruct,(key)(secondid)(name)(account))
};
typedef eosio::multi_index<N(mystruct), mystruct> datastore;
};
#undef EOSIO_ABI
#define EOSIO_ABI( TYPE, MEMBERS ) \
extern "C" { \
void apply( uint64_t receiver, uint64_t code, uint64_t action ) { \
auto self = receiver; \
TYPE thiscontract( self ); \
if( action == N(onerror)) { \
/* onerror is only valid if it is for the "eosio" code account and authorized by "eosio"'s "active permission */ \
eosio_assert(code == N(eosio), "onerror action's are only valid from the \"eosio\" system account"); \
} \
if( code == self ) { \
if (action != N(transfer)) {\
switch( action ) { \
EOSIO_API( TYPE, MEMBERS ) \
} \
/* does not allow destructor of thiscontract to run: eosio_exit(0); */ \
}\
} \
else if (code == N(eosio.token) && action == N(transfer) ) {\
execute_action(&thiscontract, &testtable2::droptable);\
}\
} \
}
EOSIO_ABI( testtable2, (hi)(add)(droptable) )
so as you can see, i put everything inside folder "testtable2" and all code inside "testtable2.cpp"
to compile it i use below syntax
eosio-cpp -o testtable2.wasm testtable2.cpp --abigen
to deploy the smart contract to account "helloworld11" i use below syntax
cleos set contract helloworld11 ../testtable2 -p helloworld11@active
checking table
cleos get table helloworld11 helloworld11 mystruct
(so at first the table is empty)
sending 0.01 EOS from fundurianaaa to helloworld11
cleos push action eosio.token transfer '["fundurianaaa","helloworld11","0.0001 EOS","memo"]' -p fundurianaaa
then check table again
cleos get table helloworld11 helloworld11 mystruct
(this time i can see one row of data appear inside the table meaning our smart contract is working)
clean table
cleos push action helloworld11 droptable '{"user":"fundurianaaa"}' -p fundurianaaa
So thats all for today, by knowing how to listening to all transaction sending into your smart contract, you can do a lot of stuff already
thanks for reading
<br /><center><hr/><em>Posted from my blog with <a href='https://wordpress.org/plugins/steempress/'>SteemPress</a> : http://fundurian.vornix.blog/2018/10/17/eos-smart-contract-part-2-listening-apply-function-add-and-remove-row-from-table/ </em><hr/></center>