From 2d0437dd5e261cdb91ac85f38f9051ce4f8b5dc3 Mon Sep 17 00:00:00 2001 From: Ulises Manuel <90291778+ulisesmac@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:07:33 -0600 Subject: [PATCH] fix(wallet): Improvements on activity tab (#20703) * Fix schema for networks in context-tags * Fix wallet-activity component overflowing the activity tab * Improve robustness of the activity tab fetching mechanism * Handle `wallet-activity-filtering-entries-updated` signal * Improve processing of data received for the activity tab --- .../components/tags/context_tag/schema.cljs | 2 +- .../components/tags/context_tag/style.cljs | 9 +- src/quo/components/tags/context_tag/view.cljs | 21 ++-- .../wallet/wallet_activity/style.cljs | 12 +- .../wallet/wallet_activity/view.cljs | 9 +- .../wallet/common/activity_tab/events.cljs | 48 ++++++-- .../wallet/common/activity_tab/view.cljs | 90 +++++++++++---- src/status_im/contexts/wallet/signals.cljs | 53 ++++++--- src/status_im/subs/wallet/activities.cljs | 105 +++++++++++++----- .../subs/wallet/activities_test.cljs | 40 +++---- src/status_im/subs/wallet/send.cljs | 3 +- src/status_im/subs/wallet/send_test.cljs | 40 +++---- 12 files changed, 291 insertions(+), 141 deletions(-) diff --git a/src/quo/components/tags/context_tag/schema.cljs b/src/quo/components/tags/context_tag/schema.cljs index 4e7345737c..e4fd74ea0d 100644 --- a/src/quo/components/tags/context_tag/schema.cljs +++ b/src/quo/components/tags/context_tag/schema.cljs @@ -53,7 +53,7 @@ (def ^:private ?network [:map [:network-logo {:optional true} [:maybe :schema.common/image-source]] - [:network-name {:optional true} [:maybe :string]]]) + [:network-name {:optional true} [:maybe [:or :string :keyword]]]]) (def ^:private ?multinetwork [:map diff --git a/src/quo/components/tags/context_tag/style.cljs b/src/quo/components/tags/context_tag/style.cljs index 688cf59db1..4caea0f2fc 100644 --- a/src/quo/components/tags/context_tag/style.cljs +++ b/src/quo/components/tags/context_tag/style.cljs @@ -41,7 +41,8 @@ :align-items :center :height size :background-color background-color - :border-radius border-radius} + :border-radius border-radius + :flex-shrink 1} (= state :selected) (assoc :height (+ size 2) :border-color border-color :border-width 1)))) @@ -50,11 +51,13 @@ [size] {:margin-right (if (= size 24) 6 10) :flex-direction :row + :flex-shrink 1 :align-items :center}) (defn tag-spacing - [size] - {:margin-left (if (= size 24) 4 8)}) + [size shrinkable?] + (cond-> {:margin-left (if (= size 24) 4 8)} + shrinkable? (assoc :flex-shrink 1))) (defn text [theme] diff --git a/src/quo/components/tags/context_tag/view.cljs b/src/quo/components/tags/context_tag/view.cljs index 78ad97ae90..3248f1d94a 100644 --- a/src/quo/components/tags/context_tag/view.cljs +++ b/src/quo/components/tags/context_tag/view.cljs @@ -17,17 +17,19 @@ [schema.core :as schema])) (defn- tag-skeleton - [{:keys [size text theme] + [{:keys [size text theme shrinkable?] :or {size 24 theme (quo.theme/use-theme)}} logo-component] [rn/view {:style (style/tag-container size)} logo-component - [rn/view {:style (style/tag-spacing size)} + [rn/view {:style (style/tag-spacing size shrinkable?)} [text/text - {:style (style/text theme) - :weight :medium - :size (if (= size 24) :paragraph-2 :paragraph-1)} + {:style (style/text theme) + :weight :medium + :size (if (= size 24) :paragraph-2 :paragraph-1) + :number-of-lines 1 + :ellipsize-mode :middle} text]]]) (defn- communities-tag @@ -37,7 +39,7 @@ icon-size (if (= size 24) 16 20)] [rn/view {:style (style/tag-container size)} [fast-image/fast-image {:style (style/circle-logo size) :source community-logo}] - [rn/view {:style (style/tag-spacing size)} + [rn/view {:style (style/tag-spacing size false)} [text/text {:style (style/text theme) :weight :medium @@ -148,9 +150,10 @@ :collectible [tag-skeleton - {:theme theme - :size size - :text (str collectible-name " #" collectible-number)} + {:theme theme + :size size + :text (str collectible-name " #" collectible-number) + :shrinkable? true} [rn/image {:style (style/rounded-logo size) :source collectible}]] :account diff --git a/src/quo/components/wallet/wallet_activity/style.cljs b/src/quo/components/wallet/wallet_activity/style.cljs index 76d3c89e20..6d77607237 100644 --- a/src/quo/components/wallet/wallet_activity/style.cljs +++ b/src/quo/components/wallet/wallet_activity/style.cljs @@ -51,8 +51,7 @@ (defn prop-text [theme] - {:margin-right 4 - :color (colors/theme-colors colors/neutral-100 colors/white theme)}) + {:color (colors/theme-colors colors/neutral-100 colors/white theme)}) (def icon-container {:width 32 @@ -61,12 +60,15 @@ (def container {:flex-direction :row + :flex 1 :column-gap 8}) (def content-line - {:flex-direction :row - :margin-top 2 - :align-items :center}) + {:flex-direction :row + :margin-top 2 + :align-items :center + :column-gap 4 + :justify-content :flex-start}) (def icon-hole-view {:width 32 diff --git a/src/quo/components/wallet/wallet_activity/view.cljs b/src/quo/components/wallet/wallet_activity/view.cljs index 5f9bc8aaa3..d6d72f4913 100644 --- a/src/quo/components/wallet/wallet_activity/view.cljs +++ b/src/quo/components/wallet/wallet_activity/view.cljs @@ -98,8 +98,11 @@ (defn prop-tag [props blur?] - [rn/view {:style {:margin-right 4}} - [context-tag/view (merge props {:size 24 :blur? blur?})]]) + [context-tag/view + (assoc props + :size 24 + :blur? blur? + :container-style {:flex-shrink 1})]) (defn- view-internal [{:keys [state blur? first-tag second-tag third-tag fourth-tag on-press @@ -121,7 +124,7 @@ :on-press-out on-press-out} [rn/view {:style style/container} [transaction-icon-view props theme] - [rn/view + [rn/view {:style {:flex 1}} [transaction-header props theme] [rn/view {:style style/content-line} (when first-tag [prop-tag first-tag blur?]) diff --git a/src/status_im/contexts/wallet/common/activity_tab/events.cljs b/src/status_im/contexts/wallet/common/activity_tab/events.cljs index 0ee358e4b6..5d46201ab9 100644 --- a/src/status_im/contexts/wallet/common/activity_tab/events.cljs +++ b/src/status_im/contexts/wallet/common/activity_tab/events.cljs @@ -4,12 +4,19 @@ [utils.re-frame :as rf] [utils.transforms :as transforms])) +(defonce ^:private request-id-atom (atom 0)) + +(defn- get-unique-request-id + [] + (swap! request-id-atom inc) + @request-id-atom) + (rf/reg-event-fx :wallet/fetch-activities-for-current-account (fn [{:keys [db]}] (let [address (-> db :wallet :current-viewing-account-address) chain-ids (chain/chain-ids db) - request-id 0 + request-id (get-unique-request-id) filters {:period {:startTimestamp 0 :endTimestamp 0} :types [] @@ -20,9 +27,10 @@ :filterOutAssets false :filterOutCollectibles false} offset 0 - limit 35 + limit 50 request-params [request-id [address] chain-ids filters offset limit]] - {:fx [[:json-rpc/call + {:db (assoc-in db [:wallet :ui :activity-tab :request request-id] address) + :fx [[:json-rpc/call [{;; This method is deprecated and will be replaced by ;; "wallet_startActivityFilterSession" ;; https://github.com/status-im/status-mobile/issues/19864 @@ -32,13 +40,31 @@ {:event :wallet/fetch-activities-for-current-account :params request-params}]}]]]}))) +(def ^:private activity-transaction-id (comp hash :transaction)) + (rf/reg-event-fx :wallet/activity-filtering-for-current-account-done - (fn [{:keys [db]} [{:keys [message]}]] - (let [address (-> db :wallet :current-viewing-account-address) - activities (->> message - (transforms/json->clj) - (:activities) - (cske/transform-keys transforms/->kebab-case-keyword)) - sorted-activities (sort :timestamp activities)] - {:db (assoc-in db [:wallet :activities address] sorted-activities)}))) + (fn [{:keys [db]} [{:keys [message requestId]}]] + (let [address (get-in db [:wallet :ui :activity-tab :request requestId]) + activities (->> message + (transforms/json->clj) + (:activities) + (cske/transform-keys transforms/->kebab-case-keyword)) + activities-indexed (zipmap (map activity-transaction-id activities) + activities)] + {:db (assoc-in db [:wallet :activities address] activities-indexed)}))) + +(def ^:private nested-merge (partial merge-with merge)) + +(rf/reg-event-fx + :wallet/activities-filtering-entries-updated + (fn [{:keys [db]} [{:keys [message requestId]}]] + (let [address (get-in db [:wallet :ui :activity-tab :request requestId]) + activities (->> message + (transforms/json->clj) + (cske/transform-keys transforms/->kebab-case-keyword)) + activities-indexed (zipmap (map activity-transaction-id activities) + activities)] + {:db (-> db + (update-in [:wallet :ui :activity-tab :request] dissoc requestId) + (update-in [:wallet :activities address] nested-merge activities-indexed))}))) diff --git a/src/status_im/contexts/wallet/common/activity_tab/view.cljs b/src/status_im/contexts/wallet/common/activity_tab/view.cljs index b10f9d0b52..480b9d0b22 100644 --- a/src/status_im/contexts/wallet/common/activity_tab/view.cljs +++ b/src/status_im/contexts/wallet/common/activity_tab/view.cljs @@ -11,31 +11,81 @@ (defn send-and-receive-activity [{:keys [transaction relative-date status sender recipient token amount network-name - network-logo]}] - [quo/wallet-activity - {:transaction transaction - :timestamp relative-date - :status status - :counter 1 - :first-tag {:size 24 - :type :token - :token token - :amount amount} - :second-tag-prefix :t/from - :second-tag {:type :address :address sender} - :third-tag-prefix :t/to - :third-tag {:type :address :address recipient} - :fourth-tag-prefix :t/via - :fourth-tag {:size 24 - :type :network - :network-name network-name - :network-logo network-logo} - :blur? false}]) + network-logo token-id nft-url nft-name]}] + (if token-id + [quo/wallet-activity + {:transaction transaction + :timestamp relative-date + :status status + :counter 1 + :first-tag {:size 24 + :type :collectible + :collectible nft-url + :collectible-name (if (> amount 1) + (str amount " " nft-name) + nft-name) + :collectible-number token-id} + :second-tag-prefix :t/from + :second-tag {:type :address :address sender} + :third-tag-prefix :t/to + :third-tag {:type :address :address recipient} + :fourth-tag-prefix :t/via + :fourth-tag {:size 24 + :type :network + :network-name network-name + :network-logo network-logo} + :blur? false}] + [quo/wallet-activity + {:transaction transaction + :timestamp relative-date + :status status + :counter 1 + :first-tag {:size 24 + :type :token + :token token + :amount amount} + :second-tag-prefix :t/from + :second-tag {:type :address :address sender} + :third-tag-prefix :t/to + :third-tag {:type :address :address recipient} + :fourth-tag-prefix :t/via + :fourth-tag {:size 24 + :type :network + :network-name network-name + :network-logo network-logo} + :blur? false}])) + +;; WIP to add the mint activity. +;(defn mint-activity +; [{:keys [transaction relative-date status recipient network-name +; network-logo nft-name nft-url token-id]}] +; [quo/wallet-activity +; {:transaction transaction +; :timestamp relative-date +; :status status +; :counter 1 +; :first-tag {:size 24 +; :type :collectible +; :collectible nft-url +; :collectible-name nft-name +; :collectible-number token-id} +; :second-tag-prefix :t/at +; :second-tag {:type :address :address recipient} +; :third-tag-prefix :t/to +; :third-tag {:type :address :address recipient} +; :fourth-tag-prefix :t/via +; :fourth-tag {:size 24 +; :type :network +; :network-name network-name +; :network-logo network-logo} +; :blur? false}]) (defn activity-item [{:keys [transaction] :as activity}] (case transaction (:send :receive) [send-and-receive-activity activity] + ;; WIP to add the mint activity. + ;; :mint [mint-activity activity] nil)) (defn view diff --git a/src/status_im/contexts/wallet/signals.cljs b/src/status_im/contexts/wallet/signals.cljs index 3b503d80b9..cb9b37f571 100644 --- a/src/status_im/contexts/wallet/signals.cljs +++ b/src/status_im/contexts/wallet/signals.cljs @@ -23,22 +23,39 @@ :block-number blockNumber :accounts accounts}) (case event-type - "pending-transaction-status-changed" {:fx - [[:dispatch - [:wallet/pending-transaction-status-changed-received - (transforms/js->clj event-js)]]]} - "wallet-owned-collectibles-filtering-done" {:fx [[:dispatch - [:wallet/owned-collectibles-filtering-done - (transforms/js->clj event-js)]]]} - "wallet-get-collectibles-details-done" {:fx [[:dispatch - [:wallet/get-collectible-details-done - (transforms/js->clj event-js)]]]} - "wallet-tick-reload" {:fx [[:dispatch [:wallet/reload]]]} - "wallet-blockchain-status-changed" {:fx [[:dispatch - [:wallet/blockchain-status-changed - (transforms/js->clj event-js)]]]} - "wallet-activity-filtering-done" {:fx - [[:dispatch - [:wallet/activity-filtering-for-current-account-done - (transforms/js->clj event-js)]]]} + "pending-transaction-status-changed" + {:fx + [[:dispatch + [:wallet/pending-transaction-status-changed-received + (transforms/js->clj event-js)]]]} + + "wallet-owned-collectibles-filtering-done" + {:fx [[:dispatch + [:wallet/owned-collectibles-filtering-done + (transforms/js->clj event-js)]]]} + + "wallet-get-collectibles-details-done" + {:fx [[:dispatch + [:wallet/get-collectible-details-done + (transforms/js->clj event-js)]]]} + + "wallet-tick-reload" + {:fx [[:dispatch [:wallet/reload]]]} + + "wallet-blockchain-status-changed" + {:fx [[:dispatch + [:wallet/blockchain-status-changed + (transforms/js->clj event-js)]]]} + + "wallet-activity-filtering-done" + {:fx + [[:dispatch + [:wallet/activity-filtering-for-current-account-done + (transforms/js->clj event-js)]]]} + + "wallet-activity-filtering-entries-updated" + {:fx [[:dispatch + [:wallet/activities-filtering-entries-updated + (transforms/js->clj event-js)]]]} + (log/debug ::unknown-wallet-event :type event-type))))) diff --git a/src/status_im/subs/wallet/activities.cljs b/src/status_im/subs/wallet/activities.cljs index 418680b12d..4deb544dad 100644 --- a/src/status_im/subs/wallet/activities.cljs +++ b/src/status_im/subs/wallet/activities.cljs @@ -1,5 +1,6 @@ (ns status-im.subs.wallet.activities (:require + [clojure.string :as string] [native-module.core :as native-module] [quo.foundations.resources :as quo.resources] [quo.foundations.resources] @@ -16,49 +17,91 @@ :<- [:wallet] :-> :activities) -(defn- activity-amount - [amount] - (-> amount +(defn- hex-wei->amount + [hex-str-amount] + (-> hex-str-amount (utils.hex/normalize-hex) (native-module/hex-to-number) (money/wei->ether) (money/with-precision precision) (str))) +(defn- hex-string->number + [hex-str-amount] + (-> hex-str-amount + (utils.hex/normalize-hex) + (native-module/hex-to-number) + (str))) + +(defn- normalize-nft-name + [token-id nft-name] + (if (and (some? token-id) (string/blank? nft-name)) + "Unknown" + nft-name)) + +(defn- get-token-amount + [token amount] + (let [token-type (:token-type token)] + (if (#{constants/wallet-activity-token-type-erc-721 + constants/wallet-activity-token-type-erc-1155} + token-type) + (hex-string->number amount) + (hex-wei->amount amount)))) + (defn- process-send-activity - [{:keys [symbol-out chain-id-out amount-out]} activity chain-id->network-name] - (let [network-name (chain-id->network-name chain-id-out)] - (assoc activity - :transaction :send - :token symbol-out - :amount (activity-amount amount-out) - :network-name network-name - :network-logo (quo.resources/get-network network-name)))) + [{:keys [symbol-out amount-out token-out] + :as data}] + (assoc data + :transaction :send + :token symbol-out + :amount (get-token-amount token-out amount-out))) (defn- process-receive-activity - [{:keys [symbol-in amount-in chain-id-in]} activity chain-id->network-name] - (let [network-name (chain-id->network-name chain-id-in)] - (assoc activity - :transaction :receive - :token symbol-in - :amount (activity-amount amount-in) - :network-name network-name - :network-logo (quo.resources/get-network network-name)))) + [{:keys [symbol-in amount-in token-in] :as data}] + (assoc data + :transaction :receive + :token symbol-in + :amount (get-token-amount token-in amount-in))) + +;; WIP to add the mint activity. +;(defn- process-mint-activity +; [{:keys [token-in symbol-in amount-in chain-id-in nft-name] :as data} +; chain-id->network-name] +; (-> data +; (merge activity) +; (assoc :transaction :mint +; ;:token symbol-in +; ;:amount (activity-amount amount-in) +; :nft-name (normalize-nft-name token-id nft-name)))) (defn- process-activity-by-type [chain-id->network-name - {:keys [activity-type activity-status timestamp sender recipient] :as data}] - (let [activity {:relative-date (datetime/timestamp->relative (* timestamp 1000)) - :timestamp timestamp - :status (constants/wallet-activity-status->name activity-status) - :sender sender - :recipient recipient}] + {:keys [activity-type activity-status timestamp sender recipient token-in token-out + chain-id-in chain-id-out nft-name] + :as data}] + (let [network-name (chain-id->network-name (or chain-id-in chain-id-out)) + token-id (some-> (or token-in token-out) + :token-id + hex-string->number) + activity (assoc data + :relative-date (datetime/timestamp->relative (* timestamp 1000)) + :sender sender + :recipient recipient + :timestamp timestamp + :network-name network-name + :token-id token-id + :status (constants/wallet-activity-status->name activity-status) + :network-logo (quo.resources/get-network network-name) + :nft-name (normalize-nft-name token-id nft-name))] (condp = activity-type constants/wallet-activity-type-send - (process-send-activity data activity chain-id->network-name) + (process-send-activity activity) constants/wallet-activity-type-receive - (process-receive-activity data activity chain-id->network-name) + (process-receive-activity activity) + + ;; WIP to add the mint activity. Constants/wallet-activity-type-mint + ;; (process-mint-activity activity chain-id->network-name) nil))) @@ -69,9 +112,11 @@ :<- [:wallet/network-details] (fn [[activities current-viewing-account-address network-details]] (let [chain-id->network-name (update-vals (group-by :chain-id network-details) - (comp :network-name first))] - (->> current-viewing-account-address - (get activities) + (comp :network-name first)) + address-activities (->> (get activities current-viewing-account-address) + (vals) + (sort :timestamp))] + (->> address-activities (keep #(process-activity-by-type chain-id->network-name %)) (group-by (fn [{:keys [timestamp]}] (datetime/timestamp->relative-short-date (* timestamp 1000)))) diff --git a/src/status_im/subs/wallet/activities_test.cljs b/src/status_im/subs/wallet/activities_test.cljs index b949598910..b90b2872a9 100644 --- a/src/status_im/subs/wallet/activities_test.cljs +++ b/src/status_im/subs/wallet/activities_test.cljs @@ -24,26 +24,26 @@ (fn [db] (-> db (assoc-in [:wallet :activities] - {"acc1" [{:activity-type constants/wallet-activity-type-send - :amount-out "0x1" - :sender "acc1" - :recipient "acc2" - :timestamp 1588291200} - {:activity-type constants/wallet-activity-type-receive - :amount-in "0x1" - :sender "acc2" - :recipient "acc1" - :timestamp 1588377600} - {:activity-type constants/wallet-activity-type-send - :amount-out "0x1" - :sender "acc1" - :recipient "acc4" - :timestamp 1588464000}] - "acc3" [{:activity-type constants/wallet-activity-type-receive - :amount-in "0x1" - :sender "acc4" - :recipient "acc3" - :timestamp 1588464000}]}) + {"acc1" {1 {:activity-type constants/wallet-activity-type-send + :amount-out "0x1" + :sender "acc1" + :recipient "acc2" + :timestamp 1588291200} + 2 {:activity-type constants/wallet-activity-type-receive + :amount-in "0x1" + :sender "acc2" + :recipient "acc1" + :timestamp 1588377600} + 3 {:activity-type constants/wallet-activity-type-send + :amount-out "0x1" + :sender "acc1" + :recipient "acc4" + :timestamp 1588464000}} + "acc3" {4 {:activity-type constants/wallet-activity-type-receive + :amount-in "0x1" + :sender "acc4" + :recipient "acc3" + :timestamp 1588464000}}}) (assoc-in [:wallet :current-viewing-account-address] "acc1")))) (is (match? [{:title "May 3, 2020" diff --git a/src/status_im/subs/wallet/send.cljs b/src/status_im/subs/wallet/send.cljs index 24f98ffda2..ad1045ba51 100644 --- a/src/status_im/subs/wallet/send.cljs +++ b/src/status_im/subs/wallet/send.cljs @@ -49,8 +49,9 @@ :<- [:wallet/all-activities] :<- [:wallet/current-viewing-account-address] (fn [[all-activities current-viewing-account-address]] - (let [address-activity (get all-activities current-viewing-account-address)] + (let [address-activity (vals (get all-activities current-viewing-account-address))] (->> address-activity + (sort :timestamp) (keep (fn [{:keys [activity-type recipient]}] (when (= constants/wallet-activity-type-send activity-type) recipient))) diff --git a/src/status_im/subs/wallet/send_test.cljs b/src/status_im/subs/wallet/send_test.cljs index 0cb307b41b..16714d4af3 100644 --- a/src/status_im/subs/wallet/send_test.cljs +++ b/src/status_im/subs/wallet/send_test.cljs @@ -62,25 +62,25 @@ (fn [db] (-> db (assoc-in [:wallet :activities] - {"acc1" [{:activity-type constants/wallet-activity-type-send - :amount-out "0x1" - :sender "acc1" - :recipient "acc2" - :timestamp 1588291200} - {:activity-type constants/wallet-activity-type-receive - :amount-in "0x1" - :sender "acc2" - :recipient "acc1" - :timestamp 1588377600} - {:activity-type constants/wallet-activity-type-send - :amount-out "0x1" - :sender "acc1" - :recipient "acc4" - :timestamp 1588464000}] - "acc3" [{:activity-type constants/wallet-activity-type-receive - :amount-in "0x1" - :sender "acc4" - :recipient "acc3" - :timestamp 1588464000}]}) + {"acc1" {1 {:activity-type constants/wallet-activity-type-send + :amount-out "0x1" + :sender "acc1" + :recipient "acc2" + :timestamp 1588291200} + 2 {:activity-type constants/wallet-activity-type-receive + :amount-in "0x1" + :sender "acc2" + :recipient "acc1" + :timestamp 1588377600} + 3 {:activity-type constants/wallet-activity-type-send + :amount-out "0x1" + :sender "acc1" + :recipient "acc4" + :timestamp 1588464000}} + "acc3" {4 {:activity-type constants/wallet-activity-type-receive + :amount-in "0x1" + :sender "acc4" + :recipient "acc3" + :timestamp 1588464000}}}) (assoc-in [:wallet :current-viewing-account-address] "acc1")))) (is (match? ["acc2" "acc4"] (rf/sub [sub-name])))))