From 38fc712f071e9d6da943ac2f01b3ac9ae028b4cf Mon Sep 17 00:00:00 2001 From: tbenr Date: Wed, 27 Mar 2019 09:46:13 +0100 Subject: [PATCH] fixes #7667 Signed-off-by: Julien Eluard --- src/status_im/events.cljs | 2 +- src/status_im/extensions/core.cljs | 23 ++++++- src/status_im/extensions/network.cljs | 41 ++++++++++++ src/status_im/network/core.cljs | 52 ++++++++++----- test/cljs/status_im/test/models/network.cljs | 68 +++++++++++++++++++- translations/en.json | 2 + 6 files changed, 167 insertions(+), 21 deletions(-) create mode 100644 src/status_im/extensions/network.cljs diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index c6ce4e649e..17884ee3ec 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -506,7 +506,7 @@ (handlers/register-handler-fx :network.ui/remove-network-confirmed (fn [cofx [_ network]] - (network/remove-network cofx network))) + (network/remove-network cofx network [:navigate-back]))) (handlers/register-handler-fx :network.ui/connect-network-pressed diff --git a/src/status_im/extensions/core.cljs b/src/status_im/extensions/core.cljs index 39f68bd05e..5cea6717ee 100644 --- a/src/status_im/extensions/core.cljs +++ b/src/status_im/extensions/core.cljs @@ -23,6 +23,7 @@ [status-im.utils.fx :as fx] status-im.extensions.ethereum status-im.extensions.camera + status-im.extensions.network [status-im.extensions.map :as map] [status-im.utils.ethereum.tokens :as tokens] [status-im.utils.ethereum.core :as ethereum] @@ -549,7 +550,27 @@ :arguments {:key :string}} 'store/clear-all {:permissions [:read] - :data :store/clear-all} + :data :store/clear-all} + 'network/add + {:permissions [:read] + :data :network/add + :arguments {:chain-id :number + :name :string + :url :string + :on-success? :event + :on-failure? :event}} + 'network/select + {:permissions [:read] + :data :network/select + :arguments {:chain-id :number + :on-success? :event + :on-failure? :event}} + 'network/remove + {:permissions [:read] + :data :network/remove + :arguments {:chain-id :number + :on-success? :event + :on-failure? :event}} 'http/get {:permissions [:read] :data :http/get diff --git a/src/status_im/extensions/network.cljs b/src/status_im/extensions/network.cljs new file mode 100644 index 0000000000..d1d3ebb62c --- /dev/null +++ b/src/status_im/extensions/network.cljs @@ -0,0 +1,41 @@ +(ns status-im.extensions.network + (:require [status-im.utils.handlers :as handlers] + [status-im.i18n :as i18n] + [status-im.network.core :as network])) + +(handlers/register-handler-fx + :extensions/network-on-success + (fn [cofx [_ on-success result]] + (when on-success (on-success {:value result})))) + +(defn- network-id [extension-id chain-id] + (str extension-id "_" chain-id)) + +(handlers/register-handler-fx + :network/select + (fn [cofx [_ _ {:keys [chain-id on-success on-failure]}]] + (if-let [network-id (network/get-network-id-for-chain-id cofx chain-id)] + (network/connect cofx {:network-id network-id + :on-success (when on-success #(on-success {:value %})) + :on-failure (when on-failure #(on-failure {:value %}))}) + (when on-failure (on-failure {:value (i18n/label :t/extensions-network-not-found)}))))) + +(handlers/register-handler-fx + :network/add + (fn [{:keys [db] :as cofx} [_ {extension-id :id} {:keys [chain-id name url on-success on-failure]}]] + (network/save cofx {:data {:name {:value name} + :url {:value url} + :network-id {:value chain-id} + :chain {:value :custom}} + :network-id (network-id extension-id chain-id) + :success-event (when on-success [:extensions/network-on-success on-success chain-id]) + :on-failure (when on-failure #(on-failure {:value %})) + :chain-id-unique? false}))) + +(handlers/register-handler-fx + :network/remove + (fn [cofx [_ {extension-id :id} {:keys [chain-id on-success on-failure]}]] + (let [network-id (network-id extension-id chain-id)] + (if (network/get-network cofx network-id) + (network/remove-network cofx network-id (when on-success [:extensions/network-on-success on-success chain-id])) + (when on-failure (on-failure {:value (i18n/label :t/extensions-chain-id-not-found)})))))) diff --git a/src/status_im/network/core.cljs b/src/status_im/network/core.cljs index e93fd93f10..9fa9eb468d 100644 --- a/src/status_im/network/core.cljs +++ b/src/status_im/network/core.cljs @@ -53,9 +53,18 @@ (map :error) (not-any? identity))) -(defn new-network [random-id network-name upstream-url type network-id] +(defn get-network-id-for-chain-id [{:keys [db]} chain-id] + (let [networks (get-in db [:account/account :networks]) + filtered (filter #(= chain-id (get-in % [1 :config :NetworkId])) networks)] + (first (keys filtered)))) + +(defn chain-id-available? [current-networks network] + (let [chain-id (get-in network [:config :NetworkId])] + (every? #(not= chain-id (get-in % [1 :config :NetworkId])) current-networks))) + +(defn new-network [random-id network-name upstream-url type chain-id] (let [data-dir (str "/ethereum/" (name type) "_rpc") - config {:NetworkId (or (when network-id (int network-id)) + config {:NetworkId (or (when chain-id (int chain-id)) (ethereum/chain-keyword->chain-id type)) :DataDir data-dir :UpstreamConfig {:Enabled true @@ -68,6 +77,9 @@ (let [network (get (:networks (:account/account db)) (:network db))] (ethereum/network->chain-keyword network))) +(defn get-network [{:keys [db]} network-id] + (get-in db [:account/account :networks network-id])) + (fx/defn set-input [{:keys [db]} input-key value] {:db (-> db @@ -82,25 +94,31 @@ (handler data cofx)))) (fx/defn save - [{{:network/keys [manage] :account/keys [account] :as db} :db + [{{:networks/keys [manage] :account/keys [account] :as db} :db random-id-generator :random-id-generator :as cofx} - {:keys [data success-event on-success on-failure]}] + {:keys [data success-event on-success on-failure network-id chain-id-unique?]}] (let [data (or data manage)] (if (valid-manage? data) - (let [{:keys [name url chain network-id]} data - network (new-network (random-id-generator) + ;; rename network-id from UI to chain-id + (let [{:keys [name url chain] chain-id :network-id} data + ;; network-id overrides random id + network (new-network (or network-id (random-id-generator)) (:value name) (:value url) (:value chain) - (:value network-id)) - new-networks (merge {(:id network) network} (:networks account))] - (fx/merge cofx - {:db (dissoc db :networks/manage)} - #(action-handler on-success (:id network) %) - (accounts.update/account-update - {:networks new-networks} - {:success-event success-event}))) - (action-handler on-failure)))) + (:value chain-id)) + current-networks (:networks account) + new-networks (merge {(:id network) network} current-networks)] + (if (or (not chain-id-unique?) + (chain-id-available? current-networks network)) + (fx/merge cofx + {:db (dissoc db :networks/manage)} + #(action-handler on-success (:id network) %) + (accounts.update/account-update + {:networks new-networks} + {:success-event success-event})) + (action-handler on-failure "chain-id already defined" nil))) + (action-handler on-failure "invalid network parameters" nil)))) ;; No edit functionality actually implemented (fx/defn edit @@ -218,12 +236,12 @@ {:success-event [:accounts.update.callback/save-settings-success]})) (fx/defn remove-network - [{:keys [db now] :as cofx} network] + [{:keys [db now] :as cofx} network success-event] (let [networks (dissoc (get-in db [:account/account :networks]) network)] (accounts.update/account-update cofx {:networks networks :last-updated now} - {:success-event [:navigate-back]}))) + {:success-event success-event}))) (fx/defn save-network [cofx] diff --git a/test/cljs/status_im/test/models/network.cljs b/test/cljs/status_im/test/models/network.cljs index e8dcc46bab..702404911b 100644 --- a/test/cljs/status_im/test/models/network.cljs +++ b/test/cljs/status_im/test/models/network.cljs @@ -1,6 +1,7 @@ (ns status-im.test.models.network (:require [cljs.test :refer-macros [deftest is testing]] - [status-im.network.core :as model])) + [status-im.network.core :as model] + [reagent.core :as reagent])) (deftest valid-rpc-url-test (testing "nil?" @@ -96,7 +97,7 @@ :error false}}}} :url "http://valid.com"))))) -(deftest save +(deftest not-save-invalid-url (testing "it does not save a network with an invalid url" (is (nil? (model/save {:random-id-generator (constantly "random") :db {:networks/manage {:url {:value "wrong"} @@ -104,3 +105,66 @@ :name {:value "empty"}} :account/account {}}} {}))))) + +(deftest save-valid-network + (testing "save a valid network" + (is (some? (model/save {:random-id-generator (constantly "random") + :db {:networks/manage {:url {:value "http://valid.com"} + :chain {:value "mainnet"} + :name {:value "valid"}} + :account/account {}}} + {}))))) + +(deftest not-save-non-unique-id + (testing "it does not save a network with network-id already defined" + (let [failure (reagent/atom false)] + (do (model/save {:random-id-generator (constantly "random") + :db {:networks/manage {:url {:value "http://valid.com"} + :chain {:value :mainnet} + :name {:value "valid"}} + :account/account {:networks {"randomid" + {:id "randomid" + :name "network-name" + :config {:NetworkId 1 + :DataDir "/ethereum/mainnet_rpc" + :UpstreamConfig {:Enabled true + :URL "upstream-url"}}}}}}} + {:chain-id-unique? true + :on-failure #(reset! failure true)}) + (is @failure))))) + +(deftest save-valid-network-with-unique-check + (testing "save a valid network with network-id not already defined" + (is (some? (model/save {:random-id-generator (constantly "random") + :db {:networks/manage {:url {:value "http://valid.com"} + :chain {:value :mainnet} + :name {:value "valid"}} + :account/account {:networks {"randomid" + {:id "randomid" + :name "network-name" + :config {:NetworkId 3 + :DataDir "/ethereum/mainnet_rpc" + :UpstreamConfig {:Enabled true + :URL "upstream-url"}}}}}}} + {:chain-id-unique? true}))))) + +(deftest save-with-id-override + (testing "save a valid network with id override" + (let [result (model/save {:random-id-generator (constantly "random") + :db {:networks/manage {:url {:value "http://valid.com"} + :chain {:value :mainnet} + :name {:value "valid"}} + :account/account {}}} + {:network-id "override"})] + (is (some? (get-in result [:db :account/account :networks "override"])))))) + +(deftest get-network-id-for-chain-id + (testing "get the first network id for the given chain-id" + (is (= "randomid" (model/get-network-id-for-chain-id {:db {:account/account {:networks {"randomid" + {:id "randomid" + :name "network-name" + :config {:NetworkId 1 + :DataDir "/ethereum/mainnet_rpc" + :UpstreamConfig {:Enabled true + :URL "upstream-url"}}}}}}} + 1))))) \ No newline at end of file diff --git a/translations/en.json b/translations/en.json index 6f922789d0..d9737ccfbc 100644 --- a/translations/en.json +++ b/translations/en.json @@ -960,6 +960,8 @@ "dapps-permissions": "DApp permissions", "revoke-access": "Revoke access", "extensions-camera-send-picture": "Send picture", + "extensions-network-not-found": "network not found for the given chain-id", + "extensions-chain-id-not-found": "chain-id not found or was not created by this extension", "mobile-syncing-sheet-title": "Sync using Mobile data", "mobile-syncing-sheet-details": "Status tends to use a lot of data when syncing chats. You can choose not to sync when on mobile network", "mobile-network-continue-syncing": "Continue syncing",