feat: implement getSuggestedRoutes in the wallet Send Flow (#18104)
Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
parent
d40f70dca4
commit
a4f99de8d5
|
@ -173,8 +173,7 @@
|
|||
:use-mailservers? true
|
||||
:recovered recovered}
|
||||
config/default-multiaccount)
|
||||
;; The address from which we derive any chat
|
||||
;; account/encryption keys
|
||||
;; The address from which we derive any chat account/encryption keys
|
||||
eip1581-address
|
||||
(assoc :eip1581-address eip1581-address)
|
||||
save-mnemonic?
|
||||
|
|
|
@ -394,3 +394,15 @@
|
|||
|
||||
(def ^:const status-address-domain ".stateofus.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)
|
||||
|
|
|
@ -74,6 +74,18 @@
|
|||
(map #(total-token-fiat-value currency %))
|
||||
(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
|
||||
[{:keys [balances-per-chain]} networks]
|
||||
(into #{}
|
||||
|
|
|
@ -152,7 +152,9 @@
|
|||
(rf/defn clean-scanned-address
|
||||
{:events [:wallet/clean-scanned-address]}
|
||||
[{: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
|
||||
(fn [{:keys [db]} [{:keys [sha3-pwd path]} on-success]]
|
||||
|
@ -437,10 +439,6 @@
|
|||
(background-timer/clear-timeout current-timeout)
|
||||
{: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
|
||||
(fn [{:keys [db]} [{:keys [hasActivity]}]]
|
||||
{:db (assoc-in db
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
(deftest clean-scanned-address
|
||||
(let [db {:wallet/scanned-address address}]
|
||||
(testing "clean-scanned-address"
|
||||
(let [expected-db {}
|
||||
(let [expected-db {:wallet {:ui {:send nil}}}
|
||||
effects (events/clean-scanned-address {:db db})
|
||||
result-db (:db effects)]
|
||||
(is (match? result-db expected-db))))))
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
(ns status-im2.contexts.wallet.send.events
|
||||
(:require
|
||||
[status-im2.constants :as constants]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.money :as money]
|
||||
[utils.number]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
@ -10,3 +13,79 @@
|
|||
(rf/reg-event-fx :wallet/select-send-account-address
|
||||
(fn [{:keys [db]} [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}))}]})))
|
||||
|
|
|
@ -31,30 +31,37 @@
|
|||
:color :purple
|
||||
:hidden false
|
||||
:prod-preferred-chain-ids #{1 10 42161}
|
||||
:network-preferences-names #{:ethereum :arbitrum :optimism}
|
||||
:network-preferences-names #{:ethereum :arbitrum
|
||||
:optimism}
|
||||
:position 1
|
||||
:clock 1698945829328
|
||||
:created-at 1698928839000
|
||||
:operable "fully"
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x04371e2d9d66b82f056bc128064"
|
||||
:removed false}})
|
||||
: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/test "Default render"
|
||||
(with-redefs [re-frame/dispatch #()]
|
||||
(setup-subs sub-mocks)
|
||||
(h/render [input-amount/view {}])
|
||||
(h/is-truthy (h/get-by-text "0"))
|
||||
(h/is-truthy (h/get-by-text "ETH"))
|
||||
(h/is-truthy (h/get-by-text "$0.00"))
|
||||
(h/is-disabled (h/get-by-label-text :button-one)))
|
||||
(h/is-disabled (h/get-by-label-text :button-one))))
|
||||
|
||||
(h/test "Fill token input and confirm"
|
||||
(with-redefs [re-frame/dispatch #()]
|
||||
(setup-subs sub-mocks)
|
||||
(let [on-confirm (h/mock-fn)]
|
||||
(h/render [input-amount/view
|
||||
{:on-confirm on-confirm
|
||||
:rate 10}])
|
||||
: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-2))
|
||||
|
@ -68,9 +75,10 @@
|
|||
(h/is-truthy (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"
|
||||
(with-redefs [re-frame/dispatch #()]
|
||||
(setup-subs sub-mocks)
|
||||
(h/render [input-amount/view
|
||||
{:rate 10
|
||||
|
@ -85,9 +93,10 @@
|
|||
(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-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"
|
||||
(with-redefs [re-frame/dispatch #()]
|
||||
(setup-subs sub-mocks)
|
||||
(h/render [input-amount/view
|
||||
{:rate 10
|
||||
|
@ -106,4 +115,4 @@
|
|||
|
||||
(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/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"))))))
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.wallet.common.account-switcher.view :as account-switcher]
|
||||
[status-im2.contexts.wallet.send.input-amount.style :as style]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
@ -48,23 +49,24 @@
|
|||
current))
|
||||
|
||||
(defn- f-view-internal
|
||||
[{:keys [token limit rate]}]
|
||||
[{:keys [rate limit]}]
|
||||
(let [bottom (safe-area/get-bottom)
|
||||
{:keys [currency]} (rf/sub [:profile/profile])
|
||||
networks (rf/sub [:wallet/network-details])
|
||||
;; Temporary values
|
||||
token (or token :eth)
|
||||
token (rf/sub [:wallet/wallet-send-token])
|
||||
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
|
||||
token-symbol (:symbol token)
|
||||
limit-crypto (or (:total-balance token) limit)
|
||||
conversion-rate (or rate 10)
|
||||
limit-crypto (or limit 2860000.32)
|
||||
limit-fiat (* limit-crypto conversion-rate)
|
||||
input-value (reagent/atom "")
|
||||
current-limit (reagent/atom {:amount limit-crypto
|
||||
:currency token})
|
||||
:currency token-symbol})
|
||||
handle-swap (fn [crypto?]
|
||||
(let [num-value (parse-double @input-value)]
|
||||
(reset! current-limit (if crypto?
|
||||
{:amount limit-crypto
|
||||
:currency token}
|
||||
:currency token-symbol}
|
||||
{:amount limit-fiat
|
||||
:currency currency}))
|
||||
(when (> num-value (:amount @current-limit))
|
||||
|
@ -73,12 +75,14 @@
|
|||
(let [current-value @input-value
|
||||
new-value (make-new-input current-value v)
|
||||
num-value (or (parse-double new-value) 0)]
|
||||
(when (<= num-value (:amount @current-limit))
|
||||
(when (and (not loading-suggested-routes?)
|
||||
(<= num-value (:amount @current-limit)))
|
||||
(reset! input-value new-value)
|
||||
(reagent/flush))))
|
||||
handle-delete (fn [_]
|
||||
(when-not loading-suggested-routes?
|
||||
(swap! input-value #(subs % 0 (dec (count %))))
|
||||
(reagent/flush))
|
||||
(reagent/flush)))
|
||||
handle-on-change (fn [v]
|
||||
(when (valid-input? @input-value v)
|
||||
(let [num-value (or (parse-double v) 0)
|
||||
|
@ -88,10 +92,15 @@
|
|||
(reset! input-value v))
|
||||
(reagent/flush))))]
|
||||
(fn [{:keys [on-confirm]
|
||||
:or {on-confirm #(js/alert "Confirmed")}}]
|
||||
:or {on-confirm #(rf/dispatch [:wallet/send-select-amount
|
||||
{:amount @input-value
|
||||
:stack-id :wallet-send-input-amount}])}}]
|
||||
(let [limit-label (make-limit-label @current-limit)
|
||||
input-num-value (parse-double @input-value)
|
||||
route (rf/sub [:wallet/wallet-send-route])
|
||||
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)))]
|
||||
|
@ -100,15 +109,24 @@
|
|||
(let [dismiss-keyboard-fn #(when (= % "active") (rn/dismiss-keyboard!))
|
||||
app-keyboard-listener (.addEventListener rn/app-state "change" dismiss-keyboard-fn)]
|
||||
#(.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
|
||||
{:style style/screen}
|
||||
[account-switcher/view
|
||||
{: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}]
|
||||
[quo/token-input
|
||||
{:container-style style/input-container
|
||||
:token token
|
||||
:token token-symbol
|
||||
:currency currency
|
||||
:networks networks
|
||||
:title (i18n/label :t/send-limit {:limit limit-label})
|
||||
|
@ -119,7 +137,16 @@
|
|||
:on-change-text (fn [text]
|
||||
(handle-on-change text))}]
|
||||
;; 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
|
||||
{:actions :1-action
|
||||
:button-one-label (i18n/label :t/confirm)
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
[input-value input-focused?]
|
||||
(fn []
|
||||
(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?])
|
||||
chain-id (rf/sub [:chain-id])
|
||||
contacts (rf/sub [:contacts/active])]
|
||||
|
@ -76,7 +76,10 @@
|
|||
_ _]
|
||||
(let [props {:on-press (fn []
|
||||
(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}]
|
||||
(cond
|
||||
(= type types/saved-address)
|
||||
|
@ -151,7 +154,9 @@
|
|||
:type :primary
|
||||
:disabled? (not valid-ens-or-address?)
|
||||
: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)])]
|
||||
[:<>
|
||||
[quo/tabs
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
(defn- asset-component
|
||||
[]
|
||||
(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)
|
||||
balance-fiat-formatted (.toFixed (:total-balance-fiat token) 2)
|
||||
currency-symbol (rf/sub [:profile/currency-symbol])]
|
||||
|
|
|
@ -156,7 +156,6 @@
|
|||
(reg-root-key-sub :wallet/networks :wallet/networks)
|
||||
(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/send-address :wallet/send-address)
|
||||
|
||||
;;debug
|
||||
(when js/goog.DEBUG
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
:<- [:wallet]
|
||||
:-> :ui)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/wallet-send
|
||||
:<- [:wallet/ui]
|
||||
:-> :send)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/tokens-loading?
|
||||
:<- [:wallet/ui]
|
||||
|
@ -40,6 +45,31 @@
|
|||
:<- [:wallet]
|
||||
:-> :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
|
||||
:wallet/watch-address-activity-state
|
||||
:<- [:wallet/ui]
|
||||
|
@ -110,7 +140,7 @@
|
|||
(assoc token
|
||||
:networks (utils/network-list token networks)
|
||||
: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))
|
||||
sorted-tokens (sort-by :name compare tokens)
|
||||
filtered-tokens (filter #(or (string/starts-with? (string/lower-case (:name %))
|
||||
|
|
|
@ -246,3 +246,7 @@
|
|||
(schema/=> format-amount
|
||||
[:=> [:cat [:maybe :int]]
|
||||
[:maybe :string]])
|
||||
|
||||
(defn amount-in-hex
|
||||
[amount token-decimal]
|
||||
(to-hex (mul (bignumber amount) (from-decimal token-decimal))))
|
||||
|
|
Loading…
Reference in New Issue