From 75d6faabe0cba3818bd9df4b7e9e49766bd2dd0b Mon Sep 17 00:00:00 2001 From: Dcorral Date: Mon, 6 Jun 2022 15:28:56 +0200 Subject: [PATCH 1/9] Add optional flag includeTokenId for listaccounthistory --- src/masternodes/govvariables/attributes.cpp | 2 +- src/masternodes/rpc_accounts.cpp | 55 ++++++++++++++------- src/masternodes/rpc_vault.cpp | 4 +- test/functional/rpc_getaccounthistory.py | 9 +++- 4 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/masternodes/govvariables/attributes.cpp b/src/masternodes/govvariables/attributes.cpp index 216e88c7b87..ce5f3bd931e 100644 --- a/src/masternodes/govvariables/attributes.cpp +++ b/src/masternodes/govvariables/attributes.cpp @@ -13,7 +13,7 @@ #include /// ValueFromAmount #include -extern UniValue AmountsToJSON(TAmounts const & diffs); +extern UniValue AmountsToJSON(TAmounts const & diffs, bool include_token_id = false); static inline std::string trim_all_ws(std::string s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { diff --git a/src/masternodes/rpc_accounts.cpp b/src/masternodes/rpc_accounts.cpp index 8144fc7f11e..f5590387329 100644 --- a/src/masternodes/rpc_accounts.cpp +++ b/src/masternodes/rpc_accounts.cpp @@ -2,22 +2,23 @@ #include #include -std::string tokenAmountString(CTokenAmount const& amount) { +std::string tokenAmountString(CTokenAmount const& amount, bool with_token_id = false) { const auto token = pcustomcsview->GetToken(amount.nTokenId); - const auto valueString = ValueFromAmount(amount.nValue).getValStr(); - return valueString + "@" + token->CreateSymbolKey(amount.nTokenId); + const auto amountString = ValueFromAmount(amount.nValue).getValStr(); + const auto tokenString = with_token_id ? amount.nTokenId.ToString() : token->CreateSymbolKey(amount.nTokenId); + return amountString + "@" + tokenString; } -UniValue AmountsToJSON(TAmounts const & diffs) { +UniValue AmountsToJSON(TAmounts const & diffs, bool with_token_id = false) { UniValue obj(UniValue::VARR); for (auto const & diff : diffs) { - obj.push_back(tokenAmountString({diff.first, diff.second})); + obj.push_back(tokenAmountString({diff.first, diff.second}, with_token_id)); } return obj; } -UniValue accountToJSON(CScript const& owner, CTokenAmount const& amount, bool verbose, bool indexed_amounts) { +UniValue accountToJSON(CScript const& owner, CTokenAmount const& amount, bool verbose, bool indexed_amounts, bool include_token_id = false) { // encode CScript into JSON UniValue ownerObj(UniValue::VOBJ); ScriptPubKeyToUniv(owner, ownerObj, true); @@ -43,10 +44,14 @@ UniValue accountToJSON(CScript const& owner, CTokenAmount const& amount, bool ve obj.pushKV("amount", tokenAmountString(amount)); } + if (include_token_id) { + obj.pushKV("amount_with_id", tokenAmountString(amount, include_token_id)); + } + return obj; } -UniValue accounthistoryToJSON(AccountHistoryKey const & key, AccountHistoryValue const & value) { +UniValue accounthistoryToJSON(AccountHistoryKey const & key, AccountHistoryValue const & value, bool include_token_id = false) { UniValue obj(UniValue::VOBJ); obj.pushKV("owner", ScriptToString(key.owner)); @@ -59,10 +64,12 @@ UniValue accounthistoryToJSON(AccountHistoryKey const & key, AccountHistoryValue obj.pushKV("txn", (uint64_t) key.txn); obj.pushKV("txid", value.txid.ToString()); obj.pushKV("amounts", AmountsToJSON(value.diff)); + if(include_token_id) + obj.pushKV("amounts_with_id", AmountsToJSON(value.diff, include_token_id)); return obj; } -UniValue rewardhistoryToJSON(CScript const & owner, uint32_t height, DCT_ID const & poolId, RewardType type, CTokenAmount amount) { +UniValue rewardhistoryToJSON(CScript const & owner, uint32_t height, DCT_ID const & poolId, RewardType type, CTokenAmount amount, bool include_token_id = false) { UniValue obj(UniValue::VOBJ); obj.pushKV("owner", ScriptToString(owner)); obj.pushKV("blockHeight", (uint64_t) height); @@ -77,10 +84,12 @@ UniValue rewardhistoryToJSON(CScript const & owner, uint32_t height, DCT_ID cons obj.pushKV("poolID", poolId.ToString()); TAmounts amounts({{amount.nTokenId,amount.nValue}}); obj.pushKV("amounts", AmountsToJSON(amounts)); + if (include_token_id) + obj.pushKV("amounts_with_id", AmountsToJSON(amounts, include_token_id)); return obj; } -UniValue outputEntryToJSON(COutputEntry const & entry, CBlockIndex const * index, CWalletTx const * pwtx) { +UniValue outputEntryToJSON(COutputEntry const & entry, CBlockIndex const * index, CWalletTx const * pwtx, bool include_token_id = false) { UniValue obj(UniValue::VOBJ); obj.pushKV("owner", EncodeDestination(entry.destination)); @@ -98,6 +107,8 @@ UniValue outputEntryToJSON(COutputEntry const & entry, CBlockIndex const * index obj.pushKV("txid", pwtx->GetHash().ToString()); TAmounts amounts({{DCT_ID{0},entry.amount}}); obj.pushKV("amounts", AmountsToJSON(amounts)); + if (include_token_id) + obj.pushKV("amounts_with_id", AmountsToJSON(amounts, include_token_id)); return obj; } @@ -299,9 +310,6 @@ UniValue listaccounts(const JSONRPCRequest& request) { including_start = false; start = decodeBalanceKey(paginationObj["start"].get_str()); } - if (!paginationObj["including_start"].isNull()) { - including_start = paginationObj["including_start"].getBool(); - } if (!including_start) { start.tokenID.v++; } @@ -968,6 +976,9 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { "Maximum number of records to return, 100 by default"}, {"txn", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Order in block, unlimited by default"}, + {"includeTokenId", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, + "Include extra field with amounts containing token id (default = false)"}, + }, }, }, @@ -998,6 +1009,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { uint32_t limit = 100; auto txType = CustomTxType::None; uint32_t txn = std::numeric_limits::max(); + bool includeTokenId = false; if (request.params.size() > 1) { UniValue optionsObj = request.params[1].get_obj(); @@ -1010,6 +1022,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { {"txtype", UniValueType(UniValue::VSTR)}, {"limit", UniValueType(UniValue::VNUM)}, {"txn", UniValueType(UniValue::VNUM)}, + {"includeTokenId", UniValueType(UniValue::VBOOL)} }, true, true); if (!optionsObj["maxBlockHeight"].isNull()) { @@ -1045,6 +1058,10 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { if (!optionsObj["txn"].isNull()) { txn = (uint32_t) optionsObj["txn"].get_int64(); } + + if (!optionsObj["includeTokenId"].isNull()) { + includeTokenId = optionsObj["includeTokenId"].get_bool(); + } } std::function isMatchOwner = [](CScript const &) { @@ -1147,7 +1164,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { if (accountRecord && (tokenFilter.empty() || hasToken(value.diff))) { auto& array = ret.emplace(workingHeight, UniValue::VARR).first->second; - array.push_back(accounthistoryToJSON(key, value)); + array.push_back(accounthistoryToJSON(key, value, includeTokenId)); if (shouldSearchInWallet) { txs.insert(value.txid); } @@ -1159,7 +1176,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { [&](int32_t height, DCT_ID poolId, RewardType type, CTokenAmount amount) { if (tokenFilter.empty() || hasToken({{amount.nTokenId, amount.nValue}})) { auto& array = ret.emplace(height, UniValue::VARR).first->second; - array.push_back(rewardhistoryToJSON(key.owner, height, poolId, type, amount)); + array.push_back(rewardhistoryToJSON(key.owner, height, poolId, type, amount, includeTokenId)); count ? --count : 0; } } @@ -1203,7 +1220,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { return true; } auto& array = ret.emplace(index->nHeight, UniValue::VARR).first->second; - array.push_back(outputEntryToJSON(entry, index, pwtx)); + array.push_back(outputEntryToJSON(entry, index, pwtx, includeTokenId)); return --count != 0; } ); @@ -1821,7 +1838,7 @@ UniValue getburninfo(const JSONRPCRequest& request) { } for (const auto& kv : Params().GetConsensus().newNonUTXOSubsidies) { - if (kv.first == CommunityAccountType::Unallocated || + if (kv.first == CommunityAccountType::Unallocated || kv.first == CommunityAccountType::IncentiveFunding || (height >= fortCanningHeight && kv.first == CommunityAccountType::Loan)) { burnt += view.GetCommunityBalance(kv.first); @@ -1876,10 +1893,10 @@ UniValue getburninfo(const JSONRPCRequest& request) { return true; }; - AccountHistoryKey startKey{{}, - std::numeric_limits::max(), + AccountHistoryKey startKey{{}, + std::numeric_limits::max(), std::numeric_limits::max()}; - + burnView->ForEachAccountHistory(calculateBurnAmounts, startKey); UniValue result(UniValue::VOBJ); diff --git a/src/masternodes/rpc_vault.cpp b/src/masternodes/rpc_vault.cpp index 838a5b251b9..b2a2bc53351 100644 --- a/src/masternodes/rpc_vault.cpp +++ b/src/masternodes/rpc_vault.cpp @@ -3,8 +3,8 @@ #include #include -extern UniValue AmountsToJSON(TAmounts const & diffs); -extern std::string tokenAmountString(CTokenAmount const& amount); +extern UniValue AmountsToJSON(TAmounts const & diffs, bool include_token_id = false); +extern std::string tokenAmountString(CTokenAmount const& amount, bool include_token_id = false); namespace { diff --git a/test/functional/rpc_getaccounthistory.py b/test/functional/rpc_getaccounthistory.py index 03bfd9bd11b..83b899f687d 100755 --- a/test/functional/rpc_getaccounthistory.py +++ b/test/functional/rpc_getaccounthistory.py @@ -53,7 +53,14 @@ def run_test(self): self.nodes[0].generate(1) # Get node 0 results - results = self.nodes[0].listaccounthistory(collateral_a) + results = self.nodes[0].listaccounthistory(collateral_a, {"includeTokenId": True} ) + # test token ids match token symbol + for result in results: + amounts_with_id = result["amounts_with_id"] + for index, amount in enumerate(result["amounts"]): + symbol = amount.split('@')[1] + id = list(self.nodes[0].gettoken(symbol).keys())[0] + assert_equal(amounts_with_id[index].split("@")[1], id) # An account history from listaccounthistory and gettaccounthistory must be matched expected = results[0] From d63fe127a0105f4900be0a9177a4484c10b0f024 Mon Sep 17 00:00:00 2001 From: Dcorral Date: Fri, 10 Jun 2022 00:16:00 +0200 Subject: [PATCH 2/9] Fix listaccounts pagination --- src/masternodes/rpc_accounts.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/masternodes/rpc_accounts.cpp b/src/masternodes/rpc_accounts.cpp index f5590387329..e3c32eb1e78 100644 --- a/src/masternodes/rpc_accounts.cpp +++ b/src/masternodes/rpc_accounts.cpp @@ -310,6 +310,9 @@ UniValue listaccounts(const JSONRPCRequest& request) { including_start = false; start = decodeBalanceKey(paginationObj["start"].get_str()); } + if (!paginationObj["including_start"].isNull()) { + including_start = paginationObj["including_start"].getBool(); + } if (!including_start) { start.tokenID.v++; } From 997c200c369a47c4a390dc1a6fdc897edd4dd418 Mon Sep 17 00:00:00 2001 From: Dcorral Date: Mon, 13 Jun 2022 18:17:46 +0200 Subject: [PATCH 3/9] Modifies flag for formating amounts in listaccounthistory --- src/masternodes/govvariables/attributes.cpp | 3 +- src/masternodes/mn_rpc.h | 10 +++ src/masternodes/rpc_accounts.cpp | 78 ++++++++++++--------- src/masternodes/rpc_vault.cpp | 4 +- test/functional/rpc_getaccounthistory.py | 29 +++++--- 5 files changed, 81 insertions(+), 43 deletions(-) diff --git a/src/masternodes/govvariables/attributes.cpp b/src/masternodes/govvariables/attributes.cpp index 7d56396813a..536e72aa7a3 100644 --- a/src/masternodes/govvariables/attributes.cpp +++ b/src/masternodes/govvariables/attributes.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file LICENSE or http://www.opensource.org/licenses/mit-license.php. +#include #include #include /// CAccountsHistoryWriter @@ -13,7 +14,7 @@ #include /// ValueFromAmount #include -extern UniValue AmountsToJSON(TAmounts const & diffs, bool include_token_id = false); +extern UniValue AmountsToJSON(TAmounts const & diffs, AmountFormat format = AmountFormat::Id); static inline std::string trim_all_ws(std::string s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { diff --git a/src/masternodes/mn_rpc.h b/src/masternodes/mn_rpc.h index 7a2cb3f8fa1..b77296c1afb 100644 --- a/src/masternodes/mn_rpc.h +++ b/src/masternodes/mn_rpc.h @@ -35,6 +35,16 @@ typedef enum { SelectionPie, } AccountSelectionMode; +enum class AmountFormat : uint8_t { + // amount@0 + Id = (1 << 0), + // amount@DFI + Symbol = (2 << 1), + // amount@0#DFI + Combined = (3 << 2), + Unknown = 0 +}; + class CWalletCoinsUnlocker { std::shared_ptr pwallet; std::vector coins; diff --git a/src/masternodes/rpc_accounts.cpp b/src/masternodes/rpc_accounts.cpp index 8b27bec2de4..56437d4c1d1 100644 --- a/src/masternodes/rpc_accounts.cpp +++ b/src/masternodes/rpc_accounts.cpp @@ -2,23 +2,38 @@ #include #include -std::string tokenAmountString(CTokenAmount const& amount, bool with_token_id = false) { +std::string tokenAmountString(CTokenAmount const& amount, AmountFormat format = AmountFormat::Id) { const auto token = pcustomcsview->GetToken(amount.nTokenId); const auto amountString = ValueFromAmount(amount.nValue).getValStr(); - const auto tokenString = with_token_id ? amount.nTokenId.ToString() : token->CreateSymbolKey(amount.nTokenId); - return amountString + "@" + tokenString; + + std::string tokenStr = {}; + switch (format) { + case AmountFormat::Id: + tokenStr = amount.nTokenId.ToString(); + break; + case AmountFormat::Symbol: + tokenStr = token->CreateSymbolKey(amount.nTokenId); + break; + case AmountFormat::Combined: + tokenStr = amount.nTokenId.ToString() + "#" + token->CreateSymbolKey(amount.nTokenId); + break; + case AmountFormat::Unknown: + tokenStr = "unknown"; + break; + } + return amountString + "@" + tokenStr; } -UniValue AmountsToJSON(TAmounts const & diffs, bool with_token_id = false) { +UniValue AmountsToJSON(TAmounts const & diffs, AmountFormat format = AmountFormat::Id) { UniValue obj(UniValue::VARR); for (auto const & diff : diffs) { - obj.push_back(tokenAmountString({diff.first, diff.second}, with_token_id)); + obj.push_back(tokenAmountString({diff.first, diff.second}, format)); } return obj; } -UniValue accountToJSON(CScript const& owner, CTokenAmount const& amount, bool verbose, bool indexed_amounts, bool include_token_id = false) { +UniValue accountToJSON(CScript const& owner, CTokenAmount const& amount, bool verbose, bool indexed_amounts,AmountFormat format = AmountFormat::Id) { // encode CScript into JSON UniValue ownerObj(UniValue::VOBJ); ScriptPubKeyToUniv(owner, ownerObj, true); @@ -41,17 +56,13 @@ UniValue accountToJSON(CScript const& owner, CTokenAmount const& amount, bool ve obj.pushKV("amount", amountObj); } else { - obj.pushKV("amount", tokenAmountString(amount)); - } - - if (include_token_id) { - obj.pushKV("amount_with_id", tokenAmountString(amount, include_token_id)); + obj.pushKV("amount", tokenAmountString(amount, format)); } return obj; } -UniValue accounthistoryToJSON(AccountHistoryKey const & key, AccountHistoryValue const & value, bool include_token_id = false) { +UniValue accounthistoryToJSON(AccountHistoryKey const & key, AccountHistoryValue const & value, AmountFormat format = AmountFormat::Id) { UniValue obj(UniValue::VOBJ); obj.pushKV("owner", ScriptToString(key.owner)); @@ -63,13 +74,11 @@ UniValue accounthistoryToJSON(AccountHistoryKey const & key, AccountHistoryValue obj.pushKV("type", ToString(CustomTxCodeToType(value.category))); obj.pushKV("txn", (uint64_t) key.txn); obj.pushKV("txid", value.txid.ToString()); - obj.pushKV("amounts", AmountsToJSON(value.diff)); - if(include_token_id) - obj.pushKV("amounts_with_id", AmountsToJSON(value.diff, include_token_id)); + obj.pushKV("amounts", AmountsToJSON(value.diff, format)); return obj; } -UniValue rewardhistoryToJSON(CScript const & owner, uint32_t height, DCT_ID const & poolId, RewardType type, CTokenAmount amount, bool include_token_id = false) { +UniValue rewardhistoryToJSON(CScript const & owner, uint32_t height, DCT_ID const & poolId, RewardType type, CTokenAmount amount, AmountFormat format = AmountFormat::Id) { UniValue obj(UniValue::VOBJ); obj.pushKV("owner", ScriptToString(owner)); obj.pushKV("blockHeight", (uint64_t) height); @@ -83,13 +92,11 @@ UniValue rewardhistoryToJSON(CScript const & owner, uint32_t height, DCT_ID cons } obj.pushKV("poolID", poolId.ToString()); TAmounts amounts({{amount.nTokenId,amount.nValue}}); - obj.pushKV("amounts", AmountsToJSON(amounts)); - if (include_token_id) - obj.pushKV("amounts_with_id", AmountsToJSON(amounts, include_token_id)); + obj.pushKV("amounts", AmountsToJSON(amounts, format)); return obj; } -UniValue outputEntryToJSON(COutputEntry const & entry, CBlockIndex const * index, CWalletTx const * pwtx, bool include_token_id = false) { +UniValue outputEntryToJSON(COutputEntry const & entry, CBlockIndex const * index, CWalletTx const * pwtx, AmountFormat format = AmountFormat::Id) { UniValue obj(UniValue::VOBJ); obj.pushKV("owner", EncodeDestination(entry.destination)); @@ -106,9 +113,7 @@ UniValue outputEntryToJSON(COutputEntry const & entry, CBlockIndex const * index obj.pushKV("txn", (uint64_t) pwtx->nIndex); obj.pushKV("txid", pwtx->GetHash().ToString()); TAmounts amounts({{DCT_ID{0},entry.amount}}); - obj.pushKV("amounts", AmountsToJSON(amounts)); - if (include_token_id) - obj.pushKV("amounts_with_id", AmountsToJSON(amounts, include_token_id)); + obj.pushKV("amounts", AmountsToJSON(amounts, format)); return obj; } @@ -979,8 +984,8 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { "Maximum number of records to return, 100 by default"}, {"txn", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Order in block, unlimited by default"}, - {"includeTokenId", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, - "Include extra field with amounts containing token id (default = false)"}, + {"amountFormat", RPCArg::Type::STR, RPCArg::Optional::OMITTED, + "Return amounts with the following: (default)'id' -> @id; 'symbol' -> @symbol"}, }, }, @@ -1012,7 +1017,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { uint32_t limit = 100; auto txType = CustomTxType::None; uint32_t txn = std::numeric_limits::max(); - bool includeTokenId = false; + AmountFormat format = AmountFormat::Id; if (request.params.size() > 1) { UniValue optionsObj = request.params[1].get_obj(); @@ -1025,7 +1030,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { {"txtype", UniValueType(UniValue::VSTR)}, {"limit", UniValueType(UniValue::VNUM)}, {"txn", UniValueType(UniValue::VNUM)}, - {"includeTokenId", UniValueType(UniValue::VBOOL)} + {"amountFormat", UniValueType(UniValue::VSTR)} }, true, true); if (!optionsObj["maxBlockHeight"].isNull()) { @@ -1062,8 +1067,17 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { txn = (uint32_t) optionsObj["txn"].get_int64(); } - if (!optionsObj["includeTokenId"].isNull()) { - includeTokenId = optionsObj["includeTokenId"].get_bool(); + if (!optionsObj["amountFormat"].isNull()) { + const auto formatStr = optionsObj["amountFormat"].getValStr(); + if (formatStr == "symbol"){ + format = AmountFormat::Symbol; + } + else if (formatStr == "id") { + format = AmountFormat::Id; + } + else { + throw JSONRPCError(RPC_INVALID_REQUEST, "amountFormat must be one of the following: \"id\", \"symbol\""); + } } } @@ -1167,7 +1181,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { if (accountRecord && (tokenFilter.empty() || hasToken(value.diff))) { auto& array = ret.emplace(workingHeight, UniValue::VARR).first->second; - array.push_back(accounthistoryToJSON(key, value, includeTokenId)); + array.push_back(accounthistoryToJSON(key, value, format)); if (shouldSearchInWallet) { txs.insert(value.txid); } @@ -1179,7 +1193,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { [&](int32_t height, DCT_ID poolId, RewardType type, CTokenAmount amount) { if (tokenFilter.empty() || hasToken({{amount.nTokenId, amount.nValue}})) { auto& array = ret.emplace(height, UniValue::VARR).first->second; - array.push_back(rewardhistoryToJSON(key.owner, height, poolId, type, amount, includeTokenId)); + array.push_back(rewardhistoryToJSON(key.owner, height, poolId, type, amount, format)); count ? --count : 0; } } @@ -1223,7 +1237,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { return true; } auto& array = ret.emplace(index->nHeight, UniValue::VARR).first->second; - array.push_back(outputEntryToJSON(entry, index, pwtx, includeTokenId)); + array.push_back(outputEntryToJSON(entry, index, pwtx, format)); return --count != 0; } ); diff --git a/src/masternodes/rpc_vault.cpp b/src/masternodes/rpc_vault.cpp index b2a2bc53351..f2b231da73a 100644 --- a/src/masternodes/rpc_vault.cpp +++ b/src/masternodes/rpc_vault.cpp @@ -3,8 +3,8 @@ #include #include -extern UniValue AmountsToJSON(TAmounts const & diffs, bool include_token_id = false); -extern std::string tokenAmountString(CTokenAmount const& amount, bool include_token_id = false); +extern UniValue AmountsToJSON(TAmounts const & diffs, AmountFormat format = AmountFormat::Id); +extern std::string tokenAmountString(CTokenAmount const& amount, AmountFormat format = AmountFormat::Id); namespace { diff --git a/test/functional/rpc_getaccounthistory.py b/test/functional/rpc_getaccounthistory.py index 83b899f687d..0561a996c1c 100755 --- a/test/functional/rpc_getaccounthistory.py +++ b/test/functional/rpc_getaccounthistory.py @@ -6,10 +6,9 @@ """Test getaccounthistory RPC.""" from test_framework.test_framework import DefiTestFramework +from test_framework.authproxy import JSONRPCException +from test_framework.util import assert_equal -from test_framework.util import ( - assert_equal -) class TokensRPCGetAccountHistory(DefiTestFramework): def set_test_params(self): @@ -53,14 +52,28 @@ def run_test(self): self.nodes[0].generate(1) # Get node 0 results - results = self.nodes[0].listaccounthistory(collateral_a, {"includeTokenId": True} ) + # test amount@id format + results = self.nodes[0].listaccounthistory(collateral_a, {"amountFormat": "id"} ) # test token ids match token symbol for result in results: - amounts_with_id = result["amounts_with_id"] - for index, amount in enumerate(result["amounts"]): + for amount in result["amounts"]: symbol = amount.split('@')[1] - id = list(self.nodes[0].gettoken(symbol).keys())[0] - assert_equal(amounts_with_id[index].split("@")[1], id) + assert(symbol.isnumeric()) + + # test amount@symbol format + results = self.nodes[0].listaccounthistory(collateral_a, {"amountFormat": "symbol"} ) + # test token ids match token symbol + for result in results: + for amount in result["amounts"]: + symbol = amount.split('@')[1] + assert(symbol.isnumeric() == False) + + # test amount@symbol format + try: + results = self.nodes[0].listaccounthistory(collateral_a, {"amountFormat": "combined"} ) + except JSONRPCException as e: + errorString = e.error['message'] + assert("amountFormat must be one of the following: \"id\", \"symbol\"" in errorString) # An account history from listaccounthistory and gettaccounthistory must be matched expected = results[0] From b200a8f902b53dc7ccff6f22e917a85c1b2d2035 Mon Sep 17 00:00:00 2001 From: Dcorral Date: Mon, 13 Jun 2022 18:29:00 +0200 Subject: [PATCH 4/9] Fix circular dependency error lint --- test/lint/lint-circular-dependencies.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index 68111416af6..4efef483b5f 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -28,6 +28,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "consensus/tx_verify -> masternodes/masternodes -> validation -> consensus/tx_verify" "consensus/tx_verify -> masternodes/mn_checks -> txmempool -> consensus/tx_verify" "index/txindex -> validation -> index/txindex" + "init -> miner -> masternodes/govvariables/attributes -> masternodes/mn_rpc -> wallet/rpcwallet -> init" "masternodes/accountshistory -> masternodes/masternodes -> masternodes/mn_checks -> masternodes/accountshistory" "masternodes/accountshistory -> masternodes/masternodes -> validation -> masternodes/accountshistory" "masternodes/anchors -> masternodes/masternodes -> masternodes/anchors" @@ -39,6 +40,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "masternodes/govvariables/attributes -> masternodes/masternodes -> masternodes/govvariables/attributes" "masternodes/govvariables/attributes -> masternodes/masternodes -> validation -> masternodes/govvariables/attributes" "masternodes/govvariables/attributes -> masternodes/mn_checks -> masternodes/govvariables/attributes" + "masternodes/govvariables/attributes -> masternodes/mn_rpc -> masternodes/govvariables/attributes" "masternodes/govvariables/icx_takerfee_per_btc -> masternodes/gv -> masternodes/govvariables/icx_takerfee_per_btc" "masternodes/govvariables/loan_daily_reward -> masternodes/gv -> masternodes/govvariables/loan_daily_reward" "masternodes/govvariables/loan_daily_reward -> masternodes/masternodes -> validation -> masternodes/govvariables/loan_daily_reward" From 0d0b8054788edf390d5f0713592d87248267c689 Mon Sep 17 00:00:00 2001 From: Dcorral Date: Tue, 14 Jun 2022 23:27:52 +0200 Subject: [PATCH 5/9] getaccount to maintain previous behaviour --- src/masternodes/rpc_accounts.cpp | 2 +- test/functional/feature_token_split_usd_value.py | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/masternodes/rpc_accounts.cpp b/src/masternodes/rpc_accounts.cpp index 56437d4c1d1..be571dc5aae 100644 --- a/src/masternodes/rpc_accounts.cpp +++ b/src/masternodes/rpc_accounts.cpp @@ -452,7 +452,7 @@ UniValue getaccount(const JSONRPCRequest& request) { if (indexed_amounts) ret.pushKV(balance.nTokenId.ToString(), ValueFromAmount(balance.nValue)); else - ret.push_back(tokenAmountString(balance)); + ret.push_back(tokenAmountString(balance, AmountFormat::Symbol)); // Maintain default behaviour returning symbol limit--; return limit != 0; diff --git a/test/functional/feature_token_split_usd_value.py b/test/functional/feature_token_split_usd_value.py index 2544235dbd6..2c546ad5b3d 100755 --- a/test/functional/feature_token_split_usd_value.py +++ b/test/functional/feature_token_split_usd_value.py @@ -113,7 +113,6 @@ def setup_accounts(self): self.generate_and_fill_accounts() def add_total_account_to_liquidity_pool(self): - print(f'Adding liquidity with {len(self.accounts)} accounts...') size = 1000000 for account in self.accounts: totalAmount = Decimal(self.get_amount_from_account(account, self.symbolDUSD)) @@ -128,7 +127,6 @@ def add_total_account_to_liquidity_pool(self): self.nodes[0].addpoolliquidity({account: [str(finalAmount)+"@T1", str(finalAmount)+"@DUSD"]}, account) self.nodes[0].generate(1) totalAmount -= finalAmount - print(f'account {account} finished') def setup_pools(self): self.nodes[0].createpoolpair({ @@ -212,14 +210,12 @@ def accounts_usd_values(self): def compare_value_list(self, pre, post): for index, amount in enumerate(pre): - print(f'Comparing values in valut {amount["account"]}') if index != 0: almost_equal(amount["DUSD"], post[index]["DUSD"]) almost_equal(amount["T1"], post[index]["T1"]) def compare_vaults_list(self, pre, post): for index, vault in enumerate(pre): - print(f'Comparing valuts {vault["vaultId"]}') if index != 0: almost_equal(vault["collateralValue"], post[index]["collateralValue"]) almost_equal(vault["loanValue"], post[index]["loanValue"]) From 921b99a0aff1e654f6bf54e92d0781fba9b1a244 Mon Sep 17 00:00:00 2001 From: Dcorral Date: Wed, 15 Jun 2022 00:53:09 +0200 Subject: [PATCH 6/9] Return to default behaviour not to break other rpcs --- src/masternodes/govvariables/attributes.cpp | 2 +- src/masternodes/rpc_accounts.cpp | 14 +++++++------- src/masternodes/rpc_vault.cpp | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/masternodes/govvariables/attributes.cpp b/src/masternodes/govvariables/attributes.cpp index 536e72aa7a3..e005fad0f1e 100644 --- a/src/masternodes/govvariables/attributes.cpp +++ b/src/masternodes/govvariables/attributes.cpp @@ -14,7 +14,7 @@ #include /// ValueFromAmount #include -extern UniValue AmountsToJSON(TAmounts const & diffs, AmountFormat format = AmountFormat::Id); +extern UniValue AmountsToJSON(TAmounts const & diffs, AmountFormat format = AmountFormat::Symbol); static inline std::string trim_all_ws(std::string s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { diff --git a/src/masternodes/rpc_accounts.cpp b/src/masternodes/rpc_accounts.cpp index be571dc5aae..65fec7b0c86 100644 --- a/src/masternodes/rpc_accounts.cpp +++ b/src/masternodes/rpc_accounts.cpp @@ -2,7 +2,7 @@ #include #include -std::string tokenAmountString(CTokenAmount const& amount, AmountFormat format = AmountFormat::Id) { +std::string tokenAmountString(CTokenAmount const& amount, AmountFormat format = AmountFormat::Symbol) { const auto token = pcustomcsview->GetToken(amount.nTokenId); const auto amountString = ValueFromAmount(amount.nValue).getValStr(); @@ -24,7 +24,7 @@ std::string tokenAmountString(CTokenAmount const& amount, AmountFormat format = return amountString + "@" + tokenStr; } -UniValue AmountsToJSON(TAmounts const & diffs, AmountFormat format = AmountFormat::Id) { +UniValue AmountsToJSON(TAmounts const & diffs, AmountFormat format = AmountFormat::Symbol) { UniValue obj(UniValue::VARR); for (auto const & diff : diffs) { @@ -33,7 +33,7 @@ UniValue AmountsToJSON(TAmounts const & diffs, AmountFormat format = AmountForma return obj; } -UniValue accountToJSON(CScript const& owner, CTokenAmount const& amount, bool verbose, bool indexed_amounts,AmountFormat format = AmountFormat::Id) { +UniValue accountToJSON(CScript const& owner, CTokenAmount const& amount, bool verbose, bool indexed_amounts,AmountFormat format = AmountFormat::Symbol) { // encode CScript into JSON UniValue ownerObj(UniValue::VOBJ); ScriptPubKeyToUniv(owner, ownerObj, true); @@ -62,7 +62,7 @@ UniValue accountToJSON(CScript const& owner, CTokenAmount const& amount, bool ve return obj; } -UniValue accounthistoryToJSON(AccountHistoryKey const & key, AccountHistoryValue const & value, AmountFormat format = AmountFormat::Id) { +UniValue accounthistoryToJSON(AccountHistoryKey const & key, AccountHistoryValue const & value, AmountFormat format = AmountFormat::Symbol) { UniValue obj(UniValue::VOBJ); obj.pushKV("owner", ScriptToString(key.owner)); @@ -96,7 +96,7 @@ UniValue rewardhistoryToJSON(CScript const & owner, uint32_t height, DCT_ID cons return obj; } -UniValue outputEntryToJSON(COutputEntry const & entry, CBlockIndex const * index, CWalletTx const * pwtx, AmountFormat format = AmountFormat::Id) { +UniValue outputEntryToJSON(COutputEntry const & entry, CBlockIndex const * index, CWalletTx const * pwtx, AmountFormat format = AmountFormat::Symbol) { UniValue obj(UniValue::VOBJ); obj.pushKV("owner", EncodeDestination(entry.destination)); @@ -452,7 +452,7 @@ UniValue getaccount(const JSONRPCRequest& request) { if (indexed_amounts) ret.pushKV(balance.nTokenId.ToString(), ValueFromAmount(balance.nValue)); else - ret.push_back(tokenAmountString(balance, AmountFormat::Symbol)); // Maintain default behaviour returning symbol + ret.push_back(tokenAmountString(balance)); limit--; return limit != 0; @@ -1017,7 +1017,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { uint32_t limit = 100; auto txType = CustomTxType::None; uint32_t txn = std::numeric_limits::max(); - AmountFormat format = AmountFormat::Id; + AmountFormat format = AmountFormat::Symbol; if (request.params.size() > 1) { UniValue optionsObj = request.params[1].get_obj(); diff --git a/src/masternodes/rpc_vault.cpp b/src/masternodes/rpc_vault.cpp index f2b231da73a..ee9e8905a85 100644 --- a/src/masternodes/rpc_vault.cpp +++ b/src/masternodes/rpc_vault.cpp @@ -3,8 +3,8 @@ #include #include -extern UniValue AmountsToJSON(TAmounts const & diffs, AmountFormat format = AmountFormat::Id); -extern std::string tokenAmountString(CTokenAmount const& amount, AmountFormat format = AmountFormat::Id); +extern UniValue AmountsToJSON(TAmounts const & diffs, AmountFormat format = AmountFormat::Symbol); +extern std::string tokenAmountString(CTokenAmount const& amount, AmountFormat format = AmountFormat::Symbol); namespace { From 2ed6bfe338592a2a0dc59655b048b4d0467a3892 Mon Sep 17 00:00:00 2001 From: dcorral Date: Thu, 16 Jun 2022 13:32:55 +0200 Subject: [PATCH 7/9] Fix typo on default description --- src/masternodes/rpc_accounts.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/masternodes/rpc_accounts.cpp b/src/masternodes/rpc_accounts.cpp index 65fec7b0c86..8a270a0cece 100644 --- a/src/masternodes/rpc_accounts.cpp +++ b/src/masternodes/rpc_accounts.cpp @@ -985,7 +985,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { {"txn", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Order in block, unlimited by default"}, {"amountFormat", RPCArg::Type::STR, RPCArg::Optional::OMITTED, - "Return amounts with the following: (default)'id' -> @id; 'symbol' -> @symbol"}, + "Return amounts with the following: 'id' -> @id; (default)'symbol' -> @symbol"}, }, }, From b5fb4c7a2acd88604cda13aa1cc76f25ae42a16f Mon Sep 17 00:00:00 2001 From: dcorral Date: Wed, 22 Jun 2022 16:57:30 +0200 Subject: [PATCH 8/9] Refactor amountFormat to format --- src/masternodes/rpc_accounts.cpp | 10 +++++----- test/functional/rpc_getaccounthistory.py | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/masternodes/rpc_accounts.cpp b/src/masternodes/rpc_accounts.cpp index 8a270a0cece..fce556eb1c6 100644 --- a/src/masternodes/rpc_accounts.cpp +++ b/src/masternodes/rpc_accounts.cpp @@ -984,7 +984,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { "Maximum number of records to return, 100 by default"}, {"txn", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Order in block, unlimited by default"}, - {"amountFormat", RPCArg::Type::STR, RPCArg::Optional::OMITTED, + {"format", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Return amounts with the following: 'id' -> @id; (default)'symbol' -> @symbol"}, }, @@ -1030,7 +1030,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { {"txtype", UniValueType(UniValue::VSTR)}, {"limit", UniValueType(UniValue::VNUM)}, {"txn", UniValueType(UniValue::VNUM)}, - {"amountFormat", UniValueType(UniValue::VSTR)} + {"format", UniValueType(UniValue::VSTR)} }, true, true); if (!optionsObj["maxBlockHeight"].isNull()) { @@ -1067,8 +1067,8 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { txn = (uint32_t) optionsObj["txn"].get_int64(); } - if (!optionsObj["amountFormat"].isNull()) { - const auto formatStr = optionsObj["amountFormat"].getValStr(); + if (!optionsObj["format"].isNull()) { + const auto formatStr = optionsObj["format"].getValStr(); if (formatStr == "symbol"){ format = AmountFormat::Symbol; } @@ -1076,7 +1076,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { format = AmountFormat::Id; } else { - throw JSONRPCError(RPC_INVALID_REQUEST, "amountFormat must be one of the following: \"id\", \"symbol\""); + throw JSONRPCError(RPC_INVALID_REQUEST, "format must be one of the following: \"id\", \"symbol\""); } } } diff --git a/test/functional/rpc_getaccounthistory.py b/test/functional/rpc_getaccounthistory.py index 0561a996c1c..06c8eadb6dd 100755 --- a/test/functional/rpc_getaccounthistory.py +++ b/test/functional/rpc_getaccounthistory.py @@ -53,7 +53,7 @@ def run_test(self): # Get node 0 results # test amount@id format - results = self.nodes[0].listaccounthistory(collateral_a, {"amountFormat": "id"} ) + results = self.nodes[0].listaccounthistory(collateral_a, {"format": "id"} ) # test token ids match token symbol for result in results: for amount in result["amounts"]: @@ -61,7 +61,7 @@ def run_test(self): assert(symbol.isnumeric()) # test amount@symbol format - results = self.nodes[0].listaccounthistory(collateral_a, {"amountFormat": "symbol"} ) + results = self.nodes[0].listaccounthistory(collateral_a, {"format": "symbol"} ) # test token ids match token symbol for result in results: for amount in result["amounts"]: @@ -70,10 +70,10 @@ def run_test(self): # test amount@symbol format try: - results = self.nodes[0].listaccounthistory(collateral_a, {"amountFormat": "combined"} ) + results = self.nodes[0].listaccounthistory(collateral_a, {"format": "combined"} ) except JSONRPCException as e: errorString = e.error['message'] - assert("amountFormat must be one of the following: \"id\", \"symbol\"" in errorString) + assert("format must be one of the following: \"id\", \"symbol\"" in errorString) # An account history from listaccounthistory and gettaccounthistory must be matched expected = results[0] From cdb157526c6bfaca40f70b2a426ea1bcb727fefc Mon Sep 17 00:00:00 2001 From: Prasanna Loganathar Date: Thu, 23 Jun 2022 02:15:46 +0530 Subject: [PATCH 9/9] Simplify enum --- src/masternodes/mn_rpc.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/masternodes/mn_rpc.h b/src/masternodes/mn_rpc.h index b77296c1afb..46a15477fe2 100644 --- a/src/masternodes/mn_rpc.h +++ b/src/masternodes/mn_rpc.h @@ -36,13 +36,13 @@ typedef enum { } AccountSelectionMode; enum class AmountFormat : uint8_t { + Unknown, // amount@0 - Id = (1 << 0), + Id, // amount@DFI - Symbol = (2 << 1), + Symbol, // amount@0#DFI - Combined = (3 << 2), - Unknown = 0 + Combined, }; class CWalletCoinsUnlocker {