feat(wallet): Skip From page while sending an asset only owned by one account (#20773)

- Update tests

- Omit from page while sending a token in home page

- Hide send and bridge option for not owned tokens

- Fix subscription to return accounts owning an asset
This commit is contained in:
Ulises Manuel 2024-07-23 16:08:33 -06:00 committed by GitHub
parent 8597b899bd
commit e4639c153f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 140 additions and 61 deletions

View File

@ -262,7 +262,7 @@
can-edit-addresses? (rf/sub [:communities/can-edit-shared-addresses? id])
wallet-accounts (rf/sub [:wallet/operable-accounts-without-watched-accounts])
wallet-accounts (rf/sub [:wallet/operable-accounts])
joined (rf/sub [:communities/community-joined id])
unmodified-addresses-to-reveal (rf/sub [:communities/addresses-to-reveal id])
[addresses-to-reveal set-addresses-to-reveal] (rn/use-state unmodified-addresses-to-reveal)

View File

@ -16,14 +16,14 @@
:right-icon :i/external})
(defn- action-send
[send-params]
[send-params entry-point]
{:icon :i/send
:accessibility-label :send
:label (i18n/label :t/send)
:on-press (fn []
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:wallet/clean-send-data])
(rf/dispatch [:wallet/set-token-to-send send-params]))})
(rf/dispatch [:wallet/set-token-to-send send-params entry-point]))})
(defn- action-receive
[selected-account?]
@ -66,36 +66,41 @@
:on-press #(js/alert "to be implemented")})
(defn token-value-drawer
[token watch-only?]
[token watch-only? entry-point]
(let [token-symbol (:token token)
token-data (first (rf/sub [:wallet/current-viewing-account-tokens-filtered
token-symbol]))
selected-account? (rf/sub [:wallet/current-viewing-account-address])
token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
send-or-bridge-params (if selected-account?
{:token token-data
:stack-id :screen/wallet.accounts
:start-flow? true}
:start-flow? true
:owners token-owners}
{:token-symbol token-symbol
:stack-id :wallet-stack
:start-flow? true})]
:start-flow? true
:owners token-owners})]
[quo/action-drawer
[(cond->> [(when (ff/enabled? ::ff/wallet.assets-modal-manage-tokens)
(action-manage-tokens watch-only?))
(when (ff/enabled? ::ff/wallet.assets-modal-hide)
(action-hide))]
(not watch-only?) (concat [(action-buy)
(action-send send-or-bridge-params)
(when (seq token-owners)
(action-send send-or-bridge-params entry-point))
(action-receive selected-account?)
(when (ff/enabled? ::ff/wallet.swap) (action-swap))
(action-bridge send-or-bridge-params)]))]]))
(when (seq (seq token-owners))
(action-bridge send-or-bridge-params))]))]]))
(defn view
[item _ _ {:keys [watch-only?]}]
[item _ _ {:keys [watch-only? entry-point]}]
[quo/token-value
(cond-> item
(or (not watch-only?) (ff/enabled? ::ff/wallet.long-press-watch-only-asset))
(assoc :on-long-press
#(rf/dispatch
[:show-bottom-sheet
{:content (fn [] [token-value-drawer item watch-only?])
{:content (fn [] [token-value-drawer item watch-only? entry-point])
:selected-item (fn [] [quo/token-value item])}])))])

View File

@ -65,10 +65,21 @@
{:db (assoc-in db [:wallet :current-viewing-account-address] address)}))
(rf/reg-event-fx :wallet/clean-current-viewing-account
(fn [{:keys [db]}]
(let [just-completed-transaction? (get-in db [:wallet :ui :send :just-completed-transaction?])]
(when-not just-completed-transaction?
{:db (update db :wallet dissoc :current-viewing-account-address)}))))
(fn [{:keys [db]} [ignore-just-completed-transaction?]]
(let [{:keys [entry-point just-completed-transaction?]} (-> db :wallet :ui :send)
entry-point-wallet-home? (= entry-point :wallet-stack)]
{:db (cond-> db
(and (not entry-point)
(not ignore-just-completed-transaction?)
(not just-completed-transaction?))
(update :wallet dissoc :current-viewing-account-address)
entry-point-wallet-home?
(update-in [:wallet :ui :send] dissoc :entry-point)
(and entry-point-wallet-home?
(not just-completed-transaction?))
(update :wallet dissoc :current-viewing-account-address))})))
(rf/reg-event-fx :wallet/close-account-page
(fn [{:keys [db]}]

View File

@ -18,4 +18,5 @@
[rn/flat-list
{:render-fn token-value/view
:data tokens
:render-data {:entry-point :wallet-stack}
:content-container-style style/list-container}])))

View File

@ -193,25 +193,35 @@
(rf/reg-event-fx
:wallet/set-token-to-send
(fn [{:keys [db]} [{:keys [token-symbol token stack-id start-flow?]}]]
(fn [{:keys [db]} [{:keys [token-symbol token stack-id start-flow? owners]} entry-point]]
;; `token` is a map extracted from the sender, but in the wallet home page we don't know the
;; sender yet, so we only provide the `token-symbol`, later in
;; `:wallet/select-from-account` the `token` key will be set.
(let [{token-networks :networks} token
(let [{:keys [networks]} token
receiver-networks (get-in db [:wallet :ui :send :receiver-networks])
token-networks-ids (mapv #(:chain-id %) token-networks)
token-not-supported-in-receiver-networks? (not-any? (set receiver-networks)
token-networks-ids)]
(when (or token token-symbol)
token-networks-ids (map :chain-id networks)
unsupported-token? (not-any? (set receiver-networks) token-networks-ids)
unique-owner (when (= (count owners) 1)
(first owners))
unique-owner-tokens (get-in db [:wallet :accounts unique-owner :tokens])
token-data (or token
(when (and token-symbol unique-owner)
(some #(when (= (:symbol %) token-symbol) %)
unique-owner-tokens)))]
(when (or token-data token-symbol)
{:db (cond-> db
:always (update-in [:wallet :ui :send] dissoc :collectible)
:always (assoc-in
[:wallet :ui :send :token-not-supported-in-receiver-networks?]
token-not-supported-in-receiver-networks?)
token (assoc-in [:wallet :ui :send :token] token)
token (assoc-in [:wallet :ui :send :token-display-name]
(:symbol token))
token-symbol (assoc-in [:wallet :ui :send :token-symbol] token-symbol))
:always (update-in [:wallet :ui :send]
#(-> %
(dissoc :collectible)
(assoc :token-not-supported-in-receiver-networks?
unsupported-token?)))
token-symbol (assoc-in [:wallet :ui :send :token-symbol] token-symbol)
token-data (update-in [:wallet :ui :send]
#(assoc %
:token token-data
:token-display-name (:symbol token-data)))
unique-owner (assoc-in [:wallet :current-viewing-account-address] unique-owner)
entry-point (assoc-in [:wallet :ui :send :entry-point] entry-point))
:fx [[:dispatch [:wallet/clean-suggested-routes]]
[:dispatch
[:wallet/wizard-navigate-forward
@ -225,9 +235,9 @@
(let [{token-networks :networks
token-symbol :symbol} token
receiver-networks (get-in db [:wallet :ui :send :receiver-networks])
token-networks-ids (mapv #(:chain-id %) token-networks)
token-not-supported-in-receiver-networks? (not (some (set receiver-networks)
token-networks-ids))]
token-networks-ids (map :chain-id token-networks)
token-not-supported-in-receiver-networks? (not-any? (set receiver-networks)
token-networks-ids)]
{:db (-> db
(assoc-in [:wallet :ui :send :token] token)
(assoc-in [:wallet :ui :send :token-display-name] token-symbol)
@ -256,7 +266,9 @@
(rf/reg-event-fx
:wallet/set-collectible-to-send
(fn [{db :db} [{:keys [collectible current-screen start-flow?]}]]
(let [collection-data (:collection-data collectible)
(let [viewing-account? (some? (-> db :wallet :current-viewing-account-address))
entry-point (when-not viewing-account? :wallet-stack)
collection-data (:collection-data collectible)
collectible-data (:collectible-data collectible)
contract-type (:contract-type collectible)
tx-type (if (= contract-type constants/wallet-contract-type-erc-1155)
@ -271,6 +283,7 @@
collectible
(str (:name collection-data) " #" collectible-id))
owner-address (-> collectible :ownership first :address)
collectible-tx (-> db
(update-in [:wallet :ui :send] dissoc :token)
(assoc-in [:wallet :ui :send :collectible] collectible)
@ -278,7 +291,14 @@
(assoc-in [:wallet :ui :send :tx-type] tx-type))
recipient-set? (-> db :wallet :ui :send :recipient)]
{:db (cond-> collectible-tx
one-collectible? (assoc-in [:wallet :ui :send :amount] 1))
:always
(assoc-in [:wallet :ui :send :entry-point] entry-point)
(not viewing-account?)
(assoc-in [:wallet :current-viewing-account-address] owner-address)
one-collectible?
(assoc-in [:wallet :ui :send :amount] 1))
:fx [(when (and one-collectible? recipient-set?)
[:dispatch [:wallet/get-suggested-routes {:amount 1}]])
[:dispatch

View File

@ -42,7 +42,6 @@
{:on-press #(rf/dispatch [:navigate-back])
:margin-top (safe-area/get-top)
:switcher-type :select-account}]}
[quo/page-top
{:title (i18n/label :t/from-label)
:title-accessibility-label :title-label}]

View File

@ -177,7 +177,9 @@
(rf/dispatch [:wallet/clean-selected-collectible])
(rf/dispatch [:wallet/clean-send-address])
(rf/dispatch [:wallet/clean-disabled-from-networks])
(rf/dispatch [:wallet/select-address-tab nil]))
(rf/dispatch [:wallet/select-address-tab nil])
(rf/dispatch [:wallet/clean-current-viewing-account
:ignore-just-complete-transaction]))
on-change-tab #(rf/dispatch [:wallet/select-address-tab %])
input-value (reagent/atom "")
input-focused? (reagent/atom false)]

View File

@ -20,7 +20,7 @@
(defn view
[]
(let [selected-account-address (rf/sub [:wallet/current-viewing-account-address])
accounts (rf/sub [:wallet/operable-accounts-without-watched-accounts])]
accounts (rf/sub [:wallet/operable-accounts])]
[:<>
[quo/drawer-top {:title (i18n/label :t/select-account)}]
[gesture/flat-list

View File

@ -70,7 +70,7 @@
(defn- accounts-list
[]
(let [accounts (rf/sub [:wallet/operable-accounts-without-watched-accounts])
(let [accounts (rf/sub [:wallet/operable-accounts])
selected-address (rf/sub [:wallet-connect/current-proposal-address])]
[rn/view {:style style/account-switcher-list}
(for [{:keys [address] :as account} accounts]

View File

@ -53,7 +53,7 @@
(re-frame/reg-sub :communities/accounts-to-reveal
(fn [[_ community-id]]
[(re-frame/subscribe [:wallet/operable-accounts-without-watched-accounts])
[(re-frame/subscribe [:wallet/operable-accounts])
(re-frame/subscribe [:communities/addresses-to-reveal community-id])])
(fn [[accounts addresses] _]
(filter #(contains? addresses (:address %))
@ -61,7 +61,7 @@
(re-frame/reg-sub :communities/airdrop-account
(fn [[_ community-id]]
[(re-frame/subscribe [:wallet/operable-accounts-without-watched-accounts])
[(re-frame/subscribe [:wallet/operable-accounts])
(re-frame/subscribe [:communities/airdrop-address community-id])])
(fn [[accounts airdrop-address] _]
(->> accounts

View File

@ -134,10 +134,12 @@
(:chain-id %))))
(map :chain-id)
set)]
(assoc token
:networks (network-utils/network-list token networks)
(some-> token
(assoc :networks (network-utils/network-list token networks)
:available-balance (utils/calculate-total-token-balance token)
:total-balance (utils/calculate-total-token-balance token enabled-from-chain-ids)))))
:total-balance (utils/calculate-total-token-balance
token
enabled-from-chain-ids))))))
(rf/reg-sub
:wallet/wallet-send-token-symbol
@ -464,22 +466,47 @@
keep-operable-accounts)
(rf/reg-sub
:wallet/operable-accounts-without-watched-accounts
:wallet/operable-accounts
:<- [:wallet/accounts-without-watched-accounts]
keep-operable-accounts)
(rf/reg-sub
:wallet/operable-addresses-tokens-with-positive-balance
:<- [:wallet/operable-accounts]
(fn [accounts]
(let [positive-balance-in-any-chain? (fn [{:keys [balances-per-chain]}]
(->> balances-per-chain
(map (comp :raw-balance val))
(some pos?)))]
(as-> accounts $
(group-by :address $)
(update-vals $ #(filter positive-balance-in-any-chain? (:tokens (first %))))))))
(rf/reg-sub
:wallet/accounts-with-current-asset
:<- [:wallet/operable-accounts-without-watched-accounts]
:<- [:wallet/operable-accounts]
:<- [:wallet/operable-addresses-tokens-with-positive-balance]
:<- [:wallet/wallet-send-token-symbol]
:<- [:wallet/wallet-send-token]
(fn [[accounts token-symbol token]]
(let [asset-symbol (or token-symbol (:symbol token))]
(if asset-symbol
(filter (fn [account]
(some #(= (:symbol %) asset-symbol) (:tokens account)))
accounts)
accounts))))
(fn [[accounts addresses-tokens token-symbol token]]
(if-let [asset-symbol (or token-symbol (:symbol token))]
(let [addresses-with-asset (as-> addresses-tokens $
(update-vals $ #(set (map :symbol %)))
(keep (fn [[address token-symbols]]
(when (token-symbols asset-symbol) address))
$)
(set $))]
(filter #(addresses-with-asset (:address %)) accounts))
accounts)))
(rf/reg-sub
:wallet/operable-addresses-with-token-symbol
:<- [:wallet/operable-addresses-tokens-with-positive-balance]
(fn [addresses-tokens [_ token-symbol]]
(keep (fn [[address tokens]]
(some #(when (= (:symbol %) token-symbol) address)
tokens))
addresses-tokens)))
(rf/reg-sub
:wallet/account-tab

View File

@ -13,16 +13,22 @@
{:before #(reset! rf-db/app-db {})})
(def ^:private accounts-with-tokens
{:0x1 {:tokens [{:symbol "ETH"} {:symbol "SNT"}]
{:0x1 {:tokens [{:symbol "ETH"
:balances-per-chain {1 {:raw-balance "100"}}}
{:symbol "SNT"
:balances-per-chain {1 {:raw-balance "100"}}}]
:network-preferences-names #{}
:customization-color nil
:operable? true
:operable :fully}
:0x2 {:tokens [{:symbol "SNT"}]
:operable :fully
:address "0x1"}
:0x2 {:tokens [{:symbol "SNT"
:balances-per-chain {1 {:raw-balance "200"}}}]
:network-preferences-names #{}
:customization-color nil
:operable? true
:operable :partially}})
:operable :partially
:address "0x2"}})
(def tokens-0x1
[{:decimals 1
@ -495,11 +501,15 @@
(assoc-in [:wallet :ui :send :token-symbol] "ETH")))
(let [result (rf/sub [sub-name])]
(is (match? result
[{:tokens [{:symbol "ETH"} {:symbol "SNT"}]
[{:tokens [{:symbol "ETH"
:balances-per-chain {1 {:raw-balance "100"}}}
{:symbol "SNT"
:balances-per-chain {1 {:raw-balance "100"}}}]
:network-preferences-names #{}
:customization-color nil
:operable? true
:operable :fully}]))))
:operable :fully
:address "0x1"}]))))
(testing "returns the accounts list with the current asset using token"
(swap! rf-db/app-db
@ -508,11 +518,15 @@
(assoc-in [:wallet :ui :send :token] {:symbol "ETH"})))
(let [result (rf/sub [sub-name])]
(is (match? result
[{:tokens [{:symbol "ETH"} {:symbol "SNT"}]
[{:tokens [{:symbol "ETH"
:balances-per-chain {1 {:raw-balance "100"}}}
{:symbol "SNT"
:balances-per-chain {1 {:raw-balance "100"}}}]
:network-preferences-names #{}
:customization-color nil
:operable? true
:operable :fully}]))))
:operable :fully
:address "0x1"}]))))
(testing
"returns the full accounts list with the current asset using token-symbol if each account has the asset"