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
This commit is contained in:
Ulises Manuel 2024-07-16 15:07:33 -06:00 committed by GitHub
parent 43651ef0d0
commit 2d0437dd5e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 291 additions and 141 deletions

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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?])

View File

@ -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))})))

View File

@ -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

View File

@ -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)))))

View File

@ -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))))

View File

@ -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"

View File

@ -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)))

View File

@ -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])))))