parent
dc8976a8b2
commit
efdd76b364
|
@ -26,7 +26,6 @@
|
|||
(def snoopy-filter #js {})
|
||||
(def snoopy-bars #js {})
|
||||
(def snoopy-buffer #js {})
|
||||
(def background-timer #js {:setTimeout (fn [])})
|
||||
(def background-timer #js {:setTimeout (fn [cb ms] (js/setTimeout cb ms))})
|
||||
(def testfairy #js {})
|
||||
(def react-navigation #js {:NavigationActions #js {}})
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
(ns status-im.accounts.update.core
|
||||
(:require [status-im.data-store.accounts :as accounts-store]
|
||||
[status-im.transport.message.core :as transport]
|
||||
[status-im.transport.message.v1.contact :as message.contact]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.transport.message.contact :as message.contact]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
(fx/defn account-update
|
||||
|
@ -18,7 +18,7 @@
|
|||
(if (or (:name new-account-fields) (:photo-path new-account-fields))
|
||||
(fx/merge cofx
|
||||
fx
|
||||
#(transport/send (message.contact/ContactUpdate. name photo-path address fcm-token) nil %))
|
||||
#(protocol/send (message.contact/ContactUpdate. name photo-path address fcm-token) nil %))
|
||||
fx)))
|
||||
|
||||
(fx/defn clean-seed-phrase
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
;; Seen messages
|
||||
(fx/defn receive-seen
|
||||
[{:keys [db js-obj]} chat-id sender {:keys [message-ids]}]
|
||||
(merge {:confirm-messages-processed [{:web3 (:web3 db)
|
||||
(merge {:transport/confirm-messages-processed [{:web3 (:web3 db)
|
||||
:js-obj js-obj}]}
|
||||
(when-let [seen-messages-ids (-> (get-in db [:chats chat-id :messages])
|
||||
(select-keys message-ids)
|
||||
|
|
|
@ -1,23 +1,18 @@
|
|||
(ns status-im.chat.models
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.data-store.chats :as chats-store]
|
||||
[status-im.data-store.messages :as messages-store]
|
||||
[status-im.data-store.user-statuses :as user-statuses-store]
|
||||
[status-im.transport.message.core :as transport.message]
|
||||
[status-im.transport.message.v1.protocol :as protocol]
|
||||
[status-im.transport.message.v1.core :as transport]
|
||||
[status-im.transport.message.v1.public-chat :as public-chat]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.ui.components.styles :as styles]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.transport.chat.core :as transport.chat]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.transport.message.public-chat :as public-chat]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.ui.components.colors :as colors]))
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.utils.utils :as utils]))
|
||||
|
||||
(defn multi-user-chat? [cofx chat-id]
|
||||
(get-in cofx [:db :chats chat-id :group-chat]))
|
||||
|
@ -105,10 +100,6 @@
|
|||
:data-store/tx [(chats-store/clear-history-tx chat-id last-message-clock-value)
|
||||
(messages-store/delete-messages-tx chat-id)]}))
|
||||
|
||||
(fx/defn remove-transport
|
||||
[cofx chat-id]
|
||||
(transport.utils/unsubscribe-from-chat cofx chat-id))
|
||||
|
||||
(fx/defn deactivate-chat
|
||||
[{:keys [db now] :as cofx} chat-id]
|
||||
{:db (-> db
|
||||
|
@ -127,7 +118,7 @@
|
|||
[{:keys [db now] :as cofx} chat-id]
|
||||
(fx/merge cofx
|
||||
#(when (public-chat? % chat-id)
|
||||
(remove-transport % chat-id))
|
||||
(transport.chat/unsubscribe-from-chat % chat-id))
|
||||
(deactivate-chat chat-id)
|
||||
(clear-history chat-id)
|
||||
(navigation/navigate-to-cofx :home {})))
|
||||
|
@ -135,7 +126,7 @@
|
|||
(fx/defn send-messages-seen
|
||||
[{:keys [db] :as cofx} chat-id message-ids]
|
||||
(when (not (get-in db [:chats chat-id :group-chat]))
|
||||
(transport.message/send (protocol/map->MessagesSeen {:message-ids message-ids}) chat-id cofx)))
|
||||
(protocol/send (protocol/map->MessagesSeen {:message-ids message-ids}) chat-id cofx)))
|
||||
|
||||
;; TODO (janherich) - ressurect `constants/system` messages for group chats in the future
|
||||
(fx/defn mark-messages-seen
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
(ns status-im.chat.models.input
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[goog.object :as object]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.chat.models.message :as chat.message]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.input :as commands.input]
|
||||
[status-im.chat.commands.sending :as commands.sending]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.chat.models.message :as chat.message]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.js-dependencies :as dependencies]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
(ns status-im.chat.models.loading
|
||||
(:require [clojure.set :as set]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im.data-store.user-statuses :as user-statuses-store]
|
||||
[status-im.utils.contacts :as utils.contacts]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
[status-im.utils.types :as types]
|
||||
[status-im.notifications.core :as notifications]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.transport.message.core :as transport]
|
||||
[status-im.transport.message.v1.protocol :as protocol]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.data-store.messages :as messages-store]
|
||||
[status-im.data-store.user-statuses :as user-statuses-store]
|
||||
[status-im.utils.fx :as fx]
|
||||
|
@ -94,7 +93,7 @@
|
|||
(fx/defn send-message-seen
|
||||
[cofx chat-id message-id send-seen?]
|
||||
(when send-seen?
|
||||
(transport/send (protocol/map->MessagesSeen {:message-ids #{message-id}}) chat-id cofx)))
|
||||
(protocol/send (protocol/map->MessagesSeen {:message-ids #{message-id}}) chat-id cofx)))
|
||||
|
||||
(defn ensure-clock-value [{:keys [clock-value] :as message} {:keys [last-clock-value]}]
|
||||
(if clock-value
|
||||
|
@ -127,7 +126,7 @@
|
|||
;; TODO (cammellos): Refactor so it's not computed twice
|
||||
(add-outgoing-status cofx))]
|
||||
(fx/merge cofx
|
||||
{:confirm-messages-processed [{:web3 web3
|
||||
{:transport/confirm-messages-processed [{:web3 web3
|
||||
:js-obj js-obj}]}
|
||||
(add-message batch? message current-chat?)
|
||||
;; Checking :outgoing here only works for now as we don't have a :seen
|
||||
|
@ -216,7 +215,7 @@
|
|||
(group-chats/wrap-group-message cofx chat-id send-record)
|
||||
send-record)]
|
||||
|
||||
(transport/send wrapped-record chat-id cofx))))
|
||||
(protocol/send wrapped-record chat-id cofx))))
|
||||
|
||||
(defn add-message-type [message {:keys [chat-id group-chat public?]}]
|
||||
(cond-> message
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.data-store.realm.schemas.account.core
|
||||
(: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-inbox-topic :as transport-inbox-topic]
|
||||
[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.user-status :as user-status]
|
||||
|
@ -143,18 +144,22 @@
|
|||
browser/v8
|
||||
dapp-permissions/v9])
|
||||
|
||||
(def v14 [chat/v6
|
||||
(def v14 v13)
|
||||
|
||||
(def v15 [chat/v7
|
||||
transport/v6
|
||||
contact/v1
|
||||
message/v7
|
||||
mailserver/v11
|
||||
user-status/v1
|
||||
membership-update/v1
|
||||
local-storage/v1
|
||||
browser/v8
|
||||
dapp-permissions/v9])
|
||||
|
||||
(def v15 [chat/v7
|
||||
transport/v6
|
||||
(def v16 [chat/v7
|
||||
transport/v7
|
||||
transport-inbox-topic/v1
|
||||
contact/v1
|
||||
message/v7
|
||||
mailserver/v11
|
||||
|
@ -209,4 +214,7 @@
|
|||
:migration migrations/v14}
|
||||
{:schema v15
|
||||
:schemaVersion 15
|
||||
:migration migrations/v15}])
|
||||
:migration migrations/v15}
|
||||
{:schema v16
|
||||
:schemaVersion 16
|
||||
:migration migrations/v16}])
|
||||
|
|
|
@ -97,3 +97,6 @@
|
|||
|
||||
(defn v15 [old-realm new-realm]
|
||||
(log/debug "migrating v15 account database"))
|
||||
|
||||
(defn v16 [old-realm new-realm]
|
||||
(log/debug "migrating v16 account database"))
|
||||
|
|
|
@ -47,3 +47,20 @@
|
|||
;;TODO (yenda) remove once go implements persistence
|
||||
:sym-key {:type :string
|
||||
:optional true}}})
|
||||
|
||||
(def v7 {:name :transport
|
||||
:primaryKey :chat-id
|
||||
:properties {:chat-id :string
|
||||
:ack :string
|
||||
:seen :string
|
||||
:pending-ack :string
|
||||
:pending-send :string
|
||||
:topic {:type :string
|
||||
:optional true}
|
||||
:resend? {:type :string
|
||||
:optional true}
|
||||
:sym-key-id {:type :string
|
||||
:optional true}
|
||||
;;TODO (yenda) remove once go implements persistence
|
||||
:sym-key {:type :string
|
||||
:optional true}}})
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
(ns status-im.data-store.realm.schemas.account.transport-inbox-topic)
|
||||
|
||||
(def v1 {:name :transport-inbox-topic
|
||||
:primaryKey :topic
|
||||
:properties {:topic :string
|
||||
:chat-ids :string
|
||||
:last-request {:type :int :default 1}}})
|
|
@ -44,3 +44,39 @@
|
|||
(let [transport (core/single
|
||||
(core/get-by-field realm :transport :chat-id chat-id))]
|
||||
(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))))
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
[status-im.bootnodes.core :as bootnodes]
|
||||
[status-im.browser.core :as browser]
|
||||
[status-im.browser.permissions :as browser.permissions]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.chat.models.message :as chat.message]
|
||||
[status-im.chat.models.loading :as chat.loading]
|
||||
[status-im.chat.models.input :as chat.input]
|
||||
[status-im.chat.commands.input :as commands.input]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.chat.models.input :as chat.input]
|
||||
[status-im.chat.models.loading :as chat.loading]
|
||||
[status-im.chat.models.message :as chat.message]
|
||||
[status-im.data-store.core :as data-store]
|
||||
[status-im.fleet.core :as fleet]
|
||||
[status-im.group-chats.core :as group-chats]
|
||||
|
@ -28,6 +28,8 @@
|
|||
[status-im.protocol.core :as protocol]
|
||||
[status-im.qr-scanner.core :as qr-scanner]
|
||||
[status-im.signals.core :as signals]
|
||||
[status-im.transport.inbox :as inbox]
|
||||
[status-im.transport.message.core :as transport.message]
|
||||
[status-im.ui.screens.currency-settings.models
|
||||
:as
|
||||
currency-settings.models]
|
||||
|
@ -89,6 +91,7 @@
|
|||
(re-frame/inject-cofx :data-store/get-all-contacts)
|
||||
(re-frame/inject-cofx :data-store/get-all-mailservers)
|
||||
(re-frame/inject-cofx :data-store/transport)
|
||||
(re-frame/inject-cofx :data-store/transport-inbox-topics)
|
||||
(re-frame/inject-cofx :data-store/all-browsers)
|
||||
(re-frame/inject-cofx :data-store/all-dapp-permissions)]
|
||||
(fn [cofx [_ address]]
|
||||
|
@ -938,7 +941,65 @@
|
|||
(fn [cofx [_ group-update sender-signature]]
|
||||
(group-chats/handle-membership-update cofx group-update sender-signature)))
|
||||
|
||||
;; profile module
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:profile.ui/ens-names-button-pressed
|
||||
(fn [cofx]
|
||||
(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)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:inbox.callback/request-messages-success
|
||||
(fn [cofx [_ request]]
|
||||
(inbox/add-request cofx request)))
|
||||
|
||||
;; transport module
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:transport/messages-received
|
||||
[handlers/logged-in (re-frame/inject-cofx :random-id-generator)]
|
||||
(fn [cofx [_ js-error js-messages chat-id]]
|
||||
(transport.message/receive-whisper-messages cofx js-error js-messages chat-id)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:transport/send-status-message-error
|
||||
(fn [{:keys [db] :as cofx} [_ err]]
|
||||
(log/error :send-status-message-error err)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:transport/message-sent
|
||||
(fn [cofx [_ chat-id message-id message-type envelope-hash-js]]
|
||||
(transport.message/set-message-envelope-hash cofx chat-id message-id message-type envelope-hash-js)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:transport/contact-message-sent
|
||||
(fn [cofx [_ chat-id envelope-hash]]
|
||||
(transport.message/set-contact-message-envelope-hash cofx chat-id envelope-hash)))
|
||||
|
|
|
@ -11,9 +11,8 @@
|
|||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.transport.db :as transport.db]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.transport.message.core :as protocol.message]
|
||||
[status-im.transport.message.v1.core :as transport]
|
||||
[status-im.transport.message.v1.protocol :as transport.protocol]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.transport.message.group-chat :as message.group-chat]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.chat.models :as models.chat]))
|
||||
|
||||
|
@ -105,7 +104,7 @@
|
|||
"Wrap a group message in a membership update"
|
||||
[cofx chat-id message]
|
||||
(when-let [chat (get-in cofx [:db :chats chat-id])]
|
||||
(transport/map->GroupMembershipUpdate.
|
||||
(message.group-chat/map->GroupMembershipUpdate.
|
||||
{:chat-id chat-id
|
||||
:membership-updates (:membership-updates chat)
|
||||
:message message})))
|
||||
|
@ -123,7 +122,7 @@
|
|||
{:shh/send-group-message {:web3 web3
|
||||
:src current-public-key
|
||||
:dsts (disj members current-public-key)
|
||||
:success-event [:transport/set-message-envelope-hash
|
||||
:success-event [:transport/message-sent
|
||||
chat-id
|
||||
(transport.utils/message-id (:message payload))
|
||||
:group-user-message]
|
||||
|
@ -137,7 +136,7 @@
|
|||
(defn chat->group-update
|
||||
"Transform a chat in a GroupMembershipUpdate"
|
||||
[chat-id {:keys [membership-updates]}]
|
||||
(transport/map->GroupMembershipUpdate. {:chat-id chat-id
|
||||
(message.group-chat/map->GroupMembershipUpdate. {:chat-id chat-id
|
||||
:membership-updates membership-updates}))
|
||||
|
||||
(defn handle-sign-response
|
||||
|
@ -312,9 +311,9 @@
|
|||
(update-membership previous-chat membership-update)
|
||||
#(when (and message
|
||||
;; don't allow anything but group messages
|
||||
(instance? transport.protocol/Message message)
|
||||
(instance? protocol/Message message)
|
||||
(= :group-user-message (:message-type message)))
|
||||
(protocol.message/receive message chat-id sender-signature nil %))))))
|
||||
(protocol/receive message chat-id sender-signature nil %))))))
|
||||
|
||||
(defn handle-sign-success
|
||||
"Upsert chat and send signed payload to group members"
|
||||
|
|
|
@ -110,11 +110,6 @@
|
|||
{:db (assoc db :inbox/current-id
|
||||
(selected-or-random-id cofx))})
|
||||
|
||||
(fx/defn set-initial-last-request
|
||||
[{:keys [db now] :as cofx}]
|
||||
{:db (update-in db [:account/account :last-request]
|
||||
(fnil identity (quot now 1000)))})
|
||||
|
||||
(fx/defn add-custom-mailservers
|
||||
[{:keys [db]} mailservers]
|
||||
{:db (reduce (fn [db {:keys [id fleet] :as mailserver}]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
(ns status-im.models.contact
|
||||
(:require [status-im.data-store.contacts :as contacts-store]
|
||||
[status-im.transport.message.core :as transport]
|
||||
[status-im.transport.message.v1.contact :as message.v1.contact]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.transport.message.contact :as message.contact]
|
||||
[status-im.utils.contacts :as utils.contacts]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
|
@ -39,8 +39,8 @@
|
|||
[{:keys [db] :as cofx} {:keys [whisper-identity pending? dapp?] :as contact}]
|
||||
(when-not dapp?
|
||||
(if pending?
|
||||
(transport/send (message.v1.contact/map->ContactRequestConfirmed (own-info db)) whisper-identity cofx)
|
||||
(transport/send (message.v1.contact/map->ContactRequest (own-info db)) whisper-identity cofx))))
|
||||
(protocol/send (message.contact/map->ContactRequestConfirmed (own-info db)) whisper-identity cofx)
|
||||
(protocol/send (message.contact/map->ContactRequest (own-info db)) whisper-identity cofx))))
|
||||
|
||||
(fx/defn add-contact [{:keys [db] :as cofx} whisper-id]
|
||||
(let [contact (build-contact whisper-id cofx)]
|
||||
|
|
|
@ -157,7 +157,7 @@
|
|||
[{:keys [db] :as cofx} is-connected?]
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :network-status (if is-connected? :online :offline))}
|
||||
(inbox/request-messages)))
|
||||
(inbox/request-messages nil)))
|
||||
|
||||
(defn- navigate-to-network-details
|
||||
[cofx network show-warning?]
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
[status-im.transport.core :as transport]
|
||||
[status-im.transport.inbox :as transport.inbox]
|
||||
[status-im.utils.ethereum.core :as ethereum]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.semaphores :as semaphores]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[status-im.utils.utils :as utils]))
|
||||
|
||||
(fx/defn update-sync-state
|
||||
[{{:keys [sync-state sync-data] :as db} :db} error sync]
|
||||
|
@ -44,13 +44,15 @@
|
|||
(semaphores/lock :check-sync-state?))))
|
||||
|
||||
(fx/defn initialize-protocol
|
||||
[{:data-store/keys [transport mailservers] :keys [db web3] :as cofx} address]
|
||||
[{:data-store/keys [transport transport-inbox-topics mailservers]
|
||||
:keys [db web3] :as cofx} address]
|
||||
(let [network (get-in db [:account/account :network])
|
||||
network-id (str (get-in db [:account/account :networks network :config :NetworkId]))]
|
||||
(fx/merge cofx
|
||||
{:db (assoc db
|
||||
:rpc-url constants/ethereum-rpc-url
|
||||
:transport/chats transport)
|
||||
:transport/chats transport
|
||||
:transport.inbox/topics transport-inbox-topics)
|
||||
:protocol/assert-correct-network {:web3 web3
|
||||
:network-id network-id}}
|
||||
(start-check-sync-state)
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
[status-im.accounts.login.core :as accounts.login]
|
||||
[status-im.init.core :as init]
|
||||
[status-im.node.core :as node]
|
||||
[status-im.transport.handlers :as transport.handlers]
|
||||
[status-im.transport.inbox :as inbox]
|
||||
[status-im.transport.message.core :as transport.message]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.types :as types]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(fx/defn status-node-started
|
||||
[{db :db :as cofx}]
|
||||
|
@ -33,7 +33,7 @@
|
|||
{:db (assoc db
|
||||
:peers-summary peers-summary
|
||||
:peers-count peers-count)}
|
||||
(transport.handlers/resend-contact-messages previous-summary)
|
||||
(transport.message/resend-contact-messages previous-summary)
|
||||
(inbox/peers-summary-change previous-summary))))
|
||||
|
||||
(fx/defn process
|
||||
|
@ -43,7 +43,12 @@
|
|||
"node.ready" (status-node-started cofx)
|
||||
"node.stopped" (status-node-stopped cofx)
|
||||
"module.initialized" (status-module-initialized cofx)
|
||||
"envelope.sent" (transport.handlers/update-envelope-status cofx (:hash event) :sent)
|
||||
"envelope.expired" (transport.handlers/update-envelope-status cofx (:hash event) :sent)
|
||||
"envelope.sent" (transport.message/update-envelope-status cofx (:hash event) :sent)
|
||||
"envelope.expired" (transport.message/update-envelope-status cofx (:hash event) :sent)
|
||||
"mailserver.request.completed" (when (accounts.db/logged-in? cofx)
|
||||
(inbox/update-inbox-topic cofx {:request-id (:requestID event)
|
||||
:cursor (:cursor event)}))
|
||||
"mailserver.request.expired" (when (accounts.db/logged-in? cofx)
|
||||
(inbox/resend-request cofx {:request-id (:hash event)}))
|
||||
"discovery.summary" (summary cofx event)
|
||||
(log/debug "Event " type " not handled"))))
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
(ns status-im.transport.chat.core
|
||||
(:require [status-im.data-store.transport :as transport-store]
|
||||
[status-im.transport.inbox :as inbox]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
(fx/defn remove-transport-chat
|
||||
[{:keys [db]} chat-id]
|
||||
{:db (update db :transport/chats dissoc chat-id)
|
||||
:data-store/tx [(transport-store/delete-transport-tx chat-id)]
|
||||
:shh/remove-filter (get-in db [:transport/filters chat-id])})
|
||||
|
||||
(fx/defn unsubscribe-from-chat
|
||||
"Unsubscribe from chat on transport layer"
|
||||
[cofx chat-id]
|
||||
(fx/merge cofx
|
||||
(inbox/remove-chat-from-inbox-topic chat-id)
|
||||
(remove-transport-chat chat-id)))
|
|
@ -4,12 +4,13 @@
|
|||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.transport :as transport-store]
|
||||
[status-im.transport.handlers :as transport.handlers]
|
||||
[status-im.transport.inbox :as inbox]
|
||||
[status-im.transport.message.core :as message]
|
||||
[status-im.transport.shh :as shh]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(fx/defn init-whisper
|
||||
"Initialises whisper protocol by:
|
||||
|
@ -19,6 +20,7 @@
|
|||
[{:keys [db web3] :as cofx} current-account-id]
|
||||
(log/debug :init-whisper)
|
||||
(when-let [public-key (get-in db [:account/account :public-key])]
|
||||
|
||||
(let [sym-key-added-callback (fn [chat-id sym-key sym-key-id]
|
||||
(re-frame/dispatch [::sym-key-added {:chat-id chat-id
|
||||
:sym-key sym-key
|
||||
|
@ -32,7 +34,7 @@
|
|||
:transport (:transport/chats db)
|
||||
:on-success sym-key-added-callback}}
|
||||
(inbox/connect-to-mailserver)
|
||||
(transport.handlers/resend-contact-messages [])))))
|
||||
(message/resend-contact-messages [])))))
|
||||
|
||||
;;TODO (yenda) remove once go implements persistence
|
||||
;;Since symkeys are not persisted, we restore them via add sym-keys,
|
||||
|
@ -67,7 +69,5 @@
|
|||
to clean-up after logout. When logging out of account A and logging in account B, account B would receive
|
||||
account A messages without this."
|
||||
[{:keys [db]}]
|
||||
(let [{:transport/keys [chats discovery-filter]} db
|
||||
chat-filters (keep :filter (vals chats))
|
||||
all-filters (conj chat-filters discovery-filter)]
|
||||
{:shh/remove-filters all-filters}))
|
||||
(let [{:transport/keys [filters]} db]
|
||||
{:shh/remove-filters (vals filters)}))
|
||||
|
|
|
@ -1,41 +1,61 @@
|
|||
(ns ^{:doc "DB spec and utils for the transport layer"}
|
||||
status-im.transport.db
|
||||
(:require-macros [status-im.utils.db :refer [allowed-keys]])
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
[clojure.string :as s]
|
||||
status-im.ui.screens.contacts.db
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[clojure.string :as s]))
|
||||
[status-im.utils.clocks :as utils.clocks])
|
||||
(:require-macros [status-im.utils.db :refer [allowed-keys]]))
|
||||
|
||||
;; required
|
||||
(spec/def ::ack (spec/coll-of string? :kind vector?))
|
||||
(spec/def ::seen (spec/coll-of string? :kind vector?))
|
||||
(spec/def ::pending-ack (spec/coll-of string? :kind vector?))
|
||||
(spec/def ::pending-send (spec/coll-of string? :kind vector?))
|
||||
(spec/def ::topic string?)
|
||||
(spec/def ::fetch-history? boolean?)
|
||||
(spec/def ::resend? (spec/nilable #{"contact-request" "contact-request-confirmation" "contact-update"}))
|
||||
(spec/def ::request-from pos-int?)
|
||||
|
||||
;; optional
|
||||
(spec/def ::topic (spec/nilable string?))
|
||||
(spec/def ::request-id (spec/nilable string?))
|
||||
(spec/def ::request-to (spec/nilable pos-int?))
|
||||
(spec/def ::sym-key-id (spec/nilable string?))
|
||||
;;TODO (yenda) remove once go implements persistence
|
||||
(spec/def ::sym-key (spec/nilable string?))
|
||||
(spec/def ::filter any?)
|
||||
(spec/def :transport/filter-id (spec/or :keyword keyword?
|
||||
:chat-id :global/not-empty-string))
|
||||
(spec/def :transport/filter any?)
|
||||
(spec/def :request/from pos-int?)
|
||||
(spec/def :request/to pos-int?)
|
||||
(spec/def :request/cursor :global/not-empty-string)
|
||||
(spec/def :transport.inbox/request (spec/keys :req-un [:request/from :request/to ::topic]))
|
||||
(spec/def ::request-from pos-int?)
|
||||
(spec/def :transport.inbox.topic/last-request ::request-from)
|
||||
(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/request-pending? boolean?)
|
||||
|
||||
(spec/def :transport/chat (allowed-keys :req-un [::ack ::seen ::pending-ack ::pending-send ::topic ::fetch-history?]
|
||||
:opt-un [::sym-key-id ::sym-key ::filter ::resend?]))
|
||||
(spec/def :transport.inbox/topic (allowed-keys :req-un [:transport.inbox.topic/last-request
|
||||
:transport.inbox.topic/chat-ids]
|
||||
:opt-un [:transport.inbox.topic/request-pending?]))
|
||||
(spec/def :transport/chat (allowed-keys :req-un [::ack ::seen ::pending-ack ::pending-send ::topic]
|
||||
:opt-un [::sym-key-id ::sym-key ::resend?]))
|
||||
|
||||
(spec/def :transport/chats (spec/map-of :global/not-empty-string :transport/chat))
|
||||
(spec/def :transport/discovery-filter (spec/nilable any?))
|
||||
(spec/def :transport/filters (spec/map-of :transport/filter-id :transport/filter))
|
||||
(spec/def :transport.inbox/topics (spec/map-of :global/not-empty-string :transport.inbox/topic))
|
||||
(spec/def :transport.inbox/requests (spec/map-of :global/not-empty-string :transport.inbox/request))
|
||||
|
||||
(defn create-chat
|
||||
"Initialize datastructure for chat representation at the transport level
|
||||
Currently only :topic is actually used"
|
||||
[{:keys [topic resend?]}]
|
||||
[{:keys [topic resend? now]}]
|
||||
{:ack []
|
||||
:seen []
|
||||
:pending-ack []
|
||||
:pending-send []
|
||||
:fetch-history? true
|
||||
:resend? resend?
|
||||
:topic topic})
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
(ns ^{:doc "API for whisper filters"}
|
||||
status-im.transport.filters
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.transport.inbox :as inbox]
|
||||
[status-im.transport.utils :as utils]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn remove-filter! [filter]
|
||||
|
@ -14,47 +15,41 @@
|
|||
(log/debug :removed-filter filter))))
|
||||
(log/debug :stop-watching filter))
|
||||
|
||||
(defn add-shh-filter!
|
||||
[web3 options callback]
|
||||
(.newMessageFilter (utils/shh web3) (clj->js options)
|
||||
callback
|
||||
#(log/warn :add-filter-error (.stringify js/JSON (clj->js options)) %)))
|
||||
|
||||
(defn add-filter!
|
||||
[web3 {:keys [topics to] :as options} callback]
|
||||
[web3 {:keys [topics to] :as options} callback chat-id]
|
||||
(let [options (assoc options :allowP2P true)]
|
||||
(log/debug :add-filter options)
|
||||
(add-shh-filter! web3 options callback)))
|
||||
(when-let [filter (.newMessageFilter (utils/shh web3)
|
||||
(clj->js options)
|
||||
callback
|
||||
#(log/warn :add-filter-error (.stringify js/JSON (clj->js options)) %))]
|
||||
(re-frame/dispatch [:shh.callback/filter-added (first topics) chat-id filter]))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:shh/add-filter
|
||||
(fn [{:keys [web3 sym-key-id topic chat-id]}]
|
||||
(when-let [filter (add-filter! web3
|
||||
{:topics [topic]
|
||||
(let [params {:topics [topic]
|
||||
:symKeyID sym-key-id}
|
||||
(fn [js-error js-message]
|
||||
(re-frame/dispatch [:protocol/receive-whisper-message js-error js-message chat-id])))]
|
||||
(re-frame/dispatch [::filter-added chat-id filter]))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::filter-added
|
||||
(fn [{:keys [db]} [_ chat-id filter]]
|
||||
{:db (assoc-in db [:transport/chats chat-id :filter] filter)}))
|
||||
callback (fn [js-error js-message]
|
||||
(re-frame/dispatch [:transport/messages-received js-error js-message chat-id]))]
|
||||
(add-filter! web3 params callback chat-id))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:shh/add-discovery-filter
|
||||
(fn [{:keys [web3 private-key-id topic]}]
|
||||
(when-let [filter (add-filter! web3
|
||||
{:topics [topic]
|
||||
(let [params {:topics [topic]
|
||||
:privateKeyID private-key-id}
|
||||
(fn [js-error js-message]
|
||||
(re-frame/dispatch [:protocol/receive-whisper-message js-error js-message])))]
|
||||
(re-frame/dispatch [::discovery-filter-added filter]))))
|
||||
callback (fn [js-error js-message]
|
||||
(re-frame/dispatch [:transport/messages-received js-error js-message]))]
|
||||
(add-filter! web3 params callback :discovery-topic))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::discovery-filter-added
|
||||
(fn [{:keys [db]} [_ filter]]
|
||||
{:db (assoc db :transport/discovery-filter filter)}))
|
||||
:shh.callback/filter-added
|
||||
(fn [{:keys [db] :as cofx} [_ topic chat-id filter]]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:transport/filters chat-id] filter)}
|
||||
(inbox/upsert-inbox-topic {:topic topic
|
||||
:chat-id chat-id}))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:shh/remove-filter
|
||||
|
|
|
@ -1,214 +0,0 @@
|
|||
(ns ^{:doc "Events for message handling"}
|
||||
status-im.transport.handlers
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.chat.models.message :as models.message]
|
||||
[status-im.data-store.transport :as transport-store]
|
||||
[status-im.transport.message.core :as message]
|
||||
[status-im.transport.message.transit :as transit]
|
||||
[status-im.transport.message.v1.contact :as v1.contact]
|
||||
[status-im.transport.message.v1.protocol :as protocol]
|
||||
[status-im.transport.shh :as shh]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(fx/defn update-last-received-from-inbox
|
||||
"Distinguishes messages that are expired from those that are not
|
||||
Expired messages are coming from offline inboxing"
|
||||
[{:keys [db now] :as cofx} now-in-s timestamp ttl]
|
||||
(when (> (- now-in-s timestamp) ttl)
|
||||
{:db (assoc db :inbox/last-received now)}))
|
||||
|
||||
(fx/defn receive-message
|
||||
[cofx now-in-s chat-id js-message]
|
||||
(let [{:keys [payload sig timestamp ttl]} (js->clj js-message :keywordize-keys true)
|
||||
status-message (-> payload
|
||||
transport.utils/to-utf8
|
||||
transit/deserialize)]
|
||||
(when (and sig status-message)
|
||||
(try
|
||||
(when-let [valid-message (message/validate status-message)]
|
||||
(fx/merge (assoc cofx :js-obj js-message)
|
||||
#(message/receive valid-message (or chat-id sig) sig timestamp %)
|
||||
(update-last-received-from-inbox now-in-s timestamp ttl)))
|
||||
(catch :default e nil))))) ; ignore unknown message types
|
||||
|
||||
(defn- js-array->seq [array]
|
||||
(for [i (range (.-length array))]
|
||||
(aget array i)))
|
||||
|
||||
(fx/defn receive-whisper-messages
|
||||
[{:keys [now] :as cofx} js-error js-messages chat-id]
|
||||
(if (and (not js-error)
|
||||
js-messages)
|
||||
(let [now-in-s (quot now 1000)
|
||||
receive-message-fxs (map (fn [message]
|
||||
(receive-message now-in-s chat-id message))
|
||||
(js-array->seq js-messages))]
|
||||
(apply fx/merge cofx receive-message-fxs))
|
||||
(do (log/error "Something went wrong" js-error js-messages)
|
||||
cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:protocol/receive-whisper-message
|
||||
[handlers/logged-in (re-frame/inject-cofx :random-id-generator)]
|
||||
(fn [cofx [_ js-error js-messages chat-id]]
|
||||
(receive-whisper-messages cofx js-error js-messages chat-id)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:protocol/send-status-message-error
|
||||
(fn [{:keys [db] :as cofx} [_ err]]
|
||||
(log/error :send-status-message-error err)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:contact/send-new-sym-key
|
||||
(fn [{:keys [db] :as cofx}
|
||||
[_ {:keys [chat-id topic message sym-key sym-key-id]}]]
|
||||
(let [{:keys [web3 current-public-key]} db
|
||||
chat-transport-info (-> (get-in db [:transport/chats chat-id])
|
||||
(assoc :sym-key-id sym-key-id
|
||||
:sym-key sym-key
|
||||
:topic topic))]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:transport/chats chat-id] chat-transport-info)
|
||||
:shh/add-filter {:web3 web3
|
||||
:sym-key-id sym-key-id
|
||||
:topic topic
|
||||
:chat-id chat-id}
|
||||
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
|
||||
:chat chat-transport-info})]}
|
||||
#(message/send (v1.contact/NewContactKey. sym-key topic message)
|
||||
chat-id %)))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:contact/add-new-sym-key
|
||||
(fn [{:keys [db] :as cofx} [_ {:keys [sym-key-id sym-key chat-id topic timestamp message]}]]
|
||||
(let [{:keys [web3 current-public-key]} db
|
||||
chat-transport-info (-> (get-in db [:transport/chats chat-id])
|
||||
(assoc :sym-key-id sym-key-id
|
||||
:sym-key sym-key
|
||||
:topic topic))]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:transport/chats chat-id]
|
||||
chat-transport-info)
|
||||
:dispatch [:inbox/request-chat-history chat-id]
|
||||
:shh/add-filter {:web3 web3
|
||||
:sym-key-id sym-key-id
|
||||
:topic topic
|
||||
:chat-id chat-id}
|
||||
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
|
||||
:chat chat-transport-info})]}
|
||||
#(message/receive message chat-id chat-id timestamp %)))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:group/unsubscribe-from-chat
|
||||
(fn [cofx [_ chat-id]]
|
||||
(transport.utils/unsubscribe-from-chat chat-id cofx)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
;; TODO(janherich): this should be called after `:data-store/tx` actually
|
||||
:confirm-messages-processed
|
||||
(fn [messages]
|
||||
(let [{:keys [web3]} (first messages)
|
||||
js-messages (->> messages
|
||||
(keep :js-obj)
|
||||
(apply array))]
|
||||
(when (pos? (.-length js-messages))
|
||||
(.confirmMessagesProcessed (transport.utils/shh web3)
|
||||
js-messages
|
||||
(fn [err resp]
|
||||
(when err
|
||||
(log/info "Confirming messages processed failed"))))))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:transport/set-message-envelope-hash
|
||||
;; message-type is used for tracking
|
||||
(fn [{:keys [db]} [_ chat-id message-id message-type envelope-hash-js]]
|
||||
;; TODO (cammellos): For group messages it returns multiple hashes, for now
|
||||
;; we naively assume that if one is sent the batch is ok
|
||||
(let [envelope-hash (js->clj envelope-hash-js)
|
||||
hash (if (vector? envelope-hash)
|
||||
(last envelope-hash)
|
||||
envelope-hash)]
|
||||
{:db (assoc-in db [:transport/message-envelopes hash]
|
||||
{:chat-id chat-id
|
||||
:message-id message-id
|
||||
:message-type message-type})})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:transport/set-contact-message-envelope-hash
|
||||
(fn [{:keys [db]} [_ chat-id envelope-hash]]
|
||||
{:db (assoc-in db [:transport/message-envelopes envelope-hash]
|
||||
{:chat-id chat-id
|
||||
:message-type :contact-message})}))
|
||||
|
||||
(fx/defn remove-hash [{:keys [db] :as cofx} envelope-hash]
|
||||
{:db (update db :transport/message-envelopes dissoc envelope-hash)})
|
||||
|
||||
(fx/defn update-resend-contact-message [{:keys [db] :as cofx} chat-id]
|
||||
(let [chat (get-in db [:transport/chats chat-id])
|
||||
updated-chat (assoc chat :resend? nil)]
|
||||
{:db (assoc-in db [:transport/chats chat-id :resend?] nil)
|
||||
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
|
||||
:chat updated-chat})]}))
|
||||
|
||||
(fx/defn update-envelope-status
|
||||
[{:keys [db] :as cofx} envelope-hash status]
|
||||
(let [{:keys [chat-id message-type message-id]}
|
||||
(get-in db [:transport/message-envelopes envelope-hash])]
|
||||
(case message-type
|
||||
:contact-message
|
||||
(when (= :sent status)
|
||||
(fx/merge cofx
|
||||
(remove-hash envelope-hash)
|
||||
(update-resend-contact-message chat-id)))
|
||||
|
||||
(when-let [{:keys [from]} (get-in db [:chats chat-id :messages message-id])]
|
||||
(let [{:keys [fcm-token]} (get-in db [:contacts/contacts chat-id])]
|
||||
(fx/merge cofx
|
||||
(remove-hash envelope-hash)
|
||||
(models.message/update-message-status chat-id message-id status)
|
||||
(models.message/send-push-notification fcm-token status)))))))
|
||||
|
||||
(defn- own-info [db]
|
||||
(let [{:keys [name photo-path address]} (:account/account db)
|
||||
fcm-token (get-in db [:notifications :fcm-token])]
|
||||
{:name name
|
||||
:profile-image photo-path
|
||||
:address address
|
||||
:fcm-token fcm-token}))
|
||||
|
||||
(fx/defn resend-contact-request [cofx own-info chat-id {:keys [sym-key topic]}]
|
||||
(message/send (v1.contact/NewContactKey. sym-key
|
||||
topic
|
||||
(v1.contact/map->ContactRequest own-info))
|
||||
chat-id cofx))
|
||||
|
||||
(fx/defn resend-contact-message
|
||||
[cofx own-info chat-id]
|
||||
(let [{:keys [resend?] :as chat} (get-in cofx [:db :transport/chats chat-id])]
|
||||
(case resend?
|
||||
"contact-request"
|
||||
(resend-contact-request cofx own-info chat-id chat)
|
||||
"contact-request-confirmation"
|
||||
(message/send (v1.contact/map->ContactRequestConfirmed own-info)
|
||||
chat-id
|
||||
cofx)
|
||||
"contact-update"
|
||||
(protocol/send cofx
|
||||
{:chat-id chat-id
|
||||
:payload (v1.contact/map->ContactUpdate own-info)})
|
||||
nil)))
|
||||
|
||||
(fx/defn resend-contact-messages
|
||||
[{:keys [db] :as cofx} previous-summary]
|
||||
(when (and (zero? (count previous-summary))
|
||||
(= :online (:network-status db))
|
||||
(pos? (count (:peers-summary db))))
|
||||
(let [own-info (own-info db)
|
||||
resend-contact-message-fxs (map (fn [chat-id]
|
||||
(resend-contact-message own-info chat-id))
|
||||
(keys (:transport/chats db)))]
|
||||
(apply fx/merge cofx resend-contact-message-fxs))))
|
|
@ -1,27 +1,26 @@
|
|||
(ns status-im.transport.impl.receive
|
||||
(:require
|
||||
(:require [status-im.group-chats.core :as group-chats]
|
||||
[status-im.models.contact :as models.contact]
|
||||
[status-im.group-chats.core :as group-chats]
|
||||
[status-im.transport.message.core :as message]
|
||||
[status-im.transport.message.v1.contact :as transport.contact]
|
||||
[status-im.transport.message.v1.core :as transport.protocol]))
|
||||
[status-im.transport.message.contact :as transport.contact]
|
||||
[status-im.transport.message.group-chat :as transport.group-chat]
|
||||
[status-im.transport.message.protocol :as protocol]))
|
||||
|
||||
(extend-type transport.protocol/GroupMembershipUpdate
|
||||
message/StatusMessage
|
||||
(extend-type transport.group-chat/GroupMembershipUpdate
|
||||
protocol/StatusMessage
|
||||
(receive [this _ signature _ cofx]
|
||||
(group-chats/handle-membership-update-received cofx this signature)))
|
||||
|
||||
(extend-type transport.contact/ContactRequest
|
||||
message/StatusMessage
|
||||
protocol/StatusMessage
|
||||
(receive [this _ signature timestamp cofx]
|
||||
(models.contact/receive-contact-request signature timestamp this cofx)))
|
||||
|
||||
(extend-type transport.contact/ContactRequestConfirmed
|
||||
message/StatusMessage
|
||||
protocol/StatusMessage
|
||||
(receive [this _ signature timestamp cofx]
|
||||
(models.contact/receive-contact-request-confirmation signature timestamp this cofx)))
|
||||
|
||||
(extend-type transport.contact/ContactUpdate
|
||||
message/StatusMessage
|
||||
protocol/StatusMessage
|
||||
(receive [this _ signature timestamp cofx]
|
||||
(models.contact/receive-contact-update signature timestamp this cofx)))
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
(ns status-im.transport.impl.send
|
||||
(:require
|
||||
[status-im.group-chats.core :as group-chats]
|
||||
[status-im.transport.message.core :as message]
|
||||
[status-im.transport.message.v1.core :as transport]))
|
||||
(:require [status-im.group-chats.core :as group-chats]
|
||||
[status-im.transport.message.group-chat :as transport.group-chat]
|
||||
[status-im.transport.message.protocol :as protocol]))
|
||||
|
||||
(extend-type transport/GroupMembershipUpdate
|
||||
message/StatusMessage
|
||||
(extend-type transport.group-chat/GroupMembershipUpdate
|
||||
protocol/StatusMessage
|
||||
(send [this chat-id cofx]
|
||||
(group-chats/send-membership-update cofx this chat-id)))
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
status-im.transport.inbox
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.accounts :as accounts-store]
|
||||
[status-im.data-store.core :as data-store]
|
||||
[status-im.data-store.transport :as transport-store]
|
||||
[status-im.fleet.core :as fleet]
|
||||
|
@ -10,38 +9,28 @@
|
|||
[status-im.native-module.core :as status]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.utils :as utils]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
;; How does offline inboxing work ?
|
||||
;;
|
||||
;; - We send a request to the mailserver, we are only interested in the
|
||||
;; messages since `last-request`, the time of the last successful request,
|
||||
;; 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.
|
||||
;; - These messages are expired that is how we differentiate them from
|
||||
;; normal whisper messages to update last-received
|
||||
;; - After fetching-timeout is reached since the last mailserver message
|
||||
;; was received without a connection incident, we consider the request
|
||||
;; successfull and update `last-request` and `fetch-history?` fields of each
|
||||
;; topic to false
|
||||
;; - 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 connection-timeout
|
||||
"Time after which mailserver connection is considered to have failed"
|
||||
15000)
|
||||
|
||||
(def fetching-timeout
|
||||
"Time we should wait after last message was fetch from mailserver before we
|
||||
consider it done
|
||||
Needs to be at least 10 seconds because that is the time it takes for the app
|
||||
to realize it was disconnected"
|
||||
10000)
|
||||
5000)
|
||||
|
||||
(defn- parse-json
|
||||
;; NOTE(dmitryn) Expects JSON response like:
|
||||
|
@ -61,7 +50,7 @@
|
|||
(catch :default e
|
||||
{:error (.-message e)})))
|
||||
|
||||
(defn- response-handler [error-fn success-fn]
|
||||
(defn- response-handler [success-fn error-fn]
|
||||
(fn handle-response
|
||||
([response]
|
||||
(let [{:keys [error result]} (parse-json response)]
|
||||
|
@ -71,126 +60,86 @@
|
|||
(error-fn error)
|
||||
(success-fn result)))))
|
||||
|
||||
(fx/defn add-sym-key-id-to-wnode
|
||||
[{:keys [db]} {:keys [id]} sym-key-id]
|
||||
(let [current-fleet (fleet/current-fleet db)]
|
||||
{:db (assoc-in db [:inbox/wnodes current-fleet id :sym-key-id] sym-key-id)}))
|
||||
(defn add-peer! [wnode]
|
||||
(status/add-peer wnode
|
||||
(response-handler #(log/debug "offline inbox: add-peer success" %)
|
||||
#(log/error "offline inbox: add-peer error" %))))
|
||||
|
||||
(defn registered-peer? [peers enode]
|
||||
(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 add-peer [enode success-fn error-fn]
|
||||
(status/add-peer enode (response-handler error-fn success-fn)))
|
||||
(defn update-mailserver-status [db state]
|
||||
(assoc db :mailserver-status state))
|
||||
|
||||
(defn mark-trusted-peer [web3 enode success-fn error-fn]
|
||||
(.markTrustedPeer (transport.utils/shh web3)
|
||||
enode
|
||||
(fn [err resp]
|
||||
(if-not err
|
||||
(success-fn resp)
|
||||
(error-fn err)))))
|
||||
(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)))))
|
||||
|
||||
(def one-day (* 24 3600))
|
||||
(def seven-days (* 7 one-day))
|
||||
|
||||
(defn request-inbox-messages-params [mailserver from to topics]
|
||||
(let [days (conj
|
||||
(into [] (range from to one-day))
|
||||
to)
|
||||
day-ranges (map vector days (drop 1 days))]
|
||||
(for [topic topics
|
||||
[current-from current-to] day-ranges]
|
||||
{:topic topic
|
||||
:mailServerPeer (:address mailserver)
|
||||
:symKeyID (:sym-key-id mailserver)
|
||||
:from current-from
|
||||
:to current-to})))
|
||||
|
||||
(defn request-inbox-messages
|
||||
[web3 mailserver topics start-from end-to success-fn error-fn]
|
||||
(log/info "offline inbox: request-messages request for topics " topics " from " start-from " to " end-to)
|
||||
(doseq [{:keys [topic] :as params} (request-inbox-messages-params
|
||||
mailserver
|
||||
start-from
|
||||
end-to
|
||||
topics)]
|
||||
(log/info "offline inbox: request-messages for: "
|
||||
" topic " topic
|
||||
" from " (:from params)
|
||||
" to " (:to params))
|
||||
(.requestMessages (transport.utils/shh web3)
|
||||
(clj->js params)
|
||||
(fn [err resp]
|
||||
(if-not err
|
||||
(success-fn resp topic)
|
||||
(error-fn err topic))))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::add-peer
|
||||
(fn [{:keys [wnode]}]
|
||||
(add-peer wnode
|
||||
#(log/debug "offline inbox: add-peer success" %)
|
||||
#(log/error "offline inbox: add-peer error" %))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::mark-trusted-peer
|
||||
(fn [{:keys [wnode web3]}]
|
||||
(mark-trusted-peer web3
|
||||
wnode
|
||||
#(re-frame/dispatch [:inbox/mailserver-trusted %])
|
||||
#(re-frame/dispatch [:inbox/check-connection]))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::request-messages
|
||||
(fn [params]
|
||||
(doseq [{:keys [wnode topics to from web3]} params]
|
||||
(request-inbox-messages web3
|
||||
wnode
|
||||
topics
|
||||
from
|
||||
to
|
||||
#(log/info "offline inbox: request-messages response" %1 %2 from to)
|
||||
#(log/error "offline inbox: request-messages error" %1 %2 from to)))))
|
||||
|
||||
(fx/defn update-mailserver-status [{:keys [db]} transition]
|
||||
(let [state transition]
|
||||
{:db (assoc db
|
||||
:mailserver-status state
|
||||
:inbox/fetching? false)}))
|
||||
|
||||
(fx/defn generate-mailserver-symkey [{:keys [db] :as cofx} wnode]
|
||||
(when-not (:sym-key-id wnode)
|
||||
{:shh/generate-sym-key-from-password
|
||||
[{:password (:password wnode)
|
||||
:web3 (:web3 db)
|
||||
:on-success (fn [_ sym-key-id]
|
||||
(re-frame/dispatch [:inbox/get-sym-key-success wnode sym-key-id]))
|
||||
:on-error #(log/error "offline inbox: get-sym-key error" %)}]}))
|
||||
(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 (update-mailserver-status db :connecting)
|
||||
: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
|
||||
"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 [web3 (:web3 db)
|
||||
{:keys [address] :as wnode} (mailserver/fetch-current cofx)
|
||||
peers-summary (:peers-summary db)
|
||||
connected? (registered-peer? peers-summary address)]
|
||||
(if connected?
|
||||
(fx/merge cofx
|
||||
(update-mailserver-status :connected)
|
||||
(generate-mailserver-symkey wnode))
|
||||
(fx/merge cofx
|
||||
{::add-peer {:wnode address}
|
||||
:utils/dispatch-later [{:ms connection-timeout
|
||||
:dispatch [:inbox/check-connection]}]}
|
||||
(update-mailserver-status :connecting)
|
||||
(generate-mailserver-symkey wnode)))))
|
||||
(let [{:keys [address] :as wnode} (mailserver/fetch-current cofx)
|
||||
{:keys [peers-summary]} db
|
||||
added? (registered-peer? peers-summary
|
||||
address)]
|
||||
(if added?
|
||||
(mark-trusted-peer cofx)
|
||||
(add-peer cofx))))
|
||||
|
||||
(fx/defn peers-summary-change
|
||||
"There is only 2 summary changes that require offline inboxing action:
|
||||
|
@ -199,183 +148,191 @@
|
|||
[{:keys [db] :as cofx} previous-summary]
|
||||
(when (:account/account db)
|
||||
(let [{:keys [peers-summary peers-count]} db
|
||||
wnode (:address (mailserver/fetch-current cofx))
|
||||
{:keys [address sym-key-id] :as wnode} (mailserver/fetch-current cofx)
|
||||
mailserver-was-registered? (registered-peer? previous-summary
|
||||
wnode)
|
||||
address)
|
||||
mailserver-is-registered? (registered-peer? peers-summary
|
||||
wnode)
|
||||
;; the mailserver just connected
|
||||
mailserver-connected? (and mailserver-is-registered?
|
||||
address)
|
||||
mailserver-added? (and mailserver-is-registered?
|
||||
(not mailserver-was-registered?))
|
||||
;; the mailserver just disconnected
|
||||
mailserver-disconnected? (and mailserver-was-registered?
|
||||
mailserver-removed? (and mailserver-was-registered?
|
||||
(not mailserver-is-registered?))]
|
||||
(cond
|
||||
mailserver-disconnected?
|
||||
(connect-to-mailserver cofx)
|
||||
mailserver-added?
|
||||
(mark-trusted-peer cofx)
|
||||
mailserver-removed?
|
||||
(connect-to-mailserver cofx)))))
|
||||
|
||||
mailserver-connected?
|
||||
{::mark-trusted-peer {:web3 (:web3 db)
|
||||
:wnode wnode}}))))
|
||||
(defn request-messages! [web3 {:keys [sym-key-id address]} {:keys [topic to from]}]
|
||||
(log/info "offline inbox: request-messages for: "
|
||||
" topic " topic
|
||||
" from " from
|
||||
" to " to)
|
||||
(.requestMessages (transport.utils/shh web3)
|
||||
(clj->js {:topic topic
|
||||
:mailServerPeer address
|
||||
:symKeyID sym-key-id
|
||||
:timeout 20
|
||||
:from from
|
||||
:to to})
|
||||
(fn [err request-id]
|
||||
(if-not err
|
||||
(re-frame/dispatch [:inbox.callback/request-messages-success {:topic topic
|
||||
:request-id request-id
|
||||
:from from
|
||||
:to to}])
|
||||
(log/error "offline inbox: messages request error for topic " topic ": " err)))))
|
||||
|
||||
(defn inbox-ready? [{:keys [sym-key-id]} {:keys [db]}]
|
||||
(let [mailserver-status (:mailserver-status db)]
|
||||
(and (= :connected mailserver-status)
|
||||
sym-key-id)))
|
||||
(re-frame/reg-fx
|
||||
:transport.inbox/request-messages
|
||||
(fn [{:keys [web3 wnode requests]}]
|
||||
(doseq [request requests]
|
||||
(request-messages! web3 wnode request))))
|
||||
|
||||
(defn get-request-messages-topics
|
||||
"Returns topics for which full history has already been recovered"
|
||||
[db]
|
||||
(conj (map :topic
|
||||
(remove :fetch-history?
|
||||
(vals (:transport/chats db))))
|
||||
(transport.utils/get-topic constants/contact-discovery)))
|
||||
|
||||
(defn get-request-history-topics
|
||||
"Returns topics for which full history has not been recovered"
|
||||
[db]
|
||||
(map :topic
|
||||
(filter :fetch-history?
|
||||
(vals (:transport/chats db)))))
|
||||
|
||||
(defn request-history-span [now-in-s]
|
||||
(defn prepare-request [now-in-s topic {:keys [last-request request-pending?]}]
|
||||
(when-not request-pending?
|
||||
{:from (max last-request
|
||||
(- now-in-s one-day))
|
||||
:to now-in-s
|
||||
:topic topic}))
|
||||
|
||||
(defn prepare-requests [now-in-s topics]
|
||||
(remove nil? (map (fn [[topic inbox-topic]]
|
||||
(prepare-request now-in-s topic inbox-topic))
|
||||
topics)))
|
||||
|
||||
(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)))
|
||||
|
||||
(fx/defn request-messages
|
||||
[{:keys [db now] :as cofx}]
|
||||
(let [wnode (mailserver/fetch-current cofx)
|
||||
web3 (:web3 db)
|
||||
"request messages if the inbox is ready"
|
||||
[{:keys [db now] :as cofx} topic]
|
||||
(when-let [wnode (get-wnode-when-ready cofx)]
|
||||
(let [web3 (:web3 db)
|
||||
now-in-s (quot now 1000)
|
||||
last-request (max
|
||||
(get-in db [:account/account :last-request])
|
||||
(- now-in-s seven-days))
|
||||
request-messages-topics (get-request-messages-topics db)
|
||||
request-history-topics (get-request-history-topics db)]
|
||||
(when (inbox-ready? wnode cofx)
|
||||
{::request-messages [{:wnode wnode
|
||||
:topics request-messages-topics
|
||||
:from last-request
|
||||
:to now-in-s
|
||||
:web3 web3}
|
||||
{:wnode wnode
|
||||
:from (request-history-span now-in-s)
|
||||
:to now-in-s
|
||||
:topics request-history-topics
|
||||
:web3 web3}]
|
||||
:db (assoc db :inbox/fetching? true)
|
||||
:dispatch-later [{:ms fetching-timeout
|
||||
:dispatch [:inbox/check-fetching now-in-s]}]})))
|
||||
requests (if topic
|
||||
[(prepare-request now-in-s topic (get-in db [:transport.inbox/topics topic]))]
|
||||
(prepare-requests now-in-s (:transport.inbox/topics db)))]
|
||||
{:transport.inbox/request-messages {:web3 web3
|
||||
:wnode wnode
|
||||
:requests requests}})))
|
||||
|
||||
(fx/defn request-chat-history [{:keys [db now] :as cofx} chat-id]
|
||||
(let [wnode (mailserver/fetch-current cofx)
|
||||
web3 (:web3 db)
|
||||
topic (get-in db [:transport/chats chat-id :topic])
|
||||
now-in-s (quot now 1000)]
|
||||
(when (inbox-ready? wnode cofx)
|
||||
{::request-messages [{:wnode wnode
|
||||
:topics [topic]
|
||||
:from (request-history-span now-in-s)
|
||||
:to now-in-s
|
||||
:web3 web3}]
|
||||
:db (assoc db :inbox/fetching? true)
|
||||
:dispatch-later [{:ms fetching-timeout
|
||||
:dispatch [:inbox/check-fetching now-in-s chat-id]}]})))
|
||||
|
||||
;;;; Handlers
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:inbox/mailserver-trusted
|
||||
(fn [{:keys [db] :as cofx} _]
|
||||
(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
|
||||
(update-mailserver-status :connected)
|
||||
(request-messages))))
|
||||
{:db (update-mailserver-status db :connected)}
|
||||
(request-messages nil)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:inbox/get-sym-key-success
|
||||
(fn [{:keys [db] :as cofx} [_ wnode sym-key-id]]
|
||||
(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
|
||||
(add-sym-key-id-to-wnode wnode sym-key-id)
|
||||
(request-messages))))
|
||||
{: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?))}
|
||||
(request-messages nil))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:inbox/request-chat-history
|
||||
(fn [{:keys [db] :as cofx} [_ chat-id]]
|
||||
(request-chat-history cofx chat-id)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:inbox/check-connection
|
||||
(fn [{:keys [db] :as cofx} _]
|
||||
(fx/defn check-connection
|
||||
"check if mailserver is connected
|
||||
mark mailserver status as `:error` if custom mailserver is used
|
||||
otherwise try to reconnect to another mailserver"
|
||||
[{:keys [db] :as cofx}]
|
||||
(when (= :connecting (:mailserver-status db))
|
||||
(if (mailserver/preferred-mailserver-id cofx)
|
||||
(update-mailserver-status cofx :error)
|
||||
{:db (update-mailserver-status db :error)}
|
||||
(fx/merge cofx
|
||||
(mailserver/set-current-mailserver)
|
||||
(connect-to-mailserver))))))
|
||||
(connect-to-mailserver)))))
|
||||
|
||||
(fx/defn update-last-request
|
||||
[{:keys [db]} last-request]
|
||||
(let [chats (:transport/chats db)
|
||||
transport-txs (reduce (fn [txs [chat-id chat]]
|
||||
(if (:fetch-history? chat)
|
||||
(conj txs
|
||||
(transport-store/save-transport-tx
|
||||
{:chat-id chat-id
|
||||
:chat (assoc chat
|
||||
:fetch-history? false)}))
|
||||
txs))
|
||||
[]
|
||||
chats)
|
||||
chats-update (reduce (fn [acc [chat-id chat]]
|
||||
(if (:fetch-history? chat)
|
||||
(assoc acc chat-id (assoc chat :fetch-history? false))
|
||||
(assoc acc chat-id chat)))
|
||||
{}
|
||||
chats)]
|
||||
(fx/defn remove-chat-from-inbox-topic
|
||||
"if the chat is the only chat of the inbox topic delete the inbox 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)
|
||||
{:db (update db :transport.inbox/topics dissoc topic)
|
||||
:data-store/tx [(transport-store/delete-transport-inbox-topic-tx topic)]}
|
||||
{: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 update-inbox-topic
|
||||
"TODO: add support for cursors
|
||||
if there is a cursor, do not update `request-to` and `request-from`"
|
||||
[{:keys [db now] :as cofx} {:keys [request-id cursor]}]
|
||||
(let [{:keys [from to topic]} (get-in db [:transport.inbox/requests request-id])
|
||||
inbox-topic (-> (get-in db [:transport.inbox/topics topic])
|
||||
(assoc :last-request to)
|
||||
(dissoc :request-pending?))]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc :transport/chats chats-update)
|
||||
(assoc-in [:account/account :last-request]
|
||||
last-request))
|
||||
:data-store/base-tx [(accounts-store/save-account-tx
|
||||
(assoc (:account/account db)
|
||||
:last-request last-request))]
|
||||
:data-store/tx transport-txs}))
|
||||
(update :transport.inbox/requests dissoc request-id)
|
||||
(assoc-in [:transport.inbox/topics topic] inbox-topic))
|
||||
:data-store/tx [(transport-store/save-transport-inbox-topic-tx
|
||||
{:topic topic
|
||||
:inbox-topic inbox-topic})]})))
|
||||
|
||||
(fx/defn update-fetch-history [{:keys [db]} chat-id]
|
||||
{:db (assoc-in db
|
||||
[:transport/chats chat-id :fetch-history?]
|
||||
false)
|
||||
:data-store/tx [(transport-store/save-transport-tx
|
||||
{:chat-id chat-id
|
||||
:chat (assoc (get-in db [:transport/chats chat-id])
|
||||
:fetch-history? false)})]})
|
||||
(fx/defn upsert-inbox-topic
|
||||
"if the chat-id is already in the topic we do nothing, otherwise we update
|
||||
the topic
|
||||
if the topic already existed we add the chat-id andreset last-request
|
||||
because there was no filter for the chat and messages were ignored
|
||||
if the topic didn't exist we created"
|
||||
[{: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})]}
|
||||
(request-messages topic)))))
|
||||
|
||||
(fx/defn initialize-offline-inbox [cofx custom-mailservers]
|
||||
(fx/defn resend-request
|
||||
[{:keys [db] :as cofx} {:keys [request-id]}]
|
||||
(let [{:keys [from to topic]} (get-in db [:transport.inbox/requests request-id])]
|
||||
(log/info "offline inbox: message request" request-id " expired for inbox topic" topic "from" from "to" to)
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(update :transport.inbox/requests dissoc request-id)
|
||||
(update-in [:transport.inbox/topics topic] dissoc :request-pending?))}
|
||||
(request-messages topic))))
|
||||
|
||||
(fx/defn add-request
|
||||
[{:keys [db] :as cofx} {:keys [topic request-id from to]}]
|
||||
(log/info "offline inbox: message request " request-id "sent for inbox topic" topic "from" from "to" to)
|
||||
{:db (-> db
|
||||
(assoc-in [:transport.inbox/requests request-id] {:from from
|
||||
:to to
|
||||
:topic topic})
|
||||
(assoc-in [:transport.inbox/topics topic :request-pending?] true))})
|
||||
|
||||
(fx/defn initialize-offline-inbox
|
||||
[cofx custom-mailservers]
|
||||
(let [discovery-topic (transport.utils/get-topic constants/contact-discovery)]
|
||||
(fx/merge cofx
|
||||
(mailserver/add-custom-mailservers custom-mailservers)
|
||||
(mailserver/set-initial-last-request)
|
||||
(mailserver/set-current-mailserver)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:inbox/check-fetching
|
||||
(fn [{:keys [db now] :as cofx} [_ last-request chat-id]]
|
||||
(when (and (:inbox/fetching? db)
|
||||
;; if chat was removed before messages were fetched no need
|
||||
;; to proceed with further actions
|
||||
(or (not chat-id) (contains? (:transport/chats db) chat-id)))
|
||||
(let [time-since-last-received (- now (:inbox/last-received db))]
|
||||
(if (> time-since-last-received fetching-timeout)
|
||||
(if chat-id
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :inbox/fetching? false)}
|
||||
(update-fetch-history chat-id))
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :inbox/fetching? false)}
|
||||
(update-last-request last-request)))
|
||||
{:dispatch-later [{:ms (- fetching-timeout
|
||||
time-since-last-received)
|
||||
:dispatch [:inbox/check-fetching last-request chat-id]}]})))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:inbox/reconnect
|
||||
(fn [cofx [_ args]]
|
||||
(connect-to-mailserver cofx)))
|
||||
(mailserver/set-current-mailserver)
|
||||
(when-not (get-in cofx [:db :transport.inbox/topics discovery-topic])
|
||||
(upsert-inbox-topic {:topic discovery-topic
|
||||
:chat-id :discovery-topic})))))
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
(ns ^{:doc "Contact request and update API"}
|
||||
status-im.transport.message.contact
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
[status-im.data-store.transport :as transport-store]
|
||||
[status-im.transport.db :as transport.db]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
(defrecord ContactRequest [name profile-image address fcm-token]
|
||||
protocol/StatusMessage
|
||||
(send [this chat-id {:keys [db random-id-generator] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(protocol/init-chat {:chat-id chat-id
|
||||
:resend? "contact-request"})
|
||||
(protocol/send-with-pubkey {:chat-id chat-id
|
||||
:payload this
|
||||
:success-event [:transport/contact-message-sent chat-id]})))
|
||||
(validate [this]
|
||||
(when (spec/valid? :message/contact-request this)
|
||||
this)))
|
||||
|
||||
(defrecord ContactRequestConfirmed [name profile-image address fcm-token]
|
||||
protocol/StatusMessage
|
||||
(send [this chat-id {:keys [db] :as cofx}]
|
||||
(let [success-event [:transport/contact-message-sent chat-id]
|
||||
chat (get-in db [:transport/chats chat-id])
|
||||
updated-chat (if chat
|
||||
(assoc chat :resend? "contact-request-confirmation")
|
||||
(transport.db/create-chat {:resend? "contact-request-confirmation"}))]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:transport/chats chat-id] updated-chat)
|
||||
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
|
||||
:chat updated-chat})]}
|
||||
(protocol/send-with-pubkey {:chat-id chat-id
|
||||
:payload this
|
||||
:success-event success-event}))))
|
||||
(validate [this]
|
||||
(when (spec/valid? :message/contact-request-confirmed this)
|
||||
this)))
|
||||
|
||||
(fx/defn send-contact-update
|
||||
[{:keys [db] :as cofx} chat-id payload]
|
||||
(when-let [chat (get-in cofx [:db :transport/chats chat-id])]
|
||||
(let [updated-chat (assoc chat :resend? "contact-update")
|
||||
tx [(transport-store/save-transport-tx {:chat-id chat-id
|
||||
:chat updated-chat})]
|
||||
success-event [:transport/contact-message-sent chat-id]]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:transport/chats chat-id :resend?]
|
||||
"contact-update")
|
||||
:data-store/tx tx}
|
||||
(protocol/send-with-pubkey {:chat-id chat-id
|
||||
:payload payload
|
||||
:success-event success-event})))))
|
||||
|
||||
(defrecord ContactUpdate [name profile-image address fcm-token]
|
||||
protocol/StatusMessage
|
||||
(send [this _ {:keys [db] :as cofx}]
|
||||
;;TODO: here we look for contact which have a :public-key to differentiate
|
||||
;;actual contacts from dapps
|
||||
;;This is not an ideal solution and we should think about a more reliable way
|
||||
;;to do this when we refactor app-db
|
||||
(let [contact-public-keys (reduce (fn [acc [_ {:keys [public-key pending?]}]]
|
||||
(if (and public-key
|
||||
(not pending?))
|
||||
(conj acc public-key)
|
||||
acc))
|
||||
#{}
|
||||
(:contacts/contacts db))
|
||||
;;NOTE: chats with contacts use public-key as chat-id
|
||||
send-contact-update-fxs (map #(send-contact-update % this) contact-public-keys)]
|
||||
(apply fx/merge cofx send-contact-update-fxs)))
|
||||
(validate [this]
|
||||
(when (spec/valid? :message/contact-update this)
|
||||
this)))
|
||||
|
||||
(fx/defn remove-chat-filter
|
||||
"Stops the filter for the given chat-id"
|
||||
[{:keys [db]} chat-id]
|
||||
(when-let [filter (get-in db [:transport/filters chat-id])]
|
||||
{:shh/remove-filter filter}))
|
||||
|
||||
(defrecord NewContactKey [sym-key topic message]
|
||||
protocol/StatusMessage
|
||||
(send
|
||||
;; no-op, we don't send NewContactKey anymore
|
||||
[this chat-id cofx])
|
||||
(receive
|
||||
;;for compatibility with old clients, we only care about the message within
|
||||
[this chat-id _ timestamp {:keys [db] :as cofx}]
|
||||
(protocol/receive message chat-id chat-id timestamp cofx))
|
||||
(validate [this]
|
||||
(when (spec/valid? :message/new-contact-key this)
|
||||
this)))
|
|
@ -1,8 +1,143 @@
|
|||
(ns ^{:doc "Definition of the StatusMessage protocol"}
|
||||
status-im.transport.message.core)
|
||||
status-im.transport.message.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.chat.models.message :as models.message]
|
||||
[status-im.data-store.transport :as transport-store]
|
||||
[status-im.transport.message.contact :as contact]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.transport.message.transit :as transit]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defprotocol StatusMessage
|
||||
"Protocol for the messages that are sent through the transport layer"
|
||||
(send [this chat-id cofx] "Method producing all effects necessary for sending the message record")
|
||||
(receive [this chat-id signature timestamp cofx] "Method producing all effects necessary for receiving the message record")
|
||||
(validate [this] "Method returning the message if it is valid or nil if it is not"))
|
||||
(fx/defn receive-message
|
||||
[cofx now-in-s chat-id js-message]
|
||||
(let [{:keys [payload sig timestamp ttl]} (js->clj js-message :keywordize-keys true)
|
||||
status-message (-> payload
|
||||
transport.utils/to-utf8
|
||||
transit/deserialize)]
|
||||
(when (and sig status-message)
|
||||
(try
|
||||
(when-let [valid-message (protocol/validate status-message)]
|
||||
(fx/merge (assoc cofx :js-obj js-message)
|
||||
#(protocol/receive valid-message (or chat-id sig) sig timestamp %)))
|
||||
(catch :default e nil))))) ; ignore unknown message types
|
||||
|
||||
(defn- js-array->seq [array]
|
||||
(for [i (range (.-length array))]
|
||||
(aget array i)))
|
||||
|
||||
(fx/defn receive-whisper-messages
|
||||
[{:keys [now] :as cofx} js-error js-messages chat-id]
|
||||
(if (and (not js-error)
|
||||
js-messages)
|
||||
(let [now-in-s (quot now 1000)
|
||||
receive-message-fxs (map (fn [message]
|
||||
(receive-message now-in-s chat-id message))
|
||||
(js-array->seq js-messages))]
|
||||
(apply fx/merge cofx receive-message-fxs))
|
||||
(do (log/error "Something went wrong" js-error js-messages)
|
||||
cofx)))
|
||||
|
||||
(fx/defn remove-hash
|
||||
[{:keys [db] :as cofx} envelope-hash]
|
||||
{:db (update db :transport/message-envelopes dissoc envelope-hash)})
|
||||
|
||||
(fx/defn update-resend-contact-message
|
||||
[{:keys [db] :as cofx} chat-id]
|
||||
(let [chat (get-in db [:transport/chats chat-id])
|
||||
updated-chat (assoc chat :resend? nil)]
|
||||
{:db (assoc-in db [:transport/chats chat-id :resend?] nil)
|
||||
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
|
||||
:chat updated-chat})]}))
|
||||
(fx/defn update-envelope-status
|
||||
[{:keys [db] :as cofx} envelope-hash status]
|
||||
(let [{:keys [chat-id message-type message-id]}
|
||||
(get-in db [:transport/message-envelopes envelope-hash])]
|
||||
(case message-type
|
||||
:contact-message
|
||||
(when (= :sent status)
|
||||
(fx/merge cofx
|
||||
(remove-hash envelope-hash)
|
||||
(update-resend-contact-message chat-id)))
|
||||
|
||||
(when-let [{:keys [from]} (get-in db [:chats chat-id :messages message-id])]
|
||||
(let [{:keys [fcm-token]} (get-in db [:contacts/contacts chat-id])]
|
||||
(fx/merge cofx
|
||||
(remove-hash envelope-hash)
|
||||
(models.message/update-message-status chat-id message-id status)
|
||||
(models.message/send-push-notification fcm-token status)))))))
|
||||
|
||||
(fx/defn set-contact-message-envelope-hash
|
||||
[{:keys [db] :as cofx} chat-id envelope-hash]
|
||||
{:db (assoc-in db [:transport/message-envelopes envelope-hash]
|
||||
{:chat-id chat-id
|
||||
:message-type :contact-message})})
|
||||
|
||||
(fx/defn set-message-envelope-hash
|
||||
"message-type is used for tracking
|
||||
TODO (cammellos): For group messages it returns multiple hashes, for now
|
||||
we naively assume that if one is sent the batch is ok"
|
||||
[{:keys [db] :as cofx} chat-id message-id message-type envelope-hash-js]
|
||||
(let [envelope-hash (js->clj envelope-hash-js)
|
||||
hash (if (vector? envelope-hash)
|
||||
(last envelope-hash)
|
||||
envelope-hash)]
|
||||
{:db (assoc-in db [:transport/message-envelopes hash]
|
||||
{:chat-id chat-id
|
||||
:message-id message-id
|
||||
:message-type message-type})}))
|
||||
|
||||
(defn- own-info [db]
|
||||
(let [{:keys [name photo-path address]} (:account/account db)
|
||||
fcm-token (get-in db [:notifications :fcm-token])]
|
||||
{:name name
|
||||
:profile-image photo-path
|
||||
:address address
|
||||
:fcm-token fcm-token}))
|
||||
|
||||
(fx/defn resend-contact-request [cofx own-info chat-id {:keys [sym-key topic]}]
|
||||
(protocol/send (contact/map->ContactRequest own-info)
|
||||
chat-id cofx))
|
||||
|
||||
(fx/defn resend-contact-message
|
||||
[cofx own-info chat-id]
|
||||
(let [{:keys [resend?] :as chat} (get-in cofx [:db :transport/chats chat-id])]
|
||||
(case resend?
|
||||
"contact-request"
|
||||
(resend-contact-request cofx own-info chat-id chat)
|
||||
"contact-request-confirmation"
|
||||
(protocol/send (contact/map->ContactRequestConfirmed own-info)
|
||||
chat-id
|
||||
cofx)
|
||||
"contact-update"
|
||||
(protocol/send-with-pubkey cofx
|
||||
{:chat-id chat-id
|
||||
:payload (contact/map->ContactUpdate own-info)})
|
||||
nil)))
|
||||
|
||||
(fx/defn resend-contact-messages
|
||||
[{:keys [db] :as cofx} previous-summary]
|
||||
(when (and (zero? (count previous-summary))
|
||||
(= :online (:network-status db))
|
||||
(pos? (count (:peers-summary db))))
|
||||
(let [own-info (own-info db)
|
||||
resend-contact-message-fxs (map (fn [chat-id]
|
||||
(resend-contact-message own-info chat-id))
|
||||
(keys (:transport/chats db)))]
|
||||
(apply fx/merge cofx resend-contact-message-fxs))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
;; TODO(janherich): this should be called after `:data-store/tx` actually
|
||||
:transport/confirm-messages-processed
|
||||
(fn [messages]
|
||||
(let [{:keys [web3]} (first messages)
|
||||
js-messages (->> messages
|
||||
(keep :js-obj)
|
||||
(apply array))]
|
||||
(when (pos? (.-length js-messages))
|
||||
(.confirmMessagesProcessed (transport.utils/shh web3)
|
||||
js-messages
|
||||
(fn [err resp]
|
||||
(when err
|
||||
(log/info "Confirming messages processed failed"))))))))
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
(ns status-im.transport.message.v1.core
|
||||
(:require [status-im.transport.message.core :as message]
|
||||
[taoensso.timbre :as log]
|
||||
[cljs.spec.alpha :as spec]))
|
||||
(ns status-im.transport.message.group-chat
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defrecord GroupMembershipUpdate
|
||||
[chat-id membership-updates message]
|
||||
message/StatusMessage
|
||||
protocol/StatusMessage
|
||||
(validate [this]
|
||||
(if (spec/valid? :message/group-membership-update this)
|
||||
this
|
|
@ -1,17 +1,19 @@
|
|||
(ns ^{:doc "Protocol API and protocol utils"}
|
||||
status-im.transport.message.v1.protocol
|
||||
(:require [status-im.utils.config :as config]
|
||||
[status-im.constants :as constants]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.config :as config]
|
||||
status-im.transport.message.protocol
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
[status-im.chat.core :as chat]
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.transport.db :as transport.db]
|
||||
[status-im.transport.message.core :as message]
|
||||
[status-im.transport.message.v1.core :as transport]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.fx :as fx]
|
||||
[cljs.spec.alpha :as spec]))
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defprotocol StatusMessage
|
||||
"Protocol for the messages that are sent through the transport layer"
|
||||
(send [this chat-id cofx] "Method producing all effects necessary for sending the message record")
|
||||
(receive [this chat-id signature timestamp cofx] "Method producing all effects necessary for receiving the message record")
|
||||
(validate [this] "Method returning the message if it is valid or nil if it is not"))
|
||||
|
||||
(def ^:private whisper-opts
|
||||
{:ttl 10 ;; ttl of 10 sec
|
||||
|
@ -21,15 +23,15 @@
|
|||
(fx/defn init-chat
|
||||
"Initialises chat on protocol layer.
|
||||
If topic is not passed as argument it is derived from `chat-id`"
|
||||
[{:keys [db]}
|
||||
{:keys [chat-id topic resend?]
|
||||
:or {topic (transport.utils/get-topic chat-id)}}]
|
||||
[{:keys [db now]}
|
||||
{:keys [chat-id topic resend?]}]
|
||||
{:db (assoc-in db
|
||||
[:transport/chats chat-id]
|
||||
(transport.db/create-chat {:topic topic
|
||||
:resend? resend?}))})
|
||||
:resend? resend?
|
||||
:now now}))})
|
||||
|
||||
(fx/defn send
|
||||
(fx/defn send-with-sym-key
|
||||
"Sends the payload using symetric key and topic from db (looked up by `chat-id`)"
|
||||
[{:keys [db] :as cofx} {:keys [payload chat-id success-event]}]
|
||||
;; we assume that the chat contains the contact public-key
|
||||
|
@ -76,11 +78,11 @@
|
|||
whisper-opts)}]}))
|
||||
|
||||
(defrecord Message [content content-type message-type clock-value timestamp]
|
||||
message/StatusMessage
|
||||
StatusMessage
|
||||
(send [this chat-id cofx]
|
||||
(let [params {:chat-id chat-id
|
||||
:payload this
|
||||
:success-event [:transport/set-message-envelope-hash
|
||||
:success-event [:transport/message-sent
|
||||
chat-id
|
||||
(transport.utils/message-id this)
|
||||
message-type]}]
|
||||
|
@ -92,7 +94,7 @@
|
|||
chat-id
|
||||
(:success-event params)
|
||||
this)
|
||||
(send cofx params))
|
||||
(send-with-sym-key cofx params))
|
||||
|
||||
:user-message
|
||||
(if config/pfs-encryption-enabled?
|
||||
|
@ -116,14 +118,14 @@
|
|||
(log/warn "failed to validate Message" (spec/explain :message/message this)))))
|
||||
|
||||
(defrecord MessagesSeen [message-ids]
|
||||
message/StatusMessage
|
||||
StatusMessage
|
||||
(send [this chat-id cofx]
|
||||
(if config/pfs-encryption-enabled?
|
||||
(send-direct-message cofx
|
||||
chat-id
|
||||
nil
|
||||
this)
|
||||
(send cofx {:chat-id chat-id
|
||||
(send-with-sym-key cofx {:chat-id chat-id
|
||||
:payload this})))
|
||||
(receive [this chat-id signature _ cofx]
|
||||
(chat/receive-seen cofx chat-id signature this))
|
|
@ -1,8 +1,8 @@
|
|||
(ns ^{:doc "Public chat API"}
|
||||
status-im.transport.message.v1.public-chat
|
||||
status-im.transport.message.public-chat
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.data-store.transport :as transport-store]
|
||||
[status-im.transport.message.v1.protocol :as protocol]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.handlers :as handlers]))
|
||||
|
@ -22,7 +22,8 @@
|
|||
{:shh/generate-sym-key-from-password [{:web3 (:web3 db)
|
||||
:password chat-id
|
||||
:on-success on-success}]}
|
||||
(protocol/init-chat {:chat-id chat-id})))))
|
||||
(protocol/init-chat {:chat-id chat-id
|
||||
:topic (transport.utils/get-topic chat-id)})))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::add-new-sym-key
|
||||
|
@ -39,5 +40,4 @@
|
|||
:chat (-> (get-in db [:transport/chats chat-id])
|
||||
(assoc :sym-key-id sym-key-id)
|
||||
;;TODO (yenda) remove once go implements persistence
|
||||
(assoc :sym-key sym-key))})]
|
||||
:dispatch [:inbox/request-chat-history chat-id]})))
|
||||
(assoc :sym-key sym-key))})]})))
|
|
@ -1,8 +1,8 @@
|
|||
(ns ^{:doc "Transit custom readers and writers, required when adding a new record implementing StatusMessage protocol"}
|
||||
status-im.transport.message.transit
|
||||
(:require [status-im.transport.message.v1.contact :as v1.contact]
|
||||
[status-im.transport.message.v1.protocol :as v1.protocol]
|
||||
[status-im.transport.message.v1.core :as v1]
|
||||
(:require [status-im.transport.message.contact :as contact]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.transport.message.group-chat :as group-chat]
|
||||
[status-im.constants :as constants]
|
||||
[cognitect.transit :as transit]))
|
||||
|
||||
|
@ -89,13 +89,13 @@
|
|||
|
||||
(def writer (transit/writer :json
|
||||
{:handlers
|
||||
{v1.contact/NewContactKey (NewContactKeyHandler.)
|
||||
v1.contact/ContactRequest (ContactRequestHandler.)
|
||||
v1.contact/ContactRequestConfirmed (ContactRequestConfirmedHandler.)
|
||||
v1.contact/ContactUpdate (ContactUpdateHandler.)
|
||||
v1.protocol/Message (MessageHandler.)
|
||||
v1.protocol/MessagesSeen (MessagesSeenHandler.)
|
||||
v1/GroupMembershipUpdate (GroupMembershipUpdateHandler.)}}))
|
||||
{contact/NewContactKey (NewContactKeyHandler.)
|
||||
contact/ContactRequest (ContactRequestHandler.)
|
||||
contact/ContactRequestConfirmed (ContactRequestConfirmedHandler.)
|
||||
contact/ContactUpdate (ContactUpdateHandler.)
|
||||
protocol/Message (MessageHandler.)
|
||||
protocol/MessagesSeen (MessagesSeenHandler.)
|
||||
group-chat/GroupMembershipUpdate (GroupMembershipUpdateHandler.)}}))
|
||||
|
||||
;;
|
||||
;; Reader handlers
|
||||
|
@ -131,22 +131,22 @@
|
|||
(def reader (transit/reader :json
|
||||
{:handlers
|
||||
{"c1" (fn [[sym-key topic message]]
|
||||
(v1.contact/NewContactKey. sym-key topic message))
|
||||
(contact/NewContactKey. sym-key topic message))
|
||||
"c2" (fn [[name profile-image address fcm-token]]
|
||||
(v1.contact/ContactRequest. name profile-image address fcm-token))
|
||||
(contact/ContactRequest. name profile-image address fcm-token))
|
||||
"c3" (fn [[name profile-image address fcm-token]]
|
||||
(v1.contact/ContactRequestConfirmed. name profile-image address fcm-token))
|
||||
(contact/ContactRequestConfirmed. name profile-image address fcm-token))
|
||||
"c4" (fn [[legacy-content content-type message-type clock-value timestamp content]]
|
||||
(let [[new-content new-content-type] (legacy->new-message-data (or content legacy-content) content-type)]
|
||||
(v1.protocol/Message. new-content new-content-type message-type clock-value timestamp)))
|
||||
(protocol/Message. new-content new-content-type message-type clock-value timestamp)))
|
||||
"c7" (fn [[content content-type message-type clock-value timestamp]]
|
||||
(v1.protocol/Message. content content-type message-type clock-value timestamp))
|
||||
(protocol/Message. content content-type message-type clock-value timestamp))
|
||||
"c5" (fn [message-ids]
|
||||
(v1.protocol/MessagesSeen. message-ids))
|
||||
(protocol/MessagesSeen. message-ids))
|
||||
"c6" (fn [[name profile-image address fcm-token]]
|
||||
(v1.contact/ContactUpdate. name profile-image address fcm-token))
|
||||
(contact/ContactUpdate. name profile-image address fcm-token))
|
||||
"g5" (fn [[chat-id membership-updates message]]
|
||||
(v1/GroupMembershipUpdate. chat-id membership-updates message))}}))
|
||||
(group-chat/GroupMembershipUpdate. chat-id membership-updates message))}}))
|
||||
|
||||
(defn serialize
|
||||
"Serializes a record implementing the StatusMessage protocol using the custom writers"
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
(ns ^{:doc "Contact request and update API"}
|
||||
status-im.transport.message.v1.contact
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.data-store.transport :as transport-store]
|
||||
[status-im.transport.message.core :as message]
|
||||
[status-im.transport.message.v1.protocol :as protocol]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.utils.fx :as fx]
|
||||
[cljs.spec.alpha :as spec]))
|
||||
|
||||
(defrecord ContactRequest [name profile-image address fcm-token]
|
||||
message/StatusMessage
|
||||
(send [this chat-id {:keys [db random-id-generator] :as cofx}]
|
||||
(let [topic (transport.utils/get-topic (random-id-generator))
|
||||
on-success (fn [sym-key sym-key-id]
|
||||
(re-frame/dispatch [:contact/send-new-sym-key
|
||||
{:sym-key-id sym-key-id
|
||||
:sym-key sym-key
|
||||
:chat-id chat-id
|
||||
:topic topic
|
||||
:message this}]))]
|
||||
(fx/merge cofx
|
||||
{:shh/get-new-sym-keys [{:web3 (:web3 db)
|
||||
:on-success on-success}]}
|
||||
(protocol/init-chat {:chat-id chat-id
|
||||
:topic topic
|
||||
:resend? "contact-request"}))))
|
||||
(validate [this]
|
||||
(when (spec/valid? :message/contact-request this)
|
||||
this)))
|
||||
|
||||
(defrecord ContactRequestConfirmed [name profile-image address fcm-token]
|
||||
message/StatusMessage
|
||||
(send [this chat-id {:keys [db] :as cofx}]
|
||||
(let [success-event [:transport/set-contact-message-envelope-hash chat-id]
|
||||
chat (get-in db [:transport/chats chat-id])
|
||||
updated-chat (assoc chat :resend? "contact-request-confirmation")]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:transport/chats chat-id :resend?]
|
||||
"contact-request-confirmation")
|
||||
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
|
||||
:chat updated-chat})]}
|
||||
(protocol/send-with-pubkey {:chat-id chat-id
|
||||
:payload this
|
||||
:success-event success-event}))))
|
||||
(validate [this]
|
||||
(when (spec/valid? :message/contact-request-confirmed this)
|
||||
this)))
|
||||
|
||||
(fx/defn send-contact-update
|
||||
[{:keys [db] :as cofx} chat-id payload]
|
||||
(when-let [chat (get-in cofx [:db :transport/chats chat-id])]
|
||||
(let [updated-chat (assoc chat :resend? "contact-update")
|
||||
tx [(transport-store/save-transport-tx {:chat-id chat-id
|
||||
:chat updated-chat})]
|
||||
success-event [:transport/set-contact-message-envelope-hash chat-id]]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:transport/chats chat-id :resend?]
|
||||
"contact-update")
|
||||
:data-store/tx tx}
|
||||
(protocol/send-with-pubkey {:chat-id chat-id
|
||||
:payload payload
|
||||
:success-event success-event})))))
|
||||
|
||||
(defrecord ContactUpdate [name profile-image address fcm-token]
|
||||
message/StatusMessage
|
||||
(send [this _ {:keys [db] :as cofx}]
|
||||
;;TODO: here we look for contact which have a :public-key to differentiate
|
||||
;;actual contacts from dapps
|
||||
;;This is not an ideal solution and we should think about a more reliable way
|
||||
;;to do this when we refactor app-db
|
||||
(let [contact-public-keys (reduce (fn [acc [_ {:keys [public-key pending?]}]]
|
||||
(if (and public-key
|
||||
(not pending?))
|
||||
(conj acc public-key)
|
||||
acc))
|
||||
#{}
|
||||
(:contacts/contacts db))
|
||||
;;NOTE: chats with contacts use public-key as chat-id
|
||||
send-contact-update-fxs (map #(send-contact-update % this) contact-public-keys)]
|
||||
(apply fx/merge cofx send-contact-update-fxs)))
|
||||
(validate [this]
|
||||
(when (spec/valid? :message/contact-update this)
|
||||
this)))
|
||||
|
||||
(fx/defn remove-chat-filter
|
||||
"Stops the filter for the given chat-id"
|
||||
[{:keys [db]} chat-id]
|
||||
(when-let [filter (get-in db [:transport/chats chat-id :filter])]
|
||||
{:shh/remove-filter filter}))
|
||||
|
||||
(fx/defn init-chat
|
||||
[cofx chat-id topic]
|
||||
(when-not (get-in cofx [:db :transport/chats chat-id])
|
||||
(protocol/init-chat cofx
|
||||
{:chat-id chat-id
|
||||
:topic topic})))
|
||||
|
||||
(defrecord NewContactKey [sym-key topic message]
|
||||
message/StatusMessage
|
||||
(send [this chat-id cofx]
|
||||
(let [success-event [:transport/set-contact-message-envelope-hash chat-id]]
|
||||
(protocol/send-with-pubkey cofx
|
||||
{:chat-id chat-id
|
||||
:payload this
|
||||
:success-event success-event})))
|
||||
(receive [this chat-id _ timestamp {:keys [db] :as cofx}]
|
||||
(let [current-sym-key (get-in db [:transport/chats chat-id :sym-key])
|
||||
;; NOTE(yenda) to support concurrent contact request without additional
|
||||
;; interactions we don't save the new key if these conditions are met:
|
||||
;; - the message is a contact request
|
||||
;; - we already have a sym-key
|
||||
;; - this sym-key is first in alphabetical order compared to the new one
|
||||
save-key? (not (and (= ContactRequest (type message))
|
||||
current-sym-key
|
||||
(= current-sym-key
|
||||
(first (sort [current-sym-key sym-key])))))]
|
||||
(if save-key?
|
||||
(let [on-success (fn [sym-key sym-key-id]
|
||||
(re-frame/dispatch [:contact/add-new-sym-key
|
||||
{:sym-key-id sym-key-id
|
||||
:timestamp timestamp
|
||||
:sym-key sym-key
|
||||
:chat-id chat-id
|
||||
:topic topic
|
||||
:message message}]))]
|
||||
(fx/merge cofx
|
||||
{:shh/add-new-sym-keys [{:web3 (:web3 db)
|
||||
:sym-key sym-key
|
||||
:on-success on-success}]}
|
||||
(init-chat chat-id topic)
|
||||
;; in case of concurrent contact request we want
|
||||
;; to stop the filter for the previous key before
|
||||
;; dereferrencing it
|
||||
(remove-chat-filter chat-id)))
|
||||
;; if we don't save the key, we read the message directly
|
||||
(message/receive message chat-id chat-id timestamp cofx))))
|
||||
(validate [this]
|
||||
(when (spec/valid? :message/new-contact-key this)
|
||||
this)))
|
|
@ -1,9 +1,9 @@
|
|||
(ns ^{:doc "Whisper API and events for managing keys and posting messages"}
|
||||
status-im.transport.shh
|
||||
(:require [taoensso.timbre :as log]
|
||||
[re-frame.core :as re-frame]
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.transport.message.transit :as transit]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.transport.message.transit :as transit]))
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn get-new-key-pair [{:keys [web3 on-success on-error]}]
|
||||
(if web3
|
||||
|
@ -70,7 +70,7 @@
|
|||
:shh/send-direct-message
|
||||
(fn [post-calls]
|
||||
(doseq [{:keys [web3 payload src dst success-event error-event]
|
||||
:or {error-event :protocol/send-status-message-error}} post-calls]
|
||||
:or {error-event :transport/send-status-message-error}} post-calls]
|
||||
(let [direct-message (clj->js {:pubKey dst
|
||||
:sig src
|
||||
:payload (-> payload
|
||||
|
@ -86,7 +86,7 @@
|
|||
:shh/send-group-message
|
||||
(fn [params]
|
||||
(let [{:keys [web3 payload src dsts success-event error-event]
|
||||
:or {error-event :protocol/send-status-message-error}} params
|
||||
:or {error-event :transport/send-status-message-error}} params
|
||||
message (clj->js {:pubKeys dsts
|
||||
:sig src
|
||||
:payload (-> payload
|
||||
|
@ -102,7 +102,7 @@
|
|||
:shh/send-public-message
|
||||
(fn [post-calls]
|
||||
(doseq [{:keys [web3 payload src chat success-event error-event]
|
||||
:or {error-event :protocol/send-status-message-error}} post-calls]
|
||||
:or {error-event :transport/send-status-message-error}} post-calls]
|
||||
(let [message (clj->js {:chat chat
|
||||
:sig src
|
||||
:payload (-> payload
|
||||
|
@ -118,7 +118,7 @@
|
|||
:shh/post
|
||||
(fn [post-calls]
|
||||
(doseq [{:keys [web3 message success-event error-event]
|
||||
:or {error-event :protocol/send-status-message-error}} post-calls]
|
||||
:or {error-event :transport/send-status-message-error}} post-calls]
|
||||
(post-message {:web3 web3
|
||||
:whisper-message (update message :payload (comp transport.utils/from-utf8
|
||||
transit/serialize))
|
||||
|
@ -127,28 +127,6 @@
|
|||
#(log/debug :shh/post-success))
|
||||
:on-error #(re-frame/dispatch [error-event %])}))))
|
||||
|
||||
;; This event params contain a recipients key because it's a vector of map with public-key and topic keys.
|
||||
;; the :shh/post event has public-key and topic keys at the top level of the args map.
|
||||
;; This event is used to send messages to multiple recipients when you can't send it on a topic.
|
||||
;; It is used for renewing keys in a private group chat, because if someone leaves/join.
|
||||
;; We want to change the symmetric key but we can't do that in the group topic with the old key
|
||||
;; otherwise leavers can still eavesdrop / joiners can read past history."
|
||||
(re-frame/reg-fx
|
||||
:shh/multi-post
|
||||
(fn [{:keys [web3 message recipients success-event error-event]
|
||||
:or {error-event :protocol/send-status-message-error}}]
|
||||
(let [whisper-message (update message :payload (comp transport.utils/from-utf8
|
||||
transit/serialize))]
|
||||
(doseq [{:keys [sym-key-id topic]} recipients]
|
||||
(post-message {:web3 web3
|
||||
:whisper-message (assoc whisper-message
|
||||
:topic topic
|
||||
:symKeyID sym-key-id)
|
||||
:on-success (if success-event
|
||||
#(re-frame/dispatch success-event)
|
||||
#(log/debug :shh/post-success))
|
||||
:on-error #(re-frame/dispatch [error-event %])})))))
|
||||
|
||||
(defn add-sym-key
|
||||
[{:keys [web3 sym-key on-success on-error]}]
|
||||
(.. web3
|
||||
|
|
|
@ -1,19 +1,7 @@
|
|||
(ns ^{:doc "Utils for transport layer"}
|
||||
status-im.transport.utils
|
||||
(:require [cljs-time.coerce :refer [to-long]]
|
||||
[cljs-time.core :refer [now]]
|
||||
[clojure.string :as string]
|
||||
[status-im.js-dependencies :as dependencies]
|
||||
[status-im.data-store.transport :as transport-store]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
(fx/defn unsubscribe-from-chat
|
||||
"Unsubscribe from chat on transport layer"
|
||||
[{:keys [db]} chat-id]
|
||||
(let [filter (get-in db [:transport/chats chat-id :filter])]
|
||||
{:db (update db :transport/chats dissoc chat-id)
|
||||
:data-store/tx [(transport-store/delete-transport-tx chat-id)]
|
||||
:shh/remove-filter filter}))
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.js-dependencies :as dependencies]))
|
||||
|
||||
(defn from-utf8 [s]
|
||||
(.fromUtf8 dependencies/Web3.prototype s))
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
:accessibility-label :connection-status-text}
|
||||
[react/text {:style styles/text
|
||||
:on-press (when mailserver-error?
|
||||
#(re-frame/dispatch [:inbox/reconnect]))}
|
||||
#(re-frame/dispatch [:inbox.ui/reconnect-mailserver-pressed]))}
|
||||
(i18n/label label)]]))
|
||||
|
||||
(defview error-view [{:keys [top]}]
|
||||
|
|
|
@ -49,7 +49,10 @@
|
|||
:inbox/wnodes fleet/default-wnodes
|
||||
:my-profile/editing? false
|
||||
:transport/chats {}
|
||||
:transport/filters {}
|
||||
:transport/message-envelopes {}
|
||||
:transport.inbox/topics {}
|
||||
:transport.inbox/requests {}
|
||||
:chat/cooldowns 0
|
||||
:chat/cooldown-enabled? false
|
||||
:chat/last-outgoing-message-sent-at 0
|
||||
|
@ -86,7 +89,7 @@
|
|||
;;:online - presence of internet connection in the phone
|
||||
(spec/def ::network-status (spec/nilable keyword?))
|
||||
|
||||
(spec/def ::mailserver-status (spec/nilable keyword?))
|
||||
(spec/def ::mailserver-status (spec/nilable #{:disconnected :connecting :added :connected :error}))
|
||||
|
||||
(spec/def ::app-state string?)
|
||||
|
||||
|
@ -212,7 +215,6 @@
|
|||
:mailservers/manage
|
||||
:bootnodes/manage
|
||||
:inbox/wnodes
|
||||
:inbox/last-received
|
||||
:inbox/current-id
|
||||
:inbox/fetching?
|
||||
:universal-links/url
|
||||
|
@ -227,7 +229,9 @@
|
|||
:chat/spam-messages-frequency
|
||||
:transport/message-envelopes
|
||||
:transport/chats
|
||||
:transport/discovery-filter
|
||||
:transport/filters
|
||||
:transport.inbox/topics
|
||||
:transport.inbox/requests
|
||||
:desktop/desktop
|
||||
:dimensions/window
|
||||
:dapps/permissions]
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
|
||||
(fx/defn on-return-from-background [cofx]
|
||||
(fx/merge cofx
|
||||
(inbox/request-messages)
|
||||
(inbox/request-messages nil)
|
||||
(hardwallet/return-back-from-nfc-settings)))
|
||||
|
||||
(defn app-state-change [state {:keys [db] :as cofx}]
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
[status-im.i18n :as i18n]
|
||||
[status-im.chat.models.message :as models.message]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.transport.message.v1.core :as protocol]
|
||||
[status-im.transport.message.core :as transport]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.data-store.chats :as chats-store]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
|
|
@ -12,10 +12,11 @@
|
|||
(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))))
|
||||
(spec/def :inbox/last-received integer?)
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
|
||||
(reg-sub :fetching?
|
||||
(fn [db]
|
||||
(get db :inbox/fetching?)))
|
||||
(pos-int? (count (get db :transport.inbox/requests)))))
|
||||
|
||||
(reg-sub :offline?
|
||||
:<- [:network-status]
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
(def ^:private mergable-keys
|
||||
#{:data-store/tx :data-store/base-tx :chat-received-message/add-fx
|
||||
:shh/add-new-sym-keys :shh/get-new-sym-keys :shh/post
|
||||
:shh/generate-sym-key-from-password :confirm-messages-processed
|
||||
:shh/generate-sym-key-from-password :transport/confirm-messages-processed
|
||||
:group-chats/extract-membership-signature :utils/dispatch-later})
|
||||
|
||||
(defn- safe-merge [fx new-fx]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
(ns status-im.test.chat.models.message
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.transport.message.v1.protocol :as protocol]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.chat.models.message :as message]
|
||||
[status-im.utils.datetime :as time]))
|
||||
|
||||
|
@ -62,7 +62,7 @@
|
|||
(testing "it marks the message as outgoing"
|
||||
(is (= true (:outgoing message))))
|
||||
(testing "it confirm the message as processed"
|
||||
(is (:confirm-messages-processed actual)))
|
||||
(is (:transport/confirm-messages-processed actual)))
|
||||
(testing "it stores the message"
|
||||
(is (:data-store/tx actual)))
|
||||
(testing "it does not send a seen confirmation"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
[status-im.transport.utils :as transport.utils]
|
||||
[day8.re-frame.test :refer-macros [run-test-async run-test-sync] :as rf-test]
|
||||
[status-im.test.protocol.node :as node]
|
||||
[status-im.transport.message.v1.contact :as transport.contact]
|
||||
[status-im.transport.message.contact :as transport.contact]
|
||||
[status-im.test.protocol.utils :as utils]))
|
||||
|
||||
;; NOTE(oskarth): All these tests are evaluated in NodeJS
|
||||
|
@ -45,7 +45,7 @@
|
|||
(rf-test/wait-for [::transport.contact/send-new-sym-key]
|
||||
(rf/dispatch [:set-chat-input-text "test message"])
|
||||
(rf/dispatch [:send-current-message])
|
||||
(rf-test/wait-for [:update-message-status :protocol/send-status-message-error]
|
||||
(rf-test/wait-for [:update-message-status :transport/send-status-message-error]
|
||||
(is true)))))))
|
||||
|
||||
(deftest test-whisper-version!
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
[status-im.test.models.wallet]
|
||||
[status-im.test.transport.core]
|
||||
[status-im.test.transport.inbox]
|
||||
[status-im.test.transport.handlers]
|
||||
[status-im.test.chat.models]
|
||||
[status-im.test.chat.models.input]
|
||||
[status-im.test.chat.models.loading]
|
||||
|
@ -97,7 +96,6 @@
|
|||
'status-im.test.i18n
|
||||
'status-im.test.transport.core
|
||||
'status-im.test.transport.inbox
|
||||
'status-im.test.transport.handlers
|
||||
'status-im.test.protocol.web3.inbox
|
||||
'status-im.test.utils.utils
|
||||
'status-im.test.utils.money
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
(ns status-im.test.transport.core
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[status-im.transport.core :as transport]))
|
||||
[status-im.transport.message.core :as message]))
|
||||
|
||||
(deftest init-whisper
|
||||
(let [cofx {:db {:account/account {:public-key "1"}
|
||||
|
@ -41,6 +41,30 @@
|
|||
ms-2
|
||||
ms-3])]
|
||||
(is (= expected-wnodes
|
||||
(get-in
|
||||
(-> (get-in
|
||||
(protocol/initialize-protocol cofx-with-ms "user-address")
|
||||
[:db :inbox/wnodes])))))))
|
||||
[:db :inbox/wnodes])
|
||||
(update-in [:eth.beta "1"] dissoc :generating-sym-key?)
|
||||
(update-in [:eth.beta "2"] dissoc :generating-sym-key?)
|
||||
(update-in [:eth.test "3"] dissoc :generating-sym-key?))))))))
|
||||
|
||||
(def sig "0x04325367620ae20dd878dbb39f69f02c567d789dd21af8a88623dc5b529827c2812571c380a2cd8236a2851b8843d6486481166c39debf60a5d30b9099c66213e4")
|
||||
|
||||
(def messages #js [{:sig sig
|
||||
:ttl 10
|
||||
:timestamp 1527692015
|
||||
:topic "0x9c22ff5f"
|
||||
:payload "0x5b227e236334222c5b2246222c22746578742f706c61696e222c227e3a7075626c69632d67726f75702d757365722d6d657373616765222c3135323736393230313433383130312c313532373639323031343337375d5d"
|
||||
:padding "0xbf06347cc7f9aa18b4a846032264a88f559d9b14079975d14b10648847c0543a77a80624e101c082d19b502ae3b4f97958d18abf59eb0a82afc1301aa22470495fac739a30c2f563599fa8d8e09363a43d39311596b7f119dee7b046989c08224f1ef5cdc385"
|
||||
:pow 0.002631578947368421
|
||||
:hash "0x220ef9994a4fae64c112b27ed07ef910918159cbe6fcf8ac515ee2bf9a6711a0"}])
|
||||
|
||||
(deftest receive-whisper-messages-test
|
||||
(testing "an error is reported"
|
||||
(is (nil? (:chat-received-message/add-fx (message/receive-whisper-messages {:db {}} "error" #js [] nil)))))
|
||||
(testing "messages is undefined"
|
||||
(is (nil? (:chat-received-message/add-fx (message/receive-whisper-messages {:db {}} nil js/undefined nil)))))
|
||||
(testing "happy path"
|
||||
(let [actual (message/receive-whisper-messages {:db {}} nil messages sig)]
|
||||
(testing "it add an fx for the message"
|
||||
(is (:chat-received-message/add-fx actual))))))
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
(ns status-im.test.transport.handlers
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.transport.handlers :as handlers]))
|
||||
|
||||
(def sig "0x04325367620ae20dd878dbb39f69f02c567d789dd21af8a88623dc5b529827c2812571c380a2cd8236a2851b8843d6486481166c39debf60a5d30b9099c66213e4")
|
||||
|
||||
(def messages #js [{:sig sig
|
||||
:ttl 10
|
||||
:timestamp 1527692015
|
||||
:topic "0x9c22ff5f"
|
||||
:payload "0x5b227e236334222c5b2246222c22746578742f706c61696e222c227e3a7075626c69632d67726f75702d757365722d6d657373616765222c3135323736393230313433383130312c313532373639323031343337375d5d"
|
||||
:padding "0xbf06347cc7f9aa18b4a846032264a88f559d9b14079975d14b10648847c0543a77a80624e101c082d19b502ae3b4f97958d18abf59eb0a82afc1301aa22470495fac739a30c2f563599fa8d8e09363a43d39311596b7f119dee7b046989c08224f1ef5cdc385"
|
||||
:pow 0.002631578947368421
|
||||
:hash "0x220ef9994a4fae64c112b27ed07ef910918159cbe6fcf8ac515ee2bf9a6711a0"}])
|
||||
|
||||
(deftest receive-whisper-messages-test
|
||||
(testing "an error is reported"
|
||||
(is (nil? (:chat-received-message/add-fx (handlers/receive-whisper-messages {:db {}} "error" #js [] nil)))))
|
||||
(testing "messages is undefined"
|
||||
(is (nil? (:chat-received-message/add-fx (handlers/receive-whisper-messages {:db {}} nil js/undefined nil)))))
|
||||
(testing "happy path"
|
||||
(let [actual (handlers/receive-whisper-messages {:db {}} nil messages sig)]
|
||||
(testing "it add an fx for the message"
|
||||
(is (:chat-received-message/add-fx actual))))))
|
|
@ -20,20 +20,20 @@
|
|||
[])))
|
||||
|
||||
(deftest peers-summary-change
|
||||
(testing "Mailserver connected"
|
||||
(testing "Mailserver added, sym-key doesn't exist"
|
||||
(let [result (peers-summary-change-result false true false)]
|
||||
(is (= (into #{} (keys result))
|
||||
#{:status-im.transport.inbox/mark-trusted-peer}))))
|
||||
#{: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 :status-im.transport.inbox/add-peer :utils/dispatch-later}))
|
||||
#{: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 :status-im.transport.inbox/add-peer :utils/dispatch-later :shh/generate-sym-key-from-password}))
|
||||
#{: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"
|
||||
|
@ -51,8 +51,8 @@
|
|||
{:settings {:fleet :eth.beta
|
||||
:wnode {:eth.beta "wnodeid"}}}}]
|
||||
(testing "it adds the peer"
|
||||
(is (= {:wnode "wnode-address"}
|
||||
(::inbox/add-peer (inbox/connect-to-mailserver {:db db})))))
|
||||
(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})
|
||||
|
@ -67,7 +67,7 @@
|
|||
:shh/generate-sym-key-from-password
|
||||
first)))))))
|
||||
|
||||
(deftest request-messages
|
||||
#_(deftest request-messages
|
||||
(let [db {:mailserver-status :connected
|
||||
:inbox/current-id "wnodeid"
|
||||
:inbox/wnodes {:eth.beta {"wnodeid" {:address "wnode-address"
|
||||
|
@ -76,95 +76,37 @@
|
|||
:account/account {:settings {:fleet :eth.beta}}
|
||||
:transport/chats
|
||||
{:dont-fetch-history {:topic "dont-fetch-history"}
|
||||
:fetch-history {:topic "fetch-history"
|
||||
:fetch-history? true}}}
|
||||
:fetch-history {:topic "fetch-history"}}}
|
||||
cofx {:db db :now 1000000000}]
|
||||
(testing "inbox is ready"
|
||||
(testing "last request is > the 7 days ago"
|
||||
(let [cofx-with-last-request (assoc-in cofx [:db :account/account :last-request] 400000)
|
||||
actual (inbox/request-messages cofx-with-last-request)]
|
||||
actual (inbox/request-messages cofx-with-last-request nil)]
|
||||
(testing "it uses last request"
|
||||
(is (= 400000 (get-in actual [::inbox/request-messages 0 :from]))))))
|
||||
(is (= 400000 (get-in actual [:transport.inbox/request-messages :requests]))))))
|
||||
(testing "last request is < the 7 days ago"
|
||||
(let [cofx-with-last-request (assoc-in cofx [:db :account/account :last-request] 2)
|
||||
actual (inbox/request-messages cofx-with-last-request)]
|
||||
actual (inbox/request-messages cofx-with-last-request nil)]
|
||||
(testing "it uses last 7 days for catching up"
|
||||
(is (= 395200 (get-in actual [::inbox/request-messages 0 :from]))))
|
||||
(is (= 395200 (get-in actual [:transport.inbox/request-messages :requests]))))
|
||||
(testing "it only uses topics that dont have fetch history set"
|
||||
(is (= ["0xf8946aac" "dont-fetch-history"]
|
||||
(get-in actual [::inbox/request-messages 0 :topics]))))
|
||||
(get-in actual [:transport.inbox/request-messages :requests]))))
|
||||
(testing "it uses the last 24 hours to request history"
|
||||
(is (= 913600
|
||||
(get-in actual [::inbox/request-messages 1 :from]))))
|
||||
(get-in actual [:transport.inbox/request-messages :requests]))))
|
||||
(testing "it fetches the right topic for history"
|
||||
(is (= ["fetch-history"]
|
||||
(get-in actual [::inbox/request-messages 1 :topics])))))))
|
||||
(get-in actual [:transport.inbox/request-messages :requests])))))))
|
||||
(testing "inbox is not ready"
|
||||
(testing "it does not do anything"
|
||||
(is (nil? (inbox/request-messages {:db {}})))))))
|
||||
(is (nil? (inbox/request-messages {:db {}} nil)))))))
|
||||
|
||||
(deftest request-messages-params
|
||||
(let [mailserver {:address "peer"
|
||||
:sym-key-id "id"}]
|
||||
(testing "from is greater that to"
|
||||
(testing "it returns an empty sequence"
|
||||
(is (empty? (inbox/request-inbox-messages-params mailserver 2 0 ["a" "b" "c"])))))
|
||||
(testing "from is equal to to"
|
||||
(testing "it returns an empty sequence"
|
||||
(is (empty? (inbox/request-inbox-messages-params mailserver 2 2 ["a" "b" "c"])))))
|
||||
(testing "to is less than the step"
|
||||
(is (= #{{:topic "a"
|
||||
:mailServerPeer "peer"
|
||||
:symKeyID "id"
|
||||
:from 0
|
||||
:to 3}
|
||||
{:topic "b"
|
||||
:mailServerPeer "peer"
|
||||
:symKeyID "id"
|
||||
:from 0
|
||||
:to 3}}
|
||||
(into #{} (inbox/request-inbox-messages-params mailserver 0 3 ["a" "b"])))))
|
||||
(testing "to is equal the step"
|
||||
(is (= #{{:topic "a"
|
||||
:mailServerPeer "peer"
|
||||
:symKeyID "id"
|
||||
:from 0
|
||||
:to 86400}
|
||||
{:topic "b"
|
||||
:mailServerPeer "peer"
|
||||
:symKeyID "id"
|
||||
:from 0
|
||||
:to 86400}}
|
||||
(into #{} (inbox/request-inbox-messages-params mailserver 0 86400 ["a" "b"])))))
|
||||
(testing "to is greather than the step"
|
||||
(is (= #{{:topic "a"
|
||||
:mailServerPeer "peer"
|
||||
:symKeyID "id"
|
||||
:from 0
|
||||
:to 86400}
|
||||
{:topic "b"
|
||||
:mailServerPeer "peer"
|
||||
:symKeyID "id"
|
||||
:from 0
|
||||
:to 86400}
|
||||
{:topic "a"
|
||||
:mailServerPeer "peer"
|
||||
:symKeyID "id"
|
||||
:from 86400
|
||||
:to 90000}
|
||||
{:topic "b"
|
||||
:mailServerPeer "peer"
|
||||
:symKeyID "id"
|
||||
:from 86400
|
||||
:to 90000}}
|
||||
(into #{} (inbox/request-inbox-messages-params mailserver 0 90000 ["a" "b"])))))))
|
||||
|
||||
(deftest initialize-offline-inbox
|
||||
#_(deftest initialize-offline-inbox
|
||||
(let [db {:mailserver-status :connected
|
||||
:account/account {:settings {:fleet :eth.beta}}
|
||||
:inbox/current-id "wnodeid"
|
||||
:inbox/wnodes
|
||||
{:eth.beta {"wnodeid" {:address "wnode-address"
|
||||
:inbox/wnodes {:eth.beta {"wnodeid" {:address "wnode-address"
|
||||
:sym-key-id "something"
|
||||
:password "wnode-password"}}}}]
|
||||
(testing "last-request is not set"
|
||||
|
|
Loading…
Reference in New Issue