Swap flows (launch from home / launch from account) (#21269)

* Swap flows (launch from home / launch from account)

* Fixes

* Lint fix
This commit is contained in:
Alexander 2024-09-30 10:44:25 +02:00 committed by GitHub
parent c166c7c314
commit f539bb5ca2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 119 additions and 70 deletions

View File

@ -1,6 +1,5 @@
(ns status-im.contexts.wallet.common.token-value.view (ns status-im.contexts.wallet.common.token-value.view
(:require [quo.core :as quo] (:require [quo.core :as quo]
[status-im.common.not-implemented :as not-implemented]
[status-im.contexts.wallet.send.utils :as send-utils] [status-im.contexts.wallet.send.utils :as send-utils]
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token] [status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
[status-im.feature-flags :as ff] [status-im.feature-flags :as ff]
@ -18,15 +17,15 @@
:right-icon :i/external}) :right-icon :i/external})
(defn- action-send (defn- action-send
[send-params entry-point] [{:keys [disabled?] :as params} entry-point]
{:icon :i/send {:icon :i/send
:accessibility-label :send :accessibility-label :send
:label (i18n/label :t/send) :label (i18n/label :t/send)
:disabled? (:disabled? send-params) :disabled? disabled?
:on-press (fn [] :on-press (fn []
(rf/dispatch [:hide-bottom-sheet]) (rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:wallet/clean-send-data]) (rf/dispatch [:wallet/clean-send-data])
(rf/dispatch [:wallet/set-token-to-send send-params entry-point]))}) (rf/dispatch [:wallet/set-token-to-send params entry-point]))})
(defn- action-receive (defn- action-receive
[selected-account?] [selected-account?]
@ -38,21 +37,25 @@
#(rf/dispatch [:open-modal :screen/share-shell {:initial-tab :wallet}]))}) #(rf/dispatch [:open-modal :screen/share-shell {:initial-tab :wallet}]))})
(defn- action-bridge (defn- action-bridge
[bridge-params] [{:keys [bridge-disabled?] :as params}]
{:icon :i/bridge {:icon :i/bridge
:accessibility-label :bridge :accessibility-label :bridge
:label (i18n/label :t/bridge) :label (i18n/label :t/bridge)
:disabled? (:bridge-disabled? bridge-params) :disabled? bridge-disabled?
:on-press (fn [] :on-press (fn []
(rf/dispatch [:hide-bottom-sheet]) (rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:wallet/bridge-select-token bridge-params]))}) (rf/dispatch [:wallet/bridge-select-token params]))})
(defn- action-swap (defn- action-swap
[] [{:keys [token token-symbol]}]
{:icon :i/swap {:icon :i/swap
:accessibility-label :swap :accessibility-label :swap
:label (i18n/label :t/swap) :label (i18n/label :t/swap)
:on-press #(not-implemented/alert)}) :on-press (fn []
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:wallet.swap/start
{:asset-to-pay (or token {:symbol token-symbol})
:open-new-screen? true}]))})
(defn- action-manage-tokens (defn- action-manage-tokens
[watch-only?] [watch-only?]
@ -71,47 +74,37 @@
(defn token-value-drawer (defn token-value-drawer
[token watch-only? entry-point] [token watch-only? entry-point]
(let [token-symbol (:token token) (let [token-symbol (:token token)
token-data (first (rf/sub [:wallet/current-viewing-account-tokens-filtered token-data (first (rf/sub [:wallet/current-viewing-account-tokens-filtered
{:query token-symbol}])) {:query token-symbol}]))
fiat-unformatted-value (get-in token [:values :fiat-unformatted-value]) selected-account (rf/sub [:wallet/current-viewing-account-address])
has-balance? (money/greater-than fiat-unformatted-value (money/bignumber "0")) token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
selected-account? (rf/sub [:wallet/current-viewing-account-address]) params (cond-> {:start-flow? true
token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
send-params (if selected-account?
{:token token-data
:stack-id :screen/wallet.accounts
:disabled? (not has-balance?)
:start-flow? true
:owners token-owners} :owners token-owners}
{:token-symbol token-symbol selected-account
:stack-id :wallet-stack (assoc :token token-data
:start-flow? true :stack-id :screen/wallet.accounts
:owners token-owners}) :has-balance? (-> (get-in token [:values :fiat-unformatted-value])
bridge-params (if selected-account? (money/greater-than (money/bignumber "0"))))
{:token token-data (not selected-account)
:bridge-disabled? (or (not has-balance?) (assoc :token-symbol token-symbol
(send-utils/bridge-disabled? token-symbol)) :stack-id :wallet-stack))]
:stack-id :screen/wallet.accounts
:start-flow? true
:owners token-owners}
{:token-symbol token-symbol
:bridge-disabled? (send-utils/bridge-disabled? token-symbol)
:stack-id :wallet-stack
:start-flow? true
:owners token-owners})]
[quo/action-drawer [quo/action-drawer
[(cond->> [(when (ff/enabled? ::ff/wallet.assets-modal-manage-tokens) [(cond->> [(when (ff/enabled? ::ff/wallet.assets-modal-manage-tokens)
(action-manage-tokens watch-only?)) (action-manage-tokens watch-only?))
(when (ff/enabled? ::ff/wallet.assets-modal-hide) (when (ff/enabled? ::ff/wallet.assets-modal-hide)
(action-hide))] (action-hide))]
(not watch-only?) (concat [(action-buy) (not watch-only?)
(when (seq token-owners) (concat [(action-buy)
(action-send send-params entry-point)) (when (seq token-owners)
(action-receive selected-account?) (action-send params entry-point))
(when (ff/enabled? ::ff/wallet.swap) (action-swap)) (action-receive selected-account)
(when (seq (seq token-owners)) (when (ff/enabled? ::ff/wallet.swap)
(action-bridge bridge-params))]))]])) (action-swap params))
(when (seq token-owners)
(action-bridge (assoc params
:bridge-disabled?
(send-utils/bridge-disabled? token-symbol))))]))]]))
(defn view (defn view
[item _ _ {:keys [watch-only? entry-point]}] [item _ _ {:keys [watch-only? entry-point]}]

View File

@ -14,22 +14,36 @@
[utils.number :as number])) [utils.number :as number]))
(rf/reg-event-fx :wallet.swap/start (rf/reg-event-fx :wallet.swap/start
(fn [{:keys [db]} [{:keys [asset-to-pay asset-to-receive network]}]] (fn [{:keys [db]} [{:keys [network open-new-screen?] :as data}]]
(let [asset-to-receive' (or asset-to-receive (let [{:keys [wallet]} db
(swap-utils/select-asset-to-receive test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
(:wallet db) account (swap-utils/wallet-account wallet)
(:profile/profile db) asset-to-pay (if (get-in data [:asset-to-pay :networks])
asset-to-pay)) (:asset-to-pay data)
network' (or network (swap-utils/select-asset-to-pay-by-symbol
(swap-utils/select-network asset-to-pay))] {:wallet wallet
:account account
:test-networks-enabled? test-networks-enabled?
:token-symbol (get-in data [:asset-to-pay :symbol])}))
asset-to-receive (or (:asset-to-receive data)
(swap-utils/select-default-asset-to-receive
{:wallet wallet
:account account
:test-networks-enabled? test-networks-enabled?
:asset-to-pay asset-to-pay}))
network' (or network
(swap-utils/select-network asset-to-pay))]
{:db (-> db {:db (-> db
(assoc-in [:wallet :ui :swap :asset-to-pay] asset-to-pay) (assoc-in [:wallet :ui :swap :asset-to-pay] asset-to-pay)
(assoc-in [:wallet :ui :swap :asset-to-receive] asset-to-receive') (assoc-in [:wallet :ui :swap :asset-to-receive] asset-to-receive)
(assoc-in [:wallet :ui :swap :network] network')) (assoc-in [:wallet :ui :swap :network] network'))
:fx (if network' :fx (if network'
[[:dispatch [[:dispatch [:wallet/switch-current-viewing-account (:address account)]]
[:navigate-to-within-stack [:dispatch
[:screen/wallet.setup-swap :screen/wallet.swap-select-asset-to-pay]]] (if open-new-screen?
[:navigate-to :screen/wallet.setup-swap]
[:navigate-to-within-stack
[:screen/wallet.setup-swap :screen/wallet.swap-select-asset-to-pay]])]
[:dispatch [:wallet.swap/set-default-slippage]]] [:dispatch [:wallet.swap/set-default-slippage]]]
[[:dispatch [[:dispatch
[:show-bottom-sheet [:show-bottom-sheet
@ -41,8 +55,9 @@
(rf/dispatch (rf/dispatch
[:wallet.swap/start [:wallet.swap/start
{:asset-to-pay asset-to-pay {:asset-to-pay asset-to-pay
:asset-to-receive asset-to-receive' :asset-to-receive asset-to-receive
:network network}]))}])}]]])}))) :network network
:open-new-screen? open-new-screen?}]))}])}]]])})))
(rf/reg-event-fx :wallet.swap/select-asset-to-pay (rf/reg-event-fx :wallet.swap/select-asset-to-pay
(fn [{:keys [db]} [{:keys [token]}]] (fn [{:keys [db]} [{:keys [token]}]]

View File

@ -21,7 +21,9 @@
(defn- assets-view (defn- assets-view
[search-text on-change-text] [search-text on-change-text]
(let [on-token-press (fn [token] (let [on-token-press (fn [token]
(rf/dispatch [:wallet.swap/start {:asset-to-pay token}]))] (rf/dispatch [:wallet.swap/start
{:asset-to-pay token
:open-new-screen? false}]))]
[:<> [:<>
[search-input search-text on-change-text] [search-input search-text on-change-text]
[asset-list/view [asset-list/view

View File

@ -30,22 +30,61 @@
:else :else
(i18n/label :t/something-went-wrong-please-try-again-later))) (i18n/label :t/something-went-wrong-please-try-again-later)))
(defn select-asset-to-receive (defn- first-operable-account
[wallet profile asset-to-pay] [accounts]
(let [wallet-address (get-in wallet [:current-viewing-account-address]) (->> accounts
account (-> wallet vals
:accounts (remove :watch-only?)
vals (filter :operable?)
(utils/get-account-by-address wallet-address)) (sort-by :position)
test-networks-enabled? (get profile :test-networks-enabled?) first))
networks (-> (get-in wallet
[:wallet :networks (if test-networks-enabled? :test :prod)]) (defn wallet-account
(network-utils/sorted-networks-with-details))] "Picks the account that's gonna be used for the swap operation.
It's gonna be either the preselected account defined by
`[:wallet :current-viewing-account-address]` in `db`
or the first operable account."
[wallet]
(if-let [wallet-address (get wallet :current-viewing-account-address)]
(-> wallet
:accounts
vals
(utils/get-account-by-address wallet-address))
(-> wallet :accounts first-operable-account)))
(defn select-asset-to-pay-by-symbol
"Selects an asset to pay by token symbol.
It's used for cases when only token symbol is available and the information
about token needs to be extracted from the database.
That happens when token is being selected on the home screen and
it basically indicates that no account pre-selection was made."
[{:keys [wallet account test-networks-enabled? token-symbol]}]
(let [networks (-> (get-in wallet [:networks (if test-networks-enabled? :test :prod)])
(network-utils/sorted-networks-with-details))
token (->> account
:tokens
(filter #(= token-symbol (:symbol %)))
first)]
(assoc token :networks (network-utils/network-list token networks))))
(defn select-default-asset-to-receive
"Selects an asset to receive if it was not provided explicitly.
The principle of how the asset is being selected is simple: we get the
whole list, remove the currently selected `asset-to-pay` from it, and choose
the first one of what's left."
[{:keys [wallet account test-networks-enabled? asset-to-pay]}]
(let [networks (-> (get-in wallet [:networks (if test-networks-enabled? :test :prod)])
(network-utils/sorted-networks-with-details))]
(->> (utils/tokens-with-balance (:tokens account) networks nil) (->> (utils/tokens-with-balance (:tokens account) networks nil)
(remove #(= (:symbol %) (:symbol asset-to-pay))) (remove #(= (:symbol %) (:symbol asset-to-pay)))
first))) first)))
(defn select-network (defn select-network
"Chooses the network.
Usually user needs to do the selection first and if the selection was done
then the list of networks for the defined token will always contain
one entry. Otherwise `nil` will be returned from here which will serve
as an indicator that the network selector needs to be displayed."
[{:keys [networks]}] [{:keys [networks]}]
(when (= (count networks) 1) (when (= (count networks) 1)
(first networks))) (first networks)))