Accounts refactoring #1610

This commit is contained in:
Andrey Shovkoplyas 2017-08-15 17:14:39 +03:00 committed by Roman Volosovskyi
parent cb48195383
commit bab4e33ec2
41 changed files with 451 additions and 385 deletions

View File

@ -1,6 +1,7 @@
(ns status-im.android.core (ns status-im.android.core
(:require [reagent.core :as reagent] (:require [reagent.core :as reagent]
[re-frame.core :refer [subscribe dispatch dispatch-sync]] [re-frame.core :refer [subscribe dispatch dispatch-sync]]
status-im.utils.db
status-im.ui.screens.db status-im.ui.screens.db
status-im.ui.screens.events status-im.ui.screens.events
status-im.ui.screens.subs status-im.ui.screens.subs
@ -16,7 +17,7 @@
;; this listener and handle application's closing ;; this listener and handle application's closing
;; in handlers ;; in handlers
(let [stack (subscribe [:get :navigation-stack]) (let [stack (subscribe [:get :navigation-stack])
creating? (subscribe [:get :creating-account?]) creating? (subscribe [:get :accounts/creating-account?])
result-box (subscribe [:chat-ui-props :result-box]) result-box (subscribe [:chat-ui-props :result-box])
webview (subscribe [:get :webview-bridge])] webview (subscribe [:get :webview-bridge])]
(cond (cond

View File

@ -15,7 +15,7 @@
(defn generate-context (defn generate-context
"Generates context for jail call" "Generates context for jail call"
[{:keys [current-account-id chats]} chat-id to] [{:keys [chats] :accounts/keys [current-account-id]} chat-id to]
(merge {:platform platform/platform (merge {:platform platform/platform
:from current-account-id :from current-account-id
:to to :to to
@ -72,7 +72,8 @@
[{{:keys [command content-command params type]} :content [{{:keys [command content-command params type]} :content
:keys [chat-id jail-id] :as message} :keys [chat-id jail-id] :as message}
data-type]] data-type]]
(let [{:keys [current-account-id chats] (let [{:keys [chats]
:accounts/keys [current-account-id]
:contacts/keys [contacts]} db :contacts/keys [contacts]} db
jail-id (or jail-id chat-id) jail-id (or jail-id chat-id)
jail-id (if (get-in chats [jail-id :group-chat]) jail-id (if (get-in chats [jail-id :group-chat])

View File

@ -202,7 +202,7 @@
(register-handler-fx (register-handler-fx
:load-chat-parameter-box :load-chat-parameter-box
[trim-v] [trim-v]
(fn [{{:keys [current-chat-id bot-db current-account-id] :as db} :db} (fn [{{:keys [current-chat-id bot-db] :accounts/keys [current-account-id] :as db} :db}
[{:keys [name type bot owner-id] :as command}]] [{:keys [name type bot owner-id] :as command}]]
(let [parameter-index (input-model/argument-position db current-chat-id)] (let [parameter-index (input-model/argument-position db current-chat-id)]
(when (and command (> parameter-index -1)) (when (and command (> parameter-index -1))
@ -238,7 +238,7 @@
(register-handler-fx (register-handler-fx
::send-message ::send-message
[trim-v] [trim-v]
(fn [{{:keys [current-public-key current-account-id] :as db} :db} [command chat-id]] (fn [{{:keys [current-public-key] :accounts/keys [current-account-id] :as db} :db} [command chat-id]]
(let [text (get-in db [:chats chat-id :input-text]) (let [text (get-in db [:chats chat-id :input-text])
data {:message text data {:message text
:command command :command command
@ -385,7 +385,7 @@
(register-handler-fx (register-handler-fx
::check-dapp-suggestions ::check-dapp-suggestions
[trim-v] [trim-v]
(fn [{{:keys [current-account-id] :as db} :db} [chat-id text]] (fn [{{:accounts/keys [current-account-id] :as db} :db} [chat-id text]]
(let [data (get-in db [:local-storage chat-id])] (let [data (get-in db [:local-storage chat-id])]
{:chat-fx/call-jail-function {:chat-id chat-id {:chat-fx/call-jail-function {:chat-id chat-id
:function :on-message-input-change :function :on-message-input-change

View File

@ -104,7 +104,7 @@
(update-in [:chats current-chat-id :input-text] safe-trim)))) (update-in [:chats current-chat-id :input-text] safe-trim))))
(defn init-console-chat (defn init-console-chat
([{:keys [chats current-account-id] :as db} existing-account?] ([{:keys [chats] :accounts/keys [current-account-id] :as db} existing-account?]
(let [new-chat sign-up-service/console-chat] (let [new-chat sign-up-service/console-chat]
(if (chats console-chat-id) (if (chats console-chat-id)
db db
@ -213,7 +213,7 @@
(compare timestamp2 timesatmp1)) (compare timestamp2 timesatmp1))
(defn initialize-chats (defn initialize-chats
[{:keys [loaded-chats account-creation? chats] :as db} _] [{:keys [loaded-chats chats] :accounts/keys [account-creation?] :as db} _]
(let [chats' (if account-creation? (let [chats' (if account-creation?
chats chats
(->> loaded-chats (->> loaded-chats
@ -228,7 +228,7 @@
(init-console-chat true)))) (init-console-chat true))))
(defn load-chats! (defn load-chats!
[{:keys [account-creation?] :as db} _] [{:accounts/keys [account-creation?] :as db} _]
(if account-creation? (if account-creation?
db db
(assoc db :loaded-chats (chats/get-all)))) (assoc db :loaded-chats (chats/get-all))))
@ -253,7 +253,7 @@
(init-console-chat true))))) (init-console-chat true)))))
(defmethod nav/preload-data! :chat (defmethod nav/preload-data! :chat
[{:keys [current-chat-id current-account-id] :as db} [_ _ id]] [{:keys [current-chat-id] :accounts/keys [current-account-id] :as db} [_ _ id]]
(let [chat-id (or id current-chat-id) (let [chat-id (or id current-chat-id)
messages (get-in db [:chats chat-id :messages]) messages (get-in db [:chats chat-id :messages])
db' (-> db db' (-> db

View File

@ -43,7 +43,7 @@
(register-handler :open-faucet (register-handler :open-faucet
(u/side-effect! (u/side-effect!
(fn [{:keys [accounts current-account-id]} [_ faucet-name _]] (fn [{:accounts/keys [accounts current-account-id]} [_ faucet-name _]]
(if-let [faucet (faucet-by-name faucet-name)] (if-let [faucet (faucet-by-name faucet-name)]
(let [current-address (get-in accounts [current-account-id :address])] (let [current-address (get-in accounts [current-account-id :address])]
(open-faucet faucet-name current-address faucet)))))) (open-faucet faucet-name current-address faucet))))))

View File

@ -18,8 +18,8 @@
(messages/save chat-id (dissoc message :new?))) (messages/save chat-id (dissoc message :new?)))
(defn get-current-identity (defn get-current-identity
[{:keys [current-account-id accounts]}] [{:accounts/keys [accounts current-account-id]}]
(:public-key (accounts current-account-id))) (get-in accounts [current-account-id :public-key]))
(declare add-message-to-wallet) (declare add-message-to-wallet)

View File

@ -137,7 +137,8 @@
(register-handler ::invoke-command-handlers! (register-handler ::invoke-command-handlers!
(u/side-effect! (u/side-effect!
(fn [{:keys [bot-db accounts current-account-id] (fn [{:keys [bot-db]
:accounts/keys [accounts current-account-id]
:contacts/keys [contacts] :as db} :contacts/keys [contacts] :as db}
[_ {{:keys [command [_ {{:keys [command
params params
@ -207,7 +208,7 @@
(register-handler ::send-dapp-message (register-handler ::send-dapp-message
(u/side-effect! (u/side-effect!
(fn [{:keys [current-account-id] :as db} [_ chat-id {:keys [content]}]] (fn [{:accounts/keys [current-account-id] :as db} [_ chat-id {:keys [content]}]]
(let [data (get-in db [:local-storage chat-id])] (let [data (get-in db [:local-storage chat-id])]
(status/call-function! (status/call-function!
{:chat-id chat-id {:chat-id chat-id
@ -287,7 +288,8 @@
(register-handler ::send-message! (register-handler ::send-message!
(u/side-effect! (u/side-effect!
(fn [{:keys [web3 chats network-status current-account-id accounts] (fn [{:keys [web3 chats network-status]
:accounts/keys [accounts current-account-id]
:contacts/keys [contacts] :contacts/keys [contacts]
:as db} [_ {{:keys [message-type] :as db} [_ {{:keys [message-type]
:as message} :message :as message} :message
@ -324,8 +326,8 @@
(register-handler ::send-command-protocol! (register-handler ::send-command-protocol!
(u/side-effect! (u/side-effect!
(fn [{:keys [web3 current-public-key chats network-status (fn [{:keys [web3 current-public-key chats network-status]
current-account-id accounts] :accounts/keys [accounts current-account-id]
:contacts/keys [contacts] :as db} :contacts/keys [contacts] :as db}
[_ {:keys [chat-id command]}]] [_ {:keys [chat-id command]}]]
(if (get-in contacts [chat-id :dapp?]) (if (get-in contacts [chat-id :dapp?])

View File

@ -7,12 +7,12 @@
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.models.commands :as commands] [status-im.models.commands :as commands]
[status-im.commands.utils :as cu] [status-im.commands.utils :as cu]
[status-im.ui.screens.contacts.db :as v]
[status-im.components.status :as s] [status-im.components.status :as s]
[status-im.components.nfc :as nfc] [status-im.components.nfc :as nfc]
[status-im.constants :as c] [status-im.constants :as c]
[cljs.reader :refer [read-string]] [cljs.reader :refer [read-string]]
[status-im.ui.screens.navigation :as nav])) [status-im.ui.screens.navigation :as nav]
[cljs.spec.alpha :as spec]))
(defn by-public-key [public-key contacts] (defn by-public-key [public-key contacts]
(when-let [{:keys [address]} (contacts public-key)] (when-let [{:keys [address]} (contacts public-key)]
@ -29,7 +29,7 @@
(catch :default e data)) (catch :default e data))
data'' (cond data'' (cond
(map? data') data' (map? data') data'
(v/is-address? data') {:address data'} (spec/valid? :global/address data') {:address data'}
(string? data') (by-public-key data' contacts) (string? data') (by-public-key data' contacts)
:else nil)] :else nil)]
(when data'' (when data''
@ -127,7 +127,7 @@
(register-handler :webview-send-eth! (register-handler :webview-send-eth!
(u/side-effect! (u/side-effect!
(fn [{:keys [current-account-id]} [_ {:keys [amount address]}]] (fn [{:accounts/keys [current-account-id]} [_ {:keys [amount address]}]]
(let [context {:from current-account-id} (let [context {:from current-account-id}
path [:functions :send] path [:functions :send]
parameters {:context context parameters {:context context

View File

@ -1,5 +1,6 @@
(ns status-im.chat.new-public-chat.db (ns status-im.chat.new-public-chat.db
(:require [cljs.spec.alpha :as spec] (:require [cljs.spec.alpha :as spec]
status-im.utils.db
[status-im.constants :refer [console-chat-id wallet-chat-id]] [status-im.constants :refer [console-chat-id wallet-chat-id]]
[clojure.string :as string] [clojure.string :as string]
[status-im.utils.homoglyph :as utils])) [status-im.utils.homoglyph :as utils]))
@ -10,11 +11,10 @@
(not (utils/matches username wallet-chat-id))))) (not (utils/matches username wallet-chat-id)))))
(spec/def ::legal-name legal-name?) (spec/def ::legal-name legal-name?)
(spec/def ::not-empty-string (spec/and string? not-empty))
(spec/def ::name (spec/and ::not-empty-string (spec/def ::name (spec/and :global/not-empty-string
::legal-name)) ::legal-name))
(spec/def ::topic (spec/and ::not-empty-string (spec/def ::topic (spec/and :global/not-empty-string
::legal-name ::legal-name
(partial re-matches #"[a-z0-9\-]+"))) (partial re-matches #"[a-z0-9\-]+")))

View File

@ -1,6 +1,7 @@
(ns status-im.chat.new-public-chat.view (ns status-im.chat.new-public-chat.view
(:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [re-frame.core :refer [dispatch]] (:require [re-frame.core :refer [dispatch]]
status-im.utils.db
[status-im.components.react :refer [view text]] [status-im.components.react :refer [view text]]
[status-im.components.text-field.view :refer [text-field]] [status-im.components.text-field.view :refer [text-field]]
[status-im.components.styles :as common] [status-im.components.styles :as common]
@ -30,7 +31,7 @@
[view [view
[text-field [text-field
{:error (cond {:error (cond
(not (spec/valid? ::v/not-empty-string topic)) (not (spec/valid? :global/not-empty-string topic))
(label :t/empty-topic) (label :t/empty-topic)
(not (spec/valid? ::v/topic topic)) (not (spec/valid? ::v/topic topic))

View File

@ -110,8 +110,8 @@
(defview chat-toolbar [] (defview chat-toolbar []
[show-actions? [:chat-ui-props :show-actions?] [show-actions? [:chat-ui-props :show-actions?]
accounts [:get :accounts] accounts [:get-accounts]
creating? [:get :creating-account?]] creating? [:get :accounts/creating-account?]]
[view [view
[status-bar] [status-bar]
[toolbar {:hide-nav? (or (empty? accounts) show-actions? creating?) [toolbar {:hide-nav? (or (empty? accounts) show-actions? creating?)

View File

@ -69,10 +69,10 @@
public? [:chat :public?] public? [:chat :public?]
public-key [:chat :public-key] public-key [:chat :public-key]
show-actions? [:chat-ui-props :show-actions?] show-actions? [:chat-ui-props :show-actions?]
accounts [:get :accounts] accounts [:get-accounts]
contact [:get-in [:contacts/contacts @chat-id]] contact [:get-in [:contacts/contacts @chat-id]]
sync-state [:get :sync-state] sync-state [:get :sync-state]
creating? [:get :creating-account?]] creating? [:get :accounts/creating-account?]]
[view (st/chat-name-view (or (empty? accounts) [view (st/chat-name-view (or (empty? accounts)
show-actions? show-actions?
creating?)) creating?))

View File

@ -126,7 +126,7 @@
(register-handler :debug-switch-node (register-handler :debug-switch-node
(u/side-effect! (u/side-effect!
(fn [{:keys [current-account-id]} [_ {:keys [url]}]] (fn [{:accounts/keys [current-account-id]} [_ {:keys [url]}]]
(dispatch [:initialize-protocol current-account-id url]) (dispatch [:initialize-protocol current-account-id url])
(respond {:type :ok (respond {:type :ok
:text "You've successfully switched the node."})))) :text "You've successfully switched the node."}))))

View File

@ -6,8 +6,8 @@
(defn sign-up (defn sign-up
[db phone-number message-id handler] [db phone-number message-id handler]
(let [current-account-id (get db :current-account-id) (let [current-account-id (get db :accounts/current-account-id)
{:keys [public-key address]} (get-in db [:accounts current-account-id])] {:keys [public-key address]} (get-in db [:accounts/accounts current-account-id])]
(log/debug "signing up with public-key" public-key "and phone " phone-number) (log/debug "signing up with public-key" public-key "and phone " phone-number)
(http-post "sign-up" {:phone-number phone-number (http-post "sign-up" {:phone-number phone-number
:whisper-identity public-key :whisper-identity public-key

View File

@ -1,6 +1,7 @@
(ns status-im.ios.core (ns status-im.ios.core
(:require [reagent.core :as reagent] (:require [reagent.core :as reagent]
[re-frame.core :refer [subscribe dispatch dispatch-sync]] [re-frame.core :refer [subscribe dispatch dispatch-sync]]
status-im.utils.db
status-im.ui.screens.db status-im.ui.screens.db
status-im.ui.screens.events status-im.ui.screens.events
status-im.ui.screens.subs status-im.ui.screens.subs

View File

@ -19,13 +19,14 @@
[status-im.components.status :as status] [status-im.components.status :as status]
[clojure.string :refer [join]] [clojure.string :refer [join]]
[status-im.utils.scheduler :as s] [status-im.utils.scheduler :as s]
[status-im.utils.web3-provider :as w3])) [status-im.utils.web3-provider :as w3]
[status-im.utils.datetime :as time]))
(register-handler :initialize-protocol (register-handler :initialize-protocol
(fn [db [_ current-account-id ethereum-rpc-url]] (fn [db [_ current-account-id ethereum-rpc-url]]
(let [{:keys [public-key status updates-public-key (let [{:keys [public-key status updates-public-key
updates-private-key]} updates-private-key]}
(get-in db [:accounts current-account-id])] (get-in db [:accounts/accounts current-account-id])]
(if public-key (if public-key
(let [rpc-url (or ethereum-rpc-url c/ethereum-rpc-url) (let [rpc-url (or ethereum-rpc-url c/ethereum-rpc-url)
groups (chats/get-active-group-chats) groups (chats/get-active-group-chats)
@ -393,3 +394,12 @@
(when android-error? (status/init-jail)) (when android-error? (status/init-jail))
(status/restart-rpc) (status/restart-rpc)
(dispatch [:load-commands!])))))) (dispatch [:load-commands!]))))))
(register-handler
:load-processed-messages
(u/side-effect!
(fn [_]
(let [now (time/now-ms)
messages (processed-messages/get-filtered (str "ttl > " now))]
(cache/init! messages)
(processed-messages/delete (str "ttl <=" now))))))

View File

@ -194,7 +194,7 @@
(register-handler :transaction-failed (register-handler :transaction-failed
(u/side-effect! (u/side-effect!
(fn [{:keys [current-account-id accounts]} [_ {:keys [id args message_id error_code error_message] :as event}]] (fn [{:accounts/keys [accounts current-account-id]} [_ {:keys [id args message_id error_code error_message] :as event}]]
(let [current-account-address (:address (get accounts current-account-id)) (let [current-account-address (:address (get accounts current-account-id))
transaction-initiator-address (normalize-hex (:from args))] transaction-initiator-address (normalize-hex (:from args))]
(cond (cond

View File

@ -1,15 +1,40 @@
(ns status-im.ui.screens.accounts.db (ns status-im.ui.screens.accounts.db
(:require [cljs.spec.alpha :as s])) (:require-macros [status-im.utils.db :refer [allowed-keys]])
(:require [cljs.spec.alpha :as spec]
status-im.utils.db))
(spec/def :account/address :global/address)
(spec/def :account/name :global/not-empty-string)
(spec/def :account/public-key :global/public-key)
;;not used
(spec/def :account/email nil?)
(spec/def :account/signed-up? (spec/nilable boolean?))
(spec/def :account/last-updated (spec/nilable int?))
(spec/def :account/updates-private-key :global/not-empty-string)
(spec/def :account/updates-public-key :global/not-empty-string)
(spec/def :account/photo-path (spec/nilable string?))
(spec/def :account/debug? (spec/nilable boolean?))
(spec/def :account/status (spec/nilable string?))
(spec/def :account/network (spec/nilable string?))
(spec/def :account/phone (spec/nilable string?))
(spec/def :accounts/account (allowed-keys
:req-un [:account/name :account/address :account/public-key
:account/photo-path]
:opt-un [:account/debug? :account/status :account/last-updated
:account/updates-private-key :account/updates-public-key
:account/email :account/signed-up? :account/network
:account/phone]))
(spec/def :accounts/accounts (spec/nilable (spec/map-of :account/address :accounts/account)))
;;{id (string) account (map)} all created accounts
(s/def :accounts/accounts (s/nilable map?))
;;true during creating new account ;;true during creating new account
(s/def :accounts/account-creation? (s/nilable boolean?)) (spec/def :accounts/account-creation? (spec/nilable boolean?))
;;what is the difference ? ^ ;;true during login just created account
(s/def :accounts/creating-account? (s/nilable boolean?)) (spec/def :accounts/creating-account? (spec/nilable boolean?))
;;id of logged in account ;;id of logged in account
(s/def :accounts/current-account-id (s/nilable string?)) (spec/def :accounts/current-account-id (spec/nilable string?))
;;used during recovering account ;;used during recovering account
(s/def :accounts/recover (s/nilable map?)) (spec/def :accounts/recover (spec/nilable map?))
;;used during logging ;;used during logging
(s/def :accounts/login (s/nilable map?)) (spec/def :accounts/login (spec/nilable map?))

View File

@ -1,82 +1,72 @@
(ns status-im.ui.screens.accounts.events (ns status-im.ui.screens.accounts.events
(:require [status-im.data-store.accounts :as accounts-store] (:require
[status-im.data-store.processed-messages :as processed-messages] status-im.ui.screens.accounts.login.events
[re-frame.core :refer [reg-event-db after dispatch dispatch-sync debug]] status-im.ui.screens.accounts.recover.events
[taoensso.timbre :as log]
[status-im.protocol.core :as protocol]
[status-im.components.status :as status]
[status-im.utils.types :refer [json->clj]]
[status-im.utils.identicon :refer [identicon]]
[status-im.utils.random :as random]
[status-im.i18n :refer [label]]
[status-im.constants :refer [content-type-command-request console-chat-id]]
status-im.ui.screens.accounts.login.events
status-im.ui.screens.accounts.recover.events
[clojure.string :as str]
[status-im.utils.datetime :as time]
[status-im.utils.handlers :as u :refer [get-hashtags]]
[status-im.ui.screens.accounts.statuses :as statuses]
[status-im.utils.gfycat.core :refer [generate-gfy]]
[status-im.utils.scheduler :as s]
[status-im.protocol.message-cache :as cache]
[status-im.ui.screens.navigation :as nav]))
(defn save-account [status-im.data-store.accounts :as accounts-store]
[{:keys [network]} [_ account]] [re-frame.core :refer [reg-cofx reg-fx dispatch inject-cofx]]
(accounts-store/save (assoc account :network network) true)) [taoensso.timbre :as log]
[status-im.protocol.core :as protocol]
[status-im.components.status :as status]
[status-im.utils.types :refer [json->clj]]
[status-im.utils.identicon :refer [identicon]]
[status-im.utils.random :as random]
[clojure.string :as str]
[status-im.utils.datetime :as time]
[status-im.utils.handlers :refer [register-handler-db register-handler-fx get-hashtags] :as handlers]
[status-im.ui.screens.accounts.statuses :as statuses]
[status-im.utils.gfycat.core :refer [generate-gfy]]))
(defn update-account ;;;; COFX
[{:keys [network] :as db} [_ {:keys [address] :as account}]]
(let [account' (assoc account :network network)]
(update db :accounts assoc address account')))
(reg-event-db (reg-cofx
:add-account :get-new-keypair!
(u/handlers-> (fn [coeffects _]
update-account (assoc coeffects :keypair (protocol/new-keypair!))))
save-account))
(reg-cofx
::get-all-accounts
(fn [coeffects _]
(assoc coeffects :all-accounts (accounts-store/get-all))))
;;;; FX
(reg-fx
::save-account
(fn [account]
(accounts-store/save account true)))
(defn account-created [result password] (defn account-created [result password]
(let [data (json->clj result) (let [data (json->clj result)
public-key (:pubkey data) public-key (:pubkey data)
address (:address data) address (:address data)
mnemonic (:mnemonic data) mnemonic (:mnemonic data)
{:keys [public private]} (protocol/new-keypair!) {:keys [public private]} (protocol/new-keypair!)
account {:public-key public-key account {:public-key public-key
:address address :address address
:name (generate-gfy public-key) :name (generate-gfy public-key)
:status (rand-nth statuses/data) :status (rand-nth statuses/data)
:signed-up? true :signed-up? true
:updates-public-key public :updates-public-key public
:updates-private-key private :updates-private-key private
:photo-path (identicon public-key)}] :photo-path (identicon public-key)}]
(log/debug "account-created") (log/debug "account-created")
(when-not (str/blank? public-key) (when-not (str/blank? public-key)
(dispatch [:show-mnemonic mnemonic]) (dispatch [:show-mnemonic mnemonic])
(dispatch [:add-account account]) (dispatch [:add-account account])
(dispatch [:login-account address password true])))) (dispatch [:login-account address password true]))))
(reg-event-db :create-account (reg-fx
(u/side-effect! ::create-account
(fn [_ [_ password]] (fn [password]
(dispatch [:set :creating-account? true]) (status/create-account
(s/execute-later #(dispatch [:account-generation-message]) 400) password
(status/create-account #(account-created % password))))
password
#(account-created % password)))))
(defn save-account! (reg-fx
[{:keys [current-account-id accounts network]} _] ::broadcast-account-update
(let [{acc-network :network :as account} (fn [{:keys [current-public-key web3 name photo-path status
(get accounts current-account-id) updates-public-key updates-private-key]}]
account' (assoc account :network (or acc-network network))]
(accounts-store/save account' true)))
(defn broadcast-account-update
[{:keys [current-account-id current-public-key web3 accounts]} _]
(let [{:keys [name photo-path status]} (get accounts current-account-id)
{:keys [updates-public-key updates-private-key]} (accounts current-account-id)]
(when web3 (when web3
(protocol/broadcast-profile! (protocol/broadcast-profile!
{:web3 web3 {:web3 web3
@ -88,11 +78,11 @@
:status status :status status
:profile-image photo-path}}}})))) :profile-image photo-path}}}}))))
(defn send-keys-update (reg-fx
[{:keys [current-account-id current-public-key web3 accounts contacts]} _] ::send-keys-update
(let [{:keys [name photo-path status]} (get accounts current-account-id) (fn [{:keys [web3 current-public-key contacts
{:keys [updates-public-key updates-private-key]} (accounts current-account-id)] updates-public-key updates-private-key]}]
(doseq [id (u/identities contacts)] (doseq [id (handlers/identities contacts)]
(protocol/update-keys! (protocol/update-keys!
{:web3 web3 {:web3 web3
:message {:from current-public-key :message {:from current-public-key
@ -100,93 +90,96 @@
:message-id (random/id) :message-id (random/id)
:payload {:keypair {:public updates-public-key :payload {:keypair {:public updates-public-key
:private updates-private-key}}}})))) :private updates-private-key}}}}))))
;;;; Handlers
(reg-event-db (register-handler-fx
:add-account
(fn [{{:keys [network] :as db} :db} [_ {:keys [address] :as account}]]
(let [account' (assoc account :network network)]
{:db (assoc-in db [:accounts/accounts address] account')
::save-account account'})))
(register-handler-fx
:create-account
(fn [{db :db} [_ password]]
{:db (assoc db :accounts/creating-account? true)
::create-account password
:dispatch-later [{:ms 400 :dispatch [:account-generation-message]}]}))
(register-handler-fx
:create-new-account-handler
(fn [_ _]
{:dispatch-n [[:initialize-db]
[:load-accounts]
[:check-console-chat true]]}))
(register-handler-fx
:load-accounts
[(inject-cofx ::get-all-accounts)]
(fn [{:keys [db all-accounts]} _]
(let [accounts (->> all-accounts
(map (fn [{:keys [address] :as account}]
[address account]))
(into {}))]
{:db (assoc db :accounts/accounts accounts)})))
(register-handler-fx
:check-status-change :check-status-change
(u/side-effect! (fn [{:accounts/keys [accounts current-account-id]} [_ status]]
(fn [{:keys [current-account-id accounts]} [_ status]] (let [{old-status :status} (get accounts current-account-id)
(let [{old-status :status} (get accounts current-account-id) status-updated? (and (not= status nil)
status-updated? (and (not= status nil) (not= status old-status))]
(not= status old-status))] (when status-updated?
(when status-updated? (let [hashtags (get-hashtags status)]
(let [hashtags (get-hashtags status)] (when (seq hashtags)
(when (seq hashtags) {:dispatch [:broadcast-status status hashtags]}))))))
(dispatch [:broadcast-status status hashtags]))))))))
(defn account-update (defn update-account [current-account new-fields]
[{:keys [current-account-id accounts] :as db} data] (merge current-account (assoc new-fields :last-updated (time/now-ms))))
(let [data (assoc data :last-updated (time/now-ms))
account (merge (get accounts current-account-id) data)]
(assoc-in db [:accounts current-account-id] account)))
(defn account-update-keys (register-handler-fx
[db _]
(let [{:keys [public private]} (protocol/new-keypair!)]
(account-update db {:updates-public-key public
:updates-private-key private})))
(reg-event-db
:account-update :account-update
(u/handlers-> (fn [{{:keys [network]
(fn [db [_ data]] :accounts/keys [accounts current-account-id] :as db} :db} [_ new-account-fields]]
(account-update db data)) (let [current-account (get accounts current-account-id)
save-account! new-account-fields' (assoc new-account-fields :network (or (:network current-account) network))
broadcast-account-update)) new-account (update-account current-account new-account-fields')]
{:db (assoc-in db [:accounts/accounts current-account-id] new-account)
::save-account new-account
::broadcast-account-update (merge
(select-keys db [:current-public-key :web3])
(select-keys new-account [:name :photo-path :status
:updates-public-key :updates-private-key]))})))
(reg-event-db (register-handler-fx
:account-update-keys :account-update-keys
(u/handlers-> [(inject-cofx :get-new-keypair!)]
save-account! (fn [{:keys [db keypair]} _]
send-keys-update (let [{:accounts/keys [accounts current-account-id]} db
account-update-keys)) {:keys [public private]} keypair
current-account (get accounts current-account-id)
new-account (update-account current-account {:updates-public-key public
:updates-private-key private})]
{:db (assoc-in db [:accounts/accounts current-account-id] new-account)
::save-account new-account
::send-keys-update (merge
(select-keys db [:web3 :current-public-key :contacts])
(select-keys new-account [:updates-public-key
:updates-private-key]))})))
(reg-event-db (register-handler-fx
:send-account-update-if-needed :send-account-update-if-needed
(u/side-effect! (fn [{{:accounts/keys [accounts current-account-id]} :db} _]
(fn [{:keys [current-account-id accounts]} _] (let [{:keys [last-updated]} (get accounts current-account-id)
(let [{:keys [last-updated]} (get accounts current-account-id) now (time/now-ms)
now (time/now-ms) needs-update? (> (- now last-updated) time/week)]
needs-update? (> (- now last-updated) time/week)] (log/info "Need to send account-update: " needs-update?)
(log/info "Need to send account-update: " needs-update?) (when needs-update?
(when needs-update? (dispatch [:account-update])))))
(dispatch [:account-update]))))))
(defn set-current-account (register-handler-db
[{:keys [accounts] :as db} [_ address]] :set-current-account
(let [key (:public-key (accounts address))] (fn [{:accounts/keys [accounts] :as db} [_ address]]
(assoc db :current-account-id address (let [key (:public-key (accounts address))]
:current-public-key key))) (assoc db :accounts/current-account-id address
:current-public-key key))))
(reg-event-db :set-current-account set-current-account)
(defn load-accounts! [db _]
(let [accounts (->> (accounts-store/get-all)
(map (fn [{:keys [address] :as account}]
[address account]))
(into {}))]
(assoc db :accounts accounts)))
(reg-event-db :load-accounts load-accounts!)
(defn console-create-account [db _]
(let [message-id (random/id)]
(dispatch [:received-message
{:message-id message-id
:content {:command (name :keypair)
:content (label :t/keypair-generated)}
:content-type content-type-command-request
:outgoing false
:from console-chat-id
:to "me"}])
db))
(reg-event-db :console-create-account console-create-account)
(reg-event-db
:load-processed-messages
(u/side-effect!
(fn [_]
(let [now (time/now-ms)
messages (processed-messages/get-filtered (str "ttl > " now))]
(cache/init! messages)
(processed-messages/delete (str "ttl <=" now))))))

View File

@ -1,76 +1,82 @@
(ns status-im.ui.screens.accounts.login.events (ns status-im.ui.screens.accounts.login.events
(:require [re-frame.core :refer [after dispatch]] (:require
[status-im.utils.handlers :refer [register-handler] :as u] status-im.ui.screens.accounts.login.navigation
[taoensso.timbre :as log]
[status-im.utils.types :refer [json->clj]]
[status-im.data-store.core :as data-store]
[status-im.components.status :as status]
[status-im.constants :refer [console-chat-id]]
[status-im.ui.screens.navigation :as nav]))
(defmethod nav/preload-data! :login [re-frame.core :refer [dispatch reg-fx]]
[db] [status-im.utils.handlers :refer [register-handler-db register-handler-fx]]
(update db :login dissoc :error :password :processing)) [taoensso.timbre :as log]
[status-im.utils.types :refer [json->clj]]
[status-im.data-store.core :as data-store]
[status-im.components.status :as status]
[status-im.constants :refer [console-chat-id]]))
(defn set-login-from-qr ;;;; FX
[{:keys [login] :as db} [_ _ login-info]]
(assoc db :login (merge login login-info)))
(register-handler :set-login-from-qr set-login-from-qr) (reg-fx
::login
(fn [[address password]]
(status/login address password #(dispatch [:login-handler % address]))))
(register-handler :open-login (reg-fx
(after #(dispatch [:navigate-to :login])) ::clear-web-data
(fn [db [_ address photo-path name]] (fn []
(update db :login assoc :address address :photo-path photo-path :name name))) (status/clear-web-data)))
(defn initialize-account (reg-fx
[address new-account?] ::change-account
(dispatch [:set :login {}]) (fn [[address new-account?]]
(dispatch [:debug-server-stop]) (data-store/change-account address new-account?
(dispatch [:set-current-account address]) #(dispatch [:change-account-handler % address new-account?]))))
(dispatch [:initialize-account address])
(if new-account?
(do
(dispatch [:navigate-to-clean :chat-list])
(dispatch [:navigate-to :chat console-chat-id]))
(do
(dispatch [:navigate-to-clean :chat-list])
(dispatch [:navigate-to :chat-list]))))
(register-handler :change-account ;;;; Handlers
(u/side-effect!
(fn [_ [_ address new-account? callback]]
(status/clear-web-data)
(data-store/change-account address new-account?
#(callback % address new-account?)))))
(defn on-account-changed (register-handler-fx
[error address new-account?] :open-login
(if (nil? error) (fn [{db :db} [_ address photo-path name]]
(initialize-account address new-account?) {:db (update db
(log/debug "Error changing acount: " error))) :accounts/login assoc
:address address
:photo-path photo-path
:name name)
:dispatch [:navigate-to :login]}))
(defn logged-in (register-handler-fx
[db address] :login-account
(let [is-login-screen? (= (:view-id db) :login) (fn [{db :db} [_ address password account-creation?]]
new-account? (not is-login-screen?)] {:db (-> db
(log/debug "Logged in: " (:view-id db) is-login-screen? new-account?) (assoc :accounts/account-creation? account-creation?)
(dispatch [:change-account address new-account? on-account-changed]))) (assoc-in [:accounts/login :processing] true))
::login [address password]}))
(register-handler :login-account (register-handler-fx
(after :login-handler
(fn [db [_ address password]] (fn [{db :db} [_ result address]]
(status/login address password (let [data (json->clj result)
(fn [result] error (:error data)
(let [data (json->clj result) success (zero? (count error))
error (:error data) db' (assoc-in db [:accounts/login :processing] false)]
success (zero? (count error))] (log/debug "Logged in account: ")
(log/debug "Logged in account: ") (merge
(dispatch [:set-in [:login :processing] false]) {:db (if success db' (assoc-in db' [:accounts/login :error] error))}
(if success (when success
(logged-in db address) (let [is-login-screen? (= (:view-id db) :login)
(dispatch [:set-in [:login :error] error]))))))) new-account? (not is-login-screen?)]
(fn [db [_ _ _ account-creation?]] (log/debug "Logged in: " (:view-id db) is-login-screen? new-account?)
(-> db {::clear-web-data nil
(assoc :account-creation? account-creation?) ::change-account [address new-account?]}))))))
(assoc-in [:login :processing] true))))
(register-handler-fx
:change-account-handler
(fn [{db :db} [_ error address new-account?]]
(if (nil? error)
{:db (assoc db :accounts/login {})
:dispatch-n (concat
[[:debug-server-stop]
[:set-current-account address]
[:initialize-account address]]
(if new-account?
[[:navigate-to-clean :chat-list]
[:navigate-to :chat console-chat-id]]
[[:navigate-to-clean :chat-list]
[:navigate-to :chat-list]]))}
(log/debug "Error changing acount: " error))))

View File

@ -0,0 +1,6 @@
(ns status-im.ui.screens.accounts.login.navigation
(:require [status-im.ui.screens.navigation :as nav]))
(defmethod nav/preload-data! :login
[db]
(update db :accounts/login dissoc :error :password :processing))

View File

@ -29,7 +29,7 @@
(dispatch [:login-account address password])) (dispatch [:login-account address password]))
(defview login [] (defview login []
(letsubs [{:keys [address photo-path name password error processing]} [:get :login]] (letsubs [{:keys [address photo-path name password error processing]} [:get :accounts/login]]
[view ast/accounts-container [view ast/accounts-container
[status-bar {:type :transparent}] [status-bar {:type :transparent}]
[login-toolbar] [login-toolbar]
@ -42,8 +42,8 @@
:auto-capitalize :none :auto-capitalize :none
:hide-underline? true :hide-underline? true
:on-change-text #(do :on-change-text #(do
(dispatch [:set-in [:login :password] %]) (dispatch [:set-in [:accounts/login :password] %])
(dispatch [:set-in [:login :error] ""])) (dispatch [:set-in [:accounts/login :error] ""]))
:on-submit-editing #(login-account password-text-input address password) :on-submit-editing #(login-account password-text-input address password)
:auto-focus true :auto-focus true
:secure-text-entry true :secure-text-entry true

View File

@ -1,6 +1,6 @@
(ns status-im.ui.screens.accounts.recover.db (ns status-im.ui.screens.accounts.recover.db
(:require [cljs.spec.alpha :as s])) (:require [cljs.spec.alpha :as s]
status-im.utils.db))
(s/def ::not-empty-string (s/and string? not-empty)) (s/def ::passphrase :global/not-empty-string)
(s/def ::passphrase ::not-empty-string) (s/def ::password :global/not-empty-string)
(s/def ::password ::not-empty-string)

View File

@ -1,43 +1,48 @@
(ns status-im.ui.screens.accounts.recover.events (ns status-im.ui.screens.accounts.recover.events
(:require [re-frame.core :refer [reg-event-db after dispatch dispatch-sync]] (:require
[status-im.components.status :as status] status-im.ui.screens.accounts.recover.navigation
[status-im.utils.types :refer [json->clj]]
[status-im.utils.identicon :refer [identicon]]
[taoensso.timbre :as log]
[clojure.string :as str]
[status-im.utils.handlers :as u]
[status-im.utils.gfycat.core :refer [generate-gfy]]
[status-im.protocol.core :as protocol]
[status-im.ui.screens.navigation :as nav]))
(defn account-recovered [result] [re-frame.core :refer [reg-fx inject-cofx dispatch]]
(let [data (json->clj result) [status-im.components.status :as status]
public-key (:pubkey data) [status-im.utils.types :refer [json->clj]]
address (:address data) [status-im.utils.identicon :refer [identicon]]
{:keys [public private]} (protocol/new-keypair!) [taoensso.timbre :as log]
account {:public-key public-key [clojure.string :as str]
:address address [status-im.utils.handlers :refer [register-handler-fx]]
:name (generate-gfy public-key) [status-im.utils.gfycat.core :refer [generate-gfy]]))
:photo-path (identicon public-key)
:updates-public-key public
:updates-private-key private
:signed-up? true}]
(log/debug "account-recovered")
(when-not (str/blank? public-key)
(dispatch [:set-in [:recover :passphrase] ""])
(dispatch [:set-in [:recover :password] ""])
(dispatch [:add-account account])
(dispatch [:navigate-back]))))
(defn recover-account ;;;; FX
[_ [_ passphrase password]]
(status/recover-account
passphrase
password
account-recovered))
(reg-event-db :recover-account (u/side-effect! recover-account)) (reg-fx
::recover-account-fx
(fn [[passphrase password]]
(status/recover-account passphrase password #(dispatch [:account-recovered %]))))
;;;; Handlers
(register-handler-fx
:account-recovered
[(inject-cofx :get-new-keypair!)]
(fn [{:keys [db keypair]} [_ result]]
(let [data (json->clj result)
public-key (:pubkey data)
address (:address data)
{:keys [public private]} keypair
account {:public-key public-key
:address address
:name (generate-gfy public-key)
:photo-path (identicon public-key)
:updates-public-key public
:updates-private-key private
:signed-up? true}]
(log/debug "account-recovered")
(when-not (str/blank? public-key)
{:db (update db :accounts/recover assoc :passphrase "" :password "")
:dispatch-n [[:add-account account]
[:navigate-back]]}))))
(register-handler-fx
:recover-account
(fn [_ [_ passphrase password]]
{::recover-account-fx [passphrase password]}))
(defmethod nav/preload-data! :recover
[db]
(update db :recover dissoc :password :passphrase))

View File

@ -0,0 +1,6 @@
(ns status-im.ui.screens.accounts.recover.navigation
(:require [status-im.ui.screens.navigation :as nav]))
(defmethod nav/preload-data! :recover
[db]
(update db :accounts/recover dissoc :password :passphrase))

View File

@ -18,7 +18,7 @@
[clojure.string :as str])) [clojure.string :as str]))
(defview passphrase-input [passphrase] (defview passphrase-input [passphrase]
(letsubs [error [:get-in [:recover :passphrase-error]]] (letsubs [error [:get-in [:accounts/recover :passphrase-error]]]
[view {:margin-top 10} [view {:margin-top 10}
[text-input-with-label {:label (i18n/label :t/passphrase) [text-input-with-label {:label (i18n/label :t/passphrase)
:description (i18n/label :t/twelve-words-in-correct-order) :description (i18n/label :t/twelve-words-in-correct-order)
@ -27,21 +27,21 @@
:max-height st/passphrase-input-max-height :max-height st/passphrase-input-max-height
:default-value passphrase :default-value passphrase
:auto-capitalize :none :auto-capitalize :none
:on-change-text #(dispatch [:set-in [:recover :passphrase] %]) :on-change-text #(dispatch [:set-in [:accounts/recover :passphrase] %])
:error error}]])) :error error}]]))
(defview password-input [password] (defview password-input [password]
(letsubs [error [:get-in [:recover :password-error]]] (letsubs [error [:get-in [:accounts/recover :password-error]]]
[view {:margin-top 10} [view {:margin-top 10}
[text-input-with-label {:label (i18n/label :t/password) [text-input-with-label {:label (i18n/label :t/password)
:default-value password :default-value password
:auto-capitalize :none :auto-capitalize :none
:on-change-text #(dispatch [:set-in [:recover :password] %]) :on-change-text #(dispatch [:set-in [:accounts/recover :password] %])
:secure-text-entry true :secure-text-entry true
:error error}]])) :error error}]]))
(defview recover [] (defview recover []
(letsubs [{:keys [passphrase password]} [:get :recover]] (letsubs [{:keys [passphrase password]} [:get :accounts/recover]]
(let [valid-form? (and (let [valid-form? (and
(spec/valid? ::v/passphrase passphrase) (spec/valid? ::v/passphrase passphrase)
(spec/valid? ::v/password password))] (spec/valid? ::v/password password))]

View File

@ -0,0 +1,7 @@
(ns status-im.ui.screens.accounts.subs
(:require [re-frame.core :refer [reg-sub subscribe]]))
(reg-sub
:get-accounts
(fn [db _]
(get db :accounts/accounts)))

View File

@ -33,13 +33,8 @@
[view st/account-view [view st/account-view
[account-bage address photo-path name]]]]) [account-bage address photo-path name]]]])
(defn create-account [_]
(dispatch [:initialize-db])
(dispatch [:load-accounts])
(dispatch [:check-console-chat true]))
(defview accounts [] (defview accounts []
[accounts [:get :accounts]] [accounts [:get-accounts]]
[view st/accounts-container [view st/accounts-container
[status-bar {:type :transparent}] [status-bar {:type :transparent}]
[view st/account-title-conatiner [view st/account-title-conatiner
@ -53,7 +48,7 @@
[view st/bottom-actions-container [view st/bottom-actions-container
[action-button (i18n/label :t/create-new-account) [action-button (i18n/label :t/create-new-account)
:add_white :add_white
create-account #(dispatch [:create-new-account-handler])
st/accounts-action-button] st/accounts-action-button]
[common/separator st/accounts-separator st/accounts-separator-wrapper] [common/separator st/accounts-separator st/accounts-separator-wrapper]
[action-button (i18n/label :t/recover-access) [action-button (i18n/label :t/recover-access)

View File

@ -1,45 +1,23 @@
(ns status-im.ui.screens.contacts.db (ns status-im.ui.screens.contacts.db
(:require-macros [status-im.utils.db :refer [allowed-keys]]) (:require-macros [status-im.utils.db :refer [allowed-keys]])
(:require [cljs.spec.alpha :as spec] (:require [cljs.spec.alpha :as spec]
status-im.utils.db
[clojure.string :as string] [clojure.string :as string]
[status-im.data-store.contacts :as contacts] [status-im.data-store.contacts :as contacts]))
[status-im.js-dependencies :as dependencies]))
(defn contact-can-be-added? [identity] (defn contact-can-be-added? [identity]
(if (contacts/exists? identity) (if (contacts/exists? identity)
(:pending? (contacts/get-by-id identity)) (:pending? (contacts/get-by-id identity))
true)) true))
(defn is-address? [s]
(.isAddress dependencies/Web3.prototype s))
(defn hex-string? [s]
(let [s' (if (string/starts-with? s "0x")
(subs s 2)
s)]
(boolean (re-matches #"(?i)[0-9a-f]+" s'))))
(defn valid-length? [identity]
(let [length (count identity)]
(and
(hex-string? identity)
(or
(and (= 128 length) (not (string/includes? identity "0x")))
(and (= 130 length) (string/starts-with? identity "0x"))
(and (= 132 length) (string/starts-with? identity "0x04"))
(is-address? identity)))))
(spec/def ::not-empty-string (spec/and string? not-empty))
(spec/def ::public-key (spec/and ::not-empty-string valid-length?))
;;;; DB ;;;; DB
;;Contact ;;Contact
;we can't validate public key, because for dapps whisper-identity is just string ;we can't validate public key, because for dapps whisper-identity is just string
(spec/def :contact/whisper-identity ::not-empty-string) (spec/def :contact/whisper-identity :global/not-empty-string)
(spec/def :contact/name ::not-empty-string) (spec/def :contact/name :global/not-empty-string)
(spec/def :contact/address (spec/nilable is-address?)) (spec/def :contact/address (spec/nilable :global/address))
(spec/def :contact/private-key (spec/nilable string?)) (spec/def :contact/private-key (spec/nilable string?))
(spec/def :contact/public-key (spec/nilable string?)) (spec/def :contact/public-key (spec/nilable string?))
(spec/def :contact/photo-path (spec/nilable string?)) (spec/def :contact/photo-path (spec/nilable string?))
@ -77,12 +55,12 @@
(spec/def :contacts-ui/edit? boolean?) (spec/def :contacts-ui/edit? boolean?)
(spec/def :contacts/contacts (spec/nilable (spec/map-of ::not-empty-string :contact/contact))) (spec/def :contacts/contacts (spec/nilable (spec/map-of :global/not-empty-string :contact/contact)))
;public key of new contact during adding this new contact ;public key of new contact during adding this new contact
(spec/def :contacts/new-identity (spec/nilable string?)) (spec/def :contacts/new-identity (spec/nilable string?))
(spec/def :contacts/new-public-key-error (spec/nilable string?)) (spec/def :contacts/new-public-key-error (spec/nilable string?))
;on showing this contact's profile (andrey: better to move into profile ns) ;on showing this contact's profile (andrey: better to move into profile ns)
(spec/def :contacts/identity (spec/nilable ::not-empty-string)) (spec/def :contacts/identity (spec/nilable :global/not-empty-string))
(spec/def :contacts/list-ui-props (spec/nilable (allowed-keys :opt-un [:contact-list-ui/edit?]))) (spec/def :contacts/list-ui-props (spec/nilable (allowed-keys :opt-un [:contact-list-ui/edit?])))
(spec/def :contacts/ui-props (spec/nilable (allowed-keys :opt-un [:contacts-ui/edit?]))) (spec/def :contacts/ui-props (spec/nilable (allowed-keys :opt-un [:contacts-ui/edit?])))
;used in modal list (for example for wallet) ;used in modal list (for example for wallet)

View File

@ -16,8 +16,8 @@
[status-im.utils.identicon :refer [identicon]] [status-im.utils.identicon :refer [identicon]]
[status-im.utils.gfycat.core :refer [generate-gfy]] [status-im.utils.gfycat.core :refer [generate-gfy]]
[status-im.i18n :refer [label]] [status-im.i18n :refer [label]]
[status-im.ui.screens.contacts.db :as v] [status-im.ui.screens.contacts.navigation]
[status-im.ui.screens.contacts.navigation])) [cljs.spec.alpha :as spec]))
;;;; COFX ;;;; COFX
@ -310,10 +310,11 @@
(register-handler-fx (register-handler-fx
::send-contact-request ::send-contact-request
(fn [{{:keys [accounts current-account-id] :as db} :db} [_ contact]] (fn [{{:accounts/keys [accounts current-account-id] :as db} :db} [_ contact]]
(let [current-account (get accounts current-account-id)] (let [current-account (get accounts current-account-id)]
{::send-contact-request-fx (merge {::send-contact-request-fx (merge
(select-keys db [:current-public-key :web3 :current-account-id :accounts]) (select-keys db [:current-public-key :web3])
{:current-account-id current-account-id}
(select-keys contact [:whisper-identity]) (select-keys contact [:whisper-identity])
(select-keys current-account [:name :photo-path :status (select-keys current-account [:name :photo-path :status
:updates-public-key :updates-private-key]))}))) :updates-public-key :updates-private-key]))})))
@ -437,7 +438,7 @@
(register-handler-fx (register-handler-fx
:add-contact-handler :add-contact-handler
(fn [{:keys [db]} [_ id]] (fn [{:keys [db]} [_ id]]
(if (v/is-address? id) (if (spec/valid? :global/address id)
{::request-contacts-by-address id} {::request-contacts-by-address id}
{:dispatch (if (get-in db [:contacts/contacts id]) {:dispatch (if (get-in db [:contacts/contacts id])
[:add-pending-contact id] [:add-pending-contact id]

View File

@ -31,7 +31,7 @@
(normalize-hex whisper-identity)) (normalize-hex whisper-identity))
(label :t/can-not-add-yourself) (label :t/can-not-add-yourself)
(not (s/valid? ::v/public-key whisper-identity)) (not (s/valid? :global/public-key whisper-identity))
(label :t/enter-valid-public-key) (label :t/enter-valid-public-key)
(not (v/contact-can-be-added? whisper-identity)) (not (v/contact-can-be-added? whisper-identity))

View File

@ -17,7 +17,7 @@
(def app-db {:current-public-key "" (def app-db {:current-public-key ""
:status-module-initialized? (or platform/ios? js/goog.DEBUG) :status-module-initialized? (or platform/ios? js/goog.DEBUG)
:keyboard-height 0 :keyboard-height 0
:accounts {} :accounts/accounts {}
:navigation-stack '() :navigation-stack '()
:contacts/contacts {} :contacts/contacts {}
:qr-codes {} :qr-codes {}
@ -36,7 +36,7 @@
:discover-search-tags '() :discover-search-tags '()
:tags [] :tags []
:sync-state :done :sync-state :done
:network :testnet}) :network "testnet"})
;;;;GLOBAL ;;;;GLOBAL
@ -79,8 +79,7 @@
;;;;NETWORK ;;;;NETWORK
;;network name :testnet (spec/def ::network (spec/nilable string?))
(spec/def ::network (spec/nilable keyword?))
(spec/def ::db (allowed-keys (spec/def ::db (allowed-keys
:opt :opt
@ -98,6 +97,12 @@
:group/group-type :group/group-type
:group/selected-contacts :group/selected-contacts
:group/groups-order :group/groups-order
:accounts/accounts
:accounts/account-creation?
:accounts/creating-account?
:accounts/current-account-id
:accounts/recover
:accounts/login
:my-profile/edit] :my-profile/edit]
:opt-un :opt-un
[::current-public-key [::current-public-key
@ -117,12 +122,6 @@
::sync-state ::sync-state
::sync-data ::sync-data
::network ::network
:accounts/accounts
:accounts/account-creation?
:accounts/creating-account?
:accounts/current-account-id
:accounts/recover
:accounts/login
:navigation/view-id :navigation/view-id
:navigation/navigation-stack :navigation/navigation-stack
:navigation/prev-tab-view-id :navigation/prev-tab-view-id

View File

@ -29,7 +29,8 @@
(register-handler :broadcast-status (register-handler :broadcast-status
(u/side-effect! (u/side-effect!
(fn [{:keys [current-public-key web3 current-account-id accounts] (fn [{:keys [current-public-key web3]
:accounts/keys [accounts current-account-id]
:contacts/keys [contacts]} :contacts/keys [contacts]}
[_ status hashtags]] [_ status hashtags]]
(let [{:keys [name photo-path]} (get accounts current-account-id) (let [{:keys [name photo-path]} (get accounts current-account-id)

View File

@ -131,12 +131,12 @@
network-status network _]} :db} _] network-status network _]} :db} _]
{::init-store nil {::init-store nil
:db (assoc app-db :db (assoc app-db
:current-account-id nil :accounts/current-account-id nil
:contacts/contacts {} :contacts/contacts {}
:network-status network-status :network-status network-status
:status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?) :status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?)
:status-node-started? status-node-started? :status-node-started? status-node-started?
:network (or network :testnet))})) :network (or network "testnet"))}))
(register-handler-db (register-handler-db
:initialize-account-db :initialize-account-db
@ -163,11 +163,11 @@
[:send-account-update-if-needed] [:send-account-update-if-needed]
[:start-requesting-discoveries] [:start-requesting-discoveries]
[:remove-old-discoveries!] [:remove-old-discoveries!]
[:set :creating-account? false]]})) [:set :accounts/creating-account? false]]}))
(register-handler-fx (register-handler-fx
:check-console-chat :check-console-chat
(fn [{{:keys [accounts] :as db} :db} [_ open-console?]] (fn [{{:accounts/keys [accounts] :as db} :db} [_ open-console?]]
(let [view (if (empty? accounts) (let [view (if (empty? accounts)
:chat :chat
:accounts)] :accounts)]

View File

@ -1,22 +1,21 @@
(ns status-im.ui.screens.group.db (ns status-im.ui.screens.group.db
(:require-macros [status-im.utils.db :refer [allowed-keys]]) (:require-macros [status-im.utils.db :refer [allowed-keys]])
(:require [cljs.spec.alpha :as spec] (:require [cljs.spec.alpha :as spec]
status-im.utils.db
[status-im.constants :refer [console-chat-id wallet-chat-id]] [status-im.constants :refer [console-chat-id wallet-chat-id]]
[clojure.string :as string] [clojure.string :as string]
[status-im.utils.homoglyph :as utils])) [status-im.utils.homoglyph :as utils]))
(spec/def ::not-empty-string (spec/and string? not-empty)) (spec/def ::name :global/not-empty-string)
(spec/def ::name ::not-empty-string)
;;;; DB ;;;; DB
(spec/def :group/group-id ::not-empty-string) (spec/def :group/group-id :global/not-empty-string)
(spec/def :group/name ::not-empty-string) (spec/def :group/name :global/not-empty-string)
(spec/def :group/timestamp int?) (spec/def :group/timestamp int?)
(spec/def :group/pending? boolean?) (spec/def :group/pending? boolean?)
(spec/def :group/order int?) (spec/def :group/order int?)
(spec/def :group-contact/identity ::not-empty-string) (spec/def :group-contact/identity :global/not-empty-string)
(spec/def :group/contact (allowed-keys :req-un [:group-contact/identity])) (spec/def :group/contact (allowed-keys :req-un [:group-contact/identity]))
@ -27,7 +26,7 @@
:group/order :group/contacts] :group/order :group/contacts]
:opt-un [:group/pending?])) :opt-un [:group/pending?]))
(spec/def :group/contact-groups (spec/nilable (spec/map-of ::not-empty-string :group/contact-group))) (spec/def :group/contact-groups (spec/nilable (spec/map-of :global/not-empty-string :group/contact-group)))
;;used during editing contact group ;;used during editing contact group
(spec/def :group/contact-group-id (spec/nilable string?)) (spec/def :group/contact-group-id (spec/nilable string?))
(spec/def :group/group-type (spec/nilable #{:chat-group :contact-group})) (spec/def :group/group-type (spec/nilable #{:chat-group :contact-group}))

View File

@ -56,7 +56,7 @@
(replace-view db view-id))) (replace-view db view-id)))
(defn- can-navigate-back? [db] (defn- can-navigate-back? [db]
(and (not (db :creating-account?)))) (not (get db :accounts/creating-account?)))
(register-handler-db (register-handler-db
:navigate-back :navigate-back

View File

@ -39,8 +39,8 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:my-profile/edit :my-profile/edit
(fn [{:keys [db]} [_ edit-type edit-value]] (fn [{:keys [db]} [_ edit-type edit-value]]
(let [current-account-id (:current-account-id db) (let [current-account-id (:accounts/current-account-id db)
current-account (select-keys (get-in db [:accounts current-account-id]) current-account (select-keys (get-in db [:accounts/accounts current-account-id])
[:name :photo-path :status]) [:name :photo-path :status])
new-db (-> db new-db (-> db
(update-in [:my-profile/edit] merge current-account) (update-in [:my-profile/edit] merge current-account)

View File

@ -2,8 +2,8 @@
(:require [status-im.ui.screens.navigation :as navigation])) (:require [status-im.ui.screens.navigation :as navigation]))
(defmethod navigation/preload-data! :qr-code-view (defmethod navigation/preload-data! :qr-code-view
[{:keys [current-account-id] :as db} [_ _ {:keys [contact qr-source amount?]}]] [{:accounts/keys [current-account-id] :as db} [_ _ {:keys [contact qr-source amount?]}]]
(assoc db :qr-modal {:contact (or contact (assoc db :qr-modal {:contact (or contact
(get-in db [:accounts current-account-id])) (get-in db [:accounts/accounts current-account-id]))
:qr-source qr-source :qr-source qr-source
:amount? amount?})) :amount? amount?}))

View File

@ -1,6 +1,7 @@
(ns status-im.ui.screens.subs (ns status-im.ui.screens.subs
(:require [re-frame.core :refer [reg-sub subscribe]] (:require [re-frame.core :refer [reg-sub subscribe]]
status-im.chat.subs status-im.chat.subs
status-im.ui.screens.accounts.subs
status-im.ui.screens.chats-list.subs status-im.ui.screens.chats-list.subs
status-im.ui.screens.group.chat-settings.subs status-im.ui.screens.group.chat-settings.subs
status-im.ui.screens.discover.subs status-im.ui.screens.discover.subs
@ -15,16 +16,16 @@
(reg-sub :get-current-account (reg-sub :get-current-account
(fn [db] (fn [db]
(let [current-account-id (:current-account-id db)] (let [current-account-id (:accounts/current-account-id db)]
(get-in db [:accounts current-account-id])))) (get-in db [:accounts/accounts current-account-id]))))
(reg-sub :get-in (reg-sub :get-in
(fn [db [_ path]] (fn [db [_ path]]
(get-in db path))) (get-in db path)))
(reg-sub :signed-up? (reg-sub :signed-up?
:<- [:get :current-account-id] :<- [:get :accounts/current-account-id]
:<- [:get :accounts] :<- [:get-accounts]
(fn [[account-id accounts]] (fn [[account-id accounts]]
(when (and accounts account-id) (when (and accounts account-id)
(get-in accounts [account-id :signed-up?])))) (get-in accounts [account-id :signed-up?]))))

View File

@ -0,0 +1,27 @@
(ns status-im.utils.db
(:require [clojure.string :as string]
[cljs.spec.alpha :as spec]
[status-im.js-dependencies :as dependencies]))
(defn address? [s]
(.isAddress dependencies/Web3.prototype s))
(defn hex-string? [s]
(let [s' (if (string/starts-with? s "0x")
(subs s 2)
s)]
(boolean (re-matches #"(?i)[0-9a-f]+" s'))))
(defn valid-length? [identity]
(let [length (count identity)]
(and
(hex-string? identity)
(or
(and (= 128 length) (not (string/includes? identity "0x")))
(and (= 130 length) (string/starts-with? identity "0x"))
(and (= 132 length) (string/starts-with? identity "0x04"))
(address? identity)))))
(spec/def :global/not-empty-string (spec/and string? not-empty))
(spec/def :global/public-key (spec/and :global/not-empty-string valid-length?))
(spec/def :global/address address?)

View File

@ -280,11 +280,12 @@
:status "test status"} :status "test status"}
recieved-contact' (merge new-contact recieved-contact' (merge new-contact
(dissoc recieved-contact :profile-image) (dissoc recieved-contact :profile-image)
{:public-key "" :private-key ""})] {:public-key new-contact-public-key
:private-key ""})]
(rf/dispatch [:contact-request-received {:from new-contact-public-key (rf/dispatch [:contact-request-received {:from new-contact-public-key
:payload {:contact recieved-contact :payload {:contact recieved-contact
:keypair {:public "" :keypair {:public new-contact-public-key
:private ""}}}]) :private ""}}}])
(is (= (assoc contacts-browse-wallet new-contact-public-key recieved-contact') (is (= (assoc contacts-browse-wallet new-contact-public-key recieved-contact')