feat: implement getSuggestedRoutes in the wallet Send Flow (#18104)

Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
Brian Sztamfater 2023-12-19 07:59:58 -03:00 committed by GitHub
parent d40f70dca4
commit a4f99de8d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 316 additions and 139 deletions

View File

@ -173,8 +173,7 @@
:use-mailservers? true :use-mailservers? true
:recovered recovered} :recovered recovered}
config/default-multiaccount) config/default-multiaccount)
;; The address from which we derive any chat ;; The address from which we derive any chat account/encryption keys
;; account/encryption keys
eip1581-address eip1581-address
(assoc :eip1581-address eip1581-address) (assoc :eip1581-address eip1581-address)
save-mnemonic? save-mnemonic?

View File

@ -394,3 +394,15 @@
(def ^:const status-address-domain ".stateofus.eth") (def ^:const status-address-domain ".stateofus.eth")
(def ^:const eth-address-domain ".eth") (def ^:const eth-address-domain ".eth")
(def ^:const gas-rate-low 0)
(def ^:const gas-rate-medium 1)
(def ^:const gas-rate-high 2)
(def ^:const send-type-transfer 0)
(def ^:const send-type-ens-register 1)
(def ^:const send-type-ens-release 2)
(def ^:const send-type-ens-set-pub-key 3)
(def ^:const send-type-stickers-buy 4)
(def ^:const send-type-bridge 5)
(def ^:const send-type-erc-721-transfer 6)

View File

@ -74,6 +74,18 @@
(map #(total-token-fiat-value currency %)) (map #(total-token-fiat-value currency %))
(reduce money/add))) (reduce money/add)))
(defn calculate-balance-for-token
[token]
(money/bignumber
(money/mul (total-token-units-in-all-chains token)
(-> token :market-values-per-currency :usd :price))))
(defn calculate-balance
[tokens-in-account]
(->> tokens-in-account
(map #(calculate-balance-for-token %))
(reduce +)))
(defn network-list (defn network-list
[{:keys [balances-per-chain]} networks] [{:keys [balances-per-chain]} networks]
(into #{} (into #{}

View File

@ -152,7 +152,9 @@
(rf/defn clean-scanned-address (rf/defn clean-scanned-address
{:events [:wallet/clean-scanned-address]} {:events [:wallet/clean-scanned-address]}
[{:keys [db]}] [{:keys [db]}]
{:db (dissoc db :wallet/scanned-address :wallet/send-address)}) {:db (-> db
(dissoc :wallet/scanned-address :wallet/send-address)
(update-in [:wallet :ui :send] dissoc :to-address))})
(rf/reg-event-fx :wallet/create-derived-addresses (rf/reg-event-fx :wallet/create-derived-addresses
(fn [{:keys [db]} [{:keys [sha3-pwd path]} on-success]] (fn [{:keys [db]} [{:keys [sha3-pwd path]} on-success]]
@ -437,10 +439,6 @@
(background-timer/clear-timeout current-timeout) (background-timer/clear-timeout current-timeout)
{:db (assoc db :wallet/local-suggestions [] :wallet/valid-ens-or-address? false)}))) {:db (assoc db :wallet/local-suggestions [] :wallet/valid-ens-or-address? false)})))
(rf/reg-event-fx :wallet/select-send-address
(fn [{:keys [db]} [address]]
{:db (assoc db :wallet/send-address address)}))
(rf/reg-event-fx :wallet/get-address-details-success (rf/reg-event-fx :wallet/get-address-details-success
(fn [{:keys [db]} [{:keys [hasActivity]}]] (fn [{:keys [db]} [{:keys [hasActivity]}]]
{:db (assoc-in db {:db (assoc-in db

View File

@ -17,7 +17,7 @@
(deftest clean-scanned-address (deftest clean-scanned-address
(let [db {:wallet/scanned-address address}] (let [db {:wallet/scanned-address address}]
(testing "clean-scanned-address" (testing "clean-scanned-address"
(let [expected-db {} (let [expected-db {:wallet {:ui {:send nil}}}
effects (events/clean-scanned-address {:db db}) effects (events/clean-scanned-address {:db db})
result-db (:db effects)] result-db (:db effects)]
(is (match? result-db expected-db)))))) (is (match? result-db expected-db))))))

View File

@ -1,5 +1,8 @@
(ns status-im2.contexts.wallet.send.events (ns status-im2.contexts.wallet.send.events
(:require (:require
[status-im2.constants :as constants]
[taoensso.timbre :as log]
[utils.money :as money]
[utils.number] [utils.number]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
@ -10,3 +13,79 @@
(rf/reg-event-fx :wallet/select-send-account-address (rf/reg-event-fx :wallet/select-send-account-address
(fn [{:keys [db]} [address]] (fn [{:keys [db]} [address]]
{:db (assoc db [:wallet :ui :send :send-account-address] address)})) {:db (assoc db [:wallet :ui :send :send-account-address] address)}))
(rf/reg-event-fx :wallet/suggested-routes-success
(fn [{:keys [db]} [suggested-routes timestamp]]
(when (= (get-in db [:wallet :ui :send :suggested-routes-call-timestamp]) timestamp)
{:db (-> db
(assoc-in [:wallet :ui :send :suggested-routes] suggested-routes)
(assoc-in [:wallet :ui :send :route] (first (:Best suggested-routes)))
(assoc-in [:wallet :ui :send :loading-suggested-routes?] false))})))
(rf/reg-event-fx :wallet/suggested-routes-error
(fn [{:keys [db]} [_error]]
{:db (-> db
(update-in [:wallet :ui :send] dissoc :suggested-routes)
(update-in [:wallet :ui :send] dissoc :route)
(assoc-in [:wallet :ui :send :loading-suggested-routes?] false))}))
(rf/reg-event-fx :wallet/clean-suggested-routes
(fn [{:keys [db]}]
{:db (-> db
(update-in [:wallet :ui :send] dissoc :suggested-routes)
(update-in [:wallet :ui :send] dissoc :route)
(update-in [:wallet :ui :send] dissoc :loading-suggested-routes?))}))
(rf/reg-event-fx :wallet/select-send-address
(fn [{:keys [db]} [{:keys [address stack-id]}]]
{:db (assoc-in db [:wallet :ui :send :to-address] address)
:fx [[:navigate-to-within-stack [:wallet-select-asset stack-id]]]}))
(rf/reg-event-fx :wallet/send-select-token
(fn [{:keys [db]} [{:keys [token stack-id]}]]
{:db (assoc-in db [:wallet :ui :send :token] token)
:fx [[:navigate-to-within-stack [:wallet-send-input-amount stack-id]]]}))
(rf/reg-event-fx :wallet/send-select-amount
(fn [{:keys [db]} [{:keys [amount]}]]
(js/alert "Not implemented yet")
{:db (assoc-in db [:wallet :ui :send :amount] amount)}))
(rf/reg-event-fx :wallet/get-suggested-routes
(fn [{:keys [db now]} [amount]]
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
token (get-in db [:wallet :ui :send :token])
to-address (get-in db [:wallet :ui :send :to-address])
token-decimal (:decimals token)
token-id (:symbol token)
network-preferences []
gas-rates constants/gas-rate-medium
amount-in (money/amount-in-hex amount token-decimal)
from-address wallet-address
disabled-from-chain-ids []
disabled-to-chain-ids []
from-locked-amount {}
request-params [constants/send-type-transfer
from-address
to-address
amount-in
token-id
disabled-from-chain-ids
disabled-to-chain-ids
network-preferences
gas-rates
from-locked-amount]]
{:db (-> db
(assoc-in [:wallet :ui :send :loading-suggested-routes?] true)
(assoc-in [:wallet :ui :send :suggested-routes-call-timestamp] now))
:json-rpc/call [{:method "wallet_getSuggestedRoutes"
:params request-params
:on-success (fn [suggested-routes]
(rf/dispatch [:wallet/suggested-routes-success suggested-routes
now]))
:on-error (fn [error]
(rf/dispatch [:wallet/suggested-routes-error error])
(log/error "failed to get suggested routes"
{:event :wallet/get-suggested-routes
:error error
:params request-params}))}]})))

View File

@ -12,98 +12,107 @@
(fn [_] (val keyval))))) (fn [_] (val keyval)))))
(def sub-mocks (def sub-mocks
{:profile/profile {:currency :usd} {:profile/profile {:currency :usd}
:wallet/network-details [{:source 525 :wallet/network-details [{:source 525
:short-name "eth" :short-name "eth"
:network-name :ethereum :network-name :ethereum
:chain-id 1 :chain-id 1
:related-chain-id 5}] :related-chain-id 5}]
:wallet/current-viewing-account {:path "m/44'/60'/0'/0/1" :wallet/current-viewing-account {:path "m/44'/60'/0'/0/1"
:emoji "💎" :emoji "💎"
:key-uid "0x2f5ea39" :key-uid "0x2f5ea39"
:address "0x1" :address "0x1"
:wallet false :wallet false
:name "Account One" :name "Account One"
:type :generated :type :generated
:watch-only? false :watch-only? false
:chat false :chat false
:test-preferred-chain-ids #{5 420 421613} :test-preferred-chain-ids #{5 420 421613}
:color :purple :color :purple
:hidden false :hidden false
:prod-preferred-chain-ids #{1 10 42161} :prod-preferred-chain-ids #{1 10 42161}
:network-preferences-names #{:ethereum :arbitrum :optimism} :network-preferences-names #{:ethereum :arbitrum
:position 1 :optimism}
:clock 1698945829328 :position 1
:created-at 1698928839000 :clock 1698945829328
:operable "fully" :created-at 1698928839000
:mixedcase-address "0x7bcDfc75c431" :operable "fully"
:public-key "0x04371e2d9d66b82f056bc128064" :mixedcase-address "0x7bcDfc75c431"
:removed false}}) :public-key "0x04371e2d9d66b82f056bc128064"
:removed false}
:wallet/wallet-send-token {:symbol :eth}
:wallet/wallet-send-loading-suggested-routes? false
:wallet/wallet-send-route {:route []}})
(h/describe "Send > input amount screen" (h/describe "Send > input amount screen"
(h/test "Default render" (h/test "Default render"
(setup-subs sub-mocks) (with-redefs [re-frame/dispatch #()]
(h/render [input-amount/view {}]) (setup-subs sub-mocks)
(h/is-truthy (h/get-by-text "0")) (h/render [input-amount/view {}])
(h/is-truthy (h/get-by-text "ETH")) (h/is-truthy (h/get-by-text "0"))
(h/is-truthy (h/get-by-text "$0.00")) (h/is-truthy (h/get-by-text "ETH"))
(h/is-disabled (h/get-by-label-text :button-one))) (h/is-truthy (h/get-by-text "$0.00"))
(h/is-disabled (h/get-by-label-text :button-one))))
(h/test "Fill token input and confirm" (h/test "Fill token input and confirm"
(setup-subs sub-mocks) (with-redefs [re-frame/dispatch #()]
(let [on-confirm (h/mock-fn)] (setup-subs sub-mocks)
(h/render [input-amount/view (let [on-confirm (h/mock-fn)]
{:on-confirm on-confirm (h/render [input-amount/view
:rate 10}]) {:on-confirm on-confirm
:rate 10
:limit 1000}])
(h/fire-event :press (h/query-by-label-text :keyboard-key-1)) (h/fire-event :press (h/query-by-label-text :keyboard-key-1))
(h/fire-event :press (h/query-by-label-text :keyboard-key-2)) (h/fire-event :press (h/query-by-label-text :keyboard-key-2))
(h/fire-event :press (h/query-by-label-text :keyboard-key-3)) (h/fire-event :press (h/query-by-label-text :keyboard-key-3))
(h/fire-event :press (h/query-by-label-text :keyboard-key-.)) (h/fire-event :press (h/query-by-label-text :keyboard-key-.))
(h/fire-event :press (h/query-by-label-text :keyboard-key-4)) (h/fire-event :press (h/query-by-label-text :keyboard-key-4))
(h/fire-event :press (h/query-by-label-text :keyboard-key-5)) (h/fire-event :press (h/query-by-label-text :keyboard-key-5))
(h/wait-for #(h/is-truthy (h/get-by-text "$1234.50"))) (h/wait-for #(h/is-truthy (h/get-by-text "$1234.50")))
(h/is-truthy (h/get-by-label-text :button-one)) (h/is-truthy (h/get-by-label-text :button-one))
(h/fire-event :press (h/get-by-label-text :button-one)) (h/fire-event :press (h/get-by-label-text :button-one))
(h/was-called on-confirm))) (h/was-called on-confirm))))
(h/test "Try to fill more than limit" (h/test "Try to fill more than limit"
(setup-subs sub-mocks) (with-redefs [re-frame/dispatch #()]
(h/render [input-amount/view (setup-subs sub-mocks)
{:rate 10 (h/render [input-amount/view
:limit 286}]) {:rate 10
:limit 286}])
(h/fire-event :press (h/query-by-label-text :keyboard-key-2)) (h/fire-event :press (h/query-by-label-text :keyboard-key-2))
(h/fire-event :press (h/query-by-label-text :keyboard-key-9)) (h/fire-event :press (h/query-by-label-text :keyboard-key-9))
(h/fire-event :press (h/query-by-label-text :keyboard-key-5)) (h/fire-event :press (h/query-by-label-text :keyboard-key-5))
(h/wait-for #(h/is-truthy (h/get-by-text "$290.00"))) (h/wait-for #(h/is-truthy (h/get-by-text "$290.00")))
(h/fire-event :press (h/query-by-label-text :keyboard-key-backspace)) (h/fire-event :press (h/query-by-label-text :keyboard-key-backspace))
(h/fire-event :press (h/query-by-label-text :keyboard-key-8)) (h/fire-event :press (h/query-by-label-text :keyboard-key-8))
(h/fire-event :press (h/query-by-label-text :keyboard-key-5)) (h/fire-event :press (h/query-by-label-text :keyboard-key-5))
(h/wait-for #(h/is-truthy (h/get-by-text "$2850.00")))) (h/wait-for #(h/is-truthy (h/get-by-text "$2850.00")))))
(h/test "Switch from crypto to fiat and check limit" (h/test "Switch from crypto to fiat and check limit"
(setup-subs sub-mocks) (with-redefs [re-frame/dispatch #()]
(h/render [input-amount/view (setup-subs sub-mocks)
{:rate 10 (h/render [input-amount/view
:limit 250}]) {:rate 10
:limit 250}])
(h/fire-event :press (h/query-by-label-text :keyboard-key-2)) (h/fire-event :press (h/query-by-label-text :keyboard-key-2))
(h/fire-event :press (h/query-by-label-text :keyboard-key-0)) (h/fire-event :press (h/query-by-label-text :keyboard-key-0))
(h/wait-for #(h/is-truthy (h/get-by-text "$200.00"))) (h/wait-for #(h/is-truthy (h/get-by-text "$200.00")))
(h/fire-event :press (h/query-by-label-text :reorder)) (h/fire-event :press (h/query-by-label-text :reorder))
(h/wait-for #(h/is-truthy (h/get-by-text "2.00 ETH"))) (h/wait-for #(h/is-truthy (h/get-by-text "2.00 ETH")))
(h/fire-event :press (h/query-by-label-text :keyboard-key-5)) (h/fire-event :press (h/query-by-label-text :keyboard-key-5))
(h/fire-event :press (h/query-by-label-text :keyboard-key-5)) (h/fire-event :press (h/query-by-label-text :keyboard-key-5))
(h/wait-for #(h/is-truthy (h/get-by-text "205.50 ETH"))) (h/wait-for #(h/is-truthy (h/get-by-text "205.50 ETH")))
(h/fire-event :press (h/query-by-label-text :keyboard-key-5)) (h/fire-event :press (h/query-by-label-text :keyboard-key-5))
(h/wait-for #(h/is-truthy (h/get-by-text "205.50 ETH"))))) (h/wait-for #(h/is-truthy (h/get-by-text "205.50 ETH"))))))

View File

@ -8,6 +8,7 @@
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im2.contexts.wallet.common.account-switcher.view :as account-switcher] [status-im2.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im2.contexts.wallet.send.input-amount.style :as style] [status-im2.contexts.wallet.send.input-amount.style :as style]
[utils.debounce :as debounce]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
@ -48,67 +49,84 @@
current)) current))
(defn- f-view-internal (defn- f-view-internal
[{:keys [token limit rate]}] [{:keys [rate limit]}]
(let [bottom (safe-area/get-bottom) (let [bottom (safe-area/get-bottom)
{:keys [currency]} (rf/sub [:profile/profile]) {:keys [currency]} (rf/sub [:profile/profile])
networks (rf/sub [:wallet/network-details]) networks (rf/sub [:wallet/network-details])
;; Temporary values token (rf/sub [:wallet/wallet-send-token])
token (or token :eth) loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
conversion-rate (or rate 10) token-symbol (:symbol token)
limit-crypto (or limit 2860000.32) limit-crypto (or (:total-balance token) limit)
limit-fiat (* limit-crypto conversion-rate) conversion-rate (or rate 10)
input-value (reagent/atom "") limit-fiat (* limit-crypto conversion-rate)
current-limit (reagent/atom {:amount limit-crypto input-value (reagent/atom "")
:currency token}) current-limit (reagent/atom {:amount limit-crypto
handle-swap (fn [crypto?] :currency token-symbol})
(let [num-value (parse-double @input-value)] handle-swap (fn [crypto?]
(reset! current-limit (if crypto? (let [num-value (parse-double @input-value)]
{:amount limit-crypto (reset! current-limit (if crypto?
:currency token} {:amount limit-crypto
{:amount limit-fiat :currency token-symbol}
:currency currency})) {:amount limit-fiat
(when (> num-value (:amount @current-limit)) :currency currency}))
(reset! input-value "")))) (when (> num-value (:amount @current-limit))
handle-keyboard-press (fn [v] (reset! input-value ""))))
(let [current-value @input-value handle-keyboard-press (fn [v]
new-value (make-new-input current-value v) (let [current-value @input-value
num-value (or (parse-double new-value) 0)] new-value (make-new-input current-value v)
(when (<= num-value (:amount @current-limit)) num-value (or (parse-double new-value) 0)]
(reset! input-value new-value) (when (and (not loading-suggested-routes?)
(reagent/flush)))) (<= num-value (:amount @current-limit)))
handle-delete (fn [_] (reset! input-value new-value)
(swap! input-value #(subs % 0 (dec (count %)))) (reagent/flush))))
(reagent/flush)) handle-delete (fn [_]
handle-on-change (fn [v] (when-not loading-suggested-routes?
(when (valid-input? @input-value v) (swap! input-value #(subs % 0 (dec (count %))))
(let [num-value (or (parse-double v) 0) (reagent/flush)))
current-limit-amount (:amount @current-limit)] handle-on-change (fn [v]
(if (> num-value current-limit-amount) (when (valid-input? @input-value v)
(reset! input-value (str current-limit-amount)) (let [num-value (or (parse-double v) 0)
(reset! input-value v)) current-limit-amount (:amount @current-limit)]
(reagent/flush))))] (if (> num-value current-limit-amount)
(reset! input-value (str current-limit-amount))
(reset! input-value v))
(reagent/flush))))]
(fn [{:keys [on-confirm] (fn [{:keys [on-confirm]
:or {on-confirm #(js/alert "Confirmed")}}] :or {on-confirm #(rf/dispatch [:wallet/send-select-amount
(let [limit-label (make-limit-label @current-limit) {:amount @input-value
input-num-value (parse-double @input-value) :stack-id :wallet-send-input-amount}])}}]
confirm-disabled? (or (let [limit-label (make-limit-label @current-limit)
(empty? @input-value) input-num-value (parse-double @input-value)
(<= input-num-value 0) route (rf/sub [:wallet/wallet-send-route])
(> input-num-value (:amount @current-limit)))] loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
confirm-disabled? (or
(nil? route)
(empty? @input-value)
(<= input-num-value 0)
(> input-num-value (:amount @current-limit)))]
(rn/use-effect (rn/use-effect
(fn [] (fn []
(let [dismiss-keyboard-fn #(when (= % "active") (rn/dismiss-keyboard!)) (let [dismiss-keyboard-fn #(when (= % "active") (rn/dismiss-keyboard!))
app-keyboard-listener (.addEventListener rn/app-state "change" dismiss-keyboard-fn)] app-keyboard-listener (.addEventListener rn/app-state "change" dismiss-keyboard-fn)]
#(.remove app-keyboard-listener)))) #(.remove app-keyboard-listener))))
(rn/use-effect (fn []
(rf/dispatch [:wallet/clean-suggested-routes])
(when-not (or
(empty? @input-value)
(<= input-num-value 0)
(> input-num-value (:amount @current-limit)))
(debounce/debounce-and-dispatch [:wallet/get-suggested-routes @input-value]
100)))
[@input-value])
[rn/view [rn/view
{:style style/screen} {:style style/screen}
[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-within-stack :wallet-send-input-amount])
:switcher-type :select-account}] :switcher-type :select-account}]
[quo/token-input [quo/token-input
{:container-style style/input-container {:container-style style/input-container
:token token :token token-symbol
:currency currency :currency currency
:networks networks :networks networks
:title (i18n/label :t/send-limit {:limit limit-label}) :title (i18n/label :t/send-limit {:limit limit-label})
@ -119,7 +137,16 @@
:on-change-text (fn [text] :on-change-text (fn [text]
(handle-on-change text))}] (handle-on-change text))}]
;; Network routing content to be added ;; Network routing content to be added
[rn/scroll-view] [rn/scroll-view
{:content-container-style {:flex-grow 1
:align-items :center
:justify-content :center}}
(cond loading-suggested-routes?
[quo/text "Loading routes"]
(and (not loading-suggested-routes?) route)
[quo/text "Route found"]
(and (not loading-suggested-routes?) (nil? route))
[quo/text "Route not found"])]
[quo/bottom-actions [quo/bottom-actions
{:actions :1-action {:actions :1-action
:button-one-label (i18n/label :t/confirm) :button-one-label (i18n/label :t/confirm)

View File

@ -23,7 +23,7 @@
[input-value input-focused?] [input-value input-focused?]
(fn [] (fn []
(let [scanned-address (rf/sub [:wallet/scanned-address]) (let [scanned-address (rf/sub [:wallet/scanned-address])
send-address (rf/sub [:wallet/send-address]) send-address (rf/sub [:wallet/wallet-send-to-address])
valid-ens-or-address? (rf/sub [:wallet/valid-ens-or-address?]) valid-ens-or-address? (rf/sub [:wallet/valid-ens-or-address?])
chain-id (rf/sub [:chain-id]) chain-id (rf/sub [:chain-id])
contacts (rf/sub [:contacts/active])] contacts (rf/sub [:contacts/active])]
@ -76,7 +76,10 @@
_ _] _ _]
(let [props {:on-press (fn [] (let [props {:on-press (fn []
(let [address (if accounts (:address (first accounts)) address)] (let [address (if accounts (:address (first accounts)) address)]
(when-not ens (rf/dispatch [:wallet/select-send-address address])))) (when-not ens
(rf/dispatch [:wallet/select-send-address
{:address address
:stack-id :wallet-select-address}]))))
:active-state? false}] :active-state? false}]
(cond (cond
(= type types/saved-address) (= type types/saved-address)
@ -151,7 +154,9 @@
:type :primary :type :primary
:disabled? (not valid-ens-or-address?) :disabled? (not valid-ens-or-address?)
:container-style style/button :container-style style/button
:on-press #(js/alert "Not implemented yet")} :on-press #(rf/dispatch [:wallet/select-send-address
{:address @input-value
:stack-id :wallet-select-address}])}
(i18n/label :t/continue)])] (i18n/label :t/continue)])]
[:<> [:<>
[quo/tabs [quo/tabs

View File

@ -17,10 +17,13 @@
(defn- asset-component (defn- asset-component
[] []
(fn [token _ _ _] (fn [token _ _ _]
(let [on-press #(js/alert "Not implemented yet") (let [on-press
#(rf/dispatch [:wallet/send-select-token
{:token token
:stack-id :wallet-select-asset}])
total-balance-formatted (.toFixed (:total-balance token) 2) total-balance-formatted (.toFixed (:total-balance token) 2)
balance-fiat-formatted (.toFixed (:total-balance-fiat token) 2) balance-fiat-formatted (.toFixed (:total-balance-fiat token) 2)
currency-symbol (rf/sub [:profile/currency-symbol])] currency-symbol (rf/sub [:profile/currency-symbol])]
[quo/token-network [quo/token-network
{:token (:symbol token) {:token (:symbol token)
:label (:name token) :label (:name token)

View File

@ -156,7 +156,6 @@
(reg-root-key-sub :wallet/networks :wallet/networks) (reg-root-key-sub :wallet/networks :wallet/networks)
(reg-root-key-sub :wallet/local-suggestions :wallet/local-suggestions) (reg-root-key-sub :wallet/local-suggestions :wallet/local-suggestions)
(reg-root-key-sub :wallet/valid-ens-or-address? :wallet/valid-ens-or-address?) (reg-root-key-sub :wallet/valid-ens-or-address? :wallet/valid-ens-or-address?)
(reg-root-key-sub :wallet/send-address :wallet/send-address)
;;debug ;;debug
(when js/goog.DEBUG (when js/goog.DEBUG

View File

@ -29,6 +29,11 @@
:<- [:wallet] :<- [:wallet]
:-> :ui) :-> :ui)
(rf/reg-sub
:wallet/wallet-send
:<- [:wallet/ui]
:-> :send)
(rf/reg-sub (rf/reg-sub
:wallet/tokens-loading? :wallet/tokens-loading?
:<- [:wallet/ui] :<- [:wallet/ui]
@ -40,6 +45,31 @@
:<- [:wallet] :<- [:wallet]
:-> :current-viewing-account-address) :-> :current-viewing-account-address)
(rf/reg-sub
:wallet/wallet-send-to-address
:<- [:wallet/wallet-send]
:-> :to-address)
(rf/reg-sub
:wallet/wallet-send-route
:<- [:wallet/wallet-send]
:-> :route)
(rf/reg-sub
:wallet/wallet-send-token
:<- [:wallet/wallet-send]
:-> :token)
(rf/reg-sub
:wallet/wallet-send-amount
:<- [:wallet/wallet-send]
:-> :amount)
(rf/reg-sub
:wallet/wallet-send-loading-suggested-routes?
:<- [:wallet/wallet-send]
:-> :loading-suggested-routes?)
(rf/reg-sub (rf/reg-sub
:wallet/watch-address-activity-state :wallet/watch-address-activity-state
:<- [:wallet/ui] :<- [:wallet/ui]
@ -110,7 +140,7 @@
(assoc token (assoc token
:networks (utils/network-list token networks) :networks (utils/network-list token networks)
:total-balance (utils/total-token-units-in-all-chains token) :total-balance (utils/total-token-units-in-all-chains token)
:total-balance-fiat 0)) :total-balance-fiat (utils/calculate-balance-for-token token)))
(:tokens account)) (:tokens account))
sorted-tokens (sort-by :name compare tokens) sorted-tokens (sort-by :name compare tokens)
filtered-tokens (filter #(or (string/starts-with? (string/lower-case (:name %)) filtered-tokens (filter #(or (string/starts-with? (string/lower-case (:name %))

View File

@ -246,3 +246,7 @@
(schema/=> format-amount (schema/=> format-amount
[:=> [:cat [:maybe :int]] [:=> [:cat [:maybe :int]]
[:maybe :string]]) [:maybe :string]])
(defn amount-in-hex
[amount token-decimal]
(to-hex (mul (bignumber amount) (from-decimal token-decimal))))