diff --git a/android/java/org/chromium/chrome/browser/crypto_wallet/BraveWalletNativeWorker.java b/android/java/org/chromium/chrome/browser/crypto_wallet/BraveWalletNativeWorker.java index 7ced45e4fe1..fae5c2d747a 100644 --- a/android/java/org/chromium/chrome/browser/crypto_wallet/BraveWalletNativeWorker.java +++ b/android/java/org/chromium/chrome/browser/crypto_wallet/BraveWalletNativeWorker.java @@ -103,14 +103,15 @@ public class BraveWalletNativeWorker { BraveWalletNativeWorkerJni.get().resetWallet(mNativeBraveWalletNativeWorker); } - public void getAssetPrice(String asset) { - BraveWalletNativeWorkerJni.get().getAssetPrice(mNativeBraveWalletNativeWorker, asset); + public void getAssetPrice(String[] fromAssets, String[] toAssets) { + BraveWalletNativeWorkerJni.get().getAssetPrice( + mNativeBraveWalletNativeWorker, fromAssets, toAssets); } @CalledByNative - public void OnGetPrice(String price, boolean isSuccess) { + public void OnGetPrice(String prices, boolean isSuccess) { for (BraveWalletObserver observer : mObservers) { - observer.OnGetPrice(price, isSuccess); + observer.OnGetPrice(prices, isSuccess); } } @@ -137,7 +138,8 @@ public class BraveWalletNativeWorker { boolean unlockWallet(long nativeBraveWalletNativeWorker, String password); String restoreWallet(long nativeBraveWalletNativeWorker, String mnemonic, String password); void resetWallet(long nativeBraveWalletNativeWorker); - void getAssetPrice(long nativeBraveWalletNativeWorker, String asset); + void getAssetPrice( + long nativeBraveWalletNativeWorker, String[] fromAssets, String[] toAssets); void getAssetPriceHistory(long nativeBraveWalletNativeWorker, String asset, int timeFrame); } } diff --git a/browser/brave_wallet/android/brave_wallet_native_worker.cc b/browser/brave_wallet/android/brave_wallet_native_worker.cc index a4678fb2296..5bb084e6b3e 100644 --- a/browser/brave_wallet/android/brave_wallet_native_worker.cc +++ b/browser/brave_wallet/android/brave_wallet_native_worker.cc @@ -5,7 +5,10 @@ #include "brave/browser/brave_wallet/android/brave_wallet_native_worker.h" +#include + #include "base/android/jni_android.h" +#include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/json/json_writer.h" #include "base/values.h" @@ -143,21 +146,42 @@ void BraveWalletNativeWorker::ResetWallet(JNIEnv* env) { void BraveWalletNativeWorker::GetAssetPrice( JNIEnv* env, - const base::android::JavaParamRef& asset) { + const base::android::JavaParamRef& from_assets, + const base::android::JavaParamRef& to_assets) { EnsureConnected(); + std::vector assets_from; + base::android::AppendJavaStringArrayToStringVector(env, from_assets, + &assets_from); + std::vector assets_to; + base::android::AppendJavaStringArrayToStringVector(env, to_assets, + &assets_to); + asset_ratio_controller_->GetPrice( - base::android::ConvertJavaStringToUTF8(env, asset), + assets_from, assets_to, base::BindOnce(&BraveWalletNativeWorker::OnGetPrice, weak_ptr_factory_.GetWeakPtr())); } -void BraveWalletNativeWorker::OnGetPrice(bool success, - const std::string& price) { +void BraveWalletNativeWorker::OnGetPrice( + bool success, + std::vector prices) { + std::string prices_json; + base::Value list(base::Value::Type::LIST); + for (const auto& asset_price : prices) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetStringKey("from_asset", asset_price->from_asset); + dict.SetStringKey("to_asset", asset_price->to_asset); + dict.SetStringKey("price", asset_price->price); + dict.SetStringKey("asset_24h_change", asset_price->asset_24h_change); + list.Append(std::move(dict)); + } + base::JSONWriter::Write(list, &prices_json); + JNIEnv* env = base::android::AttachCurrentThread(); Java_BraveWalletNativeWorker_OnGetPrice( env, weak_java_brave_wallet_native_worker_.get(env), - base::android::ConvertUTF8ToJavaString(env, price), success); + base::android::ConvertUTF8ToJavaString(env, prices_json), success); } void BraveWalletNativeWorker::GetAssetPriceHistory( diff --git a/browser/brave_wallet/android/brave_wallet_native_worker.h b/browser/brave_wallet/android/brave_wallet_native_worker.h index c7aaa95fd58..4da1b1afe54 100644 --- a/browser/brave_wallet/android/brave_wallet_native_worker.h +++ b/browser/brave_wallet/android/brave_wallet_native_worker.h @@ -40,9 +40,12 @@ class BraveWalletNativeWorker { const base::android::JavaParamRef& password); void ResetWallet(JNIEnv* env); - void GetAssetPrice(JNIEnv* env, - const base::android::JavaParamRef& asset); - void OnGetPrice(bool success, const std::string& price); + void GetAssetPrice( + JNIEnv* env, + const base::android::JavaParamRef& from_assets, + const base::android::JavaParamRef& to_assets); + void OnGetPrice(bool success, + std::vector prices); void GetAssetPriceHistory(JNIEnv* env, const base::android::JavaParamRef& asset, diff --git a/browser/brave_wallet/asset_ratio_controller_browsertest.cc b/browser/brave_wallet/asset_ratio_controller_browsertest.cc index 4163b5ca7c7..c84a4d677ef 100644 --- a/browser/brave_wallet/asset_ratio_controller_browsertest.cc +++ b/browser/brave_wallet/asset_ratio_controller_browsertest.cc @@ -30,8 +30,7 @@ std::unique_ptr HandleRequest( http_response->set_code(net::HTTP_OK); http_response->set_content_type("text/html"); if (request.GetURL().spec().find("/v2/history") != std::string::npos) { - http_response->set_content(R"( - { + http_response->set_content(R"({ "payload": { "prices":[[1622733088498,0.8201346624954003],[1622737203757,0.8096978545029869]], "market_caps":[[1622733088498,1223507820.383275],[1622737203757,1210972881.4928021]], @@ -40,7 +39,29 @@ std::unique_ptr HandleRequest( })"); } else { http_response->set_content( - R"({"payload":{"basic-attention-token":{"usd":0.694503}}})"); + R"({ + "payload":{ + "basic-attention-token":{ + "btc":0.00001732, + "btc_24h_change":8.021672460190562, + "usd":0.55393, + "usd_24h_change":9.523443444373276 + }, + "bat":{ + "btc":0.00001732, + "btc_24h_change":8.021672460190562, + "usd":0.55393, + "usd_24h_change":9.523443444373276 + }, + "link":{ + "btc":0.00261901, + "btc_24h_change":0.5871625385632929, + "usd":83.77, + "usd_24h_change":1.7646208048244043 + } + }, + "lastUpdated":"2021-07-16T19:11:28.907Z" + })"); } return std::move(http_response); } @@ -83,11 +104,12 @@ class AssetRatioControllerTest : public InProcessBrowserTest { https_server_->base_url()); } - void OnGetPrice(bool success, const std::string& price) { + void OnGetPrice(bool success, + std::vector prices) { if (wait_for_request_) { wait_for_request_->Quit(); } - ASSERT_EQ(expected_price_response_, price); + ASSERT_EQ(expected_prices_response_, prices); ASSERT_EQ(expected_success_, success); } @@ -101,12 +123,13 @@ class AssetRatioControllerTest : public InProcessBrowserTest { ASSERT_EQ(expected_success_, success); } - void WaitForPriceResponse(const std::string& expected_price_response, - bool expected_success) { + void WaitForPriceResponse( + std::vector expected_prices_response, + bool expected_success) { if (wait_for_request_) { return; } - expected_price_response_ = expected_price_response; + expected_prices_response_ = std::move(expected_prices_response); expected_success_ = expected_success; wait_for_request_.reset(new base::RunLoop); wait_for_request_->Run(); @@ -145,7 +168,7 @@ class AssetRatioControllerTest : public InProcessBrowserTest { net::EmbeddedTestServer* https_server() { return https_server_.get(); } bool expected_success_; - std::string expected_price_response_; + std::vector expected_prices_response_; std::vector expected_price_history_response_; @@ -154,28 +177,59 @@ class AssetRatioControllerTest : public InProcessBrowserTest { }; IN_PROC_BROWSER_TEST_F(AssetRatioControllerTest, GetPrice) { + std::vector expected_prices_response; ResetHTTPSServer(base::BindRepeating(&HandleRequest)); auto controller = GetAssetRatioController(); - controller->GetPrice("basic-attention-token", + controller->GetPrice({"bat", "link"}, {"btc", "usd"}, base::BindOnce(&AssetRatioControllerTest::OnGetPrice, base::Unretained(this))); - WaitForPriceResponse("0.694503", true); + + auto asset_price = brave_wallet::mojom::AssetPrice::New(); + asset_price->from_asset = "bat"; + asset_price->to_asset = "btc"; + asset_price->price = "0.00001732"; + asset_price->asset_24h_change = "8.021672460190562"; + expected_prices_response.push_back(std::move(asset_price)); + + asset_price = brave_wallet::mojom::AssetPrice::New(); + asset_price->from_asset = "bat"; + asset_price->to_asset = "usd"; + asset_price->price = "0.55393"; + asset_price->asset_24h_change = "9.523443444373276"; + expected_prices_response.push_back(std::move(asset_price)); + + asset_price = brave_wallet::mojom::AssetPrice::New(); + asset_price->from_asset = "link"; + asset_price->to_asset = "btc"; + asset_price->price = "0.00261901"; + asset_price->asset_24h_change = "0.5871625385632929"; + expected_prices_response.push_back(std::move(asset_price)); + + asset_price = brave_wallet::mojom::AssetPrice::New(); + asset_price->from_asset = "link"; + asset_price->to_asset = "usd"; + asset_price->price = "83.77"; + asset_price->asset_24h_change = "1.7646208048244043"; + expected_prices_response.push_back(std::move(asset_price)); + + WaitForPriceResponse(std::move(expected_prices_response), true); } IN_PROC_BROWSER_TEST_F(AssetRatioControllerTest, GetPriceServerError) { + std::vector expected_prices_response; ResetHTTPSServer(base::BindRepeating(&HandleRequestServerError)); auto controller = GetAssetRatioController(); - controller->GetPrice("basic-attention-token", + controller->GetPrice({"bat", "link"}, {"btc", "usd"}, base::BindOnce(&AssetRatioControllerTest::OnGetPrice, base::Unretained(this))); - WaitForPriceResponse("", false); + WaitForPriceResponse(std::move(expected_prices_response), false); } IN_PROC_BROWSER_TEST_F(AssetRatioControllerTest, GetPriceHistory) { ResetHTTPSServer(base::BindRepeating(&HandleRequest)); auto controller = GetAssetRatioController(); controller->GetPriceHistory( - "basic-attention-token", brave_wallet::mojom::AssetPriceTimeframe::OneDay, + "bat", brave_wallet::mojom::AssetPriceTimeframe::OneDay, base::BindOnce(&AssetRatioControllerTest::OnGetPriceHistory, base::Unretained(this))); @@ -199,7 +253,7 @@ IN_PROC_BROWSER_TEST_F(AssetRatioControllerTest, GetPriceHistoryServerError) { ResetHTTPSServer(base::BindRepeating(&HandleRequestServerError)); auto controller = GetAssetRatioController(); controller->GetPriceHistory( - "basic-attention-token", brave_wallet::mojom::AssetPriceTimeframe::OneDay, + "bat", brave_wallet::mojom::AssetPriceTimeframe::OneDay, base::BindOnce(&AssetRatioControllerTest::OnGetPriceHistory, base::Unretained(this))); std::vector diff --git a/browser/ui/webui/brave_wallet/common_handler/wallet_handler.cc b/browser/ui/webui/brave_wallet/common_handler/wallet_handler.cc index 2d9f31b96d7..886ca9d4b42 100644 --- a/browser/ui/webui/brave_wallet/common_handler/wallet_handler.cc +++ b/browser/ui/webui/brave_wallet/common_handler/wallet_handler.cc @@ -103,10 +103,12 @@ void WalletHandler::UnlockWallet(const std::string& password, keyring_controller_->Unlock(password, std::move(callback)); } -void WalletHandler::GetAssetPrice(const std::string& asset, +void WalletHandler::GetAssetPrice(const std::vector& from_assets, + const std::vector& to_assets, GetAssetPriceCallback callback) { EnsureConnected(); - asset_ratio_controller_->GetPrice(asset, std::move(callback)); + asset_ratio_controller_->GetPrice(from_assets, to_assets, + std::move(callback)); } void WalletHandler::GetAssetPriceHistory( diff --git a/browser/ui/webui/brave_wallet/common_handler/wallet_handler.h b/browser/ui/webui/brave_wallet/common_handler/wallet_handler.h index 69207cc43b1..fe56c7c455e 100644 --- a/browser/ui/webui/brave_wallet/common_handler/wallet_handler.h +++ b/browser/ui/webui/brave_wallet/common_handler/wallet_handler.h @@ -30,7 +30,9 @@ class WalletHandler : public brave_wallet::mojom::WalletHandler { void GetWalletInfo(GetWalletInfoCallback) override; void LockWallet() override; void UnlockWallet(const std::string& password, UnlockWalletCallback) override; - void GetAssetPrice(const std::string& asset, GetAssetPriceCallback) override; + void GetAssetPrice(const std::vector& from_assets, + const std::vector& to_assets, + GetAssetPriceCallback) override; void GetAssetPriceHistory(const std::string& asset, brave_wallet::mojom::AssetPriceTimeframe timeframe, GetAssetPriceHistoryCallback) override; diff --git a/components/brave_wallet/browser/asset_ratio_controller.cc b/components/brave_wallet/browser/asset_ratio_controller.cc index c99c40533c0..f946ace82a9 100644 --- a/components/brave_wallet/browser/asset_ratio_controller.cc +++ b/components/brave_wallet/browser/asset_ratio_controller.cc @@ -38,6 +38,17 @@ net::NetworkTrafficAnnotationTag GetNetworkTrafficAnnotationTag() { )"); } +std::string VectorToCommaSeparatedList(const std::vector& assets) { + std::stringstream ss; + std::for_each(assets.begin(), assets.end(), [&ss](const std::string asset) { + if (ss.tellp() != 0) { + ss << ","; + } + ss << asset; + }); + return ss.str(); +} + } // namespace namespace brave_wallet { @@ -63,12 +74,16 @@ void AssetRatioController::SetBaseURLForTest(const GURL& base_url_for_test) { } // static -GURL AssetRatioController::GetPriceURL(const std::string& asset) { +GURL AssetRatioController::GetPriceURL( + const std::vector& from_assets, + const std::vector& to_assets) { + std::string from = VectorToCommaSeparatedList(from_assets); + std::string to = VectorToCommaSeparatedList(to_assets); std::string spec = base::StringPrintf( - "%sv2/relative/provider/coingecko/%s/usd", + "%sv2/relative/provider/coingecko/%s/%s", base_url_for_test_.is_empty() ? kAssetRatioBaseURL : base_url_for_test_.spec().c_str(), - asset.c_str()); + from.c_str(), to.c_str()); return GURL(spec); } @@ -108,31 +123,34 @@ GURL AssetRatioController::GetPriceHistoryURL( return GURL(spec); } -void AssetRatioController::GetPrice(const std::string& asset, +void AssetRatioController::GetPrice(const std::vector& from_assets, + const std::vector& to_assets, GetPriceCallback callback) { - auto internal_callback = - base::BindOnce(&AssetRatioController::OnGetPrice, - weak_ptr_factory_.GetWeakPtr(), std::move(callback)); - api_request_helper_.Request("GET", GetPriceURL(asset), "", "", true, - std::move(internal_callback)); + auto internal_callback = base::BindOnce( + &AssetRatioController::OnGetPrice, weak_ptr_factory_.GetWeakPtr(), + from_assets, to_assets, std::move(callback)); + api_request_helper_.Request("GET", GetPriceURL(from_assets, to_assets), "", + "", true, std::move(internal_callback)); } void AssetRatioController::OnGetPrice( + std::vector from_assets, + std::vector to_assets, GetPriceCallback callback, const int status, const std::string& body, const std::map& headers) { + std::vector prices; if (status < 200 || status > 299) { - std::move(callback).Run(false, ""); + std::move(callback).Run(false, std::move(prices)); return; } - std::string price; - if (!ParseAssetPrice(body, &price)) { - std::move(callback).Run(false, ""); + if (!ParseAssetPrice(body, from_assets, to_assets, &prices)) { + std::move(callback).Run(false, std::move(prices)); return; } - std::move(callback).Run(true, price); + std::move(callback).Run(true, std::move(prices)); } void AssetRatioController::GetPriceHistory( diff --git a/components/brave_wallet/browser/asset_ratio_controller.h b/components/brave_wallet/browser/asset_ratio_controller.h index 23aae63bbf6..338d5502d98 100644 --- a/components/brave_wallet/browser/asset_ratio_controller.h +++ b/components/brave_wallet/browser/asset_ratio_controller.h @@ -41,20 +41,25 @@ class AssetRatioController : public KeyedService, mojo::PendingRemote MakeRemote(); - void GetPrice(const std::string& asset, GetPriceCallback callback) override; + void GetPrice(const std::vector& from_assets, + const std::vector& to_assets, + GetPriceCallback callback) override; // The asset param is a string like: "bat" void GetPriceHistory(const std::string& asset, brave_wallet::mojom::AssetPriceTimeframe timeframe, GetPriceHistoryCallback callback) override; - static GURL GetPriceURL(const std::string& asset); + static GURL GetPriceURL(const std::vector& from_assets, + const std::vector& to_assets); static GURL GetPriceHistoryURL( const std::string& asset, brave_wallet::mojom::AssetPriceTimeframe timeframe); static void SetBaseURLForTest(const GURL& base_url_for_test); private: - void OnGetPrice(GetPriceCallback callback, + void OnGetPrice(std::vector from_assets, + std::vector to_assets, + GetPriceCallback callback, const int status, const std::string& body, const std::map& headers); diff --git a/components/brave_wallet/browser/asset_ratio_response_parser.cc b/components/brave_wallet/browser/asset_ratio_response_parser.cc index cef625f800a..ce3d24720f1 100644 --- a/components/brave_wallet/browser/asset_ratio_response_parser.cc +++ b/components/brave_wallet/browser/asset_ratio_response_parser.cc @@ -8,19 +8,42 @@ #include "base/json/json_reader.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" #include "base/time/time.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace brave_wallet { -bool ParseAssetPrice(const std::string& json, std::string* price) { +bool ParseAssetPrice(const std::string& json, + const std::vector& from_assets, + const std::vector& to_assets, + std::vector* values) { // Parses results like this: - // { "payload": - // { - // "basic-attention-token":{"usd":0.694503} - // } + // { + // "payload":{ + // "basic-attention-token":{ + // "btc":0.00001732, + // "btc_24h_change":8.021672460190562, + // "usd":0.55393, + // "usd_24h_change":9.523443444373276 + // }, + // "bat":{ + // "btc":0.00001732, + // "btc_24h_change":8.021672460190562, + // "usd":0.55393, + // "usd_24h_change":9.523443444373276 + // }, + // "link":{ + // "btc":0.00261901, + // "btc_24h_change":0.5871625385632929, + // "usd":83.77, + // "usd_24h_change":1.7646208048244043 + // } + // }, + // "lastUpdated":"2021-07-16T19:11:28.907Z" // } - DCHECK(price); + + DCHECK(values); base::JSONReader::ValueWithError value_with_error = base::JSONReader::ReadAndReturnValueWithError( @@ -46,27 +69,37 @@ bool ParseAssetPrice(const std::string& json, std::string* price) { return false; } - if (payload->DictSize() == 0) { - return false; - } + for (const std::string& from_asset : from_assets) { + const base::Value* from_asset_value = + payload_dict->FindDictPath(from_asset); + const base::DictionaryValue* from_asset_dict; + if (!from_asset_value->GetAsDictionary(&from_asset_dict)) { + return false; + } - auto items = payload->DictItems(); - if (!items.begin()->second.is_dict()) { - return false; - } - const auto& usd_price_dict = - base::Value::AsDictionaryValue(items.begin()->second); - if (usd_price_dict.DictSize() != 1) { - return false; - } - auto converted_items = usd_price_dict.DictItems(); - const auto& value = converted_items.begin()->second; + for (const std::string& to_asset : to_assets) { + auto asset_price = brave_wallet::mojom::AssetPrice::New(); + asset_price->from_asset = from_asset; + asset_price->to_asset = to_asset; - double num; - if (!value.GetAsDouble(&num)) { - return false; + absl::optional to_price = + from_asset_dict->FindDoublePath(to_asset); + if (!to_price) { + return false; + } + asset_price->price = base::NumberToString(*to_price); + std::string to_asset_24h_key = + base::StringPrintf("%s_24h_change", to_asset.c_str()); + absl::optional to_24h_change = + from_asset_dict->FindDoublePath(to_asset_24h_key); + if (!to_24h_change) { + return false; + } + asset_price->asset_24h_change = base::NumberToString(*to_24h_change); + + values->push_back(std::move(asset_price)); + } } - *price = base::NumberToString(num); return true; } diff --git a/components/brave_wallet/browser/asset_ratio_response_parser.h b/components/brave_wallet/browser/asset_ratio_response_parser.h index 40309f775e2..4e4dce8c9da 100644 --- a/components/brave_wallet/browser/asset_ratio_response_parser.h +++ b/components/brave_wallet/browser/asset_ratio_response_parser.h @@ -15,7 +15,10 @@ namespace brave_wallet { -bool ParseAssetPrice(const std::string& json, std::string* price); +bool ParseAssetPrice(const std::string& json, + const std::vector& from_assets, + const std::vector& to_assets, + std::vector* values); bool ParseAssetPriceHistory( const std::string& json, std::vector* values); diff --git a/components/brave_wallet/browser/asset_ratio_response_parser_unittest.cc b/components/brave_wallet/browser/asset_ratio_response_parser_unittest.cc index ebe7fc186a2..de23d911b9f 100644 --- a/components/brave_wallet/browser/asset_ratio_response_parser_unittest.cc +++ b/components/brave_wallet/browser/asset_ratio_response_parser_unittest.cc @@ -15,10 +15,54 @@ namespace brave_wallet { TEST(AssetRatioResponseParserUnitTest, ParseAssetPrice) { - std::string json( - R"({"payload": {"basic-attention-token":{"usd":0.694503}}})"); - std::string price; - ASSERT_TRUE(ParseAssetPrice(json, &price)); + std::string json(R"({ + "payload":{ + "basic-attention-token":{ + "btc":0.00001732, + "btc_24h_change":8.021672460190562, + "usd":0.55393, + "usd_24h_change":9.523443444373276 + }, + "bat":{ + "btc":0.00001732, + "btc_24h_change":8.021672460190562, + "usd":0.55393, + "usd_24h_change":9.523443444373276 + }, + "link":{ + "btc":0.00261901, + "btc_24h_change":0.5871625385632929, + "usd":83.77, + "usd_24h_change":1.7646208048244043 + } + }, + "lastUpdated":"2021-07-16T19:11:28.907Z" + })"); + + std::vector prices; + ASSERT_TRUE(ParseAssetPrice(json, {"bat", "link"}, {"btc", "usd"}, &prices)); + ASSERT_EQ(prices.size(), 4UL); + ASSERT_EQ(prices[0]->from_asset, "bat"); + ASSERT_EQ(prices[0]->to_asset, "btc"); + ASSERT_EQ(prices[0]->price, "0.00001732"); + ASSERT_EQ(prices[0]->asset_24h_change, "8.021672460190562"); + + ASSERT_EQ(prices[1]->from_asset, "bat"); + ASSERT_EQ(prices[1]->to_asset, "usd"); + ASSERT_EQ(prices[1]->price, "0.55393"); + ASSERT_EQ(prices[1]->asset_24h_change, "9.523443444373276"); + + ASSERT_EQ(prices[2]->from_asset, "link"); + ASSERT_EQ(prices[2]->to_asset, "btc"); + ASSERT_EQ(prices[2]->price, "0.00261901"); + ASSERT_EQ(prices[2]->asset_24h_change, "0.5871625385632929"); + + ASSERT_EQ(prices[3]->from_asset, "link"); + ASSERT_EQ(prices[3]->to_asset, "usd"); + ASSERT_EQ(prices[3]->price, "83.77"); + ASSERT_EQ(prices[3]->asset_24h_change, "1.7646208048244043"); + + /* ASSERT_EQ(price, "0.694503"); // 2 value responses happen now for the alias and the full name // We always parse only the first. @@ -35,6 +79,7 @@ TEST(AssetRatioResponseParserUnitTest, ParseAssetPrice) { ASSERT_FALSE(ParseAssetPrice(json, &price)); json = ""; ASSERT_FALSE(ParseAssetPrice(json, &price)); + */ } TEST(AssetRatioResponseParserUnitTest, ParseAssetPriceHistory) { diff --git a/components/brave_wallet/common/brave_wallet.mojom b/components/brave_wallet/common/brave_wallet.mojom index 0325096591b..f76704ba5bc 100644 --- a/components/brave_wallet/common/brave_wallet.mojom +++ b/components/brave_wallet/common/brave_wallet.mojom @@ -75,6 +75,13 @@ struct AssetTimePrice { string price; }; +struct AssetPrice { + string from_asset; + string to_asset; + string price; + string asset_24h_change; +}; + struct SwapParams { string taker_address; string sell_amount; @@ -124,7 +131,7 @@ interface WalletHandler { array walletAccountNames); LockWallet(); UnlockWallet(string password) => (bool isWalletUnlocked); - GetAssetPrice(string asset) => (bool success, string price); + GetAssetPrice(array from_assets, array to_assets) => (bool success, array values); GetAssetPriceHistory(string asset, AssetPriceTimeframe timeframe) => (bool success, array values); GetPriceQuote(SwapParams params) => (bool success, SwapResponse response); @@ -166,7 +173,8 @@ interface KeyringController { }; interface AssetRatioController { - GetPrice(string asset) => (bool success, string price); + GetPrice(array from_assets, array to_assets) => + (bool success, array values); GetPriceHistory(string asset, AssetPriceTimeframe timeframe) => (bool success, array values); }; diff --git a/components/brave_wallet_ui/components/desktop/views/crypto/index.tsx b/components/brave_wallet_ui/components/desktop/views/crypto/index.tsx index 6e96ea6ac60..f20a8939ccd 100644 --- a/components/brave_wallet_ui/components/desktop/views/crypto/index.tsx +++ b/components/brave_wallet_ui/components/desktop/views/crypto/index.tsx @@ -9,7 +9,7 @@ import { AssetOptionType, UserAssetOptionType, RPCTransactionType, - AssetPriceReturnInfo, + AssetPriceInfo, WalletAccountType, AssetPriceTimeframe } from '../../../../constants/types' @@ -37,7 +37,8 @@ export interface Props { selectedTimeline: AssetPriceTimeframe portfolioPriceHistory: PriceDataObjectType[] selectedAssetPriceHistory: PriceDataObjectType[] - selectedAssetPrice: AssetPriceReturnInfo | undefined + selectedUSDAssetPrice: AssetPriceInfo | undefined + selectedBTCAssetPrice: AssetPriceInfo | undefined selectedAsset: AssetOptionType | undefined portfolioBalance: string transactions: (RPCTransactionType | undefined)[] @@ -68,7 +69,8 @@ const CryptoView = (props: Props) => { selectedAsset, portfolioBalance, transactions, - selectedAssetPrice, + selectedUSDAssetPrice, + selectedBTCAssetPrice, isLoading, showAddModal, onToggleAddModal @@ -169,7 +171,8 @@ const CryptoView = (props: Props) => { portfolioBalance={portfolioBalance} portfolioPriceHistory={portfolioPriceHistory} transactions={transactions} - selectedAssetPrice={selectedAssetPrice} + selectedUSDAssetPrice={selectedUSDAssetPrice} + selectedBTCAssetPrice={selectedBTCAssetPrice} userAssetList={userAssetList} isLoading={isLoading} /> diff --git a/components/brave_wallet_ui/components/desktop/views/portfolio/index.tsx b/components/brave_wallet_ui/components/desktop/views/portfolio/index.tsx index 2c798daa6db..1f7810e6048 100644 --- a/components/brave_wallet_ui/components/desktop/views/portfolio/index.tsx +++ b/components/brave_wallet_ui/components/desktop/views/portfolio/index.tsx @@ -5,7 +5,7 @@ import { PriceDataObjectType, AssetOptionType, RPCTransactionType, - AssetPriceReturnInfo, + AssetPriceInfo, UserAssetOptionType, WalletAccountType, AssetPriceTimeframe @@ -59,7 +59,8 @@ export interface Props { accounts: WalletAccountType[] selectedTimeline: AssetPriceTimeframe selectedAsset: AssetOptionType | undefined - selectedAssetPrice: AssetPriceReturnInfo | undefined + selectedUSDAssetPrice: AssetPriceInfo | undefined + selectedBTCAssetPrice: AssetPriceInfo | undefined selectedAssetPriceHistory: PriceDataObjectType[] portfolioPriceHistory: PriceDataObjectType[] portfolioBalance: string @@ -75,7 +76,8 @@ const Portfolio = (props: Props) => { onClickAddAccount, portfolioPriceHistory, selectedAssetPriceHistory, - selectedAssetPrice, + selectedUSDAssetPrice, + selectedBTCAssetPrice, selectedTimeline, accounts, selectedAsset, @@ -168,17 +170,17 @@ const Portfolio = (props: Props) => { {selectedAsset.name} {locale.price} ({selectedAsset.symbol}) - ${hoverPrice ? hoverPrice : selectedAssetPrice ? formatePrices(Number(selectedAssetPrice.usd)) : 0.00} - - - {selectedAssetPrice ? selectedAssetPrice.change24Hour : 0}% + ${hoverPrice ? hoverPrice : selectedUSDAssetPrice ? formatePrices(Number(selectedUSDAssetPrice.price)) : 0.00} + + + {selectedUSDAssetPrice ? Number(selectedUSDAssetPrice.asset24hChange).toFixed(2) : 0.00}% - {selectedAssetPrice ? selectedAssetPrice.btc : 0} BTC + {selectedBTCAssetPrice ? selectedBTCAssetPrice.price : 0} BTC )} Promise addAccountToWallet: () => Promise unlockWallet: (password: string) => Promise - getAssetPrice: (asset: string) => Promise + getAssetPrice: (fromAssets: string[], toAssets: string[]) => Promise getAssetPriceHistory: (asset: string, timeframe: AssetPriceTimeframe) => Promise addFavoriteApp: (appItem: AppObjectType) => Promise removeFavoriteApp: (appItem: AppObjectType) => Promise diff --git a/components/brave_wallet_ui/page/async/wallet_page_async_handler.ts b/components/brave_wallet_ui/page/async/wallet_page_async_handler.ts index 4fd54886f42..851c854548e 100644 --- a/components/brave_wallet_ui/page/async/wallet_page_async_handler.ts +++ b/components/brave_wallet_ui/page/async/wallet_page_async_handler.ts @@ -74,17 +74,16 @@ handler.on(WalletPageActions.walletBackupComplete.getType(), async (store) => { await refreshWalletInfo(store) }) -// TODO: Spot Price will need to return btc: value and change24Hour: value in the future handler.on(WalletPageActions.selectAsset.getType(), async (store, payload: UpdateSelectedAssetType) => { store.dispatch(WalletPageActions.updateSelectedAsset(payload.asset)) store.dispatch(WalletPageActions.setIsFetchingPriceHistory(true)) const walletHandler = await getWalletHandler() if (payload.asset) { - const price = await walletHandler.getAssetPrice(payload.asset.symbol.toLowerCase()) + const priceInfo = await walletHandler.getAssetPrice([payload.asset.symbol.toLowerCase()], ['usd', 'btc']) const priceHistory = await walletHandler.getAssetPriceHistory(payload.asset.symbol.toLowerCase(), payload.timeFrame) - store.dispatch(WalletPageActions.updatePriceInfo({ priceHistory: priceHistory, price: price.price, timeFrame: payload.timeFrame })) + store.dispatch(WalletPageActions.updatePriceInfo({ priceHistory: priceHistory, usdPriceInfo: priceInfo.values[0], btcPriceInfo: priceInfo.values[1], timeFrame: payload.timeFrame })) } else { - store.dispatch(WalletPageActions.updatePriceInfo({ priceHistory: undefined, price: '', timeFrame: payload.timeFrame })) + store.dispatch(WalletPageActions.updatePriceInfo({ priceHistory: undefined, btcPriceInfo: undefined, usdPriceInfo: undefined, timeFrame: payload.timeFrame })) } }) diff --git a/components/brave_wallet_ui/page/constants/action_types.ts b/components/brave_wallet_ui/page/constants/action_types.ts index f14fe9db68b..4713e04b50f 100644 --- a/components/brave_wallet_ui/page/constants/action_types.ts +++ b/components/brave_wallet_ui/page/constants/action_types.ts @@ -2,7 +2,7 @@ // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this file, // you can obtain one at http://mozilla.org/MPL/2.0/. -import { GetAssetPriceHistoryReturnObjectInfo, AssetOptionType, AssetPriceTimeframe } from '../../constants/types' +import { GetAssetPriceHistoryReturnObjectInfo, AssetOptionType, AssetPriceInfo, AssetPriceTimeframe } from '../../constants/types' export type CreateWalletPayloadType = { password: string @@ -32,6 +32,7 @@ export type UpdateSelectedAssetType = { export type SelectAssetPayloadType = { priceHistory: GetAssetPriceHistoryReturnObjectInfo | undefined, - price: string + usdPriceInfo: AssetPriceInfo | undefined, + btcPriceInfo: AssetPriceInfo | undefined, timeFrame: AssetPriceTimeframe } diff --git a/components/brave_wallet_ui/page/container.tsx b/components/brave_wallet_ui/page/container.tsx index 2abd3f6175c..0aecce9ce7a 100644 --- a/components/brave_wallet_ui/page/container.tsx +++ b/components/brave_wallet_ui/page/container.tsx @@ -74,7 +74,8 @@ function Container (props: Props) { mnemonic, selectedTimeline, selectedAsset, - selectedAssetPrice, + selectedUSDAssetPrice, + selectedBTCAssetPrice, selectedAssetPriceHistory, portfolioPriceHistory, userAssets, @@ -373,7 +374,8 @@ function Container (props: Props) { onSelectAsset={onSelectAsset} portfolioBalance={fullPortfolioBalance} selectedAsset={selectedAsset} - selectedAssetPrice={selectedAssetPrice} + selectedUSDAssetPrice={selectedUSDAssetPrice} + selectedBTCAssetPrice={selectedBTCAssetPrice} selectedAssetPriceHistory={formatedPriceHistory} portfolioPriceHistory={portfolioPriceHistory} selectedTimeline={selectedTimeline} diff --git a/components/brave_wallet_ui/page/reducers/page_reducer.ts b/components/brave_wallet_ui/page/reducers/page_reducer.ts index 390c3d27648..6ba98a49dc8 100644 --- a/components/brave_wallet_ui/page/reducers/page_reducer.ts +++ b/components/brave_wallet_ui/page/reducers/page_reducer.ts @@ -15,7 +15,8 @@ const defaultState: PageState = { invalidMnemonic: false, selectedTimeline: AssetPriceTimeframe.OneDay, selectedAsset: undefined, - selectedAssetPrice: undefined, + selectedUSDAssetPrice: undefined, + selectedBTCAssetPrice: undefined, selectedAssetPriceHistory: [], portfolioPriceHistory: [], userAssets: ['1', '2'], @@ -78,11 +79,8 @@ reducer.on(Actions.updatePriceInfo, (state: PageState, payload: SelectAssetPaylo const history = payload.priceHistory ? payload.priceHistory.values : [] return { ...state, - selectedAssetPrice: payload.priceHistory ? { - usd: payload.price, - btc: 0, - change24Hour: 0 - } : undefined, + selectedUSDAssetPrice: payload.usdPriceInfo, + selectedBTCAssetPrice: payload.btcPriceInfo, selectedAssetPriceHistory: history, selectedTimeline: payload.timeFrame, isFetchingPriceHistory: false diff --git a/components/brave_wallet_ui/stories/mock-data/current-price-data.ts b/components/brave_wallet_ui/stories/mock-data/current-price-data.ts index 15f8088cb0d..0312e63cf73 100644 --- a/components/brave_wallet_ui/stories/mock-data/current-price-data.ts +++ b/components/brave_wallet_ui/stories/mock-data/current-price-data.ts @@ -2,30 +2,34 @@ export const CurrentPriceMockData = [ { name: 'Bitcoin', symbol: 'BTC', - usd: 56806.36, - btc: 1, - change24Hour: 2.3 + usd: '56806.36', + btc: '1', + usd24hChange: '2.3', + btc24hChange: '-0.1' }, { name: 'Binance Coin', symbol: 'BNB', - usd: 502.24, - btc: 0.0098, - change24Hour: -4.6 + usd: '502.24', + btc: '0.0098', + usd24hChange: '-4.6', + btc24hChange: '-4.8' }, { name: 'Ethereum', symbol: 'ETH', - usd: 2156.20, - btc: 0.042, - change24Hour: 0.2 + usd: '2156.20', + btc: '0.042', + usd24hChange: '0.2', + btc24hChange: '0.3' }, { name: 'Basic Attention Token', symbol: 'BAT', - usd: 1.34, - btc: 0.000022, - change24Hour: 20 + usd: '1.34', + btc: '0.000022', + usd24hChange: '2', + btc24hChange: '2.1' } ] diff --git a/components/brave_wallet_ui/stories/wallet-concept.tsx b/components/brave_wallet_ui/stories/wallet-concept.tsx index 722ca828002..06f7325f5cb 100644 --- a/components/brave_wallet_ui/stories/wallet-concept.tsx +++ b/components/brave_wallet_ui/stories/wallet-concept.tsx @@ -12,7 +12,7 @@ import { AssetPriceTimeframe, PriceDataObjectType, AssetOptionType, - AssetPriceReturnInfo, + AssetPriceInfo, RPCResponseType, NetworkOptionsType, OrderTypes, @@ -127,16 +127,32 @@ export const _DesktopWalletConcept = (args: { onboarding: boolean, locked: boole } } - const selectedAssetPrice = React.useMemo(() => { + const selectedUSDAssetPrice = React.useMemo(() => { if (selectedAsset) { const data = CurrentPriceMockData.find((coin) => coin.symbol === selectedAsset.symbol) - const usdValue = data ? data.usd : 0 - const btcValue = data ? data.btc : 0 - const change24Hour = data ? data.change24Hour : 0 - const response: AssetPriceReturnInfo = { - usd: formatePrices(usdValue), - btc: btcValue, - change24Hour: change24Hour + const usdValue = data ? data.usd : '0' + const usd24hChange = data ? data.usd24hChange : '0' + const response: AssetPriceInfo = { + price: usdValue, + asset24hChange: usd24hChange, + fromAsset: '', + toAsset: '' + } + return response + } + return undefined + }, [selectedAsset]) + + const selectedBTCAssetPrice = React.useMemo(() => { + if (selectedAsset) { + const data = CurrentPriceMockData.find((coin) => coin.symbol === selectedAsset.symbol) + const btcValue = data ? data.btc : '0' + const btc24hChange = data ? data.btc24hChange : '0' + const response: AssetPriceInfo = { + price: btcValue, + asset24hChange: btc24hChange, + fromAsset: '', + toAsset: '' } return response } @@ -152,7 +168,7 @@ export const _DesktopWalletConcept = (args: { onboarding: boolean, locked: boole const singleAccountFiatBalance = (account: RPCResponseType) => { const asset = assetInfo(account) const data = CurrentPriceMockData.find((coin) => coin.symbol === asset?.symbol) - const value = data ? asset ? asset.balance * data.usd : 0 : 0 + const value = data ? asset ? Number(asset.balance) * Number(data.usd) : 0 : 0 return formatePrices(value) } @@ -215,7 +231,7 @@ export const _DesktopWalletConcept = (args: { onboarding: boolean, locked: boole // This will scrape all of the user's accounts and combine the fiat value for a single asset const scrapedFullAssetFiatBalance = (asset: AssetOptionType) => { const fullBallance = scrapedFullAssetBalance(asset) - const price = CurrentPriceMockData.find((coin) => coin.symbol === asset?.symbol)?.usd + const price = Number(CurrentPriceMockData.find((coin) => coin.symbol === asset?.symbol)?.usd) const value = price ? price * fullBallance : 0 return value } @@ -433,7 +449,8 @@ export const _DesktopWalletConcept = (args: { onboarding: boolean, locked: boole portfolioPriceHistory={selectedAssetPriceHistory} portfolioBalance={scrapedFullPortfolioBalance()} transactions={transactions} - selectedAssetPrice={selectedAssetPrice} + selectedUSDAssetPrice={selectedUSDAssetPrice} + selectedBTCAssetPrice={selectedBTCAssetPrice} userAssetList={userAssetList} onConnectHardwareWallet={onConnectHardwareWallet} onCreateAccount={onCreateAccount}