Skip to content
This repository has been archived by the owner on Dec 11, 2021. It is now read-only.

Commit

Permalink
adding cycle function and billing function
Browse files Browse the repository at this point in the history
  • Loading branch information
alepacheco committed Jun 28, 2018
1 parent cdf7987 commit 740d013
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 63 deletions.
6 changes: 6 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
"command": "cleos --wallet-url=http://localhost:8899/ -u http://localhost:8888/ set contract exchangedeml ./bin/resource_exchange",
"problemMatcher": []
},
{
"label": "build & deploy",
"type": "shell",
"command": "eosiocpp -o bin/resource_exchange/resource_exchange.wast resource_exchange.cpp && eosiocpp -g bin/resource_exchange/resource_exchange.abi resource_exchange.cpp && cleos --wallet-url=http://localhost:8899/ -u http://localhost:8888/ set contract exchangedeml ./bin/resource_exchange",
"problemMatcher": []
},
{
"label": "set_eosio_code",
"type": "shell",
Expand Down
114 changes: 97 additions & 17 deletions resource_exchange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ void resource_exchange::apply(account_name contract, account_name act) {
calcost(tx);
break;
}
case N(calcosttoken): {
calcosttoken();
break;
}
case N(cycle): {
// TODO requiere auth..
cycle();
break;
}
}
}

Expand Down Expand Up @@ -78,7 +87,6 @@ void resource_exchange::withdraw(account_name to, asset quantity) {
contract_state.set(
state_t{state.liquid_funds - quantity, state.total_stacked}, _self);

// TODO first unstake some tokens, 3days later send
action(permission_level(_contract, N(active)), N(eosio.token), N(transfer),
std::make_tuple(_contract, to, quantity, std::string("")))
.send();
Expand Down Expand Up @@ -120,7 +128,6 @@ void resource_exchange::buystake(account_name from, asset net, asset cpu) {
tx.user = from;
tx.net = asset(0);
tx.cpu = asset(0);
tx.withdrawing = asset(0);
});
}

Expand All @@ -132,10 +139,10 @@ void resource_exchange::buystake(account_name from, asset net, asset cpu) {
"not enough resources in exchange");

asset cost = calcost(adj_net + adj_cpu);
eosio_assert((itr->balance - pending_itr->withdrawing) >= cost,
"not enough funds on account");
eosio_assert(itr->balance >= cost, "not enough funds on account");

print("Queing purchase of: ", net, " and ", cpu, " in stake for*: ", cost, "\n");
print("Queing purchase of: ", net, " and ", cpu, " in stake for*: ", cost,
"\n");
pendingtxs.modify(pending_itr, 0, [&](auto& tx) {
tx.net = adj_net;
tx.cpu = adj_cpu;
Expand All @@ -147,7 +154,6 @@ void resource_exchange::buystake(account_name from, asset net, asset cpu) {
_self);
}


void resource_exchange::sellstake(account_name user, asset net, asset cpu) {
// to sell reduce account resources, in next cycle he will pay the new usage
require_auth(user);
Expand Down Expand Up @@ -205,7 +211,8 @@ void resource_exchange::sellstake(account_name user, asset net, asset cpu) {
}

void resource_exchange::dobuystake(account_name user, asset net, asset cpu) {
// iter over accounts, compare with output of system listbw and modify accordinly
// iter over accounts, compare with output of system listbw and modify
// accordinly

// auto itr = accounts.find(from);
// eosio_assert(itr != accounts.end(), "account not found");
Expand All @@ -227,23 +234,84 @@ void resource_exchange::dobuystake(account_name user, asset net, asset cpu) {
// if no cash, remove state staked
}


void resource_exchange::reset_delayed_tx(pendingtx tx) {
// recover old state
}
void resource_exchange::cycle() {
// TODO
// get listbw
// cleos get table eosio {contract_name} delband
del_bandwidth_table dw_table(N(eosio), _self); // TODO test this

// itirate over accounts, check matching resources, else delegate undelegate
for(auto acnt = accounts.begin(); acnt != accounts.end(); ++acnt) {

// TODO
del_bandwidth_table dw_table(N(eosio), _self);

// itirate over accounts, check matching resources, else delegate
// undelegate

// bill account and then match real delegation
auto cost_per_token = calcosttoken();
for (auto acnt = accounts.begin(); acnt != accounts.end(); ++acnt) {
print("account: ", name{acnt->owner}, "\n");
billaccount(acnt->owner, cost_per_token);
// now check with delegate_table and do changes to match
}

// itirate over pending orders, fill them and modify accounts
// pay hodlers
}

void resource_exchange::billaccount(account_name owner, double cost_per_token) {
auto acnt = accounts.find(owner);
auto pending_itr = pendingtxs.find(acnt->owner);

auto cost_all = asset(cost_per_token * acnt->get_all().amount);
asset extra_net = asset(0);
asset extra_cpu = asset(0);
//print("all: ", cost_all.amount, " ", cost_per_token);

if (pending_itr != pendingtxs.end()) {
//print("pending: ", pending_itr->get_all().amount);
cost_all += asset(cost_per_token * pending_itr->get_all().amount);
extra_net += pending_itr->net;
extra_cpu += pending_itr->cpu;
}
eosio_assert(cost_all.amount >= 0, "cost negative");
print("cost: ", cost_all, "\n");
if (acnt->balance >= cost_all) {
// has cash, buy
print("buyin all\n");
accounts.modify(acnt, 0, [&](auto& account) {
account.balance -= cost_all;
account.resource_net += extra_net;
account.resource_cpu += extra_cpu;
});
} else {
// no cash, cancel tx, try pay for account only
reset_delayed_tx(*pending_itr); // reset stake change of tx
asset cost_account = calcost(acnt->get_all());
if (acnt->balance >= cost_account) {
// pay for account
accounts.modify(acnt, 0,
[&](auto& account) { account.balance -= cost_account; });
} else {
// no cash: reset account
auto state = contract_state.get();
contract_state.set(
state_t{
state.liquid_funds + (acnt->resource_net + acnt->resource_cpu),
state.total_stacked - (acnt->resource_net + acnt->resource_cpu)},
_self);
accounts.modify(acnt, 0, [&](auto& account) {
account.resource_net = asset(0);
account.resource_cpu = asset(0);
});
}
}
// delete tx
if (pending_itr != pendingtxs.end()) {
pendingtxs.erase(pending_itr);
}
}

asset resource_exchange::calcost(asset resources) {
if (resources <= asset(0)) {
return asset(0);
}
eosio_assert(contract_state.exists(), "No contract state available");
int PURCHASE_STEP = 10000; // the lower the more persice but more cpu
int PRICE_TUNE = 100;
Expand All @@ -267,6 +335,18 @@ asset resource_exchange::calcost(asset resources) {
print("price: ", price, "\n");
return price;
}

double resource_exchange::calcosttoken() {
eosio_assert(contract_state.exists(), "No contract state available");
int PRICE_TUNE = 100;
auto state = contract_state.get();
double liquid = state.liquid_funds.amount;
double total = state.get_total().amount;
double cost_per_token = ((total * total / liquid) / (total * PRICE_TUNE)); // TODO find optimal function

print("price token: ", asset(cost_per_token * 10000), "\n");
return cost_per_token;
}
} // namespace eosio

extern "C" {
Expand Down
100 changes: 54 additions & 46 deletions resource_exchange.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,29 @@ class resource_exchange : public eosio::contract {
private:
account_name _contract;

void delegatebw(account_name receiver, asset stake_net_quantity,
asset stake_cpu_quantity);
void undelegatebw(account_name receiver, asset stake_net_quantity,
asset stake_cpu_quantity);

void dobuystake(account_name user, asset net, asset cpu);

public:
resource_exchange(account_name self)
: _contract(self),
eosio::contract(self),
accounts(_self, _self),
pendingtxs(_self, _self),
contract_state(_self, _self) {}
struct stake_trade {
account_name user;
asset net;
asset cpu;
};

struct withdraw_tx {
account_name user;
asset quantity;
};

//@abi table pendingtx i64
struct pendingtx {
pendingtx(account_name o = account_name()) : user(o) {}
account_name user;
asset net;
asset cpu;
asset get_all() const { return cpu + net; }

uint64_t primary_key() const { return user; }
EOSLIB_SERIALIZE(pendingtx, (user)(net)(cpu))
};

//@abi table state i64
struct state_t {
asset liquid_funds;
Expand All @@ -36,60 +39,62 @@ class resource_exchange : public eosio::contract {
EOSLIB_SERIALIZE(state_t, (liquid_funds)(total_stacked))
};

struct stake_trade {
account_name user;
asset net;
asset cpu;
};

//@abi table account i64
struct account {
account(account_name o = account_name()) : owner(o) {}
struct account_t {
account_t(account_name o = account_name()) : owner(o) {}
account_name owner;
asset balance = asset(0);
asset resource_net = asset(0);
asset resource_cpu = asset(0);
asset get_all() const { return resource_cpu + resource_net; }

bool is_empty() const {
return !(balance.amount | resource_net.amount | resource_cpu.amount);
}

uint64_t primary_key() const { return owner; }
EOSLIB_SERIALIZE(account, (owner)(balance)(resource_net)(resource_cpu))
EOSLIB_SERIALIZE(account_t, (owner)(balance)(resource_net)(resource_cpu))
};

//@abi table pendingtx i64
struct pendingtx {
pendingtx(account_name o = account_name()) : user(o) {}
account_name user;
asset net;
asset cpu;
asset withdrawing; // positive mumber, but withdrawing

uint64_t primary_key() const { return user; }
EOSLIB_SERIALIZE(pendingtx, (user)(net)(cpu)(withdrawing))
// FIXME import this
struct delegated_bandwidth {
account_name from;
account_name to;
asset net_weight;
asset cpu_weight;
uint64_t primary_key() const { return to; }
EOSLIB_SERIALIZE(delegated_bandwidth, (from)(to)(net_weight)(cpu_weight))
};
// FIXME import this
typedef eosio::multi_index<N(delband), delegated_bandwidth>
del_bandwidth_table;

typedef singleton<N(state_t), state_t> state_index;
typedef singleton<N(state), state_t> state_index;
state_index contract_state;

typedef eosio::multi_index<N(account), account> account_index;
typedef eosio::multi_index<N(account), account_t> account_index;
account_index accounts;

typedef eosio::multi_index<N(pendingtx), pendingtx> pendingtx_index;
pendingtx_index pendingtxs;

// FIXME import this
struct delegated_bandwidth {
account_name from;
account_name to;
asset net_weight;
asset cpu_weight;
uint64_t primary_key()const { return to; }
EOSLIB_SERIALIZE( delegated_bandwidth, (from)(to)(net_weight)(cpu_weight) )
};
// FIXME import this
typedef eosio::multi_index< N(delband), delegated_bandwidth> del_bandwidth_table;
void delegatebw(account_name receiver, asset stake_net_quantity,
asset stake_cpu_quantity);
void undelegatebw(account_name receiver, asset stake_net_quantity,
asset stake_cpu_quantity);

void dobuystake(account_name user, asset net, asset cpu);

void reset_delayed_tx(pendingtx tx);
void billaccount(account_name account, double cost_per_token);

public:
resource_exchange(account_name self)
: _contract(self),
eosio::contract(self),
accounts(_self, _self),
pendingtxs(_self, _self),
contract_state(_self, _self) {}

void apply(account_name contract, account_name act);
void deposit(currency::transfer tx);
Expand All @@ -106,6 +111,9 @@ class resource_exchange : public eosio::contract {
/// @abi action
asset calcost(asset res);

/// @abi action
double calcosttoken();

/// @abi action
void cycle();
};
Expand Down

0 comments on commit 740d013

Please sign in to comment.