[fix #3913] do not logout when changing mailserver

- do not logout and remove previous mailserver
from peers when changing mailserver
- rename wnode mailserver
- move transport.inbox to mailserver.core
- fix all subs and db keys

Signed-off-by: yenda <eric@status.im>
This commit is contained in:
yenda 2018-10-18 02:05:02 +02:00
parent ed16d9f191
commit a3b2bc1b87
No known key found for this signature in database
GPG Key ID: 0095623C0069DCE6
56 changed files with 1053 additions and 994 deletions

View File

Before

Width:  |  Height:  |  Size: 322 B

After

Width:  |  Height:  |  Size: 322 B

View File

@ -41,7 +41,7 @@
(spec/def :account/networks (spec/nilable :networks/networks)) (spec/def :account/networks (spec/nilable :networks/networks))
(spec/def :account/bootnodes (spec/nilable :bootnodes/bootnodes)) (spec/def :account/bootnodes (spec/nilable :bootnodes/bootnodes))
(spec/def :account/extensions (spec/nilable :extensions/extensions)) (spec/def :account/extensions (spec/nilable :extensions/extensions))
(spec/def :account/wnode (spec/nilable string?)) (spec/def :account/mailserver (spec/nilable string?))
(spec/def :account/settings (spec/nilable (spec/map-of keyword? any?))) (spec/def :account/settings (spec/nilable (spec/map-of keyword? any?)))
(spec/def :account/signing-phrase :global/not-empty-string) (spec/def :account/signing-phrase :global/not-empty-string)
(spec/def :account/mnemonic (spec/nilable string?)) (spec/def :account/mnemonic (spec/nilable string?))
@ -59,7 +59,7 @@
:account/installation-id] :account/installation-id]
:opt-un [:account/debug? :account/status :account/last-updated :opt-un [:account/debug? :account/status :account/last-updated
:account/email :account/signed-up? :account/network :account/email :account/signed-up? :account/network
:account/networks :account/settings :account/wnode :account/networks :account/settings :account/mailserver
:account/last-sign-in :account/sharing-usage-data? :account/dev-mode? :account/last-sign-in :account/sharing-usage-data? :account/dev-mode?
:account/seed-backed-up? :account/mnemonic :account/desktop-notifications? :account/seed-backed-up? :account/mnemonic :account/desktop-notifications?
:account/wallet-set-up-passed? :account/last-request :account/wallet-set-up-passed? :account/last-request

View File

@ -22,7 +22,7 @@
(def blocks-per-hour 120) (def blocks-per-hour 120)
(def one-earth-day 86400) (def one-earth-day 86400)
(def inbox-password "status-offline-inbox") (def mailserver-password "status-offline-inbox")
(def default-network config/default-network) (def default-network config/default-network)

View File

@ -1,5 +1,6 @@
(ns status-im.data-store.mailservers (ns status-im.data-store.mailservers
(:require [re-frame.core :as re-frame] (:require [cljs.tools.reader.edn :as edn]
[re-frame.core :as re-frame]
[status-im.data-store.realm.core :as core])) [status-im.data-store.realm.core :as core]))
(re-frame/reg-cofx (re-frame/reg-cofx
@ -27,3 +28,39 @@
(fn [realm] (fn [realm]
(core/delete realm (core/delete realm
(core/get-by-field realm :mailserver :id id)))) (core/get-by-field realm :mailserver :id id))))
(defn deserialize-mailserver-topic [serialized-mailserver-topic]
(-> serialized-mailserver-topic
(dissoc :topic)
(update :chat-ids edn/read-string)))
(re-frame/reg-cofx
:data-store/mailserver-topics
(fn [cofx _]
(assoc cofx
:data-store/mailserver-topics
(reduce (fn [acc {:keys [topic] :as mailserver-topic}]
(assoc acc topic (deserialize-mailserver-topic mailserver-topic)))
{}
(-> @core/account-realm
(core/get-all :mailserver-topic)
(core/all-clj :mailserver-topic))))))
(defn save-mailserver-topic-tx
"Returns tx function for saving mailserver topic"
[{:keys [topic mailserver-topic]}]
(fn [realm]
(core/create realm
:mailserver-topic
(-> mailserver-topic
(assoc :topic topic)
(update :chat-ids pr-str))
true)))
(defn delete-mailserver-topic-tx
"Returns tx function for deleting mailserver topic"
[topic]
(fn [realm]
(let [mailserver-topic (core/single
(core/get-by-field realm :mailserver-topic :topic topic))]
(core/delete realm mailserver-topic))))

View File

@ -2,6 +2,7 @@
(:require [status-im.data-store.realm.schemas.account.chat :as chat] (:require [status-im.data-store.realm.schemas.account.chat :as chat]
[status-im.data-store.realm.schemas.account.transport :as transport] [status-im.data-store.realm.schemas.account.transport :as transport]
[status-im.data-store.realm.schemas.account.transport-inbox-topic :as transport-inbox-topic] [status-im.data-store.realm.schemas.account.transport-inbox-topic :as transport-inbox-topic]
[status-im.data-store.realm.schemas.account.mailserver-topic :as mailserver-topic]
[status-im.data-store.realm.schemas.account.contact :as contact] [status-im.data-store.realm.schemas.account.contact :as contact]
[status-im.data-store.realm.schemas.account.message :as message] [status-im.data-store.realm.schemas.account.message :as message]
[status-im.data-store.realm.schemas.account.user-status :as user-status] [status-im.data-store.realm.schemas.account.user-status :as user-status]
@ -212,6 +213,19 @@
browser/v8 browser/v8
dapp-permissions/v9]) dapp-permissions/v9])
(def v22 [chat/v8
transport/v7
mailserver-topic/v1
contact/v2
message/v7
mailserver/v11
user-status/v1
membership-update/v1
installation/v2
local-storage/v1
browser/v8
dapp-permissions/v9])
;; put schemas ordered by version ;; put schemas ordered by version
(def schemas [{:schema v1 (def schemas [{:schema v1
:schemaVersion 1 :schemaVersion 1
@ -275,4 +289,7 @@
:migration migrations/v20} :migration migrations/v20}
{:schema v21 {:schema v21
:schemaVersion 21 :schemaVersion 21
:migration migrations/v21}]) :migration migrations/v21}
{:schema v22
:schemaVersion 22
:migration migrations/v22}])

View File

@ -0,0 +1,7 @@
(ns status-im.data-store.realm.schemas.account.mailserver-topic)
(def v1 {:name :mailserver-topic
:primaryKey :topic
:properties {:topic :string
:chat-ids :string
:last-request {:type :int :default 1}}})

View File

@ -130,3 +130,6 @@
(defn v21 [old-realm new-realm] (defn v21 [old-realm new-realm]
(log/debug "migrating v21 account database")) (log/debug "migrating v21 account database"))
(defn v22 [old-realm new-realm]
(log/debug "migrating v22 account database"))

View File

@ -52,6 +52,8 @@
extension/v12 extension/v12
account/v13]) account/v13])
(def v14 v13)
;; put schemas ordered by version ;; put schemas ordered by version
(def schemas [{:schema v1 (def schemas [{:schema v1
:schemaVersion 1 :schemaVersion 1
@ -91,4 +93,7 @@
:migration migrations/v12} :migration migrations/v12}
{:schema v13 {:schema v13
:schemaVersion 13 :schemaVersion 13
:migration migrations/v13}]) :migration migrations/v13}
{:schema v14
:schemaVersion 14
:migration migrations/v14}])

View File

@ -93,3 +93,18 @@
(defn v13 [old-realm new-realm] (defn v13 [old-realm new-realm]
(log/debug "migrating base database v13: " old-realm new-realm)) (log/debug "migrating base database v13: " old-realm new-realm))
(defn v14
"Rename wnode to mailserver in account settings"
[old-realm new-realm]
(log/debug "migrating accounts schema v14")
(let [accounts (.objects new-realm "account")]
(dotimes [i (.-length accounts)]
(let [account (aget accounts i)
{:keys [wnode] :as old-settings} (deserialize (aget account "settings"))
new-settings (when wnode
(-> old-settings
(dissoc :wnode)
(assoc :mailserver wnode)))
updated (serialize new-settings)]
(aset account "settings" updated)))))

View File

@ -44,39 +44,3 @@
(let [transport (core/single (let [transport (core/single
(core/get-by-field realm :transport :chat-id chat-id))] (core/get-by-field realm :transport :chat-id chat-id))]
(core/delete realm transport)))) (core/delete realm transport))))
(defn deserialize-inbox-topic [serialized-inbox-topic]
(-> serialized-inbox-topic
(dissoc :topic)
(update :chat-ids edn/read-string)))
(re-frame/reg-cofx
:data-store/transport-inbox-topics
(fn [cofx _]
(assoc cofx
:data-store/transport-inbox-topics
(reduce (fn [acc {:keys [topic] :as inbox-topic}]
(assoc acc topic (deserialize-inbox-topic inbox-topic)))
{}
(-> @core/account-realm
(core/get-all :transport-inbox-topic)
(core/all-clj :transport-inbox-topic))))))
(defn save-transport-inbox-topic-tx
"Returns tx function for saving transport inbox topic"
[{:keys [topic inbox-topic]}]
(fn [realm]
(core/create realm
:transport-inbox-topic
(-> inbox-topic
(assoc :topic topic)
(update :chat-ids pr-str))
true)))
(defn delete-transport-inbox-topic-tx
"Returns tx function for deleting transport inbox-topic"
[topic]
(fn [realm]
(let [transport-inbox-topic (core/single
(core/get-by-field realm :transport-inbox-topic :topic topic))]
(core/delete realm transport-inbox-topic))))

View File

@ -33,7 +33,6 @@
[status-im.qr-scanner.core :as qr-scanner] [status-im.qr-scanner.core :as qr-scanner]
[status-im.search.core :as search] [status-im.search.core :as search]
[status-im.signals.core :as signals] [status-im.signals.core :as signals]
[status-im.transport.inbox :as inbox]
[status-im.transport.message.core :as transport.message] [status-im.transport.message.core :as transport.message]
[status-im.ui.screens.currency-settings.models [status-im.ui.screens.currency-settings.models
:as :as
@ -99,7 +98,7 @@
(re-frame/inject-cofx :data-store/get-all-installations) (re-frame/inject-cofx :data-store/get-all-installations)
(re-frame/inject-cofx :data-store/get-all-mailservers) (re-frame/inject-cofx :data-store/get-all-mailservers)
(re-frame/inject-cofx :data-store/transport) (re-frame/inject-cofx :data-store/transport)
(re-frame/inject-cofx :data-store/transport-inbox-topics) (re-frame/inject-cofx :data-store/mailserver-topics)
(re-frame/inject-cofx :data-store/all-browsers) (re-frame/inject-cofx :data-store/all-browsers)
(re-frame/inject-cofx :data-store/all-dapp-permissions)] (re-frame/inject-cofx :data-store/all-dapp-permissions)]
(fn [cofx [_ address]] (fn [cofx [_ address]]
@ -289,7 +288,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/delete-confirmed :mailserver.ui/delete-confirmed
(fn [cofx [_ mailserver-id]] (fn [cofx [_ mailserver-id]]
(mailserver/delete mailserver-id cofx))) (mailserver/delete cofx mailserver-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/delete-pressed :mailserver.ui/delete-pressed
@ -311,6 +310,32 @@
(fn [cofx [_ current-fleet mailserver-id]] (fn [cofx [_ current-fleet mailserver-id]]
(mailserver/save-settings cofx current-fleet mailserver-id))) (mailserver/save-settings cofx current-fleet mailserver-id)))
(handlers/register-handler-fx
:mailserver.ui/reconnect-mailserver-pressed
(fn [cofx [_ args]]
(mailserver/connect-to-mailserver cofx)))
(handlers/register-handler-fx
:mailserver/check-connection-timeout
(fn [cofx _]
(mailserver/check-connection cofx)))
(handlers/register-handler-fx
:mailserver.callback/generate-mailserver-symkey-success
(fn [cofx [_ mailserver sym-key-id]]
(mailserver/add-mailserver-sym-key cofx mailserver sym-key-id)))
(handlers/register-handler-fx
:mailserver.callback/mark-trusted-peer-success
(fn [cofx _]
(mailserver/add-mailserver-trusted cofx)))
(handlers/register-handler-fx
:mailserver.callback/mark-trusted-peer-error
(fn [cofx [_ error]]
(log/error "Error on mark-trusted-peer: " error)
(mailserver/check-connection cofx)))
;; network module ;; network module
(handlers/register-handler-fx (handlers/register-handler-fx
@ -996,34 +1021,6 @@
(fn [cofx] (fn [cofx]
(browser/open-url cofx "names.statusnet.eth"))) (browser/open-url cofx "names.statusnet.eth")))
;; inbox module
(handlers/register-handler-fx
:inbox.ui/reconnect-mailserver-pressed
(fn [cofx [_ args]]
(inbox/connect-to-mailserver cofx)))
(handlers/register-handler-fx
:inbox/check-connection-timeout
(fn [cofx _]
(inbox/check-connection cofx)))
(handlers/register-handler-fx
:inbox.callback/generate-mailserver-symkey-success
(fn [cofx [_ wnode sym-key-id]]
(inbox/add-mailserver-sym-key cofx wnode sym-key-id)))
(handlers/register-handler-fx
:inbox.callback/mark-trusted-peer-success
(fn [cofx _]
(inbox/add-mailserver-trusted cofx)))
(handlers/register-handler-fx
:inbox.callback/mark-trusted-peer-error
(fn [cofx [_ error]]
(log/error "Error on mark-trusted-peer: " error)
(inbox/check-connection cofx)))
;; transport module ;; transport module
(handlers/register-handler-fx (handlers/register-handler-fx

View File

@ -28,23 +28,23 @@
[(slurp "resources/config/fleets.json") [(slurp "resources/config/fleets.json")
(slurp "resources/config/fleets-les.json")]))) (slurp "resources/config/fleets-les.json")])))
(defn format-wnode (defn format-mailserver
[wnode address] [mailserver address]
{:id wnode {:id mailserver
:name (name wnode) :name (name mailserver)
:password constants/inbox-password :password constants/mailserver-password
:address address}) :address address})
(defn format-wnodes (defn format-mailservers
[wnodes] [mailservers]
(reduce (fn [acc [wnode address]] (reduce (fn [acc [mailserver address]]
(assoc acc wnode (format-wnode wnode address))) (assoc acc mailserver (format-mailserver mailserver address)))
{} {}
wnodes)) mailservers))
(def default-wnodes (def default-mailservers
(reduce (fn [acc [fleet node-by-type]] (reduce (fn [acc [fleet node-by-type]]
(assoc acc fleet (format-wnodes (:mail node-by-type)))) (assoc acc fleet (format-mailservers (:mail node-by-type))))
{} {}
fleets)) fleets))

View File

@ -1,13 +1,485 @@
(ns status-im.mailserver.core (ns ^{:doc "Mailserver events and API"}
(:require [clojure.string :as string] status-im.mailserver.core
[re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.accounts.db :as accounts.db]
[status-im.data-store.core :as data-store]
[status-im.fleet.core :as fleet]
[status-im.native-module.core :as status]
[status-im.transport.utils :as transport.utils]
[status-im.utils.fx :as fx]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log]
[status-im.transport.db :as transport.db]
[clojure.string :as string]
[status-im.data-store.mailservers :as data-store.mailservers] [status-im.data-store.mailservers :as data-store.mailservers]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.fleet.core :as fleet]
[status-im.accounts.update.core :as accounts.update] [status-im.accounts.update.core :as accounts.update]
[status-im.utils.fx :as fx]
[status-im.ui.screens.navigation :as navigation])) [status-im.ui.screens.navigation :as navigation]))
;; How do mailserver work ?
;;
;; - We send a request to the mailserver, we are only interested in the
;; messages since `last-request` up to the last seven days
;; and the last 24 hours for topics that were just joined
;; - The mailserver doesn't directly respond to the request and
;; instead we start receiving messages in the filters for the requested
;; topics.
;; - If the mailserver was not ready when we tried for instance to request
;; the history of a topic after joining a chat, the request will be done
;; as soon as the mailserver becomes available
(def one-day (* 24 3600))
(def seven-days (* 7 one-day))
(def maximum-number-of-attempts 2)
(def request-timeout 30)
(def connection-timeout
"Time after which mailserver connection is considered to have failed"
10000)
(defn connected? [{:keys [db]} id]
(= (:mailserver/current-id db) id))
(defn fetch [{:keys [db] :as cofx} id]
(get-in db [:mailserver/mailservers (fleet/current-fleet db) id]))
(defn fetch-current [{:keys [db] :as cofx}]
(fetch cofx (:mailserver/current-id db)))
(defn preferred-mailserver-id [{:keys [db] :as cofx}]
(get-in db [:account/account :settings :mailserver (fleet/current-fleet db)]))
(defn- round-robin
"Find the choice and pick the next one, default to first if not found"
[choices current-id]
(let [next-index (reduce
(fn [index choice]
(if (= current-id choice)
(reduced (inc index))
(inc index)))
0
choices)]
(nth choices
(mod
next-index
(count choices)))))
(defn selected-or-random-id
"Use the preferred mailserver if set & exists, otherwise picks one randomly
if current-id is not set, else round-robin"
[{:keys [db] :as cofx}]
(let [current-fleet (fleet/current-fleet db)
current-id (:mailserver/current-id db)
preference (preferred-mailserver-id cofx)
choices (-> db :mailserver/mailservers current-fleet keys)]
(if (and preference
(fetch cofx preference))
preference
(if current-id
(round-robin choices current-id)
(rand-nth choices)))))
(fx/defn set-current-mailserver
[{:keys [db] :as cofx}]
{:db (assoc db :mailserver/current-id
(selected-or-random-id cofx))})
(fx/defn add-custom-mailservers
[{:keys [db]} mailservers]
{:db (reduce (fn [db {:keys [id fleet] :as mailserver}]
(assoc-in db [:mailserver/mailservers fleet id]
(-> mailserver
(dissoc :fleet)
(assoc :user-defined true))))
db
mailservers)})
(defn- parse-json
;; NOTE(dmitryn) Expects JSON response like:
;; {"error": "msg"} or {"result": true}
[s]
(try
(let [res (-> s
js/JSON.parse
(js->clj :keywordize-keys true))]
;; NOTE(dmitryn): AddPeer() may return {"error": ""}
;; assuming empty error is a success response
;; by transforming {"error": ""} to {:result true}
(if (and (:error res)
(= (:error res) ""))
{:result true}
res))
(catch :default e
{:error (.-message e)})))
(defn- response-handler [success-fn error-fn]
(fn handle-response
([response]
(let [{:keys [error result]} (parse-json response)]
(handle-response error result)))
([error result]
(if error
(error-fn error)
(success-fn result)))))
(defn add-peer! [enode]
(status/add-peer enode
(response-handler #(log/debug "mailserver: add-peer success" %)
#(log/error "mailserver: add-peer error" %))))
(defn remove-peer! [enode]
(let [args {:jsonrpc "2.0"
:id 2
:method "admin_removePeer"
:params [enode]}
payload (.stringify js/JSON (clj->js args))]
(status/call-private-rpc payload
(response-handler #(log/debug "mailserver: remove-peer success" %)
#(log/error "mailserver: remove-peer error" %)))))
(re-frame/reg-fx
:mailserver/add-peer
(fn [enode]
(add-peer! enode)))
(re-frame/reg-fx
:mailserver/remove-peer
(fn [enode]
(remove-peer! enode)))
(defn mark-trusted-peer! [web3 enode]
(.markTrustedPeer (transport.utils/shh web3)
enode
(fn [error response]
(if error
(re-frame/dispatch [:mailserver.callback/mark-trusted-peer-error error])
(re-frame/dispatch [:mailserver.callback/mark-trusted-peer-success response])))))
(re-frame/reg-fx
:mailserver/mark-trusted-peer
(fn [{:keys [address web3]}]
(mark-trusted-peer! web3 address)))
(fx/defn generate-mailserver-symkey
[{:keys [db] :as cofx} {:keys [password id] :as mailserver}]
(let [current-fleet (fleet/current-fleet db)]
{:db (assoc-in db [:mailserver/mailservers current-fleet id :generating-sym-key?] true)
:shh/generate-sym-key-from-password
[{:password password
:web3 (:web3 db)
:on-success (fn [_ sym-key-id]
(re-frame/dispatch [:mailserver.callback/generate-mailserver-symkey-success mailserver sym-key-id]))
:on-error #(log/error "mailserver: get-sym-key error" %)}]}))
(defn registered-peer?
"truthy if the enode is a registered peer"
[peers enode]
(let [peer-ids (into #{} (map :id) peers)
enode-id (transport.utils/extract-enode-id enode)]
(contains? peer-ids enode-id)))
(defn update-mailserver-state [db state]
(assoc db :mailserver/state state))
(fx/defn mark-trusted-peer
[{:keys [db] :as cofx}]
(let [{:keys [address sym-key-id generating-sym-key?] :as mailserver} (fetch-current cofx)]
(fx/merge cofx
{:db (update-mailserver-state db :added)
:mailserver/mark-trusted-peer {:web3 (:web3 db)
:address address}}
(when-not (or sym-key-id generating-sym-key?)
(generate-mailserver-symkey mailserver)))))
(fx/defn add-peer
[{:keys [db] :as cofx}]
(let [{:keys [address sym-key-id generating-sym-key?] :as mailserver} (fetch-current cofx)]
(fx/merge cofx
{:db (-> db
(update-mailserver-state :connecting)
(update :mailserver/connection-checks inc))
:mailserver/add-peer address
:utils/dispatch-later [{:ms connection-timeout
:dispatch [:mailserver/check-connection-timeout]}]}
(when-not (or sym-key-id generating-sym-key?)
(generate-mailserver-symkey mailserver)))))
(fx/defn connect-to-mailserver
"Add mailserver as a peer using `::add-peer` cofx and generate sym-key when
it doesn't exists
Peer summary will change and we will receive a signal from status go when
this is successful
A connection-check is made after `connection timeout` is reached and
mailserver-state is changed to error if it is not connected by then"
[{:keys [db] :as cofx}]
(let [{:keys [address] :as mailserver} (fetch-current cofx)
{:keys [peers-summary]} db
added? (registered-peer? peers-summary
address)]
(fx/merge cofx
{:db (dissoc db :mailserver/current-request)}
(if added?
(mark-trusted-peer)
(add-peer)))))
(fx/defn peers-summary-change
"There is only 2 summary changes that require mailserver action:
- mailserver disconnected: we try to reconnect
- mailserver connected: we mark the mailserver as trusted peer"
[{:keys [db] :as cofx} previous-summary]
(when (:account/account db)
(let [{:keys [peers-summary peers-count]} db
{:keys [address sym-key-id] :as mailserver} (fetch-current cofx)
mailserver-was-registered? (registered-peer? previous-summary
address)
mailserver-is-registered? (registered-peer? peers-summary
address)
mailserver-added? (and mailserver-is-registered?
(not mailserver-was-registered?))
mailserver-removed? (and mailserver-was-registered?
(not mailserver-is-registered?))]
(cond
mailserver-added?
(mark-trusted-peer cofx)
mailserver-removed?
(connect-to-mailserver cofx)))))
(defn request-messages! [web3 {:keys [sym-key-id address]} {:keys [topics to from]}]
(log/info "mailserver: request-messages for: "
" topics " topics
" from " from
" to " to)
(.requestMessages (transport.utils/shh web3)
(clj->js {:topics topics
:mailServerPeer address
:symKeyID sym-key-id
:timeout request-timeout
:from from
:to to})
(fn [error request-id]
(if-not error
(log/info "mailserver: messages request success for topic " topics "from" from "to" to)
(log/error "mailserver: messages request error for topic " topics ": " error)))))
(re-frame/reg-fx
:mailserver/request-messages
(fn [{:keys [web3 mailserver request]}]
(request-messages! web3 mailserver request)))
(defn get-mailserver-when-ready
"return the mailserver if the mailserver is ready"
[{:keys [db] :as cofx}]
(let [{:keys [sym-key-id] :as mailserver} (fetch-current cofx)
mailserver-state (:mailserver/state db)]
(when (and (= :connected mailserver-state)
sym-key-id)
mailserver)))
(defn split-request-per-day
"NOTE: currently the mailserver is only accepting requests for a span
of 24 hours, so we split requests per 24h spans if the last request was
done more than 24h ago"
[now-in-s [last-request topics]]
(let [days (conj
(into [] (range (max last-request
(- now-in-s one-day))
now-in-s
one-day))
now-in-s)
day-ranges (map vector days (rest days))]
(for [[from to] day-ranges]
{:topics topics
:from from
:to to})))
(defn prepare-messages-requests
[{:keys [db now] :as cofx} request-to]
(let [web3 (:web3 db)]
(remove nil?
(mapcat (partial split-request-per-day request-to)
(reduce (fn [acc [topic {:keys [last-request]}]]
(update acc last-request conj topic))
{}
(:mailserver/topics db))))))
(fx/defn process-next-messages-request
[{:keys [db now] :as cofx}]
(when (and (transport.db/all-filters-added? cofx)
(not (:mailserver/current-request db)))
(when-let [mailserver (get-mailserver-when-ready cofx)]
(let [request-to (or (:mailserver/request-to db)
(quot now 1000))
requests (prepare-messages-requests cofx request-to)
web3 (:web3 db)]
(if-let [request (first requests)]
{:db (assoc db
:mailserver/pending-requests (count requests)
:mailserver/current-request request
:mailserver/request-to request-to)
:mailserver/request-messages {:web3 web3
:mailserver mailserver
:request request}}
{:db (dissoc db
:mailserver/pending-requests
:mailserver/request-to)})))))
(fx/defn add-mailserver-trusted
"the current mailserver has been trusted
update mailserver status to `:connected` and request messages
if mailserver is ready"
[{:keys [db] :as cofx}]
(fx/merge cofx
{:db (update-mailserver-state db :connected)}
(process-next-messages-request)))
(fx/defn add-mailserver-sym-key
"the current mailserver sym-key has been generated
add sym-key to the mailserver in app-db and request messages if
mailserver is ready"
[{:keys [db] :as cofx} {:keys [id]} sym-key-id]
(let [current-fleet (fleet/current-fleet db)]
(fx/merge cofx
{:db (-> db
(assoc-in [:mailserver/mailservers current-fleet id :sym-key-id] sym-key-id)
(update-in [:mailserver/mailservers current-fleet id] dissoc :generating-sym-key?))}
(process-next-messages-request))))
(fx/defn change-mailserver
"mark mailserver status as `:error` if custom mailserver is used
otherwise try to reconnect to another mailserver"
[{:keys [db] :as cofx}]
(if (preferred-mailserver-id cofx)
{:db (update-mailserver-state db :error)}
(let [{:keys [address]} (fetch-current cofx)]
(fx/merge cofx
{:mailserver/remove-peer address}
(set-current-mailserver)
(connect-to-mailserver)))))
(fx/defn check-connection
"connection-checks counter is used to prevent changing
mailserver on flaky connections
if there is more than one connection check pending
decrement the connection check counter
else
change mailserver if mailserver is connected"
[{:keys [db] :as cofx}]
(if (zero? (dec (:mailserver/connection-checks db)))
(fx/merge cofx
{:db (dissoc db :mailserver/connection-checks)}
(when (= :connecting (:mailserver/state db))
(change-mailserver cofx)))
{:db (update db :mailserver/connection-checks dec)}))
(fx/defn reset-request-to
[{:keys [db]}]
{:db (dissoc db :mailserver/request-to)})
(fx/defn network-connection-status-changed
"when host reconnects, reset request-to and
reconnect to mailserver"
[{:keys [db] :as cofx} is-connected?]
(when (and (accounts.db/logged-in? cofx)
is-connected?)
(fx/merge cofx
(reset-request-to)
(connect-to-mailserver))))
(fx/defn remove-chat-from-mailserver-topic
"if the chat is the only chat of the mailserver topic delete the mailserver topic
and process-next-messages-requests again to remove pending request for that topic
otherwise remove the chat-id of the chat from the mailserver topic and save"
[{:keys [db now] :as cofx} chat-id]
(let [topic (get-in db [:transport/chats chat-id :topic])
{:keys [chat-ids] :as mailserver-topic} (update (get-in db [:mailserver/topics topic])
:chat-ids
disj chat-id)]
(if (empty? chat-ids)
(fx/merge cofx
{:db (update db :mailserver/topics dissoc topic)
:data-store/tx [(data-store.mailservers/delete-mailserver-topic-tx topic)]}
(process-next-messages-request))
{:db (assoc-in db [:mailserver/topics topic] mailserver-topic)
:data-store/tx [(data-store.mailservers/save-mailserver-topic-tx
{:topic topic
:mailserver-topic mailserver-topic})]})))
(defn get-updated-mailserver-topics [db topics last-request]
(reduce (fn [acc topic]
(if-let [mailserver-topic (some-> (get-in db [:mailserver/topics topic])
(assoc :last-request last-request))]
(assoc acc topic mailserver-topic)
acc))
{}
topics))
(fx/defn update-mailserver-topics
"TODO: add support for cursors
if there is a cursor, do not update `last-request`"
[{:keys [db now] :as cofx} {:keys [request-id]}]
(when-let [request (get db :mailserver/current-request)]
(let [{:keys [from to topics]} request
mailserver-topics (get-updated-mailserver-topics db topics to)]
(log/info "mailserver: message request " request-id
"completed for mailserver topics" topics "from" from "to" to)
(if (empty? mailserver-topics)
;; when topics were deleted (filter was removed while request was pending)
(fx/merge cofx
{:db (dissoc db :mailserver/current-request)}
(process-next-messages-request))
(fx/merge cofx
{:db (-> db
(dissoc :mailserver/current-request)
(update :mailserver/topics merge mailserver-topics))
:data-store/tx (mapv (fn [[topic mailserver-topic]]
(data-store.mailservers/save-mailserver-topic-tx
{:topic topic
:mailserver-topic mailserver-topic}))
mailserver-topics)}
(process-next-messages-request))))))
(fx/defn upsert-mailserver-topic
"if the topic didn't exist
create the topic
else if chat-id is not in the topic
add the chat-id to the topic and reset last-request
there was no filter for the chat and messages for that
so the whole history for that topic needs to be re-fetched"
[{:keys [db] :as cofx} {:keys [topic chat-id]}]
(let [{:keys [chat-ids last-request] :as current-mailserver-topic}
(get-in db [:mailserver/topics topic] {:chat-ids #{}})]
(when-let [mailserver-topic (when-not (chat-ids chat-id)
(-> current-mailserver-topic
(assoc :last-request 1)
(update :chat-ids conj chat-id)))]
(fx/merge cofx
{:db (assoc-in db [:mailserver/topics topic] mailserver-topic)
:data-store/tx [(data-store.mailservers/save-mailserver-topic-tx
{:topic topic
:mailserver-topic mailserver-topic})]}))))
(fx/defn resend-request
[{:keys [db] :as cofx} {:keys [request-id]}]
(if (<= maximum-number-of-attempts
(get-in db [:mailserver/current-request :attemps]))
(fx/merge cofx
{:db (update db :mailserver/current-request dissoc :attemps)}
(change-mailserver))
(when-let [mailserver (get-mailserver-when-ready cofx)]
(let [{:keys [topics from to] :as request} (get db :mailserver/current-request)
web3 (:web3 db)]
(log/info "mailserver: message request " request-id "expired for mailserver topic" topics "from" from "to" to)
{:db (update-in db [:mailserver/current-request :attemps] inc)
:mailserver/request-messages {:web3 web3
:mailserver mailserver
:request request}}))))
(fx/defn initialize-mailserver
[cofx custom-mailservers]
(fx/merge cofx
(add-custom-mailservers custom-mailservers)
(set-current-mailserver)))
(def enode-address-regex #"enode://[a-zA-Z0-9]+\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})") (def enode-address-regex #"enode://[a-zA-Z0-9]+\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})")
(def enode-url-regex #"enode://[a-zA-Z0-9]+:(.+)\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})") (def enode-url-regex #"enode://[a-zA-Z0-9]+:(.+)\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})")
@ -30,7 +502,7 @@
(fx/defn set-input [{:keys [db]} input-key value] (fx/defn set-input [{:keys [db]} input-key value]
{:db (update {:db (update
db db
:mailservers/manage :mailserver.edit/mailserver
assoc assoc
input-key input-key
{:value value {:value value
@ -52,74 +524,8 @@
:id id :id id
:name mailserver-name)) :name mailserver-name))
(defn connected? [{:keys [db]} id]
(= (:inbox/current-id db) id))
(defn fetch [{:keys [db] :as cofx} id]
(get-in db [:inbox/wnodes (fleet/current-fleet db) id]))
(defn fetch-current [{:keys [db] :as cofx}]
(fetch cofx (:inbox/current-id db)))
(defn preferred-mailserver-id [{:keys [db] :as cofx}]
(get-in db [:account/account :settings :wnode (fleet/current-fleet db)]))
(defn- round-robin
"Find the choice and pick the next one, default to first if not found"
[choices current-id]
(let [next-index (reduce
(fn [index choice]
(if (= current-id choice)
(reduced (inc index))
(inc index)))
0
choices)]
(nth choices
(mod
next-index
(count choices)))))
(defn selected-or-random-id
"Use the preferred mailserver if set & exists, otherwise picks one randomly
if current-id is not set, else round-robin"
[{:keys [db] :as cofx}]
(let [current-fleet (fleet/current-fleet db)
current-id (:inbox/current-id db)
preference (preferred-mailserver-id cofx)
choices (-> db :inbox/wnodes current-fleet keys)]
(if (and preference
(fetch cofx preference))
preference
(if current-id
(round-robin choices current-id)
(rand-nth choices)))))
(def default? (comp not :user-defined fetch)) (def default? (comp not :user-defined fetch))
(fx/defn delete
[{:keys [db] :as cofx} id]
(merge (when-not (or
(default? cofx id)
(connected? cofx id))
{:db (update-in db [:inbox/wnodes (fleet/current-fleet db)] dissoc id)
:data-store/tx [(data-store.mailservers/delete-tx id)]})
{:dispatch [:navigate-back]}))
(fx/defn set-current-mailserver
[{:keys [db] :as cofx}]
{:db (assoc db :inbox/current-id
(selected-or-random-id cofx))})
(fx/defn add-custom-mailservers
[{:keys [db]} mailservers]
{:db (reduce (fn [db {:keys [id fleet] :as mailserver}]
(assoc-in db [:inbox/wnodes fleet id]
(-> mailserver
(dissoc :fleet)
(assoc :user-defined true))))
db
mailservers)})
(fx/defn edit [{:keys [db] :as cofx} id] (fx/defn edit [{:keys [db] :as cofx} id]
(let [{:keys [id (let [{:keys [id
address address
@ -133,9 +539,9 @@
(navigation/navigate-to-cofx :edit-mailserver nil)))) (navigation/navigate-to-cofx :edit-mailserver nil))))
(fx/defn upsert (fx/defn upsert
[{{:mailservers/keys [manage] :account/keys [account] :as db} :db [{{:mailserver.edit/keys [mailserver] :account/keys [account] :as db} :db
random-id-generator :random-id-generator :as cofx}] random-id-generator :random-id-generator :as cofx}]
(let [{:keys [name url id]} manage (let [{:keys [name url id]} mailserver
current-fleet (fleet/current-fleet db) current-fleet (fleet/current-fleet db)
mailserver (build mailserver (build
(or (:value id) (or (:value id)
@ -144,8 +550,8 @@
(:value url)) (:value url))
current (connected? cofx (:id mailserver))] current (connected? cofx (:id mailserver))]
{:db (-> db {:db (-> db
(dissoc :mailservers/manage) (dissoc :mailserver.edit/mailserver)
(assoc-in [:inbox/wnodes current-fleet (:id mailserver)] mailserver)) (assoc-in [:mailserver/mailservers current-fleet (:id mailserver)] mailserver))
:data-store/tx [{:transaction :data-store/tx [{:transaction
(data-store.mailservers/save-tx (assoc (data-store.mailservers/save-tx (assoc
mailserver mailserver
@ -155,13 +561,22 @@
:success-event (when current [:accounts.logout.ui/logout-confirmed])}] :success-event (when current [:accounts.logout.ui/logout-confirmed])}]
:dispatch [:navigate-back]})) :dispatch [:navigate-back]}))
(fx/defn delete
[{:keys [db] :as cofx} id]
(merge (when-not (or
(default? cofx id)
(connected? cofx id))
{:db (update-in db [:mailserver/mailservers (fleet/current-fleet db)] dissoc id)
:data-store/tx [(data-store.mailservers/delete-tx id)]})
{:dispatch [:navigate-back]}))
(fx/defn show-connection-confirmation (fx/defn show-connection-confirmation
[{:keys [db]} mailserver-id] [{:keys [db]} mailserver-id]
(let [current-fleet (fleet/current-fleet db)] (let [current-fleet (fleet/current-fleet db)]
{:ui/show-confirmation {:ui/show-confirmation
{:title (i18n/label :t/close-app-title) {:title (i18n/label :t/close-app-title)
:content (i18n/label :t/connect-wnode-content :content (i18n/label :t/connect-mailserver-content
{:name (get-in db [:inbox/wnodes current-fleet mailserver-id :name])}) {:name (get-in db [:mailserver/mailservers current-fleet mailserver-id :name])})
:confirm-button-text (i18n/label :t/close-app-button) :confirm-button-text (i18n/label :t/close-app-button)
:on-accept #(re-frame/dispatch [:mailserver.ui/connect-confirmed current-fleet mailserver-id]) :on-accept #(re-frame/dispatch [:mailserver.ui/connect-confirmed current-fleet mailserver-id])
:on-cancel nil}})) :on-cancel nil}}))
@ -174,14 +589,18 @@
:confirm-button-text (i18n/label :t/delete-mailserver) :confirm-button-text (i18n/label :t/delete-mailserver)
:on-accept #(re-frame/dispatch [:mailserver.ui/delete-confirmed mailserver-id])}}) :on-accept #(re-frame/dispatch [:mailserver.ui/delete-confirmed mailserver-id])}})
(fx/defn save-settings
[{:keys [db] :as cofx} current-fleet mailserver-id]
(let [settings (get-in db [:account/account :settings])]
(accounts.update/update-settings cofx
(assoc-in settings [:wnode current-fleet] mailserver-id)
{:success-event [:accounts.update.callback/save-settings-success]})))
(fx/defn set-url-from-qr (fx/defn set-url-from-qr
[cofx url] [cofx url]
(assoc (set-input :url url cofx) (assoc (set-input cofx :url url)
:dispatch [:navigate-back])) :dispatch [:navigate-back]))
(fx/defn save-settings
[{:keys [db] :as cofx} current-fleet mailserver-id]
(let [{:keys [address]} (fetch-current cofx)
settings (get-in db [:account/account :settings])]
(fx/merge cofx
{:db (assoc db :mailserver/current-id mailserver-id)
:mailserver/remove-peer address}
(connect-to-mailserver)
(accounts.update/update-settings (assoc-in settings [:mailserver current-fleet] mailserver-id)
{}))))

View File

@ -0,0 +1,42 @@
(ns status-im.mailserver.db
(:require [status-im.mailserver.core :as mailserver]
[cljs.spec.alpha :as spec]))
(spec/def :mailserver/state (spec/nilable #{:disconnected :connecting :added :connected :error}))
(spec/def :mailserver/current-id (spec/nilable keyword?))
(spec/def :mailserver/address (spec/and string? mailserver/valid-enode-address?))
(spec/def :mailserver/name :global/not-empty-string)
(spec/def :mailserver/id keyword?)
(spec/def :mailserver/user-defined boolean?)
(spec/def :mailserver/password :global/not-empty-string)
(spec/def :mailserver/sym-key-id string?)
(spec/def :mailserver/generating-sym-key? boolean?)
(spec/def :mailserver/mailserver (spec/keys :req-un [:mailserver/address :mailserver/name :mailserver/id]
:opt-un [:mailserver/sym-key-id
:mailserver/generating-sym-key?
:mailserver/user-defined
:mailserver/password]))
(spec/def :mailserver/mailservers (spec/nilable (spec/map-of keyword? (spec/map-of :mailserver/id :mailserver/mailserver))))
(spec/def :request/from pos-int?)
(spec/def :request/to pos-int?)
(spec/def :request/attemps int?)
(spec/def :request/cursor :global/not-empty-string)
(spec/def :mailserver.topic/last-request pos-int?)
(spec/def :mailserver.topic/started-at pos-int?)
(spec/def :mailserver.topic/chat-id (spec/or :keyword keyword?
:chat-id :global/not-empty-string))
(spec/def :mailserver.topic/chat-ids (spec/coll-of :mailserver.topic/chat-id
:kind set?
:min-count 1))
(spec/def :mailserver/topic (spec/keys :req-un [:mailserver.topic/last-request
:mailserver.topic/chat-ids]))
(spec/def :mailserver/request-to :request/to)
(spec/def :mailserver/connection-checks pos-int?)
(spec/def :mailserver/topics (spec/map-of :global/not-empty-string :mailserver/topic))
(spec/def :mailserver/current-request (spec/keys :req-un [:request/from :request/to ::topics]
:opt-un [:request/attemps]))
(spec/def :mailserver/pending-requests integer?)

View File

@ -0,0 +1,70 @@
(ns status-im.mailserver.subs
(:require [re-frame.core :as re-frame]))
(re-frame/reg-sub
:mailserver/state
(fn [db]
(get db :mailserver/state)))
(re-frame/reg-sub
:mailserver/pending-requests
(fn [db]
(get db :mailserver/pending-requests)))
(re-frame/reg-sub
:mailserver/fetching?
:<- [:mailserver/state]
:<- [:mailserver/pending-requests]
(fn [[state pending-requests]]
(when (and pending-requests
(= state :connected)
(pos-int? pending-requests))
pending-requests)))
(re-frame/reg-sub
:mailserver/error
:<- [:mailserver/state]
(fn [state]
(#{:error :disconnected} state)))
(re-frame/reg-sub
:mailserver/connected?
:<- [:mailserver/state]
(fn [state]
(= :connected state)))
(re-frame/reg-sub
:mailserver/current-id
(fn [db]
(:mailserver/current-id db)))
(re-frame/reg-sub
:mailserver/mailservers
(fn [db]
(:mailserver/mailservers db)))
(re-frame/reg-sub
:mailserver/fleet-mailservers
:<- [:settings/current-fleet]
:<- [:mailserver/mailservers]
(fn [[current-fleet mailservers]]
(current-fleet mailservers)))
(re-frame/reg-sub
:mailserver.edit/mailserver
(fn [db]
(get db :mailserver.edit/mailserver)))
(re-frame/reg-sub
:mailserver.edit/connected?
:<- [:mailserver.edit/mailserver]
:<- [:mailserver/current-id]
(fn [[mailserver current-mailserver-id]]
(= (get-in mailserver [:id :value])
current-mailserver-id)))
(re-frame/reg-sub
:mailserver.edit/valid?
:<- [:mailserver.edit/mailserver]
(fn [mailserver]
(not-any? :error (vals mailserver))))

View File

@ -5,7 +5,7 @@
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.network.net-info :as net-info] [status-im.network.net-info :as net-info]
[status-im.transport.inbox :as inbox] [status-im.mailserver.core :as mailserver]
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.fleet.core :as fleet-core] [status-im.fleet.core :as fleet-core]
@ -205,7 +205,7 @@
[{:keys [db] :as cofx} is-connected?] [{:keys [db] :as cofx} is-connected?]
(fx/merge cofx (fx/merge cofx
{:db (assoc db :network-status (if is-connected? :online :offline))} {:db (assoc db :network-status (if is-connected? :online :offline))}
(inbox/network-connection-status-changed is-connected?))) (mailserver/network-connection-status-changed is-connected?)))
(defn- navigate-to-network-details (defn- navigate-to-network-details
[cofx network show-warning?] [cofx network show-warning?]

View File

@ -2,7 +2,7 @@
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.transport.core :as transport] [status-im.transport.core :as transport]
[status-im.transport.inbox :as transport.inbox] [status-im.mailserver.core :as mailserver]
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.fx :as fx] [status-im.utils.fx :as fx]
[status-im.utils.semaphores :as semaphores] [status-im.utils.semaphores :as semaphores]
@ -45,7 +45,7 @@
(semaphores/lock :check-sync-state?)))) (semaphores/lock :check-sync-state?))))
(fx/defn initialize-protocol (fx/defn initialize-protocol
[{:data-store/keys [transport transport-inbox-topics mailservers] [{:data-store/keys [transport mailserver-topics mailservers]
:keys [db web3] :as cofx} address] :keys [db web3] :as cofx} address]
(let [network (get-in db [:account/account :network]) (let [network (get-in db [:account/account :network])
network-id (str (get-in db [:account/account :networks network :config :NetworkId]))] network-id (str (get-in db [:account/account :networks network :config :NetworkId]))]
@ -53,11 +53,11 @@
{:db (assoc db {:db (assoc db
:rpc-url constants/ethereum-rpc-url :rpc-url constants/ethereum-rpc-url
:transport/chats transport :transport/chats transport
:transport.inbox/topics transport-inbox-topics) :mailserver/topics mailserver-topics)
:protocol/assert-correct-network {:web3 web3 :protocol/assert-correct-network {:web3 web3
:network-id network-id}} :network-id network-id}}
(start-check-sync-state) (start-check-sync-state)
(transport.inbox/initialize-offline-inbox mailservers) (mailserver/initialize-mailserver mailservers)
(transport/init-whisper address)))) (transport/init-whisper address))))
(fx/defn handle-close-app-confirmed (fx/defn handle-close-app-confirmed

View File

@ -4,7 +4,7 @@
[status-im.init.core :as init] [status-im.init.core :as init]
[status-im.node.core :as node] [status-im.node.core :as node]
[status-im.pairing.core :as pairing] [status-im.pairing.core :as pairing]
[status-im.transport.inbox :as inbox] [status-im.mailserver.core :as mailserver]
[status-im.transport.message.core :as transport.message] [status-im.transport.message.core :as transport.message]
[status-im.utils.fx :as fx] [status-im.utils.fx :as fx]
[status-im.utils.types :as types] [status-im.utils.types :as types]
@ -45,7 +45,7 @@
:peers-summary peers-summary :peers-summary peers-summary
:peers-count peers-count)} :peers-count peers-count)}
(transport.message/resend-contact-messages previous-summary) (transport.message/resend-contact-messages previous-summary)
(inbox/peers-summary-change previous-summary)))) (mailserver/peers-summary-change previous-summary))))
(fx/defn process (fx/defn process
[cofx event-str] [cofx event-str]
@ -58,9 +58,9 @@
"envelope.expired" (transport.message/update-envelope-status cofx (:hash event) :sent) "envelope.expired" (transport.message/update-envelope-status cofx (:hash event) :sent)
"bundles.added" (pairing/handle-bundles-added cofx event) "bundles.added" (pairing/handle-bundles-added cofx event)
"mailserver.request.completed" (when (accounts.db/logged-in? cofx) "mailserver.request.completed" (when (accounts.db/logged-in? cofx)
(inbox/update-inbox-topics cofx {:request-id (:requestID event) (mailserver/update-mailserver-topics cofx {:request-id (:requestID event)
:cursor (:cursor event)})) :cursor (:cursor event)}))
"mailserver.request.expired" (when (accounts.db/logged-in? cofx) "mailserver.request.expired" (when (accounts.db/logged-in? cofx)
(inbox/resend-request cofx {:request-id (:hash event)})) (mailserver/resend-request cofx {:request-id (:hash event)}))
"discovery.summary" (summary cofx event) "discovery.summary" (summary cofx event)
(log/debug "Event " type " not handled")))) (log/debug "Event " type " not handled"))))

View File

@ -1,6 +1,6 @@
(ns status-im.transport.chat.core (ns status-im.transport.chat.core
(:require [status-im.data-store.transport :as transport-store] (:require [status-im.data-store.transport :as transport-store]
[status-im.transport.inbox :as inbox] [status-im.mailserver.core :as mailserver]
[status-im.utils.fx :as fx])) [status-im.utils.fx :as fx]))
(fx/defn remove-transport-chat (fx/defn remove-transport-chat
@ -14,5 +14,5 @@
"Unsubscribe from chat on transport layer" "Unsubscribe from chat on transport layer"
[cofx chat-id] [cofx chat-id]
(fx/merge cofx (fx/merge cofx
(inbox/remove-chat-from-inbox-topic chat-id) (mailserver/remove-chat-from-mailserver-topic chat-id)
(remove-transport-chat chat-id))) (remove-transport-chat chat-id)))

View File

@ -4,7 +4,7 @@
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.data-store.transport :as transport-store] [status-im.data-store.transport :as transport-store]
[status-im.transport.inbox :as inbox] [status-im.mailserver.core :as mailserver]
[status-im.transport.message.core :as message] [status-im.transport.message.core :as message]
[status-im.transport.shh :as shh] [status-im.transport.shh :as shh]
[status-im.transport.utils :as transport.utils] [status-im.transport.utils :as transport.utils]
@ -16,7 +16,7 @@
"Initialises whisper protocol by: "Initialises whisper protocol by:
- adding fixed shh discovery filter - adding fixed shh discovery filter
- restoring existing symetric keys along with their unique filters - restoring existing symetric keys along with their unique filters
- (optionally) initializing offline inboxing" - (optionally) initializing mailserver"
[{:keys [db web3] :as cofx} current-account-id] [{:keys [db web3] :as cofx} current-account-id]
(log/debug :init-whisper) (log/debug :init-whisper)
(when-let [public-key (get-in db [:account/account :public-key])] (when-let [public-key (get-in db [:account/account :public-key])]
@ -33,7 +33,7 @@
:shh/restore-sym-keys {:web3 web3 :shh/restore-sym-keys {:web3 web3
:transport (filter (comp :topic second) (:transport/chats db)) :transport (filter (comp :topic second) (:transport/chats db))
:on-success sym-key-added-callback}} :on-success sym-key-added-callback}}
(inbox/connect-to-mailserver) (mailserver/connect-to-mailserver)
(message/resend-contact-messages []))))) (message/resend-contact-messages [])))))
;;TODO (yenda) remove once go implements persistence ;;TODO (yenda) remove once go implements persistence

View File

@ -3,8 +3,7 @@
(:require [cljs.spec.alpha :as spec] (:require [cljs.spec.alpha :as spec]
[clojure.string :as s] [clojure.string :as s]
status-im.contact.db status-im.contact.db
[status-im.utils.clocks :as utils.clocks]) [status-im.utils.clocks :as utils.clocks]))
(:require-macros [status-im.utils.db :refer [allowed-keys]]))
;; required ;; required
(spec/def ::ack (spec/coll-of string? :kind vector?)) (spec/def ::ack (spec/coll-of string? :kind vector?))
@ -22,35 +21,14 @@
(spec/def :transport/filter-id (spec/or :keyword keyword? (spec/def :transport/filter-id (spec/or :keyword keyword?
:chat-id :global/not-empty-string)) :chat-id :global/not-empty-string))
(spec/def :transport/filter any?) (spec/def :transport/filter any?)
(spec/def :request/from pos-int?)
(spec/def :request/to pos-int?)
(spec/def :request/attemps int?)
(spec/def :request/cursor :global/not-empty-string)
(spec/def :pairing/installation-id :global/not-empty-string) (spec/def :pairing/installation-id :global/not-empty-string)
(spec/def :pairing/device-type :global/not-empty-string) (spec/def :pairing/device-type :global/not-empty-string)
(spec/def :transport.inbox.topic/last-request pos-int?)
(spec/def :transport.inbox.topic/started-at pos-int?)
(spec/def :transport.inbox.topic/chat-id (spec/or :keyword keyword?
:chat-id :global/not-empty-string))
(spec/def :transport.inbox.topic/chat-ids (spec/coll-of :transport.inbox.topic/chat-id
:kind set?
:min-count 1))
(spec/def :transport.inbox/topic (spec/keys :req-un [:transport.inbox.topic/last-request
:transport.inbox.topic/chat-ids]))
(spec/def :transport/chat (spec/keys :req-un [::ack ::seen ::pending-ack ::pending-send ::topic] (spec/def :transport/chat (spec/keys :req-un [::ack ::seen ::pending-ack ::pending-send ::topic]
:opt-un [::sym-key-id ::sym-key ::resend?])) :opt-un [::sym-key-id ::sym-key ::resend?]))
(spec/def :transport.inbox/request-to :request/to)
(spec/def :transport/chats (spec/map-of :global/not-empty-string :transport/chat)) (spec/def :transport/chats (spec/map-of :global/not-empty-string :transport/chat))
(spec/def :transport/filters (spec/map-of :transport/filter-id :transport/filter)) (spec/def :transport/filters (spec/map-of :transport/filter-id :transport/filter))
(spec/def :transport.inbox/connection-checks pos-int?)
(spec/def :transport.inbox/topics (spec/map-of :global/not-empty-string :transport.inbox/topic))
(spec/def :transport.inbox/current-request (spec/keys :req-un [:request/from :request/to ::topics]
:opt-un [:request/attemps]))
(spec/def :transport.inbox/pending-requests integer?)
(defn create-chat (defn create-chat
"Initialize datastructure for chat representation at the transport level "Initialize datastructure for chat representation at the transport level

View File

@ -1,7 +1,7 @@
(ns ^{:doc "API for whisper filters"} (ns ^{:doc "API for whisper filters"}
status-im.transport.filters status-im.transport.filters
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.transport.inbox :as inbox] [status-im.mailserver.core :as mailserver]
[status-im.transport.utils :as utils] [status-im.transport.utils :as utils]
[status-im.utils.fx :as fx] [status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
@ -55,10 +55,10 @@
(fn [{:keys [db] :as cofx} [_ topic chat-id filter]] (fn [{:keys [db] :as cofx} [_ topic chat-id filter]]
(fx/merge cofx (fx/merge cofx
{:db (assoc-in db [:transport/filters chat-id] filter)} {:db (assoc-in db [:transport/filters chat-id] filter)}
(inbox/reset-request-to) (mailserver/reset-request-to)
(inbox/upsert-inbox-topic {:topic topic (mailserver/upsert-mailserver-topic {:topic topic
:chat-id chat-id}) :chat-id chat-id})
(inbox/process-next-messages-request)))) (mailserver/process-next-messages-request))))
(handlers/register-handler-fx (handlers/register-handler-fx
:shh.callback/filter-removed :shh.callback/filter-removed

View File

@ -1,405 +0,0 @@
(ns ^{:doc "Offline inboxing events and API"}
status-im.transport.inbox
(:require [re-frame.core :as re-frame]
[status-im.accounts.db :as accounts.db]
[status-im.data-store.core :as data-store]
[status-im.data-store.transport :as transport-store]
[status-im.fleet.core :as fleet]
[status-im.mailserver.core :as mailserver]
[status-im.native-module.core :as status]
[status-im.transport.utils :as transport.utils]
[status-im.utils.fx :as fx]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log]
[status-im.transport.db :as transport.db]))
;; How does offline inboxing work ?
;;
;; - We send a request to the mailserver, we are only interested in the
;; messages since `last-request` up to the last seven days
;; and the last 24 hours for topics that were just joined
;; - The mailserver doesn't directly respond to the request and
;; instead we start receiving messages in the filters for the requested
;; topics.
;; - If the mailserver was not ready when we tried for instance to request
;; the history of a topic after joining a chat, the request will be done
;; as soon as the mailserver becomes available
(def one-day (* 24 3600))
(def seven-days (* 7 one-day))
(def maximum-number-of-attempts 2)
(def request-timeout 30)
(def connection-timeout
"Time after which mailserver connection is considered to have failed"
10000)
(defn- parse-json
;; NOTE(dmitryn) Expects JSON response like:
;; {"error": "msg"} or {"result": true}
[s]
(try
(let [res (-> s
js/JSON.parse
(js->clj :keywordize-keys true))]
;; NOTE(dmitryn): AddPeer() may return {"error": ""}
;; assuming empty error is a success response
;; by transforming {"error": ""} to {:result true}
(if (and (:error res)
(= (:error res) ""))
{:result true}
res))
(catch :default e
{:error (.-message e)})))
(defn- response-handler [success-fn error-fn]
(fn handle-response
([response]
(let [{:keys [error result]} (parse-json response)]
(handle-response error result)))
([error result]
(if error
(error-fn error)
(success-fn result)))))
(defn add-peer! [wnode]
(status/add-peer wnode
(response-handler #(log/debug "offline inbox: add-peer success" %)
#(log/error "offline inbox: add-peer error" %))))
(re-frame/reg-fx
:transport.inbox/add-peer
(fn [wnode]
(add-peer! wnode)))
(defn mark-trusted-peer! [web3 enode]
(.markTrustedPeer (transport.utils/shh web3)
enode
(fn [error response]
(if error
(re-frame/dispatch [:inbox.callback/mark-trusted-peer-error error])
(re-frame/dispatch [:inbox.callback/mark-trusted-peer-success response])))))
(re-frame/reg-fx
:transport.inbox/mark-trusted-peer
(fn [{:keys [wnode web3]}]
(mark-trusted-peer! web3 wnode)))
(fx/defn generate-mailserver-symkey
[{:keys [db] :as cofx} {:keys [password id] :as wnode}]
(let [current-fleet (fleet/current-fleet db)]
{:db (assoc-in db [:inbox/wnodes current-fleet id :generating-sym-key?] true)
:shh/generate-sym-key-from-password
[{:password password
:web3 (:web3 db)
:on-success (fn [_ sym-key-id]
(re-frame/dispatch [:inbox.callback/generate-mailserver-symkey-success wnode sym-key-id]))
:on-error #(log/error "offline inbox: get-sym-key error" %)}]}))
(defn registered-peer?
"truthy if the enode is a registered peer"
[peers enode]
(let [peer-ids (into #{} (map :id) peers)
enode-id (transport.utils/extract-enode-id enode)]
(contains? peer-ids enode-id)))
(defn update-mailserver-status [db state]
(assoc db :mailserver-status state))
(fx/defn mark-trusted-peer
[{:keys [db] :as cofx}]
(let [{:keys [address sym-key-id generating-sym-key?] :as wnode} (mailserver/fetch-current cofx)]
(fx/merge cofx
{:db (update-mailserver-status db :added)
:transport.inbox/mark-trusted-peer {:web3 (:web3 db)
:wnode address}}
(when-not (or sym-key-id generating-sym-key?)
(generate-mailserver-symkey wnode)))))
(fx/defn add-peer
[{:keys [db] :as cofx}]
(let [{:keys [address sym-key-id generating-sym-key?] :as wnode} (mailserver/fetch-current cofx)]
(fx/merge cofx
{:db (-> db
(update-mailserver-status :connecting)
(update :transport.inbox/connection-checks inc))
:transport.inbox/add-peer address
:utils/dispatch-later [{:ms connection-timeout
:dispatch [:inbox/check-connection-timeout]}]}
(when-not (or sym-key-id generating-sym-key?)
(generate-mailserver-symkey wnode)))))
(fx/defn connect-to-mailserver
"Add mailserver as a peer using `::add-peer` cofx and generate sym-key when
it doesn't exists
Peer summary will change and we will receive a signal from status go when
this is successful
A connection-check is made after `connection timeout` is reached and
mailserver-status is changed to error if it is not connected by then"
[{:keys [db] :as cofx}]
(let [{:keys [address] :as wnode} (mailserver/fetch-current cofx)
{:keys [peers-summary]} db
added? (registered-peer? peers-summary
address)]
(fx/merge cofx
{:db (dissoc db :transport.inbox/current-request)}
(if added?
(mark-trusted-peer)
(add-peer)))))
(fx/defn peers-summary-change
"There is only 2 summary changes that require offline inboxing action:
- mailserver disconnected: we try to reconnect
- mailserver connected: we mark the mailserver as trusted peer"
[{:keys [db] :as cofx} previous-summary]
(when (:account/account db)
(let [{:keys [peers-summary peers-count]} db
{:keys [address sym-key-id] :as wnode} (mailserver/fetch-current cofx)
mailserver-was-registered? (registered-peer? previous-summary
address)
mailserver-is-registered? (registered-peer? peers-summary
address)
mailserver-added? (and mailserver-is-registered?
(not mailserver-was-registered?))
mailserver-removed? (and mailserver-was-registered?
(not mailserver-is-registered?))]
(cond
mailserver-added?
(mark-trusted-peer cofx)
mailserver-removed?
(connect-to-mailserver cofx)))))
(defn request-messages! [web3 {:keys [sym-key-id address]} {:keys [topics to from]}]
(log/info "offline inbox: request-messages for: "
" topics " topics
" from " from
" to " to)
(.requestMessages (transport.utils/shh web3)
(clj->js {:topics topics
:mailServerPeer address
:symKeyID sym-key-id
:timeout request-timeout
:from from
:to to})
(fn [error request-id]
(if-not error
(log/info "offline inbox: messages request success for topic " topics "from" from "to" to)
(log/error "offline inbox: messages request error for topic " topics ": " error)))))
(re-frame/reg-fx
:transport.inbox/request-messages
(fn [{:keys [web3 wnode request]}]
(request-messages! web3 wnode request)))
(defn get-wnode-when-ready
"return the wnode if the inbox is ready"
[{:keys [db] :as cofx}]
(let [{:keys [sym-key-id] :as wnode} (mailserver/fetch-current cofx)
mailserver-status (:mailserver-status db)]
(when (and (= :connected mailserver-status)
sym-key-id)
wnode)))
(defn split-request-per-day
"NOTE: currently the mailserver is only accepting requests for a span
of 24 hours, so we split requests per 24h spans if the last request was
done more than 24h ago"
[now-in-s [last-request topics]]
(let [days (conj
(into [] (range (max last-request
(- now-in-s one-day))
now-in-s
one-day))
now-in-s)
day-ranges (map vector days (rest days))]
(for [[from to] day-ranges]
{:topics topics
:from from
:to to})))
(defn prepare-messages-requests
[{:keys [db now] :as cofx} request-to]
(let [web3 (:web3 db)]
(remove nil?
(mapcat (partial split-request-per-day request-to)
(reduce (fn [acc [topic {:keys [last-request]}]]
(update acc last-request conj topic))
{}
(:transport.inbox/topics db))))))
(fx/defn process-next-messages-request
[{:keys [db now] :as cofx}]
(when (and (transport.db/all-filters-added? cofx)
(not (:transport.inbox/current-request db)))
(when-let [wnode (get-wnode-when-ready cofx)]
(let [request-to (or (:transport.inbox/request-to db)
(quot now 1000))
requests (prepare-messages-requests cofx request-to)
web3 (:web3 db)]
(if-let [request (first requests)]
{:db (assoc db
:transport.inbox/pending-requests (count requests)
:transport.inbox/current-request request
:transport.inbox/request-to request-to)
:transport.inbox/request-messages {:web3 web3
:wnode wnode
:request request}}
{:db (dissoc db
:transport.inbox/pending-requests
:transport.inbox/request-to)})))))
(fx/defn add-mailserver-trusted
"the current mailserver has been trusted
update mailserver status to `:connected` and request messages
if wnode is ready"
[{:keys [db] :as cofx}]
(fx/merge cofx
{:db (update-mailserver-status db :connected)}
(process-next-messages-request)))
(fx/defn add-mailserver-sym-key
"the current mailserver sym-key has been generated
add sym-key to the wnode in app-db and request messages if
wnode is ready"
[{:keys [db] :as cofx} {:keys [id]} sym-key-id]
(let [current-fleet (fleet/current-fleet db)]
(fx/merge cofx
{:db (-> db
(assoc-in [:inbox/wnodes current-fleet id :sym-key-id] sym-key-id)
(update-in [:inbox/wnodes current-fleet id] dissoc :generating-sym-key?))}
(process-next-messages-request))))
(fx/defn change-mailserver
"mark mailserver status as `:error` if custom mailserver is used
otherwise try to reconnect to another mailserver"
[{:keys [db] :as cofx}]
(if (mailserver/preferred-mailserver-id cofx)
{:db (update-mailserver-status db :error)}
(fx/merge cofx
(mailserver/set-current-mailserver)
(connect-to-mailserver))))
(fx/defn check-connection
"connection-checks counter is used to prevent changing
mailserver on flaky connections
if there is more than one connection check pending
decrement the connection check counter
else
change mailserver if mailserver is connected"
[{:keys [db] :as cofx}]
(if (zero? (dec (:transport.inbox/connection-checks db)))
(fx/merge cofx
{:db (dissoc db :transport.inbox/connection-checks)}
(when (= :connecting (:mailserver-status db))
(change-mailserver cofx)))
{:db (update db :transport.inbox/connection-checks dec)}))
(fx/defn reset-request-to
[{:keys [db]}]
{:db (dissoc db :transport.inbox/request-to)})
(fx/defn network-connection-status-changed
"when host reconnects, reset request-to and
reconnect to mailserver"
[{:keys [db] :as cofx} is-connected?]
(when (and (accounts.db/logged-in? cofx)
is-connected?)
(fx/merge cofx
(reset-request-to)
(connect-to-mailserver))))
(fx/defn remove-chat-from-inbox-topic
"if the chat is the only chat of the inbox topic delete the inbox topic
and process-next-messages-requests again to remove pending request for that topic
otherwise remove the chat-id of the chat from the inbox topic and save"
[{:keys [db now] :as cofx} chat-id]
(let [topic (get-in db [:transport/chats chat-id :topic])
{:keys [chat-ids] :as inbox-topic} (update (get-in db [:transport.inbox/topics topic])
:chat-ids
disj chat-id)]
(if (empty? chat-ids)
(fx/merge cofx
{:db (update db :transport.inbox/topics dissoc topic)
:data-store/tx [(transport-store/delete-transport-inbox-topic-tx topic)]}
(process-next-messages-request))
{:db (assoc-in db [:transport.inbox/topics topic] inbox-topic)
:data-store/tx [(transport-store/save-transport-inbox-topic-tx
{:topic topic
:inbox-topic inbox-topic})]})))
(defn get-updated-inbox-topics [db topics last-request]
(reduce (fn [acc topic]
(if-let [inbox-topic (some-> (get-in db [:transport.inbox/topics topic])
(assoc :last-request last-request))]
(assoc acc topic inbox-topic)
acc))
{}
topics))
(fx/defn update-inbox-topics
"TODO: add support for cursors
if there is a cursor, do not update `last-request`"
[{:keys [db now] :as cofx} {:keys [request-id]}]
(when-let [request (get db :transport.inbox/current-request)]
(let [{:keys [from to topics]} request
inbox-topics (get-updated-inbox-topics db topics to)]
(log/info "offline inbox: message request " request-id
"completed for inbox topics" topics "from" from "to" to)
(if (empty? inbox-topics)
;; when topics were deleted (filter was removed while request was pending)
(fx/merge cofx
{:db (dissoc db :transport.inbox/current-request)}
(process-next-messages-request))
(fx/merge cofx
{:db (-> db
(dissoc :transport.inbox/current-request)
(update :transport.inbox/topics merge inbox-topics))
:data-store/tx (mapv (fn [[topic inbox-topic]]
(transport-store/save-transport-inbox-topic-tx
{:topic topic
:inbox-topic inbox-topic}))
inbox-topics)}
(process-next-messages-request))))))
(fx/defn upsert-inbox-topic
"if the topic didn't exist
create the topic
else if chat-id is not in the topic
add the chat-id to the topic and reset last-request
there was no filter for the chat and messages for that
so the whole history for that topic needs to be re-fetched"
[{:keys [db] :as cofx} {:keys [topic chat-id]}]
(let [{:keys [chat-ids last-request] :as current-inbox-topic}
(get-in db [:transport.inbox/topics topic] {:chat-ids #{}})]
(when-let [inbox-topic (when-not (chat-ids chat-id)
(-> current-inbox-topic
(assoc :last-request 1)
(update :chat-ids conj chat-id)))]
(fx/merge cofx
{:db (assoc-in db [:transport.inbox/topics topic] inbox-topic)
:data-store/tx [(transport-store/save-transport-inbox-topic-tx
{:topic topic
:inbox-topic inbox-topic})]}))))
(fx/defn resend-request
[{:keys [db] :as cofx} {:keys [request-id]}]
(if (<= maximum-number-of-attempts
(get-in db [:transport.inbox/current-request :attemps]))
(fx/merge cofx
{:db (update db :transport.inbox/current-request dissoc :attemps)}
(change-mailserver))
(when-let [wnode (get-wnode-when-ready cofx)]
(let [{:keys [topics from to] :as request} (get db :transport.inbox/current-request)
web3 (:web3 db)]
(log/info "offline inbox: message request " request-id "expired for inbox topic" topics "from" from "to" to)
{:db (update-in db [:transport.inbox/current-request :attemps] inc)
:transport.inbox/request-messages {:web3 web3
:wnode wnode
:request request}}))))
(fx/defn initialize-offline-inbox
[cofx custom-mailservers]
(fx/merge cofx
(mailserver/add-custom-mailservers custom-mailservers)
(mailserver/set-current-mailserver)))

View File

@ -7,8 +7,7 @@
[status-im.i18n :as i18n])) [status-im.i18n :as i18n]))
(defview error-label (defview error-label
[{:keys [view-id label fetching? mailserver-error?] :as opts}] [{:keys [view-id label mailserver-fetching? mailserver-error?] :as opts}]
{:should-component-update {:should-component-update
(fn [_ [_ old-props] [_ new-props]] (fn [_ [_ old-props] [_ new-props]]
;; prevents flickering on navigation ;; prevents flickering on navigation
@ -19,16 +18,17 @@
:accessibility-label :connection-status-text} :accessibility-label :connection-status-text}
[react/text {:style styles/text [react/text {:style styles/text
:on-press (when mailserver-error? :on-press (when mailserver-error?
#(re-frame/dispatch [:inbox.ui/reconnect-mailserver-pressed]))} #(re-frame/dispatch [:mailserver.ui/reconnect-mailserver-pressed]))}
(if (and (not mailserver-error?) fetching?) (if (and (not mailserver-error?)
(i18n/label :t/fetching-messages {:requests-left (str fetching?)}) mailserver-fetching?)
(i18n/label :t/fetching-messages {:requests-left (str mailserver-fetching?)})
(i18n/label label))]])) (i18n/label label))]]))
(defview error-view [{:keys [top]}] (defview error-view [{:keys [top]}]
(letsubs [offline? [:offline?] (letsubs [offline? [:offline?]
disconnected? [:disconnected?] disconnected? [:disconnected?]
mailserver-error? [:mailserver-error?] mailserver-error? [:mailserver/error]
fetching? [:fetching?] mailserver-fetching? [:mailserver/fetching?]
current-chat-contact [:get-current-chat-contact] current-chat-contact [:get-current-chat-contact]
view-id [:get :view-id] view-id [:get :view-id]
window-width [:dimensions/window-width]] window-width [:dimensions/window-width]]
@ -36,14 +36,14 @@
offline? :t/offline offline? :t/offline
disconnected? :t/disconnected disconnected? :t/disconnected
mailserver-error? :t/mailserver-reconnect mailserver-error? :t/mailserver-reconnect
fetching? :t/fetching-messages mailserver-fetching? :t/fetching-messages
:else nil)] :else nil)]
(let [pending? (and (:pending current-chat-contact) (= :chat view-id))] (let [pending? (and (:pending current-chat-contact) (= :chat view-id))]
[error-label [error-label
{:view-id view-id {:view-id view-id
:top top :top top
:window-width window-width :window-width window-width
:pending? pending? :pending? pending?
:label label :label label
:fetching? fetching? :mailserver-fetching? mailserver-fetching?
:mailserver-error? mailserver-error?}])))) :mailserver-error? mailserver-error?}]))))

View File

@ -83,9 +83,9 @@
:icons/tooltip-triangle (js/require "./resources/icons/tooltip-triangle.svg") :icons/tooltip-triangle (js/require "./resources/icons/tooltip-triangle.svg")
:icons/open (js/require "./resources/icons/open.svg") :icons/open (js/require "./resources/icons/open.svg")
:icons/network (js/require "./resources/icons/network.svg") :icons/network (js/require "./resources/icons/network.svg")
:icons/wnode (js/require "./resources/icons/wnode.svg") :icons/mailserver (js/require "./resources/icons/mailserver.svg")
:icons/log-level (js/require "./resources/icons/wnode.svg") :icons/log-level (js/require "./resources/icons/mailserver.svg")
:icons/fleet (js/require "./resources/icons/wnode.svg") :icons/fleet (js/require "./resources/icons/mailserver.svg")
:icons/refresh (js/require "./resources/icons/refresh.svg") :icons/refresh (js/require "./resources/icons/refresh.svg")
:icons/newchat (js/require "./resources/icons/newchat.svg") :icons/newchat (js/require "./resources/icons/newchat.svg")
:icons/logo (js/require "./resources/icons/logo.svg") :icons/logo (js/require "./resources/icons/logo.svg")
@ -155,9 +155,9 @@
:icons/tooltip-triangle (components.svg/slurp-svg "./resources/icons/tooltip-triangle.svg") :icons/tooltip-triangle (components.svg/slurp-svg "./resources/icons/tooltip-triangle.svg")
:icons/open (components.svg/slurp-svg "./resources/icons/open.svg") :icons/open (components.svg/slurp-svg "./resources/icons/open.svg")
:icons/network (components.svg/slurp-svg "./resources/icons/network.svg") :icons/network (components.svg/slurp-svg "./resources/icons/network.svg")
:icons/wnode (components.svg/slurp-svg "./resources/icons/wnode.svg") :icons/mailserver (components.svg/slurp-svg "./resources/icons/mailserver.svg")
:icons/log-level (components.svg/slurp-svg "./resources/icons/wnode.svg") :icons/log-level (components.svg/slurp-svg "./resources/icons/mailserver.svg")
:icons/fleet (components.svg/slurp-svg "./resources/icons/wnode.svg") :icons/fleet (components.svg/slurp-svg "./resources/icons/mailserver.svg")
:icons/refresh (components.svg/slurp-svg "./resources/icons/refresh.svg") :icons/refresh (components.svg/slurp-svg "./resources/icons/refresh.svg")
:icons/newchat (components.svg/slurp-svg "./resources/icons/newchat.svg") :icons/newchat (components.svg/slurp-svg "./resources/icons/newchat.svg")
:icons/logo (components.svg/slurp-svg "./resources/icons/logo.svg") :icons/logo (components.svg/slurp-svg "./resources/icons/logo.svg")

View File

@ -25,7 +25,7 @@
(letsubs [{:keys [command-completion]} [:selected-chat-command] (letsubs [{:keys [command-completion]} [:selected-chat-command]
{:keys [input-text seq-arg-input-text]} [:get-current-chat] {:keys [input-text seq-arg-input-text]} [:get-current-chat]
network-status [:network-status] network-status [:network-status]
mailserver-connected? [:mailserver-connected?] mailserver-connected? [:mailserver/connected?]
spin-value (animation/create-value 1)] spin-value (animation/create-value 1)]
{:component-did-update (send-button-view-on-update {:spin-value spin-value {:component-did-update (send-button-view-on-update {:spin-value spin-value
:command-completion command-completion})} :command-completion command-completion})}

View File

@ -14,7 +14,7 @@
status-im.chat.specs status-im.chat.specs
status-im.ui.screens.profile.db status-im.ui.screens.profile.db
status-im.ui.screens.network-settings.db status-im.ui.screens.network-settings.db
status-im.ui.screens.offline-messaging-settings.db status-im.mailserver.db
status-im.browser.db status-im.browser.db
status-im.ui.screens.add-new.db status-im.ui.screens.add-new.db
status-im.ui.screens.add-new.new-public-chat.db)) status-im.ui.screens.add-new.new-public-chat.db))
@ -47,13 +47,13 @@
:semaphores #{} :semaphores #{}
:network constants/default-network :network constants/default-network
:networks/networks constants/default-networks :networks/networks constants/default-networks
:inbox/wnodes fleet/default-wnodes
:my-profile/editing? false :my-profile/editing? false
:transport/chats {} :transport/chats {}
:transport/filters {} :transport/filters {}
:transport/message-envelopes {} :transport/message-envelopes {}
:transport.inbox/topics {} :mailserver/mailservers fleet/default-mailservers
:transport.inbox/pending-requests 0 :mailserver/topics {}
:mailserver/pending-requests 0
:chat/cooldowns 0 :chat/cooldowns 0
:chat/cooldown-enabled? false :chat/cooldown-enabled? false
:chat/last-outgoing-message-sent-at 0 :chat/last-outgoing-message-sent-at 0
@ -93,8 +93,6 @@
;;:online - presence of internet connection in the phone ;;:online - presence of internet connection in the phone
(spec/def ::network-status (spec/nilable keyword?)) (spec/def ::network-status (spec/nilable keyword?))
(spec/def ::mailserver-status (spec/nilable #{:disconnected :connecting :added :connected :error}))
(spec/def ::app-state string?) (spec/def ::app-state string?)
;;;;NODE ;;;;NODE
@ -156,7 +154,6 @@
(spec/def ::chain (spec/nilable string?)) (spec/def ::chain (spec/nilable string?))
(spec/def ::peers-count (spec/nilable integer?)) (spec/def ::peers-count (spec/nilable integer?))
(spec/def ::peers-summary (spec/nilable vector?)) (spec/def ::peers-summary (spec/nilable vector?))
(spec/def :inbox/current-id (spec/nilable keyword?))
(spec/def ::collectible (spec/nilable map?)) (spec/def ::collectible (spec/nilable map?))
(spec/def ::collectibles (spec/nilable map?)) (spec/def ::collectibles (spec/nilable map?))
@ -217,11 +214,8 @@
:networks/selected-network :networks/selected-network
:networks/networks :networks/networks
:networks/manage :networks/manage
:mailservers/manage
:bootnodes/manage :bootnodes/manage
:extensions/manage :extensions/manage
:inbox/wnodes
:inbox/current-id
:node/status :node/status
:node/restart? :node/restart?
:node/address :node/address
@ -238,11 +232,15 @@
:transport/message-envelopes :transport/message-envelopes
:transport/chats :transport/chats
:transport/filters :transport/filters
:transport.inbox/topics :mailserver.edit/mailserver
:transport.inbox/pending-requests :mailserver/mailservers
:transport.inbox/current-request :mailserver/current-id
:transport.inbox/connection-checks :mailserver/state
:transport.inbox/request-to :mailserver/topics
:mailserver/pending-requests
:mailserver/current-request
:mailserver/connection-checks
:mailserver/request-to
:desktop/desktop :desktop/desktop
:dimensions/window :dimensions/window
:dapps/permissions :dapps/permissions
@ -263,7 +261,6 @@
::keyboard-max-height ::keyboard-max-height
::tab-bar-visible? ::tab-bar-visible?
::network-status ::network-status
::mailserver-status
::peers-count ::peers-count
::peers-summary ::peers-summary
::sync-state ::sync-state

View File

@ -296,7 +296,7 @@
(views/defview chat-text-input [chat-id input-text] (views/defview chat-text-input [chat-id input-text]
(views/letsubs [inp-ref (atom nil) (views/letsubs [inp-ref (atom nil)
network-status [:network-status] network-status [:network-status]
mailserver-connected? [:mailserver-connected?]] mailserver-connected? [:mailserver/connected?]]
{:component-will-update {:component-will-update
(fn [e [_ new-chat-id new-input-text]] (fn [e [_ new-chat-id new-input-text]]
(let [[_ old-chat-id] (.. e -props -argv)] (let [[_ old-chat-id] (.. e -props -argv)]

View File

@ -89,10 +89,10 @@
[pairing.views/render-row installation]])]) [pairing.views/render-row installation]])])
(views/defview advanced-settings [] (views/defview advanced-settings []
(views/letsubs [current-wnode-id [:settings/current-wnode] (views/letsubs [installations [:pairing/installations]
installations [:pairing/installations] current-mailserver-id [:mailserver/current-id]
wnodes [:settings/fleet-wnodes]] mailservers [:mailserver/fleet-mailservers]]
(let [render-fn (offline-messaging.views/render-row current-wnode-id)] (let [render-fn (offline-messaging.views/render-row current-mailserver-id)]
[react/scroll-view [react/scroll-view
[react/text {:style styles/advanced-settings-title [react/text {:style styles/advanced-settings-title
:font :medium} :font :medium}
@ -100,10 +100,10 @@
[react/view {:style styles/title-separator}] [react/view {:style styles/title-separator}]
[react/text {:style styles/mailserver-title} (i18n/label :offline-messaging)] [react/text {:style styles/mailserver-title} (i18n/label :offline-messaging)]
[react/view [react/view
(for [node (vals wnodes)] (for [mailserver (vals mailservers)]
^{:key (:id node)} ^{:key (:id mailserver)}
[react/view {:style {:margin-vertical 8}} [react/view {:style {:margin-vertical 8}}
[render-fn node]])] [render-fn mailserver]])]
(when (config/pairing-enabled? true) (when (config/pairing-enabled? true)
(installations-section installations))]))) (installations-section installations))])))

View File

@ -26,7 +26,7 @@
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.hardwallet.core :as hardwallet] [status-im.hardwallet.core :as hardwallet]
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.transport.inbox :as inbox] [status-im.mailserver.core :as mailserver]
[status-im.ui.components.permissions :as permissions] [status-im.ui.components.permissions :as permissions]
[status-im.utils.dimensions :as dimensions] [status-im.utils.dimensions :as dimensions]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
@ -118,7 +118,7 @@
(fx/defn on-return-from-background [cofx] (fx/defn on-return-from-background [cofx]
(fx/merge cofx (fx/merge cofx
(inbox/process-next-messages-request) (mailserver/process-next-messages-request)
(hardwallet/return-back-from-nfc-settings))) (hardwallet/return-back-from-nfc-settings)))
(defn app-state-change [state {:keys [db] :as cofx}] (defn app-state-change [state {:keys [db] :as cofx}]

View File

@ -25,7 +25,7 @@
:line-height 20} :line-height 20}
:android {:font-size 16}}) :android {:font-size 16}})
(defn wnode-icon [connected?] (defn mailserver-icon [connected?]
{:width 40 {:width 40
:height 40 :height 40
:border-radius 20 :border-radius 20
@ -38,4 +38,3 @@
(def empty-list (def empty-list
{:color colors/black {:color colors/black
:text-align :center}) :text-align :center})

View File

@ -10,16 +10,16 @@
[status-im.ui.components.toolbar.actions :as toolbar.actions] [status-im.ui.components.toolbar.actions :as toolbar.actions]
[status-im.ui.screens.extensions.styles :as styles])) [status-im.ui.screens.extensions.styles :as styles]))
(def wnode-icon (def mailserver-icon
[react/view (styles/wnode-icon true) [react/view (styles/mailserver-icon true)
[vector-icons/icon :icons/wnode {:color :white}]]) [vector-icons/icon :icons/mailserver {:color :white}]])
(defn- render-extension [{:keys [id name url active?]}] (defn- render-extension [{:keys [id name url active?]}]
[list/list-item-with-checkbox [list/list-item-with-checkbox
{:checked? active? {:checked? active?
:on-value-change #(re-frame/dispatch [:extensions.ui/activation-checkbox-pressed id %])} :on-value-change #(re-frame/dispatch [:extensions.ui/activation-checkbox-pressed id %])}
[list/item [list/item
wnode-icon mailserver-icon
[list/item-content [list/item-content
[list/item-primary name] [list/item-primary name]
[list/item-secondary url]]]]) [list/item-secondary url]]]])

View File

@ -1,22 +0,0 @@
(ns status-im.ui.screens.offline-messaging-settings.db
(:require-macros [status-im.utils.db :refer [allowed-keys]])
(:require
[status-im.mailserver.core :as mailserver]
[cljs.spec.alpha :as spec]))
(spec/def ::not-blank-string (spec/and string? seq))
(spec/def :wnode/address (spec/and string? mailserver/valid-enode-address?))
(spec/def :wnode/name ::not-blank-string)
(spec/def :wnode/id keyword?)
(spec/def :wnode/user-defined boolean?)
(spec/def :wnode/password ::not-blank-string)
(spec/def :wnode/sym-key-id string?)
(spec/def :wnode/generating-sym-key? boolean?)
(spec/def :wnode/wnode (allowed-keys :req-un [:wnode/address :wnode/name :wnode/id]
:opt-un [:wnode/sym-key-id
:wnode/generating-sym-key?
:wnode/user-defined
:wnode/password]))
(spec/def :inbox/wnodes (spec/nilable (spec/map-of keyword? (spec/map-of :wnode/id :wnode/wnode))))

View File

@ -1,22 +0,0 @@
(ns status-im.ui.screens.offline-messaging-settings.edit-mailserver.subs
(:require
[re-frame.core :refer [reg-sub]]
[status-im.mailserver.core :as mailserver]))
(reg-sub
:get-manage-mailserver
:<- [:get :mailservers/manage]
(fn [manage]
manage))
(reg-sub
:get-connected-mailserver
(fn [db]
(mailserver/connected? (get-in db [:mailservers/manage :id :value])
{:db db})))
(reg-sub
:manage-mailserver-valid?
:<- [:get-manage-mailserver]
(fn [manage]
(not-any? :error (vals manage))))

View File

@ -42,12 +42,12 @@
[vector-icons/icon :icons/qr {:color colors/blue}]]]) [vector-icons/icon :icons/qr {:color colors/blue}]]])
(views/defview edit-mailserver [] (views/defview edit-mailserver []
(views/letsubs [manage-mailserver [:get-manage-mailserver] (views/letsubs [mailserver [:mailserver.edit/mailserver]
connected? [:get-connected-mailserver] connected? [:mailserver.edit/connected?]
is-valid? [:manage-mailserver-valid?]] is-valid? [:mailserver.edit/valid?]]
(let [url (get-in manage-mailserver [:url :value]) (let [url (get-in mailserver [:url :value])
id (get-in manage-mailserver [:id :value]) id (get-in mailserver [:id :value])
name (get-in manage-mailserver [:name :value])] name (get-in mailserver [:name :value])]
[react/view components.styles/flex [react/view components.styles/flex
[status-bar/status-bar] [status-bar/status-bar]
[react/keyboard-avoiding-view components.styles/flex [react/keyboard-avoiding-view components.styles/flex

View File

@ -7,10 +7,10 @@
{:flex 1 {:flex 1
:background-color :white}) :background-color :white})
(def wnode-item-inner (def mailserver-item-inner
{:padding-horizontal 16}) {:padding-horizontal 16})
(defstyle wnode-item (defstyle mailserver-item
{:flex-direction :row {:flex-direction :row
:background-color :white :background-color :white
:align-items :center :align-items :center
@ -18,7 +18,7 @@
:ios {:height 64} :ios {:height 64}
:android {:height 56}}) :android {:height 56}})
(defstyle wnode-item-name-text (defstyle mailserver-item-name-text
{:color colors/black {:color colors/black
:ios {:font-size 17 :ios {:font-size 17
:letter-spacing -0.2 :letter-spacing -0.2
@ -26,7 +26,7 @@
:desktop {:font-size 16} :desktop {:font-size 16}
:android {:font-size 16}}) :android {:font-size 16}})
(defstyle wnode-item-connected-text (defstyle mailserver-item-connected-text
{:color colors/gray {:color colors/gray
:ios {:font-size 14 :ios {:font-size 14
:margin-top 6 :margin-top 6
@ -34,7 +34,7 @@
:android {:font-size 12 :android {:font-size 12
:margin-top 2}}) :margin-top 2}})
(defn wnode-icon-container [connected?] (defn mailserver-icon-container [connected?]
{:width 40 {:width 40
:height 40 :height 40
:border-radius 20 :border-radius 20
@ -44,5 +44,5 @@
:align-items :center :align-items :center
:justify-content :center}) :justify-content :center})
(defn wnode-icon [connected?] (defn mailserver-icon [connected?]
(hash-map (if platform/desktop? :tint-color :color) (if connected? :white :gray))) (hash-map (if platform/desktop? :tint-color :color) (if connected? :white :gray)))

View File

@ -1,14 +0,0 @@
(ns status-im.ui.screens.offline-messaging-settings.subs
(:require [re-frame.core :as re-frame]
status-im.ui.screens.offline-messaging-settings.edit-mailserver.subs
[status-im.utils.ethereum.core :as ethereum]))
(re-frame/reg-sub :settings/current-wnode
(fn [db _]
(:inbox/current-id db)))
(re-frame/reg-sub :settings/fleet-wnodes
:<- [:settings/current-fleet]
:<- [:get :inbox/wnodes]
(fn [[current-fleet wnodes]]
(current-fleet wnodes)))

View File

@ -12,31 +12,31 @@
[status-im.ui.components.toolbar.actions :as toolbar.actions] [status-im.ui.components.toolbar.actions :as toolbar.actions]
[status-im.ui.screens.offline-messaging-settings.styles :as styles])) [status-im.ui.screens.offline-messaging-settings.styles :as styles]))
(defn- wnode-icon [connected?] (defn- mailserver-icon [connected?]
[react/view (if platform/desktop? [react/view (if platform/desktop?
{:style (styles/wnode-icon-container connected?)} {:style (styles/mailserver-icon-container connected?)}
(styles/wnode-icon-container connected?)) (styles/mailserver-icon-container connected?))
[vector-icons/icon :icons/wnode [vector-icons/icon :icons/mailserver
(if platform/desktop? {:style (styles/wnode-icon connected?)} (if platform/desktop? {:style (styles/mailserver-icon connected?)}
(styles/wnode-icon connected?))]]) (styles/mailserver-icon connected?))]])
(defn render-row [current-wnode-id] (defn render-row [current-mailserver-id]
(fn [{:keys [name id user-defined]}] (fn [{:keys [name id user-defined]}]
(let [connected? (= id current-wnode-id)] (let [connected? (= id current-mailserver-id)]
[react/touchable-highlight [react/touchable-highlight
{:on-press #(if user-defined {:on-press #(if user-defined
(re-frame/dispatch [:mailserver.ui/user-defined-mailserver-selected id]) (re-frame/dispatch [:mailserver.ui/user-defined-mailserver-selected id])
(re-frame/dispatch [:mailserver.ui/default-mailserver-selected id])) (re-frame/dispatch [:mailserver.ui/default-mailserver-selected id]))
:accessibility-label :mailserver-item} :accessibility-label :mailserver-item}
[react/view styles/wnode-item [react/view styles/mailserver-item
[wnode-icon connected?] [mailserver-icon connected?]
[react/view styles/wnode-item-inner [react/view styles/mailserver-item-inner
[react/text {:style styles/wnode-item-name-text} [react/text {:style styles/mailserver-item-name-text}
name]]]]))) name]]]])))
(views/defview offline-messaging-settings [] (views/defview offline-messaging-settings []
(views/letsubs [current-wnode-id [:settings/current-wnode] (views/letsubs [current-mailserver-id [:mailserver/current-id]
wnodes [:settings/fleet-wnodes]] mailservers [:mailserver/fleet-mailservers]]
[react/view {:flex 1} [react/view {:flex 1}
[status-bar/status-bar] [status-bar/status-bar]
[toolbar/toolbar {} [toolbar/toolbar {}
@ -45,7 +45,7 @@
[toolbar/actions [toolbar/actions
[(toolbar.actions/add false #(re-frame/dispatch [:mailserver.ui/add-pressed]))]]] [(toolbar.actions/add false #(re-frame/dispatch [:mailserver.ui/add-pressed]))]]]
[react/view styles/wrapper [react/view styles/wrapper
[list/flat-list {:data (vals wnodes) [list/flat-list {:data (vals mailservers)
:default-separator? false :default-separator? false
:key-fn :name :key-fn :name
:render-fn (render-row current-wnode-id)}]]])) :render-fn (render-row current-mailserver-id)}]]]))

View File

@ -4,6 +4,7 @@
status-im.chat.subs status-im.chat.subs
status-im.contact.subs status-im.contact.subs
status-im.search.subs status-im.search.subs
status-im.mailserver.subs
status-im.ui.screens.accounts.subs status-im.ui.screens.accounts.subs
status-im.ui.screens.extensions.subs status-im.ui.screens.extensions.subs
status-im.ui.screens.home.subs status-im.ui.screens.home.subs
@ -16,7 +17,6 @@
status-im.ui.screens.network-settings.subs status-im.ui.screens.network-settings.subs
status-im.ui.screens.log-level-settings.subs status-im.ui.screens.log-level-settings.subs
status-im.ui.screens.fleet-settings.subs status-im.ui.screens.fleet-settings.subs
status-im.ui.screens.offline-messaging-settings.subs
status-im.ui.screens.bootnodes-settings.subs status-im.ui.screens.bootnodes-settings.subs
status-im.ui.screens.pairing.subs status-im.ui.screens.pairing.subs
status-im.ui.screens.currency-settings.subs status-im.ui.screens.currency-settings.subs
@ -46,14 +46,6 @@
(reg-sub :sync-state :sync-state) (reg-sub :sync-state :sync-state)
(reg-sub :network-status :network-status) (reg-sub :network-status :network-status)
(reg-sub :peers-count :peers-count) (reg-sub :peers-count :peers-count)
(reg-sub :mailserver-status :mailserver-status)
(reg-sub :fetching?
(fn [db]
(let [pending-requests (get db :transport.inbox/pending-requests)]
(when (and (pos-int? pending-requests)
(:transport.inbox/current-request db))
pending-requests))))
(reg-sub :offline? (reg-sub :offline?
:<- [:network-status] :<- [:network-status]
@ -67,16 +59,6 @@
(fn [peers-count] (fn [peers-count]
(zero? peers-count))) (zero? peers-count)))
(reg-sub :mailserver-error?
:<- [:mailserver-status]
(fn [mailserver-status]
(#{:error :disconnected} mailserver-status)))
(reg-sub :mailserver-connected?
:<- [:mailserver-status]
(fn [mailserver-status]
(= :connected mailserver-status)))
(reg-sub :syncing? (reg-sub :syncing?
:<- [:sync-state] :<- [:sync-state]
(fn [sync-state] (fn [sync-state]

View File

@ -1,7 +1,43 @@
(ns status-im.test.mailserver.core (ns status-im.test.mailserver.core
(:require [cljs.test :refer-macros [deftest is testing]] (:require [cljs.test :refer-macros [deftest is testing]]
[status-im.transport.utils :as utils]
[status-im.mailserver.core :as mailserver])) [status-im.mailserver.core :as mailserver]))
(def enode "enode://08d8eb6177b187049f6c97ed3f6c74fbbefb94c7ad10bafcaf4b65ce89c314dcfee0a8bc4e7a5b824dfa08b45b360cc78f34f0aff981f8386caa07652d2e601b@163.172.177.138:40404")
(def enode2 "enode://12d8eb6177b187049f6c97ed3f6c74fbbefb94c7ad10bafcaf4b65ce89c314dcfee0a8bc4e7a5b824dfa08b45b360cc78f34f0aff981f8386caa07652d2e601b@163.172.177.138:40404")
(deftest test-extract-enode-id
(testing "Get enode id from enode uri"
(is (= "08d8eb6177b187049f6c97ed3f6c74fbbefb94c7ad10bafcaf4b65ce89c314dcfee0a8bc4e7a5b824dfa08b45b360cc78f34f0aff981f8386caa07652d2e601b"
(utils/extract-enode-id enode))))
(testing "Get enode id from mailformed enode uri"
(is (= ""
(utils/extract-enode-id "08d8eb6177b187049f6c97ed3f6c74fbbefb94c7ad10bafcaf4b65ce89c314dcfee0a8bc4e7a5b824dfa08b45b360cc78f34f0aff981f8386caa07652d2e601b@163.172.177.138:40404"))))
(testing "Test empty string"
(is (= ""
(utils/extract-enode-id ""))))
(testing "Test nil"
(is (= ""
(utils/extract-enode-id nil)))))
(def peers
[{:id "08d8eb6177b187049f6c97ed3f6c74fbbefb94c7ad10bafcaf4b65ce89c314dcfee0a8bc4e7a5b824dfa08b45b360cc78f34f0aff981f8386caa07652d2e601b"
:name "StatusIM/v0.9.9-unstable/linux-amd64/go1.9.2"}
{:id "0f7c65277f916ff4379fe520b875082a56e587eb3ce1c1567d9ff94206bdb05ba167c52272f20f634cd1ebdec5d9dfeb393018bfde1595d8e64a717c8b46692f"
:name "Geth/v1.7.2-stable/linux-amd64/go1.9.1"}])
(deftest test-registered-peer?
(testing "Peer is registered"
(is (mailserver/registered-peer? peers enode)))
(testing "Peer is not peers list"
(is (not (mailserver/registered-peer? peers enode2))))
(testing "Empty peers"
(is (not (mailserver/registered-peer? [] enode))))
(testing "Empty peer"
(is (not (mailserver/registered-peer? peers ""))))
(testing "Nil peer"
(is (not (mailserver/registered-peer? peers nil)))))
(def enode-id "1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40") (def enode-id "1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40")
(def password "password") (def password "password")
(def host "167.99.209.61:30504") (def host "167.99.209.61:30504")
@ -45,25 +81,25 @@
(deftest set-input (deftest set-input
(testing "it validates names" (testing "it validates names"
(testing "correct name" (testing "correct name"
(is (= {:db {:mailservers/manage {:name {:value "value" (is (= {:db {:mailserver.edit/mailserver {:name {:value "value"
:error false}}}} :error false}}}}
(mailserver/set-input {:db {}} :name "value")))) (mailserver/set-input {:db {}} :name "value"))))
(testing "blank name" (testing "blank name"
(is (= {:db {:mailservers/manage {:name {:value "" (is (= {:db {:mailserver.edit/mailserver {:name {:value ""
:error true}}}} :error true}}}}
(mailserver/set-input {:db {}} :name ""))))) (mailserver/set-input {:db {}} :name "")))))
(testing "it validates enodes url" (testing "it validates enodes url"
(testing "correct url" (testing "correct url"
(is (= {:db {:mailservers/manage {:url {:value valid-enode-url (is (= {:db {:mailserver.edit/mailserver {:url {:value valid-enode-url
:error false}}}} :error false}}}}
(mailserver/set-input {:db {}} :url valid-enode-url)))) (mailserver/set-input {:db {}} :url valid-enode-url))))
(testing "broken url" (testing "broken url"
(is (= {:db {:mailservers/manage {:url {:value "broken" (is (= {:db {:mailserver.edit/mailserver {:url {:value "broken"
:error true}}}} :error true}}}}
(mailserver/set-input {:db {}} :url "broken")))))) (mailserver/set-input {:db {}} :url "broken"))))))
(deftest edit-mailserver (deftest edit-mailserver
(let [db {:inbox/wnodes (let [db {:mailserver/mailservers
{:eth.beta {"a" {:id "a" {:eth.beta {"a" {:id "a"
:address valid-enode-address :address valid-enode-address
:password password :password password
@ -78,12 +114,12 @@
:error true} :error true}
:name {:value "" :name {:value ""
:error true}} :error true}}
(-> actual :db :mailservers/manage)))) (-> actual :db :mailserver.edit/mailserver))))
(testing "it navigates to edit-mailserver view" (testing "it navigates to edit-mailserver view"
(is (= :edit-mailserver (is (= :edit-mailserver
(:status-im.ui.screens.navigation/navigate-to actual)))))) (:status-im.ui.screens.navigation/navigate-to actual))))))
(testing "when an id is given" (testing "when an id is given"
(testing "when the wnode is in the list" (testing "when the mailserver is in the list"
(let [actual (mailserver/edit cofx "a")] (let [actual (mailserver/edit cofx "a")]
(testing "it populates the fields with the correct values" (testing "it populates the fields with the correct values"
(is (= {:id {:value "a" (is (= {:id {:value "a"
@ -92,11 +128,11 @@
:error false} :error false}
:name {:value "name" :name {:value "name"
:error false}} :error false}}
(-> actual :db :mailservers/manage)))) (-> actual :db :mailserver.edit/mailserver))))
(testing "it navigates to edit-mailserver view" (testing "it navigates to edit-mailserver view"
(is (= :edit-mailserver (is (= :edit-mailserver
(:status-im.ui.screens.navigation/navigate-to actual)))))) (:status-im.ui.screens.navigation/navigate-to actual))))))
(testing "when the wnode is not in the list" (testing "when the mailserver is not in the list"
(let [actual (mailserver/edit cofx "not-existing")] (let [actual (mailserver/edit cofx "not-existing")]
(testing "it populates the fields with the correct values" (testing "it populates the fields with the correct values"
(is (= {:id {:value nil (is (= {:id {:value nil
@ -105,88 +141,88 @@
:error true} :error true}
:name {:value "" :name {:value ""
:error true}} :error true}}
(-> actual :db :mailservers/manage)))) (-> actual :db :mailserver.edit/mailserver))))
(testing "it navigates to edit-mailserver view" (testing "it navigates to edit-mailserver view"
(is (= :edit-mailserver (is (= :edit-mailserver
(:status-im.ui.screens.navigation/navigate-to actual))))))))) (:status-im.ui.screens.navigation/navigate-to actual)))))))))
(deftest connected-mailserver (deftest connected-mailserver
(testing "it returns true when set in inbox/current-id" (testing "it returns true when set in mailserver/current-id"
(let [cofx {:db {:inbox/current-id "a"}}] (let [cofx {:db {:mailserver/current-id "a"}}]
(is (mailserver/connected? cofx "a")))) (is (mailserver/connected? cofx "a"))))
(testing "it returns false otherwise" (testing "it returns false otherwise"
(is (not (mailserver/connected? {:db {}} "a"))))) (is (not (mailserver/connected? {:db {}} "a")))))
(deftest fetch-mailserver (deftest fetch-mailserver
(testing "it fetches the mailserver from the db" (testing "it fetches the mailserver from the db"
(let [cofx {:db {:inbox/wnodes {:eth.beta {"a" {:id "a" (let [cofx {:db {:mailserver/mailservers {:eth.beta {"a" {:id "a"
:name "old-name" :name "old-name"
:address "enode://old-id:old-password@url:port"}}}}}] :address "enode://old-id:old-password@url:port"}}}}}]
(is (mailserver/fetch cofx "a"))))) (is (mailserver/fetch cofx "a")))))
(deftest fetch-current-mailserver (deftest fetch-current-mailserver
(testing "it fetches the mailserver from the db with corresponding id" (testing "it fetches the mailserver from the db with corresponding id"
(let [cofx {:db {:inbox/current-id "a" (let [cofx {:db {:mailserver/current-id "a"
:inbox/wnodes {:eth.beta {"a" {:id "a" :mailserver/mailservers {:eth.beta {"a" {:id "a"
:name "old-name" :name "old-name"
:address "enode://old-id:old-password@url:port"}}}}}] :address "enode://old-id:old-password@url:port"}}}}}]
(is (mailserver/fetch-current cofx))))) (is (mailserver/fetch-current cofx)))))
(deftest set-current-mailserver (deftest set-current-mailserver
(with-redefs [rand-nth (comp last sort)] (with-redefs [rand-nth (comp last sort)]
(let [cofx {:db {:inbox/wnodes {:eth.beta {"a" {} (let [cofx {:db {:mailserver/mailservers {:eth.beta {"a" {}
"b" {} "b" {}
"c" {} "c" {}
"d" {}}}}}] "d" {}}}}}]
(testing "the user has already a preference" (testing "the user has already a preference"
(let [cofx (assoc-in cofx (let [cofx (assoc-in cofx
[:db :account/account :settings] [:db :account/account :settings]
{:wnode {:eth.beta "a"}})] {:mailserver {:eth.beta "a"}})]
(testing "the mailserver exists" (testing "the mailserver exists"
(testing "it sets the preferred mailserver" (testing "it sets the preferred mailserver"
(is (= "a" (-> (mailserver/set-current-mailserver cofx) (is (= "a" (-> (mailserver/set-current-mailserver cofx)
:db :db
:inbox/current-id))))) :mailserver/current-id)))))
(testing "the mailserver does not exists" (testing "the mailserver does not exists"
(let [cofx (update-in cofx [:db :inbox/wnodes :eth.beta] dissoc "a")] (let [cofx (update-in cofx [:db :mailserver/mailservers :eth.beta] dissoc "a")]
(testing "sets a random mailserver" (testing "sets a random mailserver"
(is (= "d" (-> (mailserver/set-current-mailserver cofx) (is (= "d" (-> (mailserver/set-current-mailserver cofx)
:db :db
:inbox/current-id)))))))) :mailserver/current-id))))))))
(testing "the user has not set an explicit preference" (testing "the user has not set an explicit preference"
(testing "current-id is not set" (testing "current-id is not set"
(testing "it sets a random mailserver" (testing "it sets a random mailserver"
(is (= "d" (-> (mailserver/set-current-mailserver cofx) (is (= "d" (-> (mailserver/set-current-mailserver cofx)
:db :db
:inbox/current-id))))) :mailserver/current-id)))))
(testing "current-id is set" (testing "current-id is set"
(testing "it sets the next mailserver" (testing "it sets the next mailserver"
(is (= "c" (-> (mailserver/set-current-mailserver (assoc-in (is (= "c" (-> (mailserver/set-current-mailserver (assoc-in
cofx cofx
[:db :inbox/current-id] [:db :mailserver/current-id]
"b")) "b"))
:db :db
:inbox/current-id))) :mailserver/current-id)))
(is (= "a" (-> (mailserver/set-current-mailserver (assoc-in (is (= "a" (-> (mailserver/set-current-mailserver (assoc-in
cofx cofx
[:db :inbox/current-id] [:db :mailserver/current-id]
"d")) "d"))
:db :db
:inbox/current-id))) :mailserver/current-id)))
(is (= "a" (-> (mailserver/set-current-mailserver (assoc-in (is (= "a" (-> (mailserver/set-current-mailserver (assoc-in
cofx cofx
[:db :inbox/current-id] [:db :mailserver/current-id]
"non-existing")) "non-existing"))
:db :db
:inbox/current-id))))))))) :mailserver/current-id)))))))))
(deftest delete-mailserver (deftest delete-mailserver
(testing "the user is not connected to the mailserver" (testing "the user is not connected to the mailserver"
(let [cofx {:random-id-generator (constantly "random-id") (let [cofx {:random-id-generator (constantly "random-id")
:db {:inbox/wnodes {:eth.beta {"a" {:id "a" :db {:mailserver/mailservers {:eth.beta {"a" {:id "a"
:name "old-name" :name "old-name"
:user-defined true :user-defined true
:address "enode://old-id:old-password@url:port"}}}}} :address "enode://old-id:old-password@url:port"}}}}}
actual (mailserver/delete cofx "a")] actual (mailserver/delete cofx "a")]
(testing "it removes the mailserver from the list" (testing "it removes the mailserver from the list"
(is (not (mailserver/fetch actual "a")))) (is (not (mailserver/fetch actual "a"))))
@ -194,17 +230,17 @@
(is (= 1 (count (:data-store/tx actual))))))) (is (= 1 (count (:data-store/tx actual)))))))
(testing "the mailserver is not user-defined" (testing "the mailserver is not user-defined"
(let [cofx {:random-id-generator (constantly "random-id") (let [cofx {:random-id-generator (constantly "random-id")
:db {:inbox/wnodes {:eth.beta {"a" {:id "a" :db {:mailserver/mailservers {:eth.beta {"a" {:id "a"
:name "old-name" :name "old-name"
:address "enode://old-id:old-password@url:port"}}}}} :address "enode://old-id:old-password@url:port"}}}}}
actual (mailserver/delete cofx "a")] actual (mailserver/delete cofx "a")]
(testing "it does not delete the mailserver" (testing "it does not delete the mailserver"
(is (= {:dispatch [:navigate-back]} actual))))) (is (= {:dispatch [:navigate-back]} actual)))))
(testing "the user is connected to the mailserver" (testing "the user is connected to the mailserver"
(let [cofx {:random-id-generator (constantly "random-id") (let [cofx {:random-id-generator (constantly "random-id")
:db {:inbox/wnodes {:eth.beta {"a" {:id "a" :db {:mailserver/mailservers {:eth.beta {"a" {:id "a"
:name "old-name" :name "old-name"
:address "enode://old-id:old-password@url:port"}}}}} :address "enode://old-id:old-password@url:port"}}}}}
actual (mailserver/delete cofx "a")] actual (mailserver/delete cofx "a")]
(testing "it does not remove the mailserver from the list" (testing "it does not remove the mailserver from the list"
(is (= {:dispatch [:navigate-back]} actual)))))) (is (= {:dispatch [:navigate-back]} actual))))))
@ -212,19 +248,19 @@
(deftest upsert-mailserver (deftest upsert-mailserver
(testing "new mailserver" (testing "new mailserver"
(let [cofx {:random-id-generator (constantly "random-id") (let [cofx {:random-id-generator (constantly "random-id")
:db {:mailservers/manage {:name {:value "test-name"} :db {:mailserver.edit/mailserver {:name {:value "test-name"}
:url {:value "enode://test-id:test-password@url:port"}} :url {:value "enode://test-id:test-password@url:port"}}
:inbox/wnodes {}}} :mailserver/mailservers {}}}
actual (mailserver/upsert cofx)] actual (mailserver/upsert cofx)]
(testing "it adds the enode to inbox/wnodes" (testing "it adds the enode to mailserver/mailservers"
(is (= {:eth.beta {:randomid {:password "test-password" (is (= {:eth.beta {:randomid {:password "test-password"
:address "enode://test-id@url:port" :address "enode://test-id@url:port"
:name "test-name" :name "test-name"
:id :randomid :id :randomid
:user-defined true}}} :user-defined true}}}
(get-in actual [:db :inbox/wnodes])))) (get-in actual [:db :mailserver/mailservers]))))
(testing "it navigates back" (testing "it navigates back"
(is (= [:navigate-back] (is (= [:navigate-back]
(:dispatch actual)))) (:dispatch actual))))
@ -232,28 +268,93 @@
(is (= 1 (count (:data-store/tx actual))))))) (is (= 1 (count (:data-store/tx actual)))))))
(testing "existing mailserver" (testing "existing mailserver"
(let [cofx {:random-id-generator (constantly "random-id") (let [cofx {:random-id-generator (constantly "random-id")
:db {:mailservers/manage {:id {:value :a} :db {:mailserver.edit/mailserver {:id {:value :a}
:name {:value "new-name"} :name {:value "new-name"}
:url {:value "enode://new-id:new-password@url:port"}} :url {:value "enode://new-id:new-password@url:port"}}
:inbox/wnodes {:eth.beta {:a {:id :a :mailserver/mailservers {:eth.beta {:a {:id :a
:name "old-name" :name "old-name"
:address "enode://old-id:old-password@url:port"}}}}} :address "enode://old-id:old-password@url:port"}}}}}
actual (mailserver/upsert cofx)] actual (mailserver/upsert cofx)]
(testing "it navigates back" (testing "it navigates back"
(is (= [:navigate-back] (is (= [:navigate-back]
(:dispatch actual)))) (:dispatch actual))))
(testing "it updates the enode to inbox/wnodes" (testing "it updates the enode to mailserver/mailservers"
(is (= {:eth.beta {:a {:password "new-password" (is (= {:eth.beta {:a {:password "new-password"
:address "enode://new-id@url:port" :address "enode://new-id@url:port"
:name "new-name" :name "new-name"
:id :a :id :a
:user-defined true}}} :user-defined true}}}
(get-in actual [:db :inbox/wnodes])))) (get-in actual [:db :mailserver/mailservers]))))
(testing "it stores it in the db" (testing "it stores it in the db"
(is (= 1 (count (:data-store/tx actual))))) (is (= 1 (count (:data-store/tx actual)))))
(testing "it logs the user out if connected to the current mailserver" (testing "it logs the user out if connected to the current mailserver"
(let [actual (mailserver/upsert (assoc-in cofx (let [actual (mailserver/upsert (assoc-in cofx
[:db :inbox/current-id] :a))] [:db :mailserver/current-id] :a))]
(is (= [:accounts.logout.ui/logout-confirmed] (is (= [:accounts.logout.ui/logout-confirmed]
(-> actual :data-store/tx first :success-event)))))))) (-> actual :data-store/tx first :success-event))))))))
(defn cofx-fixtures [sym-key registered-peer?]
{:db {:mailserver/state :connected
:peers-summary (if registered-peer?
[{:id "mailserver-id"}]
[])
:account/account {:settings {:fleet :eth.beta}}
:mailserver/current-id "mailserver-a"
:mailserver/mailservers {:eth.beta {"mailserver-a" {:sym-key-id sym-key
:address "enode://mailserver-id@ip"}}}}})
(defn peers-summary-change-result [sym-key registered-peer? registered-peer-before?]
(mailserver/peers-summary-change (cofx-fixtures sym-key
registered-peer?)
(if registered-peer-before?
[{:id "mailserver-id"}]
[])))
(deftest peers-summary-change
(testing "Mailserver added, sym-key doesn't exist"
(let [result (peers-summary-change-result false true false)]
(is (= (into #{} (keys result))
#{:mailserver/mark-trusted-peer :shh/generate-sym-key-from-password :db}))))
(testing "Mailserver disconnected, sym-key exists"
(let [result (peers-summary-change-result true false true)]
(is (= (into #{} (keys result))
#{:db :mailserver/add-peer :utils/dispatch-later}))
(is (= (get-in result [:db :mailserver/state])
:connecting))))
(testing "Mailserver disconnected, sym-key doesn't exists (unlikely situation in practice)"
(let [result (peers-summary-change-result false false true)]
(is (= (into #{} (keys result))
#{:db :mailserver/add-peer :utils/dispatch-later :shh/generate-sym-key-from-password}))
(is (= (get-in result [:db :mailserver/state])
:connecting))))
(testing "Mailserver isn't concerned by peer summary changes"
(is (= (into #{} (keys (peers-summary-change-result true true true)))
#{}))
(is (= (into #{} (keys (peers-summary-change-result true false false)))
#{}))))
(deftest connect-to-mailserver
(let [db {:mailserver/current-id "mailserverid"
:mailserver/mailservers
{:eth.beta {"mailserverid" {:address "mailserver-address"
:password "mailserver-password"}}}
:account/account
{:settings {:fleet :eth.beta
:mailserver {:eth.beta "mailserverid"}}}}]
(testing "it adds the peer"
(is (= "mailserver-address"
(:mailserver/add-peer (mailserver/connect-to-mailserver {:db db})))))
(testing "it generates a sym key if hasn't been generated before"
(is (= "mailserver-password"
(-> (mailserver/connect-to-mailserver {:db db})
:shh/generate-sym-key-from-password
first
:password))))
(let [mailserver-with-sym-key-db (assoc-in db
[:mailserver/mailservers :eth.beta "mailserverid" :sym-key-id]
"somesymkeyid")]
(testing "it does not generate a sym key if already present"
(is (not (-> (mailserver/connect-to-mailserver {:db mailserver-with-sym-key-db})
:shh/generate-sym-key-from-password
first)))))))

View File

@ -1,39 +0,0 @@
(ns status-im.test.protocol.web3.inbox
(:require [status-im.transport.inbox :as inbox]
[status-im.transport.utils :as utils]
[cljs.test :refer-macros [deftest is testing]]))
(def enode "enode://08d8eb6177b187049f6c97ed3f6c74fbbefb94c7ad10bafcaf4b65ce89c314dcfee0a8bc4e7a5b824dfa08b45b360cc78f34f0aff981f8386caa07652d2e601b@163.172.177.138:40404")
(def enode2 "enode://12d8eb6177b187049f6c97ed3f6c74fbbefb94c7ad10bafcaf4b65ce89c314dcfee0a8bc4e7a5b824dfa08b45b360cc78f34f0aff981f8386caa07652d2e601b@163.172.177.138:40404")
(deftest test-extract-enode-id
(testing "Get enode id from enode uri"
(is (= "08d8eb6177b187049f6c97ed3f6c74fbbefb94c7ad10bafcaf4b65ce89c314dcfee0a8bc4e7a5b824dfa08b45b360cc78f34f0aff981f8386caa07652d2e601b"
(utils/extract-enode-id enode))))
(testing "Get enode id from mailformed enode uri"
(is (= ""
(utils/extract-enode-id "08d8eb6177b187049f6c97ed3f6c74fbbefb94c7ad10bafcaf4b65ce89c314dcfee0a8bc4e7a5b824dfa08b45b360cc78f34f0aff981f8386caa07652d2e601b@163.172.177.138:40404"))))
(testing "Test empty string"
(is (= ""
(utils/extract-enode-id ""))))
(testing "Test nil"
(is (= ""
(utils/extract-enode-id nil)))))
(def peers
[{:id "08d8eb6177b187049f6c97ed3f6c74fbbefb94c7ad10bafcaf4b65ce89c314dcfee0a8bc4e7a5b824dfa08b45b360cc78f34f0aff981f8386caa07652d2e601b"
:name "StatusIM/v0.9.9-unstable/linux-amd64/go1.9.2"}
{:id "0f7c65277f916ff4379fe520b875082a56e587eb3ce1c1567d9ff94206bdb05ba167c52272f20f634cd1ebdec5d9dfeb393018bfde1595d8e64a717c8b46692f"
:name "Geth/v1.7.2-stable/linux-amd64/go1.9.1"}])
(deftest test-registered-peer?
(testing "Peer is registered"
(is (inbox/registered-peer? peers enode)))
(testing "Peer is not peers list"
(is (not (inbox/registered-peer? peers enode2))))
(testing "Empty peers"
(is (not (inbox/registered-peer? [] enode))))
(testing "Empty peer"
(is (not (inbox/registered-peer? peers ""))))
(testing "Nil peer"
(is (not (inbox/registered-peer? peers nil)))))

View File

@ -20,7 +20,6 @@
[status-im.test.models.wallet] [status-im.test.models.wallet]
[status-im.test.search.core] [status-im.test.search.core]
[status-im.test.transport.core] [status-im.test.transport.core]
[status-im.test.transport.inbox]
[status-im.test.chat.models] [status-im.test.chat.models]
[status-im.test.chat.models.input] [status-im.test.chat.models.input]
[status-im.test.chat.models.loading] [status-im.test.chat.models.loading]
@ -32,7 +31,6 @@
[status-im.test.chat.commands.input] [status-im.test.chat.commands.input]
[status-im.test.chat.commands.impl.transactions] [status-im.test.chat.commands.impl.transactions]
[status-im.test.i18n] [status-im.test.i18n]
[status-im.test.protocol.web3.inbox]
[status-im.test.utils.utils] [status-im.test.utils.utils]
[status-im.test.utils.money] [status-im.test.utils.money]
[status-im.test.utils.clocks] [status-im.test.utils.clocks]
@ -99,8 +97,6 @@
'status-im.test.i18n 'status-im.test.i18n
'status-im.test.search.core 'status-im.test.search.core
'status-im.test.transport.core 'status-im.test.transport.core
'status-im.test.transport.inbox
'status-im.test.protocol.web3.inbox
'status-im.test.utils.utils 'status-im.test.utils.utils
'status-im.test.utils.money 'status-im.test.utils.money
'status-im.test.utils.clocks 'status-im.test.utils.clocks

View File

@ -32,24 +32,24 @@
:name "name-3" :name "name-3"
:address "address-3" :address "address-3"
:password "password-3"} :password "password-3"}
expected-wnodes {:eth.beta {"1" (-> ms-1 expected-mailservers {:eth.beta {"1" (-> ms-1
(dissoc :fleet) (dissoc :fleet)
(assoc :user-defined true)) (assoc :user-defined true))
"2" (-> ms-2 "2" (-> ms-2
(dissoc ms-2 :fleet) (dissoc ms-2 :fleet)
(assoc :user-defined true))} (assoc :user-defined true))}
:eth.test {"3" (-> ms-3 :eth.test {"3" (-> ms-3
(dissoc :fleet) (dissoc :fleet)
(assoc :user-defined true))}} (assoc :user-defined true))}}
cofx-with-ms (assoc cofx cofx-with-ms (assoc cofx
:data-store/mailservers :data-store/mailservers
[ms-1 [ms-1
ms-2 ms-2
ms-3])] ms-3])]
(is (= expected-wnodes (is (= expected-mailservers
(-> (get-in (-> (get-in
(protocol/initialize-protocol cofx-with-ms "user-address") (protocol/initialize-protocol cofx-with-ms "user-address")
[:db :inbox/wnodes]) [:db :mailserver/mailservers])
(update-in [:eth.beta "1"] dissoc :generating-sym-key?) (update-in [:eth.beta "1"] dissoc :generating-sym-key?)
(update-in [:eth.beta "2"] dissoc :generating-sym-key?) (update-in [:eth.beta "2"] dissoc :generating-sym-key?)
(update-in [:eth.test "3"] dissoc :generating-sym-key?)))))))) (update-in [:eth.test "3"] dissoc :generating-sym-key?))))))))

View File

@ -1,68 +0,0 @@
(ns status-im.test.transport.inbox
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.transport.inbox :as inbox]))
(defn cofx-fixtures [sym-key registered-peer?]
{:db {:mailserver-status :connected
:peers-summary (if registered-peer?
[{:id "wnode-id"}]
[])
:account/account {:settings {:fleet :eth.beta}}
:inbox/current-id "mailserver-a"
:inbox/wnodes {:eth.beta {"mailserver-a" {:sym-key-id sym-key
:address "enode://wnode-id@ip"}}}}})
(defn peers-summary-change-result [sym-key registered-peer? registered-peer-before?]
(inbox/peers-summary-change (cofx-fixtures sym-key
registered-peer?)
(if registered-peer-before?
[{:id "wnode-id"}]
[])))
(deftest peers-summary-change
(testing "Mailserver added, sym-key doesn't exist"
(let [result (peers-summary-change-result false true false)]
(is (= (into #{} (keys result))
#{:transport.inbox/mark-trusted-peer :shh/generate-sym-key-from-password :db}))))
(testing "Mailserver disconnected, sym-key exists"
(let [result (peers-summary-change-result true false true)]
(is (= (into #{} (keys result))
#{:db :transport.inbox/add-peer :utils/dispatch-later}))
(is (= (get-in result [:db :mailserver-status])
:connecting))))
(testing "Mailserver disconnected, sym-key doesn't exists (unlikely situation in practice)"
(let [result (peers-summary-change-result false false true)]
(is (= (into #{} (keys result))
#{:db :transport.inbox/add-peer :utils/dispatch-later :shh/generate-sym-key-from-password}))
(is (= (get-in result [:db :mailserver-status])
:connecting))))
(testing "Mailserver isn't concerned by peer summary changes"
(is (= (into #{} (keys (peers-summary-change-result true true true)))
#{}))
(is (= (into #{} (keys (peers-summary-change-result true false false)))
#{}))))
(deftest connect-to-mailserver
(let [db {:inbox/current-id "wnodeid"
:inbox/wnodes
{:eth.beta {"wnodeid" {:address "wnode-address"
:password "wnode-password"}}}
:account/account
{:settings {:fleet :eth.beta
:wnode {:eth.beta "wnodeid"}}}}]
(testing "it adds the peer"
(is (= "wnode-address"
(:transport.inbox/add-peer (inbox/connect-to-mailserver {:db db})))))
(testing "it generates a sym key if hasn't been generated before"
(is (= "wnode-password"
(-> (inbox/connect-to-mailserver {:db db})
:shh/generate-sym-key-from-password
first
:password))))
(let [wnode-with-sym-key-db (assoc-in db
[:inbox/wnodes :eth.beta "wnodeid" :sym-key-id]
"somesymkeyid")]
(testing "it does not generate a sym key if already present"
(is (not (-> (inbox/connect-to-mailserver {:db wnode-with-sym-key-db})
:shh/generate-sym-key-from-password
first)))))))

View File

@ -242,7 +242,7 @@
"edit-contacts": "Επεξεργασία επαφών", "edit-contacts": "Επεξεργασία επαφών",
"more": "περισσότερα", "more": "περισσότερα",
"cancel": "Ακύρωση", "cancel": "Ακύρωση",
"existing-wnodes": "Υπάρχοντες mailservers", "existing-mailservers": "Υπάρχοντες mailservers",
"no-statuses-found": "Δεν βρέθηκαν καταστάσεις", "no-statuses-found": "Δεν βρέθηκαν καταστάσεις",
"can-not-add-yourself": "Δεν μπορείτε να προσθέσετε τον εαυτό σας", "can-not-add-yourself": "Δεν μπορείτε να προσθέσετε τον εαυτό σας",
"transaction-description": "Περιμένετε τουλάχιστον 12 επιβεβαιώσεις για να βεβαιωθείτε ότι η συναλλαγή σας γίνεται με ασφάλεια", "transaction-description": "Περιμένετε τουλάχιστον 12 επιβεβαιώσεις για να βεβαιωθείτε ότι η συναλλαγή σας γίνεται με ασφάλεια",
@ -299,7 +299,7 @@
"profile": "Προφίλ", "profile": "Προφίλ",
"wallet-choose-recipient": "Επιλογή παραλήπτη", "wallet-choose-recipient": "Επιλογή παραλήπτη",
"no-statuses-discovered": "Δεν βρέθηκαν καταστάσεις", "no-statuses-discovered": "Δεν βρέθηκαν καταστάσεις",
"add-wnode": "Προσθήκη mailserver", "add-mailserver": "Προσθήκη mailserver",
"none": "Κανένα", "none": "Κανένα",
"removed": "αφαιρέθηκες", "removed": "αφαιρέθηκες",
"empty-topic": "Κενό θέμα", "empty-topic": "Κενό θέμα",

View File

@ -495,7 +495,7 @@
"currency-display-name-clp": "Chile Peso", "currency-display-name-clp": "Chile Peso",
"currency-display-name-ghs": "Ghana Cedi", "currency-display-name-ghs": "Ghana Cedi",
"currency-display-name-isk": "Iceland Krona", "currency-display-name-isk": "Iceland Krona",
"connect-wnode-content": "Connect to {{name}}?", "connect-mailserver-content": "Connect to {{name}}?",
"view-cryptostrikers": "View in CryptoStrikers", "view-cryptostrikers": "View in CryptoStrikers",
"view-gitcoin": "View in Gitcoin", "view-gitcoin": "View in Gitcoin",
"view-superrare": "View in SuperRare", "view-superrare": "View in SuperRare",
@ -548,7 +548,7 @@
"edit-contacts": "Edit contacts", "edit-contacts": "Edit contacts",
"more": "more", "more": "more",
"cancel": "Cancel", "cancel": "Cancel",
"existing-wnodes": "Existing mailservers", "existing-mailservers": "Existing mailservers",
"delete-network-confirmation": "Are you sure you want to delete this network?", "delete-network-confirmation": "Are you sure you want to delete this network?",
"no-statuses-found": "No statuses found", "no-statuses-found": "No statuses found",
"extension-address": "Extension address", "extension-address": "Extension address",
@ -659,7 +659,7 @@
"profile": "Profile", "profile": "Profile",
"wallet-choose-recipient": "Choose Recipient", "wallet-choose-recipient": "Choose Recipient",
"no-statuses-discovered": "No statuses discovered", "no-statuses-discovered": "No statuses discovered",
"add-wnode": "Add mailserver", "add-mailserver": "Add mailserver",
"currency-display-name-nzd": "New Zealand Dollar", "currency-display-name-nzd": "New Zealand Dollar",
"none": "None", "none": "None",
"removed": "removed", "removed": "removed",

View File

@ -14,7 +14,7 @@
"add-new-contact": "Agregar nuevo contacto", "add-new-contact": "Agregar nuevo contacto",
"add-new-network": "Agregar red", "add-new-network": "Agregar red",
"add-to-contacts": "Agregar a contactos", "add-to-contacts": "Agregar a contactos",
"add-wnode": "Agregar servidor de correo", "add-mailserver": "Agregar servidor de correo",
"address": "Dirección", "address": "Dirección",
"address-explication": "Tu clave pública se usa para generar tu dirección en Ethereum y es una serie de números y letras. Puedes encontrarlo fácilmente en tu perfil", "address-explication": "Tu clave pública se usa para generar tu dirección en Ethereum y es una serie de números y letras. Puedes encontrarlo fácilmente en tu perfil",
"advanced-settings": "Ajustes avanzados", "advanced-settings": "Ajustes avanzados",
@ -85,7 +85,7 @@
"confirmations": "Confirmaciones", "confirmations": "Confirmaciones",
"confirmations-helper-text": "Cuando la transacción tenga 12 confirmaciones, puede considerarla resuelta.", "confirmations-helper-text": "Cuando la transacción tenga 12 confirmaciones, puede considerarla resuelta.",
"connect": "Conectar", "connect": "Conectar",
"connect-wnode-content": "¿Conectar con {{name}}?", "connect-mailserver-content": "¿Conectar con {{name}}?",
"connected": "Conectado", "connected": "Conectado",
"connecting-requires-login": "Para conectarse a otra red es necesario iniciar sesión", "connecting-requires-login": "Para conectarse a otra red es necesario iniciar sesión",
"connection-problem": "Problema de conexión de mensajes", "connection-problem": "Problema de conexión de mensajes",
@ -285,7 +285,7 @@
"estimated-time": "Tiempo estimado {{time}}", "estimated-time": "Tiempo estimado {{time}}",
"eth": "ETH", "eth": "ETH",
"existing-networks": "Redes existentes", "existing-networks": "Redes existentes",
"existing-wnodes": "Servidores de correo existentes", "existing-mailservers": "Servidores de correo existentes",
"extension": "Extensión", "extension": "Extensión",
"extension-address": "Dirección de extensión", "extension-address": "Dirección de extensión",
"extension-find": "Buscar extensión", "extension-find": "Buscar extensión",

View File

@ -14,7 +14,7 @@
"add-new-contact": "افزودن مخاطب جدید", "add-new-contact": "افزودن مخاطب جدید",
"add-new-network": "افزودن شبکه جدید", "add-new-network": "افزودن شبکه جدید",
"add-to-contacts": "افزودن به مخاطبین", "add-to-contacts": "افزودن به مخاطبین",
"add-wnode": "افزودن Mailserver", "add-mailserver": "افزودن Mailserver",
"address": "آدرس", "address": "آدرس",
"address-explication": "کلید عمومی شما برای تولید آدرس شما روی اتریوم استفاده می شود و یک سری از اعداد و حروف است. شما می توانید آنرا به راحتی در قسمت مشخصات خود پیدا کنید", "address-explication": "کلید عمومی شما برای تولید آدرس شما روی اتریوم استفاده می شود و یک سری از اعداد و حروف است. شما می توانید آنرا به راحتی در قسمت مشخصات خود پیدا کنید",
"advanced-settings": "تنظیمات پیشرفته", "advanced-settings": "تنظیمات پیشرفته",
@ -86,7 +86,7 @@
"confirmations": "تاييديه", "confirmations": "تاييديه",
"confirmations-helper-text": "زمانی که یک تراکنش 12 تایید دریافت کند می توانید آنرا انجام شده در نظر بگیرید", "confirmations-helper-text": "زمانی که یک تراکنش 12 تایید دریافت کند می توانید آنرا انجام شده در نظر بگیرید",
"connect": "اتصال", "connect": "اتصال",
"connect-wnode-content": "اتصال به {{name}}؟", "connect-mailserver-content": "اتصال به {{name}}؟",
"connected": "متصل شده", "connected": "متصل شده",
"connecting-requires-login": "اتصال به شبکه دیگر نیاز به ورود شما به سیستم دارد", "connecting-requires-login": "اتصال به شبکه دیگر نیاز به ورود شما به سیستم دارد",
"connection-problem": "مشکل اتصال به پیام ها", "connection-problem": "مشکل اتصال به پیام ها",
@ -287,7 +287,7 @@
"estimated-time": "زمان تقریبی {{time}}", "estimated-time": "زمان تقریبی {{time}}",
"eth": "ETH", "eth": "ETH",
"existing-networks": "شبکه های موجود", "existing-networks": "شبکه های موجود",
"existing-wnodes": "mailserver های موجود", "existing-mailservers": "mailserver های موجود",
"extension": "افزونه", "extension": "افزونه",
"extension-address": "آدرس افزونه", "extension-address": "آدرس افزونه",
"extension-find": "یافتن افزونه", "extension-find": "یافتن افزونه",

View File

@ -247,7 +247,7 @@
"edit-contacts": "Modifier contacts", "edit-contacts": "Modifier contacts",
"more": "plus", "more": "plus",
"cancel": "Annuler", "cancel": "Annuler",
"existing-wnodes": "Serveurs de mail existants", "existing-mailservers": "Serveurs de mail existants",
"no-statuses-found": "Aucun statut trouvé", "no-statuses-found": "Aucun statut trouvé",
"can-not-add-yourself": "Vous ne pouvez pas vous ajouter vous-même", "can-not-add-yourself": "Vous ne pouvez pas vous ajouter vous-même",
"transaction-description": "Veuillez attendre au moins 12 confirmations pour être sûr que votre transaction a bien été définitivement validée", "transaction-description": "Veuillez attendre au moins 12 confirmations pour être sûr que votre transaction a bien été définitivement validée",

View File

@ -236,7 +236,7 @@
"edit-contacts": "連絡先を編集", "edit-contacts": "連絡先を編集",
"more": "もっと", "more": "もっと",
"cancel": "キャンセル", "cancel": "キャンセル",
"existing-wnodes": "既存のメールサーバー", "existing-mailservers": "既存のメールサーバー",
"no-statuses-found": "ステータスが見つかりませんでした", "no-statuses-found": "ステータスが見つかりませんでした",
"can-not-add-yourself": "自分を追加することはできません", "can-not-add-yourself": "自分を追加することはできません",
"transaction-description": "あなたの取引が安全に処理されることを確認するために少なくとも12回の確認を待ってください。", "transaction-description": "あなたの取引が安全に処理されることを確認するために少なくとも12回の確認を待ってください。",
@ -293,7 +293,7 @@
"profile": "プロフィール", "profile": "プロフィール",
"wallet-choose-recipient": "受信者を選択", "wallet-choose-recipient": "受信者を選択",
"no-statuses-discovered": "ステータスは見つかりませんでした", "no-statuses-discovered": "ステータスは見つかりませんでした",
"add-wnode": "メールサーバーを追加する", "add-mailserver": "メールサーバーを追加する",
"none": "なし", "none": "なし",
"removed": "削除済み", "removed": "削除済み",
"empty-topic": "空のトピック", "empty-topic": "空のトピック",

View File

@ -14,7 +14,7 @@
"add-new-contact": "새 연락처 추가", "add-new-contact": "새 연락처 추가",
"add-new-network": "새 네트워크 추가", "add-new-network": "새 네트워크 추가",
"add-to-contacts": "연락처에 추가", "add-to-contacts": "연락처에 추가",
"add-wnode": "메일서버 추가", "add-mailserver": "메일서버 추가",
"address": "주소", "address": "주소",
"address-explication": "공개 키는 Ethereum 주소를 생성하기 위해 사용되며, 숫자와 알파벳으로 이루어져 있습니다. 프로필에서 쉽게 확인할 수 있습니다.", "address-explication": "공개 키는 Ethereum 주소를 생성하기 위해 사용되며, 숫자와 알파벳으로 이루어져 있습니다. 프로필에서 쉽게 확인할 수 있습니다.",
"advanced-settings": "고급 설정", "advanced-settings": "고급 설정",
@ -87,7 +87,7 @@
"confirmations": "확인", "confirmations": "확인",
"confirmations-helper-text": "12번 확인된 거래는 확정된 것으로 간주됩니다.", "confirmations-helper-text": "12번 확인된 거래는 확정된 것으로 간주됩니다.",
"connect": "접속", "connect": "접속",
"connect-wnode-content": "{{name}}에 연결 하시겠습니까?", "connect-mailserver-content": "{{name}}에 연결 하시겠습니까?",
"connected": "연결됨", "connected": "연결됨",
"connecting-requires-login": "다른 네트워크에 연결하기 위해서는 로그인이 필요합니다", "connecting-requires-login": "다른 네트워크에 연결하기 위해서는 로그인이 필요합니다",
"connection-problem": "메시지 연결 문제", "connection-problem": "메시지 연결 문제",
@ -290,7 +290,7 @@
"estimated-time": "예상 시간 {{time}}", "estimated-time": "예상 시간 {{time}}",
"eth": "ETH", "eth": "ETH",
"existing-networks": "기존 네트워크", "existing-networks": "기존 네트워크",
"existing-wnodes": "기존 메일서버", "existing-mailservers": "기존 메일서버",
"extension": "확장 프로그램", "extension": "확장 프로그램",
"extension-address": "확장 프로그램 주소", "extension-address": "확장 프로그램 주소",
"extension-find": "확장 프로그램 찾기", "extension-find": "확장 프로그램 찾기",

View File

@ -14,7 +14,7 @@
"add-new-contact": "Tambah kenalan baru", "add-new-contact": "Tambah kenalan baru",
"add-new-network": "Tambah rangkaian baru", "add-new-network": "Tambah rangkaian baru",
"add-to-contacts": "Tambah pada senarai kenalan", "add-to-contacts": "Tambah pada senarai kenalan",
"add-wnode": "Tambah mailserver", "add-mailserver": "Tambah mailserver",
"address": "Address", "address": "Address",
"address-explication": "Mungkin disini sepatutnya terdapat sedikit teks menjelaskan apa itu address dan dimana untuk melihatnya", "address-explication": "Mungkin disini sepatutnya terdapat sedikit teks menjelaskan apa itu address dan dimana untuk melihatnya",
"advanced-settings": "Tetapan lanjutan", "advanced-settings": "Tetapan lanjutan",
@ -87,7 +87,7 @@
"confirmations": "Pengesahan", "confirmations": "Pengesahan",
"confirmations-helper-text": "Apabila transaksi mempunyai 12 pengesahan, anda boleh menganggap ia telah diselesaikan.", "confirmations-helper-text": "Apabila transaksi mempunyai 12 pengesahan, anda boleh menganggap ia telah diselesaikan.",
"connect": "Sambung", "connect": "Sambung",
"connect-wnode-content": "Sambung ke {{name}}?", "connect-mailserver-content": "Sambung ke {{name}}?",
"connected": "Bersambung", "connected": "Bersambung",
"connecting-requires-login": "Menyambung ke rangkaian lain memerlukan daftar masuk", "connecting-requires-login": "Menyambung ke rangkaian lain memerlukan daftar masuk",
"connection-problem": "Masalah sambungan mesej", "connection-problem": "Masalah sambungan mesej",
@ -291,7 +291,7 @@
"estimated-time": "Anggaran masa {{time}}", "estimated-time": "Anggaran masa {{time}}",
"eth": "ETH", "eth": "ETH",
"existing-networks": "Rangkaian sedia ada", "existing-networks": "Rangkaian sedia ada",
"existing-wnodes": "Mailserver sedia ada", "existing-mailservers": "Mailserver sedia ada",
"extension": "Sambungan", "extension": "Sambungan",
"extension-address": "Alamat sambungan", "extension-address": "Alamat sambungan",
"extension-find": "Cari sambungan", "extension-find": "Cari sambungan",

View File

@ -14,7 +14,7 @@
"add-new-contact": "Dodaj nowy kontakt", "add-new-contact": "Dodaj nowy kontakt",
"add-new-network": "Dodaj nową sieć", "add-new-network": "Dodaj nową sieć",
"add-to-contacts": "Dodaj do kontaktów", "add-to-contacts": "Dodaj do kontaktów",
"add-wnode": "Dodaj mailserver", "add-mailserver": "Dodaj mailserver",
"address": "Adres", "address": "Adres",
"address-explication": "Być może tutaj powinien znajdować się tekst wyjaśniający, czym jest adres i gdzie go szukać", "address-explication": "Być może tutaj powinien znajdować się tekst wyjaśniający, czym jest adres i gdzie go szukać",
"advanced-settings": "Zaawansowane ustawienia", "advanced-settings": "Zaawansowane ustawienia",
@ -81,7 +81,7 @@
"confirmations": "Potwierdzenia", "confirmations": "Potwierdzenia",
"confirmations-helper-text": "Kiedy transakcja ma 12 potwierdzeń, możesz uznać ją za uregulowaną.", "confirmations-helper-text": "Kiedy transakcja ma 12 potwierdzeń, możesz uznać ją za uregulowaną.",
"connect": "Połącz", "connect": "Połącz",
"connect-wnode-content": "Połącz z {{name}}?", "connect-mailserver-content": "Połącz z {{name}}?",
"connected": "Połączono", "connected": "Połączono",
"connecting-requires-login": "Połączenie z inną siecią wymaga logowania", "connecting-requires-login": "Połączenie z inną siecią wymaga logowania",
"connection-problem": "Problem z połączeniem", "connection-problem": "Problem z połączeniem",
@ -279,7 +279,7 @@
"errors": "Błędy", "errors": "Błędy",
"eth": "ETH", "eth": "ETH",
"existing-networks": "Istniejące sieci", "existing-networks": "Istniejące sieci",
"existing-wnodes": "Istniejące mailserver'y", "existing-mailservers": "Istniejące mailserver'y",
"extension": "Rozszerzenie", "extension": "Rozszerzenie",
"extension-address": "Adres rozszerzenia", "extension-address": "Adres rozszerzenia",
"extension-find": "Znajdź rozszerzenie", "extension-find": "Znajdź rozszerzenie",

View File

@ -14,7 +14,7 @@
"add-new-contact": "Добавить новый контакт", "add-new-contact": "Добавить новый контакт",
"add-new-network": "Добавить новую сеть", "add-new-network": "Добавить новую сеть",
"add-to-contacts": "Добавить в контакты", "add-to-contacts": "Добавить в контакты",
"add-wnode": "Добавить Mailserver", "add-mailserver": "Добавить Mailserver",
"address": "Адрес", "address": "Адрес",
"address-explication": "Ваш публичный ключ используется для создания вашего адреса в Ethereum и представляет собой ряд цифр и букв. Вы можете легко найти его в своем профиле", "address-explication": "Ваш публичный ключ используется для создания вашего адреса в Ethereum и представляет собой ряд цифр и букв. Вы можете легко найти его в своем профиле",
"advanced-settings": "Расширенные настройки", "advanced-settings": "Расширенные настройки",
@ -87,7 +87,7 @@
"confirmations": "Подтверждения", "confirmations": "Подтверждения",
"confirmations-helper-text": "Пожалуйста, дождитесь как минимум 12-ти подтверждений, чтобы убедиться, что транзакция обработана безопасно", "confirmations-helper-text": "Пожалуйста, дождитесь как минимум 12-ти подтверждений, чтобы убедиться, что транзакция обработана безопасно",
"connect": "Подключиться", "connect": "Подключиться",
"connect-wnode-content": "Подключиться к {{name}} ?", "connect-mailserver-content": "Подключиться к {{name}} ?",
"connected": "Подключен", "connected": "Подключен",
"connecting-requires-login": "Подключение к другой сети требует входа в систему", "connecting-requires-login": "Подключение к другой сети требует входа в систему",
"connection-problem": "Проблема с подключением сообщений", "connection-problem": "Проблема с подключением сообщений",
@ -290,7 +290,7 @@
"estimated-time": "Примерное время {{time}}", "estimated-time": "Примерное время {{time}}",
"eth": "ETH", "eth": "ETH",
"existing-networks": "Существующие сети", "existing-networks": "Существующие сети",
"existing-wnodes": "Существующие почтовые серверы", "existing-mailservers": "Существующие почтовые серверы",
"extension": "Расширение", "extension": "Расширение",
"extension-address": "Адрес расширения", "extension-address": "Адрес расширения",
"extension-find": "Найти расширение", "extension-find": "Найти расширение",

View File

@ -232,7 +232,7 @@
"edit-contacts": "Редагування контактів", "edit-contacts": "Редагування контактів",
"more": "більше", "more": "більше",
"cancel": "Скасувати", "cancel": "Скасувати",
"existing-wnodes": "Існуючі поштові сервери", "existing-mailservers": "Існуючі поштові сервери",
"no-statuses-found": "Статуси не виявлені", "no-statuses-found": "Статуси не виявлені",
"can-not-add-yourself": "Ви не можете додати себе", "can-not-add-yourself": "Ви не можете додати себе",
"transaction-description": "Будь ласка, почекайте як мінімум 12 підтверджень, щоб переконатися, що транзакція оброблена безпечно", "transaction-description": "Будь ласка, почекайте як мінімум 12 підтверджень, щоб переконатися, що транзакція оброблена безпечно",
@ -289,7 +289,7 @@
"profile": "Профіль", "profile": "Профіль",
"wallet-choose-recipient": "Виберіть Одержувача", "wallet-choose-recipient": "Виберіть Одержувача",
"no-statuses-discovered": "Статуси не виявлені", "no-statuses-discovered": "Статуси не виявлені",
"add-wnode": "Додати поштовий сервер", "add-mailserver": "Додати поштовий сервер",
"none": "Жоден", "none": "Жоден",
"removed": "видалений", "removed": "видалений",
"empty-topic": "Порожня тема", "empty-topic": "Порожня тема",

View File

@ -14,7 +14,7 @@
"add-new-contact": "添加新的联系人", "add-new-contact": "添加新的联系人",
"add-new-network": "添加新网络", "add-new-network": "添加新网络",
"add-to-contacts": "添加到联系人", "add-to-contacts": "添加到联系人",
"add-wnode": "添加邮件服务器", "add-mailserver": "添加邮件服务器",
"address": "地址", "address": "地址",
"address-explication": "你的公钥可以用来生成以太坊地址,由一系列数字和字母组成,可以在个人简介中轻松地找到。", "address-explication": "你的公钥可以用来生成以太坊地址,由一系列数字和字母组成,可以在个人简介中轻松地找到。",
"advanced-settings": "高级设置", "advanced-settings": "高级设置",
@ -87,7 +87,7 @@
"confirmations": "确认", "confirmations": "确认",
"confirmations-helper-text": "请等待达到至少12个确认来确保交易已被安全地处理。", "confirmations-helper-text": "请等待达到至少12个确认来确保交易已被安全地处理。",
"connect": "连接", "connect": "连接",
"connect-wnode-content": "连接到{{name}} ", "connect-mailserver-content": "连接到{{name}} ",
"connected": "已连接", "connected": "已连接",
"connecting-requires-login": "连接其它网络需要登录", "connecting-requires-login": "连接其它网络需要登录",
"connection-problem": "消息连接问题", "connection-problem": "消息连接问题",
@ -291,7 +291,7 @@
"estimated-time": "预估时间{{time}}", "estimated-time": "预估时间{{time}}",
"eth": "ETH", "eth": "ETH",
"existing-networks": "已有的网络", "existing-networks": "已有的网络",
"existing-wnodes": "现有的邮件服务器", "existing-mailservers": "现有的邮件服务器",
"extension": "扩展", "extension": "扩展",
"extension-address": "扩展地址", "extension-address": "扩展地址",
"extension-find": "查找扩展", "extension-find": "查找扩展",