Add support for custom network upstreams

Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
Connor Christie 2018-05-17 16:21:01 +12:00 committed by Andrey Shovkoplyas
parent 41900da38c
commit 24d5fabe2e
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4
30 changed files with 407 additions and 114 deletions

View File

@ -37,7 +37,7 @@
[{:keys [db get-local-storage-data]} commands-resource whisper-identity]
(let [data (get-local-storage-data whisper-identity)
local-storage-snippet (js-resources/local-storage-data data)
network-id (get-in db [:networks/networks (:network db) :raw-config :NetworkId])
network-id (get-in db [:account/account :networks (:network db) :raw-config :NetworkId])
ethereum-id-snippet (js-resources/network-id network-id)
commands-snippet (str local-storage-snippet ethereum-id-snippet commands-resource)]
{::evaluate-jail-n [{:jail-id whisper-identity

View File

@ -80,8 +80,8 @@
(handlers/register-handler-fx
:initialize-sync-listener
(fn [{{:keys [sync-listening-started network networks/networks] :as db} :db} _]
(fn [{{:keys [sync-listening-started network account/account] :as db} :db} _]
(when (and (not sync-listening-started)
(not (utils/network-with-upstream-rpc? networks network)))
(not (utils/network-with-upstream-rpc? (get-in account [:networks network]))))
{:db (assoc db :sync-listening-started true)
:dispatch [:check-sync]})))

View File

@ -331,6 +331,7 @@
:add-new-contact "Add new contact"
:scan-qr "Scan QR code"
:name "Name"
:specify-name "Specify a name"
:address-explication "Your public key is used to generate your address on Ethereum and is a series of numbers and letters. You can find it easily in your profile"
:use-valid-contact-code "Please enter a valid contact code"
:enter-valid-public-key "Please enter a valid public key or scan a QR code"
@ -580,6 +581,8 @@
:add-new-network "Add new network"
:add-wnode "Add mailserver"
:existing-networks "Existing networks"
:delete-network-title "Delete network?"
:delete-network-confirmation "Are you sure you want to delete this network?"
;; TODO(dmitryn): come up with better description/naming. Suggested namings: Mailbox and Master Node
:existing-wnodes "Existing mailservers"
:add-json-file "Add a JSON file"
@ -591,12 +594,15 @@
:process-json "Process JSON"
:error-processing-json "Error processing JSON"
:rpc-url "RPC URL"
:network-chain "Network chain"
:network "Network"
:network-details "Network details"
:remove-network "Remove network"
:network-settings "Network settings"
:offline-messaging "Offline messages"
:offline-messaging-settings "Offline messages settings"
:edit-network-warning "Be careful, editing the network data may disable this network for you"
:delete-network-error "Please connect to a different network before deleting this one"
:connecting-requires-login "Connecting to another network requires login"
:close-app-title "Warning!"
:close-app-content "The app will stop and close. When you reopen it, the selected network will be used"
@ -607,6 +613,14 @@
:mainnet-warning-text "While we highly appreciate your contribution as a tester of Status, wed like to point out the dangers. Youre switching to Mainnet mode which is still in Alpha. This means it is still in development and has not been audited yet. Some of the risks you may be exposed to include:\n\n- Accounts may be unrecoverable due to breaking changes\n- Loss of ETH and tokens\n- Failure to send or receive messages\n\nSwitching to Mainnet should be done for testing purposes only. By tapping \"I understand\", you confirm that you assume the full responsibility for all risks concerning your data and funds. "
:mainnet-warning-ok-text "I understand"
:main-networks "Main networks"
:test-networks "Test networks"
:custom-networks "Custom networks"
:mainnet-network "Main network"
:ropsten-network "Ropsten test network"
:rinkeby-network "Rinkeby test network"
;; browser
:browser "Browser"
:enter-dapp-url "Enter a ÐApp URL"

View File

@ -42,9 +42,10 @@
(success-fn result)))))
(defn get-current-wnode-address [db]
(let [network (ethereum/network->chain-keyword (get db :network))
(let [network (get (:networks (:account/account db)) (:network db))
chain (ethereum/network->chain-keyword network)
wnode-id (get-in db [:account/account :settings :wnode network])]
(get-in db [:inbox/wnodes network wnode-id :address])))
(get-in db [:inbox/wnodes chain wnode-id :address])))
(defn initialize-offline-inbox-flow []
{:first-dispatch [:inbox/get-sym-key]

View File

@ -8,10 +8,20 @@
{:background-color (if checked? colors/blue colors/gray-lighter)
:align-items :center
:justify-content :center
:border-radius 2
:width 24
:height 24})
:border-radius 2
:width 24
:height 24})
(defn icon-radio-container [checked?]
(merge (icon-check-container checked?)
{:border-radius 100
:width 26
:height 26}))
(def check-icon
{:width 12
:height 12})
(def plain-check-icon
(merge check-icon
{:tint-color colors/blue}))

View File

@ -1,17 +1,26 @@
(ns status-im.ui.components.checkbox.view
(:require [status-im.ui.components.checkbox.styles :as styles]
[status-im.ui.components.react :as react]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.utils.platform :as platform]))
(defn checkbox [{:keys [on-value-change checked? accessibility-label] :or {accessibility-label :checkbox}}]
(if platform/android?
[react/view {:style styles/wrapper}
[react/check-box {:on-value-change on-value-change
:value checked?
:accessibility-label accessibility-label}]]
[react/touchable-highlight (merge {:style styles/wrapper
:accessibility-label accessibility-label}
(when on-value-change {:on-press #(on-value-change (not checked?))}))
[react/view (styles/icon-check-container checked?)
(when checked?
[react/icon :check_on styles/check-icon])]]))
(defn- checkbox-generic [{:keys [on-value-change checked? accessibility-label] :or {accessibility-label :checkbox}} plain?]
(let [icon-check-container (if plain? #() styles/icon-check-container)
check-icon (if plain? styles/plain-check-icon styles/check-icon)]
(if platform/android?
[react/view styles/wrapper
[react/check-box {:on-value-change on-value-change
:value checked?
:accessibility-label accessibility-label}]]
[react/touchable-highlight (merge {:style styles/wrapper
:accessibility-label accessibility-label}
(when on-value-change {:on-press #(on-value-change (not checked?))}))
[react/view (icon-check-container checked?)
(when checked?
[react/icon :check_on check-icon])]])))
(defn checkbox [props]
[checkbox-generic props false])
(defn plain-checkbox [props]
[checkbox-generic props true])

View File

@ -53,7 +53,7 @@
{:width icon-size
:height icon-size})
(def horizontal-margin 16)
(def horizontal-margin 12)
(def vertical-margin 12)
(def left-item-wrapper
@ -83,11 +83,6 @@
{:android {:background-color colors/white
:height 8}})
(defstyle section-separator
(merge base-separator
{:android {:margin-top 12}
:ios {:margin-top 16}}))
(defstyle section-header
{:font-size 14
:color colors/gray
@ -95,7 +90,10 @@
:android {:margin-top 11
:margin-bottom 3}
:ios {:margin-top 10
:margin-bottom 2}})
:margin-bottom 10}})
(defstyle section-header-container
{:background-color colors/white})
(def action-list
{:background-color colors/blue})

View File

@ -34,8 +34,9 @@
([left content] (item left content nil))
([left content right]
[react/view {:style styles/item}
[react/view {:style styles/left-item-wrapper}
left]
(when left
[react/view {:style styles/left-item-wrapper}
left])
[react/view {:style styles/content-item-wrapper}
content]
(when right
@ -88,7 +89,7 @@
(defn list-item-with-checkbox [{:keys [on-value-change checked? plain-checkbox?] :as props} item]
(let [handler #(on-value-change (not checked?))
checkbox [(if plain-checkbox? checkbox/checkbox item-checkbox) props]
checkbox [(if plain-checkbox? checkbox/plain-checkbox item-checkbox) props]
item (conj item checkbox)]
[touchable-item handler item]))
@ -105,14 +106,14 @@
{:post [(some? %)]}
(f data index)))
(def base-separator [react/view styles/base-separator])
(def default-separator [react/view styles/separator])
(def default-header [react/view styles/list-header-footer-spacing])
(def default-footer [react/view styles/list-header-footer-spacing])
(def section-separator [react/view styles/section-separator])
(defn- base-list-props
[{:keys [key-fn render-fn empty-component header separator default-separator?]}]
(let [separator (or separator (when (and platform/ios? default-separator?) default-separator))]
@ -163,8 +164,9 @@
(defn- default-render-section-header [{:keys [title data]}]
(when (seq data)
[react/text {:style styles/section-header}
title]))
[react/view styles/section-header-container
[react/text {:style styles/section-header}
title]]))
(defn- wrap-per-section-render-fn [props]
(update
@ -182,8 +184,7 @@
(merge (base-list-props props)
props
{:sections (clj->js (map wrap-per-section-render-fn sections))
:renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)}
(when platform/ios? {:SectionSeparatorComponent (fn [] (reagent/as-element section-separator))}))])
:renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)})])
(defn- render-action [{:keys [label accessibility-label icon action disabled?]}
{:keys [action-style action-label-style icon-opts]}]

View File

@ -72,6 +72,11 @@
:height 24})
(def icon-add
{:width 24
:height 24
:color colors/blue})
(def icon-add-illuminated
{:width 24
:height 24
:color colors/blue

View File

@ -2,9 +2,9 @@
(:require [re-frame.core :as re-frame]
[status-im.ui.components.styles :as styles]))
(defn add [handler]
(defn add [illuminated? handler]
{:icon :icons/add
:icon-opts styles/icon-add
:icon-opts (if illuminated? styles/icon-add-illuminated styles/icon-add)
:handler handler})
(defn opts [options]

View File

@ -167,6 +167,7 @@
:group-chat-profile/editing?
:networks/selected-network
:networks/networks
:networks/manage
:node/after-start
:node/after-stop
:inbox/wnodes

View File

@ -26,7 +26,7 @@
[components.common/logo styles/toolbar-logo]])
[toolbar/actions
(when platform/ios?
[(-> (toolbar.actions/add #(re-frame/dispatch [:navigate-to :new]))
[(-> (toolbar.actions/add true #(re-frame/dispatch [:navigate-to :new]))
(assoc-in [:icon-opts :accessibility-label] :new-chat-button))])]])
(defn- home-action-button []

View File

@ -12,3 +12,5 @@
(spec/def :networks/selected-network :networks/network)
(spec/def :networks/networks (spec/nilable (spec/map-of :networks/id :networks/network)))
(spec/def :networks/manage (spec/nilable map?))

View File

@ -0,0 +1,47 @@
(ns status-im.ui.screens.network-settings.edit-network.events
(:require [re-frame.core :as re-frame]
[status-im.utils.handlers :refer [register-handler] :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.ui.screens.accounts.utils :as accounts.utils]
[status-im.utils.ethereum.core :as ethereum]
[status-im.utils.types :as types]
[clojure.string :as string]))
(defn- new-network [{:keys [random-id] :as cofx} network-name upstream-url type]
(let [data-dir (str "/ethereum/" (name type) "_rpc")
config {:NetworkId (ethereum/chain-keyword->chain-id type)
:DataDir data-dir
:UpstreamConfig {:Enabled true
:URL upstream-url}}]
{:id (string/replace random-id "-" "")
:name network-name
:config (types/clj->json config)
:raw-config config}))
(handlers/register-handler-fx
:save-new-network
[(re-frame/inject-cofx :random-id)]
(fn [{{:networks/keys [manage] :account/keys [account] :as db} :db :as cofx} _]
(let [{:keys [name url chain]} manage
network (new-network cofx (:value name) (:value url) (:value chain))
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})))))
(handlers/register-handler-fx
:network-set-input
(fn [{db :db} [_ input-key value]]
{:db (update db :networks/manage merge {input-key {:value value
:error (and (string? value) (empty? value))}})}))
(handlers/register-handler-fx
:edit-network
(fn [{db :db} _]
{:db (update-in db [:networks/manage] assoc
:name {:error true}
:url {:error true}
:chain {:value :mainnet})
:dispatch [:navigate-to :edit-network]}))

View File

@ -0,0 +1,27 @@
(ns status-im.ui.screens.network-settings.edit-network.styles
(:require-macros [status-im.utils.styles :refer [defstyle]])
(:require [status-im.ui.components.colors :as colors]
[status-im.ui.components.styles :as styles]))
(def edit-network-view
{:flex 1
:margin-horizontal 16
:margin-vertical 15})
(def input-container
{:margin-bottom 15})
(def network-type
{:flex-direction :row
:align-items :center})
(defstyle network-type-text
{:color colors/black
:ios {:font-size 17
:letter-spacing -0.2}
:android {:font-size 16}})
(def bottom-container
{:flex-direction :row
:margin-horizontal 12
:margin-vertical 15})

View File

@ -0,0 +1,14 @@
(ns status-im.ui.screens.network-settings.edit-network.subs
(:require [re-frame.core :refer [reg-sub]]))
(reg-sub
:get-manage-network
:<- [:get :networks/manage]
(fn [manage]
manage))
(reg-sub
:manage-network-valid?
:<- [:get-manage-network]
(fn [manage]
(not-any? :error (vals manage))))

View File

@ -0,0 +1,62 @@
(ns status-im.ui.screens.network-settings.edit-network.views
(:require-macros [status-im.utils.views :as views])
(:require
[re-frame.core :as re-frame]
[status-im.ui.components.react :as react]
[status-im.i18n :as i18n]
[status-im.ui.components.styles :as components.styles]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.text-input.view :as text-input]
[status-im.ui.screens.network-settings.edit-network.styles :as styles]
[status-im.ui.components.checkbox.view :as checkbox]))
(defn- render-network-type [manage-network type]
(let [name (case type
:mainnet (i18n/label :t/mainnet-network)
:testnet (i18n/label :t/ropsten-network)
:rinkeby (i18n/label :t/rinkeby-network))]
[list/list-item-with-checkbox
{:checked? (= (get-in manage-network [:chain :value]) type)
:on-value-change #(re-frame/dispatch [:network-set-input :chain type])
:plain-checkbox? true}
[list/item
nil [list/item-primary-only name]]]))
(views/defview edit-network []
(views/letsubs [manage-network [:get-manage-network]
is-valid? [:manage-network-valid?]]
[react/view components.styles/flex
[status-bar/status-bar]
[react/keyboard-avoiding-view components.styles/flex
[toolbar/simple-toolbar (i18n/label :t/add-network)]
[react/scroll-view
[react/view styles/edit-network-view
[text-input/text-input-with-label
{:label (i18n/label :t/name)
:placeholder (i18n/label :t/specify-name)
:container styles/input-container
:default-value (get-in manage-network [:name :value])
:on-change-text #(re-frame/dispatch [:network-set-input :name %])
:auto-focus true}]
[text-input/text-input-with-label
{:label (i18n/label :t/rpc-url)
:placeholder (i18n/label :t/specify-rpc-url)
:container styles/input-container
:default-value (get-in manage-network [:url :value])
:on-change-text #(re-frame/dispatch [:network-set-input :url %])}]
[react/text (i18n/label :t/network-chain)]
[react/view styles/network-type
[list/flat-list {:data [:mainnet :testnet :rinkeby]
:key-fn (fn [_ i] (str i))
:separator list/base-separator
:render-fn #(render-network-type manage-network %)}]]]]
[react/view styles/bottom-container
[react/view components.styles/flex]
[components.common/bottom-button
{:forward? true
:label (i18n/label :t/save)
:disabled? (not is-valid?)
:on-press #(re-frame/dispatch [:save-new-network])}]]]]))

View File

@ -1,11 +1,15 @@
(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]
[status-im.i18n :as i18n]
[status-im.utils.ethereum.core :as utils]
[status-im.transport.core :as transport]))
[status-im.transport.core :as transport]
[status-im.utils.ethereum.core :as ethereum]
[status-im.utils.types :as types]
[clojure.string :as string]))
;; handlers
@ -35,13 +39,21 @@
:last-updated now}
[::close-application]))))
(handlers/register-handler-fx
::remove-network
(fn [{:keys [db now] :as cofx} [_ network]]
(let [networks (dissoc (get-in db [:account/account :networks]) network)]
(handlers-macro/merge-fx cofx
{:dispatch [:navigate-back]}
(accounts.utils/account-update {:networks networks
:last-updated now})))))
(handlers/register-handler-fx
:connect-network
(fn [{:keys [db now] :as cofx} [_ network]]
(let [current-network (:network db)
networks (:networks/networks db)
(let [current-network (get-in db [:account/account :networks (:network db)])
chats (:transport/chats db)]
(if (utils/network-with-upstream-rpc? networks current-network)
(if (utils/network-with-upstream-rpc? current-network)
(handlers-macro/merge-fx cofx
{:dispatch-n [[:load-accounts]
[:navigate-to-clean :accounts]]}
@ -53,3 +65,15 @@
:confirm-button-text (i18n/label :t/close-app-button)
:on-accept #(dispatch [::save-network network])
:on-cancel nil}}))))
(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}}))))

View File

@ -6,31 +6,45 @@
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.react :as react]
[status-im.i18n :as i18n]
[status-im.ui.components.styles :as components.styles]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.screens.network-settings.styles :as st]
[status-im.ui.screens.network-settings.views :as network-settings]))
[status-im.ui.screens.network-settings.views :as network-settings]
[status-im.ui.components.colors :as colors]))
(views/defview network-details []
(views/letsubs [{:keys [networks/selected-network]} [:get-screen-params]
{:keys [network]} [:get-current-account]]
{:keys [network]} [:get-current-account]
networks [:get-networks]]
(let [{:keys [id name config]} selected-network
connected? (= id network)]
[react/view {:flex 1}
connected? (= id network)
custom? (seq (filter #(= (:id %) id) (:custom networks)))]
[react/view components.styles/flex
[status-bar/status-bar]
[toolbar/simple-toolbar]
[network-settings/network-badge
{:name name
:connected? connected?}]
(when-not connected?
[react/touchable-highlight {:on-press #(rf/dispatch [:connect-network id])}
[react/view st/connect-button-container
[react/view {:style st/connect-button
:accessibility-label :network-connect-button}
[react/text {:style st/connect-button-label
:uppercase? true}
(i18n/label :t/connect)]]
[react/text {:style st/connect-button-description}
(i18n/label :t/connecting-requires-login)]]])
[react/view st/network-config-container
[react/text {:style st/network-config-text
:accessibility-label :network-details-text}
config]]])))
[react/view components.styles/flex
[toolbar/simple-toolbar (i18n/label :t/network-details)]
[react/view components.styles/flex
[network-settings/network-badge
{:name name
:connected? connected?}]
(when-not connected?
[react/touchable-highlight {:on-press #(rf/dispatch [:connect-network id])}
[react/view st/connect-button-container
[react/view {:style st/connect-button
:accessibility-label :network-connect-button}
[react/text {:style st/connect-button-label
:uppercase? true}
(i18n/label :t/connect)]]
[react/text {:style st/connect-button-description}
(i18n/label :t/connecting-requires-login)]]])
[react/view st/network-config-container
[react/text {:style st/network-config-text
:accessibility-label :network-details-text}
config]]]
(when custom?
[react/view st/bottom-container
[react/view components.styles/flex
[components.common/button {:label (i18n/label :t/delete)
:button-style st/delete-button
:label-style st/delete-button-text
:on-press #(rf/dispatch [:delete-network id])}]]])]])))

View File

@ -139,3 +139,14 @@
:letter-spacing -0.2}
:android {:font-size 12
:margin-top 2}})
(def bottom-container
{:flex-direction :row
:margin-horizontal 12
:margin-vertical 15})
(def delete-button
{:background-color colors/white})
(def delete-button-text
{:color colors/red})

View File

@ -1,16 +1,36 @@
(ns status-im.ui.screens.network-settings.subs
(:require [re-frame.core :refer [reg-sub subscribe]]))
(reg-sub
:get-current-account-network
:<- [:get-current-account]
:<- [:get :networks/networks]
(fn [[current-account networks]]
(get networks (:network current-account))))
(:require [re-frame.core :refer [reg-sub subscribe]]
[status-im.utils.ethereum.core :as ethereum]
status-im.ui.screens.network-settings.edit-network.subs))
(reg-sub
:get-network-id
:<- [:network]
(fn [network]
(ethereum/network->chain-id network)))
(defn- filter-networks [network-type]
(fn [network]
(let [chain-id (ethereum/network->chain-id network)
testnet? (ethereum/testnet? chain-id)
custom? (:custom? network)]
(case network-type
:custom custom?
:mainnet (and (not custom?) (not testnet?))
:testnet (and (not custom?) testnet?)))))
(defn- label-networks [default-networks]
(fn [network]
(let [custom? (not (contains? default-networks (:id network)))]
(assoc network :custom? custom?))))
(reg-sub
:get-networks
:<- [:get :account/account]
:<- [:get :networks/networks]
:<- [:get :network]
(fn [[networks network]]
(get-in networks [network :raw-config :NetworkId])))
(fn [[{:keys [networks] :as account} default-networks]]
(let [networks (map (label-networks default-networks) (sort-by :name (vals networks)))
types [:mainnet :testnet :custom]]
(zipmap
types
(map #(filter (filter-networks %) networks) types)))))

View File

@ -1,12 +1,16 @@
(ns status-im.ui.screens.network-settings.views
(:require-macros [status-im.utils.views :as views])
(:require [re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.i18n :as i18n]
[status-im.ui.components.react :as react]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.toolbar.actions :as toolbar.actions]
[status-im.ui.components.styles :as components.styles]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.screens.network-settings.styles :as styles]
[status-im.utils.utils :as utils]
[status-im.utils.config :as config]))
@ -31,6 +35,9 @@
(defn navigate-to-network [network]
(re-frame/dispatch [:navigate-to :network-details {:networks/selected-network network}]))
(defn navigate-to-add-network []
(re-frame/dispatch [:edit-network]))
(defn wrap-mainnet-warning [network cb]
(fn []
(if (and config/mainnet-warning-enabled?
@ -44,9 +51,7 @@
(defn render-network [current-network]
(fn [{:keys [id name] :as network}]
(let [connected? (= id current-network)]
[react/touchable-highlight
{:on-press (wrap-mainnet-warning network navigate-to-network)
:accessibility-label :network-item}
[list/touchable-item (wrap-mainnet-warning network navigate-to-network)
[react/view styles/network-item
[network-icon connected? 40]
[react/view {:padding-horizontal 16}
@ -58,13 +63,25 @@
(i18n/label :t/connected)])]]])))
(views/defview network-settings []
(views/letsubs [{:keys [network networks]} [:get-current-account]]
[react/view {:flex 1}
(views/letsubs [{:keys [network]} [:get-current-account]
networks [:get-networks]]
[react/view components.styles/flex
[status-bar/status-bar]
[toolbar/simple-toolbar
(i18n/label :t/network-settings)]
[toolbar/toolbar {}
toolbar/default-nav-back
[toolbar/content-title (i18n/label :t/network-settings)]
[toolbar/actions
[(toolbar.actions/add false navigate-to-add-network)]]]
[react/view styles/wrapper
[list/flat-list {:data (vals networks)
:key-fn :id
:default-separator? true
:render-fn (render-network network)}]]]))
[list/section-list {:sections [{:title (i18n/label :t/main-networks)
:key :mainnet
:data (:mainnet networks)}
{:title (i18n/label :t/test-networks)
:key :testnet
:data (:testnet networks)}
{:title (i18n/label :t/custom-networks)
:key :custom
:data (:custom networks)}]
:key-fn :id
:default-separator? true
:render-fn (render-network network)}]]]))

View File

@ -9,20 +9,20 @@
(handlers/register-handler-fx
::save-wnode
(fn [{:keys [db now] :as cofx} [_ wnode]]
(let [network (ethereum/network->chain-keyword (:network db))
settings (get-in db [:account/account :settings])]
(fn [{:keys [db now] :as cofx} [_ chain wnode]]
(let [settings (get-in db [:account/account :settings])]
(handlers-macro/merge-fx cofx
{:dispatch [:logout]}
(accounts-events/update-settings (assoc-in settings [:wnode network] wnode))))))
(accounts-events/update-settings (assoc-in settings [:wnode chain] wnode))))))
(handlers/register-handler-fx
:connect-wnode
(fn [{:keys [db]} [_ wnode]]
(let [network (ethereum/network->chain-keyword (:network db))]
(let [network (get (:networks (:account/account db)) (:network db))
chain (ethereum/network->chain-keyword network)]
{:show-confirmation {:title (i18n/label :t/close-app-title)
:content (i18n/label :t/connect-wnode-content
{:name (get-in db [:inbox/wnodes network wnode :name])})
{:name (get-in db [:inbox/wnodes chain wnode :name])})
:confirm-button-text (i18n/label :t/close-app-button)
:on-accept #(dispatch [::save-wnode wnode])
:on-accept #(dispatch [::save-wnode chain wnode])
:on-cancel nil}})))

View File

@ -32,7 +32,10 @@
(fn [current-account]
(:signed-up? current-account)))
(reg-sub :network :network)
(reg-sub :network
:<- [:get-current-account]
(fn [current-account]
(get (:networks current-account) (:network current-account))))
(reg-sub :sync-state :sync-state)
(reg-sub :network-status :network-status)

View File

@ -41,6 +41,7 @@
[status-im.ui.screens.wallet.components.views :refer [contact-code recent-recipients recipient-qr-code]]
[status-im.ui.screens.network-settings.views :refer [network-settings]]
[status-im.ui.screens.network-settings.network-details.views :refer [network-details]]
[status-im.ui.screens.network-settings.edit-network.views :refer [edit-network]]
[status-im.ui.screens.offline-messaging-settings.views :refer [offline-messaging-settings]]
[status-im.ui.screens.currency-settings.views :refer [currency-settings]]
[status-im.ui.screens.browser.views :refer [browser]]
@ -151,6 +152,7 @@
:recover recover
:network-settings network-settings
:network-details network-details
:edit-network edit-network
:offline-messaging-settings offline-messaging-settings
:currency-settings currency-settings
:recent-recipients recent-recipients

View File

@ -102,7 +102,8 @@
(handlers/register-handler-fx
:update-wallet
(fn [{{:keys [web3 account/account network network-status] {:keys [address settings]} :account/account :as db} :db} _]
(let [chain (ethereum/network->chain-keyword network)
(let [network (get-in db [:account/account :networks network])
chain (ethereum/network->chain-keyword network)
mainnet? (= :mainnet chain)
symbols (get-in settings [:wallet :visible-tokens chain])
currency-id (or (get-in settings [:wallet :currency]) :usd)
@ -132,12 +133,13 @@
:update-transactions
(fn [{{:keys [network network-status web3] :as db} :db} _]
(when (not= network-status :offline)
(let [chain (ethereum/network->chain-keyword network)
(let [network (get-in db [:account/account :networks network])
chain (ethereum/network->chain-keyword network)
all-tokens (tokens/tokens-for chain)
token-addresses (map :address all-tokens)]
{:get-transactions {:account-id (get-in db [:account/account :address])
:token-addresses token-addresses
:network network
:network chain
:web3 web3
:success-event :update-transactions-success
:error-event :update-transactions-fail}

View File

@ -10,8 +10,9 @@
(handlers/register-handler-fx
:wallet.settings/toggle-visible-token
(fn [{{:keys [network account/account] :as db} :db :as cofx} [_ symbol checked?]]
(let [chain (ethereum/network->chain-keyword network)
(fn [{{:keys [account/account] :as db} :db :as cofx} [_ symbol checked?]]
(let [network (get (:networks account) (:network account))
chain (ethereum/network->chain-keyword network)
settings (get account :settings)
new-settings (update-in settings [:wallet :visible-tokens chain] #(toggle-checked % symbol checked?))]
(accounts/update-settings new-settings cofx))))

View File

@ -4,7 +4,8 @@
[status-im.utils.datetime :as datetime]
[status-im.utils.hex :as utils.hex]
[status-im.utils.money :as money]
[status-im.utils.transactions :as transactions]))
[status-im.utils.transactions :as transactions]
[status-im.utils.ethereum.core :as ethereum]))
(reg-sub :wallet.transactions/transactions-loading?
:<- [:wallet]
@ -125,7 +126,8 @@
:<- [:network]
(fn [[unsigned-transactions transactions current-transaction network]]
(let [transactions (merge transactions unsigned-transactions)
{:keys [gas-used gas-price hash timestamp type] :as transaction} (get transactions current-transaction)]
{:keys [gas-used gas-price hash timestamp type] :as transaction} (get transactions current-transaction)
chain (ethereum/network->chain-keyword network)]
(when transaction
(merge transaction
{:gas-price-eth (if gas-price (money/wei->str :eth gas-price) "-")
@ -140,7 +142,7 @@
:hash (i18n/label :not-applicable)}
{:cost (when gas-used
(money/wei->str :eth (money/fee-value gas-used gas-price)))
:url (transactions/get-transaction-details-url network hash)}))))))
:url (transactions/get-transaction-details-url chain hash)}))))))
(reg-sub :wallet.transactions.details/confirmations
:<- [:wallet.transactions/transaction-details]

View File

@ -3,7 +3,8 @@
[status-im.js-dependencies :as dependencies]
[status-im.utils.ethereum.tokens :as tokens]
[status-im.utils.money :as money]
[taoensso.timbre :as log]))
[taoensso.timbre :as log]
[status-im.utils.types :as types]))
;; IDs standardized in https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md#list-of-chain-ids
@ -21,8 +22,11 @@
(defn testnet? [id]
(contains? #{(chain-keyword->chain-id :testnet) (chain-keyword->chain-id :rinkeby)} id))
(defn network-with-upstream-rpc? [networks network]
(get-in networks [network :raw-config :UpstreamConfig :Enabled]))
(defn network-config [network]
(or (:raw-config network) (types/json->clj (:config network))))
(defn network-with-upstream-rpc? [network]
(get-in (network-config network) [:UpstreamConfig :Enabled]))
(def hex-prefix "0x")
@ -36,9 +40,11 @@
(when s
(.isAddress dependencies/Web3.prototype s)))
(defn network->chain-id [network]
(:NetworkId (network-config network)))
(defn network->chain-keyword [network]
(when network
(keyword (string/replace network "_rpc" ""))))
(chain-id->chain-keyword (network->chain-id network)))
(defn sha3 [s]
(.sha3 dependencies/Web3.prototype (str s)))

View File

@ -4,9 +4,9 @@
(defn- get-network-subdomain [network]
(case network
("testnet" "testnet_rpc") "ropsten"
("mainnet" "mainnet_rpc") nil
("rinkeby" "rinkeby_rpc") "rinkeby"))
(:testnet) "ropsten"
(:mainnet) nil
(:rinkeby) "rinkeby"))
(defn get-transaction-details-url [network hash]
(let [network-subdomain (get-network-subdomain network)]
@ -16,9 +16,9 @@
(defn- get-api-network-subdomain [network]
(case network
("testnet" "testnet_rpc") "api-ropsten"
("mainnet" "mainnet_rpc") "api"
("rinkeby" "rinkeby_rpc") "api-rinkeby"))
(:testnet) "api-ropsten"
(:mainnet) "api"
(:rinkeby) "api-rinkeby"))
(defn get-transaction-url [network account]
(let [network-subdomain (get-api-network-subdomain network)]