[#6228]: API: requesting to connect to a node that is not available crashes the application

Signed-off-by: Aleksandr Pantiukhov <alwxndr@gmail.com>
This commit is contained in:
Aleksandr Pantiukhov 2018-10-16 11:48:12 +02:00
parent df9a59e255
commit 76a724a2e7
No known key found for this signature in database
GPG Key ID: 153E4F21734042F5
6 changed files with 102 additions and 45 deletions

View File

@ -39,6 +39,7 @@
[status-im.ui.screens.navigation :as navigation]
[status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log]))
;; init module
@ -336,8 +337,10 @@
(handlers/register-handler-fx
:network.ui/connect-network-pressed
(fn [cofx [_ network]]
(network/connect cofx {:network network})))
(fn [cofx [_ network-id]]
(network/connect cofx {:network-id network-id
:on-failure (fn [{:keys [reason]} _]
(utils/show-popup "Error" (str reason)))})))
(handlers/register-handler-fx
:network.ui/delete-network-pressed

View File

@ -40,12 +40,15 @@
[{:keys [cofx data]}]
(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."}]})}))
{:network-id (:id data)
:on-success (fn [{:keys [network-id client-version]} _]
{:dev-server/respond [200 {:message "Network has been connected."
:network-id network-id
:client-version client-version}]})
:on-failure (fn [{:keys [network-id reason]} _]
{:dev-server/respond [400 {:message "Cannot connect the network."
:network-id network-id
:reason reason}]})}))
(defmethod process-request! [:DELETE "network" nil]
[{:keys [cofx data]}]

View File

@ -9,7 +9,10 @@
[status-im.utils.ethereum.core :as ethereum]
[status-im.ui.screens.navigation :as navigation]
[status-im.fleet.core :as fleet-core]
[status-im.utils.fx :as fx]))
[status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers]
[status-im.utils.http :as http]
[status-im.utils.types :as types]))
(def url-regex
#"https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}(\.[a-z]{2,6})?\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)")
@ -26,6 +29,11 @@
{:value value
:error (string/blank? value)})
(defn validate-network-id [{:keys [value]}]
{:value value
:error (and (not (string/blank? value))
(= (int value) 0))})
(defn validate-url [{:keys [value]}]
{:value value
:error (not (valid-rpc-url? value))})
@ -34,7 +42,8 @@
(-> manage
(update :url validate-url)
(update :name validate-string)
(update :chain validate-string)))
(update :chain validate-string)
(update :network-id validate-network-id)))
(defn valid-manage? [manage]
(->> (validate-manage manage)
@ -97,24 +106,60 @@
{:db (assoc db :networks/manage (validate-manage default-manage))
:dispatch [:navigate-to :edit-network]})
(fx/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)
(fx/merge cofx
#(action-handler on-success network %)
(accounts.update/account-update
{:network network
:last-updated now}
{:success-event [:accounts.update.callback/save-settings-success]}))
(fx/merge cofx
{:ui/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 [:network.ui/save-non-rpc-network-pressed network])
:on-cancel nil}}
#(action-handler on-success network %))))
(action-handler on-failure)))
(fx/defn connect-success [{:keys [db now] :as cofx} {:keys [network-id on-success client-version]}]
(let [current-network (get-in db [:account/account :networks (:network db)])]
(if (ethereum/network-with-upstream-rpc? current-network)
(fx/merge cofx
#(action-handler on-success {:network-id network-id :client-version client-version} %)
(accounts.update/account-update
{:network network-id
:last-updated now}
{}))
(fx/merge cofx
{:ui/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 [:network.ui/save-non-rpc-network-pressed network-id])
:on-cancel nil}}
#(action-handler on-success {:network-id network-id :client-version client-version} %)))))
(defn connect-failure [{:keys [network-id on-failure reason]}]
(action-handler on-failure
{:network-id network-id :reason reason}
nil))
(fx/defn connect [{:keys [db]} {:keys [network-id on-success on-failure]}]
(if-let [config (get-in db [:account/account :networks network-id :config])]
{:http-post {:url (get-in config [:UpstreamConfig :URL])
:data (types/clj->json {:jsonrpc "2.0"
:method "web3_clientVersion"
:id 1})
:opts {:headers {"Content-Type" "application/json"}}
:success-event-creator (fn [{:keys [response-body]}]
(let [client-version (:result (http/parse-payload response-body))]
[::connect-success {:network-id network-id
:on-success on-success
:client-version client-version}]))
:failure-event-creator (fn [{:keys [response-body status-code]}]
(let [reason (if status-code
(str "Got a wrong status code: " status-code)
(str response-body))]
[::connect-failure {:network-id network-id
:on-failure on-failure
:reason reason}]))}}
(connect-failure {:network-id network-id
:on-failure on-failure
:reason "A network with the specified id doesn't exist"})))
(handlers/register-handler-fx
::connect-success
(fn [cofx [_ data]]
(connect-success cofx data)))
(handlers/register-handler-fx
::connect-failure
(fn [_ [_ data]]
(connect-failure data)))
(fx/defn delete
[{{:account/keys [account]} :db :as cofx} {:keys [network on-success on-failure]}]

View File

@ -33,9 +33,9 @@
{:http-post {:url graphql-url
:data (types/clj->json {:query (graphql-query (ethereum/naked-address address))})
:opts {:headers {"Content-Type" "application/json"}}
:success-event-creator (fn [o]
:success-event-creator (fn [{:keys [response-body]}]
[:store-collectibles superrare
(get-in (http/parse-payload o) [:data :collectiblesByOwner :collectibles])])
:failure-event-creator (fn [o]
[:load-collectibles-failure (http/parse-payload o)])
(get-in (http/parse-payload response-body) [:data :collectiblesByOwner :collectibles])])
:failure-event-creator (fn [{:keys [response-body]}]
[:load-collectibles-failure (http/parse-payload response-body)])
:timeout-ms 10000}})

View File

@ -31,19 +31,23 @@
ok?' (if valid-response?
(and ok? (valid-response? response))
ok?)]
[response-body ok?']))))))
(.then (fn [[response ok?]]
{:response-body response-body
:ok? ok?'
:status-text (.-statusText response)
:status-code (.-status response)}))))))
(.then (fn [{:keys [ok?] :as data}]
(cond
(and on-success ok?)
(on-success response)
(on-success data)
(and on-error (not ok?))
(on-error response)
(on-error data)
:else false)))
(.catch (or on-error
(fn [error]
(utils/show-popup "Error" (str error))))))))
(.catch (fn [error]
(if on-error
(on-error {:response-body error})
(utils/show-popup "Error" (str error))))))))
(defn- headers [response]
(let [entries (es6-iterator-seq (.entries (.-headers response)))]

View File

@ -80,12 +80,14 @@
(deftest set-input-test
(testing "it updates and validate a field"
(is (= {:db {:networks/manage {:url {:value "http://valid.com"
:error false}
:name {:value ""
:error true}
:chain {:value "mainnet"
:error false}}}}
(is (= {:db {:networks/manage {:url {:value "http://valid.com"
:error false}
:name {:value ""
:error true}
:chain {:value "mainnet"
:error false}
:network-id {:value nil
:error false}}}}
(model/set-input {:db {:networks/manage {:url {:value "something"
:error true}
:name {:value ""