Add support for custom network upstreams
Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
parent
41900da38c
commit
24d5fabe2e
|
@ -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
|
||||
|
|
|
@ -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]})))
|
||||
|
|
|
@ -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, we’d like to point out the dangers. You’re 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"
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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}))
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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]}]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -167,6 +167,7 @@
|
|||
:group-chat-profile/editing?
|
||||
:networks/selected-network
|
||||
:networks/networks
|
||||
:networks/manage
|
||||
:node/after-start
|
||||
:node/after-stop
|
||||
:inbox/wnodes
|
||||
|
|
|
@ -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 []
|
||||
|
|
|
@ -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?))
|
||||
|
|
|
@ -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]}))
|
||||
|
|
@ -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})
|
|
@ -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))))
|
|
@ -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])}]]]]))
|
|
@ -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}}))))
|
||||
|
|
|
@ -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])}]]])]])))
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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)))))
|
||||
|
|
|
@ -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)}]]]))
|
||||
|
|
|
@ -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}})))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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)]
|
||||
|
|
Loading…
Reference in New Issue