From a239bb6412c507d628158adc2f6fdd78cf4b9187 Mon Sep 17 00:00:00 2001 From: Mohsen Date: Thu, 3 Oct 2024 18:07:41 +0300 Subject: [PATCH] [#21335] feat: add dapp analytics --- .../contexts/centralized_metrics/events.cljs | 4 + .../centralized_metrics/tracking.cljs | 15 +-- .../centralized_metrics/tracking_test.cljs | 2 +- .../contexts/wallet/connected_dapps/view.cljs | 1 + .../events/session_proposals.cljs | 68 +++++++++++--- .../events/session_responses.cljs | 91 ++++++++++++++++--- .../wallet_connect/events/sessions.cljs | 12 ++- .../wallet_connect/utils/data_store.cljs | 45 +++++++++ 8 files changed, 200 insertions(+), 38 deletions(-) diff --git a/src/status_im/contexts/centralized_metrics/events.cljs b/src/status_im/contexts/centralized_metrics/events.cljs index 431e1ccead8..10ef77afebc 100644 --- a/src/status_im/contexts/centralized_metrics/events.cljs +++ b/src/status_im/contexts/centralized_metrics/events.cljs @@ -45,3 +45,7 @@ #(rf/dispatch [:profile.login/login-with-biometric-if-available (get-in db [:profile/login :key-uid])])) :shell? true}]]]}))) + +(rf/reg-event-fx :centralized-metrics/track-event + "Track an event, :centralized-metrics/track-event event-name {:kebab_case_key value}" + (fn [_ _] {})) diff --git a/src/status_im/contexts/centralized_metrics/tracking.cljs b/src/status_im/contexts/centralized_metrics/tracking.cljs index 97129894021..29c26354e57 100644 --- a/src/status_im/contexts/centralized_metrics/tracking.cljs +++ b/src/status_im/contexts/centralized_metrics/tracking.cljs @@ -4,20 +4,20 @@ [react-native.platform :as platform])) (defn key-value-event - [event-name val-key value] + [event-name event-value] {:metric {:eventName event-name :platform platform/os :appVersion build/app-short-version - :eventValue {val-key value}}}) + :eventValue event-value}}) (defn user-journey-event [action] - (key-value-event "user-journey" :action action)) + (key-value-event "user-journey" {:action action})) (defn navigation-event [view-id] - (key-value-event "navigation" :viewId view-id)) + (key-value-event "navigation" {:viewId view-id})) (def ^:const app-started-event "app-started") @@ -51,15 +51,18 @@ (navigation-event (name view-id)))) (defn tracked-event - [[event-name second-parameter]] + [[event-name second-parameter extra-data]] (case event-name :profile/get-profiles-overview-success (user-journey-event app-started-event) :centralized-metrics/toggle-centralized-metrics - (key-value-event "events.metrics-enabled" :enabled second-parameter) + (key-value-event "events.metrics-enabled" {:enabled second-parameter}) :set-view-id (track-view-id-event second-parameter) + :centralized-metrics/track-event + (key-value-event second-parameter extra-data) + nil)) diff --git a/src/status_im/contexts/centralized_metrics/tracking_test.cljs b/src/status_im/contexts/centralized_metrics/tracking_test.cljs index 0eafedcb7d5..cbe139d0430 100644 --- a/src/status_im/contexts/centralized_metrics/tracking_test.cljs +++ b/src/status_im/contexts/centralized_metrics/tracking_test.cljs @@ -18,7 +18,7 @@ :platform platform-os :appVersion app-version :eventValue {val-key value}}}] - (is (= expected (tracking/key-value-event event-name val-key value)))))) + (is (= expected (tracking/key-value-event event-name {val-key value})))))) (deftest user-journey-event-test (testing "creates correct user journey event" diff --git a/src/status_im/contexts/wallet/connected_dapps/view.cljs b/src/status_im/contexts/wallet/connected_dapps/view.cljs index aed27909d82..bec00cded1d 100644 --- a/src/status_im/contexts/wallet/connected_dapps/view.cljs +++ b/src/status_im/contexts/wallet/connected_dapps/view.cljs @@ -20,6 +20,7 @@ (rf/dispatch [:wallet-connect/disconnect-dapp {:topic topic + :name name :on-success (fn [] (rf/dispatch [:toasts/upsert {:id :dapp-disconnect-success diff --git a/src/status_im/contexts/wallet/wallet_connect/events/session_proposals.cljs b/src/status_im/contexts/wallet/wallet_connect/events/session_proposals.cljs index 628d093c79e..46dfe274e28 100644 --- a/src/status_im/contexts/wallet/wallet_connect/events/session_proposals.cljs +++ b/src/status_im/contexts/wallet/wallet_connect/events/session_proposals.cljs @@ -135,34 +135,72 @@ :proposal-request current-proposal :session-networks session-networks :address current-address - :on-success #(rf/dispatch [:wallet-connect/approve-session-success %]) - :on-fail #(rf/dispatch [:wallet-connect/approve-session-error %])}]) + :on-success #(rf/dispatch [:wallet-connect/approve-session-success % + current-proposal]) + :on-fail #(rf/dispatch [:wallet-connect/approve-session-error % + current-proposal])}]) [:dispatch [:dismiss-modal :screen/wallet.wallet-connect-session-proposal]]]} {:fx [[:dispatch [:wallet-connect/no-internet-toast]]]})))) (rf/reg-event-fx :wallet-connect/approve-session-success - (fn [_ [session]] - (log/info "Wallet Connect session approved") - {:fx [[:dispatch [:wallet-connect/on-new-session session]] - [:dispatch [:wallet-connect/reset-current-session-proposal]] - [:dispatch [:wallet-connect/redirect-to-dapp (data-store/get-dapp-redirect-url session)]]]})) + (fn [{:keys [db]} [session proposal]] + (let [[dapp-name networks] (data-store/get-dapp-name-and-networks db proposal) + total-connected-dapps (-> db + :wallet-connect/sessions + count + inc)] + (log/info "Wallet Connect session approved") + {:fx [[:dispatch [:wallet-connect/on-new-session session]] + [:dispatch [:wallet-connect/reset-current-session-proposal]] + [:dispatch [:wallet-connect/redirect-to-dapp (data-store/get-dapp-redirect-url session)]] + [:dispatch + [:centralized-metrics/track-event "dapp-session" + {:dapp_name dapp-name + :networks networks + :action :approved + :result :success}]] + [:dispatch + [:centralized-metrics/track-event "dapp-connected" + {:dapp_name dapp-name + :networks networks + :total_connected_dapps total-connected-dapps}]]]}))) (rf/reg-event-fx :wallet-connect/approve-session-error - (fn [_ [error]] - (log/error "Wallet Connect session approval failed" - {:error error - :event :wallet-connect/approve-session}) - {:fx [[:dispatch [:wallet-connect/reset-current-session-proposal]]]})) + (fn [{:keys [db]} [error proposal]] + (let [[dapp-name networks] (data-store/get-dapp-name-and-networks db proposal)] + (log/error "Wallet Connect session approval failed" + {:error error + :event :wallet-connect/approve-session}) + {:fx [[:dispatch [:wallet-connect/reset-current-session-proposal]] + [:dispatch + [:centralized-metrics/track-event "dapp-session" + {:dapp_name dapp-name + :networks networks + :action :approved + :result :fail}]]]}))) (rf/reg-event-fx :wallet-connect/reject-session-proposal (fn [{:keys [db]} [proposal]] (let [web3-wallet (get db :wallet-connect/web3-wallet) - {:keys [request response-sent?]} (:wallet-connect/current-proposal db)] + {:keys [request response-sent?]} (:wallet-connect/current-proposal db) + [dapp-name networks] (data-store/get-dapp-name-and-networks db proposal)] {:fx [(when-not response-sent? [:effects.wallet-connect/reject-session-proposal {:web3-wallet web3-wallet :proposal (or proposal request) - :on-success #(log/info "Wallet Connect session proposal rejected") - :on-error #(log/error "Wallet Connect unable to reject session proposal")}]) + :on-success (fn [] + (log/info "Wallet Connect session proposal rejected") + (rf/dispatch [:centralized-metrics/track-event "dapp-session" + {:dapp_name dapp-name + :networks networks + :action :rejected + :result :success}])) + :on-error (fn [] + (log/error "Wallet Connect unable to reject session proposal") + (rf/dispatch [:centralized-metrics/track-event "dapp-session" + {:dapp_name dapp-name + :networks networks + :action :rejected + :result :fail}]))}]) [:dispatch [:wallet-connect/reset-current-session-proposal]]]}))) diff --git a/src/status_im/contexts/wallet/wallet_connect/events/session_responses.cljs b/src/status_im/contexts/wallet/wallet_connect/events/session_responses.cljs index 0179a5221c8..12f94e6acd7 100644 --- a/src/status_im/contexts/wallet/wallet_connect/events/session_responses.cljs +++ b/src/status_im/contexts/wallet/wallet_connect/events/session_responses.cljs @@ -1,5 +1,6 @@ (ns status-im.contexts.wallet.wallet-connect.events.session-responses - (:require [re-frame.core :as rf] + (:require [clojure.string :as string] + [re-frame.core :as rf] [react-native.wallet-connect :as wallet-connect] [status-im.constants :as constants] [status-im.contexts.wallet.wallet-connect.utils.data-store :as @@ -52,7 +53,7 @@ :data raw-data :rpc-method rpc-method :on-error #(rf/dispatch [:wallet-connect/on-sign-error %]) - :on-success #(rf/dispatch [:wallet-connect/finish-session-request %])}]]}))) + :on-success #(rf/dispatch [:wallet-connect/respond-sign-message-success %])}]]}))) (rf/reg-event-fx :wallet-connect/respond-sign-typed-data @@ -66,7 +67,7 @@ :chain-id chain-id :version typed-data-version :on-error #(rf/dispatch [:wallet-connect/on-sign-error %]) - :on-success #(rf/dispatch [:wallet-connect/finish-session-request %])}]]}))) + :on-success #(rf/dispatch [:wallet-connect/respond-sign-message-success %])}]]}))) (rf/reg-event-fx :wallet-connect/respond-send-transaction-data @@ -79,8 +80,8 @@ :chain-id chain-id :tx-hash tx-hash :tx-args tx-args - :on-error #(rf/dispatch [:wallet-connect/on-sign-error %]) - :on-success #(rf/dispatch [:wallet-connect/finish-session-request %])}]]}))) + :on-error #(rf/dispatch [:wallet-connect/respond-send-transaction-error %]) + :on-success #(rf/dispatch [:wallet-connect/respond-send-transaction-success %])}]]}))) (rf/reg-event-fx :wallet-connect/respond-sign-transaction-data @@ -94,13 +95,25 @@ :tx-hash tx-hash :tx-params tx-args :on-error #(rf/dispatch [:wallet-connect/on-sign-error %]) - :on-success #(rf/dispatch [:wallet-connect/finish-session-request %])}]]}))) + :on-success #(rf/dispatch [:wallet-connect/respond-sign-message-success %])}]]}))) + +(rf/reg-event-fx :wallet-connect/respond-sign-message-success + (fn [{:keys [db]} [result]] + (let [[dapp-name networks] (data-store/get-dapp-name-and-networks db)] + (log/info "Successfully signed Wallet Connect request") + {:fx [[:dispatch [:wallet-connect/finish-session-request result]] + [:dispatch + [:centralized-metrics/track-event "dapp-sign" + {:dapp_name dapp-name + :networks networks + :result :success}]]]}))) (rf/reg-event-fx :wallet-connect/on-sign-error (fn [{:keys [db]} [error]] (let [{:keys [raw-data address event]} (get db :wallet-connect/current-request) - method (data-store/get-request-method event)] + method (data-store/get-request-method event) + [dapp-name networks] (data-store/get-dapp-name-and-networks db)] (log/error "Failed to sign Wallet Connect request" {:error error :address address @@ -112,7 +125,39 @@ [:dispatch [:toasts/upsert {:type :negative - :text (i18n/label :t/something-went-wrong)}]]]}))) + :text (i18n/label :t/something-went-wrong)}]] + [:dispatch + [:centralized-metrics/track-event "dapp-sign" + {:dapp_name dapp-name + :networks networks + :result :fail}]]]}))) + +(rf/reg-event-fx + :wallet-connect/respond-send-transaction-error + (fn [{:keys [db]}] + (let [[dapp-name networks] (data-store/get-dapp-name-and-networks db)] + (log/error "Failed to send transaction to Wallet Connect") + {:fx [[:dispatch [:wallet-connect/dismiss-request-modal]] + [:dispatch + [:toasts/upsert + {:type :negative + :text (i18n/label :t/something-went-wrong)}]] + [:dispatch + [:centralized-metrics/track-event "dapp-send" + {:dapp_name dapp-name + :networks networks + :result :fail}]]]}))) + +(rf/reg-event-fx :wallet-connect/respond-send-transaction-success + (fn [{:keys [db]} [result]] + (let [[dapp-name networks] (data-store/get-dapp-name-and-networks db)] + (log/info "Successfully sent transaction request to Wallet connect") + {:fx [[:dispatch + [:centralized-metrics/track-event "dapp-send" + {:dapp_name dapp-name + :networks networks + :result :success}]] + [:dispatch [:wallet-connect/finish-session-request result]]]}))) (rf/reg-event-fx :wallet-connect/send-response @@ -176,9 +221,27 @@ (rf/reg-event-fx :wallet-connect/on-request-modal-dismissed (fn [{:keys [db]}] - {:fx [(when-not (get-in db [:wallet-connect/current-request :response-sent?]) - [:dispatch - [:wallet-connect/send-response - {:error (wallet-connect/get-sdk-error - constants/wallet-connect-user-rejected-error-key)}]]) - [:dispatch [:wallet-connect/reset-current-request]]]})) + (let [{:keys [response-sent? event]} (get db :wallet-connect/current-request)] + {:fx [(when-not response-sent? + (let [send-method? (-> event + (data-store/get-request-method) + (string/includes? "send")) + [dapp-name networks] (data-store/get-dapp-name-and-networks db)] + [:dispatch + [:wallet-connect/send-response + {:error (wallet-connect/get-sdk-error + constants/wallet-connect-user-rejected-error-key)}]] + (if send-method? + [:dispatch + [:centralized-metrics/track-event "dapp-send" + {:dapp_name dapp-name + :networks networks + :action :rejected + :result :success}]] + [:dispatch + [:centralized-metrics/track-event "dapp-sign" + {:dapp_name dapp-name + :networks networks + :action :rejected + :result :success}]]))) + [:dispatch [:wallet-connect/reset-current-request]]]}))) diff --git a/src/status_im/contexts/wallet/wallet_connect/events/sessions.cljs b/src/status_im/contexts/wallet/wallet_connect/events/sessions.cljs index 5aedbb120bb..24c74710f79 100644 --- a/src/status_im/contexts/wallet/wallet_connect/events/sessions.cljs +++ b/src/status_im/contexts/wallet/wallet_connect/events/sessions.cljs @@ -18,7 +18,7 @@ (rf/reg-event-fx :wallet-connect/disconnect-dapp - (fn [{:keys [db]} [{:keys [topic on-success on-fail]}]] + (fn [{:keys [db]} [{:keys [topic name on-success on-fail]}]] (let [web3-wallet (get db :wallet-connect/web3-wallet) network-status (:network/status db)] (log/info "Disconnecting dApp session" topic) @@ -26,10 +26,18 @@ {:fx [[:effects.wallet-connect/disconnect {:web3-wallet web3-wallet :topic topic - :on-fail on-fail + :on-fail (fn [] + (rf/dispatch [:centralized-metrics/track-event "dapp-disconnected" + {:dapp_name name + :result :fail}]) + (when on-fail + (on-fail))) :on-success (fn [] (log/info "Successfully disconnected dApp session" topic) (rf/dispatch [:wallet-connect/delete-session topic]) + (rf/dispatch [:centralized-metrics/track-event "dapp-disconnected" + {:dapp_name name + :result :success}]) (when on-success (on-success)))}]]} {:fx [[:dispatch [:wallet-connect/no-internet-toast]]]})))) diff --git a/src/status_im/contexts/wallet/wallet_connect/utils/data_store.cljs b/src/status_im/contexts/wallet/wallet_connect/utils/data_store.cljs index c7b52b7d748..573fb17c9e3 100644 --- a/src/status_im/contexts/wallet/wallet_connect/utils/data_store.cljs +++ b/src/status_im/contexts/wallet/wallet_connect/utils/data_store.cljs @@ -73,3 +73,48 @@ (-> db get-db-current-request-event get-request-params)) + +(defn- find-networks + [current-request current-proposal request db] + (cond + current-request + (get-in current-request [:params :chainId]) + + current-proposal + (->> (get-in db [:wallet-connect/current-proposal :session-networks]) + vec + (string/join ",")) + + request + (->> (or (get-in request [:params :requiredNamespaces :eip155 :chains]) + (get-in request [:requiredNamespaces :eip155 :chains])) + vec + (string/join ",")) + + :else + [])) + +(defn- find-url + [current-request current-proposal request] + (cond + current-request + (get-in current-request [:verifyContext :verified :origin]) + + current-proposal + (get-in current-proposal [:params :proposer :metadata :url]) + + request + (or (get-in request [:params :proposer :metadata :url]) + (get-in request [:peer :metadata :url])) + + :else + nil)) + +(defn get-dapp-name-and-networks + [db & [request]] + (let [current-request (get-in db [:wallet-connect/current-request :event]) + current-proposal (get-in db [:wallet-connect/current-proposal :request]) + session-networks (find-networks current-request current-proposal request db) + dapp-url (find-url current-request current-proposal request) + dapp-name (compute-dapp-name nil dapp-url)] + [dapp-name session-networks]))