Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7eaa8585b | ||
|
|
83f832d948 | ||
|
|
e5cd07a92b | ||
|
|
c5eda74b19 | ||
|
|
51ccf0acc8 | ||
|
|
b805cbcfe2 |
@@ -10,17 +10,14 @@
|
|||||||
[]
|
[]
|
||||||
[rn/view {:style style/bridge-send-wrapper}
|
[rn/view {:style style/bridge-send-wrapper}
|
||||||
[input-amount/view
|
[input-amount/view
|
||||||
{:current-screen-id :screen/wallet.bridge-input-amount
|
{:current-screen-id :screen/wallet.bridge-input-amount
|
||||||
:button-one-label (i18n/label :t/review-bridge)
|
:button-one-label (i18n/label :t/review-bridge)
|
||||||
:button-one-props {:icon-left :i/bridge}
|
:button-one-props {:icon-left :i/bridge}
|
||||||
:enabled-from-chain-ids (rf/sub
|
:on-confirm (fn [amount]
|
||||||
[:wallet/bridge-from-chain-ids])
|
(rf/dispatch [:wallet/set-token-amount-to-bridge
|
||||||
:from-enabled-networks (rf/sub [:wallet/bridge-from-networks])
|
{:amount amount
|
||||||
:on-confirm (fn [amount]
|
:stack-id :screen/wallet.bridge-input-amount}]))
|
||||||
(rf/dispatch [:wallet/set-token-amount-to-bridge
|
:on-navigate-back (fn []
|
||||||
{:amount amount
|
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes])
|
||||||
:stack-id :screen/wallet.bridge-input-amount}]))
|
(rf/dispatch [:wallet/clean-disabled-from-networks])
|
||||||
:on-navigate-back (fn []
|
(rf/dispatch [:wallet/clean-send-amount]))}]])
|
||||||
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes])
|
|
||||||
(rf/dispatch [:wallet/clean-disabled-from-networks])
|
|
||||||
(rf/dispatch [:wallet/clean-send-amount]))}]])
|
|
||||||
|
|||||||
@@ -27,12 +27,18 @@
|
|||||||
[balance]
|
[balance]
|
||||||
(cut-fiat-balance balance 2))
|
(cut-fiat-balance balance 2))
|
||||||
|
|
||||||
(defn prettify-balance
|
(defn prepend-curency-symbol-to-fiat-balance
|
||||||
[currency-symbol balance]
|
[fiat-balance currency-symbol]
|
||||||
(let [formatted-symbol (if (> (count currency-symbol) 1)
|
(let [formatted-symbol (if (> (count currency-symbol) 1)
|
||||||
(str currency-symbol " ")
|
(str currency-symbol " ")
|
||||||
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
|
(defn get-derivation-path
|
||||||
[number-of-accounts]
|
[number-of-accounts]
|
||||||
@@ -104,11 +110,15 @@
|
|||||||
:else (number/remove-trailing-zeroes
|
:else (number/remove-trailing-zeroes
|
||||||
(.toFixed token-units standardized-decimals-count)))))
|
(.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
|
(defn prettify-crypto-balance
|
||||||
[token-symbol crypto-balance conversion-rate]
|
[token-symbol crypto-balance conversion-rate]
|
||||||
(str (cut-crypto-decimals-to-fit-usd-cents crypto-balance conversion-rate)
|
(-> crypto-balance
|
||||||
" "
|
(cut-crypto-decimals-to-fit-usd-cents conversion-rate)
|
||||||
(string/upper-case token-symbol)))
|
(add-token-symbol-to-crypto-balance token-symbol)))
|
||||||
|
|
||||||
(defn get-standard-crypto-format
|
(defn get-standard-crypto-format
|
||||||
"For full details: https://github.com/status-im/status-mobile/issues/18225"
|
"For full details: https://github.com/status-im/status-mobile/issues/18225"
|
||||||
|
|||||||
@@ -11,4 +11,7 @@
|
|||||||
;; in and the device is offline, versus re-fetching when offline and
|
;; in and the device is offline, versus re-fetching when offline and
|
||||||
;; tokens already exist in the app-db.
|
;; tokens already exist in the app-db.
|
||||||
:tokens-loading nil
|
:tokens-loading nil
|
||||||
:active-tab :assets}})
|
:active-tab :assets
|
||||||
|
:screens {:input-amount-screen
|
||||||
|
{:crypto-currency? true
|
||||||
|
:input-value ""}}}})
|
||||||
|
|||||||
@@ -104,7 +104,7 @@
|
|||||||
:wallet/wallet-send-tx-type :tx/send
|
:wallet/wallet-send-tx-type :tx/send
|
||||||
:wallet/wallet-send-fee-fiat-formatted "$5,00"
|
:wallet/wallet-send-fee-fiat-formatted "$5,00"
|
||||||
:wallet/sending-collectible? false
|
:wallet/sending-collectible? false
|
||||||
:wallet/total-amount (money/bignumber "250")})
|
:wallet/total-amount-in-to-chains (money/bignumber "250")})
|
||||||
|
|
||||||
(h/describe "Send > input amount screen"
|
(h/describe "Send > input amount screen"
|
||||||
(h/setup-restorable-re-frame)
|
(h/setup-restorable-re-frame)
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
(ns status-im.contexts.wallet.send.input-amount.controlled-input-logic
|
||||||
|
(:require
|
||||||
|
[clojure.string :as string]
|
||||||
|
[utils.money :as money]))
|
||||||
|
|
||||||
|
(def ^:private default-max-limit 12)
|
||||||
|
|
||||||
|
(def ^:private not-digits-or-dot-pattern
|
||||||
|
#"[^0-9+\.]")
|
||||||
|
|
||||||
|
(def ^:private dot ".")
|
||||||
|
|
||||||
|
(defn- can-add-character?
|
||||||
|
[input-value character max-length]
|
||||||
|
(let [length-overflow? (>= (count input-value) max-length)
|
||||||
|
extra-dot? (and (= character dot) (string/includes? input-value dot))
|
||||||
|
extra-leading-zero? (and (= input-value "0") (= "0" (str character)))
|
||||||
|
non-numeric? (re-find not-digits-or-dot-pattern (str character))]
|
||||||
|
(not (or non-numeric? extra-dot? extra-leading-zero? length-overflow?))))
|
||||||
|
|
||||||
|
(defn- normalize-value-as-numeric
|
||||||
|
[value character]
|
||||||
|
(cond
|
||||||
|
(and (string/blank? value) (= character dot))
|
||||||
|
(str "0" character)
|
||||||
|
|
||||||
|
(and (= value "0") (not= character dot))
|
||||||
|
(str character)
|
||||||
|
|
||||||
|
:else
|
||||||
|
(str value character)))
|
||||||
|
|
||||||
|
(defn add-character
|
||||||
|
([input-value character]
|
||||||
|
(add-character input-value character default-max-limit))
|
||||||
|
([input-value character max-length]
|
||||||
|
(if (can-add-character? input-value character max-length)
|
||||||
|
(normalize-value-as-numeric input-value character)
|
||||||
|
input-value)))
|
||||||
|
|
||||||
|
(defn delete-last
|
||||||
|
([input-value]
|
||||||
|
(delete-last input-value ""))
|
||||||
|
([input-value default-value]
|
||||||
|
(let [new-value (subs input-value 0 (dec (count input-value)))]
|
||||||
|
(if (string/blank? new-value)
|
||||||
|
default-value
|
||||||
|
new-value))))
|
||||||
|
|
||||||
|
(defn upper-limit-exceeded?
|
||||||
|
[input-value upper-limit]
|
||||||
|
(and upper-limit
|
||||||
|
(when (money/bignumber? (money/bignumber input-value))
|
||||||
|
(money/greater-than (money/bignumber input-value) (money/bignumber upper-limit)))))
|
||||||
|
|
||||||
|
(defn lower-limit-exceeded?
|
||||||
|
[input-value lower-limit]
|
||||||
|
(and lower-limit
|
||||||
|
(when (money/bignumber? (money/bignumber input-value))
|
||||||
|
(money/less-than (money/bignumber input-value) (money/bignumber lower-limit)))))
|
||||||
|
|
||||||
|
(defn value-out-of-limits?
|
||||||
|
[input-value upper-limit lower-limit]
|
||||||
|
(or (upper-limit-exceeded? input-value upper-limit)
|
||||||
|
(lower-limit-exceeded? input-value lower-limit)))
|
||||||
|
|
||||||
|
(defn value-numeric
|
||||||
|
[input-value]
|
||||||
|
(or (parse-double input-value) 0))
|
||||||
|
|
||||||
|
(defn empty-value?
|
||||||
|
[input-value]
|
||||||
|
(or (string/blank? input-value) (<= (value-numeric input-value) 0)))
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
(ns status-im.contexts.wallet.send.input-amount.events
|
||||||
|
(:require
|
||||||
|
[status-im.contexts.wallet.send.input-amount.controlled-input-logic :as controlled-input-logic]
|
||||||
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
(def input-value-path [:wallet :ui :screens :input-amount-screen :input-value])
|
||||||
|
(def crypto-currency?-path [:wallet :ui :screens :input-amount-screen :crypto-currency?])
|
||||||
|
|
||||||
|
(rf/reg-event-fx :send-input-amount-screen/set-token-input-value
|
||||||
|
(fn [{:keys [db]} [v]]
|
||||||
|
{:db (assoc-in db input-value-path v)}))
|
||||||
|
|
||||||
|
(rf/reg-event-fx :send-input-amount-screen/swap-between-fiat-and-crypto
|
||||||
|
(fn [{:keys [db]} [token-input-converted-value]]
|
||||||
|
{:db (update-in db crypto-currency?-path not)
|
||||||
|
:fx [[:dispatch
|
||||||
|
[:send-input-amount-screen/set-token-input-value token-input-converted-value]]]}))
|
||||||
|
|
||||||
|
(rf/reg-event-fx :send-input-amount-screen/token-input-add-character
|
||||||
|
(fn [{:keys [db]} [c max-decimals]]
|
||||||
|
(let [input-value (get-in db input-value-path)
|
||||||
|
new-text (str input-value c)
|
||||||
|
regex-pattern (str "^\\d*\\.?\\d{0," max-decimals "}$")
|
||||||
|
regex (re-pattern regex-pattern)]
|
||||||
|
(when (re-matches regex new-text)
|
||||||
|
{:db (update-in db input-value-path #(controlled-input-logic/add-character % c))}))))
|
||||||
|
|
||||||
|
(rf/reg-event-fx :send-input-amount-screen/token-input-delete-last
|
||||||
|
(fn [{:keys [db]}]
|
||||||
|
{:db (update-in db input-value-path controlled-input-logic/delete-last)}))
|
||||||
|
|
||||||
|
(rf/reg-event-fx :send-input-amount-screen/token-input-delete-all
|
||||||
|
(fn [{:keys [db]}]
|
||||||
|
{:db (assoc-in db input-value-path "")}))
|
||||||
|
|
||||||
|
|
||||||
@@ -1,67 +1,56 @@
|
|||||||
(ns status-im.contexts.wallet.send.input-amount.view
|
(ns status-im.contexts.wallet.send.input-amount.view
|
||||||
(:require
|
(:require
|
||||||
[clojure.string :as string]
|
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[quo.foundations.colors :as colors]
|
[quo.foundations.colors :as colors]
|
||||||
[quo.theme]
|
[quo.theme]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.safe-area :as safe-area]
|
[react-native.safe-area :as safe-area]
|
||||||
[status-im.common.controlled-input.utils :as controlled-input]
|
|
||||||
[status-im.constants :as constants]
|
|
||||||
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
|
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
|
||||||
[status-im.contexts.wallet.common.asset-list.view :as asset-list]
|
[status-im.contexts.wallet.common.asset-list.view :as asset-list]
|
||||||
[status-im.contexts.wallet.common.utils :as utils]
|
[status-im.contexts.wallet.send.input-amount.events]
|
||||||
[status-im.contexts.wallet.send.input-amount.style :as style]
|
[status-im.contexts.wallet.send.input-amount.style :as style]
|
||||||
[status-im.contexts.wallet.send.routes.view :as routes]
|
[status-im.contexts.wallet.send.routes.view :as routes]
|
||||||
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
|
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
|
||||||
[status-im.contexts.wallet.sheets.unpreferred-networks-alert.view :as unpreferred-networks-alert]
|
[status-im.contexts.wallet.sheets.unpreferred-networks-alert.view :as unpreferred-networks-alert]
|
||||||
[status-im.feature-flags :as ff]
|
[status-im.feature-flags :as ff]
|
||||||
[status-im.setup.hot-reload :as hot-reload]
|
[status-im.setup.hot-reload :as hot-reload]
|
||||||
|
[status-im.subs.wallet.screens.input-amount]
|
||||||
[utils.debounce :as debounce]
|
[utils.debounce :as debounce]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.money :as money]
|
|
||||||
[utils.number :as number]
|
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn- estimated-fees
|
(defn- estimated-fees
|
||||||
[{:keys [loading-routes? fees amount]}]
|
[]
|
||||||
[rn/view {:style style/estimated-fees-container}
|
(let [loading-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
|
||||||
(when (ff/enabled? ::ff/wallet.advanced-sending)
|
fees (rf/sub [:send-input-amount-screen/fee-formatted])
|
||||||
[rn/view {:style style/estimated-fees-content-container}
|
amount (rf/sub [:send-input-amount-screen/recipient-gets-amount])]
|
||||||
[quo/button
|
[rn/view {:style style/estimated-fees-container}
|
||||||
{:icon-only? true
|
(when (ff/enabled? ::ff/wallet.advanced-sending)
|
||||||
:type :outline
|
[rn/view {:style style/estimated-fees-content-container}
|
||||||
:size 32
|
[quo/button
|
||||||
:inner-style {:opacity 1}
|
{:icon-only? true
|
||||||
:accessibility-label :advanced-button
|
:type :outline
|
||||||
:disabled? loading-routes?
|
:size 32
|
||||||
:on-press #(js/alert "Not implemented yet")}
|
:inner-style {:opacity 1}
|
||||||
:i/advanced]])
|
:accessibility-label :advanced-button
|
||||||
[quo/data-item
|
:disabled? loading-routes?
|
||||||
{:container-style style/fees-data-item
|
:on-press #(js/alert "Not implemented yet")}
|
||||||
:status (if loading-routes? :loading :default)
|
:i/advanced]])
|
||||||
:size :small
|
[quo/data-item
|
||||||
:title (i18n/label :t/fees)
|
{:container-style style/fees-data-item
|
||||||
:subtitle fees}]
|
:status (if loading-routes? :loading :default)
|
||||||
[quo/data-item
|
:size :small
|
||||||
{:container-style style/amount-data-item
|
:title (i18n/label :t/fees)
|
||||||
:status (if loading-routes? :loading :default)
|
:subtitle fees}]
|
||||||
:size :small
|
[quo/data-item
|
||||||
:title (i18n/label :t/recipient-gets)
|
{:container-style style/amount-data-item
|
||||||
:subtitle amount}]])
|
:status (if loading-routes? :loading :default)
|
||||||
|
:size :small
|
||||||
(defn- every-network-value-is-zero?
|
:title (i18n/label :t/recipient-gets)
|
||||||
[sender-network-values]
|
:subtitle amount}]]))
|
||||||
(every? (fn [{:keys [total-amount]}]
|
|
||||||
(and
|
|
||||||
total-amount
|
|
||||||
(money/bignumber? total-amount)
|
|
||||||
(money/equal-to total-amount
|
|
||||||
(money/bignumber "0"))))
|
|
||||||
sender-network-values))
|
|
||||||
|
|
||||||
(defn select-asset-bottom-sheet
|
(defn select-asset-bottom-sheet
|
||||||
[clear-input!]
|
[]
|
||||||
(let [{preselected-token-symbol :symbol} (rf/sub [:wallet/wallet-send-token])]
|
(let [{preselected-token-symbol :symbol} (rf/sub [:wallet/wallet-send-token])]
|
||||||
[:<> ;; Need to be a `:<>` to keep `asset-list` scrollable.
|
[:<> ;; Need to be a `:<>` to keep `asset-list` scrollable.
|
||||||
[quo/drawer-top
|
[quo/drawer-top
|
||||||
@@ -73,15 +62,19 @@
|
|||||||
:preselected-token-symbol preselected-token-symbol
|
:preselected-token-symbol preselected-token-symbol
|
||||||
:on-token-press (fn [token]
|
:on-token-press (fn [token]
|
||||||
(rf/dispatch [:wallet/edit-token-to-send token])
|
(rf/dispatch [:wallet/edit-token-to-send token])
|
||||||
(clear-input!))}]]))
|
(rf/dispatch
|
||||||
|
[:send-input-amount-screen/token-input-delete-all]))}]]))
|
||||||
|
|
||||||
(defn- token-not-available
|
(defn- token-not-available
|
||||||
[token-symbol receiver-networks token-networks]
|
[]
|
||||||
(let [theme (quo.theme/use-theme)
|
(let [theme (quo.theme/use-theme)
|
||||||
add-token-networks (fn []
|
{token-symbol :symbol
|
||||||
(let [chain-ids (concat receiver-networks
|
token-networks :networks} (rf/sub [:wallet/wallet-send-token])
|
||||||
(mapv #(:chain-id %) token-networks))]
|
receiver-networks (rf/sub [:wallet/wallet-send-receiver-networks])
|
||||||
(rf/dispatch [:wallet/update-receiver-networks chain-ids])))]
|
add-token-networks (fn []
|
||||||
|
(let [chain-ids (concat receiver-networks
|
||||||
|
(mapv #(:chain-id %) token-networks))]
|
||||||
|
(rf/dispatch [:wallet/update-receiver-networks chain-ids])))]
|
||||||
[rn/view {:style (style/token-not-available-container theme)}
|
[rn/view {:style (style/token-not-available-container theme)}
|
||||||
[rn/view
|
[rn/view
|
||||||
[quo/icon :i/alert
|
[quo/icon :i/alert
|
||||||
@@ -140,163 +133,117 @@
|
|||||||
|
|
||||||
:else (rf/dispatch [:wallet/stop-and-clean-suggested-routes])))
|
:else (rf/dispatch [:wallet/stop-and-clean-suggested-routes])))
|
||||||
|
|
||||||
(defn- get-fee-formatted
|
(defn token-input
|
||||||
[route]
|
[]
|
||||||
(when-let [native-currency-symbol (-> route first :from :native-currency-symbol)]
|
(let [show-select-asset-sheet #(rf/dispatch
|
||||||
(rf/sub [:wallet/wallet-send-fee-fiat-formatted native-currency-symbol])))
|
[:show-bottom-sheet
|
||||||
|
{:content (fn [] [select-asset-bottom-sheet])}])
|
||||||
|
{:keys [input-value crypto-currency?]} (rf/sub [:send-input-amount-screen/state])
|
||||||
|
from-enabled-networks (rf/sub [:send-input-amount-screen/from-enabled-networks])
|
||||||
|
{fiat-currency :currency} (rf/sub [:profile/profile])
|
||||||
|
{token-symbol :symbol} (rf/sub [:wallet/wallet-send-token])
|
||||||
|
input-value-converted (rf/sub [:send-input-amount-screen/input-value-converted])
|
||||||
|
converted-value-prettified (rf/sub
|
||||||
|
[:send-input-amount-screen/converted-value-prettified])
|
||||||
|
value-out-of-limits? (rf/sub [:send-input-amount-screen/value-out-of-limits?])
|
||||||
|
upper-limit-prettified (rf/sub
|
||||||
|
[:send-input-amount-screen/upper-limit-prettified])]
|
||||||
|
[quo/token-input
|
||||||
|
{:container-style style/input-container
|
||||||
|
:token-symbol token-symbol
|
||||||
|
:value input-value
|
||||||
|
:on-swap #(rf/dispatch [:send-input-amount-screen/swap-between-fiat-and-crypto
|
||||||
|
input-value-converted])
|
||||||
|
:on-token-press show-select-asset-sheet
|
||||||
|
:error? value-out-of-limits?
|
||||||
|
:currency-symbol (if crypto-currency? token-symbol fiat-currency)
|
||||||
|
:converted-value converted-value-prettified
|
||||||
|
:hint-component [quo/network-tags
|
||||||
|
{:networks (seq from-enabled-networks)
|
||||||
|
:title (i18n/label
|
||||||
|
:t/send-limit
|
||||||
|
{:limit upper-limit-prettified})
|
||||||
|
:status (when value-out-of-limits? :error)}]}]))
|
||||||
|
(defn routes-view
|
||||||
|
[current-screen-id]
|
||||||
|
(let [token-by-symbol (rf/sub [:send-input-amount-screen/token-by-symbol])
|
||||||
|
token (rf/sub [:wallet/wallet-send-token])
|
||||||
|
routes (rf/sub [:send-input-amount-screen/routes])
|
||||||
|
valid-input? (rf/sub [:send-input-amount-screen/valid-input?])
|
||||||
|
amount-in-crypto (rf/sub [:send-input-amount-screen/amount-in-crypto])
|
||||||
|
limit-exceeded? (rf/sub [:send-input-amount-screen/upper-limit-exceeded?])
|
||||||
|
unsupported-token-in-receiver? (rf/sub
|
||||||
|
[:send-input-amount-screen/unsupported-token-in-receiver?])
|
||||||
|
request-fetch-routes (fn [bounce-duration-ms]
|
||||||
|
(fetch-routes
|
||||||
|
{:amount amount-in-crypto
|
||||||
|
:valid-input? valid-input?
|
||||||
|
:bounce-duration-ms bounce-duration-ms
|
||||||
|
:token token
|
||||||
|
:reset-amounts-to-zero? (and limit-exceeded?
|
||||||
|
(some? routes))}))]
|
||||||
|
[routes/view
|
||||||
|
{:token token-by-symbol
|
||||||
|
:send-amount-in-crypto amount-in-crypto
|
||||||
|
:valid-input? valid-input?
|
||||||
|
:token-not-supported-in-receiver-networks? unsupported-token-in-receiver?
|
||||||
|
:current-screen-id current-screen-id
|
||||||
|
:request-fetch-routes request-fetch-routes}]))
|
||||||
|
|
||||||
|
(defn bottom-actions
|
||||||
|
[button-one-label button-one-props on-confirm]
|
||||||
|
(let [token-by-symbol (rf/sub [:send-input-amount-screen/token-by-symbol])
|
||||||
|
loading-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
|
||||||
|
amount-in-crypto (rf/sub [:send-input-amount-screen/amount-in-crypto])
|
||||||
|
sending-to-unpreferred-networks? (rf/sub
|
||||||
|
[:send-input-amount-screen/sending-to-unpreferred-networks?])
|
||||||
|
current-color (rf/sub [:wallet/current-viewing-account-color])
|
||||||
|
not-enough-asset? (rf/sub [:send-input-amount-screen/not-enough-asset?])
|
||||||
|
should-try-again? (rf/sub [:send-input-amount-screen/should-try-again?])
|
||||||
|
confirm-disabled? (rf/sub [:send-input-amount-screen/confirm-disabled?])]
|
||||||
|
[quo/bottom-actions
|
||||||
|
{:actions :one-action
|
||||||
|
:button-one-label (if should-try-again?
|
||||||
|
(i18n/label :t/try-again)
|
||||||
|
button-one-label)
|
||||||
|
:button-one-props (merge (when-not should-try-again?
|
||||||
|
button-one-props)
|
||||||
|
{:disabled? (or not-enough-asset?
|
||||||
|
loading-routes?
|
||||||
|
(and (not should-try-again?)
|
||||||
|
confirm-disabled?))
|
||||||
|
:on-press (cond
|
||||||
|
should-try-again?
|
||||||
|
#(rf/dispatch [:wallet/start-get-suggested-routes
|
||||||
|
{:amount amount-in-crypto
|
||||||
|
:updated-token token-by-symbol}])
|
||||||
|
sending-to-unpreferred-networks?
|
||||||
|
#(show-unpreferred-networks-alert on-confirm)
|
||||||
|
:else
|
||||||
|
#(on-confirm amount-in-crypto))
|
||||||
|
:customization-color current-color}
|
||||||
|
(when should-try-again?
|
||||||
|
{:type :grey}))}]))
|
||||||
|
|
||||||
(defn- insufficient-asset-amount?
|
|
||||||
[{:keys [token-symbol owned-eth-token input-state no-routes-found? limit-exceeded?
|
|
||||||
sender-network-values enough-assets?]}]
|
|
||||||
(let [eth-selected? (= token-symbol (string/upper-case constants/mainnet-short-name))
|
|
||||||
zero-owned-eth? (money/equal-to (:total-balance owned-eth-token) 0)
|
|
||||||
input-at-max-owned-amount? (money/equal-to
|
|
||||||
(controlled-input/value-bn input-state)
|
|
||||||
(controlled-input/upper-limit-bn input-state))
|
|
||||||
exceeded-input? (if eth-selected?
|
|
||||||
input-at-max-owned-amount?
|
|
||||||
zero-owned-eth?)]
|
|
||||||
(and (or no-routes-found? limit-exceeded?)
|
|
||||||
(seq sender-network-values)
|
|
||||||
(or exceeded-input? (not enough-assets?)))))
|
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
;; crypto-decimals, limit-crypto and initial-crypto-currency? args are needed
|
;; crypto-decimals, limit-crypto and initial-crypto-currency? args are needed
|
||||||
;; for component tests only
|
;; for component tests only
|
||||||
[{default-on-confirm :on-confirm
|
[{on-confirm :on-confirm
|
||||||
default-limit-crypto :limit-crypto
|
on-navigate-back :on-navigate-back
|
||||||
default-crypto-decimals :crypto-decimals
|
button-one-label :button-one-label
|
||||||
on-navigate-back :on-navigate-back
|
button-one-props :button-one-props
|
||||||
button-one-label :button-one-label
|
current-screen-id :current-screen-id}]
|
||||||
button-one-props :button-one-props
|
(let [view-id (rf/sub [:view-id])
|
||||||
current-screen-id :current-screen-id
|
active-screen? (= view-id current-screen-id)
|
||||||
initial-crypto-currency? :initial-crypto-currency?
|
bottom (safe-area/get-bottom)
|
||||||
enabled-from-chain-ids :enabled-from-chain-ids
|
max-decimals (rf/sub [:send-input-amount-screen/max-decimals])
|
||||||
from-enabled-networks :from-enabled-networks
|
value-out-of-limits? (rf/sub [:send-input-amount-screen/value-out-of-limits?])
|
||||||
:or {initial-crypto-currency? true}}]
|
current-address (rf/sub [:wallet/current-viewing-account-address])
|
||||||
(let [view-id (rf/sub [:view-id])
|
not-enough-asset? (rf/sub [:send-input-amount-screen/not-enough-asset?])
|
||||||
active-screen? (= view-id current-screen-id)
|
show-no-routes? (rf/sub [:send-input-amount-screen/show-no-routes?])
|
||||||
bottom (safe-area/get-bottom)
|
show-estimated-fees? (rf/sub [:send-input-amount-screen/show-estimated-fees?])
|
||||||
[crypto-currency?
|
token-not-available? (rf/sub [:send-input-amount-screen/token-not-available?])]
|
||||||
set-crypto-currency] (rn/use-state initial-crypto-currency?)
|
|
||||||
handle-on-confirm (fn [amount]
|
|
||||||
(rf/dispatch [:wallet/set-token-amount-to-send
|
|
||||||
{:amount amount
|
|
||||||
:stack-id current-screen-id}]))
|
|
||||||
{fiat-currency :currency} (rf/sub [:profile/profile])
|
|
||||||
{token-symbol :symbol
|
|
||||||
token-networks :networks
|
|
||||||
:as token} (rf/sub [:wallet/wallet-send-token])
|
|
||||||
send-from-locked-amounts (rf/sub [:wallet/wallet-send-from-locked-amounts])
|
|
||||||
{:keys [total-balance]
|
|
||||||
:as token-by-symbol} (rf/sub [:wallet/token-by-symbol
|
|
||||||
(str token-symbol)
|
|
||||||
enabled-from-chain-ids])
|
|
||||||
token-balance (or default-limit-crypto total-balance)
|
|
||||||
usd-conversion-rate (utils/token-usd-price token)
|
|
||||||
currency (rf/sub [:profile/currency])
|
|
||||||
conversion-rate (-> token
|
|
||||||
:market-values-per-currency
|
|
||||||
currency
|
|
||||||
:price)
|
|
||||||
token-decimals (-> token
|
|
||||||
utils/token-usd-price
|
|
||||||
utils/one-cent-value
|
|
||||||
utils/calc-max-crypto-decimals)
|
|
||||||
[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])
|
|
||||||
loading-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
|
|
||||||
route (rf/sub [:wallet/wallet-send-route])
|
|
||||||
on-confirm (or default-on-confirm handle-on-confirm)
|
|
||||||
crypto-decimals (or token-decimals default-crypto-decimals)
|
|
||||||
max-limit (if crypto-currency?
|
|
||||||
(utils/cut-crypto-decimals-to-fit-usd-cents
|
|
||||||
token-balance
|
|
||||||
usd-conversion-rate)
|
|
||||||
(utils/cut-fiat-balance-to-two-decimals
|
|
||||||
(money/crypto->fiat token-balance conversion-rate)))
|
|
||||||
input-value (controlled-input/input-value input-state)
|
|
||||||
valid-input? (not (or (controlled-input/empty-value? input-state)
|
|
||||||
(controlled-input/input-error input-state)))
|
|
||||||
amount-in-crypto (if crypto-currency?
|
|
||||||
input-value
|
|
||||||
(number/remove-trailing-zeroes
|
|
||||||
(.toFixed (/ input-value conversion-rate)
|
|
||||||
crypto-decimals)))
|
|
||||||
total-amount-receiver (rf/sub [:wallet/total-amount true])
|
|
||||||
amount-text (str (number/remove-trailing-zeroes
|
|
||||||
(.toFixed total-amount-receiver
|
|
||||||
(min token-decimals 6)))
|
|
||||||
" "
|
|
||||||
token-symbol)
|
|
||||||
show-select-asset-sheet #(rf/dispatch
|
|
||||||
[:show-bottom-sheet
|
|
||||||
{:content (fn []
|
|
||||||
[select-asset-bottom-sheet
|
|
||||||
clear-input!])}])
|
|
||||||
sender-network-values (rf/sub [:wallet/wallet-send-sender-network-values])
|
|
||||||
receiver-network-values (rf/sub [:wallet/wallet-send-receiver-network-values])
|
|
||||||
tx-type (rf/sub [:wallet/wallet-send-tx-type])
|
|
||||||
unsupported-token-in-receiver? (and (not= tx-type :tx/bridge)
|
|
||||||
(->> receiver-network-values
|
|
||||||
(remove #(= (:type %) :add))
|
|
||||||
(every? #(= (:type %) :not-available))))
|
|
||||||
suggested-routes (rf/sub [:wallet/wallet-send-suggested-routes])
|
|
||||||
routes (when suggested-routes
|
|
||||||
(or (:best suggested-routes) []))
|
|
||||||
no-routes-found? (and
|
|
||||||
(every-network-value-is-zero? sender-network-values)
|
|
||||||
(some? routes)
|
|
||||||
(not loading-routes?)
|
|
||||||
(not unsupported-token-in-receiver?))
|
|
||||||
receiver-networks (rf/sub [:wallet/wallet-send-receiver-networks])
|
|
||||||
receiver-preferred-networks (rf/sub [:wallet/wallet-send-receiver-preferred-networks])
|
|
||||||
receiver-preferred-network? (set receiver-preferred-networks)
|
|
||||||
sending-to-unpreferred-networks? (some (comp not receiver-preferred-network?)
|
|
||||||
receiver-networks)
|
|
||||||
input-error (controlled-input/input-error input-state)
|
|
||||||
limit-exceeded? (controlled-input/upper-limit-exceeded? input-state)
|
|
||||||
current-address (rf/sub [:wallet/current-viewing-account-address])
|
|
||||||
current-color (rf/sub [:wallet/current-viewing-account-color])
|
|
||||||
enough-assets? (rf/sub [:wallet/wallet-send-enough-assets?])
|
|
||||||
owned-eth-token (rf/sub [:wallet/token-by-symbol
|
|
||||||
(string/upper-case constants/mainnet-short-name)
|
|
||||||
enabled-from-chain-ids])
|
|
||||||
not-enough-asset? (insufficient-asset-amount?
|
|
||||||
{:enough-assets? enough-assets?
|
|
||||||
:token-symbol token-symbol
|
|
||||||
:owned-eth-token owned-eth-token
|
|
||||||
:input-state input-state
|
|
||||||
:no-routes-found? no-routes-found?
|
|
||||||
:limit-exceeded? limit-exceeded?
|
|
||||||
:sender-network-values sender-network-values})
|
|
||||||
should-try-again? (and (not limit-exceeded?)
|
|
||||||
no-routes-found?
|
|
||||||
(not not-enough-asset?))
|
|
||||||
show-no-routes? (and (or no-routes-found? limit-exceeded?)
|
|
||||||
(not-empty sender-network-values)
|
|
||||||
(not not-enough-asset?))
|
|
||||||
confirm-disabled? (or (nil? route)
|
|
||||||
(empty? route)
|
|
||||||
(not valid-input?))
|
|
||||||
fee-formatted (when (or (not confirm-disabled?) not-enough-asset?)
|
|
||||||
(get-fee-formatted route))
|
|
||||||
request-fetch-routes (fn [bounce-duration-ms]
|
|
||||||
(fetch-routes
|
|
||||||
{:amount amount-in-crypto
|
|
||||||
:valid-input? valid-input?
|
|
||||||
:bounce-duration-ms bounce-duration-ms
|
|
||||||
:token token
|
|
||||||
:reset-amounts-to-zero? (and limit-exceeded?
|
|
||||||
(some? routes))}))
|
|
||||||
swap-between-fiat-and-crypto (fn []
|
|
||||||
(if crypto-currency?
|
|
||||||
(set-input-state
|
|
||||||
#(controlled-input/->fiat % conversion-rate))
|
|
||||||
(set-input-state
|
|
||||||
#(controlled-input/->crypto % conversion-rate)))
|
|
||||||
(set-crypto-currency (not crypto-currency?)))]
|
|
||||||
(rn/use-effect
|
(rn/use-effect
|
||||||
(fn []
|
(fn []
|
||||||
(when active-screen?
|
(when active-screen?
|
||||||
@@ -310,125 +257,48 @@
|
|||||||
(hot-reload/use-safe-unmount on-navigate-back)
|
(hot-reload/use-safe-unmount on-navigate-back)
|
||||||
(rn/use-effect
|
(rn/use-effect
|
||||||
(fn []
|
(fn []
|
||||||
(set-input-state #(controlled-input/set-upper-limit % max-limit)))
|
(when value-out-of-limits?
|
||||||
[max-limit])
|
|
||||||
(rn/use-effect
|
|
||||||
(fn []
|
|
||||||
(when input-error
|
|
||||||
(rf/dispatch [:wallet/stop-get-suggested-routes])
|
(rf/dispatch [:wallet/stop-get-suggested-routes])
|
||||||
(debounce/clear-all)))
|
(debounce/clear-all)))
|
||||||
[input-error])
|
[value-out-of-limits?])
|
||||||
(rn/use-effect
|
(rn/use-effect
|
||||||
(fn []
|
(fn []
|
||||||
(clear-input!)
|
(rf/dispatch [:send-input-amount-screen/token-input-delete-all])
|
||||||
(rf/dispatch [:wallet/stop-and-clean-suggested-routes])
|
(rf/dispatch [:wallet/stop-and-clean-suggested-routes])
|
||||||
(rf/dispatch [:wallet/clean-disabled-from-networks]))
|
(rf/dispatch [:wallet/clean-disabled-from-networks]))
|
||||||
[current-address])
|
[current-address])
|
||||||
(rn/use-effect
|
|
||||||
(fn []
|
|
||||||
(request-fetch-routes 0))
|
|
||||||
[send-from-locked-amounts])
|
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style style/screen
|
{:style style/screen
|
||||||
:accessibility-label (str "container"
|
:accessibility-label (str "container"
|
||||||
(when (controlled-input/input-error input-state) "-error"))}
|
(when value-out-of-limits? "-error"))}
|
||||||
[account-switcher/view
|
[account-switcher/view
|
||||||
{:icon-name :i/arrow-left
|
{:icon-name :i/arrow-left
|
||||||
:on-press #(rf/dispatch [:navigate-back])
|
:on-press #(rf/dispatch [:navigate-back])
|
||||||
:switcher-type :select-account}]
|
:switcher-type :select-account}]
|
||||||
[quo/token-input
|
[token-input]
|
||||||
{:container-style style/input-container
|
[routes-view current-screen-id]
|
||||||
:token-symbol token-symbol
|
(when token-not-available?
|
||||||
:value input-value
|
[token-not-available])
|
||||||
:on-swap swap-between-fiat-and-crypto
|
|
||||||
:on-token-press show-select-asset-sheet
|
|
||||||
:error? (controlled-input/input-error input-state)
|
|
||||||
:currency-symbol (if crypto-currency? token-symbol fiat-currency)
|
|
||||||
:converted-value (if crypto-currency?
|
|
||||||
(utils/prettify-balance
|
|
||||||
currency-symbol
|
|
||||||
(money/crypto->fiat input-value
|
|
||||||
conversion-rate))
|
|
||||||
(utils/prettify-crypto-balance
|
|
||||||
(or (clj->js token-symbol) "")
|
|
||||||
(money/fiat->crypto input-value
|
|
||||||
conversion-rate)
|
|
||||||
conversion-rate))
|
|
||||||
:hint-component [quo/network-tags
|
|
||||||
{:networks (seq from-enabled-networks)
|
|
||||||
:title (i18n/label
|
|
||||||
:t/send-limit
|
|
||||||
{:limit (if crypto-currency?
|
|
||||||
(utils/prettify-crypto-balance
|
|
||||||
(or (clj->js token-symbol) "")
|
|
||||||
(controlled-input/upper-limit-bn input-state)
|
|
||||||
conversion-rate)
|
|
||||||
(utils/prettify-balance currency-symbol
|
|
||||||
(controlled-input/upper-limit-bn
|
|
||||||
input-state)))})
|
|
||||||
:status (when (controlled-input/input-error input-state) :error)}]}]
|
|
||||||
[routes/view
|
|
||||||
{:token token-by-symbol
|
|
||||||
:send-amount-in-crypto amount-in-crypto
|
|
||||||
:valid-input? valid-input?
|
|
||||||
:token-not-supported-in-receiver-networks? unsupported-token-in-receiver?
|
|
||||||
:current-screen-id current-screen-id
|
|
||||||
:request-fetch-routes request-fetch-routes}]
|
|
||||||
(when (and (not loading-routes?)
|
|
||||||
sender-network-values
|
|
||||||
unsupported-token-in-receiver?)
|
|
||||||
[token-not-available token-symbol receiver-networks token-networks])
|
|
||||||
(when not-enough-asset?
|
(when not-enough-asset?
|
||||||
[not-enough-asset])
|
[not-enough-asset])
|
||||||
(when (or (and (not no-routes-found?) (or loading-routes? route))
|
(when show-estimated-fees?
|
||||||
not-enough-asset?)
|
[estimated-fees])
|
||||||
[estimated-fees
|
|
||||||
{:loading-routes? loading-routes?
|
|
||||||
:fees fee-formatted
|
|
||||||
:amount amount-text}])
|
|
||||||
(when show-no-routes?
|
(when show-no-routes?
|
||||||
[no-routes-found])
|
[no-routes-found])
|
||||||
[quo/bottom-actions
|
[bottom-actions button-one-label button-one-props on-confirm]
|
||||||
{:actions :one-action
|
|
||||||
:button-one-label (if should-try-again?
|
|
||||||
(i18n/label :t/try-again)
|
|
||||||
button-one-label)
|
|
||||||
:button-one-props (merge (when-not should-try-again?
|
|
||||||
button-one-props)
|
|
||||||
{:disabled? (or not-enough-asset?
|
|
||||||
loading-routes?
|
|
||||||
(and (not should-try-again?)
|
|
||||||
confirm-disabled?))
|
|
||||||
:on-press (cond
|
|
||||||
should-try-again?
|
|
||||||
#(rf/dispatch [:wallet/start-get-suggested-routes
|
|
||||||
{:amount amount-in-crypto
|
|
||||||
:updated-token token-by-symbol}])
|
|
||||||
sending-to-unpreferred-networks?
|
|
||||||
#(show-unpreferred-networks-alert on-confirm)
|
|
||||||
:else
|
|
||||||
#(on-confirm amount-in-crypto))
|
|
||||||
:customization-color current-color}
|
|
||||||
(when should-try-again?
|
|
||||||
{:type :grey}))}]
|
|
||||||
[quo/numbered-keyboard
|
[quo/numbered-keyboard
|
||||||
{:container-style (style/keyboard-container bottom)
|
{:container-style (style/keyboard-container bottom)
|
||||||
:left-action :dot
|
:left-action :dot
|
||||||
:delete-key? true
|
:delete-key? true
|
||||||
:on-press (fn [c]
|
:on-press (fn [c]
|
||||||
(let [new-text (str input-value c)
|
(rf/dispatch [:send-input-amount-screen/token-input-add-character c
|
||||||
max-decimals (if crypto-currency? crypto-decimals 2)
|
max-decimals]))
|
||||||
regex-pattern (str "^\\d*\\.?\\d{0," max-decimals "}$")
|
|
||||||
regex (re-pattern regex-pattern)]
|
|
||||||
(when (re-matches regex new-text)
|
|
||||||
(debounce/clear-all)
|
|
||||||
(set-input-state #(controlled-input/add-character % c)))))
|
|
||||||
:on-delete (fn []
|
:on-delete (fn []
|
||||||
(debounce/clear-all)
|
(debounce/clear-all)
|
||||||
(set-input-state controlled-input/delete-last)
|
(rf/dispatch [:send-input-amount-screen/token-input-delete-last])
|
||||||
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes]))
|
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes]))
|
||||||
:on-long-press-delete (fn []
|
:on-long-press-delete (fn []
|
||||||
(debounce/clear-all)
|
(debounce/clear-all)
|
||||||
(set-input-state controlled-input/delete-all)
|
(rf/dispatch [:send-input-amount-screen/token-input-delete-all])
|
||||||
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes]))}]]))
|
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes]))}]]))
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,14 @@
|
|||||||
(defn view
|
(defn view
|
||||||
[]
|
[]
|
||||||
[input-amount/view
|
[input-amount/view
|
||||||
{:current-screen-id :screen/wallet.send-input-amount
|
{:current-screen-id :screen/wallet.send-input-amount
|
||||||
:button-one-label (i18n/label :t/review-send)
|
:button-one-label (i18n/label :t/review-send)
|
||||||
:enabled-from-chain-ids (rf/sub [:wallet/wallet-send-enabled-from-chain-ids])
|
:on-confirm (fn [amount]
|
||||||
:from-enabled-networks (rf/sub [:wallet/wallet-send-enabled-networks])
|
(rf/dispatch [:wallet/set-token-amount-to-send
|
||||||
:on-navigate-back (fn []
|
{:amount amount
|
||||||
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes])
|
:stack-id :screen/wallet.send-input-amount}]))
|
||||||
(rf/dispatch [:wallet/clean-disabled-from-networks])
|
:on-navigate-back (fn []
|
||||||
(rf/dispatch [:wallet/clean-from-locked-amounts])
|
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes])
|
||||||
(rf/dispatch [:wallet/clean-send-amount]))}])
|
(rf/dispatch [:wallet/clean-disabled-from-networks])
|
||||||
|
(rf/dispatch [:wallet/clean-from-locked-amounts])
|
||||||
|
(rf/dispatch [:wallet/clean-send-amount]))}])
|
||||||
|
|||||||
@@ -223,7 +223,7 @@
|
|||||||
bridge-to-chain-id]))
|
bridge-to-chain-id]))
|
||||||
loading-suggested-routes? (rf/sub
|
loading-suggested-routes? (rf/sub
|
||||||
[:wallet/wallet-send-loading-suggested-routes?])
|
[:wallet/wallet-send-loading-suggested-routes?])
|
||||||
total-amount-receiver (rf/sub [:wallet/total-amount true])
|
total-amount-receiver (rf/sub [:wallet/total-amount-in-to-chains])
|
||||||
from-account-props {:customization-color account-color
|
from-account-props {:customization-color account-color
|
||||||
:size 32
|
:size 32
|
||||||
:emoji (:emoji account)
|
:emoji (:emoji account)
|
||||||
|
|||||||
@@ -76,14 +76,13 @@
|
|||||||
network-values))))
|
network-values))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:wallet/total-amount
|
:wallet/total-amount-in-to-chains
|
||||||
:<- [:wallet/wallet-send]
|
:<- [:wallet/wallet-send]
|
||||||
(fn [{:keys [from-values-by-chain to-values-by-chain]} [_ to-values?]]
|
(fn [{:keys [to-values-by-chain]}]
|
||||||
(let [network-values (if to-values? to-values-by-chain from-values-by-chain)]
|
(reduce
|
||||||
(reduce
|
(fn [acc amount]
|
||||||
(fn [acc amount]
|
(if (money/bignumber? amount)
|
||||||
(if (money/bignumber? amount)
|
(money/add acc amount)
|
||||||
(money/add acc amount)
|
acc))
|
||||||
acc))
|
(money/bignumber 0)
|
||||||
(money/bignumber 0)
|
(vals to-values-by-chain))))
|
||||||
(vals network-values)))))
|
|
||||||
|
|||||||
@@ -0,0 +1,360 @@
|
|||||||
|
(ns status-im.subs.wallet.screens.input-amount
|
||||||
|
(:require
|
||||||
|
[clojure.string :as string]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
[status-im.contexts.wallet.common.utils :as utils]
|
||||||
|
[status-im.contexts.wallet.send.input-amount.controlled-input-logic :as controlled-input-logic]
|
||||||
|
[utils.money :as money]
|
||||||
|
[utils.number :as number]
|
||||||
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/state
|
||||||
|
:<- [:wallet/wallet-screens]
|
||||||
|
:-> :input-amount-screen)
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/enabled-from-chain-ids
|
||||||
|
:<- [:wallet/wallet-send-tx-type]
|
||||||
|
:<- [:wallet/wallet-send-enabled-from-chain-ids]
|
||||||
|
:<- [:wallet/bridge-from-chain-ids]
|
||||||
|
(fn [[tx-type send-chain-ids bridge-chain-ids]]
|
||||||
|
(if (= tx-type :tx/bridge)
|
||||||
|
bridge-chain-ids
|
||||||
|
send-chain-ids)))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/from-enabled-networks
|
||||||
|
:<- [:wallet/wallet-send-tx-type]
|
||||||
|
:<- [:wallet/wallet-send-enabled-networks]
|
||||||
|
:<- [:wallet/bridge-from-networks]
|
||||||
|
(fn [[tx-type send-enabled-networks bridge-enabled-networks]]
|
||||||
|
(if (= tx-type :tx/bridge)
|
||||||
|
bridge-enabled-networks
|
||||||
|
send-enabled-networks)))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/token-by-symbol
|
||||||
|
:<- [:send-input-amount-screen/enabled-from-chain-ids]
|
||||||
|
:<- [:wallet/wallet-send-token]
|
||||||
|
(fn [[enabled-from-chain-ids
|
||||||
|
{token-symbol :symbol}]]
|
||||||
|
(rf/sub [:wallet/token-by-symbol
|
||||||
|
(str token-symbol)
|
||||||
|
enabled-from-chain-ids])))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/total-balance
|
||||||
|
:<- [:send-input-amount-screen/token-by-symbol]
|
||||||
|
(fn [{:keys [total-balance]}]
|
||||||
|
total-balance))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/conversion-rate
|
||||||
|
:<- [:wallet/wallet-send-token]
|
||||||
|
:<- [:profile/currency]
|
||||||
|
(fn [[token
|
||||||
|
currency]]
|
||||||
|
(-> token
|
||||||
|
:market-values-per-currency
|
||||||
|
currency
|
||||||
|
:price)))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/usd-conversion-rate
|
||||||
|
:<- [:wallet/wallet-send-token]
|
||||||
|
(fn [token]
|
||||||
|
(utils/token-usd-price token)))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/token-decimals
|
||||||
|
:<- [:wallet/wallet-send-token]
|
||||||
|
(fn [token]
|
||||||
|
(-> token
|
||||||
|
utils/token-usd-price
|
||||||
|
utils/one-cent-value
|
||||||
|
utils/calc-max-crypto-decimals)))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/max-decimals
|
||||||
|
:<- [:send-input-amount-screen/state]
|
||||||
|
:<- [:send-input-amount-screen/token-decimals]
|
||||||
|
(fn [[{:keys [crypto-currency?]}
|
||||||
|
token-decimals]]
|
||||||
|
(if crypto-currency? token-decimals 2)))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/upper-limit
|
||||||
|
:<- [:send-input-amount-screen/state]
|
||||||
|
:<- [:send-input-amount-screen/conversion-rate]
|
||||||
|
:<- [:send-input-amount-screen/usd-conversion-rate]
|
||||||
|
:<- [:send-input-amount-screen/total-balance]
|
||||||
|
(fn [[{:keys [crypto-currency?]}
|
||||||
|
conversion-rate
|
||||||
|
usd-conversion-rate
|
||||||
|
total-balance]]
|
||||||
|
(if crypto-currency?
|
||||||
|
(utils/cut-crypto-decimals-to-fit-usd-cents
|
||||||
|
total-balance
|
||||||
|
usd-conversion-rate)
|
||||||
|
(utils/cut-fiat-balance-to-two-decimals
|
||||||
|
(money/crypto->fiat total-balance conversion-rate)))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/upper-limit-prettified
|
||||||
|
:<- [:send-input-amount-screen/state]
|
||||||
|
:<- [:profile/currency-symbol]
|
||||||
|
:<- [:wallet/wallet-send-token]
|
||||||
|
:<- [:send-input-amount-screen/conversion-rate]
|
||||||
|
:<- [:send-input-amount-screen/upper-limit]
|
||||||
|
(fn [[{:keys [crypto-currency?]}
|
||||||
|
currency-symbol
|
||||||
|
{token-symbol :symbol}
|
||||||
|
conversion-rate
|
||||||
|
upper-limit]]
|
||||||
|
(if crypto-currency?
|
||||||
|
(utils/prettify-crypto-balance
|
||||||
|
(or (clj->js token-symbol) "")
|
||||||
|
(money/bignumber upper-limit)
|
||||||
|
conversion-rate)
|
||||||
|
(utils/prettify-balance currency-symbol
|
||||||
|
(money/bignumber upper-limit)))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/upper-limit-exceeded?
|
||||||
|
:<- [:send-input-amount-screen/state]
|
||||||
|
:<- [:send-input-amount-screen/upper-limit]
|
||||||
|
(fn [[{:keys [input-value]}
|
||||||
|
upper-limit]]
|
||||||
|
(controlled-input-logic/upper-limit-exceeded?
|
||||||
|
input-value
|
||||||
|
upper-limit)))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/value-out-of-limits?
|
||||||
|
:<- [:send-input-amount-screen/state]
|
||||||
|
:<- [:send-input-amount-screen/upper-limit]
|
||||||
|
(fn [[{:keys [input-value]}
|
||||||
|
upper-limit]]
|
||||||
|
(controlled-input-logic/value-out-of-limits? input-value upper-limit 0)))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/valid-input?
|
||||||
|
:<- [:send-input-amount-screen/state]
|
||||||
|
:<- [:send-input-amount-screen/value-out-of-limits?]
|
||||||
|
(fn [[{:keys [input-value]}
|
||||||
|
value-out-of-limits?]]
|
||||||
|
(not (or (controlled-input-logic/empty-value? input-value) value-out-of-limits?))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/upper-limit-equals-input-value?
|
||||||
|
:<- [:send-input-amount-screen/state]
|
||||||
|
:<- [:send-input-amount-screen/upper-limit]
|
||||||
|
(fn [[{:keys [input-value]}
|
||||||
|
upper-limit]]
|
||||||
|
(money/equal-to
|
||||||
|
(money/bignumber input-value)
|
||||||
|
(money/bignumber upper-limit))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn- fiat->crypto
|
||||||
|
[value conversion-rate]
|
||||||
|
(-> value
|
||||||
|
(money/fiat->crypto conversion-rate)
|
||||||
|
(utils/cut-crypto-decimals-to-fit-usd-cents conversion-rate)))
|
||||||
|
|
||||||
|
(defn- crypto->fiat
|
||||||
|
[value conversion-rate]
|
||||||
|
(-> value
|
||||||
|
(money/crypto->fiat conversion-rate)
|
||||||
|
(utils/cut-fiat-balance-to-two-decimals)))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/input-value-converted
|
||||||
|
:<- [:send-input-amount-screen/state]
|
||||||
|
:<- [:send-input-amount-screen/conversion-rate]
|
||||||
|
(fn [[{:keys [crypto-currency? input-value]}
|
||||||
|
conversion-rate]]
|
||||||
|
(if crypto-currency?
|
||||||
|
(crypto->fiat input-value conversion-rate)
|
||||||
|
(fiat->crypto input-value conversion-rate))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/converted-value-prettified
|
||||||
|
:<- [:send-input-amount-screen/state]
|
||||||
|
:<- [:send-input-amount-screen/input-value-converted]
|
||||||
|
:<- [:profile/currency-symbol]
|
||||||
|
:<- [:wallet/wallet-send-token]
|
||||||
|
(fn [[{:keys [crypto-currency?]}
|
||||||
|
token-input-converted-value
|
||||||
|
currency-symbol
|
||||||
|
{token-symbol :symbol}]]
|
||||||
|
(if crypto-currency?
|
||||||
|
(utils/prepend-curency-symbol-to-fiat-balance token-input-converted-value currency-symbol)
|
||||||
|
(utils/add-token-symbol-to-crypto-balance token-input-converted-value
|
||||||
|
(or (clj->js token-symbol) "")))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/amount-in-crypto
|
||||||
|
:<- [:send-input-amount-screen/state]
|
||||||
|
:<- [:send-input-amount-screen/conversion-rate]
|
||||||
|
:<- [:send-input-amount-screen/token-decimals]
|
||||||
|
(fn [[{:keys [crypto-currency? input-value]}
|
||||||
|
conversion-rate
|
||||||
|
token-decimals]]
|
||||||
|
(if crypto-currency?
|
||||||
|
input-value
|
||||||
|
(number/remove-trailing-zeroes
|
||||||
|
(.toFixed (/ input-value conversion-rate) token-decimals)))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/recipient-gets-amount
|
||||||
|
:<- [:send-input-amount-screen/conversion-rate]
|
||||||
|
:<- [:wallet/total-amount-in-to-chains]
|
||||||
|
:<- [:wallet/wallet-send-token]
|
||||||
|
(fn [[conversion-rate
|
||||||
|
total-amount-receiver
|
||||||
|
{token-symbol :symbol}]]
|
||||||
|
(utils/prettify-crypto-balance
|
||||||
|
token-symbol
|
||||||
|
total-amount-receiver
|
||||||
|
conversion-rate)))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/routes
|
||||||
|
:<- [:wallet/wallet-send-suggested-routes]
|
||||||
|
(fn [suggested-routes]
|
||||||
|
(when suggested-routes
|
||||||
|
(or (:best suggested-routes) []))))
|
||||||
|
|
||||||
|
(defn- every-network-value-is-zero?
|
||||||
|
[sender-network-values]
|
||||||
|
(every? (fn [{:keys [total-amount]}]
|
||||||
|
(and
|
||||||
|
total-amount
|
||||||
|
(money/bignumber? total-amount)
|
||||||
|
(money/equal-to total-amount
|
||||||
|
(money/bignumber "0"))))
|
||||||
|
sender-network-values))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/unsupported-token-in-receiver?
|
||||||
|
:<- [:wallet/wallet-send-receiver-network-values]
|
||||||
|
:<- [:wallet/wallet-send-tx-type]
|
||||||
|
(fn [[receiver-network-values
|
||||||
|
tx-type]]
|
||||||
|
(and (not= tx-type :tx/bridge)
|
||||||
|
(->> receiver-network-values
|
||||||
|
(remove #(= (:type %) :add))
|
||||||
|
(every? #(= (:type %) :not-available))))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/no-routes-found?
|
||||||
|
:<- [:wallet/wallet-send-sender-network-values]
|
||||||
|
:<- [:send-input-amount-screen/routes]
|
||||||
|
:<- [:wallet/wallet-send-loading-suggested-routes?]
|
||||||
|
:<- [:send-input-amount-screen/unsupported-token-in-receiver?]
|
||||||
|
(fn [[sender-network-values
|
||||||
|
routes
|
||||||
|
loading-routes?
|
||||||
|
unsupported-token-in-receiver?]]
|
||||||
|
(and
|
||||||
|
(every-network-value-is-zero? sender-network-values)
|
||||||
|
(some? routes)
|
||||||
|
(not loading-routes?)
|
||||||
|
(not unsupported-token-in-receiver?))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/sending-to-unpreferred-networks?
|
||||||
|
:<- [:wallet/wallet-send-receiver-networks]
|
||||||
|
:<- [:wallet/wallet-send-receiver-preferred-networks]
|
||||||
|
(fn [[receiver-networks
|
||||||
|
receiver-preferred-networks]]
|
||||||
|
(some (comp not (set receiver-preferred-networks)) receiver-networks)))
|
||||||
|
|
||||||
|
(defn- insufficient-asset-amount?
|
||||||
|
[{:keys [token-symbol owned-eth-token upper-limit-equals-input-value? no-routes-found? limit-exceeded?
|
||||||
|
sender-network-values enough-assets?]}]
|
||||||
|
(let [eth-selected? (= token-symbol (string/upper-case constants/mainnet-short-name))
|
||||||
|
zero-owned-eth? (money/equal-to (:total-balance owned-eth-token) 0)
|
||||||
|
exceeded-input? (if eth-selected?
|
||||||
|
upper-limit-equals-input-value?
|
||||||
|
zero-owned-eth?)]
|
||||||
|
(and (or no-routes-found? limit-exceeded?)
|
||||||
|
(seq sender-network-values)
|
||||||
|
(or exceeded-input? (not enough-assets?)))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/not-enough-asset?
|
||||||
|
:<- [:wallet/wallet-send-sender-network-values]
|
||||||
|
:<- [:wallet/wallet-send-enough-assets?]
|
||||||
|
:<- [:wallet/wallet-send-token]
|
||||||
|
:<- [:send-input-amount-screen/upper-limit-equals-input-value?]
|
||||||
|
:<- [:send-input-amount-screen/no-routes-found?]
|
||||||
|
:<- [:send-input-amount-screen/upper-limit-exceeded?]
|
||||||
|
:<- [:send-input-amount-screen/enabled-from-chain-ids]
|
||||||
|
(fn [[sender-network-values
|
||||||
|
enough-assets?
|
||||||
|
{token-symbol :symbol}
|
||||||
|
upper-limit-equals-input-value?
|
||||||
|
no-routes-found?
|
||||||
|
limit-exceeded?
|
||||||
|
enabled-from-chain-ids]]
|
||||||
|
(let [owned-eth-token (rf/sub [:wallet/token-by-symbol
|
||||||
|
(string/upper-case constants/mainnet-short-name)
|
||||||
|
enabled-from-chain-ids])]
|
||||||
|
(insufficient-asset-amount?
|
||||||
|
{:enough-assets? enough-assets?
|
||||||
|
:token-symbol token-symbol
|
||||||
|
:owned-eth-token owned-eth-token
|
||||||
|
:upper-limit-equals-input-value? upper-limit-equals-input-value?
|
||||||
|
:no-routes-found? no-routes-found?
|
||||||
|
:limit-exceeded? limit-exceeded?
|
||||||
|
:sender-network-values sender-network-values}))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/should-try-again?
|
||||||
|
:<- [:send-input-amount-screen/upper-limit-exceeded?]
|
||||||
|
:<- [:send-input-amount-screen/no-routes-found?]
|
||||||
|
:<- [:send-input-amount-screen/not-enough-asset?]
|
||||||
|
(fn [[limit-exceeded?
|
||||||
|
no-routes-found?
|
||||||
|
not-enough-asset?]]
|
||||||
|
(and (not limit-exceeded?)
|
||||||
|
no-routes-found?
|
||||||
|
(not not-enough-asset?))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/show-no-routes?
|
||||||
|
:<- [:send-input-amount-screen/upper-limit-exceeded?]
|
||||||
|
:<- [:send-input-amount-screen/no-routes-found?]
|
||||||
|
:<- [:send-input-amount-screen/not-enough-asset?]
|
||||||
|
:<- [:wallet/wallet-send-sender-network-values]
|
||||||
|
(fn [[limit-exceeded?
|
||||||
|
no-routes-found?
|
||||||
|
not-enough-asset?
|
||||||
|
sender-network-values]]
|
||||||
|
(and (or no-routes-found? limit-exceeded?)
|
||||||
|
(not-empty sender-network-values)
|
||||||
|
(not not-enough-asset?))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/confirm-disabled?
|
||||||
|
:<- [:wallet/wallet-send-route]
|
||||||
|
:<- [:send-input-amount-screen/valid-input?]
|
||||||
|
(fn [[route
|
||||||
|
valid-input?]]
|
||||||
|
(or (nil? route)
|
||||||
|
(empty? route)
|
||||||
|
(not valid-input?))))
|
||||||
|
|
||||||
|
(defn- get-fee-formatted
|
||||||
|
[route]
|
||||||
|
(when-let [native-currency-symbol (-> route first :from :native-currency-symbol)]
|
||||||
|
(rf/sub [:wallet/wallet-send-fee-fiat-formatted native-currency-symbol])))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/fee-formatted
|
||||||
|
:<- [:wallet/wallet-send-route]
|
||||||
|
:<- [:send-input-amount-screen/confirm-disabled?]
|
||||||
|
:<- [:send-input-amount-screen/not-enough-asset?]
|
||||||
|
(fn [[route
|
||||||
|
confirm-disabled?
|
||||||
|
not-enough-asset?]]
|
||||||
|
(when (or (not confirm-disabled?) not-enough-asset?)
|
||||||
|
(get-fee-formatted route))))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/show-estimated-fees?
|
||||||
|
:<- [:wallet/wallet-send-route]
|
||||||
|
:<- [:send-input-amount-screen/no-routes-found?]
|
||||||
|
:<- [:send-input-amount-screen/not-enough-asset?]
|
||||||
|
:<- [:wallet/wallet-send-loading-suggested-routes?]
|
||||||
|
(fn [[route
|
||||||
|
no-routes-found?
|
||||||
|
not-enough-asset?
|
||||||
|
loading-routes?]]
|
||||||
|
(or (and (not no-routes-found?) (or loading-routes? route))
|
||||||
|
not-enough-asset?)))
|
||||||
|
|
||||||
|
(rf/reg-sub :send-input-amount-screen/token-not-available?
|
||||||
|
:<- [:wallet/wallet-send-sender-network-values]
|
||||||
|
:<- [:send-input-amount-screen/unsupported-token-in-receiver?]
|
||||||
|
:<- [:wallet/wallet-send-loading-suggested-routes?]
|
||||||
|
(fn [[sender-network-values unsupported-token-in-receiver?
|
||||||
|
loading-routes?]]
|
||||||
|
(and (not loading-routes?)
|
||||||
|
sender-network-values
|
||||||
|
unsupported-token-in-receiver?)))
|
||||||
|
|
||||||
@@ -16,6 +16,11 @@
|
|||||||
:<- [:wallet/ui]
|
:<- [:wallet/ui]
|
||||||
:-> :send)
|
:-> :send)
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet/wallet-screens
|
||||||
|
:<- [:wallet/ui]
|
||||||
|
:-> :screens)
|
||||||
|
|
||||||
(rf/reg-sub
|
(rf/reg-sub
|
||||||
:wallet/send-recipient
|
:wallet/send-recipient
|
||||||
:<- [:wallet/wallet-send]
|
:<- [:wallet/wallet-send]
|
||||||
|
|||||||
Reference in New Issue
Block a user