From 943995b9027eebb03bfe2fbd1ff4bf55366fe9b3 Mon Sep 17 00:00:00 2001 From: Mohsen Date: Wed, 25 Dec 2024 13:38:04 +0300 Subject: [PATCH] [#21483] fix: update collectible amounts after sending --- .../contexts/wallet/collectible/events.cljs | 75 ++++++++++++++----- .../contexts/wallet/collectible/utils.cljs | 17 ++++- .../wallet/common/collectibles_tab/view.cljs | 9 +-- src/status_im/contexts/wallet/data_store.cljs | 14 ++++ 4 files changed, 88 insertions(+), 27 deletions(-) diff --git a/src/status_im/contexts/wallet/collectible/events.cljs b/src/status_im/contexts/wallet/collectible/events.cljs index 2d01997f248..39f1f1df5c1 100644 --- a/src/status_im/contexts/wallet/collectible/events.cljs +++ b/src/status_im/contexts/wallet/collectible/events.cljs @@ -70,7 +70,7 @@ (let [current-collectible-idx (get-in db [:wallet :accounts account :current-collectible-idx] 0) collectibles-filter nil data-type (collectible-data-types :header) - fetch-criteria {:fetch-type (fetch-type :fetch-if-not-cached) + fetch-criteria {:fetch-type (fetch-type :fetch-if-cache-old) :max-cache-age-seconds max-cache-age-seconds} chain-ids (chain/chain-ids db) request-params [request-id @@ -171,16 +171,19 @@ (rf/reg-event-fx :wallet/collectible-ownership-update-finished - (fn [{:keys [db]} [{:keys [accounts chainId]}]] + (fn [{:keys [db]} [{:keys [accounts chainId message]}]] (let [address (first accounts) pending-chain-ids (get-in db [:wallet :ui :collectibles :updating address]) updated-chain-ids (disj pending-chain-ids chainId) - all-chain-updated? (and (some? pending-chain-ids) (empty? updated-chain-ids))] + all-chain-updated? (and (some? pending-chain-ids) (empty? updated-chain-ids)) + collectible-id (data-store/rpc->collectible-id message)] {:db (cond-> db (some? pending-chain-ids) (assoc-in [:wallet :ui :collectibles :updating address] updated-chain-ids)) :fx [(when all-chain-updated? - [:dispatch [:wallet/request-collectibles-for-account address]])]}))) + [:dispatch [:wallet/request-collectibles-for-account address]]) + (when collectible-id + [:dispatch [:wallet/get-collectibles-by-unique-id-async collectible-id]])]}))) (defn- update-collectibles-in-account [existing-collectibles updated-collectibles] @@ -282,28 +285,33 @@ [{{collectible-id :id :as collectible} :collectible aspect-ratio :aspect-ratio gradient-color :gradient-color}]] + {:db (assoc-in db + [:wallet :ui :collectible] + {:details collectible + :aspect-ratio aspect-ratio + :gradient-color gradient-color}) + :fx [[:dispatch [:wallet/get-collectibles-by-unique-id-async collectible-id]] + ;; We delay the navigation because we need re-frame to update the DB on time. + ;; By doing it, we skip a blink while visiting the collectible detail page. + [:dispatch-later + {:ms 17 + :dispatch [:navigate-to :screen/wallet.collectible]}]]})) + +(rf/reg-event-fx + :wallet/get-collectibles-by-unique-id-async + (fn [_ [collectible-id]] (let [request-id 0 collectible-id-converted (cske/transform-keys transforms/->PascalCaseKeyword collectible-id) data-type (collectible-data-types :details) request-params [request-id [collectible-id-converted] data-type]] - {:db (assoc-in db - [:wallet :ui :collectible] - {:details collectible - :aspect-ratio aspect-ratio - :gradient-color gradient-color}) - :fx [[:json-rpc/call + {:fx [[:json-rpc/call [{:method "wallet_getCollectiblesByUniqueIDAsync" :params request-params :on-error (fn [error] (log/error "failed to request collectible" {:event :wallet/navigate-to-collectible-details :error error - :params request-params}))}]] - ;; We delay the navigation because we need re-frame to update the DB on time. - ;; By doing it, we skip a blink while visiting the collectible detail page. - [:dispatch-later - {:ms 17 - :dispatch [:navigate-to :screen/wallet.collectible]}]]}))) + :params request-params}))}]]]}))) (defn- keep-not-empty-value [old-value new-value] @@ -318,19 +326,50 @@ (transforms/json->clj message)) {[collectible] :collectibles} response known-collectible-info (get-in db [:wallet :ui :collectible :details]) + current-account-address (get-in db [:wallet :current-viewing-account-address]) + total-owned (collectible-utils/collectible-balance collectible + current-account-address) merged-collectible (as-> known-collectible-info c (merge-with keep-not-empty-value c collectible) (update c :ownership - collectible-utils/remove-duplicates-in-ownership))] + collectible-utils/remove-duplicates-in-ownership)) + updated-collectible (assoc merged-collectible + :total-owned + total-owned)] (if collectible - {:db (assoc-in db [:wallet :ui :collectible :details] merged-collectible)} + {:db (assoc-in db [:wallet :ui :collectible :details] updated-collectible) + :fx [[:dispatch [:wallet/update-collectibles-data updated-collectible]]]} (log/error "failed to get collectible details" {:event :wallet/get-collectible-details-done :response response}))))) +(defn group-collectibles-by-ownership-address + [collectible] + (->> (:ownership collectible) + (map (fn [{:keys [address]}] + [address collectible])) + (into {}))) + +(rf/reg-event-fx + :wallet/update-collectibles-data + (fn [{:keys [db]} [collectible]] + (let [collectibles-by-address (group-collectibles-by-ownership-address collectible)] + {:db (update-in db + [:wallet :accounts] + #(reduce-kv + (fn [accounts address updated-collectibles] + (if (contains? accounts address) + (update-in accounts + [address :collectibles] + update-collectibles-in-account + [updated-collectibles]) + accounts)) + % + collectibles-by-address))}))) + (rf/reg-event-fx :wallet/clear-collectible-details (fn [{:keys [db]}] diff --git a/src/status_im/contexts/wallet/collectible/utils.cljs b/src/status_im/contexts/wallet/collectible/utils.cljs index 3c4a6cc5f76..22af847cffb 100644 --- a/src/status_im/contexts/wallet/collectible/utils.cljs +++ b/src/status_im/contexts/wallet/collectible/utils.cljs @@ -5,12 +5,21 @@ [taoensso.timbre :as log] [utils.number :as utils.number])) +(defn total-collectible-balance + ([ownership] + (reduce (fn [total {:keys [balance]}] + (+ total (or (js/parseInt balance) 0))) + 0 + ownership))) + (defn collectible-balance ([{:keys [ownership]} address] - (->> ownership - (some #(when (= address (:address %)) - (:balance %))) - utils.number/parse-int))) + (let [balance (if address + (some #(when (= address (:address %)) + (:balance %)) + ownership) + (total-collectible-balance ownership))] + (utils.number/parse-int balance)))) (def supported-collectible-types #{"image/jpeg" diff --git a/src/status_im/contexts/wallet/common/collectibles_tab/view.cljs b/src/status_im/contexts/wallet/common/collectibles_tab/view.cljs index 7857e0449d5..6ca66f14073 100644 --- a/src/status_im/contexts/wallet/common/collectibles_tab/view.cljs +++ b/src/status_im/contexts/wallet/common/collectibles_tab/view.cljs @@ -7,8 +7,7 @@ [status-im.contexts.wallet.collectible.utils :as utils] [status-im.contexts.wallet.common.collectibles-tab.style :as style] [status-im.contexts.wallet.common.empty-tab.view :as empty-tab] - [utils.i18n :as i18n] - [utils.re-frame :as rf])) + [utils.i18n :as i18n])) (defn- loading-collectible-item [_ index] @@ -82,9 +81,9 @@ ;; 1. If possible, move `collectibles-data` calculation to a subscription ;; 2. Optimization: do not recalculate all the collectibles, process only the new ones (let [collectibles-data (map - (fn [{:keys [ownership] :as collectible}] - (let [total-owned (rf/sub [:wallet/total-owned-collectible ownership - current-account-address])] + (fn [collectible] + (let [total-owned (utils/collectible-balance collectible + current-account-address)] (assoc collectible :total-owned total-owned :on-long-press on-collectible-long-press diff --git a/src/status_im/contexts/wallet/data_store.cljs b/src/status_im/contexts/wallet/data_store.cljs index 302a60f5007..cdf1e7203d4 100644 --- a/src/status_im/contexts/wallet/data_store.cljs +++ b/src/status_im/contexts/wallet/data_store.cljs @@ -299,3 +299,17 @@ selected-keypair-uid (get-in db [:wallet :ui :create-account :selected-keypair-uid]) keypair (get keypairs selected-keypair-uid)] (boolean (seq (:keycards keypair))))) + +(defn transform-collectible + [{:keys [added updated removed]}] + (let [entry (first (remove nil? (concat added updated removed)))] + (when entry + {:contract-id {:chain-id (:chainID (:contractID entry)) + :address (:address (:contractID entry))} + :token-id (str (:tokenID entry))}))) + +(defn rpc->collectible-id + [collectible] + (-> collectible + transforms/json->clj + transform-collectible))