Wallet: activity items (#19847)

Wallet: activity items (#19847)

---------

Co-authored-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
This commit is contained in:
Omar Basem 2024-05-03 17:26:24 +04:00 committed by GitHub
parent de29c6f7d9
commit 9187ec25c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 230 additions and 31 deletions

View File

@ -32,18 +32,17 @@
(def status-icon
{:pending :i/pending-state
:confirmed :i/positive-state
:finalised :i/diamond-blue
:finalised :i/diamond
:failed :i/negative-state})
(defn transaction-header
[{:keys [transaction
timestamp
counter
theme
blur?]
:or {transaction :receive
counter 1}}]
counter 1}}
theme]
[rn/view
{:style style/transaction-header-container}
[text/text
@ -66,9 +65,10 @@
timestamp]]])
(defn transaction-icon-view
[{:keys [theme blur? transaction status]
[{:keys [blur? transaction status]
:or {transaction :receive
status :pending}}]
status :pending}}
theme]
[rn/view {:style style/icon-container}
[hole-view/hole-view
{:style (style/icon-hole-view theme blur?)
@ -118,10 +118,10 @@
:on-press-out on-press-out}
[rn/view
{:style {:flex-direction :row}}
[transaction-icon-view props]
[transaction-icon-view props theme]
[rn/view
{:style style/content-container}
[transaction-header props]
[transaction-header props theme]
[rn/view {:style style/content-line}
(when first-tag [prop-tag first-tag blur?])
(when second-tag-prefix [prop-text second-tag-prefix theme])

View File

@ -182,7 +182,7 @@
(def ^:const community-id-length 68)
; BIP44 Wallet Root Key, the extended key from which any wallet can be derived
; BIP44 Wallet Root Key, the extended key from which any wallet can be derived
(def ^:const path-wallet-root "m/44'/60'/0'/0")
; EIP1581 Root Key, the extended key from which any whisper key/encryption key can be derived
(def ^:const path-eip1581 "m/43'/60'/1581'")

View File

@ -62,7 +62,7 @@
:unread? (not read)
:context [[common/user-avatar-tag author]
[quo/text {:style style/tag-text}
(string/lower-case (i18n/label :t/on))]
(string/lower-case (i18n/label :t/on-capitalized))]
(if community-chat?
[quo/context-tag
{:type :channel

View File

@ -83,7 +83,7 @@
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:context [[common/user-avatar-tag author]
[quo/text {:style style/lowercase-text} (i18n/label :t/on)]
[quo/text {:style style/lowercase-text} (i18n/label :t/on-capitalized)]
(if community-chat?
[quo/context-tag
{:type :channel

View File

@ -5,6 +5,7 @@
[react-native.core :as rn]
[status-im.config :as config]
[status-im.contexts.profile.utils :as profile.utils]
[status-im.contexts.shell.jump-to.constants :as constants]
[status-im.contexts.wallet.account.tabs.about.style :as style]
[status-im.contexts.wallet.common.utils :as utils]
[utils.i18n :as i18n]
@ -72,7 +73,7 @@
networks (rf/sub [:wallet/network-preference-details])]
[rn/scroll-view
{:style style/about-tab
:content-container-style {:padding-bottom 20}}
:content-container-style {:padding-bottom (+ constants/floating-shell-button-height 8)}}
[quo/data-item
{:description :default
:icon-right? true

View File

@ -33,7 +33,7 @@
[options-drawer/view
{:name (:name collectible-details)
:image (:uri preview-url)}])}]))}]
:activity [activity/view]
:activity [activity/view {:activities []}]
:permissions [empty-tab/view
{:title (i18n/label :t/no-permissions)
:description (i18n/label :t/no-collectibles-description)

View File

@ -7,6 +7,7 @@
[status-im.contexts.wallet.account.tabs.view :as tabs]
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@ -53,7 +54,11 @@
:size 32
:default-active @selected-tab
:data (tabs-data watch-only?)
:on-change #(reset! selected-tab %)
:on-change (rn/use-callback (fn [tab]
(when (and (= :activity tab)
(ff/enabled? :FLAG_WALLET_ACTIVITY_ENABLED))
(rf/dispatch [:wallet/fetch-activities]))
(reset! selected-tab tab)))
:scrollable? true
:scroll-on-press? true}]
[tabs/view {:selected-tab @selected-tab}]

View File

@ -0,0 +1,65 @@
(ns status-im.contexts.wallet.common.activity-tab.constants)
(def ^:const wallet-activity-error-code-success 1)
(def ^:const wallet-activity-error-code-task-canceled 2)
(def ^:const wallet-activity-error-code-failed 3)
(def ^:const wallet-activity-type-send 0)
(def ^:const wallet-activity-type-receive 1)
(def ^:const wallet-activity-type-buy 2)
(def ^:const wallet-activity-type-swap 3)
(def ^:const wallet-activity-type-bridge 4)
(def ^:const wallet-activity-type-contract-deployment 5)
(def ^:const wallet-activity-type-mint 6)
(def ^:const wallet-activity-status-failed 0)
(def ^:const wallet-activity-status-pending 1)
(def ^:const wallet-activity-status-confirmed 2)
(def ^:const wallet-activity-status-finalised 3)
(def ^:const wallet-activity-token-type-native 0)
(def ^:const wallet-activity-token-type-erc-20 1)
(def ^:const wallet-activity-token-type-erc-721 2)
(def ^:const wallet-activity-token-type-erc-1155 3)
(def ^:const wallet-activity-id->name
{wallet-activity-type-send :send
wallet-activity-type-receive :receive
wallet-activity-type-buy :buy
wallet-activity-type-swap :swap
wallet-activity-type-bridge :bridge
wallet-activity-type-contract-deployment :contract-deployment
wallet-activity-type-mint :mint})
(def ^:const wallet-activity-status->name
{wallet-activity-status-failed :failed
wallet-activity-status-pending :pending
wallet-activity-status-confirmed :confirmed
wallet-activity-status-finalised :finalised})
(def ^:const second-tag-prefix
{wallet-activity-type-send :t/from
wallet-activity-type-receive :t/from
wallet-activity-type-buy :t/on
wallet-activity-type-swap :t/to
wallet-activity-type-bridge :t/from
wallet-activity-type-contract-deployment :t/via
wallet-activity-type-mint :t/at})
(def ^:const third-tag-prefix
{wallet-activity-type-send :t/to
wallet-activity-type-receive :t/to
wallet-activity-type-buy :t/to
wallet-activity-type-swap :t/on
wallet-activity-type-bridge :t/to
wallet-activity-type-contract-deployment :t/on
wallet-activity-type-mint :t/via})
(def ^:const fourth-tag-prefix
{wallet-activity-type-send :t/via
wallet-activity-type-receive :t/via
wallet-activity-type-buy :t/via
wallet-activity-type-swap :t/via
wallet-activity-type-bridge :t/in})

View File

@ -1,30 +1,73 @@
(ns status-im.contexts.wallet.common.activity-tab.view
(:require
[legacy.status-im.utils.hex :as utils.hex]
[native-module.core :as native-module]
[quo.core :as quo]
[quo.foundations.resources :as quo.resources]
[quo.theme]
[react-native.core :as rn]
[status-im.common.resources :as resources]
[status-im.contexts.shell.jump-to.constants :as jump-to.constants]
[status-im.contexts.wallet.common.activity-tab.constants :as constants]
[status-im.contexts.wallet.common.empty-tab.view :as empty-tab]
[utils.i18n :as i18n]))
[utils.datetime :as datetime]
[utils.ethereum.chain :as chain]
[utils.i18n :as i18n]
[utils.money :as money]
[utils.re-frame :as rf]))
(def precision 6)
(defn activity-item
[item]
[:<>
[quo/divider-date (:date item)]
[quo/wallet-activity
(merge {:on-press #(js/alert "Item pressed")}
item)]])
[{:keys [activity-type activity-status timestamp symbol-out symbol-in token-in token-out amount-in
amount-out sender recipient]}]
(let [chain-id (or (:chain-id token-in) (:chain-id token-out))
amount-in-units (native-module/hex-to-number
(utils.hex/normalize-hex amount-in))
amount-in-value (money/with-precision
(money/wei->ether amount-in-units)
precision)
amount-out-units (native-module/hex-to-number
(utils.hex/normalize-hex amount-out))
amount-out-value (money/with-precision
(money/wei->ether amount-out-units)
precision)
relative-date (datetime/timestamp->relative (* timestamp 1000))
receiving-activity? (= activity-type constants/wallet-activity-type-receive)]
[quo/wallet-activity
{:transaction (constants/wallet-activity-id->name activity-type)
:timestamp relative-date
:status (constants/wallet-activity-status->name activity-status)
:counter 1
:first-tag {:size 24
:type :token
:token (or symbol-out symbol-in)
:amount (if receiving-activity? amount-in-value amount-out-value)}
:second-tag-prefix (constants/second-tag-prefix activity-type)
:second-tag {:type :address
:address (if receiving-activity? recipient sender)}
:third-tag-prefix (constants/third-tag-prefix activity-type)
:third-tag {:type :address
:address (if receiving-activity? sender recipient)}
:fourth-tag-prefix (constants/fourth-tag-prefix activity-type)
:fourth-tag {:size 24
:type :network
:network-logo (quo.resources/get-network (chain/chain-id->chain-keyword
chain-id))
:network-name (chain/chain-id->chain-name chain-id)}
:blur? false}]))
(defn view
[]
(let [theme (quo.theme/use-theme)
activity-list []]
activity-list (rf/sub [:wallet/activities-for-current-viewing-account])]
(if (empty? activity-list)
[empty-tab/view
{:title (i18n/label :t/no-activity)
:description (i18n/label :t/empty-tab-description)
:image (resources/get-themed-image :no-activity theme)}]
[rn/flat-list
{:data activity-list
:style {:flex 1}
:render-fn activity-item}])))
{:data activity-list
:style {:flex 1}
:content-container-style {:padding-bottom jump-to.constants/floating-shell-button-height}
:render-fn activity-item}])))

View File

@ -1,5 +1,6 @@
(ns status-im.contexts.wallet.events
(:require
[camel-snake-kebab.extras :as cske]
[clojure.string :as string]
[react-native.background-timer :as background-timer]
[react-native.platform :as platform]
@ -10,6 +11,7 @@
[status-im.contexts.wallet.item-types :as item-types]
[taoensso.timbre :as log]
[utils.collection]
[utils.ethereum.chain :as chain]
[utils.ethereum.eip.eip55 :as eip55]
[utils.i18n :as i18n]
[utils.number]
@ -63,6 +65,7 @@
(utils.collection/index-by :address (data-store/rpc->accounts wallet-accounts)))
:fx [[:dispatch [:wallet/get-wallet-token]]
[:dispatch [:wallet/request-collectibles-for-all-accounts {:new-request? true}]]
[:dispatch [:wallet/check-recent-history]]
(when new-account?
[:dispatch [:wallet/navigate-to-new-account navigate-to-account]])]})))
@ -394,6 +397,20 @@
{:error %
:event :wallet/start-wallet})}]]]}))
(rf/reg-event-fx
:wallet/check-recent-history
(fn [{:keys [db]}]
(let [addresses (->> (get-in db [:wallet :accounts])
vals
(map :address))
chain-ids (chain/chain-ids db)]
{:fx [[:json-rpc/call
[{:method "wallet_checkRecentHistoryForChainIDs"
:params [chain-ids addresses]
:on-error #(log/info "failed to check recent history"
{:error %
:event :wallet/check-recent-history})}]]]})))
(rf/reg-event-fx :wallet/initialize
(fn []
{:fx [[:dispatch [:wallet/start-wallet]]
@ -479,3 +496,46 @@
{:db (update-in db [:wallet :ui :network-filter :selected-networks] update-fn network-name)})))
(rf/reg-event-fx :wallet/update-selected-networks update-selected-networks)
(rf/reg-event-fx
:wallet/fetch-activities
(fn [{:keys [db]}]
(let [addresses (->> (get-in db [:wallet :accounts])
vals
(map :address))
chain-ids (chain/chain-ids db)
request-id 0
filters {:period {:startTimestamp 0
:endTimestamp 0}
:types []
:statuses []
:counterpartyAddresses []
:assets []
:collectibles []
:filterOutAssets false
:filterOutCollectibles false}
offset 0
limit 20
request-params [request-id
addresses
chain-ids
filters
offset
limit]]
{:fx [[:json-rpc/call
[{;; This method is deprecated and will be replaced by
;; "wallet_startActivityFilterSession"
;; https://github.com/status-im/status-mobile/issues/19864
:method "wallet_filterActivityAsync"
:params request-params
:on-error #(log/info "failed to fetch activities"
{:error %
:event :wallet/fetch-activities})}]]]})))
(rf/reg-event-fx
:wallet/activity-filtering-done
(fn [{:keys [db]} [{:keys [message]}]]
(let [{:keys [activities]} (transforms/json->clj message)
activities (cske/transform-keys transforms/->kebab-case-keyword activities)
sorted-activities (sort :timestamp activities)]
{:db (assoc-in db [:wallet :activities] sorted-activities)})))

View File

@ -34,4 +34,4 @@
:on-end-reached request-collectibles
:on-collectible-press (fn [{:keys [id]}]
(rf/dispatch [:wallet/get-collectible-details id]))}]
[activity/view])]))
[activity/view {:activities []}])]))

View File

@ -32,8 +32,7 @@
(def tabs-data
[{:id :assets :label (i18n/label :t/assets) :accessibility-label :assets-tab}
{:id :collectibles :label (i18n/label :t/collectibles) :accessibility-label :collectibles-tab}
{:id :activity :label (i18n/label :t/activity) :accessibility-label :activity-tab}])
{:id :collectibles :label (i18n/label :t/collectibles) :accessibility-label :collectibles-tab}])
(defn view
[]
@ -76,5 +75,8 @@
:size 32
:default-active selected-tab
:data tabs-data
:on-change #(set-selected-tab %)}]
:on-change (fn [tab]
(when (= :activity tab)
(rf/dispatch [:wallet/fetch-activities]))
(set-selected-tab tab))}]
[tabs/view {:selected-tab selected-tab}]]))

View File

@ -37,6 +37,9 @@
"wallet-blockchain-status-changed" {:fx [[:dispatch
[:wallet/blockchain-status-changed
(transforms/js->clj event-js)]]]}
"wallet-activity-filtering-done" {:fx [[:dispatch
[:wallet/activity-filtering-done
(transforms/js->clj event-js)]]]}
(log/debug ::unknown-wallet-event
:type event-type
:event (transforms/js->clj event-js))))))

View File

@ -19,7 +19,8 @@
::wallet.assets-modal-hide (enabled-in-env? :FLAG_ASSETS_MODAL_HIDE)
::community.edit-account-selection (enabled-in-env? :FLAG_EDIT_ACCOUNT_SELECTION_ENABLED)
::wallet.contacts (enabled-in-env? :FLAG_CONTACTS_ENABLED)
::wallet.wallet-connect (enabled-in-env? :FLAG_WALLET_CONNECT_ENABLED)}))
::wallet.wallet-connect (enabled-in-env? :FLAG_WALLET_CONNECT_ENABLED)
::wallet.activities (enabled-in-env? :FLAG_WALLET_ACTIVITY_ENABLED)}))
(defn feature-flags [] @feature-flags-config)

View File

@ -14,6 +14,7 @@
status-im.subs.pairing
status-im.subs.profile
status-im.subs.shell
status-im.subs.wallet.activities
status-im.subs.wallet.collectibles
status-im.subs.wallet.networks
status-im.subs.wallet.saved-addresses

View File

@ -0,0 +1,17 @@
(ns status-im.subs.wallet.activities
(:require [re-frame.core :as rf]))
(rf/reg-sub
:wallet/all-activities
:<- [:wallet]
:-> :activities)
(rf/reg-sub
:wallet/activities-for-current-viewing-account
:<- [:wallet/all-activities]
:<- [:wallet/current-viewing-account-address]
(fn [[activities current-viewing-account-address]]
(filter (fn [{:keys [sender recipient]}]
(or (= sender current-viewing-account-address)
(= recipient current-viewing-account-address)))
activities)))

View File

@ -1102,7 +1102,8 @@
"ok-continue": "Okay, continue",
"ok-got-it": "Okay, got it",
"okay": "Okay",
"on": "On",
"on-capitalized": "On",
"on": "on",
"on-the-web": "On the web",
"only-mentions": "Only @mentions",
"open": "Open",