From dacfe97a5809b44f894533f0b02e771d4ae17ee3 Mon Sep 17 00:00:00 2001 From: Eric Dvorsak Date: Sun, 26 Aug 2018 02:45:03 +0200 Subject: [PATCH] refactor events and fns to dedicated namespaces - move init events and fns to dedicated namespace - move web3 events and fns to dedicated namespaces - move signal events and fns to dedicated namespace - move notifications events and fns to dedicated namespace - cosmetic fixes - remove print statements - fix formating - remove unused imports --- src/status_im/android/core.cljs | 2 +- src/status_im/chat/models/message.cljs | 10 +- src/status_im/core.cljs | 2 +- src/status_im/init/core.cljs | 188 ++++++++++ src/status_im/init/events.cljs | 96 +++++ src/status_im/ios/core.cljs | 2 +- src/status_im/models/protocol.cljs | 5 +- src/status_im/network/events.cljs | 18 +- .../core.cljs} | 65 ++-- src/status_im/notifications/events.cljs | 44 +++ src/status_im/protocol/handlers.cljs | 28 +- src/status_im/signals/core.cljs | 28 ++ src/status_im/signals/events.cljs | 12 + src/status_im/transport/handlers.cljs | 34 +- .../ui/screens/accounts/login/models.cljs | 15 +- src/status_im/ui/screens/accounts/models.cljs | 6 +- .../ui/screens/add_new/new_chat/events.cljs | 1 - src/status_im/ui/screens/events.cljs | 338 ++---------------- src/status_im/utils/keychain/events.cljs | 2 +- src/status_im/utils/web3_provider.cljs | 17 - src/status_im/web3/core.cljs | 53 +++ src/status_im/web3/events.cljs | 29 ++ test/cljs/status_im/test/browser/events.cljs | 12 +- test/cljs/status_im/test/init/core.cljs | 9 + .../core.cljs} | 4 +- test/cljs/status_im/test/runner.cljs | 4 +- .../ui/screens/accounts/login/models.cljs | 165 ++++----- .../status_im/test/ui/screens/events.cljs | 9 - 28 files changed, 642 insertions(+), 556 deletions(-) create mode 100644 src/status_im/init/core.cljs create mode 100644 src/status_im/init/events.cljs rename src/status_im/{utils/notifications.cljs => notifications/core.cljs} (77%) create mode 100644 src/status_im/notifications/events.cljs create mode 100644 src/status_im/signals/core.cljs create mode 100644 src/status_im/signals/events.cljs delete mode 100644 src/status_im/utils/web3_provider.cljs create mode 100644 src/status_im/web3/core.cljs create mode 100644 src/status_im/web3/events.cljs create mode 100644 test/cljs/status_im/test/init/core.cljs rename test/cljs/status_im/test/{utils/notifications.cljs => notifications/core.cljs} (97%) delete mode 100644 test/cljs/status_im/test/ui/screens/events.cljs diff --git a/src/status_im/android/core.cljs b/src/status_im/android/core.cljs index b7f6b62a22..f14527d1a9 100644 --- a/src/status_im/android/core.cljs +++ b/src/status_im/android/core.cljs @@ -9,7 +9,7 @@ [status-im.ui.screens.views :as views] [status-im.ui.components.react :as react] [status-im.native-module.core :as status] - [status-im.utils.notifications :as notifications] + [status-im.notifications.core :as notifications] [status-im.core :as core] [status-im.utils.snoopy :as snoopy])) diff --git a/src/status_im/chat/models/message.cljs b/src/status_im/chat/models/message.cljs index 921046cc6b..0cc46627af 100644 --- a/src/status_im/chat/models/message.cljs +++ b/src/status_im/chat/models/message.cljs @@ -12,7 +12,7 @@ [status-im.utils.clocks :as utils.clocks] [status-im.utils.handlers-macro :as handlers-macro] [status-im.utils.money :as money] - [status-im.utils.notifications :as notifications] + [status-im.notifications.core :as notifications] [status-im.transport.utils :as transport.utils] [status-im.transport.message.core :as transport] [status-im.transport.message.v1.protocol :as protocol] @@ -142,10 +142,10 @@ current-chat-id (get-in cofx [:db :current-chat-id])] (when-not (and (= :chat view-id) (= current-chat-id chat-id)) - {:display-notification-fx {:title (i18n/label :notifications-new-message-title) - :body (i18n/label :notifications-new-message-body) - :to chat-id - :from from}})))) + {:notifications/display-notification {:title (i18n/label :notifications-new-message-title) + :body (i18n/label :notifications-new-message-body) + :to chat-id + :from from}})))) (defn- add-received-message [batch? diff --git a/src/status_im/core.cljs b/src/status_im/core.cljs index bb71a7f7d2..dc45aadb9b 100644 --- a/src/status_im/core.cljs +++ b/src/status_im/core.cljs @@ -15,7 +15,7 @@ (defn init [app-root] (log/set-level! config/log-level) (error-handler/register-exception-handler!) - (re-frame/dispatch [:initialize-keychain]) + (re-frame/dispatch [:init/initialize-keychain]) (when config/testfairy-enabled? (.begin js-dependencies/testfairy config/testfairy-token)) (.registerComponent react/app-registry "StatusIm" #(reagent/reactify-component app-root))) diff --git a/src/status_im/init/core.cljs b/src/status_im/init/core.cljs new file mode 100644 index 0000000000..d81da073f0 --- /dev/null +++ b/src/status_im/init/core.cljs @@ -0,0 +1,188 @@ +(ns status-im.init.core + (:require [re-frame.core :as re-frame] + [status-im.constants :as constants] + [status-im.models.account :as models.account] + [status-im.models.browser :as browser] + [status-im.models.chat :as chat] + [status-im.models.contacts :as models.contacts] + [status-im.utils.keychain.core :as keychain] + [status-im.models.protocol :as models.protocol] + [status-im.models.transactions :as transactions] + [status-im.models.wallet :as models.wallet] + [status-im.transport.inbox :as inbox] + [status-im.data-store.realm.core :as realm] + [status-im.ui.screens.accounts.models :as accounts.models] + [status-im.ui.screens.contacts.events :as contacts] + [status-im.i18n :as i18n] + [status-im.ui.screens.db :refer [app-db]] + [status-im.utils.ethereum.core :as ethereum] + [status-im.utils.handlers-macro :as handlers-macro] + [status-im.utils.platform :as platform] + [taoensso.timbre :as log] + [status-im.utils.universal-links.core :as universal-links])) + +;; TODO (yenda) move keychain functions to dedicated namespace +(defn- reset-keychain [] + (.. (keychain/reset) + (then + #(re-frame/dispatch [:init/initialize-keychain])))) + +(defn- handle-reset-data [] + (.. (realm/delete-realms) + (then reset-keychain) + (catch reset-keychain))) + +(defn handle-invalid-key-parameters [encryption-key] + {:title (i18n/label :invalid-key-title) + :content (i18n/label :invalid-key-content) + :confirm-button-text (i18n/label :invalid-key-confirm) + ;; On cancel we initialize the app with the invalid key, to allow the user + ;; to recover the seed phrase + :on-cancel #(do + (log/warn "initializing app with invalid key") + (re-frame/dispatch [:init/initialize-app encryption-key])) + :on-accept handle-reset-data}) + +(defn handle-decryption-failed-parameters [encryption-key] + {:title (i18n/label :decryption-failed-title) + :content (i18n/label :decryption-failed-content) + :confirm-button-text (i18n/label :decryption-failed-confirm) + ;; On cancel we initialize the app with the same key, in case the error was + ;; not related/fs error + :on-cancel #(do + (log/warn "initializing app with same key after decryption failed") + (re-frame/dispatch [:init/initialize-app encryption-key])) + :on-accept handle-reset-data}) + +(defn initialize-keychain [cofx] + {:keychain/get-encryption-key [:init/initialize-app]}) + +(defn set-device-uuid [device-uuid {:keys [db]}] + {:db (assoc db :device-UUID device-uuid)}) + +(defn initialize-views [{{:accounts/keys [accounts] + :push-notifications/keys [initial?] + :as db} :db}] + {:db (if (empty? accounts) + (assoc db :view-id :intro :navigation-stack (list :intro)) + (let [{:keys [address photo-path name]} (first (sort-by :last-sign-in > (vals accounts)))] + (-> db + (assoc :view-id :login + :navigation-stack (list :login)) + (update :accounts/login assoc + :address address + :photo-path photo-path + :name name)))) + :notifications/handle-initial-push-notification initial?}) + +(defn initialize-geth [{:keys [db]}] + (when-not (:status-node-started? db) + (let [default-networks (:networks/networks db) + default-network (:network db)] + {:init/initialize-geth (get-in default-networks [default-network :config])}))) + +(defn initialize-db + "Initialize db to the initial state" + [{{:universal-links/keys [url] + :push-notifications/keys [initial?] + :keys [status-module-initialized? status-node-started? + network-status network peers-count peers-summary device-UUID] + :or {network (get app-db :network)}} :db}] + {:db (assoc app-db + :contacts/contacts {} + :network-status network-status + :peers-count (or peers-count 0) + :peers-summary (or peers-summary []) + :status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?) + :status-node-started? status-node-started? + :network network + :universal-links/url url + :push-notifications/initial? initial? + :device-UUID device-UUID)}) + +(defn initialize-app [encryption-key error cofx] + (cond + (= :invalid-key error) + {:show-confirmation (handle-invalid-key-parameters encryption-key)} + + (= :decryption-failed error) + {:show-confirmation (handle-decryption-failed-parameters encryption-key)} + + :else + (handlers-macro/merge-fx cofx + {:init/init-device-UUID nil + :init/init-store encryption-key + :ui/listen-to-window-dimensions-change nil + :init/testfairy-alert nil} + (initialize-db)))) + +(defn after-decryption [cofx] + (handlers-macro/merge-fx cofx + {:network/listen-to-network-status + [#(re-frame/dispatch [:network/update-connection-status %]) + #(re-frame/dispatch [:network/update-network-status %])]} + (initialize-geth) + (accounts.models/load-accounts) + (initialize-views))) + +(defn initialize-account-db [address {:keys [db web3]}] + (let [{:keys [accounts/accounts accounts/create contacts/contacts networks/networks + network network-status peers-count peers-summary view-id navigation-stack + status-module-initialized? status-node-started? device-UUID + push-notifications/initial? semaphores] + :or {network (get app-db :network)}} db + console-contact (get contacts constants/console-chat-id) + current-account (accounts address) + account-network-id (get current-account :network network) + account-network (get-in current-account [:networks account-network-id])] + {:db (cond-> (assoc app-db + :current-public-key (:public-key current-account) + :view-id view-id + :navigation-stack navigation-stack + :status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?) + :status-node-started? status-node-started? + :accounts/create create + :networks/networks networks + :account/account current-account + :network-status network-status + :network network + :chain (ethereum/network->chain-name account-network) + :push-notifications/initial? initial? + :peers-summary peers-summary + :peers-count peers-count + :device-UUID device-UUID + :semaphores semaphores + :web3 web3) + console-contact + (assoc :contacts/contacts {constants/console-chat-id console-contact}))})) + +(defn initialize-account [address events-after {:keys [web3] :as cofx}] + (handlers-macro/merge-fx cofx + {:web3/set-default-account [web3 address] + :web3/fetch-node-version web3 + :notifications/get-fcm-token nil + :dispatch-n (or events-after [])} + (initialize-account-db address) + (models.protocol/initialize-protocol address) + (models.contacts/load-contacts) + (chat/initialize-chats) + (chat/process-pending-messages) + (browser/initialize-browsers) + (browser/initialize-dapp-permissions) + (models.wallet/update-wallet) + (transactions/run-update) + (transactions/start-sync) + (models.account/update-sign-in-time))) + +(defn status-node-started [{{:node/keys [after-start] :as db} :db}] + ;;TODO (yenda) instead of passing events we can pass effects here and simply return them + (merge {:db (assoc db :status-node-started? true)} + (when after-start {:dispatch-n [after-start]}))) + +(defn status-node-stopped [{{:node/keys [after-stop]} :db}] + ;;TODO (yenda) instead of passing events we can pass effects here and simply return them + (when after-stop {:dispatch-n [after-stop]})) + +(defn status-module-initialized [{:keys [db]}] + {:db (assoc db :status-module-initialized? true) + :init/status-module-initialized-fx nil}) diff --git a/src/status_im/init/events.cljs b/src/status_im/init/events.cljs new file mode 100644 index 0000000000..e90c3fe0df --- /dev/null +++ b/src/status_im/init/events.cljs @@ -0,0 +1,96 @@ +(ns status-im.init.events + (:require [re-frame.core :as re-frame] + [status-im.data-store.core :as data-store] + [status-im.i18n :as i18n] + [status-im.init.core :as init] + status-im.web3.events + [status-im.native-module.core :as status] + [status-im.utils.config :as config] + [status-im.utils.handlers :as handlers] + [status-im.utils.types :as types] + [status-im.utils.utils :as utils] + [taoensso.timbre :as log])) + +;; Try to decrypt the database, move on if successful otherwise go back to +;; initial state +(re-frame/reg-fx + :init/init-store + (fn [encryption-key] + (.. (data-store/init encryption-key) + (then #(re-frame/dispatch [:init/after-decryption])) + (catch (fn [error] + (log/warn "Could not decrypt database" error) + (re-frame/dispatch [:init/initialize-app encryption-key :decryption-failed])))))) + +(re-frame/reg-fx + :init/initialize-geth + (fn [config] + (status/start-node (types/clj->json config) config/fleet))) + +(re-frame/reg-fx + :init/status-module-initialized + (fn [_] + (status/module-initialized!))) + +(re-frame/reg-fx + :init/testfairy-alert + (fn [_] + (when config/testfairy-enabled? + (utils/show-popup + (i18n/label :testfairy-title) + (i18n/label :testfairy-message))))) + +(re-frame/reg-fx + :init/init-device-UUID + (fn [] + (status/get-device-UUID #(re-frame/dispatch [:init/set-device-UUID %])))) + +;; Entrypoint, fetches the key from the keychain and initialize the app +(handlers/register-handler-fx + :init/initialize-keychain + (fn [cofx _] + (init/initialize-keychain cofx))) + +;; Check the key is valid, shows options if not, otherwise continues loading +;; the database +(handlers/register-handler-fx + :init/initialize-app + (fn [cofx [_ encryption-key error]] + (init/initialize-app encryption-key error cofx))) + +;; DB has been decrypted, load accounts, initialize geth, etc +(handlers/register-handler-fx + :init/after-decryption + [(re-frame/inject-cofx :data-store/get-all-accounts)] + (fn [cofx _] + (init/after-decryption cofx))) + +(handlers/register-handler-fx + :init/initialize-account + [(re-frame/inject-cofx :web3/get-web3) + (re-frame/inject-cofx :get-default-contacts) + (re-frame/inject-cofx :get-default-dapps) + (re-frame/inject-cofx :data-store/all-chats) + (re-frame/inject-cofx :data-store/get-messages) + (re-frame/inject-cofx :data-store/get-user-statuses) + (re-frame/inject-cofx :data-store/unviewed-messages) + (re-frame/inject-cofx :data-store/message-ids) + (re-frame/inject-cofx :data-store/get-unanswered-requests) + (re-frame/inject-cofx :data-store/get-local-storage-data) + (re-frame/inject-cofx :data-store/get-all-contacts) + (re-frame/inject-cofx :data-store/get-all-mailservers) + (re-frame/inject-cofx :data-store/transport) + (re-frame/inject-cofx :data-store/all-browsers) + (re-frame/inject-cofx :data-store/all-dapp-permissions)] + (fn [cofx [_ address events-after]] + (init/initialize-account address events-after cofx))) + +(handlers/register-handler-fx + :init/initialize-geth + (fn [cofx _] + (init/initialize-geth cofx))) + +(handlers/register-handler-fx + :init/set-device-UUID + (fn [cofx [_ device-uuid]] + (init/set-device-uuid device-uuid cofx))) diff --git a/src/status_im/ios/core.cljs b/src/status_im/ios/core.cljs index ee6a5241ae..4df0d11de0 100644 --- a/src/status_im/ios/core.cljs +++ b/src/status_im/ios/core.cljs @@ -8,7 +8,7 @@ status-im.data-store.core [status-im.ui.screens.views :as views] [status-im.ui.components.react :as react] - [status-im.utils.notifications :as notifications] + [status-im.notifications.core :as notifications] [status-im.core :as core] [status-im.utils.instabug :as instabug] [status-im.utils.snoopy :as snoopy])) diff --git a/src/status_im/models/protocol.cljs b/src/status_im/models/protocol.cljs index 61a7d1ba1b..61e98bde7b 100644 --- a/src/status_im/models/protocol.cljs +++ b/src/status_im/models/protocol.cljs @@ -1,6 +1,5 @@ (ns status-im.models.protocol - (:require [re-frame.core :as re-frame] - [status-im.constants :as constants] + (:require [status-im.constants :as constants] [status-im.transport.core :as transport] [status-im.transport.inbox :as transport.inbox] [status-im.utils.ethereum.core :as ethereum] @@ -30,7 +29,7 @@ (defn check-sync-state [{{:keys [web3] :as db} :db :as cofx}] (if (:account/account db) - {:protocol/web3-get-syncing web3 + {:web3/get-syncing web3 :dispatch-later [{:ms 10000 :dispatch [:check-sync-state]}]} (semaphores/free :check-sync-state? cofx))) diff --git a/src/status_im/network/events.cljs b/src/status_im/network/events.cljs index db18b3aba3..31abd7fcc7 100644 --- a/src/status_im/network/events.cljs +++ b/src/status_im/network/events.cljs @@ -7,7 +7,7 @@ [status-im.transport.inbox :as inbox])) (re-frame/reg-fx - ::listen-to-network-status + :network/listen-to-network-status (fn [[connection-listener net-info-listener]] (net-info/is-connected? connection-listener) (net-info/net-info net-info-listener) @@ -20,22 +20,14 @@ (status/connection-change data))) (handlers/register-handler-fx - :listen-to-network-status - (fn [] - {::listen-to-network-status [#(re-frame/dispatch [::update-connection-status %]) - #(re-frame/dispatch [::update-network-status %])]})) - -(handlers/register-handler-fx - ::update-connection-status - [re-frame/trim-v] - (fn [{db :db :as cofx} [is-connected?]] + :network/update-connection-status + (fn [{db :db :as cofx} [_ is-connected?]] (handlers-macro/merge-fx cofx {:db (assoc db :network-status (if is-connected? :online :offline))} (inbox/request-messages)))) (handlers/register-handler-fx - ::update-network-status - [re-frame/trim-v] - (fn [_ [data]] + :network/update-network-status + (fn [_ [_ data]] {::notify-status-go data})) diff --git a/src/status_im/utils/notifications.cljs b/src/status_im/notifications/core.cljs similarity index 77% rename from src/status_im/utils/notifications.cljs rename to src/status_im/notifications/core.cljs index a2f780bc78..a14d2bc15d 100644 --- a/src/status_im/utils/notifications.cljs +++ b/src/status_im/notifications/core.cljs @@ -1,4 +1,4 @@ -(ns status-im.utils.notifications +(ns status-im.notifications.core (:require [goog.object :as object] [re-frame.core :as re-frame] [status-im.utils.handlers-macro :as handlers-macro] @@ -13,47 +13,32 @@ (when-not platform/desktop? - (handlers/register-handler-db - :update-fcm-token - (fn [db [_ fcm-token]] - (assoc-in db [:notifications :fcm-token] fcm-token))) - - (handlers/register-handler-fx - :request-notifications-granted - (fn [_ _] - (re-frame/dispatch [:show-mainnet-is-default-alert]))) - - (handlers/register-handler-fx - :request-notifications-denied - (fn [_ _] - (re-frame/dispatch [:show-mainnet-is-default-alert]))) - (def firebase (object/get rn/react-native-firebase "default")) ;; NOTE: Only need to explicitly request permissions on iOS. (defn request-permissions [] (if platform/desktop? - (re-frame/dispatch [:request-notifications-granted {}]) + (re-frame/dispatch [:notifications/request-notifications-granted {}]) (-> (.requestPermission (.messaging firebase)) (.then (fn [_] (log/debug "notifications-granted") - (re-frame/dispatch [:request-notifications-granted {}])) + (re-frame/dispatch [:notifications/request-notifications-granted {}])) (fn [_] (log/debug "notifications-denied") - (re-frame/dispatch [:request-notifications-denied {}])))))) + (re-frame/dispatch [:notifications/request-notifications-denied {}])))))) (defn get-fcm-token [] (-> (.getToken (.messaging firebase)) (.then (fn [x] (log/debug "get-fcm-token: " x) - (re-frame/dispatch [:update-fcm-token x]))))) + (re-frame/dispatch [:notifications/update-fcm-token x]))))) (defn on-refresh-fcm-token [] (.onTokenRefresh (.messaging firebase) (fn [x] (log/debug "on-refresh-fcm-token: " x) - (re-frame/dispatch [:update-fcm-token x])))) + (re-frame/dispatch [:notifications/update-fcm-token x])))) ;; TODO(oskarth): Only called in background on iOS right now. ;; NOTE(oskarth): Hardcoded data keys :sum and :msg in status-go right now. @@ -108,7 +93,8 @@ :dispatch [:navigate-to-chat from]}) (store-event event cofx)))) - (defn handle-push-notification [cofx [_ event]] + (defn handle-push-notification + [cofx [_ event]] (handlers-macro/merge-fx cofx (process-initial-push-notification event) (process-push-notification event))) @@ -117,8 +103,8 @@ (let [to (get-in cofx [:db :accounts/accounts address :public-key]) from (get-in cofx [:db :push-notifications/stored to])] (when from - [:handle-push-notification {:from from - :to to}]))) + [:notification/handle-push-notification {:from from + :to to}]))) (defn parse-notification-payload [s] (try @@ -133,9 +119,19 @@ to (object/get data "to")] (log/debug "on notification" (pr-str msg)) (when (and from to) - (re-frame/dispatch [:handle-push-notification {:from from - :to to - :initial? initial?}])))) + (re-frame/dispatch [:notification/handle-push-notification {:from from + :to to + :initial? initial?}])))) + + (defn handle-initial-push-notification + [initial?] + (when-not initial? + (.. firebase + notifications + getInitialNotification + (then (fn [event] + (when event + (handle-notification-event event {:initial? true}))))))) (defn on-notification-opened [] (.. firebase @@ -164,21 +160,6 @@ (then #(log/debug "Display Notification" title body)) (then #(log/debug "Display Notification error" title body)))) - (re-frame/reg-fx :display-notification-fx display-notification) - - (handlers/register-handler-fx :handle-push-notification handle-push-notification) - - (re-frame/reg-fx - :handle-initial-push-notification-fx - (fn [{:keys [push-notifications/initial?]}] - (when-not initial? - (.. firebase - notifications - getInitialNotification - (then (fn [event] - (when event - (handle-notification-event event {:initial? true})))))))) - (defn init [] (on-refresh-fcm-token) (on-notification) diff --git a/src/status_im/notifications/events.cljs b/src/status_im/notifications/events.cljs new file mode 100644 index 0000000000..0e39fb15f4 --- /dev/null +++ b/src/status_im/notifications/events.cljs @@ -0,0 +1,44 @@ +(ns status-im.notifications.events + (:require [re-frame.core :as re-frame] + [status-im.notifications.core :as notifications] + [status-im.ui.screens.accounts.models :as accounts] + [status-im.utils.handlers :as handlers] + [status-im.utils.platform :as platform])) + +(re-frame/reg-fx + :notifications/display-notification + notifications/display-notification) + +(re-frame/reg-fx + :notifications/handle-initial-push-notification + notifications/handle-initial-push-notification) + +(re-frame/reg-fx + :notifications/get-fcm-token + (fn [_] + (when platform/mobile? + (notifications/get-fcm-token)))) + +(re-frame/reg-fx + :notifications/request-notifications + (fn [_] + (notifications/request-permissions))) + +(handlers/register-handler-fx + :notifications/handle-push-notification + notifications/handle-push-notification) + +(handlers/register-handler-db + :notifications/update-fcm-token + (fn [db [_ fcm-token]] + (assoc-in db [:notifications :fcm-token] fcm-token))) + +(handlers/register-handler-fx + :notifications/request-notifications-granted + (fn [cofx _] + (accounts/show-mainnet-is-default-alert cofx))) + +(handlers/register-handler-fx + :notifications/request-notifications-denied + (fn [cofx _] + (accounts/show-mainnet-is-default-alert cofx))) diff --git a/src/status_im/protocol/handlers.cljs b/src/status_im/protocol/handlers.cljs index 551c256e9e..8e72e85e8c 100644 --- a/src/status_im/protocol/handlers.cljs +++ b/src/status_im/protocol/handlers.cljs @@ -1,34 +1,10 @@ (ns status-im.protocol.handlers (:require [re-frame.core :as re-frame] [status-im.models.protocol :as models] - [status-im.utils.ethereum.core :as ethereum] [status-im.utils.handlers :as handlers] - [status-im.utils.utils :as utils] - [status-im.utils.web3-provider :as web3-provider])) - -;;;; COFX -(re-frame/reg-cofx - :protocol/get-web3 - (fn [cofx _] - (let [web3 (web3-provider/make-internal-web3)] - (assoc cofx :web3 web3)))) - -;;; FX -(re-frame/reg-fx - :protocol/web3-get-syncing - (fn [web3] - (when web3 - (.getSyncing - (.-eth web3) - (fn [error sync] - (re-frame/dispatch [:update-sync-state error sync])))))) - -(re-frame/reg-fx - :protocol/set-default-account - (fn [[web3 address]] - (set! (.-defaultAccount (.-eth web3)) - (ethereum/normalized-address address)))) + [status-im.utils.utils :as utils])) +;;;; FX (re-frame/reg-fx :protocol/assert-correct-network (fn [{:keys [web3 network-id]}] diff --git a/src/status_im/signals/core.cljs b/src/status_im/signals/core.cljs new file mode 100644 index 0000000000..afb4a00d65 --- /dev/null +++ b/src/status_im/signals/core.cljs @@ -0,0 +1,28 @@ +(ns status-im.signals.core + (:require [status-im.init.core :as init] + [status-im.transport.handlers :as transport.handlers] + [status-im.transport.inbox :as inbox] + [status-im.utils.handlers-macro :as handlers-macro] + [status-im.utils.types :as types] + [taoensso.timbre :as log])) + +(defn summary [peers-summary {:keys [db] :as cofx}] + (let [previous-summary (:peers-summary db) + peers-count (count peers-summary)] + (handlers-macro/merge-fx cofx + {:db (assoc db + :peers-summary peers-summary + :peers-count peers-count)} + (transport.handlers/resend-contact-messages previous-summary) + (inbox/peers-summary-change-fx previous-summary)))) + +(defn process [event-str cofx] + (let [{:keys [type event]} (types/json->clj event-str)] + (case type + "node.started" (init/status-node-started cofx) + "node.stopped" (init/status-node-stopped cofx) + "module.initialized" (init/status-module-initialized cofx) + "envelope.sent" (transport.handlers/update-envelope-status (:hash event) :sent cofx) + "envelope.expired" (transport.handlers/update-envelope-status (:hash event) :sent cofx) + "discovery.summary" (summary event cofx) + (log/debug "Event " type " not handled")))) diff --git a/src/status_im/signals/events.cljs b/src/status_im/signals/events.cljs new file mode 100644 index 0000000000..68880b9844 --- /dev/null +++ b/src/status_im/signals/events.cljs @@ -0,0 +1,12 @@ +(ns status-im.signals.events + (:require [status-im.signals.core :as signals] + [status-im.utils.handlers :as handlers] + [status-im.utils.instabug :as instabug] + [taoensso.timbre :as log])) + +(handlers/register-handler-fx + :signal-event + (fn [cofx [_ event-str]] + (log/debug :event-str event-str) + (instabug/log (str "Signal event: " event-str)) + (signals/process event-str cofx))) diff --git a/src/status_im/transport/handlers.cljs b/src/status_im/transport/handlers.cljs index 37c3e7822c..066f622b15 100644 --- a/src/status_im/transport/handlers.cljs +++ b/src/status_im/transport/handlers.cljs @@ -220,25 +220,23 @@ :data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id :chat updated-chat})]})) -(handlers/register-handler-fx - :signals/envelope-status - [re-frame/trim-v] - (fn [{:keys [db] :as cofx} [envelope-hash status]] - (let [{:keys [chat-id message-type message-id]} - (get-in db [:transport/message-envelopes envelope-hash])] - (case message-type - :contact-message - (when (= :sent status) - (handlers-macro/merge-fx cofx - (remove-hash envelope-hash) - (update-resend-contact-message chat-id))) +(defn update-envelope-status + [envelope-hash status {:keys [db] :as cofx}] + (let [{:keys [chat-id message-type message-id]} + (get-in db [:transport/message-envelopes envelope-hash])] + (case message-type + :contact-message + (when (= :sent status) + (handlers-macro/merge-fx cofx + (remove-hash envelope-hash) + (update-resend-contact-message chat-id))) - (when-let [message (get-in db [:chats chat-id :messages message-id])] - (let [{:keys [fcm-token]} (get-in db [:contacts/contacts chat-id])] - (handlers-macro/merge-fx cofx - (remove-hash envelope-hash) - (models.message/update-message-status message status) - (models.message/send-push-notification fcm-token status)))))))) + (when-let [message (get-in db [:chats chat-id :messages message-id])] + (let [{:keys [fcm-token]} (get-in db [:contacts/contacts chat-id])] + (handlers-macro/merge-fx cofx + (remove-hash envelope-hash) + (models.message/update-message-status message status) + (models.message/send-push-notification fcm-token status))))))) (defn- own-info [db] (let [{:keys [name photo-path address]} (:account/account db) diff --git a/src/status_im/ui/screens/accounts/login/models.cljs b/src/status_im/ui/screens/accounts/login/models.cljs index d012609837..9585f9e68a 100644 --- a/src/status_im/ui/screens/accounts/login/models.cljs +++ b/src/status_im/ui/screens/accounts/login/models.cljs @@ -6,8 +6,7 @@ [status-im.native-module.core :as status] [status-im.utils.config :as config] [status-im.utils.keychain.core :as keychain] - [status-im.utils.notifications :as notifications] - [taoensso.timbre :as log] + [status-im.notifications.core :as notifications] [status-im.utils.platform :as platform] [status-im.utils.universal-links.core :as universal-links])) @@ -33,7 +32,7 @@ (then (partial change-account! address)) (catch (fn [error] ;; If all else fails we fallback to showing initial error - (re-frame/dispatch [:initialize-app "" :decryption-failed]))))) + (re-frame/dispatch [:init/initialize-app "" :decryption-failed]))))) ;;;; Handlers @@ -85,15 +84,15 @@ :network network :config config})) -(defn- wrap-with-initialize-geth-fx [db address password save-password] +(defn- wrap-with-initialize-geth [db address password save-password] (let [{:keys [network config]} (get-network-by-address db address)] - {:initialize-geth-fx config + {:init/initialize-geth config :db (assoc db :network network :node/after-start [:login-account-internal address password save-password])})) (defn start-node [address password save-password {db :db}] - (wrap-with-initialize-geth-fx + (wrap-with-initialize-geth (assoc db :node/after-stop nil) address password save-password)) @@ -112,7 +111,7 @@ db' (-> db (assoc-in [:accounts/login :processing] true)) wrap-fn (cond (not status-node-started?) - wrap-with-initialize-geth-fx + wrap-with-initialize-geth (not (restart-node? account-network network @@ -142,7 +141,7 @@ {:db (cond-> (dissoc db :accounts/login) (= view-id :create-account) (assoc-in [:accounts/create :step] :enter-name)) - :dispatch [:initialize-account address + :dispatch [:init/initialize-account address (when (not= view-id :create-account) [[:navigate-to-clean :home] (universal-links/stored-url-event cofx) diff --git a/src/status_im/ui/screens/accounts/models.cljs b/src/status_im/ui/screens/accounts/models.cljs index 22e1a73aad..136c8ec864 100644 --- a/src/status_im/ui/screens/accounts/models.cljs +++ b/src/status_im/ui/screens/accounts/models.cljs @@ -88,9 +88,9 @@ (defn account-set-name [{{:accounts/keys [create] :as db} :db :as cofx}] (handlers-macro/merge-fx cofx - {:db (assoc db :accounts/create {:show-welcome? true}) - :dispatch-n [[:navigate-to-clean :home] - [:request-notifications]]} + {:db (assoc db :accounts/create {:show-welcome? true}) + :notifications/request-notifications nil + :dispatch [:navigate-to-clean :home]} (accounts.utils/account-update {:name (:name create)}))) (defn account-set-input-text [input-key text {db :db}] diff --git a/src/status_im/ui/screens/add_new/new_chat/events.cljs b/src/status_im/ui/screens/add_new/new_chat/events.cljs index 72c577d5ab..a1da12f3e4 100644 --- a/src/status_im/ui/screens/add_new/new_chat/events.cljs +++ b/src/status_im/ui/screens/add_new/new_chat/events.cljs @@ -10,7 +10,6 @@ (re-frame/reg-fx :resolve-whisper-identity (fn [{:keys [web3 registry ens-name cb]}] - (println registry ens-name) (stateofus/text web3 registry ens-name cb))) (handlers/register-handler-fx diff --git a/src/status_im/ui/screens/events.cljs b/src/status_im/ui/screens/events.cljs index 25363f3158..822d8a27d1 100644 --- a/src/status_im/ui/screens/events.cljs +++ b/src/status_im/ui/screens/events.cljs @@ -1,6 +1,5 @@ (ns status-im.ui.screens.events (:require status-im.chat.events - [status-im.models.chat :as chat] status-im.network.events [status-im.transport.handlers :as transport.handlers] status-im.protocol.handlers @@ -10,15 +9,17 @@ status-im.ui.screens.accounts.login.events [status-im.ui.screens.accounts.login.models :as login] status-im.ui.screens.accounts.recover.events - [status-im.ui.screens.contacts.events :as contacts] [status-im.models.contacts :as models.contacts] status-im.ui.screens.add-new.new-chat.events status-im.ui.screens.group.chat-settings.events status-im.ui.screens.group.events [status-im.ui.screens.navigation :as navigation] - [status-im.utils.universal-links.core :as universal-links] [status-im.utils.dimensions :as dimensions] status-im.utils.universal-links.events + status-im.init.events + status-im.signals.events + status-im.web3.events + status-im.notifications.events status-im.ui.screens.add-new.new-chat.navigation status-im.ui.screens.network-settings.events status-im.ui.screens.profile.events @@ -29,13 +30,11 @@ status-im.ui.screens.wallet.send.events status-im.ui.screens.wallet.settings.events status-im.ui.screens.wallet.transactions.events - [status-im.models.transactions :as transactions] status-im.ui.screens.wallet.choose-recipient.events status-im.ui.screens.wallet.collectibles.cryptokitties.events status-im.ui.screens.wallet.collectibles.cryptostrikers.events status-im.ui.screens.wallet.collectibles.etheremon.events status-im.ui.screens.browser.events - [status-im.models.browser :as browser] status-im.ui.screens.offline-messaging-settings.events status-im.ui.screens.privacy-policy.events status-im.ui.screens.bootnodes-settings.events @@ -44,27 +43,14 @@ [re-frame.core :as re-frame] [status-im.native-module.core :as status] [status-im.ui.components.permissions :as permissions] - [status-im.constants :as constants] - [status-im.data-store.core :as data-store] - [status-im.data-store.realm.core :as realm] - [status-im.utils.keychain.core :as keychain] - [status-im.i18n :as i18n] - [status-im.js-dependencies :as dependencies] - [status-im.ui.components.react :as react] [status-im.transport.core :as transport] [status-im.transport.inbox :as inbox] [status-im.ui.screens.db :refer [app-db]] [status-im.utils.datetime :as time] - [status-im.utils.ethereum.core :as ethereum] [status-im.utils.random :as random] - [status-im.utils.config :as config] - [status-im.utils.notifications :as notifications] [status-im.utils.handlers :as handlers] [status-im.utils.handlers-macro :as handlers-macro] [status-im.utils.http :as http] - [status-im.utils.instabug :as instabug] - [status-im.utils.platform :as platform] - [status-im.utils.types :as types] [status-im.utils.utils :as utils] [taoensso.timbre :as log])) @@ -104,69 +90,16 @@ (doseq [call calls] (http-get call)))) -(re-frame/reg-fx - :fetch-web3-node-version - (fn [web3 _] - (.. web3 -version (getNode (fn [err resp] - (when-not err - (re-frame/dispatch [:fetch-web3-node-version-callback resp]))))) - nil)) - -;; Try to decrypt the database, move on if successful otherwise go back to -;; initial state -(re-frame/reg-fx - ::init-store - (fn [encryption-key] - (.. (data-store/init encryption-key) - (then #(re-frame/dispatch [:after-decryption])) - (catch (fn [error] - (log/warn "Could not decrypt database" error) - (re-frame/dispatch [:initialize-app encryption-key :decryption-failed])))))) - -(re-frame/reg-fx - :initialize-geth-fx - (fn [config] - (status/start-node (types/clj->json config) config/fleet))) - -(re-frame/reg-fx - ::status-module-initialized-fx - (fn [_] - (status/module-initialized!))) - (re-frame/reg-fx :request-permissions-fx (fn [options] (permissions/request-permissions options))) (re-frame/reg-fx - ::request-notifications-fx - (fn [_] - (notifications/request-permissions))) - -(re-frame/reg-fx - ::testfairy-alert - (fn [_] - (when config/testfairy-enabled? - (utils/show-popup - (i18n/label :testfairy-title) - (i18n/label :testfairy-message))))) - -(re-frame/reg-fx - ::init-device-UUID - (fn [] - (status/get-device-UUID #(re-frame/dispatch [:set :device-UUID %])))) - -(re-frame/reg-fx - ::listen-to-window-dimensions-change + :ui/listen-to-window-dimensions-change (fn [] (dimensions/add-event-listener))) -(re-frame/reg-fx - ::get-fcm-token-fx - (fn [_] - (when platform/mobile? - (notifications/get-fcm-token)))) - (re-frame/reg-fx :show-error (fn [content] @@ -199,262 +132,37 @@ (fn [db [_ path v]] (assoc-in db path v))) -(defn- reset-keychain [] - (.. (keychain/reset) - (then - #(re-frame/dispatch [:initialize-keychain])))) - -(defn- handle-reset-data [] - (.. (realm/delete-realms) - (then reset-keychain) - (catch reset-keychain))) - -(defn handle-invalid-key-parameters [encryption-key] - {:title (i18n/label :invalid-key-title) - :content (i18n/label :invalid-key-content) - :confirm-button-text (i18n/label :invalid-key-confirm) - ;; On cancel we initialize the app with the invalid key, to allow the user - ;; to recover the seed phrase - :on-cancel #(do - (log/warn "initializing app with invalid key") - (re-frame/dispatch [:initialize-app encryption-key])) - :on-accept handle-reset-data}) - -(defn handle-decryption-failed-parameters [encryption-key] - {:title (i18n/label :decryption-failed-title) - :content (i18n/label :decryption-failed-content) - :confirm-button-text (i18n/label :decryption-failed-confirm) - ;; On cancel we initialize the app with the same key, in case the error was - ;; not related/fs error - :on-cancel #(do - (log/warn "initializing app with same key after decryption failed") - (re-frame/dispatch [:initialize-app encryption-key])) - :on-accept handle-reset-data}) - -(defn initialize-views [cofx] - (let [{{:accounts/keys [accounts] :as db} :db} cofx - {:keys [address photo-path name]} (first (sort-by :last-sign-in > (vals accounts))) - default-fx {:handle-initial-push-notification-fx db}] - (if (nil? address) - (handlers-macro/merge-fx cofx - default-fx - (navigation/navigate-to-clean :intro)) - (handlers-macro/merge-fx cofx - default-fx - (login/open-login address photo-path name))))) - -(defn initialize-db - "Initialize db to the initial state" - [{{:universal-links/keys [url] - :push-notifications/keys [initial?] - :keys [status-module-initialized? status-node-started? - network-status network peers-count peers-summary device-UUID] - :or {network (get app-db :network)}} :db}] - {:db (assoc app-db - :contacts/contacts {} - :network-status network-status - :peers-count (or peers-count 0) - :peers-summary (or peers-summary []) - :status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?) - :status-node-started? status-node-started? - :network network - :universal-links/url url - :push-notifications/initial? initial? - :device-UUID device-UUID)}) - -;; Entrypoint, fetches the key from the keychain and initialize the app -(handlers/register-handler-fx - :initialize-keychain - (fn [_ _] - {:get-encryption-key [:initialize-app]})) - -;; Check the key is valid, shows options if not, otherwise continues loading -;; the database -(handlers/register-handler-fx - :initialize-app - (fn [cofx [_ encryption-key error]] - (cond - (= :invalid-key error) - {:show-confirmation (handle-invalid-key-parameters encryption-key)} - - (= :decryption-failed error) - {:show-confirmation (handle-decryption-failed-parameters encryption-key)} - - :else - (handlers-macro/merge-fx cofx - {::init-device-UUID nil - ::init-store encryption-key - ::listen-to-window-dimensions-change nil - ::testfairy-alert nil} - (initialize-db))))) - -;; DB has been decrypted, load accounts, initialize geth, etc -(handlers/register-handler-fx - :after-decryption - [(re-frame/inject-cofx :data-store/get-all-accounts)] - (fn [cofx _] - (handlers-macro/merge-fx cofx - {:dispatch-n - [[:listen-to-network-status] - [:initialize-geth]]} - (accounts.models/load-accounts) - (initialize-views)))) +(defn logout + [{:keys [db] :as cofx}] + (let [{:transport/keys [chats]} db] + (handlers-macro/merge-fx cofx + {:dispatch [:init/initialize-keychain] + :clear-user-password [(get-in db [:account/account :address])]} + (navigation/navigate-to-clean nil) + (transport/stop-whisper)))) (handlers/register-handler-fx :logout - (fn [{:keys [db] :as cofx} _] - (let [{:transport/keys [chats]} db] - (handlers-macro/merge-fx cofx - {:dispatch [:initialize-keychain] - :clear-user-password [(get-in db [:account/account :address])]} - (navigation/navigate-to-clean nil) - (transport/stop-whisper))))) + (fn [cofx _] + (logout cofx))) -(defn initialize-account-db [address {:keys [db web3]}] - (let [{:keys [accounts/accounts accounts/create contacts/contacts networks/networks - network network-status peers-count peers-summary view-id navigation-stack - status-module-initialized? status-node-started? device-UUID - push-notifications/initial? semaphores] - :or {network (get app-db :network)}} db - console-contact (get contacts constants/console-chat-id) - current-account (accounts address) - account-network-id (get current-account :network network) - account-network (get-in current-account [:networks account-network-id])] - {:db (cond-> (assoc app-db - :current-public-key (:public-key current-account) - :view-id view-id - :navigation-stack navigation-stack - :status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?) - :status-node-started? status-node-started? - :accounts/create create - :networks/networks networks - :account/account current-account - :network-status network-status - :network network - :chain (ethereum/network->chain-name account-network) - :push-notifications/initial? initial? - :peers-summary peers-summary - :peers-count peers-count - :device-UUID device-UUID - :semaphores semaphores - :web3 web3) - console-contact - (assoc :contacts/contacts {constants/console-chat-id console-contact}))})) - -(handlers/register-handler-fx - :initialize-account - [(re-frame/inject-cofx :protocol/get-web3) - (re-frame/inject-cofx :get-default-contacts) - (re-frame/inject-cofx :get-default-dapps) - (re-frame/inject-cofx :data-store/all-chats) - (re-frame/inject-cofx :data-store/get-messages) - (re-frame/inject-cofx :data-store/get-user-statuses) - (re-frame/inject-cofx :data-store/unviewed-messages) - (re-frame/inject-cofx :data-store/message-ids) - (re-frame/inject-cofx :data-store/get-unanswered-requests) - (re-frame/inject-cofx :data-store/get-local-storage-data) - (re-frame/inject-cofx :data-store/get-all-contacts) - (re-frame/inject-cofx :data-store/get-all-mailservers) - (re-frame/inject-cofx :data-store/transport) - (re-frame/inject-cofx :data-store/all-browsers) - (re-frame/inject-cofx :data-store/all-dapp-permissions)] - (fn [{:keys [web3] :as cofx} [_ address events-after]] - (handlers-macro/merge-fx cofx - {:protocol/set-default-account [web3 address] - :fetch-web3-node-version web3 - ::get-fcm-token-fx nil - :dispatch-n (or events-after [])} - (initialize-account-db address) - (models.protocol/initialize-protocol address) - (models.contacts/load-contacts) - (chat/initialize-chats) - (chat/process-pending-messages) - (browser/initialize-browsers) - (browser/initialize-dapp-permissions) - (models.wallet/update-wallet) - (transactions/run-update) - (transactions/start-sync) - (models.account/update-sign-in-time)))) - -(handlers/register-handler-fx - :initialize-geth - (fn [{db :db} _] - (when-not (:status-node-started? db) - (let [default-networks (:networks/networks db) - default-network (:network db)] - {:initialize-geth-fx (get-in default-networks [default-network :config])})))) - -(handlers/register-handler-fx - :fetch-web3-node-version-callback - (fn [{:keys [db]} [_ resp]] - (when-let [git-commit (nth (re-find #"-([0-9a-f]{7,})/" resp) 1)] - {:db (assoc db :web3-node-version git-commit)}))) - -(handlers/register-handler-fx - :discovery/summary - (fn [{:keys [db] :as cofx} [_ peers-summary]] - (let [previous-summary (:peers-summary db) - peers-count (count peers-summary)] - (handlers-macro/merge-fx cofx - {:db (assoc db - :peers-summary peers-summary - :peers-count peers-count)} - (transport.handlers/resend-contact-messages previous-summary) - (inbox/peers-summary-change-fx previous-summary))))) - -(handlers/register-handler-fx - :signal-event - (fn [_ [_ event-str]] - (log/debug :event-str event-str) - (instabug/log (str "Signal event: " event-str)) - (let [{:keys [type event]} (types/json->clj event-str) - to-dispatch (case type - "node.started" [:status-node-started] - "node.stopped" [:status-node-stopped] - "module.initialized" [:status-module-initialized] - "envelope.sent" [:signals/envelope-status (:hash event) :sent] - "envelope.expired" [:signals/envelope-status (:hash event) :not-sent] - "discovery.summary" [:discovery/summary event] - (log/debug "Event " type " not handled"))] - (when to-dispatch - {:dispatch to-dispatch})))) - -(handlers/register-handler-fx - :status-module-initialized - (fn [{:keys [db]} _] - {:db (assoc db :status-module-initialized? true) - ::status-module-initialized-fx nil})) - -(handlers/register-handler-fx - :status-node-started - (fn [{{:node/keys [after-start] :as db} :db} _] - (merge {:db (assoc db :status-node-started? true)} - (when after-start {:dispatch-n [after-start]})))) - -(handlers/register-handler-fx - :status-node-stopped - (fn [{{:node/keys [after-stop]} :db} _] - (when after-stop {:dispatch-n [after-stop]}))) +(defn app-state-change [state {:keys [db] :as cofx}] + (let [app-coming-from-background? (= state "active")] + (handlers-macro/merge-fx cofx + {::app-state-change-fx state + :db (assoc db :app-state state)} + (inbox/request-messages app-coming-from-background?)))) (handlers/register-handler-fx :app-state-change - (fn [{:keys [db] :as cofx} [_ state]] - (let [app-coming-from-background? (= state "active")] - (handlers-macro/merge-fx cofx - {::app-state-change-fx state - :db (assoc db :app-state state)} - (inbox/request-messages app-coming-from-background?))))) + (fn [cofx [_ state]] + (app-state-change state cofx))) (handlers/register-handler-fx :request-permissions (fn [_ [_ options]] {:request-permissions-fx options})) -(handlers/register-handler-fx - :request-notifications - (fn [_ _] - {::request-notifications-fx {}})) - (handlers/register-handler-db :set-swipe-position [re-frame/trim-v] diff --git a/src/status_im/utils/keychain/events.cljs b/src/status_im/utils/keychain/events.cljs index 78b67a0478..df44d1a844 100644 --- a/src/status_im/utils/keychain/events.cljs +++ b/src/status_im/utils/keychain/events.cljs @@ -12,7 +12,7 @@ (or error :invalid-key)])))) (re-frame/reg-fx - :get-encryption-key + :keychain/get-encryption-key (fn [event] (when platform/desktop? (keychain/set-username)) (.. (keychain/get-encryption-key) diff --git a/src/status_im/utils/web3_provider.cljs b/src/status_im/utils/web3_provider.cljs deleted file mode 100644 index d330c06c2a..0000000000 --- a/src/status_im/utils/web3_provider.cljs +++ /dev/null @@ -1,17 +0,0 @@ -(ns status-im.utils.web3-provider - (:require [taoensso.timbre :as log] - [status-im.native-module.core :as status] - [status-im.js-dependencies :as dependencies])) - -;; This Web3 object will allow access to private RPC calls -;; It should be only used for internal application needs and never provided to any -;; 3rd parties (DApps, etc) -(defn make-internal-web3 [] - (dependencies/Web3. - #js {:sendAsync (fn [payload callback] - (status/call-private-rpc - (.stringify js/JSON payload) - (fn [response] - (if (= "" response) - (log/warn :web3-response-error) - (callback nil (.parse js/JSON response))))))})) diff --git a/src/status_im/web3/core.cljs b/src/status_im/web3/core.cljs new file mode 100644 index 0000000000..2312b8317b --- /dev/null +++ b/src/status_im/web3/core.cljs @@ -0,0 +1,53 @@ +(ns status-im.web3.core + (:require [re-frame.core :as re-frame] + [status-im.js-dependencies :as dependencies] + + [status-im.utils.ethereum.core :as ethereum] + + [taoensso.timbre :as log] + [status-im.native-module.core :as status])) + +(defn make-internal-web3 + "This Web3 object will allow access to private RPC calls + It should be only used for internal application needs and never provided to any + 3rd parties (DApps, etc)" + [] + (dependencies/Web3. + #js {:sendAsync (fn [payload callback] + (status/call-private-rpc + (.stringify js/JSON payload) + (fn [response] + (if (= "" response) + (log/warn :web3-response-error) + (callback nil (.parse js/JSON response))))))})) + +(defn get-web3 [cofx] + (let [web3 (make-internal-web3)] + (assoc cofx :web3 web3))) + +;;; FX +(defn get-syncing [web3] + (when web3 + (.getSyncing + (.-eth web3) + (fn [error sync] + (re-frame/dispatch [:update-sync-state error sync]))))) + +(defn set-default-account + [web3 address] + (set! (.-defaultAccount (.-eth web3)) + (ethereum/normalized-address address))) + +(defn fetch-node-version + [web3] + (.. web3 + -version + (getNode + (fn [err resp] + (when-not err + (re-frame/dispatch [:web3/fetch-node-version-callback resp])))))) + +(defn fetch-node-version-callback + [resp {:keys [db]}] + (when-let [git-commit (nth (re-find #"-([0-9a-f]{7,})/" resp) 1)] + {:db (assoc db :web3-node-version git-commit)})) diff --git a/src/status_im/web3/events.cljs b/src/status_im/web3/events.cljs new file mode 100644 index 0000000000..7633baddc3 --- /dev/null +++ b/src/status_im/web3/events.cljs @@ -0,0 +1,29 @@ +(ns status-im.web3.events + (:require [re-frame.core :as re-frame] + [status-im.utils.handlers :as handlers] + [status-im.web3.core :as web3])) + +;;;; COFX +(re-frame/reg-cofx + :web3/get-web3 + web3/get-web3) + +;;;; FX +(re-frame/reg-fx + :web3/get-syncing + web3/get-syncing) + +(re-frame/reg-fx + :web3/set-default-account + (fn [[web3 address]] + (web3/set-default-account web3 address))) + +(re-frame/reg-fx + :web3/fetch-node-version + web3/fetch-node-version) + +;;;; Events +(handlers/register-handler-fx + :web3/fetch-node-version-callback + (fn [cofx [_ resp]] + (web3/fetch-node-version-callback resp cofx))) diff --git a/test/cljs/status_im/test/browser/events.cljs b/test/cljs/status_im/test/browser/events.cljs index da03e943af..2ca3c4a7ba 100644 --- a/test/cljs/status_im/test/browser/events.cljs +++ b/test/cljs/status_im/test/browser/events.cljs @@ -1,7 +1,7 @@ (ns status-im.test.browser.events (:require [cljs.test :refer-macros [deftest is testing]] [day8.re-frame.test :refer-macros [run-test-sync]] - [status-im.ui.screens.events :as events] + [status-im.init.core :as init] status-im.ui.screens.db status-im.ui.screens.subs [re-frame.core :as re-frame] @@ -13,7 +13,7 @@ (defn test-fixtures [] - (re-frame/reg-fx ::events/init-store #()) + (re-frame/reg-fx :init/init-store #()) (re-frame/reg-fx :browse #()) (re-frame/reg-fx :data-store/tx #()) @@ -43,7 +43,7 @@ :initialize-test (fn [cofx [_]] (handlers-macro/merge-fx cofx - (events/initialize-db) + (init/initialize-db) (browser/initialize-browsers) (browser/initialize-dapp-permissions))))) @@ -54,15 +54,13 @@ (test-fixtures) (re-frame/dispatch [:initialize-test]) - (println :app-db @re-frame.db/app-db) + (let [browsers (re-frame/subscribe [:browsers]) dapp1-url "cryptokitties.co" dapp2-url "http://test2.com"] (testing "open and remove dapps" - (println :browsers @browsers) - (is (do (println :browser @browsers) - (zero? (count @browsers)))) + (is (zero? (count @browsers))) (re-frame/dispatch [:open-url-in-browser dapp1-url]) diff --git a/test/cljs/status_im/test/init/core.cljs b/test/cljs/status_im/test/init/core.cljs new file mode 100644 index 0000000000..7778e7fbc8 --- /dev/null +++ b/test/cljs/status_im/test/init/core.cljs @@ -0,0 +1,9 @@ +(ns status-im.test.init.core + (:require [cljs.test :refer-macros [deftest is testing]] + [status-im.init.core :as init])) + +(deftest initialize-db + (testing "it preserves universal-links/url" + (is (= "some-url" (get-in (init/initialize-db {:db + {:universal-links/url "some-url"}}) + [:db :universal-links/url]))))) diff --git a/test/cljs/status_im/test/utils/notifications.cljs b/test/cljs/status_im/test/notifications/core.cljs similarity index 97% rename from test/cljs/status_im/test/utils/notifications.cljs rename to test/cljs/status_im/test/notifications/core.cljs index bdbcbcc5eb..478b6b52f9 100644 --- a/test/cljs/status_im/test/utils/notifications.cljs +++ b/test/cljs/status_im/test/notifications/core.cljs @@ -1,6 +1,6 @@ -(ns status-im.test.utils.notifications +(ns status-im.test.notifications.core (:require [cljs.test :refer-macros [deftest is testing]] - [status-im.utils.notifications :as notifications])) + [status-im.notifications.core :as notifications])) (deftest test-handle-push-notification (testing "user's signed in" diff --git a/test/cljs/status_im/test/runner.cljs b/test/cljs/status_im/test/runner.cljs index e8bb9191aa..5fdb07698f 100644 --- a/test/cljs/status_im/test/runner.cljs +++ b/test/cljs/status_im/test/runner.cljs @@ -47,7 +47,7 @@ [status-im.test.utils.keychain.core] [status-im.test.utils.universal-links.core] [status-im.test.utils.http] - [status-im.test.ui.screens.events] + [status-im.test.init.core] [status-im.test.ui.screens.accounts.login.models] [status-im.test.ui.screens.accounts.recover.models] [status-im.test.ui.screens.wallet.db])) @@ -69,6 +69,7 @@ 'status-im.test.contacts.events 'status-im.test.contacts.subs 'status-im.test.profile.events + 'status-im.test.init.core 'status-im.test.data-store.realm.core 'status-im.test.models.mailserver 'status-im.test.models.bootnode @@ -107,7 +108,6 @@ 'status-im.test.utils.keychain.core 'status-im.test.utils.universal-links.core 'status-im.test.utils.http - 'status-im.test.ui.screens.events 'status-im.test.ui.screens.accounts.login.models 'status-im.test.ui.screens.accounts.recover.models 'status-im.test.ui.screens.wallet.db diff --git a/test/cljs/status_im/test/ui/screens/accounts/login/models.cljs b/test/cljs/status_im/test/ui/screens/accounts/login/models.cljs index c60d88a38f..052d22c716 100644 --- a/test/cljs/status_im/test/ui/screens/accounts/login/models.cljs +++ b/test/cljs/status_im/test/ui/screens/accounts/login/models.cljs @@ -28,105 +28,108 @@ (testing "save password: status-go not started" (let [actual (models/login-account "testnet" "password" true initial-db)] (testing "it starts status-node if it has not started" - (is (= {:NetworkId 3} (:initialize-geth-fx actual)))) + (is (= {:NetworkId 3} + (:init/initialize-geth + actual)))) (testing "it logins the user after the node started" (is (= [:login-account-internal "testnet" "password" true] (get-in actual [:db :node/after-start])))))) + (testing "status-go has started & the user is on mainnet" (let [db (assoc-in initial-db [:db :status-node-started?] true) actual (models/login-account "mainnet" "password" false db)] (testing "it does not start status-node if it has already started" - (is (not (:initialize-geth-fx actual)))) + (is (not (:init/initialize-geth actual)))) (testing "it logs in the user" - (is (= ["mainnet" "password" false] (:login actual)))))) + (is (= ["mainnet" "password" false] (:login actual))))))) - (testing "the user has selected a different network" - (testing "status-go has started" - (let [db (assoc-in initial-db [:db :status-node-started?] true) - actual (models/login-account "testnet" "password" false db)] - (testing "it dispatches start-node" - (is (get-in actual [:db :node/after-stop] [:start-node "testnet" "password" true]))) - (testing "it stops status-node" - (is (contains? actual :stop-node)))))) + (testing "the user has selected a different network" + (testing "status-go has started" + (let [db (assoc-in initial-db [:db :status-node-started?] true) + actual (models/login-account "testnet" "password" false db)] + (testing "it dispatches start-node" + (is (get-in actual [:db :node/after-stop] [:start-node "testnet" "password" true]))) + (testing "it stops status-node" + (is (contains? actual :stop-node)))))) + + (testing "status-go has not started" + (let [actual (models/login-account "testnet" "password" false initial-db)] + (testing "it starts status-node" + (is (= {:NetworkId 3} (:init/initialize-geth actual)))) + (testing "it logins the user after the node started" + (is (= [:login-account-internal "testnet" "password" false] (get-in actual [:db :node/after-start])))))) + + (testing "status-go has started & the user is on mainnet" + (let [db (assoc-in initial-db [:db :status-node-started?] true) + actual (models/login-account "mainnet" "password" false db)] + (testing "it does not start status-node if it has already started" + (is (not (:init/initialize-geth actual)))) + (testing "it logs in the user" + (is (= ["mainnet" "password" false] (:login actual)))))) + + (testing "the user has selected a different network" + (testing "status-go has started" + (let [db (assoc-in initial-db [:db :status-node-started?] true) + actual (models/login-account "testnet" "password" false db)] + (testing "it dispatches start-node" + (is (get-in actual [:db :node/after-stop] [:start-node "testnet" "password" false]))) + (testing "it stops status-node" + (is (contains? actual :stop-node))))) (testing "status-go has not started" (let [actual (models/login-account "testnet" "password" false initial-db)] - (testing "it starts status-node if it has not started" - (is (= {:NetworkId 3} (:initialize-geth-fx actual)))) + (testing "it starts status-node" + (is (= {:NetworkId 3} (:init/initialize-geth actual)))) (testing "it logins the user after the node started" - (is (= [:login-account-internal "testnet" "password" false] (get-in actual [:db :node/after-start])))))) + (is (= [:login-account-internal "testnet" "password" false] (get-in actual [:db :node/after-start]))))))) - (testing "status-go has started & the user is on mainnet" - (let [db (assoc-in initial-db [:db :status-node-started?] true) - actual (models/login-account "mainnet" "password" false db)] - (testing "it does not start status-node if it has already started" - (is (not (:initialize-geth-fx actual)))) - (testing "it logs in the user" - (is (= ["mainnet" "password" false] (:login actual)))))) + (testing "custom bootnodes" + (let [custom-bootnodes {"a" {:id "a" + :name "name-a" + :address "address-a"} + "b" {:id "b" + :name "name-b" + :address "address-b"}} + bootnodes-db (assoc-in + initial-db + [:db :accounts/accounts "mainnet" :bootnodes] + {"mainnet_rpc" custom-bootnodes})] - (testing "the user has selected a different network" - (testing "status-go has started" - (let [db (assoc-in initial-db [:db :status-node-started?] true) - actual (models/login-account "testnet" "password" false db)] - (testing "it dispatches start-node" - (is (get-in actual [:db :node/after-stop] [:start-node "testnet" "password" false]))) - (testing "it stops status-node" - (is (contains? actual :stop-node))))) - - (testing "status-go has not started" - (let [actual (models/login-account "testnet" "password" false initial-db)] - (testing "it starts status-node" - (is (= {:NetworkId 3} (:initialize-geth-fx actual)))) - (testing "it logins the user after the node started" - (is (= [:login-account-internal "testnet" "password" false] (get-in actual [:db :node/after-start]))))))) - - (testing "custom bootnodes" - (let [custom-bootnodes {"a" {:id "a" - :name "name-a" - :address "address-a"} - "b" {:id "b" - :name "name-b" - :address "address-b"}} - bootnodes-db (assoc-in - initial-db - [:db :accounts/accounts "mainnet" :bootnodes] - {"mainnet_rpc" custom-bootnodes})] - - (testing "custom bootnodes enabled" - (let [bootnodes-enabled-db (assoc-in - bootnodes-db - [:db :accounts/accounts "mainnet" :settings] - {:bootnodes {"mainnet_rpc" true}}) - actual (models/login-account "mainnet" "password" false bootnodes-enabled-db)] - (testing "status-node has started" - (let [db (assoc-in bootnodes-enabled-db [:db :status-node-started?] true) - actual (models/login-account "mainnet" "password" false db)] - (testing "it dispatches start-node" - (is (get-in actual [:db :node/after-stop] [:start-node "testnet" "password" false]))) - (testing "it stops status-node" - (is (contains? actual :stop-node))))) - (testing "status-node has not started" - (let [actual (models/login-account "mainnet" "password" false bootnodes-enabled-db)] - (testing "it adds bootnodes to the config" - (is (= {:ClusterConfig {:Enabled true - :BootNodes ["address-a" "address-b"]} - :NetworkId 1} (:initialize-geth-fx actual)))) - (testing "it logins the user after the node started" - (is (= [:login-account-internal "mainnet" "password" false] (get-in actual [:db :node/after-start])))))))) - - (testing "custom bootnodes not enabled" + (testing "custom bootnodes enabled" + (let [bootnodes-enabled-db (assoc-in + bootnodes-db + [:db :accounts/accounts "mainnet" :settings] + {:bootnodes {"mainnet_rpc" true}}) + actual (models/login-account "mainnet" "password" false bootnodes-enabled-db)] (testing "status-node has started" - (let [db (assoc-in bootnodes-db [:db :status-node-started?] true) + (let [db (assoc-in bootnodes-enabled-db [:db :status-node-started?] true) actual (models/login-account "mainnet" "password" false db)] - (testing "it does not start status-node if it has already started" - (is (not (:initialize-geth-fx actual)))) - (testing "it logs in the user" - (is (= ["mainnet" "password" false] (:login actual)))))) + (testing "it dispatches start-node" + (is (get-in actual [:db :node/after-stop] [:start-node "testnet" "password" false]))) + (testing "it stops status-node" + (is (contains? actual :stop-node))))) (testing "status-node has not started" - (let [actual (models/login-account "mainnet" "password" false bootnodes-db)] - (testing "it starts status-node without custom bootnodes" - (is (= {:NetworkId 1} (:initialize-geth-fx actual)))) + (let [actual (models/login-account "mainnet" "password" false bootnodes-enabled-db)] + (testing "it adds bootnodes to the config" + (is (= {:ClusterConfig {:Enabled true + :BootNodes ["address-a" "address-b"]} + :NetworkId 1} (:init/initialize-geth actual)))) (testing "it logins the user after the node started" - (is (= [:login-account-internal "mainnet" "password" false] (get-in actual [:db :node/after-start])))))))))))) + (is (= [:login-account-internal "mainnet" "password" false] (get-in actual [:db :node/after-start])))))))) + + (testing "custom bootnodes not enabled" + (testing "status-node has started" + (let [db (assoc-in bootnodes-db [:db :status-node-started?] true) + actual (models/login-account "mainnet" "password" false db)] + (testing "it does not start status-node if it has already started" + (is (not (:init/initialize-geth actual)))) + (testing "it logs in the user" + (is (= ["mainnet" "password" false] (:login actual)))))) + (testing "status-node has not started" + (let [actual (models/login-account "mainnet" "password" false bootnodes-db)] + (testing "it starts status-node without custom bootnodes" + (is (= {:NetworkId 1} (:init/initialize-geth actual)))) + (testing "it logins the user after the node started" + (is (= [:login-account-internal "mainnet" "password" false] (get-in actual [:db :node/after-start]))))))))))) (deftest restart-node? (testing "custom bootnodes is toggled off" diff --git a/test/cljs/status_im/test/ui/screens/events.cljs b/test/cljs/status_im/test/ui/screens/events.cljs deleted file mode 100644 index fb65c11805..0000000000 --- a/test/cljs/status_im/test/ui/screens/events.cljs +++ /dev/null @@ -1,9 +0,0 @@ -(ns status-im.test.ui.screens.events - (:require [cljs.test :refer-macros [deftest is testing]] - [status-im.ui.screens.events :as events])) - -(deftest initialize-db - (testing "it preserves universal-links/url" - (is (= "some-url" (get-in (events/initialize-db {:db - {:universal-links/url "some-url"}}) - [:db :universal-links/url])))))