Created
April 17, 2019 02:11
-
-
Save clar/6032b4122a540841f654c144c1a70858 to your computer and use it in GitHub Desktop.
mkforwarder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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