Merge pull request #9503 from brave/asset-price-api-fixes

Update GetAssetPrice API to support multiple from/to assets and 24h change
This commit is contained in:
Brian R. Bondy
2021-07-23 15:51:20 -04:00
committed by GitHub
21 changed files with 367 additions and 140 deletions
@@ -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);
}
}
@@ -5,7 +5,10 @@
#include "brave/browser/brave_wallet/android/brave_wallet_native_worker.h"
#include <vector>
#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<jstring>& asset) {
const base::android::JavaParamRef<jobjectArray>& from_assets,
const base::android::JavaParamRef<jobjectArray>& to_assets) {
EnsureConnected();
std::vector<std::string> assets_from;
base::android::AppendJavaStringArrayToStringVector(env, from_assets,
&assets_from);
std::vector<std::string> 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<brave_wallet::mojom::AssetPricePtr> 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(
@@ -40,9 +40,12 @@ class BraveWalletNativeWorker {
const base::android::JavaParamRef<jstring>& password);
void ResetWallet(JNIEnv* env);
void GetAssetPrice(JNIEnv* env,
const base::android::JavaParamRef<jstring>& asset);
void OnGetPrice(bool success, const std::string& price);
void GetAssetPrice(
JNIEnv* env,
const base::android::JavaParamRef<jobjectArray>& from_assets,
const base::android::JavaParamRef<jobjectArray>& to_assets);
void OnGetPrice(bool success,
std::vector<brave_wallet::mojom::AssetPricePtr> prices);
void GetAssetPriceHistory(JNIEnv* env,
const base::android::JavaParamRef<jstring>& asset,
@@ -30,8 +30,7 @@ std::unique_ptr<net::test_server::HttpResponse> 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<net::test_server::HttpResponse> 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<brave_wallet::mojom::AssetPricePtr> 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<brave_wallet::mojom::AssetPricePtr> 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<brave_wallet::mojom::AssetPricePtr> expected_prices_response_;
std::vector<brave_wallet::mojom::AssetTimePricePtr>
expected_price_history_response_;
@@ -154,28 +177,59 @@ class AssetRatioControllerTest : public InProcessBrowserTest {
};
IN_PROC_BROWSER_TEST_F(AssetRatioControllerTest, GetPrice) {
std::vector<brave_wallet::mojom::AssetPricePtr> 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<brave_wallet::mojom::AssetPricePtr> 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<brave_wallet::mojom::AssetTimePricePtr>
@@ -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<std::string>& from_assets,
const std::vector<std::string>& 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(
@@ -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<std::string>& from_assets,
const std::vector<std::string>& to_assets,
GetAssetPriceCallback) override;
void GetAssetPriceHistory(const std::string& asset,
brave_wallet::mojom::AssetPriceTimeframe timeframe,
GetAssetPriceHistoryCallback) override;
@@ -38,6 +38,17 @@ net::NetworkTrafficAnnotationTag GetNetworkTrafficAnnotationTag() {
)");
}
std::string VectorToCommaSeparatedList(const std::vector<std::string>& 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<std::string>& from_assets,
const std::vector<std::string>& 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<std::string>& from_assets,
const std::vector<std::string>& 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<std::string> from_assets,
std::vector<std::string> to_assets,
GetPriceCallback callback,
const int status,
const std::string& body,
const std::map<std::string, std::string>& headers) {
std::vector<brave_wallet::mojom::AssetPricePtr> 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(
@@ -41,20 +41,25 @@ class AssetRatioController : public KeyedService,
mojo::PendingRemote<mojom::AssetRatioController> MakeRemote();
void GetPrice(const std::string& asset, GetPriceCallback callback) override;
void GetPrice(const std::vector<std::string>& from_assets,
const std::vector<std::string>& 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<std::string>& from_assets,
const std::vector<std::string>& 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<std::string> from_assets,
std::vector<std::string> to_assets,
GetPriceCallback callback,
const int status,
const std::string& body,
const std::map<std::string, std::string>& headers);
@@ -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<std::string>& from_assets,
const std::vector<std::string>& to_assets,
std::vector<brave_wallet::mojom::AssetPricePtr>* 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<double> 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<double> 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;
}
@@ -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<std::string>& from_assets,
const std::vector<std::string>& to_assets,
std::vector<brave_wallet::mojom::AssetPricePtr>* values);
bool ParseAssetPriceHistory(
const std::string& json,
std::vector<brave_wallet::mojom::AssetTimePricePtr>* values);
@@ -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<brave_wallet::mojom::AssetPricePtr> 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) {
@@ -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<string> walletAccountNames);
LockWallet();
UnlockWallet(string password) => (bool isWalletUnlocked);
GetAssetPrice(string asset) => (bool success, string price);
GetAssetPrice(array<string> from_assets, array<string> to_assets) => (bool success, array<AssetPrice> values);
GetAssetPriceHistory(string asset, AssetPriceTimeframe timeframe) =>
(bool success, array<AssetTimePrice> 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<string> from_assets, array<string> to_assets) =>
(bool success, array<AssetPrice> values);
GetPriceHistory(string asset, AssetPriceTimeframe timeframe) =>
(bool success, array<AssetTimePrice> values);
};
@@ -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}
/>
@@ -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) => {
</AssetRow>
<DetailText>{selectedAsset.name} {locale.price} ({selectedAsset.symbol})</DetailText>
<PriceRow>
<PriceText>${hoverPrice ? hoverPrice : selectedAssetPrice ? formatePrices(Number(selectedAssetPrice.usd)) : 0.00}</PriceText>
<PercentBubble isDown={selectedAssetPrice ? selectedAssetPrice.change24Hour < 0 : false}>
<ArrowIcon isDown={selectedAssetPrice ? selectedAssetPrice.change24Hour < 0 : false} />
<PercentText>{selectedAssetPrice ? selectedAssetPrice.change24Hour : 0}%</PercentText>
<PriceText>${hoverPrice ? hoverPrice : selectedUSDAssetPrice ? formatePrices(Number(selectedUSDAssetPrice.price)) : 0.00}</PriceText>
<PercentBubble isDown={selectedUSDAssetPrice ? Number(selectedUSDAssetPrice.asset24hChange) < 0 : false}>
<ArrowIcon isDown={selectedUSDAssetPrice ? Number(selectedUSDAssetPrice.asset24hChange) < 0 : false} />
<PercentText>{selectedUSDAssetPrice ? Number(selectedUSDAssetPrice.asset24hChange).toFixed(2) : 0.00}%</PercentText>
</PercentBubble>
</PriceRow>
<DetailText>{selectedAssetPrice ? selectedAssetPrice.btc : 0} BTC</DetailText>
<DetailText>{selectedBTCAssetPrice ? selectedBTCAssetPrice.price : 0} BTC</DetailText>
</InfoColumn>
)}
<LineChart
isDown={selectedAsset && selectedAssetPrice ? selectedAssetPrice.change24Hour < 0 : false}
isDown={selectedAsset && selectedUSDAssetPrice ? Number(selectedUSDAssetPrice.asset24hChange) < 0 : false}
isAsset={!!selectedAsset}
priceData={selectedAsset ? selectedAssetPriceHistory : portfolioPriceHistory}
onUpdateBalance={onUpdateBalance}
+12 -10
View File
@@ -99,12 +99,6 @@ export type ChartTimelineType =
| '1Year'
| 'AllTime'
export interface AssetPriceReturnInfo {
usd: string
btc: number
change24Hour: number
}
export interface BuySendSwapObjectType {
name: string
id: BuySendSwapTypes
@@ -171,7 +165,8 @@ export interface PageState {
invalidMnemonic: boolean
selectedTimeline: AssetPriceTimeframe
selectedAsset: AssetOptionType | undefined
selectedAssetPrice: AssetPriceReturnInfo | undefined
selectedBTCAssetPrice: AssetPriceInfo | undefined
selectedUSDAssetPrice: AssetPriceInfo | undefined
selectedAssetPriceHistory: GetAssetPriceHistoryReturnInfo[]
portfolioPriceHistory: PriceDataObjectType[]
userAssets: string[]
@@ -249,13 +244,20 @@ export interface SwapResponseReturnInfo {
response: SwapResponse
}
export interface AssetPriceInfo {
fromAsset: string
toAsset: string
price: string
asset24hChange: string
}
export interface GetAssetPriceReturnInfo {
success: boolean,
price: string
values: AssetPriceInfo[]
}
export interface GetAssetPriceHistoryReturnInfo {
price: string,
price: string
date: MojoTime
}
@@ -277,7 +279,7 @@ export interface WalletAPIHandler {
lockWallet: () => Promise<void>
addAccountToWallet: () => Promise<AddAccountToWalletReturnInfo>
unlockWallet: (password: string) => Promise<UnlockWalletReturnInfo>
getAssetPrice: (asset: string) => Promise<GetAssetPriceReturnInfo>
getAssetPrice: (fromAssets: string[], toAssets: string[]) => Promise<GetAssetPriceReturnInfo>
getAssetPriceHistory: (asset: string, timeframe: AssetPriceTimeframe) => Promise<GetAssetPriceHistoryReturnObjectInfo>
addFavoriteApp: (appItem: AppObjectType) => Promise<void>
removeFavoriteApp: (appItem: AppObjectType) => Promise<void>
@@ -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 }))
}
})
@@ -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
}
@@ -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}
@@ -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
@@ -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'
}
]
@@ -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}