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
(:require [reagent.core :as reagent]
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
status-im.utils.db
status-im.ui.screens.db
status-im.ui.screens.events
status-im.ui.screens.subs
@ -16,7 +17,7 @@
;; this listener and handle application's closing
;; in handlers
(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])
webview (subscribe [:get :webview-bridge])]
(cond

View File

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

View File

@ -202,7 +202,7 @@
(register-handler-fx
:load-chat-parameter-box
[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}]]
(let [parameter-index (input-model/argument-position db current-chat-id)]
(when (and command (> parameter-index -1))
@ -238,7 +238,7 @@
(register-handler-fx
::send-message
[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])
data {:message text
:command command
@ -385,7 +385,7 @@
(register-handler-fx
::check-dapp-suggestions
[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])]
{:chat-fx/call-jail-function {:chat-id chat-id
:function :on-message-input-change

View File

@ -104,7 +104,7 @@
(update-in [:chats current-chat-id :input-text] safe-trim))))
(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]
(if (chats console-chat-id)
db
@ -213,7 +213,7 @@
(compare timestamp2 timesatmp1))
(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?
chats
(->> loaded-chats
@ -228,7 +228,7 @@
(init-console-chat true))))
(defn load-chats!
[{:keys [account-creation?] :as db} _]
[{:accounts/keys [account-creation?] :as db} _]
(if account-creation?
db
(assoc db :loaded-chats (chats/get-all))))
@ -253,7 +253,7 @@
(init-console-chat true)))))
(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)
messages (get-in db [:chats chat-id :messages])
db' (-> db

View File

@ -43,7 +43,7 @@
(register-handler :open-faucet
(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)]
(let [current-address (get-in accounts [current-account-id :address])]
(open-faucet faucet-name current-address faucet))))))

View File

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

View File

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

View File

@ -7,12 +7,12 @@
[taoensso.timbre :as log]
[status-im.models.commands :as commands]
[status-im.commands.utils :as cu]
[status-im.ui.screens.contacts.db :as v]
[status-im.components.status :as s]
[status-im.components.nfc :as nfc]
[status-im.constants :as c]
[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]
(when-let [{:keys [address]} (contacts public-key)]
@ -29,7 +29,7 @@
(catch :default e data))
data'' (cond
(map? data') data'
(v/is-address? data') {:address data'}
(spec/valid? :global/address data') {:address data'}
(string? data') (by-public-key data' contacts)
:else nil)]
(when data''
@ -127,7 +127,7 @@
(register-handler :webview-send-eth!
(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}
path [:functions :send]
parameters {:context context

View File

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

View File

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

View File

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

View File

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

View File

@ -126,7 +126,7 @@
(register-handler :debug-switch-node
(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])
(respond {:type :ok
:text "You've successfully switched the node."}))))

View File

@ -6,8 +6,8 @@
(defn sign-up
[db phone-number message-id handler]
(let [current-account-id (get db :current-account-id)
{:keys [public-key address]} (get-in db [:accounts current-account-id])]
(let [current-account-id (get 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)
(http-post "sign-up" {:phone-number phone-number
:whisper-identity public-key

View File

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

View File

@ -19,13 +19,14 @@
[status-im.components.status :as status]
[clojure.string :refer [join]]
[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
(fn [db [_ current-account-id ethereum-rpc-url]]
(let [{:keys [public-key status updates-public-key
updates-private-key]}
(get-in db [:accounts current-account-id])]
(get-in db [:accounts/accounts current-account-id])]
(if public-key
(let [rpc-url (or ethereum-rpc-url c/ethereum-rpc-url)
groups (chats/get-active-group-chats)
@ -393,3 +394,12 @@
(when android-error? (status/init-jail))
(status/restart-rpc)
(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
(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))
transaction-initiator-address (normalize-hex (:from args))]
(cond

View File

@ -1,15 +1,40 @@
(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
(s/def :accounts/account-creation? (s/nilable boolean?))
;;what is the difference ? ^
(s/def :accounts/creating-account? (s/nilable boolean?))
(spec/def :accounts/account-creation? (spec/nilable boolean?))
;;true during login just created account
(spec/def :accounts/creating-account? (spec/nilable boolean?))
;;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
(s/def :accounts/recover (s/nilable map?))
(spec/def :accounts/recover (spec/nilable map?))
;;used during logging
(s/def :accounts/login (s/nilable map?))
(spec/def :accounts/login (spec/nilable map?))

View File

@ -1,40 +1,40 @@
(ns status-im.ui.screens.accounts.events
(:require [status-im.data-store.accounts :as accounts-store]
[status-im.data-store.processed-messages :as processed-messages]
[re-frame.core :refer [reg-event-db after dispatch dispatch-sync debug]]
(:require
status-im.ui.screens.accounts.login.events
status-im.ui.screens.accounts.recover.events
[status-im.data-store.accounts :as accounts-store]
[re-frame.core :refer [reg-cofx reg-fx dispatch inject-cofx]]
[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.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]]
[status-im.utils.scheduler :as s]
[status-im.protocol.message-cache :as cache]
[status-im.ui.screens.navigation :as nav]))
[status-im.utils.gfycat.core :refer [generate-gfy]]))
(defn save-account
[{:keys [network]} [_ account]]
(accounts-store/save (assoc account :network network) true))
;;;; COFX
(defn update-account
[{:keys [network] :as db} [_ {:keys [address] :as account}]]
(let [account' (assoc account :network network)]
(update db :accounts assoc address account')))
(reg-cofx
:get-new-keypair!
(fn [coeffects _]
(assoc coeffects :keypair (protocol/new-keypair!))))
(reg-event-db
:add-account
(u/handlers->
update-account
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]
(let [data (json->clj result)
@ -56,27 +56,17 @@
(dispatch [:add-account account])
(dispatch [:login-account address password true]))))
(reg-event-db :create-account
(u/side-effect!
(fn [_ [_ password]]
(dispatch [:set :creating-account? true])
(s/execute-later #(dispatch [:account-generation-message]) 400)
(reg-fx
::create-account
(fn [password]
(status/create-account
password
#(account-created % password)))))
#(account-created % password))))
(defn save-account!
[{:keys [current-account-id accounts network]} _]
(let [{acc-network :network :as account}
(get accounts current-account-id)
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)]
(reg-fx
::broadcast-account-update
(fn [{:keys [current-public-key web3 name photo-path status
updates-public-key updates-private-key]}]
(when web3
(protocol/broadcast-profile!
{:web3 web3
@ -88,11 +78,11 @@
:status status
:profile-image photo-path}}}}))))
(defn send-keys-update
[{:keys [current-account-id current-public-key web3 accounts contacts]} _]
(let [{:keys [name photo-path status]} (get accounts current-account-id)
{:keys [updates-public-key updates-private-key]} (accounts current-account-id)]
(doseq [id (u/identities contacts)]
(reg-fx
::send-keys-update
(fn [{:keys [web3 current-public-key contacts
updates-public-key updates-private-key]}]
(doseq [id (handlers/identities contacts)]
(protocol/update-keys!
{:web3 web3
:message {:from current-public-key
@ -100,93 +90,96 @@
:message-id (random/id)
:payload {:keypair {:public updates-public-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
(u/side-effect!
(fn [{:keys [current-account-id accounts]} [_ status]]
(fn [{:accounts/keys [accounts current-account-id]} [_ status]]
(let [{old-status :status} (get accounts current-account-id)
status-updated? (and (not= status nil)
(not= status old-status))]
(when status-updated?
(let [hashtags (get-hashtags status)]
(when (seq hashtags)
(dispatch [:broadcast-status status hashtags]))))))))
{:dispatch [:broadcast-status status hashtags]}))))))
(defn account-update
[{:keys [current-account-id accounts] :as db} data]
(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 update-account [current-account new-fields]
(merge current-account (assoc new-fields :last-updated (time/now-ms))))
(defn account-update-keys
[db _]
(let [{:keys [public private]} (protocol/new-keypair!)]
(account-update db {:updates-public-key public
:updates-private-key private})))
(reg-event-db
(register-handler-fx
:account-update
(u/handlers->
(fn [db [_ data]]
(account-update db data))
save-account!
broadcast-account-update))
(fn [{{:keys [network]
:accounts/keys [accounts current-account-id] :as db} :db} [_ new-account-fields]]
(let [current-account (get accounts current-account-id)
new-account-fields' (assoc new-account-fields :network (or (:network current-account) network))
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
(u/handlers->
save-account!
send-keys-update
account-update-keys))
[(inject-cofx :get-new-keypair!)]
(fn [{:keys [db keypair]} _]
(let [{:accounts/keys [accounts current-account-id]} db
{: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
(u/side-effect!
(fn [{:keys [current-account-id accounts]} _]
(fn [{{:accounts/keys [accounts current-account-id]} :db} _]
(let [{:keys [last-updated]} (get accounts current-account-id)
now (time/now-ms)
needs-update? (> (- now last-updated) time/week)]
(log/info "Need to send account-update: " needs-update?)
(when needs-update?
(dispatch [:account-update]))))))
(dispatch [:account-update])))))
(defn set-current-account
[{:keys [accounts] :as db} [_ address]]
(register-handler-db
:set-current-account
(fn [{:accounts/keys [accounts] :as db} [_ address]]
(let [key (:public-key (accounts address))]
(assoc db :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))))))
(assoc db :accounts/current-account-id address
:current-public-key key))))

View File

@ -1,76 +1,82 @@
(ns status-im.ui.screens.accounts.login.events
(:require [re-frame.core :refer [after dispatch]]
[status-im.utils.handlers :refer [register-handler] :as u]
(:require
status-im.ui.screens.accounts.login.navigation
[re-frame.core :refer [dispatch reg-fx]]
[status-im.utils.handlers :refer [register-handler-db register-handler-fx]]
[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]))
[status-im.constants :refer [console-chat-id]]))
(defmethod nav/preload-data! :login
[db]
(update db :login dissoc :error :password :processing))
;;;; FX
(defn set-login-from-qr
[{:keys [login] :as db} [_ _ login-info]]
(assoc db :login (merge login login-info)))
(reg-fx
::login
(fn [[address password]]
(status/login address password #(dispatch [:login-handler % address]))))
(register-handler :set-login-from-qr set-login-from-qr)
(reg-fx
::clear-web-data
(fn []
(status/clear-web-data)))
(register-handler :open-login
(after #(dispatch [:navigate-to :login]))
(fn [db [_ address photo-path name]]
(update db :login assoc :address address :photo-path photo-path :name name)))
(defn initialize-account
[address new-account?]
(dispatch [:set :login {}])
(dispatch [:debug-server-stop])
(dispatch [:set-current-account address])
(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
(u/side-effect!
(fn [_ [_ address new-account? callback]]
(status/clear-web-data)
(reg-fx
::change-account
(fn [[address new-account?]]
(data-store/change-account address new-account?
#(callback % address new-account?)))))
#(dispatch [:change-account-handler % address new-account?]))))
(defn on-account-changed
[error address new-account?]
(if (nil? error)
(initialize-account address new-account?)
(log/debug "Error changing acount: " error)))
;;;; Handlers
(defn logged-in
[db address]
(register-handler-fx
:open-login
(fn [{db :db} [_ address photo-path name]]
{:db (update db
:accounts/login assoc
:address address
:photo-path photo-path
:name name)
:dispatch [:navigate-to :login]}))
(register-handler-fx
:login-account
(fn [{db :db} [_ address password account-creation?]]
{:db (-> db
(assoc :accounts/account-creation? account-creation?)
(assoc-in [:accounts/login :processing] true))
::login [address password]}))
(register-handler-fx
:login-handler
(fn [{db :db} [_ result address]]
(let [data (json->clj result)
error (:error data)
success (zero? (count error))
db' (assoc-in db [:accounts/login :processing] false)]
(log/debug "Logged in account: ")
(merge
{:db (if success db' (assoc-in db' [:accounts/login :error] error))}
(when success
(let [is-login-screen? (= (:view-id db) :login)
new-account? (not is-login-screen?)]
(log/debug "Logged in: " (:view-id db) is-login-screen? new-account?)
(dispatch [:change-account address new-account? on-account-changed])))
{::clear-web-data nil
::change-account [address new-account?]}))))))
(register-handler :login-account
(after
(fn [db [_ address password]]
(status/login address password
(fn [result]
(let [data (json->clj result)
error (:error data)
success (zero? (count error))]
(log/debug "Logged in account: ")
(dispatch [:set-in [:login :processing] false])
(if success
(logged-in db address)
(dispatch [:set-in [:login :error] error])))))))
(fn [db [_ _ _ account-creation?]]
(-> db
(assoc :account-creation? account-creation?)
(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]))
(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
[status-bar {:type :transparent}]
[login-toolbar]
@ -42,8 +42,8 @@
:auto-capitalize :none
:hide-underline? true
:on-change-text #(do
(dispatch [:set-in [:login :password] %])
(dispatch [:set-in [:login :error] ""]))
(dispatch [:set-in [:accounts/login :password] %])
(dispatch [:set-in [:accounts/login :error] ""]))
:on-submit-editing #(login-account password-text-input address password)
:auto-focus true
:secure-text-entry true

View File

@ -1,6 +1,6 @@
(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 ::not-empty-string)
(s/def ::password ::not-empty-string)
(s/def ::passphrase :global/not-empty-string)
(s/def ::password :global/not-empty-string)

View File

@ -1,20 +1,33 @@
(ns status-im.ui.screens.accounts.recover.events
(:require [re-frame.core :refer [reg-event-db after dispatch dispatch-sync]]
(:require
status-im.ui.screens.accounts.recover.navigation
[re-frame.core :refer [reg-fx inject-cofx dispatch]]
[status-im.components.status :as status]
[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]))
[status-im.utils.handlers :refer [register-handler-fx]]
[status-im.utils.gfycat.core :refer [generate-gfy]]))
(defn account-recovered [result]
;;;; FX
(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]} (protocol/new-keypair!)
{:keys [public private]} keypair
account {:public-key public-key
:address address
:name (generate-gfy public-key)
@ -24,20 +37,12 @@
: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]))))
{:db (update db :accounts/recover assoc :passphrase "" :password "")
:dispatch-n [[:add-account account]
[:navigate-back]]}))))
(defn recover-account
[_ [_ passphrase password]]
(status/recover-account
passphrase
password
account-recovered))
(register-handler-fx
:recover-account
(fn [_ [_ passphrase password]]
{::recover-account-fx [passphrase password]}))
(reg-event-db :recover-account (u/side-effect! recover-account))
(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]))
(defview passphrase-input [passphrase]
(letsubs [error [:get-in [:recover :passphrase-error]]]
(letsubs [error [:get-in [:accounts/recover :passphrase-error]]]
[view {:margin-top 10}
[text-input-with-label {:label (i18n/label :t/passphrase)
:description (i18n/label :t/twelve-words-in-correct-order)
@ -27,21 +27,21 @@
:max-height st/passphrase-input-max-height
:default-value passphrase
:auto-capitalize :none
:on-change-text #(dispatch [:set-in [:recover :passphrase] %])
:on-change-text #(dispatch [:set-in [:accounts/recover :passphrase] %])
:error error}]]))
(defview password-input [password]
(letsubs [error [:get-in [:recover :password-error]]]
(letsubs [error [:get-in [:accounts/recover :password-error]]]
[view {:margin-top 10}
[text-input-with-label {:label (i18n/label :t/password)
:default-value password
:auto-capitalize :none
:on-change-text #(dispatch [:set-in [:recover :password] %])
:on-change-text #(dispatch [:set-in [:accounts/recover :password] %])
:secure-text-entry true
:error error}]]))
(defview recover []
(letsubs [{:keys [passphrase password]} [:get :recover]]
(letsubs [{:keys [passphrase password]} [:get :accounts/recover]]
(let [valid-form? (and
(spec/valid? ::v/passphrase passphrase)
(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
[account-bage address photo-path name]]]])
(defn create-account [_]
(dispatch [:initialize-db])
(dispatch [:load-accounts])
(dispatch [:check-console-chat true]))
(defview accounts []
[accounts [:get :accounts]]
[accounts [:get-accounts]]
[view st/accounts-container
[status-bar {:type :transparent}]
[view st/account-title-conatiner
@ -53,7 +48,7 @@
[view st/bottom-actions-container
[action-button (i18n/label :t/create-new-account)
:add_white
create-account
#(dispatch [:create-new-account-handler])
st/accounts-action-button]
[common/separator st/accounts-separator st/accounts-separator-wrapper]
[action-button (i18n/label :t/recover-access)

View File

@ -1,45 +1,23 @@
(ns status-im.ui.screens.contacts.db
(:require-macros [status-im.utils.db :refer [allowed-keys]])
(:require [cljs.spec.alpha :as spec]
status-im.utils.db
[clojure.string :as string]
[status-im.data-store.contacts :as contacts]
[status-im.js-dependencies :as dependencies]))
[status-im.data-store.contacts :as contacts]))
(defn contact-can-be-added? [identity]
(if (contacts/exists? identity)
(:pending? (contacts/get-by-id identity))
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
;;Contact
;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/name ::not-empty-string)
(spec/def :contact/address (spec/nilable is-address?))
(spec/def :contact/whisper-identity :global/not-empty-string)
(spec/def :contact/name :global/not-empty-string)
(spec/def :contact/address (spec/nilable :global/address))
(spec/def :contact/private-key (spec/nilable string?))
(spec/def :contact/public-key (spec/nilable string?))
(spec/def :contact/photo-path (spec/nilable string?))
@ -77,12 +55,12 @@
(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
(spec/def :contacts/new-identity (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)
(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/ui-props (spec/nilable (allowed-keys :opt-un [:contacts-ui/edit?])))
;used in modal list (for example for wallet)

View File

@ -16,8 +16,8 @@
[status-im.utils.identicon :refer [identicon]]
[status-im.utils.gfycat.core :refer [generate-gfy]]
[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
@ -310,10 +310,11 @@
(register-handler-fx
::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)]
{::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 current-account [:name :photo-path :status
:updates-public-key :updates-private-key]))})))
@ -437,7 +438,7 @@
(register-handler-fx
:add-contact-handler
(fn [{:keys [db]} [_ id]]
(if (v/is-address? id)
(if (spec/valid? :global/address id)
{::request-contacts-by-address id}
{:dispatch (if (get-in db [:contacts/contacts id])
[:add-pending-contact id]

View File

@ -31,7 +31,7 @@
(normalize-hex whisper-identity))
(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)
(not (v/contact-can-be-added? whisper-identity))

View File

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

View File

@ -29,7 +29,8 @@
(register-handler :broadcast-status
(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]}
[_ status hashtags]]
(let [{:keys [name photo-path]} (get accounts current-account-id)

View File

@ -131,12 +131,12 @@
network-status network _]} :db} _]
{::init-store nil
:db (assoc app-db
:current-account-id nil
:accounts/current-account-id nil
:contacts/contacts {}
:network-status network-status
:status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?)
:status-node-started? status-node-started?
:network (or network :testnet))}))
:network (or network "testnet"))}))
(register-handler-db
:initialize-account-db
@ -163,11 +163,11 @@
[:send-account-update-if-needed]
[:start-requesting-discoveries]
[:remove-old-discoveries!]
[:set :creating-account? false]]}))
[:set :accounts/creating-account? false]]}))
(register-handler-fx
: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)
:chat
:accounts)]

View File

@ -1,22 +1,21 @@
(ns status-im.ui.screens.group.db
(:require-macros [status-im.utils.db :refer [allowed-keys]])
(:require [cljs.spec.alpha :as spec]
status-im.utils.db
[status-im.constants :refer [console-chat-id wallet-chat-id]]
[clojure.string :as string]
[status-im.utils.homoglyph :as utils]))
(spec/def ::not-empty-string (spec/and string? not-empty))
(spec/def ::name ::not-empty-string)
(spec/def ::name :global/not-empty-string)
;;;; DB
(spec/def :group/group-id ::not-empty-string)
(spec/def :group/name ::not-empty-string)
(spec/def :group/group-id :global/not-empty-string)
(spec/def :group/name :global/not-empty-string)
(spec/def :group/timestamp int?)
(spec/def :group/pending? boolean?)
(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]))
@ -27,7 +26,7 @@
:group/order :group/contacts]
: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
(spec/def :group/contact-group-id (spec/nilable string?))
(spec/def :group/group-type (spec/nilable #{:chat-group :contact-group}))

View File

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

View File

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

View File

@ -2,8 +2,8 @@
(:require [status-im.ui.screens.navigation :as navigation]))
(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
(get-in db [:accounts current-account-id]))
(get-in db [:accounts/accounts current-account-id]))
:qr-source qr-source
:amount? amount?}))

View File

@ -1,6 +1,7 @@
(ns status-im.ui.screens.subs
(:require [re-frame.core :refer [reg-sub subscribe]]
status-im.chat.subs
status-im.ui.screens.accounts.subs
status-im.ui.screens.chats-list.subs
status-im.ui.screens.group.chat-settings.subs
status-im.ui.screens.discover.subs
@ -15,16 +16,16 @@
(reg-sub :get-current-account
(fn [db]
(let [current-account-id (:current-account-id db)]
(get-in db [:accounts current-account-id]))))
(let [current-account-id (:accounts/current-account-id db)]
(get-in db [:accounts/accounts current-account-id]))))
(reg-sub :get-in
(fn [db [_ path]]
(get-in db path)))
(reg-sub :signed-up?
:<- [:get :current-account-id]
:<- [:get :accounts]
:<- [:get :accounts/current-account-id]
:<- [:get-accounts]
(fn [[account-id accounts]]
(when (and accounts account-id)
(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"}
recieved-contact' (merge new-contact
(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
:payload {:contact recieved-contact
:keypair {:public ""
:keypair {:public new-contact-public-key
:private ""}}}])
(is (= (assoc contacts-browse-wallet new-contact-public-key recieved-contact')