Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wallet: token input conversion #18539

Merged
merged 12 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions src/quo/components/wallet/token_input/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,22 @@
[react-native.core :as rn]
[reagent.core :as reagent]))

(defn fiat-format
[currency num-value conversion]
(str (get common/currency-label currency) (.toFixed (* num-value conversion) 2)))

(defn crypto-format
[num-value conversion crypto-decimals token]
(str (.toFixed (/ num-value conversion) (or crypto-decimals 2))
" "
(string/upper-case (or (clj->js token) ""))))

(defn calc-value
[crypto? currency token value conversion]
[{:keys [crypto? currency token value conversion crypto-decimals]}]
(let [num-value (if (string? value) (parse-double (or value "0")) value)]
(if crypto?
(str (get common/currency-label currency) (.toFixed (* num-value conversion) 2))
(str (.toFixed (/ num-value conversion) 2) " " (string/upper-case (or (clj->js token) ""))))))
(fiat-format currency num-value conversion)
(crypto-format num-value conversion crypto-decimals token))))

(defn- view-internal
[{external-value :value}]
Expand All @@ -27,7 +37,8 @@
crypto? (reagent/atom true)
input-ref (atom nil)
controlled-input? (some? external-value)]
(fn [{:keys [theme token currency conversion networks title customization-color
(fn [{:keys [theme token currency crypto-decimals conversion networks title
customization-color
on-change-text on-swap container-style show-keyboard?]
:or {show-keyboard? true}
external-value :value}]
Expand Down Expand Up @@ -86,6 +97,11 @@
{:size :paragraph-2
:weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
(calc-value @crypto? currency token (or external-value @value) conversion)]]])))
(calc-value {:crypto? @crypto?
:currency currency
:token token
:value (or external-value @value)
:conversion conversion
:crypto-decimals crypto-decimals})]]])))

(def view (quo.theme/with-theme view-internal))
6 changes: 6 additions & 0 deletions src/status_im/contexts/wallet/common/utils.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@
"")
""))))

(defn get-crypto-decimals-count
[{:keys [market-values-per-currency]}]
(let [price (get-in market-values-per-currency [:usd :price])
one-cent-value (if (pos? price) (/ 0.01 price) 0)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should price be a big number?

Cc @ulisesmac

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think price should be.

JS numbers' implementation sometimes have an unexpected behaviour. since we are dealing with money, better to be safe 👍

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think price should be.

JS numbers' implementation sometimes have an unexpected behaviour. since we are dealing with money, better to be safe 👍

(calc-max-crypto-decimals one-cent-value)))

(defn get-standard-crypto-format
"For full details: https://github.com/status-im/status-mobile/issues/18225"
[{:keys [market-values-per-currency]} token-units]
Expand Down
4 changes: 3 additions & 1 deletion src/status_im/contexts/wallet/send/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@
(rf/reg-event-fx :wallet/send-select-token
(fn [{:keys [db]} [{:keys [token stack-id]}]]
{:db (assoc-in db [:wallet :ui :send :token] token)
:fx [[:navigate-to-within-stack [:wallet-send-input-amount stack-id]]]}))
:fx [[:dispatch-later
{:ms 1
:dispatch [:navigate-to-within-stack [:wallet-send-input-amount stack-id]]}]]}))

(rf/reg-event-fx :wallet/send-select-token-drawer
(fn [{:keys [db]} [{:keys [token]}]]
Expand Down
40 changes: 22 additions & 18 deletions src/status_im/contexts/wallet/send/input_amount/component_spec.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false}
:wallet/wallet-send-token {:symbol :eth}
:wallet/wallet-send-token {:symbol :eth
:total-balance 100
:market-values-per-currency {:usd {:price 10}}}
:wallet/wallet-send-loading-suggested-routes? false
:wallet/wallet-send-route {:route []}
:wallet/wallet-send-suggested-routes {:candidates []}})
Expand All @@ -49,7 +51,9 @@

(h/test "Default render"
(h/setup-subs sub-mocks)
(h/render [input-amount/view {}])
(h/render [input-amount/view
{:crypto-decimals 2
:limit-crypto 250}])
(h/is-truthy (h/get-by-text "0"))
(h/is-truthy (h/get-by-text "ETH"))
(h/is-truthy (h/get-by-text "$0.00"))
Expand All @@ -59,9 +63,9 @@
(h/setup-subs sub-mocks)
(let [on-confirm (h/mock-fn)]
(h/render [input-amount/view
{:on-confirm on-confirm
:rate 10
:limit 1000}])
{:on-confirm on-confirm
:crypto-decimals 10
:limit-crypto 1000}])

(h/fire-event :press (h/query-by-label-text :keyboard-key-1))
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
Expand All @@ -81,9 +85,9 @@

(let [on-confirm (h/mock-fn)]
(h/render [input-amount/view
{:rate 10
:limit 1000
:on-confirm on-confirm}])
{:crypto-decimals 10
:limit-crypto 1000
:on-confirm on-confirm}])

(h/fire-event :press (h/query-by-label-text :keyboard-key-1))
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
Expand All @@ -101,8 +105,8 @@
(h/test "Try to fill more than limit"
(h/setup-subs sub-mocks)
(h/render [input-amount/view
{:rate 10
:limit 286}])
{:crypto-decimals 10
:limit-crypto 286}])

(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
Expand All @@ -118,9 +122,9 @@
(h/test "Try to fill more than limit"
(h/setup-subs sub-mocks)
(h/render [input-amount/view
{:rate 10
:limit 286
:on-confirm #()}])
{:crypto-decimals 10
:limit-crypto 286
:on-confirm #()}])

(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
Expand All @@ -136,9 +140,9 @@
(h/test "Switch from crypto to fiat and check limit"
(h/setup-subs sub-mocks)
(h/render [input-amount/view
{:rate 10
:limit 250
:on-confirm #()}])
{:crypto-decimals 2
:limit-crypto 250
:on-confirm #()}])

(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
(h/fire-event :press (h/query-by-label-text :keyboard-key-0))
Expand All @@ -149,7 +153,7 @@
(.then (fn []
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
(h/wait-for #(h/get-by-text "205.50 ETH"))))
(h/wait-for #(h/get-by-text "20.50 ETH"))))
(.then (fn []
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
(h/wait-for #(h/get-by-text "205.50 ETH")))))))
(h/wait-for #(h/get-by-text "20.50 ETH")))))))
13 changes: 9 additions & 4 deletions src/status_im/contexts/wallet/send/input_amount/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.input-amount.style :as style]
[status-im.contexts.wallet.send.routes.view :as routes]
[utils.debounce :as debounce]
Expand Down Expand Up @@ -61,15 +62,18 @@
(map first)))

(defn- f-view-internal
[{:keys [rate limit]}]
;; crypto-decimals and limit-crypto args are needed for component tests only
[{:keys [crypto-decimals limit-crypto]}]
(let [bottom (safe-area/get-bottom)
{:keys [currency]} (rf/sub [:profile/profile])
token (rf/sub [:wallet/wallet-send-token])
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
token-symbol (:symbol token)
limit-crypto (or (:total-balance token) limit)
conversion-rate (or rate 10)
limit-fiat (* limit-crypto conversion-rate)
limit-crypto (or limit-crypto
(utils/get-standard-crypto-format token (:total-balance token)))
conversion-rate (get-in token [:market-values-per-currency :usd :price])
limit-fiat (.toFixed (* (:total-balance token) conversion-rate) 2)
crypto-decimals (or crypto-decimals (utils/get-crypto-decimals-count token))
input-value (reagent/atom "")
current-limit (reagent/atom {:amount limit-crypto
:currency token-symbol})
Expand Down Expand Up @@ -140,6 +144,7 @@
{:container-style style/input-container
:token token-symbol
:currency currency
:crypto-decimals crypto-decimals
:networks (:networks token)
:title (i18n/label :t/send-limit {:limit limit-label})
:conversion conversion-rate
Expand Down