diff --git a/Makefile b/Makefile index ef3bc120d1..dffd5f91e9 100644 --- a/Makefile +++ b/Makefile @@ -128,20 +128,11 @@ geth-connect: ##@other Connect to Geth on the device adb forward tcp:8545 tcp:8545 build/bin/geth attach http://localhost:8545 -android-ports-avd: ##@other Add reverse proxy to Android Device/Simulator +android-ports: ##@other Add proxies to Android Device/Simulator adb -e reverse tcp:8081 tcp:8081 adb -e reverse tcp:3449 tcp:3449 adb -e reverse tcp:4567 tcp:4567 - -android-ports-genymotion: ##@other Add reverse proxy to Android Device/Simulator - adb -e reverse tcp:8081 tcp:8081 - adb -e reverse tcp:3449 tcp:3449 - adb -e reverse tcp:4567 tcp:4567 - -android-ports-real: ##@other Add reverse proxy to Android Device/Simulator - adb -d reverse tcp:8081 tcp:8081 - adb -d reverse tcp:3449 tcp:3449 - adb -d reverse tcp:4567 tcp:4567 + adb -e forward tcp:5561 tcp:5561 startdev-%: diff --git a/mobile_files/package.json b/mobile_files/package.json index c5658a7522..1e46511ec1 100644 --- a/mobile_files/package.json +++ b/mobile_files/package.json @@ -41,7 +41,7 @@ "react-native-fetch-polyfill": "1.1.2", "react-native-firebase": "4.2.0", "react-native-fs": "2.8.1", - "react-native-http-bridge": "https://github.com/status-im/react-native-http-bridge.git", + "react-native-http-bridge": "0.5.2", "react-native-i18n": "2.0.9", "react-native-image-crop-picker": "0.18.1", "react-native-image-resizer": "1.0.0", diff --git a/src/status_im/dev_server/core.cljs b/src/status_im/dev_server/core.cljs new file mode 100644 index 0000000000..7dad137d7c --- /dev/null +++ b/src/status_im/dev_server/core.cljs @@ -0,0 +1,35 @@ +(ns status-im.dev-server.core + (:require [status-im.ui.components.react :as react] + [status-im.utils.platform :as platform] + [status-im.utils.types :as types] + [taoensso.timbre :as log] + [re-frame.core :as re-frame])) + +(defonce port 5561) +(defonce server-name (if platform/ios? + "Status iOS" + "Status Android")) + +(defn respond! [status-code data] + (.respond react/http-bridge + status-code + "application/json" + (types/clj->json data))) + +(defn start! [] + (.start react/http-bridge + port + server-name + (fn [req] + (try + (let [{:keys [url type postData]} (js->clj req :keywordize-keys true) + data (if (string? postData) + (-> (.parse js/JSON postData) + (js->clj :keywordize-keys true)) + postData)] + (re-frame/dispatch [:process-http-request url type data])) + (catch js/Error e + (log/debug "Error: " e)))))) + +(defn stop! [] + (.stop react/http-bridge)) \ No newline at end of file diff --git a/src/status_im/dev_server/events.cljs b/src/status_im/dev_server/events.cljs new file mode 100644 index 0000000000..40950d808e --- /dev/null +++ b/src/status_im/dev_server/events.cljs @@ -0,0 +1,37 @@ +(ns status-im.dev-server.events + (:require [clojure.string :as string] + [re-frame.core :as re-frame] + [status-im.dev-server.core :as dev-server.core] + [status-im.models.dev-server :as models.dev-server] + [status-im.utils.handlers :as handlers])) + +;; FX + +(re-frame/reg-fx + :dev-server/start + (fn [] + (dev-server.core/start!))) + +(re-frame/reg-fx + :dev-server/stop + (fn [] + (dev-server.core/stop!))) + +(re-frame/reg-fx + :dev-server/respond + (fn [[status-code data]] + (dev-server.core/respond! status-code data))) + +;; Handlers + +(handlers/register-handler-fx + :process-http-request + [re-frame/trim-v (re-frame/inject-cofx :random-id)] + (fn [cofx [url type data]] + (try + (models.dev-server/process-request! {:cofx cofx + :url (rest (string/split url "/")) + :type (keyword type) + :data data}) + (catch js/Error e + {:dev-server/respond [400 {:message (str "Unsupported operation: " e)}]})))) \ No newline at end of file diff --git a/src/status_im/init/core.cljs b/src/status_im/init/core.cljs index 5adddff95d..fc12a86fcd 100644 --- a/src/status_im/init/core.cljs +++ b/src/status_im/init/core.cljs @@ -7,6 +7,7 @@ [status-im.models.browser :as browser] [status-im.models.chat :as chat] [status-im.models.contacts :as models.contacts] + [status-im.models.dev-server :as models.dev-server] [status-im.models.protocol :as models.protocol] [status-im.models.transactions :as transactions] [status-im.models.wallet :as models.wallet] @@ -167,6 +168,7 @@ (initialize-account-db address) (models.protocol/initialize-protocol address) (models.contacts/load-contacts) + (models.dev-server/start-if-needed) (chat/initialize-chats) (chat/process-pending-messages) (browser/initialize-browsers) diff --git a/src/status_im/models/dev_server.cljs b/src/status_im/models/dev_server.cljs new file mode 100644 index 0000000000..f762f7a4d9 --- /dev/null +++ b/src/status_im/models/dev_server.cljs @@ -0,0 +1,62 @@ +(ns status-im.models.dev-server + (:require [status-im.models.network :as models.network] + [clojure.string :as string])) + +(defn start-if-needed + [{{:account/keys [account]} :db}] + (let [{:keys [dev-mode?]} account] + (when dev-mode? + {:dev-server/start nil}))) + +;; Specific server operations + +(defmulti process-request! (fn [{:keys [url type]}] [type (first url) (second url)])) + +(defmethod process-request! [:POST "ping" nil] + [_] + {:dev-server/respond [200 {:message "Pong!"}]}) + +(defmethod process-request! [:POST "dapp" "open"] + [{{:keys [url]} :data}] + {:dispatch [:open-url-in-browser url] + :dev-server/respond [200 {:message "URL has been opened."}]}) + +(defmethod process-request! [:POST "network" nil] + [{:keys [cofx data]}] + (let [data (->> data + (map (fn [[k v]] [k {:value v}])) + (into {}))] + (models.network/save + cofx + {:data data + :on-success (fn [network _] + {:dev-server/respond [200 {:message "Network has been added." + :network-id network}]}) + :on-failure (fn [_ _] + {:dev-server/respond [400 {:message "Please, check the validity of network information."}]})}))) + +(defmethod process-request! [:POST "network" "connect"] + [{:keys [cofx data]}] + (models.network/connect + cofx + {:network (:id data) + :on-success (fn [network _] + {:dev-server/respond [200 {:message "Network has been connected." + :network-id network}]}) + :on-failure (fn [_ _] + {:dev-server/respond [400 {:message "The network id you provided doesn't exist."}]})})) + +(defmethod process-request! [:DELETE "network" nil] + [{:keys [cofx data]}] + (models.network/delete + cofx + {:network (:id data) + :on-success (fn [network _] + {:dev-server/respond [200 {:message "Network has been deleted." + :network-id network}]}) + :on-failure (fn [_ _] + {:dev-server/respond [400 {:message "Cannot delete the provided network."}]})})) + +(defmethod process-request! :default + [{:keys [type url]}] + {:dev-server/respond [404 {:message (str "Not found (" (name type) " " (string/join "/" url) ")")}]}) \ No newline at end of file diff --git a/src/status_im/models/network.cljs b/src/status_im/models/network.cljs index 88bb6fb996..4cb01f8513 100644 --- a/src/status_im/models/network.cljs +++ b/src/status_im/models/network.cljs @@ -1,8 +1,10 @@ (ns status-im.models.network - (:require [clojure.string :as string] - [status-im.ui.screens.accounts.utils :as accounts.utils] + (:require [re-frame.core :as re-frame] + [clojure.string :as string] + [status-im.i18n :as i18n] [status-im.utils.ethereum.core :as ethereum] - [status-im.utils.handlers-macro :as handlers-macro])) + [status-im.utils.handlers-macro :as handlers-macro] + [status-im.ui.screens.accounts.utils :as accounts.utils])) (def url-regex #"https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}(\.[a-z]{2,6})?\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)") @@ -35,7 +37,7 @@ (map :error) (not-any? identity))) -(defn- new-network [{:keys [random-id]} network-name upstream-url type network-id] +(defn new-network [random-id network-name upstream-url type network-id] (let [data-dir (str "/ethereum/" (name type) "_rpc") config {:NetworkId (or (when network-id (int network-id)) (ethereum/chain-keyword->chain-id type)) @@ -55,17 +57,61 @@ (update-in [:networks/manage input-key] assoc :value value) (update-in [:networks/manage] validate-manage))}) -(defn save [{{:networks/keys [manage] :account/keys [account] :as db} :db :as cofx}] - (when (valid-manage? manage) - (let [{:keys [name url chain network-id]} manage - network (new-network cofx (:value name) (:value url) (:value chain) (:value network-id)) - new-networks (merge {(:id network) network} (:networks account))] - (handlers-macro/merge-fx cofx - {:db (dissoc db :networks/manage) - :dispatch [:navigate-back]} - (accounts.utils/account-update {:networks new-networks}))))) +(defn- action-handler + ([handler] + (handler nil nil)) + ([handler data cofx] + (when handler + (handler data cofx)))) + +(defn save + ([cofx] + (save cofx nil)) + ([{{:network/keys [manage] + :account/keys [account] :as db} :db :as cofx} + {:keys [data on-success on-failure]}] + (let [data (or data manage)] + (if (valid-manage? data) + (let [{:keys [name url chain network-id]} data + network (new-network (:random-id cofx) (:value name) (:value url) (:value chain) (:value network-id)) + new-networks (merge {(:id network) network} (:networks account))] + (handlers-macro/merge-fx cofx + {:db (dissoc db :networks/manage)} + (action-handler on-success (:id network)) + (accounts.utils/account-update {:networks new-networks}))) + (action-handler on-failure))))) ;; No edit functionality actually implemented (defn edit [{db :db}] {:db (assoc db :networks/manage (validate-manage default-manage)) :dispatch [:navigate-to :edit-network]}) + +(defn connect [{:keys [db now] :as cofx} {:keys [network on-success on-failure]}] + (if (get-in db [:account/account :networks network]) + (let [current-network (get-in db [:account/account :networks (:network db)])] + (if (ethereum/network-with-upstream-rpc? current-network) + (handlers-macro/merge-fx cofx + (action-handler on-success network) + (accounts.utils/account-update {:network network + :last-updated now} + [:logout])) + (handlers-macro/merge-fx {:show-confirmation {:title (i18n/label :t/close-app-title) + :content (i18n/label :t/close-app-content) + :confirm-button-text (i18n/label :t/close-app-button) + :on-accept #(re-frame/dispatch [::save-network network]) + :on-cancel nil}} + (action-handler on-success network)))) + (action-handler on-failure))) + +(defn delete [{{:account/keys [account]} :db} {:keys [network on-success on-failure]}] + (let [current-network? (= (:network account) network)] + (if (or current-network? + (not (get-in account [:networks network]))) + (handlers-macro/merge-fx {:show-error (i18n/label :t/delete-network-error)} + (action-handler on-failure network)) + (handlers-macro/merge-fx {:show-confirmation {:title (i18n/label :t/delete-network-title) + :content (i18n/label :t/delete-network-confirmation) + :confirm-button-text (i18n/label :t/delete) + :on-accept #(re-frame/dispatch [::remove-network network]) + :on-cancel nil}} + (action-handler on-success network))))) diff --git a/src/status_im/ui/screens/accounts/events.cljs b/src/status_im/ui/screens/accounts/events.cljs index a23a657674..8cba67f964 100644 --- a/src/status_im/ui/screens/accounts/events.cljs +++ b/src/status_im/ui/screens/accounts/events.cljs @@ -63,8 +63,11 @@ (handlers/register-handler-fx :switch-dev-mode - (fn [cofx [_ dev-mode]] - (accounts.utils/account-update {:dev-mode? dev-mode} cofx))) + (fn [cofx [_ dev-mode?]] + (merge (accounts.utils/account-update {:dev-mode? dev-mode?} cofx) + (if dev-mode? + {:dev-server/start nil} + {:dev-server/stop nil})))) (handlers/register-handler-fx :wallet-set-up-passed diff --git a/src/status_im/ui/screens/events.cljs b/src/status_im/ui/screens/events.cljs index 7592447bc0..4da015ecbd 100644 --- a/src/status_im/ui/screens/events.cljs +++ b/src/status_im/ui/screens/events.cljs @@ -1,13 +1,9 @@ (ns status-im.ui.screens.events (:require status-im.chat.events + status-im.dev-server.events status-im.network.events - [status-im.transport.handlers :as transport.handlers] status-im.protocol.handlers - [status-im.models.protocol :as models.protocol] - [status-im.models.account :as models.account] - [status-im.ui.screens.accounts.models :as accounts.models] 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.models.contacts :as models.contacts] status-im.ui.screens.add-new.events @@ -29,7 +25,6 @@ status-im.ui.screens.qr-scanner.events status-im.ui.screens.extensions.events status-im.ui.screens.wallet.events - [status-im.models.wallet :as models.wallet] status-im.ui.screens.wallet.collectibles.events status-im.ui.screens.wallet.send.events status-im.ui.screens.wallet.request.events @@ -57,8 +52,7 @@ [status-im.utils.handlers :as handlers] [status-im.utils.handlers-macro :as handlers-macro] [status-im.utils.http :as http] - [status-im.utils.utils :as utils] - [taoensso.timbre :as log])) + [status-im.utils.utils :as utils])) ;;;; COFX @@ -154,8 +148,9 @@ [{: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])} + {:dispatch [:init/initialize-keychain] + :clear-user-password (get-in db [:account/account :address]) + :dev-server/stop nil} (navigation/navigate-to-clean nil) (transport/stop-whisper)))) diff --git a/src/status_im/ui/screens/network_settings/edit_network/events.cljs b/src/status_im/ui/screens/network_settings/edit_network/events.cljs index dab316e4da..fb09a3872c 100644 --- a/src/status_im/ui/screens/network_settings/edit_network/events.cljs +++ b/src/status_im/ui/screens/network_settings/edit_network/events.cljs @@ -6,8 +6,11 @@ (handlers/register-handler-fx :save-new-network [(re-frame/inject-cofx :random-id)] - (fn [cofx _] - (models.network/save cofx))) + (fn [cofx] + (models.network/save cofx + {:data (get-in cofx [:db :network/manage]) + :on-success (fn [] + {:dispatch [:navigate-back]})}))) (handlers/register-handler-fx :network-set-input @@ -16,5 +19,5 @@ (handlers/register-handler-fx :edit-network - (fn [cofx _] + (fn [cofx] (models.network/edit cofx))) diff --git a/src/status_im/ui/screens/network_settings/events.cljs b/src/status_im/ui/screens/network_settings/events.cljs index 2e918e9b4f..ed9542d6af 100644 --- a/src/status_im/ui/screens/network_settings/events.cljs +++ b/src/status_im/ui/screens/network_settings/events.cljs @@ -1,15 +1,12 @@ (ns status-im.ui.screens.network-settings.events - (:require [re-frame.core :refer [dispatch dispatch-sync after] :as re-frame] - [status-im.utils.handlers :refer [register-handler] :as handlers] - status-im.ui.screens.network-settings.edit-network.events - [status-im.utils.handlers-macro :as handlers-macro] - [status-im.ui.screens.accounts.utils :as accounts.utils] + (:require [re-frame.core :as re-frame] [status-im.i18n :as i18n] - [status-im.utils.ethereum.core :as utils] - [status-im.transport.core :as transport] - [status-im.utils.ethereum.core :as ethereum] - [status-im.utils.types :as types] - [clojure.string :as string])) + [status-im.models.network :as models.network] + status-im.ui.screens.network-settings.edit-network.events + [status-im.ui.screens.accounts.utils :as accounts.utils] + [status-im.utils.handlers :as handlers] + [status-im.utils.handlers-macro :as handlers-macro] + [status-im.utils.ethereum.core :as utils])) ;; handlers @@ -37,28 +34,10 @@ (handlers/register-handler-fx :connect-network - (fn [{:keys [db now] :as cofx} [_ network]] - (let [current-network (get-in db [:account/account :networks (:network db)]) - chats (:transport/chats db)] - (if (utils/network-with-upstream-rpc? current-network) - (handlers-macro/merge-fx cofx - (accounts.utils/account-update {:network network - :last-updated now} - [:logout])) - {:show-confirmation {:title (i18n/label :t/close-app-title) - :content (i18n/label :t/close-app-content) - :confirm-button-text (i18n/label :t/close-app-button) - :on-accept #(dispatch [::save-network network]) - :on-cancel nil}})))) + (fn [cofx [_ network]] + (models.network/connect cofx {:network network}))) (handlers/register-handler-fx :delete-network - (fn [{{:account/keys [account] :as db} :db :as cofx} [_ network]] - (let [current-network? (= (:network account) network)] - (if current-network? - {:show-error (i18n/label :t/delete-network-error)} - {:show-confirmation {:title (i18n/label :t/delete-network-title) - :content (i18n/label :t/delete-network-confirmation) - :confirm-button-text (i18n/label :t/delete) - :on-accept #(dispatch [::remove-network network]) - :on-cancel nil}})))) + (fn [cofx [_ network]] + (models.network/delete cofx {:network network}))) diff --git a/test/cljs/status_im/test/models/network.cljs b/test/cljs/status_im/test/models/network.cljs index 17d554360d..eb45cc67e4 100644 --- a/test/cljs/status_im/test/models/network.cljs +++ b/test/cljs/status_im/test/models/network.cljs @@ -31,7 +31,7 @@ (is (model/valid-rpc-url? "https://valid.something.else:65323")))) (deftest new-network-test - (let [actual (model/new-network {:random-id "random-id"} + (let [actual (model/new-network "random-id" "network-name" "upstream-url" :mainnet @@ -45,7 +45,7 @@ actual)))) (deftest new-network-id-test - (let [actual (model/new-network {:random-id "random-id"} + (let [actual (model/new-network "random-id" "network-name" "upstream-url" :mainnet