Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(wallet)_: Send flow for collectibles #21871

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/status_im/contexts/wallet/collectible/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@
ownership-status (get ownership-status-by-address owner-address)
collectibles (->> collectibles
data-store/rpc->collectibles
(map #(update % :ownership distinct))
vec)
pending-requests (dec (get-in db [:wallet :ui :collectibles :pending-requests]))
;; check if collectibles are updating (never fetched and cached before) for this address
Expand Down Expand Up @@ -323,7 +322,9 @@
(merge-with keep-not-empty-value
c
collectible)
(update c :ownership distinct))]
(update c
:ownership
collectible-utils/remove-duplicates-in-ownership))]
(if collectible
{:db (assoc-in db [:wallet :ui :collectible :details] merged-collectible)}
(log/error "failed to get collectible details"
Expand Down
23 changes: 16 additions & 7 deletions src/status_im/contexts/wallet/collectible/utils.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@
[taoensso.timbre :as log]))

(defn collectible-balance
[collectible]
(let [balance (-> collectible
:ownership
first
:balance
js/parseInt)]
(if (js/Number.isNaN balance) 0 balance)))
([{:keys [ownership]} address]
(let [balance (some #(when (= address (:address %))
(js/parseInt (:balance %)))
ownership)]
(if (js/Number.isNaN balance) 0 balance))))

(def supported-collectible-types
#{"image/jpeg"
Expand Down Expand Up @@ -69,3 +67,14 @@
contract-address (-> id :contract-id :address)
token-id (-> id :token-id)]
(str chain-id contract-address token-id)))

(defn remove-duplicates-in-ownership
[ownership]
(->> ownership
(reduce (fn [acc {:keys [address timestamp] :as owner}]
(let [existing-owner (get acc address)]
(if (or (nil? existing-owner) (> timestamp (:timestamp existing-owner)))
(assoc acc address owner)
acc)))
{})
vals))
Comment on lines +71 to +80
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes, the status-go returns duplicate data in the list, we do a cleanup based on the address and timestamp of the balance.

16 changes: 10 additions & 6 deletions src/status_im/contexts/wallet/collectible/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,23 @@

(defn cta-buttons
[{:keys [chain-id token-id contract-address collectible watch-only?]}]
(let [theme (quo.theme/use-theme)]
(let [theme (quo.theme/use-theme)
on-press-send (rn/use-callback
(fn []
(rf/dispatch [:wallet/clean-send-data])
(rf/dispatch
[:wallet/set-collectible-to-send
{:collectible collectible
:start-flow? true
:current-screen :screen/wallet.collectible}])))]
[rn/view {:style style/buttons-container}
(when-not watch-only?
[quo/button
{:container-style style/send-button
:type :outline
:size 40
:icon-left :i/send
:on-press #(rf/dispatch
[:wallet/set-collectible-to-send
{:collectible collectible
:start-flow? true
:current-screen :screen/wallet.collectible}])}
:on-press on-press-send}
(i18n/label :t/send)])
[quo/button
{:container-style style/opensea-button
Expand Down
1 change: 1 addition & 0 deletions src/status_im/contexts/wallet/data_store.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@
[collectibles]
(->> collectibles
(cske/transform-keys transforms/->kebab-case-keyword)
(map #(update % :ownership collectible-utils/remove-duplicates-in-ownership))
(map #(assoc % :unique-id (collectible-utils/get-collectible-unique-id %)))
vec))

Expand Down
7 changes: 4 additions & 3 deletions src/status_im/contexts/wallet/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,16 @@

(rf/reg-event-fx :wallet/clean-current-viewing-account
(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)]
(let [{:keys [entry-point just-completed-transaction?
collectible-multiple-owners?]} (-> 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?
(and entry-point-wallet-home? (not collectible-multiple-owners?))
(update-in [:wallet :ui :send] dissoc :entry-point)

(and entry-point-wallet-home?
Expand Down
72 changes: 45 additions & 27 deletions src/status_im/contexts/wallet/send/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,13 @@
:wallet/select-send-address
(fn [{:keys [db]} [{:keys [address recipient stack-id start-flow?]}]]
(let [[_ to-address] (utils/split-prefix-and-address address)
sender (get-in db [:wallet :current-viewing-account-address])
collectible-tx? (send-utils/tx-type-collectible?
(-> db :wallet :ui :send :tx-type))
collectible (when collectible-tx?
(-> db :wallet :ui :send :collectible))
one-collectible? (when collectible-tx?
(= (collectible.utils/collectible-balance collectible) 1))]
(= (collectible.utils/collectible-balance collectible sender) 1))]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Picking the right balance of the collectible to send.

Previously, we took the first balance in the list, which may not be the right balance of the selected account.

{:db (-> db
(assoc-in [:wallet :ui :send :recipient] (or recipient address))
(assoc-in [:wallet :ui :send :to-address] to-address))
Expand Down Expand Up @@ -180,7 +181,6 @@
(:chain-id (first networks-with-balance)))
network-details))
network)]
(println multi-account-balance? "43247329479847392")
(when (or token-data token-symbol)
{:db (cond-> db
network (update-in [:wallet :ui :send]
Expand Down Expand Up @@ -257,16 +257,22 @@
{:db (update-in db [:wallet :ui :send] dissoc :token :token-display-name :tx-type)}))

(rf/reg-event-fx :wallet/clean-selected-collectible
(fn [{:keys [db]}]
(let [transaction-type (get-in db [:wallet :ui :send :tx-type])]
{:db (update-in db
[:wallet :ui :send]
dissoc
:collectible
:token-display-name
:amount
(when (send-utils/tx-type-collectible? transaction-type)
:tx-type))})))
(fn [{:keys [db]} [{:keys [ignore-entry-point?]}]]
(let [entry-point-wallet-home? (= (get-in db [:wallet :ui :send :entry-point]) :wallet-stack)
multiple-owners? (get-in db [:wallet :ui :send :collectible-multiple-owners?])
transaction-type (get-in db [:wallet :ui :send :tx-type])]
(when (or ignore-entry-point?
(and entry-point-wallet-home? (not multiple-owners?))
(not entry-point-wallet-home?))
{:db (update-in db
[:wallet :ui :send]
dissoc
:collectible
:collectible-multiple-owners?
:token-display-name
:amount
(when (send-utils/tx-type-collectible? transaction-type)
:tx-type))}))))
Comment on lines +260 to +275
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We skip cleaning the selected collectible on navigating back (the user will land on the From screen) from the select recipient screen if the collectible is present in multiple accounts.


(rf/reg-event-fx
:wallet/set-collectible-to-send
Expand All @@ -283,37 +289,48 @@
:tx/collectible-erc-1155
:tx/collectible-erc-721)
collectible-id (get-in collectible [:id :token-id])
one-collectible? (= (collectible.utils/collectible-balance collectible) 1)
single-owner? (-> collectible :ownership count (= 1))
owner-address (-> collectible :ownership first :address)
one-collectible? (when single-owner?
(= (collectible.utils/collectible-balance collectible owner-address) 1))
token-display-name (cond
(and collectible
(not (string/blank? (:name collectible-data))))
(:name collectible-data)

collectible
(str (:name collection-data) " #" collectible-id))
owner-address (-> db :wallet :current-viewing-account-address)
collectible-tx (-> db
(update-in [:wallet :ui :send] dissoc :token)
(assoc-in [:wallet :ui :send :entry-point] entry-point)
(assoc-in [:wallet :ui :send :collectible] collectible)
(assoc-in [:wallet :ui :send :collectible-multiple-owners?]
(not single-owner?))
(assoc-in [:wallet :ui :send :token-display-name] token-display-name)
(assoc-in [:wallet :ui :send :tx-type] tx-type))
recipient-set? (-> db :wallet :ui :send :recipient)]
{:db (cond-> collectible-tx
:always
(assoc-in [:wallet :ui :send :entry-point] entry-point)

(not viewing-account?)
(and (not viewing-account?) single-owner?)
(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/start-get-suggested-routes {:amount 1}]])
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen current-screen
:start-flow? start-flow?
:flow-id :wallet-send-flow}]]]})))
:fx (if
;; If the is present in multiple accounts, the user will be taken to select the address
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the collectible*

;; to send from
(and (not viewing-account?) (not single-owner?))
[[:dispatch [:open-modal :screen/wallet.select-from]]]


[(when (and one-collectible? recipient-set?)
[:dispatch [:wallet/start-get-suggested-routes {:amount 1}]])

[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen current-screen
:start-flow? start-flow?
:flow-id :wallet-send-flow}]]])})))

(rf/reg-event-fx
:wallet/set-collectible-amount-to-send
Expand Down Expand Up @@ -673,11 +690,12 @@
(fn [{db :db} [{:keys [address stack-id network-details network start-flow?] :as params}]]
(let [{:keys [token-symbol
tx-type]} (-> db :wallet :ui :send)
collectible-tx? (send-utils/tx-type-collectible? tx-type)
token (when token-symbol
;; When this flow has started in the wallet home page, we
;; know the token or collectible to send, but we don't know
;; from which account, so we extract the token data from the
;; picked account.
;; from which account, so we extract the token data from
;; the picked account.
(let [token (utils/get-token-from-account db
token-symbol
address)]
Expand All @@ -704,7 +722,7 @@
network (assoc-in [:wallet :ui :send :network] network)
token-symbol (assoc-in [:wallet :ui :send :token] token)
bridge-tx? (assoc-in [:wallet :ui :send :to-address] address))
:fx (if (some? network)
:fx (if (or (some? network) collectible-tx?)
[[:dispatch [:wallet/switch-current-viewing-account address]]
[:dispatch
[:wallet/wizard-navigate-forward
Expand Down
14 changes: 8 additions & 6 deletions src/status_im/contexts/wallet/send/events_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,10 @@
:start-flow? start-flow?
:flow-id :wallet-send-flow}]]]}]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value
:tx-type tx-type
:collectible collectible}}}
{:wallet {:current-viewing-account-address "0x01"
:ui {:send {:other-props :value
:tx-type tx-type
:collectible collectible}}}
:profile/profile {:test-networks-enabled? testnet-enabled?}})
(is (match? expected-result
(dispatch [event-id
Expand All @@ -347,9 +348,10 @@
:start-flow? start-flow?
:flow-id :wallet-send-flow}]]]}]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value
:tx-type tx-type
:collectible collectible}}}
{:wallet {:current-viewing-account-address "0x01"
:ui {:send {:other-props :value
:tx-type tx-type
:collectible collectible}}}
:profile/profile {:test-networks-enabled? testnet-enabled?}})
(is (match? expected-result
(dispatch [event-id
Expand Down
48 changes: 33 additions & 15 deletions src/status_im/contexts/wallet/send/from/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,56 @@
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.floating-button-page.view :as floating-button-page]
[status-im.contexts.wallet.collectible.utils :as collectible-utils]
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im.contexts.wallet.send.from.style :as style]
[status-im.setup.hot-reload :as hot-reload]
[utils.i18n :as i18n]
[utils.money :as money]
[utils.re-frame :as rf]))

(defn- on-account-press
[address network-details]
[address network-details collectible-tx?]
(rf/dispatch [:wallet/select-from-account
{:address address
:network-details network-details
:stack-id :screen/wallet.select-from
:start-flow? true}]))
:start-flow? (not collectible-tx?)}]))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's a collectible tx, the flow is already started.


(defn- on-close
[]
(rf/dispatch [:wallet/clean-selected-collectible {:ignore-entry-point? true}])
(rf/dispatch [:wallet/clean-current-viewing-account]))

(defn- render-fn
[item _ _ {:keys [network-details]}]
(let [has-balance (money/above-zero? (string/replace-first (:asset-pay-balance item) "<" ""))]
[item _ _ {:keys [network-details collectible-tx? collectible]}]
(let [account-address (:address item)
balance (if collectible-tx?
(collectible-utils/collectible-balance collectible account-address)
(string/replace-first (:asset-pay-balance item) "<" ""))
has-balance? (money/above-zero? balance)
asset-symbol (if collectible-tx? "" (:asset-pay-symbol item))
asset-value (if collectible-tx? (str balance) (:asset-pay-balance item))]
[quo/account-item
{:type (if has-balance :tag :default)
:on-press #(on-account-press (:address item) network-details)
: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)}]))
{:type (if has-balance? :tag :default)
:on-press #(on-account-press account-address network-details collectible-tx?)
:state (if has-balance? :default :disabled)
:token-props {:symbol asset-symbol
:value asset-value}
:account-props item}]))

(defn view
[]
(let [token-symbol (rf/sub [:wallet/send-token-symbol])
(let [collectible-tx? (rf/sub [:wallet/send-tx-type-collectible?])
token-symbol (rf/sub [:wallet/send-token-symbol])
token (rf/sub [:wallet/token-by-symbol-from-first-available-account-with-balance
token-symbol])
accounts (rf/sub [:wallet/accounts-with-balances token])
collectible (rf/sub [:wallet/wallet-send-collectible])
accounts (if collectible-tx?
(rf/sub [:wallet/operable-accounts])
(rf/sub [:wallet/accounts-with-balances token]))
network-details (rf/sub [:wallet/network-details])]
(hot-reload/use-safe-unmount on-close)
[floating-button-page/view
{:footer-container-padding 0
:header [account-switcher/view
Expand All @@ -52,6 +68,8 @@
{:style style/accounts-list
:content-container-style style/accounts-list-container
:data accounts
:render-data {:network-details network-details}
:render-data {:network-details network-details
:collectible-tx? collectible-tx?
:collectible collectible}
:render-fn render-fn
:shows-horizontal-scroll-indicator false}]]))
11 changes: 11 additions & 0 deletions src/status_im/subs/wallet/wallet.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@
:<- [:wallet/wallet-send]
:-> :enough-assets?)

(rf/reg-sub
:wallet/wallet-send-collectible
:<- [:wallet/wallet-send]
:-> :collectible)

(rf/reg-sub
:wallet/wallet-send-token
:<- [:wallet/wallet-send]
Expand Down Expand Up @@ -235,6 +240,12 @@
:<- [:wallet/wallet-send]
:-> :tx-type)

(rf/reg-sub
:wallet/send-tx-type-collectible?
:<- [:wallet/wallet-send-tx-type]
(fn [tx-type]
(send-utils/tx-type-collectible? tx-type)))

(rf/reg-sub
:wallet/keypairs
:<- [:wallet]
Expand Down