std::vector <RippleState::pointer> getRippleStateItems ( AccountID const& accountID, Ledger::ref ledger) { std::vector <RippleState::pointer> items; forEachItem(*ledger, accountID, getApp().getSLECache(), [&items,&accountID]( std::shared_ptr<SLE const> const&sleCur) { auto ret = RippleState::makeItem (accountID, sleCur); if (ret) items.push_back (ret); }); return items; }
Json::Value doGatewayBalances (RPC::Context& context) { auto& params = context.params; // Get the current ledger std::shared_ptr<ReadView const> ledger; auto result = RPC::lookupLedger (ledger, context); if (!ledger) return result; if (!(params.isMember (jss::account) || params.isMember (jss::ident))) return RPC::missing_field_error (jss::account); std::string const strIdent (params.isMember (jss::account) ? params[jss::account].asString () : params[jss::ident].asString ()); bool const bStrict = params.isMember (jss::strict) && params[jss::strict].asBool (); // Get info on account. AccountID accountID; auto jvAccepted = RPC::accountFromString (accountID, strIdent, bStrict); if (jvAccepted) return jvAccepted; context.loadType = Resource::feeHighBurdenRPC; result[jss::account] = getApp().accountIDCache().toBase58 (accountID); // Parse the specified hotwallet(s), if any std::set <AccountID> hotWallets; if (params.isMember ("hotwallet")) { Json::Value const& hw = params["hotwallet"]; bool valid = true; auto addHotWallet = [&valid, &hotWallets](Json::Value const& j) { if (j.isString()) { RippleAddress ra; if (ra.setAccountPublic (j.asString ())) { hotWallets.insert(calcAccountID(ra)); } else { auto const a =parseBase58<AccountID>(j.asString()); if (! a) valid = false; else hotWallets.insert(*a); } } else { valid = false; } }; if (hw.isArray()) { for (unsigned i = 0; i < hw.size(); ++i) addHotWallet (hw[i]); } else if (hw.isString()) { addHotWallet (hw); } else { valid = false; } if (! valid) { result[jss::error] = "invalidHotWallet"; return result; } } std::map <Currency, STAmount> sums; std::map <AccountID, std::vector <STAmount>> hotBalances; std::map <AccountID, std::vector <STAmount>> assets; // Traverse the cold wallet's trust lines { forEachItem(*ledger, accountID, [&](std::shared_ptr<SLE const> const& sle) { auto rs = RippleState::makeItem (accountID, sle); if (!rs) return; int balSign = rs->getBalance().signum(); if (balSign == 0) return; auto const& peer = rs->getAccountIDPeer(); // Here, a negative balance means the cold wallet owes (normal) // A positive balance means the cold wallet has an asset (unusual) if (hotWallets.count (peer) > 0) { // This is a specified hot wallt hotBalances[peer].push_back (-rs->getBalance ()); } else if (balSign > 0) { // This is a gateway asset assets[peer].push_back (rs->getBalance ()); } else { // normal negative balance, obligation to customer auto& bal = sums[rs->getBalance().getCurrency()]; if (bal == zero) { // This is needed to set the currency code correctly bal = -rs->getBalance(); } else bal -= rs->getBalance(); } }); } if (! sums.empty()) { Json::Value& j = (result [jss::obligations] = Json::objectValue); for (auto const& e : sums) { j[to_string (e.first)] = e.second.getText (); } } if (! hotBalances.empty()) { Json::Value& j = (result [jss::balances] = Json::objectValue); for (auto const& account : hotBalances) { Json::Value& balanceArray = (j[to_string (account.first)] = Json::arrayValue); for (auto const& balance : account.second) { Json::Value& entry = balanceArray.append (Json::objectValue); entry[jss::currency] = to_string (balance.issue ().currency); entry[jss::value] = balance.getText(); } } } if (! assets.empty()) { Json::Value& j = (result [jss::assets] = Json::objectValue); for (auto const& account : assets) { Json::Value& balanceArray = (j[to_string (account.first)] = Json::arrayValue); for (auto const& balance : account.second) { Json::Value& entry = balanceArray.append (Json::objectValue); entry[jss::currency] = to_string (balance.issue ().currency); entry[jss::value] = balance.getText(); } } } return result; }
Json::Value doGatewayBalances (RPC::Context& context) { auto& params = context.params; // Get the current ledger std::shared_ptr<ReadView const> ledger; auto result = RPC::lookupLedger (ledger, context); if (!ledger) return result; if (!(params.isMember (jss::account) || params.isMember (jss::ident))) return RPC::missing_field_error (jss::account); std::string const strIdent (params.isMember (jss::account) ? params[jss::account].asString () : params[jss::ident].asString ()); bool const bStrict = params.isMember (jss::strict) && params[jss::strict].asBool (); // Get info on account. AccountID accountID; auto jvAccepted = RPC::accountFromString (accountID, strIdent, bStrict); if (jvAccepted) return jvAccepted; context.loadType = Resource::feeHighBurdenRPC; result[jss::account] = context.app.accountIDCache().toBase58 (accountID); // Parse the specified hotwallet(s), if any std::set <AccountID> hotWallets; if (params.isMember (jss::hotwallet)) { auto addHotWallet = [&hotWallets](Json::Value const& j) { if (j.isString()) { auto const pk = parseBase58<PublicKey>( TokenType::TOKEN_ACCOUNT_PUBLIC, j.asString ()); if (pk) { hotWallets.insert(calcAccountID(*pk)); return true; } auto const id = parseBase58<AccountID>(j.asString()); if (id) { hotWallets.insert(*id); return true; } } return false; }; Json::Value const& hw = params[jss::hotwallet]; bool valid = true; if (hw.isArray()) { for (unsigned i = 0; i < hw.size(); ++i) valid &= addHotWallet (hw[i]); } else if (hw.isString()) { valid &= addHotWallet (hw); } else { valid = false; } if (! valid) { result[jss::error] = "invalidHotWallet"; return result; } } std::map <Currency, STAmount> sums; std::map <AccountID, std::vector <STAmount>> hotBalances; std::map <AccountID, std::vector <STAmount>> assets; std::map <AccountID, std::vector <STAmount>> frozenBalances; // Traverse the cold wallet's trust lines { forEachItem(*ledger, accountID, [&](std::shared_ptr<SLE const> const& sle) { auto rs = RippleState::makeItem (accountID, sle); if (!rs) return; int balSign = rs->getBalance().signum(); if (balSign == 0) return; auto const& peer = rs->getAccountIDPeer(); // Here, a negative balance means the cold wallet owes (normal) // A positive balance means the cold wallet has an asset (unusual) if (hotWallets.count (peer) > 0) { // This is a specified hot wallet hotBalances[peer].push_back (-rs->getBalance ()); } else if (balSign > 0) { // This is a gateway asset assets[peer].push_back (rs->getBalance ()); } else if (rs->getFreeze()) { // An obligation the gateway has frozen frozenBalances[peer].push_back (-rs->getBalance ()); } else { // normal negative balance, obligation to customer auto& bal = sums[rs->getBalance().getCurrency()]; if (bal == zero) { // This is needed to set the currency code correctly bal = -rs->getBalance(); } else bal -= rs->getBalance(); } }); } if (! sums.empty()) { Json::Value j; for (auto const& e : sums) { j[to_string (e.first)] = e.second.getText (); } result [jss::obligations] = std::move (j); } auto populate = []( std::map <AccountID, std::vector <STAmount>> const& array, Json::Value& result, Json::StaticString const& name) { if (!array.empty()) { Json::Value j; for (auto const& account : array) { Json::Value balanceArray; for (auto const& balance : account.second) { Json::Value entry; entry[jss::currency] = to_string (balance.issue ().currency); entry[jss::value] = balance.getText(); balanceArray.append (std::move (entry)); } j [to_string (account.first)] = std::move (balanceArray); } result [name] = std::move (j); } }; populate (hotBalances, result, jss::balances); populate (frozenBalances, result, jss::frozen_balances); populate (assets, result, jss::assets); return result; }