Json::Value doGetAccountBalance(RPC::JsonContext& context)
{
Json::Value result;
// Your implementation here
return result;
}
auto const account = parseBase58<AccountID>(
context.params[jss::account].asString()
);
if (!account) {
return rpcError(rpcACT_MALFORMED, "Invalid account address");
}
// Use *account to get the AccountID value
std::shared_ptr<ReadView const> ledger;
auto const result = RPC::lookupLedger(ledger, context);
if (!ledger) {
return result; // This already contains the error
}
// Now 'ledger' is safe to use
auto const sleAccount = ledger->read(keylet::account(*account));
if (!sleAccount) {
return rpcError(rpcACT_NOT_FOUND, "Account not found");
}
// sleAccount is a std::shared_ptr<SLE const>
// Get XRP balance
STAmount balance = sleAccount->getFieldAmount(sfBalance);
// Get sequence number
std::uint32_t sequence = sleAccount->getFieldU32(sfSequence);
// Get owner count
std::uint32_t ownerCount = sleAccount->getFieldU32(sfOwnerCount);
auto const& fees = ledger->fees();
// Base reserve (for the account itself)
XRPAmount baseReserve = fees.accountReserve(0);
// Owner reserve (base reserve × owner count)
XRPAmount ownerReserve = fees.accountReserve(ownerCount) - baseReserve;
// Total reserve
XRPAmount totalReserve = baseReserve + ownerReserve;
// Available balance
XRPAmount available = balance.xrp() - totalReserve;
// 1. Check if field exists
if (!context.params.isMember(jss::account)) {
return rpcError(rpcINVALID_PARAMS, "Missing 'account' field");
}
// 2. Check field type
if (!context.params[jss::account].isString()) {
return rpcError(rpcINVALID_PARAMS, "'account' must be a string");
}
// 3. Validate field value
auto const account = parseBase58<AccountID>(
context.params[jss::account].asString()
);
if (!account) {
return rpcError(rpcACT_MALFORMED, "Invalid account address");
}
// 4. Continue processing