* [#21557] feat: show from account page in swap flow * [#21557] feat: add disabled state to account-item * [#21557] fix: apply suggestion * [#21557] fix: add format address util and rename screen * [#21557] fix: check and count account with token balance * [#21557] fix: check for root screen
This commit is contained in:
parent
26ae330476
commit
21c2a525cf
|
@ -23,7 +23,7 @@
|
|||
[:map
|
||||
[:type {:optional true}
|
||||
[:enum :default :tag :action :balance-neutral :balance-negative :balance-positive]]
|
||||
[:state {:optional true} [:enum :default :selected :active]]
|
||||
[:state {:optional true} [:enum :default :selected :active :disabled]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:on-press {:optional true} [:maybe fn?]]
|
||||
|
|
|
@ -12,12 +12,13 @@
|
|||
:else :transparent))
|
||||
|
||||
(defn container
|
||||
[props]
|
||||
[{:keys [state] :as props}]
|
||||
{:height 56
|
||||
:border-radius 12
|
||||
:background-color (background-color props)
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:opacity (if (= state :disabled) 0.3 1)
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 6
|
||||
:justify-content :space-between})
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
:pressed? pressed?})
|
||||
:on-press-in on-press-in
|
||||
:on-press on-press
|
||||
:disabled (= state :disabled)
|
||||
:on-press-out on-press-out
|
||||
:accessibility-label :container}
|
||||
[account-view props]
|
||||
|
|
|
@ -548,3 +548,27 @@
|
|||
(:less-than-three-minutes constants/wallet-transaction-estimation) "1-3"
|
||||
(:less-than-five-minutes constants/wallet-transaction-estimation) "3-5"
|
||||
">5"))
|
||||
|
||||
(defn get-accounts-with-token-balance
|
||||
[accounts token]
|
||||
(let [operable-account (filter :operable? (vals accounts))
|
||||
positive-balance-in-any-chain? (fn [{:keys [balances-per-chain]}]
|
||||
(->> balances-per-chain
|
||||
(map (comp :raw-balance val))
|
||||
(some pos?)))
|
||||
addresses-tokens-with-positive-balance (as-> operable-account $
|
||||
(group-by :address $)
|
||||
(update-vals $
|
||||
#(filter positive-balance-in-any-chain?
|
||||
(:tokens (first %)))))]
|
||||
(if-let [asset-symbol (:symbol token)]
|
||||
(let [addresses-with-asset (as-> addresses-tokens-with-positive-balance $
|
||||
(update-vals $ #(set (map :symbol %)))
|
||||
(keep (fn [[address token-symbols]]
|
||||
(when (token-symbols asset-symbol) address))
|
||||
$)
|
||||
(set $))]
|
||||
(filter #(addresses-with-asset (:address %)) operable-account))
|
||||
(filter (fn [{:keys [tokens]}]
|
||||
(some positive-balance-in-any-chain? tokens))
|
||||
operable-account))))
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[utils.number]))
|
||||
|
||||
(def ^:private last-comma-followed-by-text-to-end-regex #",\s(?=[^,]+$)")
|
||||
(def ^:private max-network-prefixes 2)
|
||||
|
||||
(def id->network
|
||||
{constants/ethereum-mainnet-chain-id constants/mainnet-network-name
|
||||
|
@ -185,3 +186,11 @@
|
|||
:related-chain-id related-chain-id
|
||||
:layer layer)))
|
||||
(sort-by (juxt :layer :short-name))))
|
||||
|
||||
(defn format-address
|
||||
[address network-preferences]
|
||||
(let [short-names (map network->short-name network-preferences)
|
||||
prefix (when (<= (count short-names) max-network-prefixes)
|
||||
(short-names->network-preference-prefix short-names))
|
||||
transformed-address (str prefix address)]
|
||||
transformed-address))
|
||||
|
|
|
@ -269,3 +269,68 @@
|
|||
expected "0"]
|
||||
(is (= (utils/token-balance-display-for-network token chain-id rounding-decimals)
|
||||
expected)))))
|
||||
|
||||
(def mock-accounts
|
||||
{:0xfc6327a092f6232e158a0dd1d6d967a2e1c65cd5
|
||||
{:address "0xfc6327a092f6232e158a0dd1d6d967a2e1c65cd5"
|
||||
:operable? true
|
||||
:tokens [{:symbol "ETH"
|
||||
:balances-per-chain {1 {:raw-balance 1000000
|
||||
:balance 1.0}}}
|
||||
{:symbol "USDC"
|
||||
:balances-per-chain {1 {:raw-balance 0
|
||||
:balance 0}}}]}
|
||||
:0xbce36f66a8cd99f1d6489cb9585146e3f3b893be
|
||||
{:address "0xbce36f66a8cd99f1d6489cb9585146e3f3b893be"
|
||||
:operable? true
|
||||
:tokens [{:symbol "ETH"
|
||||
:balances-per-chain {1 {:raw-balance 0
|
||||
:balance 0}}}]}})
|
||||
|
||||
(deftest get-accounts-with-token-balance-test
|
||||
(testing "Positive token balance for a specific token"
|
||||
(let [accounts mock-accounts
|
||||
token {:symbol "ETH"}
|
||||
expected [{:address "0xfc6327a092f6232e158a0dd1d6d967a2e1c65cd5"
|
||||
:operable? true
|
||||
:tokens [{:symbol "ETH"
|
||||
:balances-per-chain {1 {:raw-balance 1000000
|
||||
:balance 1.0}}}
|
||||
{:symbol "USDC"
|
||||
:balances-per-chain {1 {:raw-balance 0
|
||||
:balance 0}}}]}]]
|
||||
(is (= (utils/get-accounts-with-token-balance accounts token)
|
||||
expected))))
|
||||
|
||||
(testing "No token symbol provided, return all tokens with positive balance"
|
||||
(let [accounts mock-accounts
|
||||
token {}
|
||||
expected [{:address "0xfc6327a092f6232e158a0dd1d6d967a2e1c65cd5"
|
||||
:operable? true
|
||||
:tokens [{:symbol "ETH"
|
||||
:balances-per-chain {1 {:raw-balance 1000000
|
||||
:balance 1.0}}}
|
||||
{:symbol "USDC"
|
||||
:balances-per-chain {1 {:raw-balance 0
|
||||
:balance 0}}}]}]]
|
||||
(is (= (utils/get-accounts-with-token-balance accounts token)
|
||||
expected))))
|
||||
|
||||
(testing "No matching token found for a specific token"
|
||||
(let [accounts mock-accounts
|
||||
token {:symbol "DAI"}
|
||||
expected []]
|
||||
(is (= (utils/get-accounts-with-token-balance accounts token)
|
||||
expected))))
|
||||
|
||||
(testing "No operable accounts"
|
||||
(let [accounts {:0xfc6327a092f6232e158a0dd1d6d967a2e1c65cd5
|
||||
{:address "0xfc6327a092f6232e158a0dd1d6d967a2e1c65cd5"
|
||||
:operable? false
|
||||
:tokens [{:symbol "ETH"
|
||||
:balances-per-chain {1 {:raw-balance 1000000
|
||||
:balance 1.0}}}]}}
|
||||
token {}
|
||||
expected []]
|
||||
(is (= (utils/get-accounts-with-token-balance accounts token)
|
||||
expected)))))
|
||||
|
|
|
@ -14,11 +14,12 @@
|
|||
[utils.number :as number]))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/start
|
||||
(fn [{:keys [db]} [{:keys [network asset-to-receive open-new-screen?] :as data}]]
|
||||
(fn [{:keys [db]} [{:keys [network asset-to-receive open-new-screen? from-account] :as data}]]
|
||||
(let [{:keys [wallet]} db
|
||||
test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
|
||||
view-id (:view-id db)
|
||||
account (swap-utils/wallet-account wallet)
|
||||
root-screen? (or (= view-id :wallet-stack) (nil? view-id))
|
||||
account (or from-account (swap-utils/wallet-account wallet))
|
||||
asset-to-pay (if (get-in data [:asset-to-pay :networks])
|
||||
(:asset-to-pay data)
|
||||
(swap-utils/select-asset-to-pay-by-symbol
|
||||
|
@ -26,6 +27,10 @@
|
|||
:account account
|
||||
:test-networks-enabled? test-networks-enabled?
|
||||
:token-symbol (get-in data [:asset-to-pay :symbol])}))
|
||||
multi-account-balance? (-> (utils/get-accounts-with-token-balance (:accounts wallet)
|
||||
asset-to-pay)
|
||||
(count)
|
||||
(> 1))
|
||||
network' (or network
|
||||
(swap-utils/select-network asset-to-pay))
|
||||
start-point (if open-new-screen? :action-menu :swap-button)]
|
||||
|
@ -35,7 +40,9 @@
|
|||
(assoc-in [:wallet :ui :swap :network] network')
|
||||
(assoc-in [:wallet :ui :swap :launch-screen] view-id)
|
||||
(assoc-in [:wallet :ui :swap :start-point] start-point))
|
||||
:fx (if network'
|
||||
:fx (if (and multi-account-balance? root-screen? (not from-account))
|
||||
[[:dispatch [:open-modal :screen/wallet.swap-select-account]]]
|
||||
(if network'
|
||||
[[:dispatch [:wallet/switch-current-viewing-account (:address account)]]
|
||||
[:dispatch
|
||||
(if open-new-screen?
|
||||
|
@ -62,7 +69,9 @@
|
|||
{:asset-to-pay asset-to-pay
|
||||
:asset-to-receive asset-to-receive
|
||||
:network network
|
||||
:open-new-screen? open-new-screen?}]))}])}]]])})))
|
||||
:open-new-screen?
|
||||
open-new-screen?
|
||||
:from-account from-account}]))}])}]]]))})))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/select-asset-to-pay
|
||||
(fn [{:keys [db]} [{:keys [token]}]]
|
||||
|
@ -527,3 +536,15 @@
|
|||
[:dispatch [:wallet/navigate-to-account-within-stack address]])
|
||||
[:dispatch [:wallet/fetch-activities-for-current-account]]
|
||||
[:dispatch [:wallet/select-account-tab :activity]]]})))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/start-from-account
|
||||
(fn [{:keys [db]} [account]]
|
||||
(let [asset-to-pay (get-in db [:wallet :ui :swap :asset-to-pay])
|
||||
asset-to-receive (get-in db [:wallet :ui :swap :asset-to-receive])]
|
||||
{:fx [[:dispatch [:dismiss-modal :screen/wallet.swap-select-account]]
|
||||
[:dispatch
|
||||
[:wallet.swap/start
|
||||
{:asset-to-pay asset-to-pay
|
||||
:asset-to-receive asset-to-receive
|
||||
:open-new-screen? true
|
||||
:from-account account}]]]})))
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
(ns status-im.contexts.wallet.swap.select-account.style)
|
||||
|
||||
(def accounts-list
|
||||
{:padding-bottom 12})
|
||||
|
||||
(def accounts-list-container
|
||||
{:padding-horizontal 8})
|
|
@ -0,0 +1,52 @@
|
|||
(ns status-im.contexts.wallet.swap.select-account.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.events-helper :as events-helper]
|
||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.contexts.wallet.swap.select-account.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- on-account-press
|
||||
[account]
|
||||
(rf/dispatch [:wallet.swap/start-from-account account]))
|
||||
|
||||
(defn- render-fn
|
||||
[item _ _]
|
||||
(let [has-balance (money/above-zero? (:asset-pay-balance item))]
|
||||
[quo/account-item
|
||||
{:type (if has-balance :tag :default)
|
||||
:on-press #(on-account-press item)
|
||||
:state (if has-balance :default :disabled)
|
||||
:token-props {:symbol (:asset-pay-symbol item)
|
||||
:value (:asset-pay-balance item)}
|
||||
:account-props (assoc item
|
||||
:address (:formatted-address item)
|
||||
:full-address? true)}]))
|
||||
|
||||
(defn- on-close
|
||||
[]
|
||||
(rf/dispatch [:wallet/clean-current-viewing-account])
|
||||
(events-helper/navigate-back))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [accounts (rf/sub [:wallet/accounts-with-balances])]
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
:header [quo/page-nav
|
||||
{:margin-top (safe-area/get-top)
|
||||
:icon-name :i/close
|
||||
:on-press on-close}]}
|
||||
[quo/page-top
|
||||
{:title (i18n/label :t/from-label)
|
||||
:title-accessibility-label :title-label}]
|
||||
[rn/flat-list
|
||||
{:style style/accounts-list
|
||||
:content-container-style style/accounts-list-container
|
||||
:data accounts
|
||||
:render-fn render-fn
|
||||
:shows-horizontal-scroll-indicator false}]]))
|
|
@ -134,6 +134,7 @@
|
|||
[status-im.contexts.wallet.send.send-amount.view :as wallet-send-input-amount]
|
||||
[status-im.contexts.wallet.send.transaction-confirmation.view :as wallet-transaction-confirmation]
|
||||
[status-im.contexts.wallet.send.transaction-progress.view :as wallet-transaction-progress]
|
||||
[status-im.contexts.wallet.swap.select-account.view :as wallet-swap-select-account]
|
||||
[status-im.contexts.wallet.swap.select-asset-to-pay.view :as wallet-swap-select-asset-to-pay]
|
||||
[status-im.contexts.wallet.swap.set-spending-cap.view :as wallet-swap-set-spending-cap]
|
||||
[status-im.contexts.wallet.swap.setup-swap.view :as wallet-swap-setup-swap]
|
||||
|
@ -635,6 +636,12 @@
|
|||
:insets {:top? true}}
|
||||
:component wallet-swap-select-asset-to-pay/view}
|
||||
|
||||
{:name :screen/wallet.swap-select-account
|
||||
:metrics {:track? true}
|
||||
:options {:modalPresentationStyle :overCurrentContext
|
||||
:insets {:bottom? true}}
|
||||
:component wallet-swap-select-account/view}
|
||||
|
||||
{:name :screen/wallet.setup-swap
|
||||
:metrics {:track? true
|
||||
:alias-id :wallet-swap.input-amount-to-swap}
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
[utils.money :as money]
|
||||
[utils.number :as number]))
|
||||
|
||||
(def max-network-prefixes 2)
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/networks
|
||||
:<- [:wallet]
|
||||
|
@ -53,12 +51,7 @@
|
|||
(re-frame/reg-sub
|
||||
:wallet/account-address
|
||||
(fn [_ [_ address network-preferences]]
|
||||
(let [short-names (map network-utils/network->short-name network-preferences)
|
||||
prefix (when (<= (count short-names) max-network-prefixes)
|
||||
(network-utils/short-names->network-preference-prefix
|
||||
short-names))
|
||||
transformed-address (str prefix address)]
|
||||
transformed-address)))
|
||||
(network-utils/format-address address network-preferences)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/network-values
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
[re-frame.core :as rf]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.common.utils.networks :as network-utils]
|
||||
[status-im.contexts.wallet.send.utils :as send-utils]
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]))
|
||||
|
@ -315,3 +316,23 @@
|
|||
:token token-for-fees})]
|
||||
fee-in-fiat)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/accounts-with-balances
|
||||
:<- [:wallet/operable-accounts]
|
||||
:<- [:wallet/swap-asset-to-pay]
|
||||
(fn [[accounts asset-to-pay]]
|
||||
(let [token-symbol (:symbol asset-to-pay)]
|
||||
(map
|
||||
(fn [account]
|
||||
(let [tokens (:tokens account)
|
||||
filtered-tokens (filter #(= (:symbol %) token-symbol) tokens)
|
||||
asset-pay-balance (utils/calculate-total-token-balance filtered-tokens)
|
||||
formatted-address (network-utils/format-address (:address account)
|
||||
(:network-preferences-names account))]
|
||||
(assoc account
|
||||
:formatted-address formatted-address
|
||||
:asset-pay-balance (utils/sanitized-token-amount-to-display
|
||||
asset-pay-balance
|
||||
constants/min-token-decimals-to-display)
|
||||
:asset-pay-symbol token-symbol)))
|
||||
accounts))))
|
||||
|
|
Loading…
Reference in New Issue