Add centralized metrics
6e056348...1ef2434b
This commit adds support for pushing centralized metrics to mixpanel.
It uses an interceptor and only picks a few selected events to push
through.
In order to test:
1) Create an account in the app
2) Go to Settings->Privacy
3) Enable metrics
You should now see the events on the mixpanel dashboard (login with your
status-im account for access).
Only some example events are tracked, they are just for testing
This commit is contained in:
parent
7a8db689f4
commit
0a0591f67a
6
Makefile
6
Makefile
|
@ -457,6 +457,12 @@ android-tail-geth: export VERSION ?= debug
|
|||
android-tail-geth:
|
||||
adb shell 'while true; do cat; sleep 1; done < /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
|
||||
|
||||
android-clean-geth: export TARGET := android-sdk
|
||||
android-clean-geth: export VERSION ?= debug
|
||||
android-clean-geth:
|
||||
adb shell 'rm /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
|
||||
|
||||
|
||||
android-logcat: export TARGET := android-sdk
|
||||
android-logcat: ##@other Read status-mobile logs from Android phone using adb
|
||||
adb logcat | grep -e RNBootstrap -e ReactNativeJS -e ReactNative -e StatusModule -e StatusNativeLogs -e 'F DEBUG :' -e 'Go :' -e 'GoLog :' -e 'libc :'
|
||||
|
|
|
@ -246,6 +246,14 @@ class AccountManager(private val reactContext: ReactApplicationContext) : ReactC
|
|||
utils.executeRunnableStatusGoMethod({ Statusgo.openAccounts(rootDir) }, callback)
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
private fun initializeApplication(request: String, callback: Callback) {
|
||||
Log.d(TAG, "initializeApplication")
|
||||
Log.d(TAG, "[Initializing application $request")
|
||||
utils.executeRunnableStatusGoMethod({ Statusgo.initializeApplication(request) }, callback)
|
||||
}
|
||||
|
||||
|
||||
@ReactMethod
|
||||
fun logout() {
|
||||
Log.d(TAG, "logout")
|
||||
|
|
|
@ -76,6 +76,16 @@ class StatusModule(private val reactContext: ReactApplicationContext, private va
|
|||
utils.executeRunnableStatusGoMethod({ Statusgo.getNodeConfig() }, callback)
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun addCentralizedMetric(request: String, callback: Callback) {
|
||||
utils.executeRunnableStatusGoMethod({ Statusgo.addCentralizedMetric(request) }, callback)
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun toggleCentralizedMetrics(request: String, callback: Callback) {
|
||||
utils.executeRunnableStatusGoMethod({ Statusgo.toggleCentralizedMetrics(request) }, callback)
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun deleteImportedKey(keyUID: String, address: String, password: String, callback: Callback) {
|
||||
val keyStoreDir = utils.getKeyStorePath(keyUID)
|
||||
|
|
|
@ -195,6 +195,15 @@ RCT_EXPORT_METHOD(verifyDatabasePassword:(NSString *)keyUID
|
|||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(initializeApplication:(NSString *)request
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"initializeApplication() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoInitializeApplication(request);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(openAccounts:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"OpenAccounts() method called");
|
||||
|
|
|
@ -176,6 +176,24 @@ RCT_EXPORT_METHOD(appStateChange:(NSString *)type) {
|
|||
StatusgoAppStateChange(type);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(addCentralizedMetric:(NSString *)request
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"addCentralizedMetric() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoAddCentralizedMetric(request);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(toggleCentralizedMetrics:(NSString *)request
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"toggleCentralizedMetrics() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoToggleCentralizedMetrics(request);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(startLocalNotifications) {
|
||||
#if DEBUG
|
||||
NSLog(@"StartLocalNotifications() method called");
|
||||
|
|
|
@ -302,6 +302,36 @@ void _MultiAccountStoreAccount(const FunctionCallbackInfo<Value>& args) {
|
|||
delete c;
|
||||
}
|
||||
|
||||
void _InitializeApplication(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
|
||||
if (args.Length() != 1) {
|
||||
// Throw an Error that is passed back to JavaScript
|
||||
isolate->ThrowException(Exception::TypeError(
|
||||
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for InitializeApplication")));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the argument types
|
||||
|
||||
if (!args[0]->IsString()) {
|
||||
isolate->ThrowException(Exception::TypeError(
|
||||
String::NewFromUtf8Literal(isolate, "Wrong argument type for request")));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
|
||||
char *arg0 = *arg0Obj;
|
||||
|
||||
// Call exported Go function, which returns a C string
|
||||
char *c = InitializeApplication(arg0);
|
||||
|
||||
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
|
||||
args.GetReturnValue().Set(ret);
|
||||
delete c;
|
||||
}
|
||||
|
||||
void _InitKeystore(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
@ -1935,6 +1965,7 @@ void init(Local<Object> exports) {
|
|||
NODE_SET_METHOD(exports, "multiAccountStoreDerivedAccounts", _MultiAccountStoreDerivedAccounts);
|
||||
NODE_SET_METHOD(exports, "multiAccountStoreAccount", _MultiAccountStoreAccount);
|
||||
NODE_SET_METHOD(exports, "initKeystore", _InitKeystore);
|
||||
NODE_SET_METHOD(exports, "initializeApplication", _InitializeApplication);
|
||||
NODE_SET_METHOD(exports, "fleets", _Fleets);
|
||||
NODE_SET_METHOD(exports, "stopCPUProfiling", _StopCPUProfiling);
|
||||
NODE_SET_METHOD(exports, "encodeTransfer", _EncodeTransfer);
|
||||
|
@ -1972,7 +2003,7 @@ void init(Local<Object> exports) {
|
|||
NODE_SET_METHOD(exports, "signTypedData", _SignTypedData);
|
||||
NODE_SET_METHOD(exports, "sendTransaction", _SendTransaction);
|
||||
NODE_SET_METHOD(exports, "appStateChange", _AppStateChange);
|
||||
NODE_SET_METHOD(exports, "setSignalEventCallback", _SetSignalEventCallback);
|
||||
NODE_SET_METHOD(exports, "setSignalEventCallback", _SetSignalEventCallback);
|
||||
NODE_SET_METHOD(exports, "validateNodeConfig", _ValidateNodeConfig);
|
||||
NODE_SET_METHOD(exports, "hashTypedData", _HashTypedData);
|
||||
NODE_SET_METHOD(exports, "recover", _Recover);
|
||||
|
|
|
@ -45,6 +45,8 @@ SECRETS_ENV_VARS=(
|
|||
'INFURA_TOKEN'
|
||||
'INFURA_TOKEN_SECRET'
|
||||
'OPENSEA_API_KEY'
|
||||
'MIXPANEL_APP_ID'
|
||||
'MIXPANEL_TOKEN'
|
||||
'POKT_TOKEN'
|
||||
)
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@
|
|||
:closure-defines
|
||||
{status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
||||
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
|
||||
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
|
||||
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
|
||||
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
|
||||
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
|
||||
|
@ -102,6 +104,8 @@
|
|||
{status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
||||
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
|
||||
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
|
||||
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
|
||||
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
|
||||
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
|
||||
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
|
||||
|
@ -143,6 +147,8 @@
|
|||
status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
||||
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
|
||||
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
|
||||
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
|
||||
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
|
||||
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
|
||||
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
|
||||
|
|
|
@ -1,130 +0,0 @@
|
|||
(ns legacy.status-im.utils.test
|
||||
(:require
|
||||
[legacy.status-im.utils.deprecated-types :as types]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(def native-status (js/require "../../modules/react-native-status/nodejs/bindings"))
|
||||
|
||||
(def fs (js/require "fs"))
|
||||
(def path (js/require "path"))
|
||||
(def os (js/require "os"))
|
||||
|
||||
(def tmpdir (.tmpdir os))
|
||||
|
||||
(def test-dir-prefix (.join path tmpdir "status-mobile-tests"))
|
||||
|
||||
(def test-dir (.mkdtempSync fs test-dir-prefix))
|
||||
|
||||
(def initialized? (atom false))
|
||||
|
||||
(defn signal-received-callback
|
||||
[a]
|
||||
(re-frame/dispatch [:signals/signal-received a]))
|
||||
|
||||
;; We poll for signals, could not get callback working
|
||||
(defn init!
|
||||
[]
|
||||
(when-not @initialized?
|
||||
(.setSignalEventCallback native-status)
|
||||
(reset! initialized? true)
|
||||
(js/setInterval (fn []
|
||||
(.pollSignal native-status signal-received-callback)
|
||||
100))))
|
||||
|
||||
(def ui-helper
|
||||
(clj->js
|
||||
{:clearCookies identity
|
||||
:clearStorageAPIs identity}))
|
||||
|
||||
(def encryption-utils
|
||||
(clj->js
|
||||
{:sha3
|
||||
(fn [s] (.sha3 native-status s))
|
||||
:setBlankPreviewFlag
|
||||
identity
|
||||
:encodeTransfer
|
||||
(fn [to-norm amount-hex]
|
||||
(.encodeTransfer native-status to-norm amount-hex))
|
||||
:hexToNumber
|
||||
(fn [hex] (.hexToNumber native-status hex))
|
||||
:decodeParameters
|
||||
(fn [decode-param-json]
|
||||
(.decodeParameters native-status decode-param-json))
|
||||
:numberToHex
|
||||
(fn [num-str] (.numberToHex native-status num-str))
|
||||
:initKeystore
|
||||
(fn [key-uid callback]
|
||||
(callback (.initKeystore native-status
|
||||
(str test-dir "/keystore/" key-uid))))
|
||||
:multiformatDeserializePublicKey
|
||||
(fn [public-key deserialization-key callback]
|
||||
(callback (.multiformatDeserializePublicKey
|
||||
native-status
|
||||
public-key
|
||||
deserialization-key)))}))
|
||||
|
||||
(def account-manager
|
||||
(clj->js
|
||||
{:openAccounts
|
||||
(fn [callback]
|
||||
(callback (.openAccounts native-status test-dir)))
|
||||
:createAccountAndLogin
|
||||
(fn [request] (.createAccountAndLogin native-status request))
|
||||
:logout
|
||||
(fn [] (.logout native-status))
|
||||
:multiAccountImportMnemonic
|
||||
(fn [json callback]
|
||||
(callback (.multiAccountImportMnemonic native-status json)))
|
||||
:multiAccountLoadAccount
|
||||
(fn [json callback]
|
||||
(callback (.multiAccountLoadAccount native-status json)))
|
||||
:multiAccountDeriveAddresses
|
||||
(fn [json callback]
|
||||
(callback (.multiAccountDeriveAddresses native-status json)))
|
||||
:multiAccountGenerateAndDeriveAddresses
|
||||
(fn [json callback]
|
||||
(callback (.multiAccountGenerateAndDeriveAddresses native-status json)))
|
||||
:multiAccountStoreDerived
|
||||
(fn [json callback]
|
||||
(callback (.multiAccountStoreDerivedAccounts native-status json)))}))
|
||||
|
||||
(def utils
|
||||
(clj->js
|
||||
{:backupDisabledDataDir
|
||||
(fn [] (str test-dir "/backup"))
|
||||
:keystoreDir (fn [] "")
|
||||
:toChecksumAddress
|
||||
(fn [address] (.toChecksumAddress native-status address))
|
||||
:checkAddressChecksum
|
||||
(fn [address] (.checkAddressChecksum native-status address))
|
||||
:validateMnemonic
|
||||
(fn [json callback] (callback (.validateMnemonic native-status json)))
|
||||
:isAddress
|
||||
(fn [address] (.isAddress native-status address))}))
|
||||
|
||||
(def log-manager
|
||||
(clj->js
|
||||
{:logFileDirectory
|
||||
(fn [] (str test-dir "/log"))
|
||||
:initLogging
|
||||
(fn [enabled mobile-system log-level callback]
|
||||
(callback (.initLogging native-status
|
||||
(types/clj->json {:Enabled enabled
|
||||
:MobileSystem mobile-system
|
||||
:Level log-level
|
||||
:File (str test-dir "/geth.log")}))))}))
|
||||
|
||||
(def network
|
||||
(clj->js
|
||||
{:callPrivateRPC
|
||||
(fn [payload callback]
|
||||
(callback (.callPrivateRPC native-status payload)))}))
|
||||
|
||||
(def status
|
||||
(clj->js
|
||||
{:getNodeConfig
|
||||
(fn [] (types/clj->json {:WakuV2Config ""}))
|
||||
:fleets
|
||||
(fn [] (.fleets native-status))
|
||||
:startLocalNotifications
|
||||
identity}))
|
|
@ -72,10 +72,12 @@
|
|||
(log/debug "[native-module] init-keystore" key-uid)
|
||||
(.initKeystore ^js (encryption) key-uid callback))
|
||||
|
||||
(defn open-accounts
|
||||
[callback]
|
||||
(log/debug "[native-module] open-accounts")
|
||||
(.openAccounts ^js (account-manager) #(callback (types/json->clj %))))
|
||||
(defn initialize-application
|
||||
[request callback]
|
||||
(log/debug "[native-module] initialize-application")
|
||||
(.initializeApplication ^js (account-manager)
|
||||
(types/clj->json request)
|
||||
#(callback (types/json->clj %))))
|
||||
|
||||
(defn prepare-dir-and-update-config
|
||||
[key-uid config callback]
|
||||
|
@ -513,6 +515,14 @@
|
|||
(let [result (.checkAddressChecksum ^js (utils) address)]
|
||||
(types/json->clj result)))
|
||||
|
||||
(defn toggle-centralized-metrics
|
||||
[enabled callback]
|
||||
(.toggleCentralizedMetrics ^js (status) (types/clj->json {:enabled enabled}) callback))
|
||||
|
||||
(defn add-centralized-metric
|
||||
[metric]
|
||||
(.addCentralizedMetric ^js (status) (types/clj->json metric) #(log/debug "pushed metric" % metric)))
|
||||
|
||||
(defn address?
|
||||
[address]
|
||||
(log/debug "[native-module] address?")
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
(goog-define ALCHEMY_OPTIMISM_GOERLI_TOKEN "")
|
||||
(goog-define ALCHEMY_OPTIMISM_SEPOLIA_TOKEN "")
|
||||
(goog-define WALLET_CONNECT_PROJECT_ID "87815d72a81d739d2a7ce15c2cfdefb3")
|
||||
(goog-define MIXPANEL_APP_ID "3350627")
|
||||
(goog-define MIXPANEL_TOKEN "5c73bda2d36a9f688a5ee45641fb6775")
|
||||
|
||||
(def mainnet-rpc-url (str "https://eth-archival.rpc.grove.city/v1/" POKT_TOKEN))
|
||||
(def goerli-rpc-url (str "https://goerli-archival.gateway.pokt.network/v1/lb/" POKT_TOKEN))
|
||||
|
@ -39,6 +41,9 @@
|
|||
(def opensea-link "https://opensea.io")
|
||||
(def opensea-tesnet-link "https://testnets.opensea.io")
|
||||
|
||||
(def mixpanel-app-id MIXPANEL_APP_ID)
|
||||
(def mixpanel-token MIXPANEL_TOKEN)
|
||||
|
||||
(def opensea-api-key OPENSEA_API_KEY)
|
||||
(def bootnodes-settings-enabled? (enabled? (get-config :BOOTNODES_SETTINGS_ENABLED "1")))
|
||||
(def mailserver-confirmations-enabled? (enabled? (get-config :MAILSERVER_CONFIRMATIONS_ENABLED)))
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
(ns status-im.contexts.centralized-metrics.effects
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-fx :effects.centralized-metrics/toggle-metrics
|
||||
(fn [enabled?]
|
||||
(native-module/toggle-centralized-metrics enabled? #(log/debug "toggled-metrics" % enabled?))))
|
|
@ -0,0 +1,33 @@
|
|||
(ns status-im.contexts.centralized-metrics.events
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.interceptor :as interceptor]
|
||||
status-im.contexts.centralized-metrics.effects
|
||||
[status-im.contexts.centralized-metrics.tracking :as tracking]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn push-event?
|
||||
[db]
|
||||
(or (not (:centralized-metrics/user-confirmed? db))
|
||||
(:centralized-metrics/enabled? db)))
|
||||
|
||||
(defn centralized-metrics-interceptor
|
||||
[context]
|
||||
(when-let [event (tracking/tracked-event (interceptor/get-coeffect context :event))]
|
||||
(log/debug "tracking event" event)
|
||||
(when (push-event? (interceptor/get-coeffect context :db))
|
||||
(native-module/add-centralized-metric event)))
|
||||
context)
|
||||
|
||||
(def interceptor
|
||||
(interceptor/->interceptor
|
||||
:id :centralized-metrics
|
||||
:after centralized-metrics-interceptor))
|
||||
|
||||
(rf/reg-event-fx :centralized-metrics/toggle-centralized-metrics
|
||||
(fn [{:keys [db]} [enabled?]]
|
||||
{:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]
|
||||
:db (assoc db
|
||||
:centralized-metrics/user-confirmed? true
|
||||
:centralized-metrics/enabled? enabled?)}))
|
|
@ -0,0 +1,37 @@
|
|||
(ns status-im.contexts.centralized-metrics.events-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest is testing]]
|
||||
matcher-combinators.test
|
||||
[status-im.contexts.centralized-metrics.events :as events]
|
||||
[status-im.contexts.centralized-metrics.tracking :as tracking]
|
||||
[test-helpers.unit :as h]))
|
||||
|
||||
(deftest push-event-test
|
||||
(testing "returns correct boolean value"
|
||||
(is (true? (events/push-event? {:centralized-metrics/user-confirmed? false})))
|
||||
(is (true? (events/push-event? {:centralized-metrics/enabled? true})))
|
||||
(is (false? (events/push-event? {:centralized-metrics/user-confirmed? true
|
||||
:centralized-metrics/enabled? false})))))
|
||||
|
||||
(deftest centralized-metrics-interceptor-test
|
||||
(testing "processes context correctly"
|
||||
(with-redefs [tracking/tracked-event (fn [_] {:metric "mocked-event"})
|
||||
events/push-event? (fn [_] true)]
|
||||
(let [context {:coeffects {:event [:some-event]
|
||||
:db {:centralized-metrics/enabled? true}}}]
|
||||
(is (= context (events/centralized-metrics-interceptor context)))))))
|
||||
|
||||
(h/deftest-event :centralized-metrics/toggle-centralized-metrics
|
||||
[event-id dispatch]
|
||||
(testing "toggling value to true"
|
||||
(let [enabled? true
|
||||
expected-fxs {:db {:centralized-metrics/user-confirmed? true
|
||||
:centralized-metrics/enabled? enabled?}
|
||||
:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]}]
|
||||
(is (match? expected-fxs (dispatch [event-id enabled?])))))
|
||||
(testing "toggling value to false"
|
||||
(let [enabled? false
|
||||
expected-fxs {:db {:centralized-metrics/user-confirmed? true
|
||||
:centralized-metrics/enabled? enabled?}
|
||||
:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]}]
|
||||
(is (match? expected-fxs (dispatch [event-id enabled?]))))))
|
|
@ -0,0 +1,40 @@
|
|||
(ns status-im.contexts.centralized-metrics.tracking
|
||||
(:require
|
||||
[legacy.status-im.utils.build :as build]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(defn user-journey-event
|
||||
[action]
|
||||
{:metric
|
||||
{:eventName "user-journey"
|
||||
:platform platform/os
|
||||
:appVersion build/app-short-version
|
||||
:eventValue {:action action}}})
|
||||
|
||||
(def ^:const app-started-event "app-started")
|
||||
(def ^:const navigate-to-create-profile-event "navigate-to-create-profile")
|
||||
(def ^:const communities-tab-clicked "communities-tab-clicked")
|
||||
(def ^:const wallet-tab-clicked "wallet-tab-clicked")
|
||||
(def ^:const chats-tab-clicked "chats-tab-clicked")
|
||||
|
||||
(defn track-view-id-event
|
||||
[view-id]
|
||||
(case view-id
|
||||
:communities-stack (user-journey-event communities-tab-clicked)
|
||||
:chats-stack (user-journey-event chats-tab-clicked)
|
||||
:wallet-stack (user-journey-event wallet-tab-clicked)
|
||||
nil))
|
||||
|
||||
(defn tracked-event
|
||||
[[event-name second-parameter]]
|
||||
(case event-name
|
||||
:onboarding/navigate-to-create-profile
|
||||
(user-journey-event navigate-to-create-profile-event)
|
||||
|
||||
:profile/get-profiles-overview-success
|
||||
(user-journey-event app-started-event)
|
||||
|
||||
:set-view-id
|
||||
(track-view-id-event second-parameter)
|
||||
|
||||
nil))
|
|
@ -0,0 +1,35 @@
|
|||
(ns status-im.contexts.centralized-metrics.tracking-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest is testing]]
|
||||
[legacy.status-im.utils.build :as build]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.contexts.centralized-metrics.tracking :as tracking]))
|
||||
|
||||
(deftest user-journey-event-test
|
||||
(testing "creates correct metric event"
|
||||
(let [action "some-action"
|
||||
expected {:metric {:eventName "user-journey"
|
||||
:platform platform/os
|
||||
:appVersion build/app-short-version
|
||||
:eventValue {:action action}}}]
|
||||
(is (= expected (tracking/user-journey-event action))))))
|
||||
|
||||
(deftest track-view-id-event-test
|
||||
(testing "returns correct event for view-id"
|
||||
(is (= (tracking/user-journey-event tracking/communities-tab-clicked)
|
||||
(tracking/track-view-id-event :communities-stack)))
|
||||
(is (= (tracking/user-journey-event tracking/chats-tab-clicked)
|
||||
(tracking/track-view-id-event :chats-stack)))
|
||||
(is (= (tracking/user-journey-event tracking/wallet-tab-clicked)
|
||||
(tracking/track-view-id-event :wallet-stack)))
|
||||
(is (nil? (tracking/track-view-id-event :unknown-stack)))))
|
||||
|
||||
(deftest tracked-event-test
|
||||
(testing "returns correct event for given inputs"
|
||||
(is (= (tracking/user-journey-event tracking/navigate-to-create-profile-event)
|
||||
(tracking/tracked-event [:onboarding/navigate-to-create-profile])))
|
||||
(is (= (tracking/user-journey-event tracking/app-started-event)
|
||||
(tracking/tracked-event [:profile/get-profiles-overview-success])))
|
||||
(is (= (tracking/track-view-id-event :wallet-stack)
|
||||
(tracking/tracked-event [:set-view-id :wallet-stack])))
|
||||
(is (nil? (tracking/tracked-event [:unknown-event])))))
|
|
@ -139,6 +139,7 @@
|
|||
[id token-gated? intro-message]
|
||||
[[(when-not token-gated? (view-members id))
|
||||
(when-not token-gated? (view-rules id intro-message))
|
||||
(mark-as-read id)
|
||||
(invite-contacts id)
|
||||
(when token-gated? (view-token-gating id))
|
||||
(show-qr id)
|
||||
|
|
|
@ -28,21 +28,20 @@
|
|||
(defn create
|
||||
[]
|
||||
(let [log-enabled? (boolean (not-empty config/log-level))]
|
||||
(merge (login)
|
||||
{:deviceName (native-module/get-installation-name)
|
||||
:rootDataDir (native-module/backup-disabled-data-dir)
|
||||
:rootKeystoreDir (native-module/keystore-dir)
|
||||
|
||||
:logLevel (when log-enabled? config/log-level)
|
||||
:logEnabled log-enabled?
|
||||
:logFilePath (native-module/log-file-directory)
|
||||
:verifyTransactionURL config/verify-transaction-url
|
||||
:verifyENSURL config/verify-ens-url
|
||||
:verifyENSContractAddress config/verify-ens-contract-address
|
||||
:verifyTransactionChainID config/verify-transaction-chain-id
|
||||
:wakuV2LightClient true
|
||||
:previewPrivacy config/blank-preview?
|
||||
:testNetworksEnabled config/test-networks-enabled?})))
|
||||
(assoc (login)
|
||||
:deviceName (native-module/get-installation-name)
|
||||
:rootDataDir (native-module/backup-disabled-data-dir)
|
||||
:rootKeystoreDir (native-module/keystore-dir)
|
||||
:logLevel (when log-enabled? config/log-level)
|
||||
:logEnabled log-enabled?
|
||||
:logFilePath (native-module/log-file-directory)
|
||||
:verifyTransactionURL config/verify-transaction-url
|
||||
:verifyENSURL config/verify-ens-url
|
||||
:verifyENSContractAddress config/verify-ens-contract-address
|
||||
:verifyTransactionChainID config/verify-transaction-chain-id
|
||||
:wakuV2LightClient true
|
||||
:previewPrivacy config/blank-preview?
|
||||
:testNetworksEnabled config/test-networks-enabled?)))
|
||||
|
||||
(defn strip-file-prefix
|
||||
[path]
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
(:require
|
||||
[legacy.status-im.data-store.settings :as data-store.settings]
|
||||
[native-module.core :as native-module]
|
||||
[status-im.config :as config]
|
||||
[status-im.contexts.profile.edit.accent-colour.events]
|
||||
[status-im.contexts.profile.edit.bio.events]
|
||||
[status-im.contexts.profile.edit.header.events]
|
||||
|
@ -27,7 +28,10 @@
|
|||
(rf/reg-fx
|
||||
:profile/get-profiles-overview
|
||||
(fn [callback]
|
||||
(native-module/open-accounts callback)))
|
||||
(native-module/initialize-application {:dataDir (native-module/backup-disabled-data-dir)
|
||||
:mixpanelAppId config/mixpanel-app-id
|
||||
:mixpanelToken config/mixpanel-token}
|
||||
callback)))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:profile/profile-selected
|
||||
|
@ -36,23 +40,27 @@
|
|||
|
||||
(rf/reg-event-fx
|
||||
:profile/get-profiles-overview-success
|
||||
(fn [{:keys [db]} [profiles-overview]]
|
||||
(if (seq profiles-overview)
|
||||
(let [profiles (reduce-profiles profiles-overview)
|
||||
{:keys [key-uid]} (first (sort-by :timestamp > (vals profiles)))]
|
||||
{:db (if key-uid
|
||||
(-> db
|
||||
(assoc :profile/profiles-overview profiles)
|
||||
(update :profile/login #(select-profile % key-uid)))
|
||||
db)
|
||||
:fx [[:dispatch [:init-root :screen/profile.profiles]]
|
||||
(when key-uid
|
||||
[:effects.biometric/check-if-available
|
||||
{:key-uid key-uid
|
||||
:on-success (fn [auth-method]
|
||||
(rf/dispatch [:profile.login/check-biometric-success key-uid
|
||||
auth-method]))}])]})
|
||||
{:fx [[:dispatch [:init-root :screen/onboarding.intro]]]})))
|
||||
(fn [{:keys [db]} [{:keys [accounts] {:keys [userConfirmed enabled]} :centralizedMetricsInfo}]]
|
||||
(let [db-with-settings (assoc db
|
||||
:centralized-metrics/user-confirmed? userConfirmed
|
||||
:centralized-metrics/enabled? enabled)]
|
||||
(if (seq accounts)
|
||||
(let [profiles (reduce-profiles accounts)
|
||||
{:keys [key-uid]} (first (sort-by :timestamp > (vals profiles)))]
|
||||
{:db (if key-uid
|
||||
(-> db-with-settings
|
||||
(assoc :profile/profiles-overview profiles)
|
||||
(update :profile/login #(select-profile % key-uid)))
|
||||
db-with-settings)
|
||||
:fx [[:dispatch [:init-root :screen/profile.profiles]]
|
||||
(when key-uid
|
||||
[:effects.biometric/check-if-available
|
||||
{:key-uid key-uid
|
||||
:on-success (fn [auth-method]
|
||||
(rf/dispatch [:profile.login/check-biometric-success key-uid
|
||||
auth-method]))}])]})
|
||||
{:db db-with-settings
|
||||
:fx [[:dispatch [:init-root :screen/onboarding.intro]]]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:profile/update-setting-from-backup
|
||||
|
|
|
@ -61,13 +61,12 @@
|
|||
:image :icon
|
||||
:blur? true
|
||||
:action :arrow})]
|
||||
[(when config/show-not-implemented-features?
|
||||
{:title (i18n/label :t/privacy-and-security)
|
||||
:on-press #(rf/dispatch [:open-modal :screen/settings-privacy-and-security])
|
||||
:image-props :i/privacy
|
||||
:image :icon
|
||||
:blur? true
|
||||
:action :arrow})
|
||||
[{:title (i18n/label :t/privacy-and-security)
|
||||
:on-press #(rf/dispatch [:open-modal :screen/settings-privacy-and-security])
|
||||
:image-props :i/privacy
|
||||
:image :icon
|
||||
:blur? true
|
||||
:action :arrow}
|
||||
{:title (i18n/label :t/syncing)
|
||||
:on-press #(rf/dispatch [:open-modal :settings-syncing])
|
||||
:image-props :i/syncing
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
profile)}}])}]}]]
|
||||
[rn/flat-list
|
||||
{:header [settings.header/view {:scroll-y scroll-y}]
|
||||
:data (settings.items/items (boolean (:mnemonic profile)))
|
||||
:data (settings.items/items (boolean (seq (:mnemonic profile))))
|
||||
:shows-vertical-scroll-indicator false
|
||||
:render-fn settings-category-view
|
||||
:get-item-layout get-item-layout
|
||||
|
|
|
@ -13,8 +13,9 @@
|
|||
|
||||
(defn view
|
||||
[]
|
||||
(let [insets (safe-area/get-insets)
|
||||
customization-color (rf/sub [:profile/customization-color])]
|
||||
(let [insets (safe-area/get-insets)
|
||||
centralized-metrics-enabled? (rf/sub [:centralized-metrics/enabled?])
|
||||
customization-color (rf/sub [:profile/customization-color])]
|
||||
[quo/overlay
|
||||
{:type :shell
|
||||
:container-style (style/page-wrapper (:top insets))}
|
||||
|
@ -30,13 +31,15 @@
|
|||
:customization-color customization-color}]
|
||||
[quo/category
|
||||
{:key :category
|
||||
:data [{:title "Dummy"
|
||||
:data [{:title (i18n/label :t/share-usage-data)
|
||||
:image-props :i/placeholder
|
||||
:image :icon
|
||||
:blur? true
|
||||
:action :selector
|
||||
:action-props {:on-change identity
|
||||
:checked? false}
|
||||
:action-props {:on-change #(rf/dispatch
|
||||
[:centralized-metrics/toggle-centralized-metrics
|
||||
(not centralized-metrics-enabled?)])
|
||||
:customization-color customization-color
|
||||
:checked? centralized-metrics-enabled?}
|
||||
:on-press identity}]
|
||||
:blur? true
|
||||
:list-type :settings}]]))
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[re-frame.std-interceptors :as std-interceptors]
|
||||
[status-im.contexts.centralized-metrics.events :as centralized-metrics]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn register-global-interceptors
|
||||
[]
|
||||
(re-frame/reg-global-interceptor rf/debug-handlers-names)
|
||||
(re-frame/reg-global-interceptor centralized-metrics/interceptor)
|
||||
(re-frame/reg-global-interceptor (re-frame/inject-cofx :now))
|
||||
|
||||
;; Interceptor `trim-v` removes the first element of the event vector.
|
||||
|
|
|
@ -185,3 +185,7 @@
|
|||
|
||||
;;theme
|
||||
(reg-root-key-sub :theme :theme)
|
||||
|
||||
;; centralized-metrics
|
||||
(reg-root-key-sub :centralized-metrics/enabled? :centralized-metrics/enabled?)
|
||||
(reg-root-key-sub :centralized-metrics/user-confirmed? :centralized-metrics/user-confirmed?)
|
||||
|
|
|
@ -65,9 +65,9 @@
|
|||
|
||||
(def account-manager
|
||||
(clj->js
|
||||
{:openAccounts
|
||||
(fn [callback]
|
||||
(callback (.openAccounts native-status test-dir)))
|
||||
{:initializeApplication
|
||||
(fn [request callback]
|
||||
(callback (.initializeApplication native-status request)))
|
||||
:createAccountAndLogin
|
||||
(fn [request] (.createAccountAndLogin native-status request))
|
||||
:restoreAccountAndLogin
|
||||
|
@ -130,6 +130,9 @@
|
|||
(clj->js
|
||||
{:getNodeConfig
|
||||
(fn [] (types/clj->json {:WakuV2Config ""}))
|
||||
:addCentralizedMetric
|
||||
(fn [_ callback]
|
||||
(callback))
|
||||
:fleets
|
||||
(fn [] (.fleets native-status))
|
||||
:startLocalNotifications
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v0.181.31",
|
||||
"commit-sha1": "6e056348e6d28f962167118612826f1ef0e47b22",
|
||||
"src-sha256": "1qvfwk28sg93basjzy8r55qz8pk9xg0h7kxv5ykxkbfh4q17a1ns"
|
||||
"version": "v0.181.35",
|
||||
"commit-sha1": "1ef2434b0644581e3c0404d767550cbfee8ad829",
|
||||
"src-sha256": "1dfw4cff1blg063xxrh78dgivcar92k1fspcr84ra1fxw674kmfk"
|
||||
}
|
||||
|
|
|
@ -2749,5 +2749,6 @@
|
|||
"import-keypair-to-use-account": "Import key pair to use this account",
|
||||
"import-keypair-steps": "{{account-name}} was derived from your {{keypair-name}} key pair, which has not yet been imported to this device. To transact using this account, you will need to import the {{keypair-name}} key pair first.",
|
||||
"not-now": "Not now",
|
||||
"share-usage-data": "Share usage data with Status",
|
||||
"value-higher-than-send-amount": "This value is higher than entered amount to send"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue