Skip to content

Commit

Permalink
get_balances() whitelist + limit
Browse files Browse the repository at this point in the history
  • Loading branch information
madMAx43v3r committed Oct 19, 2024
1 parent 6aea15c commit b3cd5c9
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 61 deletions.
1 change: 0 additions & 1 deletion docs/TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ Mainnet
- Swap warning for one-sided pool
- VDF trust system (order queue by trust)
- Increase min_sync_peers to 5 after launch
- Node + Wallet get_balances() limit
- mmx_test framework
- 1000 commas for balances
- Binary line_info
Expand Down
11 changes: 7 additions & 4 deletions include/mmx/Node.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,16 @@ class Node : public NodeBase {

uint128 get_total_balance(const std::vector<addr_t>& addresses, const addr_t& currency) const override;

std::map<addr_t, uint128> get_balances(const addr_t& address) const override;
std::map<addr_t, uint128> get_balances(const addr_t& address, const std::set<addr_t>& whitelist, const int32_t& limit) const override;

std::map<addr_t, balance_t> get_contract_balances(const addr_t& address) const;
std::map<addr_t, balance_t> get_contract_balances(
const addr_t& address, const std::set<addr_t>& whitelist, const int32_t& limit) const;

std::map<addr_t, uint128> get_total_balances(const std::vector<addr_t>& addresses) const override;
std::map<addr_t, uint128> get_total_balances(
const std::vector<addr_t>& addresses, const std::set<addr_t>& whitelist, const int32_t& limit) const override;

std::map<std::pair<addr_t, addr_t>, uint128> get_all_balances(const std::vector<addr_t>& addresses) const override;
std::map<std::pair<addr_t, addr_t>, uint128> get_all_balances(
const std::vector<addr_t>& addresses, const std::set<addr_t>& whitelist, const int32_t& limit) const override;

std::vector<exec_entry_t> get_exec_history(const addr_t& address, const int32_t& limit, const vnx::bool_t& recent) const override;

Expand Down
10 changes: 5 additions & 5 deletions modules/Node.vni
Original file line number Diff line number Diff line change
Expand Up @@ -160,22 +160,22 @@ module Node implements vnx.addons.HttpComponent {
uint128 get_balance(addr_t address, addr_t currency) const;

@Permission(permission_e.PUBLIC)
map<addr_t, uint128> get_balances(addr_t address) const;
map<addr_t, uint128> get_balances(addr_t address, set<addr_t> whitelist, int limit = 100) const;

@Permission(permission_e.PUBLIC)
map<addr_t, balance_t> get_contract_balances(addr_t address) const;
map<addr_t, balance_t> get_contract_balances(addr_t address, set<addr_t> whitelist, int limit = 100) const;

@Permission(permission_e.PUBLIC)
uint128 get_total_balance(vector<addr_t> addresses, addr_t currency) const;

@Permission(permission_e.PUBLIC)
map<addr_t, uint128> get_total_balances(vector<addr_t> addresses) const;
map<addr_t, uint128> get_total_balances(vector<addr_t> addresses, set<addr_t> whitelist, int limit = 100) const;

@Permission(permission_e.PUBLIC)
map<pair<addr_t, addr_t>, uint128> get_all_balances(vector<addr_t> addresses) const;
map<pair<addr_t, addr_t>, uint128> get_all_balances(vector<addr_t> addresses, set<addr_t> whitelist, int limit = 100) const;

@Permission(permission_e.PUBLIC)
vector<exec_entry_t> get_exec_history(addr_t address, int limit = -1, bool recent) const;
vector<exec_entry_t> get_exec_history(addr_t address, int limit = 100, bool recent) const;

@Permission(permission_e.PUBLIC)
map<string, varptr_t> read_storage(addr_t contract, uint height = -1) const;
Expand Down
82 changes: 55 additions & 27 deletions src/Node_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,56 +613,84 @@ uint128 Node::get_total_balance(const std::vector<addr_t>& addresses, const addr
return total;
}

std::map<addr_t, uint128> Node::get_balances(const addr_t& address) const
std::map<addr_t, uint128> Node::get_balances(const addr_t& address, const std::set<addr_t>& whitelist, const int32_t& limit) const
{
return get_total_balances({address});
return get_total_balances({address}, whitelist, limit);
}

std::map<addr_t, balance_t> Node::get_contract_balances(const addr_t& address) const
std::map<addr_t, balance_t> Node::get_contract_balances(
const addr_t& address, const std::set<addr_t>& whitelist, const int32_t& limit) const
{
std::map<addr_t, balance_t> out;
const auto height = get_height() + 1;
const auto contract = get_contract(address);
for(const auto& entry : get_total_balances({address})) {
auto& tmp = out[entry.first];
if(contract) {
if(contract->is_locked(height)) {
tmp.locked = entry.second;
} else {
tmp.spendable = entry.second;
bool is_locked = false;
if(auto exec = get_contract_as<contract::Executable>(address)) {
if(auto bin = get_contract_as<contract::Binary>(exec->binary)) {
const std::string method = "is_locked";
if(vm::find_method(bin, method)) {
is_locked = call_contract(address, method, {}).to<bool>();
}
}
}
std::map<addr_t, balance_t> out;
for(const auto& entry : get_total_balances({address}, whitelist, limit)) {
const auto& amount = entry.second;
auto& balance = out[entry.first];
if(is_locked) {
balance.locked = amount;
} else {
tmp.spendable = entry.second;
balance.spendable = amount;
}
tmp.total = entry.second;
balance.total = amount;
balance.is_validated = !whitelist.empty();
}
return out;
}

std::map<addr_t, uint128> Node::get_total_balances(const std::vector<addr_t>& addresses) const
std::map<addr_t, uint128> Node::get_total_balances(
const std::vector<addr_t>& addresses, const std::set<addr_t>& whitelist, const int32_t& limit) const
{
std::map<addr_t, uint128> totals;
for(const auto& address : std::set<addr_t>(addresses.begin(), addresses.end())) {
std::vector<std::pair<std::pair<addr_t, addr_t>, uint128>> result;
balance_table.find_range(std::make_pair(address, addr_t()), std::make_pair(address, addr_t::ones()), result);
for(const auto& entry : result) {
if(entry.second) {
totals[entry.first.second] += entry.second;
if(whitelist.empty()) {
std::vector<std::pair<std::pair<addr_t, addr_t>, uint128>> result;
balance_table.find_range(std::make_pair(address, addr_t()), std::make_pair(address, addr_t::ones()), result, limit);
for(const auto& entry : result) {
if(entry.second) {
totals[entry.first.second] += entry.second;
}
}
} else {
for(const auto& currency : whitelist) {
uint128 balance;
balance_table.find(std::make_pair(address, currency), balance);
if(balance) {
totals[currency] += balance;
}
}
}
}
return totals;
}

std::map<std::pair<addr_t, addr_t>, uint128> Node::get_all_balances(const std::vector<addr_t>& addresses) const
std::map<std::pair<addr_t, addr_t>, uint128> Node::get_all_balances(
const std::vector<addr_t>& addresses, const std::set<addr_t>& whitelist, const int32_t& limit) const
{
std::map<std::pair<addr_t, addr_t>, uint128> totals;
for(const auto& address : std::set<addr_t>(addresses.begin(), addresses.end())) {
std::vector<std::pair<std::pair<addr_t, addr_t>, uint128>> result;
balance_table.find_range(std::make_pair(address, addr_t()), std::make_pair(address, addr_t::ones()), result);
for(const auto& entry : result) {
if(entry.second) {
totals[entry.first] += entry.second;
if(whitelist.empty()) {
std::vector<std::pair<std::pair<addr_t, addr_t>, uint128>> result;
balance_table.find_range(std::make_pair(address, addr_t()), std::make_pair(address, addr_t::ones()), result, limit);
for(const auto& entry : result) {
if(entry.second) {
totals[entry.first] += entry.second;
}
}
} else {
for(const auto& currency : whitelist) {
uint128 balance;
balance_table.find(std::make_pair(address, currency), balance);
if(balance) {
totals[std::make_pair(address, currency)] += balance;
}
}
}
}
Expand Down
14 changes: 5 additions & 9 deletions src/Wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,14 +640,14 @@ void Wallet::update_cache(const uint32_t& index) const
{
const auto height = node->get_height();
const auto addresses = wallet->get_all_addresses();
const auto balances = node->get_all_balances(addresses);
const auto balances = node->get_all_balances(addresses, token_whitelist);
const auto contracts = node->get_contracts_owned_by(addresses);
const auto liquidity = node->get_swap_liquidity_by(addresses);
const auto history = wallet->pending_tx.empty() ? std::vector<hash_t>() :
node->get_tx_ids_since(wallet->height - std::min(params->commit_delay, wallet->height));

wallet->external_balance_map.clear();
for(const auto& entry : node->get_total_balances(contracts)) {
for(const auto& entry : node->get_total_balances(contracts, token_whitelist)) {
wallet->external_balance_map[entry.first] += entry.second;
}
for(const auto& entry: liquidity) {
Expand Down Expand Up @@ -770,22 +770,18 @@ std::map<addr_t, balance_t> Wallet::get_balances(
std::map<addr_t, balance_t> Wallet::get_total_balances(const std::vector<addr_t>& addresses) const
{
std::map<addr_t, balance_t> amounts;
for(const auto& entry : node->get_total_balances(addresses)) {
for(const auto& entry : node->get_total_balances(addresses, token_whitelist)) {
auto& balance = amounts[entry.first];
balance.total = entry.second;
balance.spendable = balance.total;
balance.is_validated = token_whitelist.count(entry.first);
balance.is_validated = true;
}
return amounts;
}

std::map<addr_t, balance_t> Wallet::get_contract_balances(const addr_t& address) const
{
auto amounts = node->get_contract_balances(address);
for(auto& entry : amounts) {
entry.second.is_validated = token_whitelist.count(entry.first);
}
return amounts;
return node->get_contract_balances(address, token_whitelist);
}

std::map<addr_t, std::shared_ptr<const Contract>> Wallet::get_contracts(
Expand Down
36 changes: 21 additions & 15 deletions src/WebAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1351,32 +1351,38 @@ void WebAPI::http_request_async(std::shared_ptr<const vnx::addons::HttpRequest>
}
}
else if(sub_path == "/address") {
const auto iter = query.find("id");
if(iter != query.end()) {
const auto address = vnx::from_string_value<addr_t>(iter->second);
node->get_total_balances({address},
std::bind(&WebAPI::render_address, this, request_id, address, std::placeholders::_1),
const auto address = get_param<vnx::optional<addr_t>>(query, "id");
if(address) {
const auto limit = get_param<uint32_t>(query, "limit", 100);
if(is_public && limit > 1000) {
throw std::logic_error("limit > 1000");
}
node->get_total_balances({*address}, {}, limit,
std::bind(&WebAPI::render_address, this, request_id, *address, std::placeholders::_1),
std::bind(&WebAPI::respond_ex, this, request_id, std::placeholders::_1));
} else {
respond_status(request_id, 400, "address?id");
respond_status(request_id, 400, "address?id|limit");
}
}
else if(sub_path == "/balance") {
const auto iter_id = query.find("id");
const auto iter_currency = query.find("currency");
if(iter_id != query.end()) {
vnx::optional<addr_t> currency;
if(iter_currency != query.end()) {
currency = vnx::from_string<addr_t>(iter_currency->second);
const auto address = get_param<vnx::optional<addr_t>>(query, "id");
if(address) {
const auto limit = get_param<uint32_t>(query, "limit", 100);
const auto currency = get_param<vnx::optional<addr_t>>(query, "currency");
if(is_public && limit > 1000) {
throw std::logic_error("limit > 1000");
}
const auto address = vnx::from_string_value<addr_t>(iter_id->second);
node->get_contract_balances(address,
std::set<addr_t> whitelist;
if(currency) {
whitelist.insert(*currency);
}
node->get_contract_balances(*address, whitelist, limit,
[this, currency, request_id](const std::map<addr_t, balance_t>& balances) {
render_balances(request_id, currency, balances);
},
std::bind(&WebAPI::respond_ex, this, request_id, std::placeholders::_1));
} else {
respond_status(request_id, 400, "balance?id|currency");
respond_status(request_id, 400, "balance?id|currency|limit");
}
}
else if(sub_path == "/contract") {
Expand Down

0 comments on commit b3cd5c9

Please sign in to comment.