Added support for different currencies in wallet accounts price calculation (#18078)

This commit:

- adds support for different currencies in token price calculation in the new wallet UI.
- fixes the token units and prices displayed in the individual account screen

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
This commit is contained in:
Mohamed Javid 2023-12-15 01:08:16 +05:30 committed by GitHub
parent 16a52b38e8
commit ed53fecf47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 186 additions and 41 deletions

View File

@ -15,5 +15,6 @@
(multiaccounts.update/multiaccount-update
:currency
currency
{})
;; on changing currency, we should fetch tokens prices again
{:on-success #(rf/dispatch [:wallet/get-wallet-token])})
(prices/update-prices)))

View File

@ -105,6 +105,7 @@
(def ^:const profile-default-color :blue)
(def ^:const profile-name-max-length 24)
(def ^:const profile-default-currency :usd)
(def ^:const profile-pictures-show-to-contacts-only 1)
(def ^:const profile-pictures-show-to-everyone 2)

View File

@ -35,11 +35,12 @@
[]
(let [selected-tab (reagent/atom first-tab-id)]
(fn []
(let [{:keys [name color balance watch-only?]} (rf/sub [:wallet/current-viewing-account])]
(let [{:keys [name color balance watch-only?]} (rf/sub [:wallet/current-viewing-account])
currency-symbol (rf/sub [:profile/currency-symbol])]
[rn/view {:style {:flex 1}}
[account-switcher/view {:on-press #(rf/dispatch [:wallet/close-account-page])}]
[quo/account-overview
{:current-value (utils/prettify-balance balance)
{:current-value (utils/prettify-balance currency-symbol balance)
:account-name name
:account (if watch-only? :watched-address :default)
:customization-color color}]

View File

@ -9,13 +9,13 @@
(first (string/split full-name #" ")))
(defn prettify-balance
[balance]
[currency-symbol balance]
(let [valid-balance? (and balance
(or (number? balance) (.-toFixed balance)))]
(as-> balance $
(if valid-balance? $ 0)
(.toFixed $ 2)
(str "$" $))))
(str currency-symbol $))))
(defn get-derivation-path
[number-of-accounts]
@ -60,15 +60,18 @@
(defn total-token-fiat-value
"Returns the total token fiat value taking into account all token's chains."
[{:keys [market-values-per-currency] :as token}]
(let [usd-price (-> market-values-per-currency :usd :price)
[currency {:keys [market-values-per-currency] :as token}]
(let [price (get-in market-values-per-currency
[currency :price]
(get-in market-values-per-currency
[constants/profile-default-currency :price]))
total-units-in-all-chains (total-token-units-in-all-chains token)]
(money/crypto->fiat total-units-in-all-chains usd-price)))
(money/crypto->fiat total-units-in-all-chains price)))
(defn calculate-balance-for-account
[{:keys [tokens] :as _account}]
[currency {:keys [tokens] :as _account}]
(->> tokens
(map total-token-fiat-value)
(map #(total-token-fiat-value currency %))
(reduce money/add)))
(defn network-list

View File

@ -100,14 +100,21 @@
(let [addresses (->> (get-in db [:wallet :accounts])
vals
(map :address))]
{:fx [[:json-rpc/call
{:db (assoc-in db [:wallet :ui :tokens-loading?] true)
:fx [[:json-rpc/call
[{:method "wallet_getWalletToken"
:params [addresses]
:on-success [:wallet/store-wallet-token]
:on-error #(log/info "failed to get wallet token "
{:error %
:event :wallet/get-wallet-token
:params addresses})}]]]})))
:on-error [:wallet/get-wallet-token-failed addresses]}]]]})))
(rf/reg-event-fx
:wallet/get-wallet-token-failed
(fn [{:keys [db]} [params error]]
(log/info "failed to get wallet token "
{:error error
:event :wallet/get-wallet-token
:params params})
{:db (assoc-in db [:wallet :ui :tokens-loading?] false)}))
(defn- fix-balances-per-chain
[token]

View File

@ -20,7 +20,7 @@
(let [on-press #(js/alert "Not implemented yet")
total-balance-formatted (.toFixed (:total-balance token) 2)
balance-fiat-formatted (.toFixed (:total-balance-fiat token) 2)
currency-symbol "$"]
currency-symbol (rf/sub [:profile/currency-symbol])]
[quo/token-network
{:token (:symbol token)
:label (:name token)

View File

@ -6,6 +6,7 @@
[re-frame.core :as re-frame]
[status-im.fleet.core :as fleet]
[status-im.multiaccounts.db :as multiaccounts.db]
[status-im.utils.currency :as currency]
[status-im.wallet.utils :as wallet.utils]
[status-im2.constants :as constants]
[utils.address :as address]
@ -18,6 +19,19 @@
(fn [{:keys [customization-color]}]
(or customization-color constants/profile-default-color)))
(re-frame/reg-sub
:profile/currency
:<- [:profile/profile]
(fn [{:keys [currency]}]
(or currency constants/profile-default-currency)))
(re-frame/reg-sub
:profile/currency-symbol
:<- [:profile/currency]
(fn [currency-id]
(-> (get currency/currencies currency-id)
:symbol)))
(re-frame/reg-sub
:profile/onboarding-placeholder-avatar
:<- [:mediaserver/port]

View File

@ -0,0 +1,114 @@
(ns status-im2.subs.profile-test
(:require [cljs.test :refer [is testing use-fixtures]]
[re-frame.db :as rf-db]
status-im2.subs.root
[test-helpers.unit :as h]
[utils.re-frame :as rf]))
(use-fixtures :each
{:before #(reset! rf-db/app-db {})})
(def sample-profile
{:keycard-pairing nil
:send-push-notifications? true
:send-status-updates? true
:key-uid "0x2285f5c1ffd94ade0aa3568bff85f6c06f2860391ba65ccf56276cbc6829a22a"
:backup-enabled? true
:address "0x70F8913fbE0Ca5687F1Fb73068944d6e99B27804"
:mnemonic "lucky veteran business source debris large priority color endless answer strong pave"
:preview-privacy? true
:identicon ""
:use-mailservers? true
:signing-phrase "polo rush vest"
:url-unfurling-mode 1
:custom-bootnodes-enabled? {}
:log-level "INFO"
:profile-pictures-visibility 2
:messages-from-contacts-only false
:pinned-mailservers {}
:eip1581-address "0x15636c0aa4036b9f984e8998db085328795b26d8"
:images [{:keyUid "0x2285f5c1ffd94ade0aa3568bff85f6c06f2860391ba65ccf56276cbc6829a22a"
:type "large"
:uri "data:image/jpeg;base64,/9j/2wCEAAgGBgcGBQgHBwcJC="
:width 240
:height 240
:fileSize 15973
:resizeTarget 240
:clock 0}
{:keyUid "0x2285f5c1ffd94ade0aa3568bff85f6c06f2860391ba65ccf56276cbc6829a22a"
:type "thumbnail"
:uri "data:image/jpeg;base64,/9j/2wCEAAgGBgcGBQgHBwcJC="
:width 80
:height 240
:fileSize 2558
:resizeTarget 80
:clock 0}]
:name "Plush Shiny Songbird"
:latest-derived-path 0
:compressed-key "zQ3shS6tp3NsQT4RSUFtnTqnBQzC5kt2SZzxZmnPEiNkHetwj"
:wallet-legacy/visible-tokens {:mainnet #{:SNT}}
:kdfIterations 3200
:ens-name? false
:emoji-hash ["👮" "🧑🏿‍🏭" "📬" "👰‍♀️" "🦚" "💳" "👨🏿‍🍳" "☝️" "🤰🏾" "🍊" "☁️" "☔" "👷🏽" "🤹🏾"]
:wallet-root-address "0x704c9a261b918cb8e522f7fc2bc477c12d0c74ac"
:last-backup 1701832050
:link-previews-enabled-sites #{}
:networks/networks {}
:wakuv2-config {:Port 0
:DataDir ""
:LightClient true
:AutoUpdate true
:MaxMessageSize 0
:KeepAliveInterval 0
:Nameserver ""
:UseShardAsDefaultTopic false
:PeerExchange true
:StoreCapacity 0
:UDPPort 0
:EnableStore false
:EnableFilterFullNode false
:Enabled true
:EnableConfirmations false
:Host "0.0.0.0"
:CustomNodes {}
:FullNode false
:EnableDiscV5 true
:DiscoveryLimit 20
:StoreSeconds 0}
:current-user-visibility-status {:clock 1701798568
:text ""
:status-type 1}
:gifs/api-key ""
:currency :usd
:gifs/favorite-gifs nil
:customization-color :magenta
:default-sync-period 777600
:photo-path ""
:dapps-address "0x52fB56556A039244CED121AFB9ec829788Db78c8"
:custom-bootnodes {}
:display-name "Alisher Y"
:gifs/recent-gifs nil
:appearance 0
:link-preview-request-enabled true
:profile-pictures-show-to 2
:timestamp 1701798892
:device-name ""
:colorId 2
:networks/current-network "mainnet_rpc"
:mutual-contact-enabled? false
:public-key
"0x0445b4d3a20f9fcf95b9e669857f83a073e7fdb7b79d0ac03ffb601d6889c413fa86282a2b2bed46ecf7d499807c1567549367a4eaa2b7b925067d44562d93cfa6"
:colorHash [[3 25] [4 3] [5 4] [2 0] [1 10] [5 2] [2 4] [1 17] [3 23] [2 19] [4 1]]
:installation-id "cee7e269-1ca7-4468-a1dd-e60e5cfb0894"})
(h/deftest-sub :profile/currency
[sub-name]
(testing "returns the selected currency of user"
(swap! rf-db/app-db #(assoc % :profile/profile sample-profile))
(is (match? :usd (rf/sub [sub-name])))))
(h/deftest-sub :profile/currency-symbol
[sub-name]
(testing "returns the symbol of the user's selected currency"
(swap! rf-db/app-db #(assoc % :profile/profile sample-profile))
(is (match? "$" (rf/sub [sub-name])))))

View File

@ -1,6 +1,7 @@
(ns status-im2.subs.wallet.wallet
(:require [clojure.string :as string]
[re-frame.core :as rf]
[status-im2.constants :as constants]
[status-im2.contexts.wallet.common.utils :as utils]
[utils.number]))
@ -69,23 +70,25 @@
(rf/reg-sub
:wallet/balances
:<- [:wallet/accounts]
(fn [accounts]
:<- [:profile/currency]
(fn [[accounts currency]]
(zipmap (map :address accounts)
(map utils/calculate-balance-for-account accounts))))
(map #(utils/calculate-balance-for-account currency %) accounts))))
(rf/reg-sub
:wallet/account-cards-data
:<- [:wallet/accounts]
:<- [:wallet/balances]
:<- [:wallet/tokens-loading?]
(fn [[accounts balances tokens-loading?]]
:<- [:profile/currency-symbol]
(fn [[accounts balances tokens-loading? currency-symbol]]
(mapv (fn [{:keys [color address watch-only?] :as account}]
(assoc account
:customization-color color
:type (if watch-only? :watch-only :empty)
:on-press #(rf/dispatch [:wallet/navigate-to-account address])
:loading? tokens-loading?
:balance (utils/prettify-balance (get balances address))))
:balance (utils/prettify-balance currency-symbol (get balances address))))
accounts)))
(rf/reg-sub
@ -131,31 +134,32 @@
(remove #(:watch-only? %) accounts)))
(defn- calc-token-value
[{:keys [market-values-per-currency] :as item} chain-id]
(let [crypto-value (utils/token-value-in-chain item chain-id)
market-values (:usd market-values-per-currency)
{:keys [price change-pct-24hour]} market-values
fiat-change (utils/calculate-fiat-change crypto-value change-pct-24hour)]
(when (and crypto-value (seq (:name item)))
{:token (keyword (string/lower-case (:symbol item)))
:token-name (:name item)
:state :default
:status (cond
(pos? change-pct-24hour) :positive
(neg? change-pct-24hour) :negative
:else :empty)
:customization-color :blue
:values {:crypto-value crypto-value
:fiat-value (utils/prettify-balance (* crypto-value price))
:percentage-change (.toFixed change-pct-24hour 2)
:fiat-change (utils/prettify-balance fiat-change)}})))
[{:keys [market-values-per-currency] :as token} color currency currency-symbol]
(let [token-units (utils/total-token-units-in-all-chains token)
fiat-value (utils/total-token-fiat-value currency token)
market-values (get market-values-per-currency
currency
(get market-values-per-currency
constants/profile-default-currency))
{:keys [change-pct-24hour]} market-values]
{:token (:symbol token)
:token-name (:name token)
:state :default
:status (cond
(pos? change-pct-24hour) :positive
(neg? change-pct-24hour) :negative
:else :empty)
:customization-color color
:values {:crypto-value token-units
:fiat-value (utils/prettify-balance currency-symbol fiat-value)}}))
(rf/reg-sub
:wallet/account-token-values
:<- [:wallet/current-viewing-account]
:<- [:chain-id]
(fn [[current-account chain-id]]
(mapv #(calc-token-value % chain-id) (:tokens current-account))))
:<- [:profile/currency]
:<- [:profile/currency-symbol]
(fn [[{:keys [tokens color]} currency currency-symbol]]
(mapv #(calc-token-value % color currency currency-symbol) tokens)))
(rf/reg-sub
:wallet/network-preference-details