From 5d5444e3decab9ecebb32a4af9ac98eeb13df465 Mon Sep 17 00:00:00 2001 From: psdp <4315882+psdp@users.noreply.github.com> Date: Sun, 29 Apr 2018 15:36:24 +0000 Subject: [PATCH] Show fiat value of wallet assets #4009 --- src/status_im/ui/screens/wallet/events.cljs | 11 ++--- src/status_im/ui/screens/wallet/styles.cljs | 11 +++++ src/status_im/ui/screens/wallet/subs.cljs | 48 ++++++++++++++++----- src/status_im/ui/screens/wallet/views.cljs | 35 ++++++++------- src/status_im/utils/money.cljs | 4 +- src/status_im/utils/prices.cljs | 23 +++++----- test/cljs/status_im/test/runner.cljs | 8 +++- test/cljs/status_im/test/utils/prices.cljs | 9 ++++ test/cljs/status_im/test/wallet/subs.cljs | 12 ++++++ 9 files changed, 115 insertions(+), 46 deletions(-) create mode 100644 test/cljs/status_im/test/utils/prices.cljs create mode 100644 test/cljs/status_im/test/wallet/subs.cljs diff --git a/src/status_im/ui/screens/wallet/events.cljs b/src/status_im/ui/screens/wallet/events.cljs index 84b43b65a6..4b518b7f72 100644 --- a/src/status_im/ui/screens/wallet/events.cljs +++ b/src/status_im/ui/screens/wallet/events.cljs @@ -94,9 +94,10 @@ (handlers/register-handler-fx :update-wallet (fn [{{:keys [web3 account/account network network-status] :as db} :db} _] - (let [chain (ethereum/network->chain-keyword network) - address (:address account) - symbols (get-in account [:settings :wallet :visible-tokens chain])] + (let [chain (ethereum/network->chain-keyword network) + mainnet? (= :mainnet chain) + address (:address account) + symbols (get-in account [:settings :wallet :visible-tokens chain])] (when (not= network-status :offline) {:get-balance {:web3 web3 :account-id address @@ -108,8 +109,8 @@ :chain chain :success-event :update-token-balance-success :error-event :update-token-balance-fail} - :get-prices {:from "ETH" - :to "USD" + :get-prices {:from (if mainnet? (conj symbols "ETH") ["ETH"]) + :to ["USD"] :success-event :update-prices-success :error-event :update-prices-fail} :db (-> db diff --git a/src/status_im/ui/screens/wallet/styles.cljs b/src/status_im/ui/screens/wallet/styles.cljs index 2d0781de36..d009d90da8 100644 --- a/src/status_im/ui/screens/wallet/styles.cljs +++ b/src/status_im/ui/screens/wallet/styles.cljs @@ -134,6 +134,12 @@ :margin-left 16 :color colors/gray}) +(def asset-item-container + {:flex 1 + :flex-direction :row + :align-items :center + :justify-content :space-between}) + (def asset-item-value-container {:flex 1 :flex-direction :row @@ -148,3 +154,8 @@ {:font-size 16 :color colors/gray :margin-left 6}) + +(def asset-item-price + {:font-size 16 + :color colors/gray + :margin-left 6}) diff --git a/src/status_im/ui/screens/wallet/subs.cljs b/src/status_im/ui/screens/wallet/subs.cljs index 1feb016a97..3d4f771e9a 100644 --- a/src/status_im/ui/screens/wallet/subs.cljs +++ b/src/status_im/ui/screens/wallet/subs.cljs @@ -13,23 +13,49 @@ (fn [wallet] (:balance wallet))) -(re-frame/reg-sub :price +(re-frame/reg-sub :prices (fn [db] - (get-in db [:prices :price]))) + (:prices db))) + +(re-frame/reg-sub :price + :<- [:prices] + (fn [prices [_ fsym tsym]] + (get-in prices [fsym tsym :price]))) (re-frame/reg-sub :last-day - (fn [db] - (get-in db [:prices :last-day]))) + :<- [:prices] + (fn [prices [_ fsym tsym]] + (get-in prices [fsym tsym :last-day]))) + +(re-frame/reg-sub :asset-value + (fn [[_ fsym tsym]] + [(re-frame/subscribe [:balance]) + (re-frame/subscribe [:price fsym tsym])]) + (fn [[balance price] [_ fsym tsym]] + (when (and balance price) + (-> (money/wei->ether (get balance fsym)) + (money/eth->fiat price) + (money/with-precision 2) + str)))) + +(defn- get-balance-total-value [balance prices currency] + (->> balance + (reduce-kv (fn [acc symbol value] + (if-let [price (get-in prices [symbol currency :price])] + (+ acc (-> (money/wei->ether value) + (money/eth->fiat price) + .toNumber)) + acc)) 0))) (re-frame/reg-sub :portfolio-value :<- [:balance] - :<- [:price] - (fn [[balance price]] - (if (and balance price) - (-> (money/wei->ether (get balance :ETH)) ;; TODO(jeluard) Modify to consider tokens - (money/eth->usd price) - (money/with-precision 2) - str) + :<- [:prices] + (fn [[balance prices] [_ currency]] + (if (and balance prices) + (let [balance-total-value (get-balance-total-value balance prices currency)] + (-> balance-total-value + (money/with-precision 2) + str)) "..."))) (re-frame/reg-sub :prices-loading? diff --git a/src/status_im/ui/screens/wallet/views.cljs b/src/status_im/ui/screens/wallet/views.cljs index 38410f7b9c..5ab9043b59 100644 --- a/src/status_im/ui/screens/wallet/views.cljs +++ b/src/status_im/ui/screens/wallet/views.cljs @@ -49,21 +49,24 @@ :action #(re-frame/dispatch [:navigate-to :transactions-history])}]) (defn- render-asset [{:keys [symbol icon decimals amount]}] - [react/view - [list/item - [list/item-image icon] - [react/view {:style styles/asset-item-value-container} - [react/text {:style styles/asset-item-value - :number-of-lines 1 - :ellipsize-mode :tail - :accessibility-label (str (-> symbol name clojure.string/lower-case) "-asset-value-text")} - (wallet.utils/format-amount amount decimals)] - [react/text {:style styles/asset-item-currency - :uppercase? true - :number-of-lines 1} - (clojure.core/name symbol)]]]]) - - + (let [asset-value (re-frame/subscribe [:asset-value symbol :USD])] + [react/view {:style styles/asset-item-container} + [list/item + [list/item-image icon] + [react/view {:style styles/asset-item-value-container} + [react/text {:style styles/asset-item-value + :number-of-lines 1 + :ellipsize-mode :tail + :accessibility-label (str (-> symbol name clojure.string/lower-case) "-asset-value-text")} + (wallet.utils/format-amount amount decimals)] + [react/text {:style styles/asset-item-currency + :uppercase? true + :number-of-lines 1} + (clojure.core/name symbol)]] + [react/text {:style styles/asset-item-price + :uppercase? true + :number-of-lines 1} + (if @asset-value (str "$" @asset-value) "...")]]])) (defn- asset-section [assets] [react/view styles/asset-section @@ -77,7 +80,7 @@ (views/defview wallet [] (views/letsubs [assets [:wallet/visible-assets-with-amount] - portfolio-value [:portfolio-value]] + portfolio-value [:portfolio-value :USD]] [react/view styles/main-section [toolbar-view] [react/scroll-view {:refresh-control diff --git a/src/status_im/utils/money.cljs b/src/status_im/utils/money.cljs index 846a5e4ef9..ef6cf03fe1 100644 --- a/src/status_im/utils/money.cljs +++ b/src/status_im/utils/money.cljs @@ -93,9 +93,9 @@ (defn fee-value [gas gas-price] (.times (bignumber gas) (bignumber gas-price))) -(defn eth->usd [eth usd-price] +(defn eth->fiat [eth fiat-price] (when-let [bn (bignumber eth)] - (.times bn (bignumber usd-price)))) + (.times bn (bignumber fiat-price)))) (defn percent-change [from to] (let [bnf (bignumber from) diff --git a/src/status_im/utils/prices.cljs b/src/status_im/utils/prices.cljs index 4c1d1f96cf..d3e50e8c02 100644 --- a/src/status_im/utils/prices.cljs +++ b/src/status_im/utils/prices.cljs @@ -13,19 +13,22 @@ (def api-url "https://min-api.cryptocompare.com/data") (def status-identifier "extraParams=Status.im") -(defn- gen-price-url [fsyms tsyms] - (str api-url "/pricemultifull?fsyms=" fsyms "&tsyms=" tsyms "&" status-identifier)) +(defn- ->url-param-syms [syms] + ((comp (partial clojure.string/join ",") (partial map name)) syms)) -(defn- format-price-resp [from to resp] - (let [raw (:RAW (types/json->clj resp)) - entry (get-in raw [(keyword from) (keyword to)])] - {:from from - :to to - :price (:PRICE entry) - :last-day (:OPEN24HOUR entry)})) +(defn- gen-price-url [fsyms tsyms] + (str api-url "/pricemultifull?fsyms=" (->url-param-syms fsyms) "&tsyms=" (->url-param-syms tsyms) "&" status-identifier)) + +(defn- format-price-resp [resp] + (into {} (for [[from entries] (:RAW (types/json->clj resp))] + {from (into {} (for [[to entry] entries] + {to {:from (name from) + :to (name to) + :price (:PRICE entry) + :last-day (:OPEN24HOUR entry)}}))}))) (defn get-prices [from to on-success on-error] (http/get (gen-price-url from to) - (fn [resp] (on-success (format-price-resp from to resp))) + (fn [resp] (on-success (format-price-resp resp))) on-error)) diff --git a/test/cljs/status_im/test/runner.cljs b/test/cljs/status_im/test/runner.cljs index 4d8f542b25..3902db185b 100644 --- a/test/cljs/status_im/test/runner.cljs +++ b/test/cljs/status_im/test/runner.cljs @@ -5,6 +5,7 @@ [status-im.test.contacts.subs] [status-im.test.accounts.events] [status-im.test.data-store.realm.core] + [status-im.test.wallet.subs] [status-im.test.wallet.transactions.subs] [status-im.test.wallet.transactions.views] [status-im.test.profile.events] @@ -27,7 +28,8 @@ [status-im.test.utils.transducers] [status-im.test.utils.async] [status-im.test.utils.datetime] - [status-im.test.utils.mixpanel])) + [status-im.test.utils.mixpanel] + [status-im.test.utils.prices])) (enable-console-print!) @@ -48,6 +50,7 @@ 'status-im.test.profile.events 'status-im.test.data-store.realm.core 'status-im.test.bots.events + 'status-im.test.wallet.subs 'status-im.test.wallet.transactions.subs 'status-im.test.wallet.transactions.views 'status-im.test.chat.models.input @@ -65,4 +68,5 @@ 'status-im.test.utils.signing-phrase.core 'status-im.test.utils.transducers 'status-im.test.utils.datetime - 'status-im.test.utils.mixpanel) + 'status-im.test.utils.mixpanel + 'status-im.test.utils.prices) diff --git a/test/cljs/status_im/test/utils/prices.cljs b/test/cljs/status_im/test/utils/prices.cljs new file mode 100644 index 0000000000..b821c3cae4 --- /dev/null +++ b/test/cljs/status_im/test/utils/prices.cljs @@ -0,0 +1,9 @@ +(ns status-im.test.utils.prices + (:require [cljs.test :refer-macros [deftest is]] + [status-im.utils.prices :as prices])) + +(deftest test-format-price-resp + (is (= (prices/format-price-resp + "{\"RAW\":{\"ETH\":{\"USD\":{\"TYPE\":\"5\",\"MARKET\":\"CCCAGG\",\"FROMSYMBOL\":\"ETH\",\"TOSYMBOL\":\"USD\",\"FLAGS\":\"4\",\"PRICE\":677.91,\"LASTUPDATE\":1525241472,\"LASTVOLUME\":0.69661268,\"LASTVOLUMETO\":472.0874471092,\"LASTTRADEID\":\"1525241472.6714\",\"VOLUMEDAY\":109859.96594606241,\"VOLUMEDAYTO\":73924561.52673237,\"VOLUME24HOUR\":408811.69032152055,\"VOLUME24HOURTO\":270617692.0100031,\"OPENDAY\":670.81,\"HIGHDAY\":681.06,\"LOWDAY\":662.13,\"OPEN24HOUR\":658.68,\"HIGH24HOUR\":681.67,\"LOW24HOUR\":638.25,\"LASTMARKET\":\"Kraken\",\"CHANGE24HOUR\":19.230000000000018,\"CHANGEPCT24HOUR\":2.919475314264896,\"CHANGEDAY\":7.100000000000023,\"CHANGEPCTDAY\":1.0584219078427608,\"SUPPLY\":99176837.749,\"MKTCAP\":67232970078.42458,\"TOTALVOLUME24H\":1308785.4697758215,\"TOTALVOLUME24HTO\":880718916.8398683}},\"SNT\":{\"USD\":{\"TYPE\":\"5\",\"MARKET\":\"CCCAGG\",\"FROMSYMBOL\":\"SNT\",\"TOSYMBOL\":\"USD\",\"FLAGS\":\"1\",\"PRICE\":0.1562,\"LASTUPDATE\":1525241236,\"LASTVOLUME\":582.07218,\"LASTVOLUMETO\":90.919674516,\"LASTTRADEID\":\"237582608\",\"VOLUMEDAY\":259125.16382211001,\"VOLUMEDAYTO\":40450.5318867195,\"VOLUME24HOUR\":1451022.9449243098,\"VOLUME24HOURTO\":223465.71221695316,\"OPENDAY\":0.1573,\"HIGHDAY\":0.1592,\"LOWDAY\":0.1532,\"OPEN24HOUR\":0.15,\"HIGH24HOUR\":0.1657,\"LOW24HOUR\":0.1481,\"LASTMARKET\":\"Bitfinex\",\"CHANGE24HOUR\":0.006200000000000011,\"CHANGEPCT24HOUR\":4.133333333333341,\"CHANGEDAY\":-0.0010999999999999899,\"CHANGEPCTDAY\":-0.6993006993006928,\"SUPPLY\":6804870174.87817,\"MKTCAP\":1062920721.3159702,\"TOTALVOLUME24H\":239970152.87898657,\"TOTALVOLUME24HTO\":37480153.807917476}}},\"DISPLAY\":{\"ETH\":{\"USD\":{\"FROMSYMBOL\":\"Ξ\",\"TOSYMBOL\":\"$\",\"MARKET\":\"CryptoCompare Index\",\"PRICE\":\"$ 677.91\",\"LASTUPDATE\":\"Just now\",\"LASTVOLUME\":\"Ξ 0.6966\",\"LASTVOLUMETO\":\"$ 472.09\",\"LASTTRADEID\":\"1525241472.6714\",\"VOLUMEDAY\":\"Ξ 109,860.0\",\"VOLUMEDAYTO\":\"$ 73,924,561.5\",\"VOLUME24HOUR\":\"Ξ 408,811.7\",\"VOLUME24HOURTO\":\"$ 270,617,692.0\",\"OPENDAY\":\"$ 670.81\",\"HIGHDAY\":\"$ 681.06\",\"LOWDAY\":\"$ 662.13\",\"OPEN24HOUR\":\"$ 658.68\",\"HIGH24HOUR\":\"$ 681.67\",\"LOW24HOUR\":\"$ 638.25\",\"LASTMARKET\":\"Kraken\",\"CHANGE24HOUR\":\"$ 19.23\",\"CHANGEPCT24HOUR\":\"2.92\",\"CHANGEDAY\":\"$ 7.10\",\"CHANGEPCTDAY\":\"1.06\",\"SUPPLY\":\"Ξ 99,176,837.7\",\"MKTCAP\":\"$ 67.23 B\",\"TOTALVOLUME24H\":\"Ξ 1,308.79 K\",\"TOTALVOLUME24HTO\":\"$ 880.72 M\"}},\"SNT\":{\"USD\":{\"FROMSYMBOL\":\"SNT\",\"TOSYMBOL\":\"$\",\"MARKET\":\"CryptoCompare Index\",\"PRICE\":\"$ 0.1562\",\"LASTUPDATE\":\"3 min ago\",\"LASTVOLUME\":\"SNT 582.07\",\"LASTVOLUMETO\":\"$ 90.92\",\"LASTTRADEID\":\"237582608\",\"VOLUMEDAY\":\"SNT 259,125.2\",\"VOLUMEDAYTO\":\"$ 40,450.5\",\"VOLUME24HOUR\":\"SNT 1,451,022.9\",\"VOLUME24HOURTO\":\"$ 223,465.7\",\"OPENDAY\":\"$ 0.1573\",\"HIGHDAY\":\"$ 0.1592\",\"LOWDAY\":\"$ 0.1532\",\"OPEN24HOUR\":\"$ 0.1500\",\"HIGH24HOUR\":\"$ 0.1657\",\"LOW24HOUR\":\"$ 0.1481\",\"LASTMARKET\":\"Bitfinex\",\"CHANGE24HOUR\":\"$ 0.0062\",\"CHANGEPCT24HOUR\":\"4.13\",\"CHANGEDAY\":\"$ -0.0011\",\"CHANGEPCTDAY\":\"-0.70\",\"SUPPLY\":\"SNT 6,804,870,174.9\",\"MKTCAP\":\"$ 1,062.92 M\",\"TOTALVOLUME24H\":\"SNT 239.97 M\",\"TOTALVOLUME24HTO\":\"$ 37.48 M\"}}}}") + {:ETH {:USD {:from "ETH", :to "USD", :price 677.91, :last-day 658.68}} + :SNT {:USD {:from "SNT", :to "USD", :price 0.1562, :last-day 0.15}}}))) diff --git a/test/cljs/status_im/test/wallet/subs.cljs b/test/cljs/status_im/test/wallet/subs.cljs new file mode 100644 index 0000000000..d5452160ff --- /dev/null +++ b/test/cljs/status_im/test/wallet/subs.cljs @@ -0,0 +1,12 @@ +(ns status-im.test.wallet.subs + (:require [cljs.test :refer-macros [deftest is]] + [status-im.utils.money :as money] + [status-im.ui.screens.wallet.subs :as s])) + +(deftest test-balance-total-value + (is (= (s/get-balance-total-value {:ETH (money/bignumber 1000000000000000000) + :SNT (money/bignumber 100000000000000000000)} + {:ETH {:USD {:from "ETH", :to "USD", :price 677.91, :last-day 658.688}} + :SNT {:USD {:from "SNT", :to "USD", :price 0.1562, :last-day 0.15}}} + :USD) + 693.53)))