yenda bf16116acd
move multiaccount settings to a table
integrate status-go changes to move multiaccount settings to a table
that can be migrated

Signed-off-by: yenda <eric@status.im>
2020-01-02 18:07:10 +01:00

196 lines
8.7 KiB
Clojure

(ns status-im.network.core
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.i18n :as i18n]
[status-im.node.core :as node]
[status-im.ui.screens.navigation :as navigation]
[status-im.utils.fx :as fx]
[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@:%_\+.~#?&//=]*)")
(defn valid-rpc-url? [url]
(boolean (re-matches url-regex (str url))))
(def default-manage
{:name {:value ""}
:url {:value ""}
:chain {:value :mainnet}})
(defn validate-string [{:keys [value]}]
{: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))})
(defn validate-manage [manage]
(-> manage
(update :url validate-url)
(update :name validate-string)
(update :chain validate-string)
(update :network-id validate-network-id)))
(defn valid-manage? [manage]
(->> (validate-manage manage)
vals
(map :error)
(not-any? identity)))
(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 get-network [{:keys [db]} network-id]
(get-in db [:networks/networks network-id]))
(fx/defn set-input
{:events [::input-changed]}
[{:keys [db]} input-key value]
{:db (-> db
(update-in [:networks/manage input-key] assoc :value value)
(update-in [:networks/manage] validate-manage))})
;; No edit functionality actually implemented
(fx/defn edit
{:events [::add-network-pressed]}
[{db :db}]
{:db (assoc db :networks/manage (validate-manage default-manage))
:dispatch [:navigate-to :edit-network]})
(fx/defn connect-success
{:events [::connect-success]}
[_ network-id]
{:ui/show-confirmation
{:title (i18n/label :t/close-app-title)
:content (i18n/label :t/logout-app-content)
:confirm-button-text (i18n/label :t/close-app-button)
:on-accept #(re-frame/dispatch [::save-network-settings-pressed network-id])
:on-cancel nil}})
(fx/defn connect-failure
{:events [::connect-failure]}
[_ reason]
{:utils/show-popup
{:title (i18n/label :t/error)
:content (str reason)}})
(fx/defn connect
{:events [::connect-network-pressed]}
[{:keys [db] :as cofx} network-id]
(if-let [config (get-in db [:networks/networks network-id :config])]
(if-let [upstream-url (get-in config [:UpstreamConfig :URL])]
{:http-post {:url upstream-url
:data (types/clj->json [{:jsonrpc "2.0"
:method "web3_clientVersion"
:id 1}
{:jsonrpc "2.0"
:method "net_version"
:id 2}])
:opts {:headers {"Content-Type" "application/json"}}
:success-event-creator (fn [{:keys [response-body]}]
(let [responses (http/parse-payload response-body)
client-version (:result (first responses))
expected-network-id (:NetworkId config)
rpc-network-id (when-let [res (:result (second responses))]
(js/parseInt res))]
(if (and client-version network-id
(= expected-network-id rpc-network-id))
[::connect-success network-id]
[::connect-failure (if (not= expected-network-id rpc-network-id)
(i18n/label :t/network-invalid-network-id)
(i18n/label :t/network-invalid-url))])))
:failure-event-creator (fn [{:keys [response-body status-code]}]
(let [reason (if status-code
(i18n/label :t/network-invalid-status-code {:code status-code})
(str response-body))]
[::connect-failure reason]))}}
(connect-success cofx network-id))
(connect-failure cofx "A network with the specified id doesn't exist")))
(fx/defn delete
{:events [::delete-network-pressed]}
[{:keys [db]} network]
(let [current-network? (= (:networks/current-network db) network)]
(if (or current-network?
(not (get-in db [:networks/networks network])))
{:ui/show-error (i18n/label :t/delete-network-error)}
{:ui/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-confirmed network])
:on-cancel nil}})))
(fx/defn save-network-settings
{:events [::save-network-settings-pressed]}
[{:keys [db] :as cofx} network]
(fx/merge cofx
{:db (assoc db :networks/current-network network)
::json-rpc/call [{:method "settings_saveSetting"
:params [:networks/current-network network]
:on-success #()}]}
(node/prepare-new-config {:on-success #(re-frame/dispatch [:logout])})))
(fx/defn remove-network
{:events [::remove-network-confirmed]}
[{:keys [db] :as cofx} network]
(let [networks (dissoc (:networks/networks db) network)]
{:db (assoc db :networks/networks networks)
::json-rpc/call [{:method "settings_saveSetting"
:params [:networks/networks (vals networks)]
:on-success #(re-frame/dispatch [:navigate-back])}]}))
(defn new-network
[random-id network-name upstream-url chain-type chain-id]
(let [data-dir (str "/ethereum/" (name chain-type) "_rpc")
config {:NetworkId (or (when chain-id (int chain-id))
(ethereum/chain-keyword->chain-id chain-type))
:DataDir data-dir
:UpstreamConfig {:Enabled true
:URL upstream-url}}]
{:id random-id
:name network-name
:config config}))
(fx/defn save
{:events [::save-network-pressed]
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
[{{:networks/keys [manage networks] :as db} :db
random-id-generator :random-id-generator :as cofx}]
(if (valid-manage? manage)
;; rename network-id from UI to chain-id
(let [{:keys [name url chain network-id]} manage
random-id (string/replace (random-id-generator) "-" "")
network (new-network random-id
(:value name)
(:value url)
(:value chain)
(:value network-id))
custom-chain-type? (= :custom (:value chain))
new-networks (assoc networks random-id network)]
(if (or (not custom-chain-type?)
(chain-id-available? networks network))
{:db (-> db
(dissoc :networks/manage)
(assoc :networks/networks new-networks))
::json-rpc/call [{:method "settings_saveSetting"
:params [:networks/networks (vals new-networks)]
:on-success #(re-frame/dispatch [:navigate-back])}]}
{:ui/show-error "chain-id already defined"}))
{:ui/show-error "invalid network parameters"}))
(fx/defn open-network-details
{:events [::network-entry-pressed]}
[cofx network]
(navigation/navigate-to-cofx cofx :network-details {:networks/selected-network network}))