fix: no routes are found in case of valid amount in fiat is entered (#20000)

Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
Brian Sztamfater 2024-05-20 10:08:31 -03:00 committed by GitHub
parent 3de86b09bd
commit d4e7e4cd52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 300 additions and 245 deletions

View File

@ -8,6 +8,7 @@
(h/render-with-theme-provider [token-input/view
{:token :snt
:currency :eur
:currency-symbol "€"
:conversion 1}])
(h/is-truthy (h/get-by-text "SNT")))
@ -15,5 +16,6 @@
(h/render-with-theme-provider [token-input/view
{:token :snt
:currency :eur
:currency-symbol "€"
:conversion 1}])
(h/is-truthy (h/get-by-text "€0.00"))))

View File

@ -12,30 +12,22 @@
{:padding-horizontal 20
:padding-bottom 4
:height 36
:flex-direction :row
:justify-content :space-between})
:flex-direction :row})
(defn token-name
[theme]
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:margin-right 8
:padding-bottom 2})
(def token-label-container
{:position :absolute
:left 40 ; token image size + margin
:right 0
:bottom 0
:top 0
:flex-direction :row
:align-items :flex-end})
:padding-bottom 3})
(def text-input-container
{:position :absolute
:top 0
:bottom 0
:left 40 ; token image size + margin
:right 0})
{:flex-direction :row
:align-items :flex-end})
(defn input-container
[window-width]
{:width (- window-width 120)
:margin-left 8
:margin-right 8})
(def text-input-dimensions
(-> typography/heading-1
@ -54,7 +46,8 @@
:color
(if error?
(colors/resolve-color :danger theme)
(colors/theme-colors colors/neutral-100 colors/white theme))))
(colors/theme-colors colors/neutral-100 colors/white theme))
:flex-shrink 1))
(defn placeholder-text
[theme]

View File

@ -9,32 +9,34 @@
[quo.components.utilities.token.view :as token]
[quo.components.wallet.token-input.schema :as component-schema]
[quo.components.wallet.token-input.style :as style]
[quo.foundations.common :as common]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[schema.core :as schema]))
[schema.core :as schema]
[utils.number :as number]))
(defn fiat-format
[currency num-value conversion]
(str (get common/currency-label currency) (.toFixed (* num-value conversion) 2)))
[currency-symbol num-value conversion]
(str currency-symbol (.toFixed (* num-value conversion) 2)))
(defn crypto-format
[num-value conversion crypto-decimals token]
(str (.toFixed (/ num-value conversion) (or crypto-decimals 2))
(str (number/remove-trailing-zeroes
(.toFixed (/ num-value conversion) (or crypto-decimals 2)))
" "
(string/upper-case (or (clj->js token) ""))))
(defn calc-value
[{:keys [crypto? currency token value conversion crypto-decimals]}]
[{:keys [crypto? currency-symbol token value conversion crypto-decimals]}]
(let [num-value (if (string? value)
(or (parse-double value) 0)
value)]
(if crypto?
(fiat-format currency num-value conversion)
(fiat-format currency-symbol num-value conversion)
(crypto-format num-value conversion crypto-decimals token))))
(defn- data-info
[{:keys [theme token crypto-decimals conversion networks title crypto? currency amount error?]}]
[{:keys [theme token crypto-decimals conversion networks title crypto? currency-symbol amount
error?]}]
[rn/view {:style style/data-container}
[network-tag/view
{:networks networks
@ -45,7 +47,7 @@
:weight :medium
:style (style/fiat-amount theme)}
(calc-value {:crypto? crypto?
:currency currency
:currency-symbol currency-symbol
:token token
:value amount
:conversion conversion
@ -59,20 +61,6 @@
:weight :semi-bold}
(string/upper-case (or (clj->js text) ""))])
(defn- token-label
[{:keys [theme value text]}]
[rn/view
{:style style/token-label-container
:pointer-events :none}
[rn/text-input
{:max-length 12
:style style/text-input-dimensions
:editable false
:placeholder "0"
:opacity 0
:value value}]
[token-name-text theme text]])
(defn input-section
[{:keys [on-change-text value value-internal set-value-internal on-selection-change
on-token-press]}]
@ -92,14 +80,19 @@
(oops/oget "nativeEvent.selection")
(js->clj :keywordize-keys true)
(on-selection-change))))]
(fn [{:keys [token customization-color show-keyboard? crypto? currency value error? selection]
(fn [{:keys [token customization-color show-keyboard? crypto? currency value error? selection
handle-on-swap]
:or {show-keyboard? true}}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style {:flex 1}}
[rn/pressable {:on-press on-token-press}
(let [theme (quo.theme/use-theme)
window-width (:width (rn/get-window))]
[rn/pressable
{:style {:width "100%"
:flex-direction :row}
:on-press on-token-press}
[token/view
{:token token
:size :size-32}]]
:size :size-32}]
[rn/view {:style (style/input-container window-width)}
[rn/pressable
{:style style/text-input-container
:on-press focus-input}
@ -110,18 +103,22 @@
:ref set-ref
:placeholder "0"
:keyboard-type :numeric
:max-length 12
:on-change-text handle-on-change-text
:selection-color customization-color
:show-soft-input-on-focus show-keyboard?
:on-selection-change handle-selection-change
:selection (clj->js selection)}
controlled-input? (assoc :value value)
(not controlled-input?) (assoc :default-value value-internal))]]
[token-label
{:theme theme
:text (if crypto? token currency)
:value (if controlled-input? value value-internal)}]]))))
(not controlled-input?) (assoc :default-value value-internal))]
[token-name-text theme (if crypto? token currency)]]]
[button/button
{:icon true
:icon-only? true
:size 32
:on-press handle-on-swap
:type :outline
:accessibility-label :reorder}
:i/reorder]]))))
(defn- view-internal
[{:keys [container-style value on-swap] :as props}]
@ -141,15 +138,8 @@
:value-internal value-internal
:theme theme
:set-value-internal set-value-internal
:crypto? crypto?)]
[button/button
{:icon true
:icon-only? true
:size 32
:on-press handle-on-swap
:type :outline
:accessibility-label :reorder}
:i/reorder]]
:handle-on-swap handle-on-swap
:crypto? crypto?)]]
[divider-line/view {:container-style (style/divider theme)}]
[data-info
(assoc props

View File

@ -1,5 +0,0 @@
(ns quo.foundations.common)
(def currency-label
{:eur "€"
:usd "$"})

View File

@ -37,7 +37,7 @@
[state]
(set-input-error state (upper-limit-exceeded? state)))
(defn- set-input-value
(defn set-input-value
[state value]
(-> state
(assoc :value value)

View File

@ -4,7 +4,7 @@
[status-im.common.qr-codes.view :as qr-codes]
[status-im.constants :as constants]
[utils.money :as money]
[utils.number]))
[utils.number :as number]))
(defn get-first-name
[full-name]
@ -56,16 +56,6 @@
(inc max-decimals)
max-decimals)))
(defn remove-trailing-zeroes
[num]
(let [parts (clojure.string/split (str num) #"\.")]
(str (first parts)
(if-let [decimals (second parts)]
(if (seq (clojure.string/replace decimals #"0+$" ""))
(str "." (clojure.string/replace decimals #"0+$" ""))
"")
""))))
(defn get-crypto-decimals-count
[{:keys [market-values-per-currency]}]
(let [price (get-in market-values-per-currency [:usd :price])
@ -83,8 +73,8 @@
one-cent-value (if (pos? price) (/ 0.01 price) 0)
decimals-count (calc-max-crypto-decimals one-cent-value)]
(if (< token-units one-cent-value)
(str "<" (remove-trailing-zeroes (.toFixed one-cent-value decimals-count)))
(remove-trailing-zeroes (.toFixed token-units decimals-count))))))
(str "<" (number/remove-trailing-zeroes (.toFixed one-cent-value decimals-count)))
(number/remove-trailing-zeroes (.toFixed token-units decimals-count))))))
(defn get-market-value
[currency {:keys [market-values-per-currency]}]

View File

@ -117,6 +117,7 @@
dissoc
:suggested-routes
:route
:amount
:from-values-by-chain
:to-values-by-chain
:sender-network-values

View File

@ -69,6 +69,7 @@
:view-id :screen/wallet.send-input-amount
:wallet/wallet-send-to-address "0x04371e2d9d66b82f056bc128064"
:profile/currency-symbol "$"
:profile/currency :usd
:wallet/token-by-symbol {:symbol :eth
:total-balance 100
:market-values-per-currency {:usd {:price 10}}}
@ -86,7 +87,8 @@
:chain-id 1
:related-chain-id 1
:layer 1}]
:wallet/wallet-send-enabled-from-chain-ids [1]})
:wallet/wallet-send-enabled-from-chain-ids [1]
:wallet/wallet-send-amount nil})
(h/describe "Send > input amount screen"
(h/setup-restorable-re-frame)
@ -173,6 +175,6 @@
(h/is-truthy (h/get-by-label-text :container-error))
(h/fire-event :press (h/query-by-label-text :reorder))
(-> (h/wait-for #(h/get-by-text "Max: 1000.00 USD"))
(-> (h/wait-for #(h/get-by-text "Max: $1000.00"))
(.then (fn []
(h/wait-for #(h/is-truthy (h/get-by-label-text :container))))))))

View File

@ -16,11 +16,13 @@
[status-im.contexts.wallet.send.utils :as send-utils]
[status-im.contexts.wallet.sheets.unpreferred-networks-alert.view :as unpreferred-networks-alert]
[utils.address :as address]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.money :as money]
[utils.number :as number]
[utils.re-frame :as rf]))
(defn- make-limit-label
(defn- make-limit-label-crypto
[amount currency]
(str amount
" "
@ -28,6 +30,10 @@
name
string/upper-case)))
(defn- make-limit-label-fiat
[amount currency-symbol]
(str currency-symbol amount))
(defn- estimated-fees
[{:keys [loading-routes? fees amount receiver]}]
[rn/view {:style style/estimated-fees-container}
@ -61,6 +67,7 @@
(every? (fn [{:keys [total-amount]}]
(and
total-amount
(money/bignumber? total-amount)
(money/equal-to total-amount
(money/bignumber "0"))))
sender-network-values))
@ -128,6 +135,7 @@
on-navigate-back on-navigate-back]
(fn []
(let [[input-state set-input-state] (rn/use-state controlled-input/init-state)
[just-toggled-mode? set-just-toggled-mode?] (rn/use-state false)
clear-input! #(set-input-state controlled-input/delete-all)
handle-on-confirm (fn []
(rf/dispatch [:wallet/set-token-amount-to-send
@ -137,7 +145,8 @@
:stack-id current-screen-id}]))
{fiat-currency :currency} (rf/sub [:profile/profile])
{token-symbol :symbol
token-networks :networks} (rf/sub [:wallet/wallet-send-token])
token-networks :networks
token-decimals :decimals} (rf/sub [:wallet/wallet-send-token])
send-enabled-networks (rf/sub [:wallet/wallet-send-enabled-networks])
enabled-from-chain-ids (rf/sub
[:wallet/wallet-send-enabled-from-chain-ids])
@ -147,16 +156,15 @@
token} (rf/sub
[:wallet/current-viewing-account-tokens-filtered
(str token-symbol) enabled-from-chain-ids])
conversion-rate (-> token :market-values-per-currency :usd :price)
currency-symbol (rf/sub [:profile/currency-symbol])
currency (rf/sub [:profile/currency])
conversion-rate (-> token :market-values-per-currency currency :price)
loading-routes? (rf/sub
[:wallet/wallet-send-loading-suggested-routes?])
route (rf/sub [:wallet/wallet-send-route])
to-address (rf/sub [:wallet/wallet-send-to-address])
on-confirm (or default-on-confirm handle-on-confirm)
crypto-decimals (or default-crypto-decimals
(utils/get-crypto-decimals-count token))
crypto-decimals (or token-decimals default-crypto-decimals)
current-crypto-limit (or default-limit-crypto
(utils/get-standard-crypto-format
token
@ -182,15 +190,23 @@
(> (controlled-input/numeric-value
input-state)
available-limit)))
current-currency (if @crypto-currency? token-symbol fiat-currency)
input-num-value (controlled-input/numeric-value input-state)
input-amount (controlled-input/input-value input-state)
confirm-disabled? (or (nil? route)
(empty? route)
(string/blank? (controlled-input/input-value
input-state))
(<= input-num-value 0)
(> input-num-value current-limit))
amount-text (str (controlled-input/input-value input-state)
amount (if @crypto-currency?
input-amount
(number/remove-trailing-zeroes
(.toFixed (/ input-amount conversion-rate)
crypto-decimals)))
send-amount (rf/sub [:wallet/wallet-send-amount])
amount-text (str (number/remove-trailing-zeroes
(.toFixed (js/parseFloat send-amount)
(min token-decimals 6)))
" "
token-symbol)
first-route (first route)
@ -211,7 +227,6 @@
{:currency fiat-currency
:balance fee-in-native-token
:token native-token}))
currency-symbol (rf/sub [:profile/currency-symbol])
fee-formatted (when fee-in-fiat
(utils/get-standard-fiat-format
fee-in-crypto-formatted
@ -247,6 +262,7 @@
receiver-preferred-networks-set
receiver-selected-network))
receiver-networks))
input-error (controlled-input/input-error input-state)
limit-insufficient? (> (controlled-input/numeric-value input-state)
current-limit)
should-try-again? (and (not limit-insufficient?) no-routes-found?)]
@ -259,6 +275,9 @@
(fn []
(set-input-state #(controlled-input/set-upper-limit % current-limit)))
[current-limit])
(rn/use-effect
#(when input-error (debounce/clear-all))
[input-error])
[rn/view
{:style style/screen
:accessibility-label (str "container"
@ -270,22 +289,40 @@
[quo/token-input
{:container-style style/input-container
:token token-symbol
:currency current-currency
:crypto-decimals crypto-decimals
:currency fiat-currency
:currency-symbol currency-symbol
:crypto-decimals (min token-decimals 6)
:error? (controlled-input/input-error input-state)
:networks (seq send-enabled-networks)
:title (i18n/label :t/send-limit
{:limit (make-limit-label current-limit current-currency)})
:title (i18n/label
:t/send-limit
{:limit (if @crypto-currency?
(make-limit-label-crypto current-limit token-symbol)
(make-limit-label-fiat current-limit currency-symbol))})
:conversion conversion-rate
:show-keyboard? false
:value (controlled-input/input-value input-state)
:on-swap #(reset! crypto-currency? %)
:value input-amount
:on-swap (fn [swap-to-crypto-currency?]
(set-just-toggled-mode? true)
(reset! 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))))))
:on-token-press show-select-asset-sheet}]
[routes/view
{:token token
:input-value (controlled-input/input-value input-state)
:input-value input-amount
:value amount
:valid-input? valid-input?
:token-not-supported-in-receiver-networks? token-not-supported-in-receiver-networks?
:lock-fetch-routes? just-toggled-mode?
:current-screen-id current-screen-id}]
(when (and (not loading-routes?)
sender-network-values
@ -314,9 +351,15 @@
{:disabled? (and (not should-try-again?) confirm-disabled?)
:on-press (cond
should-try-again?
#(rf/dispatch [:wallet/get-suggested-routes
{:amount (controlled-input/input-value
input-state)}])
#(let [input-amount (controlled-input/input-value
input-state)
amount (if @crypto-currency?
input-amount
(.toFixed (* token-balance
conversion-rate)
2))]
(rf/dispatch [:wallet/get-suggested-routes
{:amount amount}]))
sending-to-unpreferred-networks?
#(show-unpreferred-networks-alert on-confirm)
:else
@ -328,11 +371,22 @@
:left-action :dot
:delete-key? true
:on-press (fn [c]
(when-not loading-routes?
(set-input-state #(controlled-input/add-character % 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 (and (not loading-routes?)
(re-matches regex new-text))
(debounce/clear-all)
(set-just-toggled-mode? false)
(set-input-state #(controlled-input/add-character % c)))))
:on-delete (fn []
(when-not loading-routes?
(debounce/clear-all)
(set-just-toggled-mode? false)
(set-input-state controlled-input/delete-last)))
:on-long-press-delete (fn []
(when-not loading-routes?
(debounce/clear-all)
(set-just-toggled-mode? false)
(set-input-state controlled-input/delete-all)))}]]))))

View File

@ -16,8 +16,8 @@
(def network-link-1x-height 56)
(def network-link-2x-height 111)
(defn fetch-routes
[amount valid-input? bounce-duration-ms]
(defn- fetch-routes
[{:keys [amount bounce-duration-ms valid-input?]}]
(if valid-input?
(debounce/debounce-and-dispatch
[:wallet/get-suggested-routes {:amount amount}]
@ -174,8 +174,8 @@
:text (i18n/label :t/at-least-one-network-must-be-activated)}]))))
(defn view
[{:keys [token theme input-value valid-input?
on-press-to-network current-screen-id
[{:keys [token theme input-value value valid-input?
lock-fetch-routes? on-press-to-network current-screen-id
token-not-supported-in-receiver-networks?]}]
(let [token-symbol (:symbol token)
nav-current-screen-id (rf/sub [:view-id])
@ -198,12 +198,21 @@
:disabled-chain-ids disabled-from-chain-ids})
show-routes? (not-empty sender-network-values)]
(rn/use-effect
#(when (and active-screen? (> (count token-available-networks-for-suggested-routes) 0))
(fetch-routes input-value valid-input? 2000))
(fn []
(when (and active-screen?
(> (count token-available-networks-for-suggested-routes) 0)
(not lock-fetch-routes?))
(fetch-routes
{:amount value
:valid-input? valid-input?
:bounce-duration-ms 2000})))
[input-value valid-input?])
(rn/use-effect
#(when (and active-screen? (> (count token-available-networks-for-suggested-routes) 0))
(fetch-routes input-value valid-input? 0))
(fetch-routes
{:amount value
:valid-input? valid-input?
:bounce-duration-ms 0}))
[disabled-from-chain-ids])
[rn/scroll-view {:content-container-style style/routes-container}
(when show-routes?
@ -238,5 +247,8 @@
:loading-routes? loading-routes?
:theme theme
:token-not-supported-in-receiver-networks? token-not-supported-in-receiver-networks?
:on-save #(fetch-routes input-value valid-input? 0)}]]]))
:on-save #(fetch-routes
{:amount input-value
:valid-input? valid-input?
:bounce-duration-ms 0})}]]]))

View File

@ -24,6 +24,11 @@
:<- [:wallet/wallet-send]
:-> :transaction-ids)
(rf/reg-sub
:wallet/wallet-send-amount
:<- [:wallet/wallet-send]
:-> :amount)
(rf/reg-sub
:wallet/send-transaction-progress
:<- [:wallet/send-transaction-ids]

View File

@ -1,4 +1,5 @@
(ns utils.number)
(ns utils.number
(:require [clojure.string :as string]))
(defn naive-round
"Quickly and naively round number `n` up to `decimal-places`.
@ -29,3 +30,13 @@
if `num` exceeds a given bound, then returns the bound exceeded."
[number lower-bound upper-bound]
(max lower-bound (min number upper-bound)))
(defn remove-trailing-zeroes
[num]
(let [parts (string/split (str num) #"\.")]
(str (first parts)
(if-let [decimals (second parts)]
(if (seq (string/replace decimals #"0+$" ""))
(str "." (string/replace decimals #"0+$" ""))
"")
""))))