Compare commits

..
Author SHA1 Message Date
Ulises M 9fbf140da0 WIP: debugging 2024-10-29 14:01:21 -06:00
Ulises M e9b8118c0d Add config paths 2024-10-28 13:34:47 -06:00
Ulises M 80c15bd8d0 Code cleaning
WIP: problems porting native modules with no callback

WIP: status backend integration

WIP: status-backend integration
2024-10-28 12:12:03 -06:00
25 changed files with 547 additions and 734 deletions
+9
View File
@@ -88,6 +88,15 @@
{:chainId :chain-id
:removed :removed?})
name-details)]
(let [new-db (reduce (fn [db {:keys [username removed? chain-id] :as name-detail}]
(if removed?
(update-in db [:ens/names chain-id] dissoc username)
(let [old (get-in db [:ens/names chain-id username])]
(assoc-in db [:ens/names chain-id username] (merge old name-detail)))))
db
name-details)]
(prn "new db" new-db)
)
{:db (reduce (fn [db {:keys [username removed? chain-id] :as name-detail}]
(if removed?
(update-in db [:ens/names chain-id] dissoc username)
+64 -24
View File
@@ -4,6 +4,8 @@
[clojure.string :as string]
[native-module.utils :as native-utils]
[react-native.platform :as platform]
[status-backend.core :as status-backend]
[status-backend.config :as status-backend.config]
[taoensso.timbre :as log]
[utils.transforms :as types]))
@@ -14,18 +16,24 @@
(defn account-manager
[]
(when (exists? (.-NativeModules react-native))
(.-AccountManager ^js (.-NativeModules react-native))))
(if false
(when (exists? (.-NativeModules react-native))
(.-AccountManager ^js (.-NativeModules react-native)))
status-backend/fetch-js-obj))
(defn encryption
[]
(when (exists? (.-NativeModules react-native))
(.-EncryptionUtils ^js (.-NativeModules react-native))))
(if false
(when (exists? (.-NativeModules react-native))
(.-EncryptionUtils ^js (.-NativeModules react-native)))
status-backend/fetch-js-obj))
(defn database
[]
(when (exists? (.-NativeModules react-native))
(.-DatabaseManager ^js (.-NativeModules react-native))))
(if false
(when (exists? (.-NativeModules react-native))
(.-DatabaseManager ^js (.-NativeModules react-native)))
status-backend/fetch-js-obj))
(defn ui-helper
[]
@@ -34,23 +42,31 @@
(defn log-manager
[]
(when (exists? (.-NativeModules react-native))
(.-LogManager ^js (.-NativeModules react-native))))
(if false
(when (exists? (.-NativeModules react-native))
(.-LogManager ^js (.-NativeModules react-native)))
status-backend/fetch-js-obj))
(defn utils
[]
(when (exists? (.-NativeModules react-native))
(.-Utils ^js (.-NativeModules react-native))))
(if false
(when (exists? (.-NativeModules react-native))
(.-Utils ^js (.-NativeModules react-native)))
status-backend/fetch-js-obj))
(defn network
[]
(when (exists? (.-NativeModules react-native))
(.-NetworkManager ^js (.-NativeModules react-native))))
(if false
(when (exists? (.-NativeModules react-native))
(.-NetworkManager ^js (.-NativeModules react-native)))
status-backend/fetch-js-obj))
(defn mail-manager
[]
(when (exists? (.-NativeModules react-native))
(.-MailManager ^js (.-NativeModules react-native))))
(if false
(when (exists? (.-NativeModules react-native))
(.-MailManager ^js (.-NativeModules react-native)))
status-backend/fetch-js-obj))
(defn mail
[opts callback]
@@ -58,7 +74,9 @@
(defn init
[handler]
(.addListener ^js (.-DeviceEventEmitter ^js react-native) "gethEvent" #(handler (.-jsonEvent ^js %))))
(if false
(.addListener ^js (.-DeviceEventEmitter ^js react-native) "gethEvent" #(handler (.-jsonEvent ^js %)))
(status-backend/init-web-socket handler)))
(defn clear-web-data
[]
@@ -340,7 +358,9 @@
(log/debug "[native-module] set-blank-preview-flag")
;; Sometimes the app crashes during logout because `flag` is nil.
(when-not (nil? flag)
(.setBlankPreviewFlag ^js (encryption) flag)))
(.setBlankPreviewFlag ^js (when (exists? (.-NativeModules react-native))
(.-EncryptionUtils ^js (.-NativeModules react-native)))
flag)))
(defn get-device-model-info
[]
@@ -419,8 +439,11 @@
(defn sha3
[s]
(log/debug "[native-module] sha3")
(when s
(.sha3 ^js (encryption) (str s))))
(time
(let [temp-encryption (when (exists? (.-NativeModules react-native))
(.-EncryptionUtils ^js (.-NativeModules react-native)))]
(when s
(.sha3 ^js temp-encryption (str s))))))
(defn utf8-to-hex
[s]
@@ -444,7 +467,8 @@
(defn add-centralized-metric
[metric]
(.addCentralizedMetric ^js (status) (types/clj->json metric) #(log/debug "pushed metric" % metric)))
(.addCentralizedMetric ^js (status) (types/clj->json metric)
(fn []) #_(log/debug "pushed metric" % metric)))
(defn address?
[address]
@@ -456,7 +480,9 @@
(defn to-checksum-address
[address]
(log/debug "[native-module] to-checksum-address")
(.toChecksumAddress ^js (utils) address))
(.toChecksumAddress ^js (when (exists? (.-NativeModules react-native))
(.-Utils ^js (.-NativeModules react-native)))
address))
(defn validate-mnemonic
"Validate that a mnemonic conforms to BIP39 dictionary/checksum standards"
@@ -522,7 +548,9 @@
(defn backup-disabled-data-dir
[]
(.backupDisabledDataDir ^js (utils)))
(if false ;; Check for not use of status-backend
(.backupDisabledDataDir ^js (utils))
status-backend.config/data-dir-path))
(defn fleets
[]
@@ -530,15 +558,27 @@
(defn keystore-dir
[]
(.keystoreDir ^js (utils)))
(if false
(.keystoreDir ^js (utils))
status-backend.config/keystore-dir-path))
(defn log-file-directory
[]
(.logFileDirectory ^js (log-manager)))
(if false
(.logFileDirectory ^js (log-manager))
status-backend.config/log-dir-path))
(defn init-status-go-logging
[{:keys [enable? mobile-system? log-level log-request-go? callback]}]
(.initLogging ^js (log-manager) enable? mobile-system? log-level log-request-go? callback))
(if false
(.initLogging ^js (log-manager) enable? mobile-system? log-level log-request-go? callback)
(.initLogging ^js (log-manager)
{:Enabled enable?
:MobileSystem mobile-system?
:Level log-level
:LogRequestGo log-request-go?
:LogRequestFile status-backend.config/log-request-file-path}
callback)))
(defn get-random-mnemonic
[callback]
+24
View File
@@ -0,0 +1,24 @@
(ns status-backend.config)
;; Before run:
;; adb reverse tcp:9050 tcp:9050
;; TODO: these should be read from env vars
(def ^:private address "localhost")
(def ^:private port 9050)
(def ^:private url (str "http://" address ":" port))
(def status-go-url (str url "/statusgo/"))
(def signals-url (str url "/signals"))
(def fetch-default-params
{:method :POST
:headers {"Accept" "application/json"
"Content-Type" "application/json"}})
;; This dir musts exist before running the app
(def data-dir-path "/home/ulises/p/status-go/1_test-db")
(def keystore-dir-path "/home/ulises/p/status-go/1_test-db/1_keystore")
(def log-dir-path "/home/ulises/p/status-go/requests.log")
(def log-request-file-path (str data-dir-path "/requests.log"))
+86
View File
@@ -0,0 +1,86 @@
(ns status-backend.core
(:require
[status-backend.config :as config]
[utils.network.core :as network]
[clojure.string :as string]
[oops.core :as oops]
[taoensso.timbre :as log]))
(defn fetch
([endpoint]
(println (str ".......................... 1-----: " endpoint))
(fetch endpoint nil (fn [])))
([endpoint body-params]
(println (str ".......................... 2-----: " endpoint))
(fetch endpoint body-params (fn [])))
([endpoint body-params callback]
(println (str "========================== > INVOKE: " endpoint "::" (prn-str body-params)))
(let [url (str config/status-go-url endpoint)
params (assoc config/fetch-default-params :body body-params)]
(network/fetch url params callback))))
(defn- method-name->endpoint [s]
(let [first-letter-capitalized (string/capitalize (first s))]
(str first-letter-capitalized (subs s 1))))
(def fetch-js-obj
"Performs a request to the status-backend (by using `status-backend.core/fetch`) using
the method invoked as endpoint name. E.g
This call: (.myMethod fetch-js-obj params)
Is the same as: (fetch \"MyMethod\" params)
"
(js/Proxy. #js{}
#js{:get (fn [_target native-module-method-name]
(let [endpoint (method-name->endpoint native-module-method-name)]
(partial fetch endpoint)))}))
(declare web-socket)
(defn init-web-socket [on-message]
(defonce web-socket (js/WebSocket. config/signals-url))
(oops/oset! web-socket "onopen" #(log/debug "[backend] Web Socket connected"))
(oops/oset! web-socket "onmessage" (fn [e]
(println " NEW WEBSOCKET MESSAGE! -- START")
(-> e (oops/oget "data") (on-message))
(println " NEW WEBSOCKET MESSAGE! -- END")))
(oops/oset! web-socket "onerror" #(log/error "[backend] Web Socket error" %))
(oops/oset! web-socket "onclose" #(log/error "[backend] Web Socket closed" %)))
;(defn call-private-rpc [payload callback]
; ;; NOTE: according to the status-backend readme, we call RPCs using the `CallRPC`
; ;; endpoint, instead of using `CallPrivateRPC` as in mobile.
; (fetch "CallRPC" payload callback))
(comment ;; Useful REPL commands (will be removed)
;; STEP 1: Initialize the app
;; Option 1: Method call
(.initializeApplication ^js fetch-js-obj
(utils.transforms/clj->json {:dataDir "/home/ulises/p/status-go/test-db" ;; Put your dir
:mixpanelAppId status-im.config/mixpanel-app-id
:mixpanelToken status-im.config/mixpanel-token})
(fn [raw-response]
(let [result (utils.transforms/json->clj raw-response)]
(js/alert (prn-str result)))))
;; Option 2: calling fetch
(fetch "InitializeApplication"
{:dataDir "/home/ulises/p/status-go/test-db"
:mixpanelAppId status-im.config/mixpanel-app-id
:mixpanelToken status-im.config/mixpanel-token}
(fn [response]
(js/alert (prn-str response))))
;; STEP 2 "Create a Profile and Log in
(let [body (-> (status-im.contexts.profile.config/create)
(assoc :displayName "Sonic"
:password (native-module.core/sha3 "Hola1234.,")
:imagePath nil
:customizationColor :army))]
(fetch "CreateAccountAndLogin"
body
(fn [response]
(def --r response)
(js/alert (str "HTTP-RESPONSE:\n" (js/JSON.stringify response)))))))
+1
View File
@@ -25,6 +25,7 @@
(rf/defn process
{:events [:signals/signal-received]}
[{:keys [db] :as cofx} event-str]
(println (str "<<<<<<<<<<<<<<<<<<<<<<<<<< SIGNAL: " (prn-str event-str)))
;; We only convert to clojure when strictly necessary or we know it
;; won't impact performance, as it is a fairly costly operation on large-ish
;; data structures
@@ -16,7 +16,7 @@
[context]
(when (push-event? (interceptor/get-coeffect context :db))
(when-let [event (tracking/metrics-event (interceptor/get-coeffect context :event))]
(log/debug "tracking event" event)
#_(log/debug "tracking event" event)
(if (or (seq? event) (vector? event))
(doseq [e event]
(native-module/add-centralized-metric e))
@@ -87,7 +87,7 @@
:screen/onboarding.new-to-status)]]]
(when-not syncing-account-recovered?
[:dispatch [:syncing/clear-syncing-installation-id]])]
:dispatch-later [{:ms constants/onboarding-generating-keys-animation-duration-ms
:dispatch-later [#_{:ms constants/onboarding-generating-keys-animation-duration-ms
:dispatch [:navigate-to-within-stack
[:screen/onboarding.enable-notifications
loading-screen]]}]
@@ -65,7 +65,7 @@
(defn title
[]
(let [generate-keys-opacity (reanimated/use-shared-value 1)
#_(let [generate-keys-opacity (reanimated/use-shared-value 1)
saving-keys-opacity (reanimated/use-shared-value 0)
keys-saved-opacity (reanimated/use-shared-value 0)]
(sequence-animation generate-keys-opacity saving-keys-opacity keys-saved-opacity)
@@ -86,7 +86,8 @@
{:style (reanimated/apply-animations-to-style
{:opacity keys-saved-opacity}
style/title-style)}
[keys-saved-title]]]))
[keys-saved-title]]])
)
(defn content
[]
@@ -156,7 +156,9 @@
{:db (update db :profile/login #(-> % (dissoc :processing) (assoc :error error)))}
{:db (dissoc db :profile/login)
:fx [(when (and new-account? (not recovered-account?))
[:dispatch-later [{:ms 1000 :dispatch [:wallet-legacy/set-initial-blocks-range]}]])
;; INVALID EVENT:
;[:dispatch-later [{:ms 1000 :dispatch [:wallet-legacy/set-initial-blocks-range]}]]
)
[:dispatch-later [{:ms 2000 :dispatch [:ens/update-usernames ensUsernames]}]]
[:dispatch [:profile.login/login-existing-profile settings account]]]})))
@@ -10,14 +10,17 @@
[]
[rn/view {:style style/bridge-send-wrapper}
[input-amount/view
{:current-screen-id :screen/wallet.bridge-input-amount
:button-one-label (i18n/label :t/review-bridge)
:button-one-props {:icon-left :i/bridge}
:on-confirm (fn [amount]
(rf/dispatch [:wallet/set-token-amount-to-bridge
{:amount amount
:stack-id :screen/wallet.bridge-input-amount}]))
:on-navigate-back (fn []
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes])
(rf/dispatch [:wallet/clean-disabled-from-networks])
(rf/dispatch [:wallet/clean-send-amount]))}]])
{:current-screen-id :screen/wallet.bridge-input-amount
:button-one-label (i18n/label :t/review-bridge)
:button-one-props {:icon-left :i/bridge}
:enabled-from-chain-ids (rf/sub
[:wallet/bridge-from-chain-ids])
:from-enabled-networks (rf/sub [:wallet/bridge-from-networks])
:on-confirm (fn [amount]
(rf/dispatch [:wallet/set-token-amount-to-bridge
{:amount amount
:stack-id :screen/wallet.bridge-input-amount}]))
:on-navigate-back (fn []
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes])
(rf/dispatch [:wallet/clean-disabled-from-networks])
(rf/dispatch [:wallet/clean-send-amount]))}]])
@@ -27,18 +27,12 @@
[balance]
(cut-fiat-balance balance 2))
(defn prepend-curency-symbol-to-fiat-balance
[fiat-balance currency-symbol]
(defn prettify-balance
[currency-symbol balance]
(let [formatted-symbol (if (> (count currency-symbol) 1)
(str currency-symbol " ")
currency-symbol)]
(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)))
(str formatted-symbol (cut-fiat-balance-to-two-decimals balance))))
(defn get-derivation-path
[number-of-accounts]
@@ -110,15 +104,11 @@
:else (number/remove-trailing-zeroes
(.toFixed token-units standardized-decimals-count)))))
(defn add-token-symbol-to-crypto-balance
[crypto-balance token-symbol]
(str crypto-balance " " (string/upper-case token-symbol)))
(defn prettify-crypto-balance
[token-symbol crypto-balance conversion-rate]
(-> crypto-balance
(cut-crypto-decimals-to-fit-usd-cents conversion-rate)
(add-token-symbol-to-crypto-balance token-symbol)))
(str (cut-crypto-decimals-to-fit-usd-cents crypto-balance conversion-rate)
" "
(string/upper-case token-symbol)))
(defn get-standard-crypto-format
"For full details: https://github.com/status-im/status-mobile/issues/18225"
+1 -4
View File
@@ -11,7 +11,4 @@
;; in and the device is offline, versus re-fetching when offline and
;; tokens already exist in the app-db.
:tokens-loading nil
:active-tab :assets
:screens {:input-amount-screen
{:crypto-currency? true
:input-value ""}}}})
:active-tab :assets}})
@@ -104,7 +104,7 @@
:wallet/wallet-send-tx-type :tx/send
:wallet/wallet-send-fee-fiat-formatted "$5,00"
:wallet/sending-collectible? false
:wallet/total-amount-in-to-chains (money/bignumber "250")})
:wallet/total-amount (money/bignumber "250")})
(h/describe "Send > input amount screen"
(h/setup-restorable-re-frame)
@@ -1,75 +0,0 @@
(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)))
@@ -1,36 +0,0 @@
(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,56 +1,67 @@
(ns status-im.contexts.wallet.send.input-amount.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme]
[react-native.core :as rn]
[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.asset-list.view :as asset-list]
[status-im.contexts.wallet.send.input-amount.events]
[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]
[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.feature-flags :as ff]
[status-im.setup.hot-reload :as hot-reload]
[status-im.subs.wallet.screens.input-amount]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.money :as money]
[utils.number :as number]
[utils.re-frame :as rf]))
(defn- estimated-fees
[]
(let [loading-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
fees (rf/sub [:send-input-amount-screen/fee-formatted])
amount (rf/sub [:send-input-amount-screen/recipient-gets-amount])]
[rn/view {:style style/estimated-fees-container}
(when (ff/enabled? ::ff/wallet.advanced-sending)
[rn/view {:style style/estimated-fees-content-container}
[quo/button
{:icon-only? true
:type :outline
:size 32
:inner-style {:opacity 1}
:accessibility-label :advanced-button
:disabled? loading-routes?
:on-press #(js/alert "Not implemented yet")}
:i/advanced]])
[quo/data-item
{:container-style style/fees-data-item
:status (if loading-routes? :loading :default)
:size :small
:title (i18n/label :t/fees)
:subtitle fees}]
[quo/data-item
{:container-style style/amount-data-item
:status (if loading-routes? :loading :default)
:size :small
:title (i18n/label :t/recipient-gets)
:subtitle amount}]]))
[{:keys [loading-routes? fees amount]}]
[rn/view {:style style/estimated-fees-container}
(when (ff/enabled? ::ff/wallet.advanced-sending)
[rn/view {:style style/estimated-fees-content-container}
[quo/button
{:icon-only? true
:type :outline
:size 32
:inner-style {:opacity 1}
:accessibility-label :advanced-button
:disabled? loading-routes?
:on-press #(js/alert "Not implemented yet")}
:i/advanced]])
[quo/data-item
{:container-style style/fees-data-item
:status (if loading-routes? :loading :default)
:size :small
:title (i18n/label :t/fees)
:subtitle fees}]
[quo/data-item
{:container-style style/amount-data-item
:status (if loading-routes? :loading :default)
:size :small
:title (i18n/label :t/recipient-gets)
:subtitle amount}]])
(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))
(defn select-asset-bottom-sheet
[]
[clear-input!]
(let [{preselected-token-symbol :symbol} (rf/sub [:wallet/wallet-send-token])]
[:<> ;; Need to be a `:<>` to keep `asset-list` scrollable.
[quo/drawer-top
@@ -62,19 +73,15 @@
:preselected-token-symbol preselected-token-symbol
:on-token-press (fn [token]
(rf/dispatch [:wallet/edit-token-to-send token])
(rf/dispatch
[:send-input-amount-screen/token-input-delete-all]))}]]))
(clear-input!))}]]))
(defn- token-not-available
[]
(let [theme (quo.theme/use-theme)
{token-symbol :symbol
token-networks :networks} (rf/sub [:wallet/wallet-send-token])
receiver-networks (rf/sub [:wallet/wallet-send-receiver-networks])
add-token-networks (fn []
(let [chain-ids (concat receiver-networks
(mapv #(:chain-id %) token-networks))]
(rf/dispatch [:wallet/update-receiver-networks chain-ids])))]
[token-symbol receiver-networks token-networks]
(let [theme (quo.theme/use-theme)
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
[quo/icon :i/alert
@@ -133,117 +140,163 @@
:else (rf/dispatch [:wallet/stop-and-clean-suggested-routes])))
(defn token-input
[]
(let [show-select-asset-sheet #(rf/dispatch
[: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- 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])))
(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
;; crypto-decimals, limit-crypto and initial-crypto-currency? args are needed
;; for component tests only
[{on-confirm :on-confirm
on-navigate-back :on-navigate-back
button-one-label :button-one-label
button-one-props :button-one-props
current-screen-id :current-screen-id}]
(let [view-id (rf/sub [:view-id])
active-screen? (= view-id current-screen-id)
bottom (safe-area/get-bottom)
max-decimals (rf/sub [:send-input-amount-screen/max-decimals])
value-out-of-limits? (rf/sub [:send-input-amount-screen/value-out-of-limits?])
current-address (rf/sub [:wallet/current-viewing-account-address])
not-enough-asset? (rf/sub [:send-input-amount-screen/not-enough-asset?])
show-no-routes? (rf/sub [:send-input-amount-screen/show-no-routes?])
show-estimated-fees? (rf/sub [:send-input-amount-screen/show-estimated-fees?])
token-not-available? (rf/sub [:send-input-amount-screen/token-not-available?])]
[{default-on-confirm :on-confirm
default-limit-crypto :limit-crypto
default-crypto-decimals :crypto-decimals
on-navigate-back :on-navigate-back
button-one-label :button-one-label
button-one-props :button-one-props
current-screen-id :current-screen-id
initial-crypto-currency? :initial-crypto-currency?
enabled-from-chain-ids :enabled-from-chain-ids
from-enabled-networks :from-enabled-networks
:or {initial-crypto-currency? true}}]
(let [view-id (rf/sub [:view-id])
active-screen? (= view-id current-screen-id)
bottom (safe-area/get-bottom)
[crypto-currency?
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
(fn []
(when active-screen?
@@ -257,48 +310,125 @@
(hot-reload/use-safe-unmount on-navigate-back)
(rn/use-effect
(fn []
(when value-out-of-limits?
(rf/dispatch [:wallet/stop-get-suggested-routes])
(debounce/clear-all)))
[value-out-of-limits?])
(set-input-state #(controlled-input/set-upper-limit % max-limit)))
[max-limit])
(rn/use-effect
(fn []
(rf/dispatch [:send-input-amount-screen/token-input-delete-all])
(when input-error
(rf/dispatch [:wallet/stop-get-suggested-routes])
(debounce/clear-all)))
[input-error])
(rn/use-effect
(fn []
(clear-input!)
(rf/dispatch [:wallet/stop-and-clean-suggested-routes])
(rf/dispatch [:wallet/clean-disabled-from-networks]))
[current-address])
(rn/use-effect
(fn []
(request-fetch-routes 0))
[send-from-locked-amounts])
[rn/view
{:style style/screen
:accessibility-label (str "container"
(when value-out-of-limits? "-error"))}
(when (controlled-input/input-error input-state) "-error"))}
[account-switcher/view
{:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back])
:switcher-type :select-account}]
[token-input]
[routes-view current-screen-id]
(when token-not-available?
[token-not-available])
[quo/token-input
{:container-style style/input-container
:token-symbol token-symbol
:value input-value
: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?
[not-enough-asset])
(when show-estimated-fees?
[estimated-fees])
(when (or (and (not no-routes-found?) (or loading-routes? route))
not-enough-asset?)
[estimated-fees
{:loading-routes? loading-routes?
:fees fee-formatted
:amount amount-text}])
(when show-no-routes?
[no-routes-found])
[bottom-actions button-one-label button-one-props on-confirm]
[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}))}]
[quo/numbered-keyboard
{:container-style (style/keyboard-container bottom)
:left-action :dot
:delete-key? true
:on-press (fn [c]
(rf/dispatch [:send-input-amount-screen/token-input-add-character c
max-decimals]))
(let [new-text (str input-value c)
max-decimals (if crypto-currency? crypto-decimals 2)
regex-pattern (str "^\\d*\\.?\\d{0," max-decimals "}$")
regex (re-pattern regex-pattern)]
(when (re-matches regex new-text)
(debounce/clear-all)
(set-input-state #(controlled-input/add-character % c)))))
:on-delete (fn []
(debounce/clear-all)
(rf/dispatch [:send-input-amount-screen/token-input-delete-last])
(set-input-state controlled-input/delete-last)
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes]))
:on-long-press-delete (fn []
(debounce/clear-all)
(rf/dispatch [:send-input-amount-screen/token-input-delete-all])
(set-input-state controlled-input/delete-all)
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes]))}]]))
@@ -8,14 +8,12 @@
(defn view
[]
[input-amount/view
{:current-screen-id :screen/wallet.send-input-amount
:button-one-label (i18n/label :t/review-send)
:on-confirm (fn [amount]
(rf/dispatch [:wallet/set-token-amount-to-send
{:amount amount
:stack-id :screen/wallet.send-input-amount}]))
:on-navigate-back (fn []
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes])
(rf/dispatch [:wallet/clean-disabled-from-networks])
(rf/dispatch [:wallet/clean-from-locked-amounts])
(rf/dispatch [:wallet/clean-send-amount]))}])
{:current-screen-id :screen/wallet.send-input-amount
:button-one-label (i18n/label :t/review-send)
:enabled-from-chain-ids (rf/sub [:wallet/wallet-send-enabled-from-chain-ids])
:from-enabled-networks (rf/sub [:wallet/wallet-send-enabled-networks])
:on-navigate-back (fn []
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes])
(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]))
loading-suggested-routes? (rf/sub
[:wallet/wallet-send-loading-suggested-routes?])
total-amount-receiver (rf/sub [:wallet/total-amount-in-to-chains])
total-amount-receiver (rf/sub [:wallet/total-amount true])
from-account-props {:customization-color account-color
:size 32
:emoji (:emoji account)
+1 -1
View File
@@ -89,7 +89,7 @@
;; RN to dispatch the network status update, otherwise when going
;; offline the user will immediately see a toast saying "provider
;; X is down".
[{:ms 500
[{:ms 50000
:dispatch [:wallet/blockchain-status-changed
(transforms/js->clj event-js)]}]]]}
+2 -2
View File
@@ -40,7 +40,7 @@
(def adjust-resize 16)
(defn is-hermes
(defn hermes?
[]
(boolean (.-HermesInternal js/global)))
@@ -68,7 +68,7 @@
(ff/load-flags))
(dev/setup)
(log/info "hermesEnabled ->" (is-hermes))
(log/info "hermesEnabled ->" (hermes?))
(re-frame/dispatch-sync [:app-started])
+10 -9
View File
@@ -76,13 +76,14 @@
network-values))))
(re-frame/reg-sub
:wallet/total-amount-in-to-chains
:wallet/total-amount
:<- [:wallet/wallet-send]
(fn [{:keys [to-values-by-chain]}]
(reduce
(fn [acc amount]
(if (money/bignumber? amount)
(money/add acc amount)
acc))
(money/bignumber 0)
(vals to-values-by-chain))))
(fn [{:keys [from-values-by-chain to-values-by-chain]} [_ to-values?]]
(let [network-values (if to-values? to-values-by-chain from-values-by-chain)]
(reduce
(fn [acc amount]
(if (money/bignumber? amount)
(money/add acc amount)
acc))
(money/bignumber 0)
(vals network-values)))))
@@ -1,360 +0,0 @@
(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?)))
-5
View File
@@ -16,11 +16,6 @@
:<- [:wallet/ui]
:-> :send)
(rf/reg-sub
:wallet/wallet-screens
:<- [:wallet/ui]
:-> :screens)
(rf/reg-sub
:wallet/send-recipient
:<- [:wallet/wallet-send]
+11 -6
View File
@@ -1,6 +1,6 @@
(ns utils.network.core
(:require
[clojure.string :as string]))
(:require [clojure.string :as string]
[taoensso.timbre :as log]))
(def url-regex
#"https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}(\.[a-z]{2,6})?\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)")
@@ -41,7 +41,12 @@
(map :error)
(not-any? identity)))
(defn chain-id-available?
[current-networks network]
(let [chain-id (get-in network [:config :NetworkId])]
(every? #(not= chain-id (get-in % [1 :config :NetworkId])) current-networks)))
(defn fetch [url {:keys [body] :as params} callback]
(let [js-params (cond-> params
(map? body) (update :body (comp js/JSON.stringify clj->js))
:always clj->js)]
(-> (js/fetch url js-params)
(.then (fn [response]
(.text response)))
(.then callback)
(.catch #(log/error (str "Error while fetching: " url) %)))))
+4 -2
View File
@@ -21,8 +21,10 @@
(when js/goog.DEBUG
(reset! handler-nesting-level 0))
(when rf.interop/debug-enabled?
(log/debug "Handling re-frame event: "
(first (interceptor/get-coeffect context :event))))
(do
(log/debug "Handling re-frame event: "
(first (interceptor/get-coeffect context :event)))
nil))
context)))
(defn- update-db