From ffeb495b0b36571f0503c577a3f9b97574fc9082 Mon Sep 17 00:00:00 2001 From: Volodymyr Kozieiev Date: Mon, 25 Nov 2024 16:49:57 +0000 Subject: [PATCH] Replace GetWalletToken endpoint with FetchOrGetCachedWalletBalances --- src/legacy/status_im/utils/prices.cljs | 18 -- .../contexts/profile/settings/events.cljs | 24 +- .../wallet/bridge/bridge_to/view.cljs | 10 +- .../wallet/common/asset_list/view.cljs | 25 ++- .../contexts/wallet/common/utils.cljs | 114 ++++++---- .../contexts/wallet/common/utils_test.cljs | 63 +++--- src/status_im/contexts/wallet/events.cljs | 25 ++- .../contexts/wallet/events_test.cljs | 2 +- .../send/input_amount/component_spec.cljs | 49 ++-- .../wallet/send/input_amount/view.cljs | 11 +- .../contexts/wallet/send/routes/view.cljs | 159 ------------- .../sheets/select_asset/asset_list/view.cljs | 12 +- .../contexts/wallet/swap/setup_swap/view.cljs | 10 +- .../contexts/wallet/tokens/events.cljs | 20 +- .../subs/wallet/dapps/transactions.cljs | 9 +- src/status_im/subs/wallet/send.cljs | 5 +- src/status_im/subs/wallet/send_test.cljs | 24 +- src/status_im/subs/wallet/swap.cljs | 47 ++-- src/status_im/subs/wallet/swap_test.cljs | 53 ++--- src/status_im/subs/wallet/wallet.cljs | 97 +++++--- src/status_im/subs/wallet/wallet_test.cljs | 212 +++++++++--------- src/tests/contract_test/wallet_test.cljs | 4 +- 22 files changed, 456 insertions(+), 537 deletions(-) delete mode 100644 src/legacy/status_im/utils/prices.cljs diff --git a/src/legacy/status_im/utils/prices.cljs b/src/legacy/status_im/utils/prices.cljs deleted file mode 100644 index 71b43df6f8..0000000000 --- a/src/legacy/status_im/utils/prices.cljs +++ /dev/null @@ -1,18 +0,0 @@ -(ns legacy.status-im.utils.prices - (:require - [status-im.common.json-rpc.events :as json-rpc])) - -(defn- format-price-resp - [resp to mainnet?] - (if mainnet? - resp - {:ETH (into {} - (for [[_ price] resp] - {(keyword to) price}))})) - -(defn get-prices - [from to mainnet? on-success on-error] - (json-rpc/call {:method "wallet_fetchPrices" - :params [from to] - :on-success (fn [resp] (on-success (format-price-resp resp to mainnet?))) - :on-error on-error})) diff --git a/src/status_im/contexts/profile/settings/events.cljs b/src/status_im/contexts/profile/settings/events.cljs index f346e1cf7d..0da979bd54 100644 --- a/src/status_im/contexts/profile/settings/events.cljs +++ b/src/status_im/contexts/profile/settings/events.cljs @@ -139,10 +139,28 @@ :on-success #(log/debug "mnemonic was marked as shown") :on-error #(log/error "mnemonic was not marked as shown" %)}]]]})) +(defn token-symbols-from-accounts + [accounts] + (reduce-kv (fn [acc _ account] + (into acc (map :symbol (:tokens account)))) + #{} + accounts)) + (rf/reg-event-fx :profile.settings/update-currency - (fn [_ [currency]] - {:fx [[:dispatch [:profile.settings/profile-update :currency currency]] - [:dispatch [:wallet/get-wallet-token-for-all-accounts]]]})) + (fn [{:keys [db]} [currency]] + (let [accounts (get-in db [:wallet :accounts]) + symbols (token-symbols-from-accounts accounts)] + {:fx [[:dispatch [:profile.settings/profile-update :currency currency]] + [:effects.wallet.tokens/fetch-market-values + {:symbols symbols + :currency currency + :on-success [:wallet.tokens/store-market-values] + :on-error [:wallet.tokens/fetch-market-values-failed]}] + [:effects.wallet.tokens/fetch-prices + {:symbols symbols + :currencies [constants/profile-default-currency currency] + :on-success [:wallet.tokens/store-prices] + :on-error [:wallet.tokens/fetch-prices-failed]}]]}))) ;; Logout process (rf/reg-event-fx diff --git a/src/status_im/contexts/wallet/bridge/bridge_to/view.cljs b/src/status_im/contexts/wallet/bridge/bridge_to/view.cljs index 91b0cc6b88..dd61ac099c 100644 --- a/src/status_im/contexts/wallet/bridge/bridge_to/view.cljs +++ b/src/status_im/contexts/wallet/bridge/bridge_to/view.cljs @@ -19,12 +19,14 @@ (let [network (rf/sub [:wallet/network-details-by-chain-id chain-id]) currency (rf/sub [:profile/currency]) currency-symbol (rf/sub [:profile/currency-symbol]) + prices-per-token (rf/sub [:wallet/prices-per-token]) balance (utils/calculate-total-token-balance token [chain-id]) - crypto-value (utils/get-standard-crypto-format token balance) + crypto-value (utils/get-standard-crypto-format token balance prices-per-token) fiat-value (utils/calculate-token-fiat-value - {:currency currency - :balance balance - :token token}) + {:currency currency + :balance balance + :token token + :prices-per-token prices-per-token}) fiat-formatted (utils/fiat-formatted-for-ui currency-symbol fiat-value) token-available-on-network? (network-utils/token-available-on-network? supported-networks diff --git a/src/status_im/contexts/wallet/common/asset_list/view.cljs b/src/status_im/contexts/wallet/common/asset_list/view.cljs index 692f8f1ca8..9adf9e5726 100644 --- a/src/status_im/contexts/wallet/common/asset_list/view.cljs +++ b/src/status_im/contexts/wallet/common/asset_list/view.cljs @@ -12,12 +12,13 @@ disabled? :bridge-disabled? :as token} _ _ - {:keys [currency currency-symbol on-token-press preselected-token-symbol]}] + {:keys [currency currency-symbol on-token-press preselected-token-symbol prices-per-token]}] (let [fiat-value (utils/calculate-token-fiat-value - {:currency currency - :balance total-balance - :token token}) - crypto-formatted (utils/get-standard-crypto-format token total-balance) + {:currency currency + :balance total-balance + :token token + :prices-per-token prices-per-token}) + crypto-formatted (utils/get-standard-crypto-format token total-balance prices-per-token) fiat-formatted (utils/fiat-formatted-for-ui currency-symbol fiat-value)] [quo/token-network {:token token-symbol @@ -34,17 +35,19 @@ (defn view [{:keys [content-container-style search-text on-token-press preselected-token-symbol chain-ids] :or {content-container-style {:padding-horizontal 8}}}] - (let [filtered-tokens (rf/sub [:wallet/current-viewing-account-tokens-filtered - {:query search-text - :chain-ids chain-ids}]) - currency (rf/sub [:profile/currency]) - currency-symbol (rf/sub [:profile/currency-symbol])] + (let [filtered-tokens (rf/sub [:wallet/current-viewing-account-tokens-filtered + {:query search-text + :chain-ids chain-ids}]) + currency (rf/sub [:profile/currency]) + currency-symbol (rf/sub [:profile/currency-symbol]) + prices-per-token (rf/sub [:wallet/prices-per-token])] [gesture/flat-list {:data filtered-tokens :render-data {:currency currency :currency-symbol currency-symbol :on-token-press on-token-press - :preselected-token-symbol preselected-token-symbol} + :preselected-token-symbol preselected-token-symbol + :prices-per-token prices-per-token} :style {:flex 1} :content-container-style content-container-style :keyboard-should-persist-taps :handled diff --git a/src/status_im/contexts/wallet/common/utils.cljs b/src/status_im/contexts/wallet/common/utils.cljs index e4e856cf77..2eaedf6094 100644 --- a/src/status_im/contexts/wallet/common/utils.cljs +++ b/src/status_im/contexts/wallet/common/utils.cljs @@ -27,12 +27,18 @@ [balance] (cut-fiat-balance balance 2)) -(defn prettify-balance - [currency-symbol balance] +(defn prepend-curency-symbol-to-fiat-balance + [fiat-balance currency-symbol] (let [formatted-symbol (if (> (count currency-symbol) 1) (str currency-symbol " ") currency-symbol)] - (str formatted-symbol (cut-fiat-balance-to-two-decimals balance)))) + (str formatted-symbol fiat-balance))) + +(defn prettify-balance + [currency-symbol fiat-balance] + (-> fiat-balance + cut-fiat-balance-to-two-decimals + (prepend-curency-symbol-to-fiat-balance currency-symbol))) (defn get-derivation-path [number-of-accounts] @@ -71,9 +77,14 @@ (inc max-decimals) max-decimals))) +(defn token-price-by-symbol + "Get token price for specific currency from prices-per-token structure" + [prices-per-token token-symbol currency] + (get-in prices-per-token [(keyword token-symbol) currency])) + (defn token-usd-price - [token] - (get-in token [:market-values-per-currency :usd :price])) + [token prices-per-token] + (token-price-by-symbol prices-per-token (:symbol token) :usd)) (defn one-cent-value [token-price-in-usd] @@ -104,16 +115,20 @@ :else (number/remove-trailing-zeroes (.toFixed token-units standardized-decimals-count))))) +(defn add-token-symbol-to-crypto-balance + [crypto-balance token-symbol] + (str crypto-balance " " (string/upper-case token-symbol))) + (defn prettify-crypto-balance [token-symbol crypto-balance conversion-rate] - (str (cut-crypto-decimals-to-fit-usd-cents crypto-balance conversion-rate) - " " - (string/upper-case token-symbol))) + (-> crypto-balance + (cut-crypto-decimals-to-fit-usd-cents conversion-rate) + (add-token-symbol-to-crypto-balance token-symbol))) (defn get-standard-crypto-format "For full details: https://github.com/status-im/status-mobile/issues/18225" - [token token-units] - (let [token-price-in-usd (token-usd-price token) + [token token-units prices-per-token] + (let [token-price-in-usd (token-usd-price token prices-per-token) {:keys [zero-value? usd-cent-value standardized-decimals-count]} (analyze-token-amount-for-price token-price-in-usd token-units)] (cond @@ -127,11 +142,9 @@ (number/remove-trailing-zeroes (.toFixed token-units standardized-decimals-count))))) (defn get-market-value - [currency {:keys [market-values-per-currency]}] - (or (get-in market-values-per-currency - [currency :price]) - (get-in market-values-per-currency - [constants/profile-default-currency :price]) + [currency {token-symbol :symbol} prices-per-token] + (or (token-price-by-symbol prices-per-token token-symbol currency) + (token-price-by-symbol prices-per-token token-symbol constants/profile-default-currency) ;; NOTE: adding fallback value (zero) in case prices are ;; unavailable and to prevent crash on calculating fiat value 0)) @@ -161,15 +174,15 @@ (defn calculate-token-fiat-value "Returns the token fiat value for provided raw balance" - [{:keys [currency balance token]}] - (let [price (get-market-value currency token)] + [{:keys [currency balance token prices-per-token]}] + (let [price (get-market-value currency token prices-per-token)] (money/crypto->fiat balance price))) (defn formatted-token-fiat-value "Converts a token balance into its equivalent fiat value, formatted with a currency symbol. If the fiat value is below $0.01, it returns a <$0.01 string" - [{:keys [currency currency-symbol balance token]}] - (let [price (or (get-market-value currency token) 0) + [{:keys [currency currency-symbol balance token prices-per-token]}] + (let [price (or (get-market-value currency token prices-per-token) 0) price-zero? (zero? price) balance (or balance 0) balance-positive? (pos? balance) @@ -204,12 +217,13 @@ (sanitized-token-amount-to-display display-decimals)))) (defn calculate-balance-from-tokens - [{:keys [currency tokens chain-ids]}] + [{:keys [currency tokens chain-ids prices-per-token]}] (->> tokens (map #(calculate-token-fiat-value - {:currency currency - :balance (calculate-total-token-balance % chain-ids) - :token %})) + {:currency currency + :balance (calculate-total-token-balance % chain-ids) + :token % + :prices-per-token prices-per-token})) (reduce money/add))) (defn- add-balances-per-chain @@ -266,30 +280,30 @@ (defn calculate-token-value "This function returns token values in the props of token-value (quo) component" - [{:keys [token color currency currency-symbol]}] - (let [balance (calculate-total-token-balance token) - fiat-unformatted-value (calculate-token-fiat-value - {:currency currency - :balance balance - :token token}) - market-values (or (get-in token [:market-values-per-currency currency]) - (get-in token - [:market-values-per-currency - constants/profile-default-currency])) - {:keys [price change-pct-24hour]} market-values - formatted-token-price (prettify-balance currency-symbol price) - percentage-change (prettify-percentage-change change-pct-24hour) - crypto-value (get-standard-crypto-format token balance) - fiat-value (fiat-formatted-for-ui currency-symbol - fiat-unformatted-value)] + [{:keys [token color currency currency-symbol prices-per-token market-values-per-token]}] + (let [balance (calculate-total-token-balance token) + fiat-unformatted-value (calculate-token-fiat-value + {:currency currency + :balance balance + :token token + :prices-per-token prices-per-token}) + currency (or currency constants/profile-default-currency) + market-values (get market-values-per-token (keyword (:symbol token))) + {:keys [change-pct-24h]} market-values + price (token-price-by-symbol prices-per-token (:symbol token) currency) + formatted-token-price (prettify-balance currency-symbol price) + percentage-change (prettify-percentage-change change-pct-24h) + crypto-value (get-standard-crypto-format token balance prices-per-token) + fiat-value (fiat-formatted-for-ui currency-symbol + fiat-unformatted-value)] {:token (:symbol token) :token-name (:name token) :state :default :metrics? (money/above-zero? balance) :status (cond - (pos? change-pct-24hour) :positive - (neg? change-pct-24hour) :negative - :else :empty) + (pos? change-pct-24h) :positive + (neg? change-pct-24h) :negative + :else :empty) :customization-color color :values {:crypto-value crypto-value :fiat-value fiat-value @@ -335,10 +349,10 @@ (map #(update % :balances-per-chain select-keys chain-ids) tokens)) (defn calculate-balances-per-chain - [{:keys [tokens currency currency-symbol]}] + [{:keys [tokens currency currency-symbol prices-per-token]}] (-> (reduce (fn [acc {:keys [balances-per-chain decimals] :as token}] - (let [currency-value (get-market-value currency token) + (let [currency-value (get-market-value currency token prices-per-token) fiat-balance-per-chain (update-vals balances-per-chain #(-> (money/token->unit (:raw-balance %) decimals) @@ -379,12 +393,14 @@ (utils.string/contains-special-character? s) :special-character)) (defn calculate-and-sort-tokens - [{:keys [tokens color currency currency-symbol]}] + [{:keys [tokens color currency currency-symbol prices-per-token market-values-per-token]}] (let [calculate-token (fn [token] - (calculate-token-value {:token token - :color color - :currency currency - :currency-symbol currency-symbol})) + (calculate-token-value {:token token + :color color + :currency currency + :currency-symbol currency-symbol + :prices-per-token prices-per-token + :market-values-per-token market-values-per-token})) calculated-tokens (map calculate-token tokens)] (sort-by (fn [token] (let [fiat-value (get-in token [:values :fiat-unformatted-value]) diff --git a/src/status_im/contexts/wallet/common/utils_test.cljs b/src/status_im/contexts/wallet/common/utils_test.cljs index f5c866b532..247348ca65 100644 --- a/src/status_im/contexts/wallet/common/utils_test.cljs +++ b/src/status_im/contexts/wallet/common/utils_test.cljs @@ -59,25 +59,33 @@ (deftest get-standard-crypto-format-test (testing "get-standard-crypto-format function" - (let [market-values-per-currency {:usd {:price 100}} - token-units (money/bignumber 0.005)] - (is (= (utils/get-standard-crypto-format {:market-values-per-currency market-values-per-currency} - token-units) + (let [token {:symbol "ETH"} + prices-per-token {:ETH {:usd 100}} + token-units (money/bignumber 0.005)] + (is (= (utils/get-standard-crypto-format token + token-units + prices-per-token) "0.005"))) - (let [market-values-per-currency {:usd {:price nil}} - token-units (money/bignumber 0.0123456)] - (is (= (utils/get-standard-crypto-format {:market-values-per-currency market-values-per-currency} - token-units) + (let [token {:symbol "ETH"} + prices-per-token {:ETH {:usd nil}} + token-units (money/bignumber 0.0123456)] + (is (= (utils/get-standard-crypto-format token + token-units + prices-per-token) "0.012346"))) - (let [market-values-per-currency {:usd {:price 0.005}} - token-units (money/bignumber 0.01)] - (is (= (utils/get-standard-crypto-format {:market-values-per-currency market-values-per-currency} - token-units) + (let [token {:symbol "ETH"} + prices-per-token {:ETH {:usd 0.005}} + token-units (money/bignumber 0.01)] + (is (= (utils/get-standard-crypto-format token + token-units + prices-per-token) "<2"))) - (let [market-values-per-currency {:usd {:price 0.005}} - token-units "0.01"] - (is (= (utils/get-standard-crypto-format {:market-values-per-currency market-values-per-currency} - token-units) + (let [token {:symbol "ETH"} + prices-per-token {:ETH {:usd 0.005}} + token-units "0.01"] + (is (= (utils/get-standard-crypto-format token + token-units + prices-per-token) "0"))))) (deftest calculate-total-token-balance-test @@ -151,10 +159,12 @@ :name "Status Network Token" :balances-per-chain {:mock-chain 1} :decimals 18}] - mock-input {:tokens mock-tokens - :color mock-color - :currency mock-currency - :currency-symbol mock-currency-symbol} + mock-input {:tokens mock-tokens + :color mock-color + :currency mock-currency + :currency-symbol mock-currency-symbol + :prices-per-token {} + :market-values-per-token {}} sorted-tokens (map :token (utils/calculate-and-sort-tokens mock-input)) expected-order ["DAI" "ETH" "SNT"]] (is (= expected-order sorted-tokens)))))))) @@ -170,19 +180,20 @@ (deftest formatted-token-fiat-value-test (testing "formatted-token-fiat-value function" - (let [default-params {:currency "USD" - :currency-symbol "$" - :balance 0.5 - :token {:market-values-per-currency {:usd {:price 2000}}}}] + (let [default-params {:currency "USD" + :currency-symbol "$" + :balance 0.5 + :token {:symbol "ETH"} + :prices-per-token {:ETH {:usd 2000}}}] (is (= (utils/formatted-token-fiat-value default-params) "$1000")) (is (= (utils/formatted-token-fiat-value (assoc default-params :balance 0)) "$0")) (is (= (utils/formatted-token-fiat-value (assoc default-params :balance 0.000001)) "<$0.01")) (is (= (utils/formatted-token-fiat-value (assoc default-params :balance nil)) "$0")) (is (= (utils/formatted-token-fiat-value - (assoc default-params :balance 1 :token {:market-values-per-currency {:usd {:price nil}}})) + (assoc default-params :balance 1 :prices-per-token {:ETH {:usd nil}})) "$0")) (is (= (utils/formatted-token-fiat-value - (assoc default-params :balance 1 :token {:market-values-per-currency {:usd {:price 0}}})) + (assoc default-params :balance 1 :prices-per-token {:ETH {:usd 0}})) "$0"))))) (deftest sanitized-token-amount-to-display-test diff --git a/src/status_im/contexts/wallet/events.cljs b/src/status_im/contexts/wallet/events.cljs index 197e119c0d..53a93bc649 100644 --- a/src/status_im/contexts/wallet/events.cljs +++ b/src/status_im/contexts/wallet/events.cljs @@ -213,7 +213,7 @@ (fn [{:keys [db]} [address]] {:db (assoc-in db [:wallet :ui :tokens-loading address] true) :fx [[:json-rpc/call - [{:method "wallet_getWalletToken" + [{:method "wallet_fetchOrGetCachedWalletBalances" :params [[address]] :on-success [:wallet/store-wallet-token address] :on-error [:wallet/get-wallet-token-for-account-failed address]}]]]})) @@ -232,6 +232,7 @@ :wallet/store-wallet-token (fn [{:keys [db]} [address raw-tokens-data]] (let [supported-chains-by-token-symbol (get-in db [:wallet :tokens :supported-chains-by-symbol]) + profile-currency (get-in db [:profile/profile :currency]) tokens (data-store/rpc->tokens raw-tokens-data supported-chains-by-token-symbol) add-tokens (fn [stored-accounts tokens-per-account] @@ -241,11 +242,25 @@ (update accounts address assoc :tokens tokens-data) accounts)) stored-accounts - tokens-per-account))] - {:fx [[:dispatch [:wallet/get-last-wallet-token-update-if-needed]]] - :db (-> db + tokens-per-account)) + symbols (reduce-kv (fn [acc _ v] + (into acc (map :symbol v))) + #{} + tokens)] + {:db (-> db (update-in [:wallet :accounts] add-tokens tokens) - (assoc-in [:wallet :ui :tokens-loading address] false))}))) + (assoc-in [:wallet :ui :tokens-loading address] false)) + :fx [[:dispatch [:wallet/get-last-wallet-token-update-if-needed]] + [:effects.wallet.tokens/fetch-market-values + {:symbols symbols + :currency profile-currency + :on-success [:wallet.tokens/store-market-values] + :on-error [:wallet.tokens/fetch-market-values-failed]}] + [:effects.wallet.tokens/fetch-prices + {:symbols symbols + :currencies [constants/profile-default-currency profile-currency] + :on-success [:wallet.tokens/store-prices] + :on-error [:wallet.tokens/fetch-prices-failed]}]]}))) (rf/reg-event-fx :wallet/get-last-wallet-token-update-if-needed diff --git a/src/status_im/contexts/wallet/events_test.cljs b/src/status_im/contexts/wallet/events_test.cljs index b1f0a702aa..cb4d6fb6e0 100644 --- a/src/status_im/contexts/wallet/events_test.cljs +++ b/src/status_im/contexts/wallet/events_test.cljs @@ -124,7 +124,7 @@ [event-id dispatch] (let [expected-effects {:db {:wallet {:ui {:tokens-loading {address true}}}} :fx [[:json-rpc/call - [{:method "wallet_getWalletToken" + [{:method "wallet_fetchOrGetCachedWalletBalances" :params [[address]] :on-success [:wallet/store-wallet-token address] :on-error [:wallet/get-wallet-token-for-account-failed diff --git a/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs b/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs index 798b9a41bf..397f79cfc9 100644 --- a/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs +++ b/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs @@ -43,23 +43,22 @@ :removed false} :wallet/current-viewing-account-color :purple :wallet/wallet-send-enough-assets? true - :wallet/wallet-send-token {:symbol :eth - :networks [{:source 879 - :short-name "eth" - :network-name :mainnet - :abbreviated-name - "Eth." - :full-name "Mainnet" - :chain-id 1 - :related-chain-id 1 - :layer 1}] - :balances-per-chain {1 {:raw-balance - (money/bignumber - "2500") - :has-error false}} - :total-balance 100 - :available-balance 100 - :market-values-per-currency {:usd {:price 10}}} + :wallet/wallet-send-token {:symbol "ETH" + :networks [{:source 879 + :short-name "eth" + :network-name :mainnet + :abbreviated-name + "Eth." + :full-name "Mainnet" + :chain-id 1 + :related-chain-id 1 + :layer 1}] + :balances-per-chain {1 {:raw-balance + (money/bignumber + "2500") + :has-error false}} + :total-balance 100 + :available-balance 100} :wallet/wallet-send-loading-suggested-routes? false :wallet/wallet-send-route [{:from {:chainid 1 :native-currency-symbol "ETH"} @@ -75,14 +74,13 @@ :wallet/wallet-send-to-address "0x04371e2d9d66b82f056bc128064" :profile/currency-symbol "$" :profile/currency :usd - :wallet/token-by-symbol {:symbol :eth - :total-balance 100 - :available-balance 100 - :balances-per-chain {1 {:raw-balance - (money/bignumber - "2500") - :has-error false}} - :market-values-per-currency {:usd {:price 10}}} + :wallet/token-by-symbol {:symbol "ETH" + :total-balance 100 + :available-balance 100 + :balances-per-chain {1 {:raw-balance + (money/bignumber + "2500") + :has-error false}}} :wallet/wallet-send-disabled-from-chain-ids [] :wallet/wallet-send-from-locked-amounts {} :wallet/wallet-send-from-values-by-chain {1 (money/bignumber "250")} @@ -106,6 +104,7 @@ :wallet/sending-collectible? false :wallet/send-total-amount-formatted "250 ETH" :wallet/total-amount (money/bignumber "250") + :wallet/prices-per-token {:ETH {:usd 10}} :wallet/bridge-to-network-details nil :wallet/send-amount-fixed "" :wallet/send-display-token-decimals 5}) diff --git a/src/status_im/contexts/wallet/send/input_amount/view.cljs b/src/status_im/contexts/wallet/send/input_amount/view.cljs index 276450dd27..a8d2966752 100644 --- a/src/status_im/contexts/wallet/send/input_amount/view.cljs +++ b/src/status_im/contexts/wallet/send/input_amount/view.cljs @@ -164,13 +164,14 @@ (str token-symbol) enabled-from-chain-ids]) token-balance (or default-limit-crypto total-balance) - usd-conversion-rate (utils/token-usd-price token) + prices-per-token (rf/sub [:wallet/prices-per-token]) + usd-conversion-rate (utils/token-usd-price token prices-per-token) currency (rf/sub [:profile/currency]) - conversion-rate (-> token - :market-values-per-currency - currency - :price) token-decimals (rf/sub [:wallet/send-display-token-decimals]) + + conversion-rate (utils/token-price-by-symbol prices-per-token + token-symbol + currency) [input-state set-input-state] (rn/use-state controlled-input/init-state) clear-input! #(set-input-state controlled-input/delete-all) currency-symbol (rf/sub [:profile/currency-symbol]) diff --git a/src/status_im/contexts/wallet/send/routes/view.cljs b/src/status_im/contexts/wallet/send/routes/view.cljs index 3994d3cba1..45b777e261 100644 --- a/src/status_im/contexts/wallet/send/routes/view.cljs +++ b/src/status_im/contexts/wallet/send/routes/view.cljs @@ -80,165 +80,6 @@ (rf/dispatch [:wallet/update-receiver-networks chain-ids]))}]))}])) -#_(defn- edit-amount - [{:keys [chain-id token-symbol send-amount-in-crypto init-amount]}] - (rf/dispatch - [:show-bottom-sheet - {:content - (fn [] - (let [{:keys [network-name] :as network-details} (rf/sub [:wallet/network-details-by-chain-id - chain-id]) - {fiat-currency :currency} (rf/sub [:profile/profile]) - {token-decimals :decimals - :as - token} (rf/sub [:wallet/wallet-send-token]) - currency (rf/sub [:profile/currency]) - currency-symbol (rf/sub [:profile/currency-symbol]) - send-from-locked-amounts (rf/sub - [:wallet/wallet-send-from-locked-amounts]) - {account-color :color} (rf/sub [:wallet/current-viewing-account]) - locked-amount (get send-from-locked-amounts chain-id) - network-name-str (string/capitalize (name network-name)) - [input-state set-input-state] (rn/use-state - (cond-> controlled-input/init-state - init-amount - (controlled-input/set-input-value - (money/to-string init-amount)) - locked-amount - (controlled-input/set-input-value - locked-amount))) - [crypto-currency? set-crypto-currency] (rn/use-state true) - conversion-rate (-> token - :market-values-per-currency - currency - :price) - {token-balance :total-balance} (rf/sub [:wallet/token-by-symbol - (str token-symbol) - [chain-id]]) - current-crypto-limit (utils/get-standard-crypto-format - token - token-balance) - current-fiat-limit (.toFixed (* token-balance conversion-rate) 2) - current-limit (if crypto-currency? - current-crypto-limit - current-fiat-limit) - crypto-decimals token-decimals - input-amount (controlled-input/input-value input-state) - [is-amount-locked? set-is-amount-locked] (rn/use-state (some? locked-amount)) - bottom (safe-area/get-bottom) - amount-in-crypto (if crypto-currency? - input-amount - (number/remove-trailing-zeroes - (.toFixed (/ input-amount - conversion-rate) - crypto-decimals))) - locked-greater-then-send-amount? (let [amount (money/bignumber - amount-in-crypto) - send-amount (money/bignumber - send-amount-in-crypto)] - (and (money/bignumber? amount) - (money/bignumber? send-amount) - (money/greater-than amount - send-amount))) - swap-between-fiat-and-crypto (fn [swap-to-crypto-currency?] - (set-crypto-currency - swap-to-crypto-currency?) - (set-input-state - (fn [input-state] - (controlled-input/set-input-value - input-state - (let [value (controlled-input/input-value - input-state) - new-value - (if - swap-to-crypto-currency? - (.toFixed - (/ value - conversion-rate) - crypto-decimals) - (.toFixed - (* value - conversion-rate) - 12))] - (number/remove-trailing-zeroes - new-value)))))) - lock-or-unlock-amount (fn [] - (if is-amount-locked? - (rf/dispatch [:wallet/lock-from-amount - chain-id - amount-in-crypto]) - (rf/dispatch [:wallet/unlock-from-amount - chain-id])) - (rf/dispatch [:hide-bottom-sheet]))] - (rn/use-effect - (fn [] - (set-input-state #(controlled-input/set-upper-limit % current-limit))) - [current-limit]) - [:<> - [quo/drawer-top - {:title (i18n/label :t/send-from-network {:network network-name-str}) - :description (i18n/label :t/define-amount-sent-from-network {:network network-name-str})}] - [quo/token-input - {:container-style style/input-container - :token token-symbol - :currency fiat-currency - :currency-symbol currency-symbol - :crypto-decimals (min token-decimals 6) - :error? (controlled-input/input-error input-state) - :networks [network-details] - :title (i18n/label - :t/send-limit - {:limit (if crypto-currency? - (utils/make-limit-label-crypto current-limit token-symbol) - (utils/make-limit-label-fiat current-limit currency-symbol))}) - :conversion conversion-rate - :show-keyboard? false - :value (controlled-input/input-value input-state) - :on-swap swap-between-fiat-and-crypto - :allow-selection? false}] - (when locked-greater-then-send-amount? - [quo/information-box - {:type :error - :icon :i/info - :style style/error-box} - (i18n/label :t/value-higher-than-send-amount)]) - [quo/disclaimer - {:on-change (fn [checked?] - (set-is-amount-locked checked?)) - :checked? is-amount-locked? - :container-style style/disclaimer - :icon (if is-amount-locked? - :i/locked - :i/unlocked) - :customization-color account-color} - (i18n/label :t/dont-auto-recalculate-network {:network network-name-str})] - [quo/bottom-actions - {:actions :one-action - :button-one-label (i18n/label :t/update) - :button-one-props {:on-press lock-or-unlock-amount - :customization-color account-color - :disabled? (or (controlled-input/empty-value? input-state) - (controlled-input/input-error input-state) - locked-greater-then-send-amount?)}}] - [quo/numbered-keyboard - {:container-style (style/keyboard-container bottom) - :left-action :dot - :delete-key? true - :on-press (fn [c] - (let [new-text (str input-amount c) - max-decimals (if crypto-currency? crypto-decimals 2) - regex-pattern (str "^\\d*\\.?\\d{0," max-decimals "}$") - regex (re-pattern regex-pattern)] - (when (re-matches regex new-text) - (set-is-amount-locked true) - (set-input-state #(controlled-input/add-character % c))))) - :on-delete (fn [] - (set-is-amount-locked true) - (set-input-state controlled-input/delete-last)) - :on-long-press-delete (fn [] - (set-is-amount-locked true) - (set-input-state controlled-input/delete-all))}]]))}])) - (defn render-network-values [{:keys [network-values token-symbol on-press on-long-press receiver? loading-routes? token-not-supported-in-receiver-networks?]}] diff --git a/src/status_im/contexts/wallet/sheets/select_asset/asset_list/view.cljs b/src/status_im/contexts/wallet/sheets/select_asset/asset_list/view.cljs index ec3b2e0308..0f2f47d469 100644 --- a/src/status_im/contexts/wallet/sheets/select_asset/asset_list/view.cljs +++ b/src/status_im/contexts/wallet/sheets/select_asset/asset_list/view.cljs @@ -15,11 +15,13 @@ bridge-disabled? :bridge-disabled? :as token} {:keys [currency currency-symbol on-token-press disable-token-fn preselected-token-symbol]}] - (let [fiat-value (utils/calculate-token-fiat-value - {:currency currency - :balance total-balance - :token token}) - crypto-formatted (utils/get-standard-crypto-format token total-balance) + (let [prices-per-token (rf/sub [:wallet/prices-per-token]) + fiat-value (utils/calculate-token-fiat-value + {:currency currency + :balance total-balance + :token token + :prices-per-token prices-per-token}) + crypto-formatted (utils/get-standard-crypto-format token total-balance prices-per-token) fiat-formatted (utils/fiat-formatted-for-ui currency-symbol fiat-value)] [rn/view {:style {:padding-horizontal 8}} [quo/token-network diff --git a/src/status_im/contexts/wallet/swap/setup_swap/view.cljs b/src/status_im/contexts/wallet/swap/setup_swap/view.cljs index f9ffd1fd42..c36c54ede1 100644 --- a/src/status_im/contexts/wallet/swap/setup_swap/view.cljs +++ b/src/status_im/contexts/wallet/swap/setup_swap/view.cljs @@ -216,6 +216,7 @@ currency-symbol (rf/sub [:profile/currency-symbol]) amount-out (rf/sub [:wallet/swap-proposal-amount-out]) approval-required? (rf/sub [:wallet/swap-proposal-approval-required]) + prices-per-token (rf/sub [:wallet/prices-per-token]) receive-token-symbol (:symbol asset-to-receive) receive-token-decimals (:decimals asset-to-receive) amount-out-whole-number (when amount-out @@ -224,10 +225,11 @@ (number/to-fixed amount-out-whole-number receive-token-decimals) default-text-for-unfocused-input) receive-token-fiat-value (utils/formatted-token-fiat-value - {:currency currency - :currency-symbol currency-symbol - :balance (or amount-out-whole-number 0) - :token asset-to-receive})] + {:currency currency + :currency-symbol currency-symbol + :balance (or amount-out-whole-number 0) + :token asset-to-receive + :prices-per-token prices-per-token})] [quo/swap-input {:type :receive :error? false diff --git a/src/status_im/contexts/wallet/tokens/events.cljs b/src/status_im/contexts/wallet/tokens/events.cljs index 4d0745888c..4ffd88cc33 100644 --- a/src/status_im/contexts/wallet/tokens/events.cljs +++ b/src/status_im/contexts/wallet/tokens/events.cljs @@ -21,6 +21,7 @@ (defn store-token-list [{:keys [db]} [{:keys [data]}]] (let [chain-ids (chain/chain-ids db) + profile-currency (get-in db [:profile/profile :currency]) tokens (reduce (fn [{:keys [by-address by-symbol] :as data} {:keys [name source version tokens]}] (-> data @@ -48,13 +49,11 @@ :by-address {} :by-symbol {}} data) - symbols (->> tokens - :by-symbol - vals - (map :symbol) - set - vec) by-symbol-vals (-> tokens :by-symbol vals) + symbols (reduce (fn [acc token] + (conj acc (:symbol token))) + #{} + by-symbol-vals) supported-chains-by-symbol (reduce (fn [result {token-symbol :symbol @@ -64,9 +63,10 @@ (assoc result token-symbol #{chain-id}))) {} by-symbol-vals)] + {:fx [[:effects.wallet.tokens/fetch-market-values {:symbols symbols - :currency constants/profile-default-currency + :currency profile-currency :on-success [:wallet.tokens/store-market-values] :on-error [:wallet.tokens/fetch-market-values-failed]}] [:effects.wallet.tokens/fetch-details @@ -75,7 +75,7 @@ :on-error [:wallet.tokens/fetch-details-failed]}] [:effects.wallet.tokens/fetch-prices {:symbols symbols - :currencies [constants/profile-default-currency] + :currencies [constants/profile-default-currency profile-currency] :on-success [:wallet.tokens/store-prices] :on-error [:wallet.tokens/fetch-prices-failed]}]] :db (-> db @@ -116,7 +116,7 @@ {} raw-data)] {:db (-> db - (assoc-in [:wallet :tokens :market-values-per-token] market-values) + (update-in [:wallet :tokens :market-values-per-token] merge market-values) (assoc-in [:wallet :ui :loading :market-values] false))}))) (rf/reg-event-fx @@ -146,7 +146,7 @@ :wallet.tokens/store-prices (fn [{:keys [db]} [prices]] {:db (-> db - (assoc-in [:wallet :tokens :prices-per-token] prices) + (update-in [:wallet :tokens :prices-per-token] merge prices) (assoc-in [:wallet :ui :loading :prices] false))})) (rf/reg-event-fx diff --git a/src/status_im/subs/wallet/dapps/transactions.cljs b/src/status_im/subs/wallet/dapps/transactions.cljs index e36d7f530c..27d8d3aaa2 100644 --- a/src/status_im/subs/wallet/dapps/transactions.cljs +++ b/src/status_im/subs/wallet/dapps/transactions.cljs @@ -52,12 +52,15 @@ :<- [:wallet-connect/account-eth-token] :<- [:profile/currency] :<- [:profile/currency-symbol] - (fn [[chain-id max-fees-wei transaction eth-token currency currency-symbol]] + :<- [:wallet/prices-per-token] + (fn [[chain-id max-fees-wei transaction eth-token currency currency-symbol prices-per-token]] (when transaction (let [max-fees-ether (money/wei->ether max-fees-wei) max-fees-fiat (wallet-utils/calculate-token-fiat-value {:currency currency - :balance max-fees-ether - :token eth-token}) + :balance max-fees-ether + :token eth-token + :prices-per-token + prices-per-token}) max-fees-fiat-formatted (wallet-utils/fiat-formatted-for-ui currency-symbol max-fees-fiat) balance (-> eth-token diff --git a/src/status_im/subs/wallet/send.cljs b/src/status_im/subs/wallet/send.cljs index 0458839c76..e413ab65de 100644 --- a/src/status_im/subs/wallet/send.cljs +++ b/src/status_im/subs/wallet/send.cljs @@ -114,11 +114,12 @@ (rf/reg-sub :wallet/send-display-token-decimals :<- [:wallet/wallet-send] - (fn [{:keys [token collectible]}] + :<- [:wallet/prices-per-token] + (fn [[{:keys [token collectible]} prices-per-token]] (if collectible 0 (-> token - common-utils/token-usd-price + (common-utils/token-usd-price prices-per-token) common-utils/one-cent-value common-utils/calc-max-crypto-decimals (min constants/min-token-decimals-to-display))))) diff --git a/src/status_im/subs/wallet/send_test.cljs b/src/status_im/subs/wallet/send_test.cljs index 99845bf1a4..a2e2504ce6 100644 --- a/src/status_im/subs/wallet/send_test.cljs +++ b/src/status_im/subs/wallet/send_test.cljs @@ -10,10 +10,9 @@ [utils.re-frame :as rf])) (def ^:private token-mock - {:decimals 8 - :symbol "ETH" - :balances-per-chain {1 {:raw-balance "100"}} - :market-values-per-currency {:usd {:price 10000}}}) + {:decimals 8 + :symbol "ETH" + :balances-per-chain {1 {:raw-balance "100"}}}) (h/deftest-sub :wallet/send-tab [sub-name] @@ -105,11 +104,14 @@ (h/deftest-sub :wallet/send-display-token-decimals [sub-name] (testing "returns the decimals based on the token price for the chosen token" - (swap! rf-db/app-db assoc-in - [:wallet :ui :send :token] - {:symbol "ETH" - :balances-per-chain {1 {:raw-balance "100"}} - :market-values-per-currency {:usd {:price 10000}}}) + (swap! rf-db/app-db + (fn [db] + (-> db + (assoc-in [:wallet :ui :send :token] + {:symbol "ETH" + :balances-per-chain {1 {:raw-balance "100"}}}) + (assoc-in [:wallet :tokens :prices-per-token] + {:ETH {:usd 10000}})))) (is (match? 6 (rf/sub [sub-name])))) (testing "returns 0 if sending collectibles" @@ -179,7 +181,9 @@ (assoc-in [:wallet :ui :send :token-display-name] "ETH") (assoc-in [:wallet :ui :send :route] [{:amount-out "0x2b139f68a611c00" ;; 193999990000000000 - :to {:chain-id 1}}])))) + :to {:chain-id 1}}]) + (assoc-in [:wallet :tokens :prices-per-token] + {:ETH {:usd 10000}})))) (is (match? "0.194 ETH" (rf/sub [sub-name]))))) (h/deftest-sub :wallet/send-amount-fixed diff --git a/src/status_im/subs/wallet/swap.cljs b/src/status_im/subs/wallet/swap.cljs index c040dcf909..f7f5f9066f 100644 --- a/src/status_im/subs/wallet/swap.cljs +++ b/src/status_im/subs/wallet/swap.cljs @@ -81,18 +81,19 @@ :<- [:profile/currency] :<- [:profile/currency-symbol] :<- [:wallet/swap-asset-to-pay-token-symbol] - (fn [[token currency currency-symbol token-symbol] [_ chain-id]] + :<- [:wallet/prices-per-token] + (fn [[token currency currency-symbol token-symbol prices-per-token] [_ chain-id]] (let [{:keys [balances-per-chain decimals]} token balance-for-chain (get balances-per-chain chain-id) total-balance (money/token->unit (:raw-balance balance-for-chain) decimals) fiat-value (utils/calculate-token-fiat-value - {:currency currency - :balance total-balance - :token token}) - crypto-formatted (utils/get-standard-crypto-format token total-balance) - fiat-formatted (utils/fiat-formatted-for-ui currency-symbol - fiat-value)] + {:currency currency + :balance total-balance + :token token + :prices-per-token prices-per-token}) + crypto-formatted (utils/get-standard-crypto-format token total-balance prices-per-token) + fiat-formatted (utils/fiat-formatted-for-ui currency-symbol fiat-value)] {:crypto (str crypto-formatted " " token-symbol) :fiat fiat-formatted}))) @@ -248,7 +249,8 @@ :<- [:wallet/current-viewing-account] :<- [:wallet/swap-proposal] :<- [:profile/currency] - (fn [[account swap-proposal currency] [_ token-symbol-for-fees]] + :<- [:wallet/prices-per-token] + (fn [[account swap-proposal currency prices-per-token] [_ token-symbol-for-fees]] (when token-symbol-for-fees (let [tokens (:tokens account) token-for-fees (first (filter #(= (string/lower-case (:symbol %)) @@ -256,9 +258,10 @@ tokens)) fee-in-native-token (send-utils/calculate-full-route-gas-fee [swap-proposal]) fee-in-fiat (utils/calculate-token-fiat-value - {:currency currency - :balance fee-in-native-token - :token token-for-fees})] + {:currency currency + :balance fee-in-native-token + :token token-for-fees + :prices-per-token prices-per-token})] fee-in-fiat)))) (rf/reg-sub @@ -291,29 +294,33 @@ (rf/reg-sub :wallet/swap-asset-to-pay-amount-in-fiat :<- [:wallet/swap-asset-to-pay-balance-for-chain-data] + :<- [:wallet/prices-per-token] :<- [:profile/currency] :<- [:profile/currency-symbol] - (fn [[asset-to-pay-with-current-account-balance currency currency-symbol] [_ amount]] + (fn [[asset-to-pay-with-current-account-balance prices-per-token currency currency-symbol] [_ amount]] (utils/formatted-token-fiat-value - {:currency currency - :currency-symbol currency-symbol - :balance (or amount 0) - :token asset-to-pay-with-current-account-balance}))) + {:currency currency + :currency-symbol currency-symbol + :balance (or amount 0) + :token asset-to-pay-with-current-account-balance + :prices-per-token prices-per-token}))) (rf/reg-sub :wallet/approval-gas-fees :<- [:wallet/current-viewing-account] :<- [:wallet/swap-proposal] :<- [:profile/currency] - (fn [[account {:keys [approval-gas-fees]} currency]] + :<- [:wallet/prices-per-token] + (fn [[account {:keys [approval-gas-fees]} currency prices-per-token]] (let [tokens (:tokens account) token-for-fees (first (filter #(= (string/lower-case (:symbol %)) (string/lower-case constants/token-for-fees-symbol)) tokens)) fee-in-fiat (utils/calculate-token-fiat-value - {:currency currency - :balance approval-gas-fees - :token token-for-fees})] + {:currency currency + :balance approval-gas-fees + :token token-for-fees + :prices-per-token prices-per-token})] fee-in-fiat))) (rf/reg-sub diff --git a/src/status_im/subs/wallet/swap_test.cljs b/src/status_im/subs/wallet/swap_test.cljs index 779d8c56a1..717372966e 100644 --- a/src/status_im/subs/wallet/swap_test.cljs +++ b/src/status_im/subs/wallet/swap_test.cljs @@ -16,21 +16,26 @@ :popular? true :token? false}}) +(def ^:private prices-per-token-high + {:ETH {:usd 10000} + :SNT {:usd 10000}}) + +(def ^:private prices-per-token-low + {:DAI {:usd 0.0251} + :SNT {:usd 0.0251}}) + (def ^:private accounts-with-tokens - {:0x1 {:tokens [{:symbol "ETH" - :balances-per-chain {1 {:raw-balance "100"}} - :market-values-per-currency {:usd {:price 10000}}} - {:symbol "SNT" - :balances-per-chain {1 {:raw-balance "100"}} - :market-values-per-currency {:usd {:price 10000}}}] + {:0x1 {:tokens [{:symbol "ETH" + :balances-per-chain {1 {:raw-balance "100"}}} + {:symbol "SNT" + :balances-per-chain {1 {:raw-balance "100"}}}] :network-preferences-names #{} :customization-color nil :operable? true :operable :fully :address "0x1"} - :0x2 {:tokens [{:symbol "SNT" - :balances-per-chain {1 {:raw-balance "200"}} - :market-values-per-currency {:usd {:price 10000}}}] + :0x2 {:tokens [{:symbol "SNT" + :balances-per-chain {1 {:raw-balance "200"}}}] :network-preferences-names #{} :customization-color nil :operable? true @@ -78,17 +83,6 @@ :chain-id 42161}} :networks (concat [(networks :mainnet-network)] (networks :layer-2-networks)) :chain-id 0 - :market-values-per-currency - {:usd - {:change-24hour -0.00109422754667007 - :change-pct-day -5.57352274163899 - :change-pct-24hour -4.177805426737527 - :high-day 0.0271858672171352 - :market-cap 170783296.1155821 - :has-error false - :change-pct-hour -0.0160462113709363 - :low-day 0.02473516779550377 - :price 0.0251}} :asset-website-url "https://status.im/" :available-balance 1 :token-list-id "" @@ -115,17 +109,6 @@ :chain-id 42161}} :networks (concat [(networks :mainnet-network)] (networks :layer-2-networks)) :chain-id 0 - :market-values-per-currency - {:usd - {:change-24hour -0.00109422754667007 - :change-pct-day -5.57352274163899 - :change-pct-24hour -4.177805426737527 - :high-day 0.0271858672171352 - :market-cap 170783296.1155821 - :has-error false - :change-pct-hour -0.0160462113709363 - :low-day 0.02473516779550377 - :price 0.0251}} :asset-website-url "https://status.im/" :available-balance 1 :token-list-id "" @@ -190,7 +173,8 @@ (swap! rf-db/app-db #(-> % (assoc :currencies currencies) - (assoc-in [:wallet :ui :swap] swap-data))) + (assoc-in [:wallet :ui :swap] swap-data) + (assoc-in [:wallet :tokens :prices-per-token] prices-per-token-low))) (is (match? {:crypto "1 SNT" :fiat "$0.03"} (rf/sub [sub-name 1]))))) (h/deftest-sub :wallet/swap-network @@ -266,8 +250,9 @@ (assoc-in [:wallet :current-viewing-account-address] "0x1") (assoc-in [:wallet :ui :swap] swap-data) (assoc-in [:currencies] currencies) - (assoc-in [:profile/profile :currency] :usd))) - + (assoc-in [:profile/profile :currency] :usd) + (assoc-in [:profile/profile :currency-symbol] "$") + (assoc-in [:wallet :tokens :prices-per-token] prices-per-token-high))) (let [token-symbol-for-fees "ETH" result (rf/sub [sub-name token-symbol-for-fees])] (is (match? result 1))))) diff --git a/src/status_im/subs/wallet/wallet.cljs b/src/status_im/subs/wallet/wallet.cljs index 40265a5a1f..da4cac87ea 100644 --- a/src/status_im/subs/wallet/wallet.cljs +++ b/src/status_im/subs/wallet/wallet.cljs @@ -72,6 +72,16 @@ :<- [:wallet] :-> :tokens) +(rf/reg-sub + :wallet/prices-per-token + :<- [:wallet/tokens] + :-> :prices-per-token) + +(rf/reg-sub + :wallet/market-values-per-token + :<- [:wallet/tokens] + :-> :market-values-per-token) + (rf/reg-sub :wallet/tokens-loading :<- [:wallet/ui] @@ -376,11 +386,14 @@ :<- [:wallet/accounts] :<- [:profile/currency] :<- [:wallet/selected-networks->chain-ids] - (fn [[accounts currency chain-ids]] + :<- [:wallet/prices-per-token] + (fn [[accounts currency chain-ids prices-per-token]] (zipmap (map :address accounts) - (map #(utils/calculate-balance-from-tokens {:currency currency - :tokens (:tokens %) - :chain-ids chain-ids}) + (map (fn [account] + (utils/calculate-balance-from-tokens {:currency currency + :tokens (:tokens account) + :chain-ids chain-ids + :prices-per-token prices-per-token})) accounts)))) (rf/reg-sub @@ -503,22 +516,19 @@ sorted-tokens)) sorted-tokens)))) + (rf/reg-sub :wallet/tokens-filtered :<- [:wallet/tokens] - :<- [:profile/currency] - (fn [[{:keys [by-symbol market-values-per-token details-per-token prices-per-token]} currency] + (fn [{:keys [by-symbol market-values-per-token details-per-token]} [_ {:keys [query chain-ids hide-token-fn]}]] (let [tokens (->> by-symbol (map (fn [token] - (let [token-symbol (keyword (:symbol token)) - price (get-in prices-per-token [token-symbol currency])] + (let [token-symbol (keyword (:symbol token))] (-> token (assoc :market-values (get market-values-per-token token-symbol)) - (assoc :details (get details-per-token token-symbol)) - (assoc-in [:market-values-per-currency currency :price] - price))))) + (assoc :details (get details-per-token token-symbol)))))) (filter (fn [{:keys [chain-id]}] (some #{chain-id} chain-ids))) (remove #(when hide-token-fn @@ -645,11 +655,15 @@ :<- [:wallet/current-viewing-account-tokens-in-selected-networks] :<- [:profile/currency] :<- [:profile/currency-symbol] - (fn [[{:keys [color]} tokens currency currency-symbol]] - (utils/calculate-and-sort-tokens {:tokens tokens - :color color - :currency currency - :currency-symbol currency-symbol}))) + :<- [:wallet/prices-per-token] + :<- [:wallet/market-values-per-token] + (fn [[{:keys [color]} tokens currency currency-symbol prices-per-token market-values-per-token]] + (utils/calculate-and-sort-tokens {:tokens tokens + :color color + :currency currency + :currency-symbol currency-symbol + :prices-per-token prices-per-token + :market-values-per-token market-values-per-token}))) (rf/reg-sub :wallet/aggregated-token-values-and-balance @@ -657,19 +671,24 @@ :<- [:profile/customization-color] :<- [:profile/currency] :<- [:profile/currency-symbol] - (fn [[aggregated-tokens color currency currency-symbol]] - (let [balance (utils/calculate-balance-from-tokens {:currency currency - :tokens aggregated-tokens}) + :<- [:wallet/prices-per-token] + :<- [:wallet/market-values-per-token] + (fn [[aggregated-tokens color currency currency-symbol prices-per-token market-values-per-token]] + (let [balance (utils/calculate-balance-from-tokens {:currency currency + :tokens aggregated-tokens + :prices-per-token prices-per-token}) formatted-balance (utils/prettify-balance currency-symbol balance) - sorted-token-values (utils/calculate-and-sort-tokens {:tokens aggregated-tokens - :color color - :currency currency - :currency-symbol currency-symbol})] + sorted-token-values (utils/calculate-and-sort-tokens {:tokens aggregated-tokens + :color color + :currency currency + :currency-symbol currency-symbol + :prices-per-token prices-per-token + :market-values-per-token + market-values-per-token})] {:balance balance :formatted-balance formatted-balance :tokens sorted-token-values}))) - (rf/reg-sub :wallet/network-preference-details :<- [:wallet/current-viewing-account] @@ -742,22 +761,26 @@ :<- [:wallet/aggregated-tokens] :<- [:profile/currency] :<- [:profile/currency-symbol] - (fn [[aggregated-tokens currency currency-symbol]] + :<- [:wallet/prices-per-token] + (fn [[aggregated-tokens currency currency-symbol prices-per-token]] (utils/calculate-balances-per-chain - {:tokens aggregated-tokens - :currency currency - :currency-symbol currency-symbol}))) + {:tokens aggregated-tokens + :currency currency + :currency-symbol currency-symbol + :prices-per-token prices-per-token}))) (rf/reg-sub :wallet/current-viewing-account-fiat-balance-per-chain :<- [:wallet/current-viewing-account] :<- [:profile/currency] :<- [:profile/currency-symbol] - (fn [[{:keys [tokens]} currency currency-symbol]] + :<- [:wallet/prices-per-token] + (fn [[{:keys [tokens]} currency currency-symbol prices-per-token]] (utils/calculate-balances-per-chain - {:tokens tokens - :currency currency - :currency-symbol currency-symbol}))) + {:tokens tokens + :currency currency + :currency-symbol currency-symbol + :prices-per-token prices-per-token}))) (rf/reg-sub :wallet/import-private-key @@ -794,7 +817,8 @@ :<- [:wallet/wallet-send-route] :<- [:profile/currency] :<- [:profile/currency-symbol] - (fn [[account route currency currency-symbol] [_ token-symbol-for-fees]] + :<- [:wallet/prices-per-token] + (fn [[account route currency currency-symbol prices-per-token] [_ token-symbol-for-fees]] (when token-symbol-for-fees (let [tokens (:tokens account) token-for-fees (first (filter #(= (string/lower-case (:symbol %)) @@ -802,9 +826,10 @@ tokens)) fee-in-native-token (send-utils/calculate-full-route-gas-fee route) fee-in-fiat (utils/calculate-token-fiat-value - {:currency currency - :balance fee-in-native-token - :token token-for-fees}) + {:currency currency + :balance fee-in-native-token + :token token-for-fees + :prices-per-token prices-per-token}) fee-formatted (utils/fiat-formatted-for-ui currency-symbol fee-in-fiat)] diff --git a/src/status_im/subs/wallet/wallet_test.cljs b/src/status_im/subs/wallet/wallet_test.cljs index f511fc6426..97b34ea9d0 100644 --- a/src/status_im/subs/wallet/wallet_test.cljs +++ b/src/status_im/subs/wallet/wallet_test.cljs @@ -22,20 +22,17 @@ :token? false}}) (def ^:private accounts-with-tokens - {:0x1 {:tokens [{:symbol "ETH" - :balances-per-chain {1 {:raw-balance "100"}} - :market-values-per-currency {:usd {:price 10000}}} - {:symbol "SNT" - :balances-per-chain {1 {:raw-balance "100"}} - :market-values-per-currency {:usd {:price 10000}}}] + {:0x1 {:tokens [{:symbol "ETH" + :balances-per-chain {1 {:raw-balance "100"}}} + {:symbol "SNT" + :balances-per-chain {1 {:raw-balance "100"}}}] :network-preferences-names #{} :customization-color nil :operable? true :operable :fully :address "0x1"} - :0x2 {:tokens [{:symbol "SNT" - :balances-per-chain {1 {:raw-balance "200"}} - :market-values-per-currency {:usd {:price 10000}}}] + :0x2 {:tokens [{:symbol "SNT" + :balances-per-chain {1 {:raw-balance "200"}}}] :network-preferences-names #{} :customization-color nil :operable? true @@ -43,79 +40,73 @@ :address "0x2"}}) (def tokens-0x1 - [{:decimals 1 - :symbol "ETH" - :name "Ether" - :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber "20") - :has-error false} - constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber "10") - :has-error false}} - :market-values-per-currency {:usd {:price 1000}}} - {:decimals 2 - :symbol "DAI" - :name "Dai Stablecoin" - :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber - "100") - :has-error false} - constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber - "150") - :has-error false} - constants/arbitrum-mainnet-chain-id {:raw-balance nil :has-error false}} - :market-values-per-currency {:usd {:price 100}}}]) + [{:decimals 0 + :symbol "ETH" + :name "Ether" + :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber "2") + :has-error false} + constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber "1") + :has-error false}}} + {:decimals 0 + :symbol "DAI" + :name "Dai Stablecoin" + :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber + "1") + :has-error false} + constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber + "1.5") + :has-error false} + constants/arbitrum-mainnet-chain-id {:raw-balance nil :has-error false}}}]) (def tokens-0x2 - [{:decimals 3 - :symbol "ETH" - :name "Ether" - :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber - "2500") - :has-error false} - constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber - "3000") - :has-error false} - constants/arbitrum-mainnet-chain-id {:raw-balance (money/bignumber - "") - :has-error false}} - :market-values-per-currency {:usd {:price 200}}} - {:decimals 10 - :symbol "DAI" - :name "Dai Stablecoin" - :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber - "10000000000") - :has-error false} - constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber "0") - :has-error false} - constants/arbitrum-mainnet-chain-id {:raw-balance (money/bignumber - "") - :has-error false}} - :market-values-per-currency {:usd {:price 1000}}}]) + [{:decimals 0 + :symbol "ETH" + :name "Ether" + :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber + "2.5") + :has-error false} + constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber + "3") + :has-error false} + constants/arbitrum-mainnet-chain-id {:raw-balance (money/bignumber + "") + :has-error false}}} + {:decimals 0 + :symbol "DAI" + :name "Dai Stablecoin" + :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber + "1") + :has-error false} + constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber "0") + :has-error false} + constants/arbitrum-mainnet-chain-id {:raw-balance (money/bignumber + "") + :has-error false}}}]) (def tokens-0x3 - [{:decimals 3 - :symbol "ETH" - :name "Ether" - :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber - "5000") - :has-error false} - constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber - "2000") - :has-error false} - constants/arbitrum-mainnet-chain-id {:raw-balance (money/bignumber - "") - :has-error false}} - :market-values-per-currency {:usd {:price 200}}} - {:decimals 10 - :symbol "DAI" - :name "Dai Stablecoin" - :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber - "10000000000") - :has-error false} - constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber "0") - :has-error false} - constants/arbitrum-mainnet-chain-id {:raw-balance (money/bignumber - "") - :has-error false}} - :market-values-per-currency {:usd {:price 1000}}}]) + [{:decimals 0 + :symbol "ETH" + :name "Ether" + :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber + "5") + :has-error false} + constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber + "2") + :has-error false} + constants/arbitrum-mainnet-chain-id {:raw-balance (money/bignumber + "") + :has-error false}}} + {:decimals 0 + :symbol "DAI" + :name "Dai Stablecoin" + :balances-per-chain {constants/ethereum-mainnet-chain-id {:raw-balance (money/bignumber + "1") + :has-error false} + constants/optimism-mainnet-chain-id {:raw-balance (money/bignumber "0") + :has-error false} + constants/arbitrum-mainnet-chain-id {:raw-balance (money/bignumber + "") + :has-error false}}}]) (def accounts {"0x1" {:path "m/44'/60'/0'/0/0" @@ -223,11 +214,13 @@ (testing "a map: address->balance" (swap! rf-db/app-db #(-> % (assoc :wallet db/defaults) - (assoc-in [:wallet :accounts] accounts))) + (assoc-in [:wallet :accounts] accounts) + (assoc-in [:wallet :tokens :prices-per-token] + {:ETH {:usd 2000} :DAI {:usd 1}}))) (let [result (rf/sub [sub-name]) - balance-0x1 (money/bignumber 3250) - balance-0x2 (money/bignumber 2100) - balance-0x3 (money/bignumber 2400)] + balance-0x1 (money/bignumber 6002.5) + balance-0x2 (money/bignumber 11001) + balance-0x3 (money/bignumber 14001)] (is (money/equal-to balance-0x1 (get result "0x1"))) (is (money/equal-to balance-0x2 (get result "0x2"))) @@ -330,6 +323,8 @@ (assoc :currencies currencies) (assoc-in [:wallet :accounts] accounts) (assoc-in [:wallet :current-viewing-account-address] "0x1") + (assoc-in [:wallet :tokens :prices-per-token] + {:ETH {:usd 2000} :DAI {:usd 1}}) (assoc-in [:wallet :networks] network-data))) (let [result (rf/sub [sub-name])] @@ -359,8 +354,8 @@ :tokens tokens-0x1} (dissoc result :balance :formatted-balance))) - (is (money/equal-to (:balance result) (money/bignumber 3250))) - (is (match? (:formatted-balance result) "$3250.00"))))) + (is (money/equal-to (:balance result) (money/bignumber 6002.5))) + (is (match? (:formatted-balance result) "$6002.50"))))) (h/deftest-sub :wallet/addresses [sub-name] @@ -514,12 +509,10 @@ (assoc-in [:wallet :ui :send :token-symbol] "ETH"))) (let [result (rf/sub [sub-name])] (is (match? result - [{:tokens [{:symbol "ETH" - :balances-per-chain {1 {:raw-balance "100"}} - :market-values-per-currency {:usd {:price 10000}}} - {:symbol "SNT" - :balances-per-chain {1 {:raw-balance "100"}} - :market-values-per-currency {:usd {:price 10000}}}] + [{:tokens [{:symbol "ETH" + :balances-per-chain {1 {:raw-balance "100"}}} + {:symbol "SNT" + :balances-per-chain {1 {:raw-balance "100"}}}] :network-preferences-names #{} :customization-color nil :operable? true @@ -533,12 +526,10 @@ (assoc-in [:wallet :ui :send :token] {:symbol "ETH"}))) (let [result (rf/sub [sub-name])] (is (match? result - [{:tokens [{:symbol "ETH" - :balances-per-chain {1 {:raw-balance "100"}} - :market-values-per-currency {:usd {:price 10000}}} - {:symbol "SNT" - :balances-per-chain {1 {:raw-balance "100"}} - :market-values-per-currency {:usd {:price 10000}}}] + [{:tokens [{:symbol "ETH" + :balances-per-chain {1 {:raw-balance "100"}}} + {:symbol "SNT" + :balances-per-chain {1 {:raw-balance "100"}}}] :network-preferences-names #{} :customization-color nil :operable? true @@ -568,6 +559,8 @@ #(-> % (assoc-in [:wallet :accounts] accounts) (assoc-in [:wallet :current-viewing-account-address] "0x1") + (assoc-in [:wallet :tokens :prices-per-token] + {:ETH {:usd 2000} :DAI {:usd 1}}) (assoc-in [:wallet :networks] network-data))) (is (match? [{:short-name "eth" @@ -603,7 +596,7 @@ eth-token (some #(when (= (:symbol %) "ETH") %) result) eth-mainnet-raw-balance (get-in eth-token [:balances-per-chain 1 :raw-balance])] (is (match? 2 (count result))) - (is (money/equal-to (money/bignumber 2520) eth-mainnet-raw-balance))))) + (is (money/equal-to (money/bignumber 4.5) eth-mainnet-raw-balance))))) (h/deftest-sub :wallet/aggregated-token-values-and-balance [sub-name] @@ -611,10 +604,12 @@ (swap! rf-db/app-db #(-> % (assoc :wallet db/defaults) (assoc :currencies currencies) - (assoc-in [:wallet :accounts] accounts))) + (assoc-in [:wallet :accounts] accounts) + (assoc-in [:wallet :tokens :prices-per-token] + {:ETH {:usd 2000} :DAI {:usd 1}}))) (let [{:keys [formatted-balance tokens]} (rf/sub [sub-name])] (is (match? 2 (count tokens))) - (is (match? "$2106.00" formatted-balance))))) + (is (match? "$17003.50" formatted-balance))))) (h/deftest-sub :wallet/accounts-with-customization-color [sub-name] @@ -885,6 +880,8 @@ (assoc-in [:wallet :networks] network-data) (assoc-in [:wallet :current-viewing-account-address] "0x2") (assoc :currencies currencies) + (assoc-in [:wallet :tokens :prices-per-token] + {:ETH {:usd 2000} :DAI {:usd 1}}) (assoc-in [:profile/profile :currency] :usd))) (is (match? (count (rf/sub [sub-name ""])) 2)) (is (match? (count (rf/sub [sub-name "et"])) 2)))) @@ -914,6 +911,8 @@ (assoc-in [:wallet :ui :network-filter :selected-networks] #{constants/arbitrum-network-name}) (assoc-in [:wallet :accounts] accounts) (assoc-in [:wallet :current-viewing-account-address] "0x1") + (assoc-in [:wallet :tokens :prices-per-token] + {:ETH {:usd 2000} :DAI {:usd 1}}) (assoc-in [:wallet :networks] network-data))) (let [result (rf/sub [sub-name]) @@ -948,14 +947,15 @@ #(-> % (assoc-in [:wallet :accounts] accounts) (assoc-in [:wallet :networks] network-data) + (assoc-in [:wallet :tokens :prices-per-token] {:ETH {:usd 2000} :DAI {:usd 1}}) (assoc :currencies currencies) (assoc-in [:profile/profile :currency] :usd))) (let [result (rf/sub [sub-name]) chains (keys result)] (is (match? (count chains) 3)) - (is (match? (get result constants/ethereum-mainnet-chain-id) "$1504.00")) - (is (match? (get result constants/optimism-mainnet-chain-id) "$602.00"))))) + (is (match? (get result constants/ethereum-mainnet-chain-id) "$9002.00")) + (is (match? (get result constants/optimism-mainnet-chain-id) "$8001.50"))))) (h/deftest-sub :wallet/current-viewing-account-fiat-balance-per-chain [sub-name] @@ -965,14 +965,15 @@ (assoc-in [:wallet :accounts] accounts) (assoc-in [:wallet :networks] network-data) (assoc-in [:wallet :current-viewing-account-address] "0x2") + (assoc-in [:wallet :tokens :prices-per-token] {:ETH {:usd 2000} :DAI {:usd 1}}) (assoc :currencies currencies) (assoc-in [:profile/profile :currency] :usd))) (let [result (rf/sub [sub-name]) chains (keys result)] (is (match? (count chains) 3)) - (is (match? (get result constants/ethereum-mainnet-chain-id) "$1500.00")) - (is (match? (get result constants/optimism-mainnet-chain-id) "$600.00")) + (is (match? (get result constants/ethereum-mainnet-chain-id) "$5001.00")) + (is (match? (get result constants/optimism-mainnet-chain-id) "$6000.00")) (is (match? (get result constants/arbitrum-mainnet-chain-id) "$0.00"))))) (h/deftest-sub :wallet/wallet-send-fee-fiat-formatted @@ -984,12 +985,14 @@ (assoc-in [:wallet :current-viewing-account-address] "0x1") (assoc-in [:wallet :ui :send :route] route-data) (assoc :currencies currencies) + (assoc-in [:wallet :tokens :prices-per-token] + {:ETH {:usd 2000} :DAI {:usd 1}}) (assoc-in [:profile/profile :currency] :usd) (assoc-in [:profile/profile :currency-symbol] "$"))) (let [token-symbol-for-fees "ETH" result (rf/sub [sub-name token-symbol-for-fees])] - (is (match? result "$1.00"))))) + (is (match? result "$0.20"))))) (h/deftest-sub :wallet/has-partially-operable-accounts? [sub-name] @@ -1004,3 +1007,4 @@ [:wallet :accounts] (update accounts "0x2" assoc :operable :partially))) (is (true? (rf/sub [sub-name]))))) + diff --git a/src/tests/contract_test/wallet_test.cljs b/src/tests/contract_test/wallet_test.cljs index ed19bdbd47..73efc1b401 100644 --- a/src/tests/contract_test/wallet_test.cljs +++ b/src/tests/contract_test/wallet_test.cljs @@ -71,8 +71,6 @@ (is (not-empty (:symbol token))) (is (:decimals token)) (is (contains? token :balancesPerChain)) - (is (contains? token :marketValuesPerCurrency)) - (is (contains? (:marketValuesPerCurrency token) :usd)) (let [balances-per-chain (:balancesPerChain token)] (doseq [[_ balance] balances-per-chain] (is (contains? balance :rawBalance)) @@ -86,7 +84,7 @@ (promesa/let [accounts (rpc-events/call-async "accounts_getAccounts" false) default-address (contract-utils/get-default-address accounts) response (rpc-events/call-async - "wallet_getWalletToken" + "wallet_fetchOrGetCachedWalletBalances" false [default-address])] (assert-wallet-tokens response)))))