diff --git a/src/quo/components/wallet/wallet_activity/view.cljs b/src/quo/components/wallet/wallet_activity/view.cljs index 4690cd3499..aa675dd9fa 100644 --- a/src/quo/components/wallet/wallet_activity/view.cljs +++ b/src/quo/components/wallet/wallet_activity/view.cljs @@ -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]) diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index ded6ae10b0..f501404f9d 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -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'") diff --git a/src/status_im/contexts/shell/activity_center/notification/mentions/view.cljs b/src/status_im/contexts/shell/activity_center/notification/mentions/view.cljs index 052e4b8f54..fe0300dc6c 100644 --- a/src/status_im/contexts/shell/activity_center/notification/mentions/view.cljs +++ b/src/status_im/contexts/shell/activity_center/notification/mentions/view.cljs @@ -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 diff --git a/src/status_im/contexts/shell/activity_center/notification/reply/view.cljs b/src/status_im/contexts/shell/activity_center/notification/reply/view.cljs index aadce4b95c..f0bbc201b4 100644 --- a/src/status_im/contexts/shell/activity_center/notification/reply/view.cljs +++ b/src/status_im/contexts/shell/activity_center/notification/reply/view.cljs @@ -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 diff --git a/src/status_im/contexts/wallet/account/tabs/about/view.cljs b/src/status_im/contexts/wallet/account/tabs/about/view.cljs index 6c1cd43634..82b6d3c478 100644 --- a/src/status_im/contexts/wallet/account/tabs/about/view.cljs +++ b/src/status_im/contexts/wallet/account/tabs/about/view.cljs @@ -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 diff --git a/src/status_im/contexts/wallet/account/tabs/view.cljs b/src/status_im/contexts/wallet/account/tabs/view.cljs index fd06ce5cad..7728c25041 100644 --- a/src/status_im/contexts/wallet/account/tabs/view.cljs +++ b/src/status_im/contexts/wallet/account/tabs/view.cljs @@ -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) diff --git a/src/status_im/contexts/wallet/account/view.cljs b/src/status_im/contexts/wallet/account/view.cljs index 4666ad74ef..ab9d06ce24 100644 --- a/src/status_im/contexts/wallet/account/view.cljs +++ b/src/status_im/contexts/wallet/account/view.cljs @@ -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}] diff --git a/src/status_im/contexts/wallet/common/activity_tab/constants.cljs b/src/status_im/contexts/wallet/common/activity_tab/constants.cljs new file mode 100644 index 0000000000..7713d23363 --- /dev/null +++ b/src/status_im/contexts/wallet/common/activity_tab/constants.cljs @@ -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}) + 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 00c7b38e70..2a93b18e69 100644 --- a/src/status_im/contexts/wallet/common/activity_tab/view.cljs +++ b/src/status_im/contexts/wallet/common/activity_tab/view.cljs @@ -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}]))) diff --git a/src/status_im/contexts/wallet/events.cljs b/src/status_im/contexts/wallet/events.cljs index fe6161231f..ee785ca67e 100644 --- a/src/status_im/contexts/wallet/events.cljs +++ b/src/status_im/contexts/wallet/events.cljs @@ -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)}))) diff --git a/src/status_im/contexts/wallet/home/tabs/view.cljs b/src/status_im/contexts/wallet/home/tabs/view.cljs index 570108f1d9..b02b92137c 100644 --- a/src/status_im/contexts/wallet/home/tabs/view.cljs +++ b/src/status_im/contexts/wallet/home/tabs/view.cljs @@ -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 []}])])) diff --git a/src/status_im/contexts/wallet/home/view.cljs b/src/status_im/contexts/wallet/home/view.cljs index 307de25720..276f032689 100644 --- a/src/status_im/contexts/wallet/home/view.cljs +++ b/src/status_im/contexts/wallet/home/view.cljs @@ -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}]])) diff --git a/src/status_im/contexts/wallet/signals.cljs b/src/status_im/contexts/wallet/signals.cljs index 335478c97c..fa296d434c 100644 --- a/src/status_im/contexts/wallet/signals.cljs +++ b/src/status_im/contexts/wallet/signals.cljs @@ -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)))))) diff --git a/src/status_im/feature_flags.cljs b/src/status_im/feature_flags.cljs index 2150a6bcd9..6828fee8f4 100644 --- a/src/status_im/feature_flags.cljs +++ b/src/status_im/feature_flags.cljs @@ -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) diff --git a/src/status_im/subs/root.cljs b/src/status_im/subs/root.cljs index 1917e09b6f..75d55309a7 100644 --- a/src/status_im/subs/root.cljs +++ b/src/status_im/subs/root.cljs @@ -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 diff --git a/src/status_im/subs/wallet/activities.cljs b/src/status_im/subs/wallet/activities.cljs new file mode 100644 index 0000000000..38f10ff45b --- /dev/null +++ b/src/status_im/subs/wallet/activities.cljs @@ -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))) diff --git a/translations/en.json b/translations/en.json index 933b78953b..ca5fa7daa5 100644 --- a/translations/en.json +++ b/translations/en.json @@ -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",