Skip to content

Instantly share code, notes, and snippets.

@clar
Created April 17, 2019 02:11
Show Gist options
  • Save clar/6032b4122a540841f654c144c1a70858 to your computer and use it in GitHub Desktop.
Save clar/6032b4122a540841f654c144c1a70858 to your computer and use it in GitHub Desktop.
mkforwarder
#include <eosiolib/eosio.hpp>
#include <eosiolib/asset.hpp>
#include <eosiolib/transaction.hpp>
#include <string>
using namespace eosio;
using namespace std;
#define _myself name("mykeyuseraaa")//("hellomykey11")
#define SENDER_ID(X, Y) ( ((uint128_t)X << 64) | Y )
time_point current_time_point() {
const static time_point ct{ microseconds{ static_cast<int64_t>( current_time() ) } };
return ct;
}
struct account {
asset balance;
uint64_t primary_key()const { return balance.symbol.code().raw(); }
};
typedef eosio::multi_index<name("accounts"), account> accounts;
class [[eosio::contract]] mkforwarder : public eosio::contract {
public:
using contract::contract;
struct [[eosio::table]] forward_request {
// uint64_t index;
name code; //token contract
asset quantity;
name from; //user account
name to; //exchange account
std::string memo;
time_point_sec create_time;
uint64_t primary_key()const { return from.value; }
EOSLIB_SERIALIZE( forward_request, (code)(quantity)(from)(to)(memo)(create_time) )
};
typedef eosio::multi_index< name("forwards"), forward_request > forwards_table;
// manually forward tx if deferred tx did not trigger
[[eosio::action]]
void forwardtx(name user) {
print("forwardtx is called.\n");
forwards_table forwards_tbl( _self, _self.value);
auto req = forwards_tbl.find(user.value );
eosio_assert( req != forwards_tbl.end(), "forward request not found" );
eosio_assert( req->create_time < current_time_point(), "time not due");
eosio::transaction out;
out.actions.emplace_back( permission_level{_self, name("active")}, req->code, name("transfer"), std::make_tuple(_self, req->to, req->quantity, req->memo) );
out.actions.emplace_back( permission_level{_myself, name("active")}, _myself, name("clear"), std::make_tuple(user) );
out.delay_sec = 0;
// out.send( req->to.value, _myself, true );
uint128_t sender_id = SENDER_ID(user.value, req->to.value);
cancel_deferred(sender_id);
out.send( sender_id, _myself, false );
}
[[eosio::action]]
void clear(name user) {
require_auth(_myself);
// clean up
mkforwarder::forwards_table forwards_tbl( _myself, _myself.value);
auto req = forwards_tbl.find( user.value );
// eosio_assert( req != forwards_tbl.end(), "forward request not found" );
if (req != forwards_tbl.end()) {
forwards_tbl.erase(req);
}
}
};
extern "C" {
struct transfer_action {
name from;
name to;
asset quantity;
std::string memo;
};
void on_transfer( transfer_action t, name code ) {
// if(t.from == _myself) {
// // clean up
// mkforwarder::forwards_table forwards_tbl( _myself, _myself.value);
// auto req = forwards_tbl.find( t..value );
// eosio_assert( req != forwards_tbl.end(), "forward request not found" );
// forwards_tbl.erase(req);
// }
if (t.to != _myself) {
return;
}
print(code.to_string(), "::transfer is called.\n");
// // get asset balance
// eosio::extended_asset exasset(t.quantity, code);
// exasset.print();
// print("\n");
// accounts acnts(exasset.contract, _myself.value);
// const auto& act = acnts.get(t.quantity.symbol.code().raw(), "no balance object found");
// // if asset exists before , reject tx
// if(act.balance > t.quantity) {
// std::string msg = exasset.quantity.to_string() + " exists before transfer";
// eosio_assert(false, msg.c_str());
// }
// memo example: ForwardTo:huobiaccount|123456
auto separator_pos = t.memo.find(':');
eosio_assert(separator_pos != string::npos, "memo format is invalid.");
string prefix = t.memo.substr(0, separator_pos);
string main_memo = t.memo.substr(separator_pos + 1);
eosio_assert(prefix == "ForwardTo", "only support 'ForwardTo' .");
separator_pos = main_memo.find('|');
eosio_assert(separator_pos != string::npos, "memo format is invalid.");
string sub_memo1 = main_memo.substr(0, separator_pos);
string sub_memo2 = main_memo.substr(separator_pos + 1);
eosio_assert( is_account( name(sub_memo1) ), "'sub_memo1' account does not exist");
mkforwarder::forwards_table forwards_tbl( _myself, _myself.value);
auto item = forwards_tbl.find(t.from.value);
eosio_assert(item == forwards_tbl.end(), "forward-request of account 'from' already exists!");
forwards_tbl.emplace( _myself, [&]( mkforwarder::forward_request& r ) {
r.code = code;
r.quantity = t.quantity;
r.from = t.from;
r.to = name(sub_memo1);
r.memo = sub_memo2;
r.create_time = current_time_point();
});
eosio::transaction out;
out.actions.emplace_back( permission_level{_myself, name("active")}, code, name("transfer"), std::make_tuple(_myself, name(sub_memo1), t.quantity, sub_memo2) );
out.actions.emplace_back( permission_level{_myself, name("active")}, _myself, name("clear"), std::make_tuple(t.from) );
out.delay_sec = 0;
uint128_t sender_id = SENDER_ID(t.from.value, name(sub_memo1).value);
cancel_deferred(sender_id);
out.send( sender_id, _myself, false );
}
void apply(uint64_t receiver, uint64_t code, uint64_t action) {
if (action == name("transfer").value) {
on_transfer( eosio::unpack_action_data<transfer_action>(), name(code) );
// eosio::execute_action( eosio::name(receiver), eosio::name(code), &test::transfer);
return;
}
else if( code == receiver ) {
switch( action ) {
EOSIO_DISPATCH_HELPER( mkforwarder, (forwardtx)(clear) )
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment