- ensure that `:key-uid` is always added to `app-db` with proper case - tests which cover multiacc duplication case
This commit is contained in:
parent
e5f7a94ee2
commit
9a713148c7
|
@ -1846,20 +1846,20 @@
|
||||||
(assoc :intro-wizard nil))}
|
(assoc :intro-wizard nil))}
|
||||||
(multiaccounts.create/on-multiaccount-created
|
(multiaccounts.create/on-multiaccount-created
|
||||||
{:derived {constants/path-wallet-root-keyword
|
{:derived {constants/path-wallet-root-keyword
|
||||||
{:publicKey wallet-root-public-key
|
{:public-key wallet-root-public-key
|
||||||
:address (eip55/address->checksum wallet-root-address)}
|
:address (eip55/address->checksum wallet-root-address)}
|
||||||
constants/path-whisper-keyword
|
constants/path-whisper-keyword
|
||||||
{:publicKey whisper-public-key
|
{:public-key whisper-public-key
|
||||||
:address (eip55/address->checksum whisper-address)
|
:address (eip55/address->checksum whisper-address)
|
||||||
:name name
|
:name name
|
||||||
:photo-path photo-path}
|
:photo-path photo-path}
|
||||||
constants/path-default-wallet-keyword
|
constants/path-default-wallet-keyword
|
||||||
{:publicKey wallet-public-key
|
{:public-key wallet-public-key
|
||||||
:address (eip55/address->checksum wallet-address)}}
|
:address (eip55/address->checksum wallet-address)}}
|
||||||
:address address
|
:address address
|
||||||
:public-key public-key
|
:public-key public-key
|
||||||
:keycard-instance-uid instance-uid
|
:keycard-instance-uid instance-uid
|
||||||
:keyUid (ethereum/normalized-hex key-uid)
|
:key-uid (ethereum/normalized-hex key-uid)
|
||||||
:keycard-pairing pairing
|
:keycard-pairing pairing
|
||||||
:keycard-paired-on paired-on
|
:keycard-paired-on paired-on
|
||||||
:chat-key whisper-private-key}
|
:chat-key whisper-private-key}
|
||||||
|
|
|
@ -51,13 +51,30 @@
|
||||||
(let [{:keys [selected-id multiaccounts]} (:intro-wizard db)]
|
(let [{:keys [selected-id multiaccounts]} (:intro-wizard db)]
|
||||||
(some #(when (= selected-id (:id %)) %) multiaccounts)))
|
(some #(when (= selected-id (:id %)) %) multiaccounts)))
|
||||||
|
|
||||||
|
(defn normalize-derived-data-keys [derived-data]
|
||||||
|
(->> derived-data
|
||||||
|
(map (fn [[path {:keys [publicKey] :as data}]]
|
||||||
|
[path (cond-> (-> data
|
||||||
|
(dissoc :publicKey)
|
||||||
|
(assoc :public-key publicKey)))]))
|
||||||
|
(into {})))
|
||||||
|
|
||||||
|
(defn normalize-multiaccount-data-keys
|
||||||
|
[{:keys [publicKey keyUid derived] :as data}]
|
||||||
|
(cond-> (-> data
|
||||||
|
(dissoc :keyUid :publicKey)
|
||||||
|
(assoc :key-uid keyUid
|
||||||
|
:public-key publicKey))
|
||||||
|
derived
|
||||||
|
(update :derived normalize-derived-data-keys)))
|
||||||
|
|
||||||
(fx/defn create-multiaccount
|
(fx/defn create-multiaccount
|
||||||
[{:keys [db]}]
|
[{:keys [db]}]
|
||||||
(let [{:keys [selected-id key-code]} (:intro-wizard db)
|
(let [{:keys [selected-id key-code]} (:intro-wizard db)
|
||||||
hashed-password (ethereum/sha3 (security/safe-unmask-data key-code))
|
hashed-password (ethereum/sha3 (security/safe-unmask-data key-code))
|
||||||
callback (fn [result]
|
callback (fn [result]
|
||||||
(let [derived-data (types/json->clj result)
|
(let [derived-data (normalize-derived-data-keys (types/json->clj result))
|
||||||
public-key (get-in derived-data [constants/path-whisper-keyword :publicKey])]
|
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
|
||||||
(status/gfycat-identicon-async
|
(status/gfycat-identicon-async
|
||||||
public-key
|
public-key
|
||||||
(fn [name photo-path]
|
(fn [name photo-path]
|
||||||
|
@ -191,17 +208,17 @@
|
||||||
|
|
||||||
(defn prepare-accounts-data
|
(defn prepare-accounts-data
|
||||||
[multiaccount]
|
[multiaccount]
|
||||||
[(let [{:keys [publicKey address]}
|
[(let [{:keys [public-key address]}
|
||||||
(get-in multiaccount [:derived constants/path-default-wallet-keyword])]
|
(get-in multiaccount [:derived constants/path-default-wallet-keyword])]
|
||||||
{:public-key publicKey
|
{:public-key public-key
|
||||||
:address (eip55/address->checksum address)
|
:address (eip55/address->checksum address)
|
||||||
:color colors/blue
|
:color colors/blue
|
||||||
:wallet true
|
:wallet true
|
||||||
:path constants/path-default-wallet
|
:path constants/path-default-wallet
|
||||||
:name "Status account"})
|
:name "Status account"})
|
||||||
(let [{:keys [publicKey address name photo-path]}
|
(let [{:keys [public-key address name photo-path]}
|
||||||
(get-in multiaccount [:derived constants/path-whisper-keyword])]
|
(get-in multiaccount [:derived constants/path-whisper-keyword])]
|
||||||
{:public-key publicKey
|
{:public-key public-key
|
||||||
:address (eip55/address->checksum address)
|
:address (eip55/address->checksum address)
|
||||||
:name name
|
:name name
|
||||||
:photo-path photo-path
|
:photo-path photo-path
|
||||||
|
@ -227,7 +244,7 @@
|
||||||
|
|
||||||
(fx/defn on-multiaccount-created
|
(fx/defn on-multiaccount-created
|
||||||
[{:keys [signing-phrase random-guid-generator db] :as cofx}
|
[{:keys [signing-phrase random-guid-generator db] :as cofx}
|
||||||
{:keys [address chat-key keycard-instance-uid keyUid
|
{:keys [address chat-key keycard-instance-uid key-uid
|
||||||
keycard-pairing keycard-paired-on mnemonic public-key]
|
keycard-pairing keycard-paired-on mnemonic public-key]
|
||||||
:as multiaccount}
|
:as multiaccount}
|
||||||
password
|
password
|
||||||
|
@ -236,7 +253,7 @@
|
||||||
multiaccount-data {:name name
|
multiaccount-data {:name name
|
||||||
:address address
|
:address address
|
||||||
:photo-path photo-path
|
:photo-path photo-path
|
||||||
:key-uid keyUid
|
:key-uid key-uid
|
||||||
:keycard-pairing keycard-pairing}
|
:keycard-pairing keycard-pairing}
|
||||||
keycard-multiaccount? (boolean keycard-pairing)
|
keycard-multiaccount? (boolean keycard-pairing)
|
||||||
eip1581-address (get-in multiaccount [:derived
|
eip1581-address (get-in multiaccount [:derived
|
||||||
|
@ -247,7 +264,7 @@
|
||||||
{;; address of the master key
|
{;; address of the master key
|
||||||
:address address
|
:address address
|
||||||
;; sha256 of master public key
|
;; sha256 of master public key
|
||||||
:key-uid keyUid
|
:key-uid key-uid
|
||||||
;; The address from which we derive any wallet
|
;; The address from which we derive any wallet
|
||||||
:wallet-root-address
|
:wallet-root-address
|
||||||
(get-in multiaccount [:derived
|
(get-in multiaccount [:derived
|
||||||
|
@ -274,7 +291,7 @@
|
||||||
:keycard-pairing keycard-pairing
|
:keycard-pairing keycard-pairing
|
||||||
:keycard-paired-on keycard-paired-on))
|
:keycard-paired-on keycard-paired-on))
|
||||||
db (assoc db
|
db (assoc db
|
||||||
:multiaccounts/login {:key-uid keyUid
|
:multiaccounts/login {:key-uid key-uid
|
||||||
:name name
|
:name name
|
||||||
:photo-path photo-path
|
:photo-path photo-path
|
||||||
:password password
|
:password password
|
||||||
|
@ -311,7 +328,9 @@
|
||||||
5
|
5
|
||||||
12
|
12
|
||||||
[constants/path-whisper constants/path-default-wallet]
|
[constants/path-whisper constants/path-default-wallet]
|
||||||
#(re-frame/dispatch [:intro-wizard/on-keys-generated (types/json->clj %)]))))
|
#(re-frame/dispatch [:intro-wizard/on-keys-generated
|
||||||
|
(mapv normalize-multiaccount-data-keys
|
||||||
|
(types/json->clj %))]))))
|
||||||
|
|
||||||
(fx/defn on-keys-generated
|
(fx/defn on-keys-generated
|
||||||
{:events [:intro-wizard/on-keys-generated]}
|
{:events [:intro-wizard/on-keys-generated]}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
(spec/def :multiaccount/accounts (spec/coll-of :multiaccount/account :kind vector?))
|
(spec/def :multiaccount/accounts (spec/coll-of :multiaccount/account :kind vector?))
|
||||||
|
|
||||||
(spec/def :multiaccount/address :global/address)
|
(spec/def :multiaccount/address :global/address)
|
||||||
(spec/def :multiaccount/key-uid string?)
|
(spec/def :multiaccount/key-uid :global/key-uid)
|
||||||
(spec/def :multiaccount/name :global/not-empty-string)
|
(spec/def :multiaccount/name :global/not-empty-string)
|
||||||
(spec/def :multiaccount/public-key :global/public-key)
|
(spec/def :multiaccount/public-key :global/public-key)
|
||||||
(spec/def :multiaccount/signed-up? (spec/nilable boolean?))
|
(spec/def :multiaccount/signed-up? (spec/nilable boolean?))
|
||||||
|
@ -76,6 +76,20 @@
|
||||||
:multiaccount/keycard-paired-on
|
:multiaccount/keycard-paired-on
|
||||||
:multiaccount/root-address
|
:multiaccount/root-address
|
||||||
:multiaccount/accounts]))
|
:multiaccount/accounts]))
|
||||||
|
;; generated multiaccounts
|
||||||
|
(spec/def :generated-multiaccounts/id string?)
|
||||||
|
(spec/def :generated-multiaccounts/derived-key
|
||||||
|
(spec/keys :req-un [:multiaccount/address
|
||||||
|
:multiaccount/public-key]))
|
||||||
|
(spec/def :generated-multiaccounts/derived
|
||||||
|
(spec/map-of keyword? :generated-multiaccounts/derived-key))
|
||||||
|
(spec/def :multiaccounts/generated-multiaccount
|
||||||
|
(spec/keys :req-un [:multiaccount/address
|
||||||
|
:multiaccount/mnemonic
|
||||||
|
:multiaccount/public-key
|
||||||
|
:multiaccount/key-uid
|
||||||
|
:generated-multiaccounts/id]
|
||||||
|
:opt-un [:generated-multiaccounts/derived]))
|
||||||
|
|
||||||
;;used during recovering multiaccount
|
;;used during recovering multiaccount
|
||||||
(spec/def :multiaccounts/recover (spec/nilable map?))
|
(spec/def :multiaccounts/recover (spec/nilable map?))
|
||||||
|
|
|
@ -19,8 +19,9 @@
|
||||||
[taoensso.timbre :as log]))
|
[taoensso.timbre :as log]))
|
||||||
|
|
||||||
(defn existing-account?
|
(defn existing-account?
|
||||||
[root-key multiaccounts]
|
[multiaccounts key-uid]
|
||||||
(contains? multiaccounts (:keyUid root-key)))
|
{:pre [(not (nil? key-uid))]}
|
||||||
|
(contains? multiaccounts key-uid))
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
::validate-mnemonic
|
::validate-mnemonic
|
||||||
|
@ -100,7 +101,9 @@
|
||||||
passphrase
|
passphrase
|
||||||
password
|
password
|
||||||
(fn [result]
|
(fn [result]
|
||||||
(let [{:keys [id] :as root-data} (types/json->clj result)]
|
(let [{:keys [id] :as root-data}
|
||||||
|
(multiaccounts.create/normalize-multiaccount-data-keys
|
||||||
|
(types/json->clj result))]
|
||||||
(status-im.native-module.core/multiaccount-derive-addresses
|
(status-im.native-module.core/multiaccount-derive-addresses
|
||||||
id
|
id
|
||||||
[constants/path-wallet-root
|
[constants/path-wallet-root
|
||||||
|
@ -108,13 +111,16 @@
|
||||||
constants/path-whisper
|
constants/path-whisper
|
||||||
constants/path-default-wallet]
|
constants/path-default-wallet]
|
||||||
(fn [result]
|
(fn [result]
|
||||||
(let [derived-data (types/json->clj result)
|
(let [derived-data (multiaccounts.create/normalize-derived-data-keys
|
||||||
public-key (get-in derived-data [constants/path-whisper-keyword :publicKey])]
|
(types/json->clj result))
|
||||||
|
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
|
||||||
(status/gfycat-identicon-async
|
(status/gfycat-identicon-async
|
||||||
public-key
|
public-key
|
||||||
(fn [name photo-path]
|
(fn [name photo-path]
|
||||||
(let [derived-whisper (derived-data constants/path-whisper-keyword)
|
(let [derived-data-extended
|
||||||
derived-data-extended (assoc-in derived-data [constants/path-whisper-keyword] (merge derived-whisper {:name name :photo-path photo-path}))]
|
(update derived-data
|
||||||
|
constants/path-whisper-keyword
|
||||||
|
merge {:name name :photo-path photo-path})]
|
||||||
(re-frame/dispatch [::import-multiaccount-success
|
(re-frame/dispatch [::import-multiaccount-success
|
||||||
root-data derived-data-extended]))))))))))))
|
root-data derived-data-extended]))))))))))))
|
||||||
|
|
||||||
|
@ -130,7 +136,7 @@
|
||||||
|
|
||||||
(fx/defn on-import-multiaccount-success
|
(fx/defn on-import-multiaccount-success
|
||||||
{:events [::import-multiaccount-success]}
|
{:events [::import-multiaccount-success]}
|
||||||
[{:keys [db] :as cofx} root-data derived-data]
|
[{:keys [db] :as cofx} {:keys [key-uid] :as root-data} derived-data]
|
||||||
(let [multiaccounts (:multiaccounts/multiaccounts db)]
|
(let [multiaccounts (:multiaccounts/multiaccounts db)]
|
||||||
(fx/merge
|
(fx/merge
|
||||||
cofx
|
cofx
|
||||||
|
@ -139,8 +145,8 @@
|
||||||
:derived derived-data
|
:derived derived-data
|
||||||
:step :recovery-success
|
:step :recovery-success
|
||||||
:forward-action :multiaccounts.recover/re-encrypt-pressed)}
|
:forward-action :multiaccounts.recover/re-encrypt-pressed)}
|
||||||
(when (existing-account? root-data multiaccounts)
|
(when (existing-account? multiaccounts key-uid)
|
||||||
(show-existing-multiaccount-alert (:keyUid root-data)))
|
(show-existing-multiaccount-alert key-uid))
|
||||||
(navigation/navigate-to-cofx :recover-multiaccount-success nil))))
|
(navigation/navigate-to-cofx :recover-multiaccount-success nil))))
|
||||||
|
|
||||||
(fx/defn enter-phrase-pressed
|
(fx/defn enter-phrase-pressed
|
||||||
|
|
|
@ -265,7 +265,7 @@
|
||||||
:intro-wizard/recovery-success
|
:intro-wizard/recovery-success
|
||||||
:<- [:intro-wizard]
|
:<- [:intro-wizard]
|
||||||
(fn [wizard-state]
|
(fn [wizard-state]
|
||||||
{:pubkey (get-in wizard-state [:derived constants/path-whisper-keyword :publicKey])
|
{:pubkey (get-in wizard-state [:derived constants/path-whisper-keyword :public-key])
|
||||||
:name (get-in wizard-state [:derived constants/path-whisper-keyword :name])
|
:name (get-in wizard-state [:derived constants/path-whisper-keyword :name])
|
||||||
:photo-path (get-in wizard-state [:derived constants/path-whisper-keyword :photo-path])
|
:photo-path (get-in wizard-state [:derived constants/path-whisper-keyword :photo-path])
|
||||||
:processing? (:processing? wizard-state)}))
|
:processing? (:processing? wizard-state)}))
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
status-im.browser.db
|
status-im.browser.db
|
||||||
status-im.ui.screens.add-new.new-public-chat.db
|
status-im.ui.screens.add-new.new-public-chat.db
|
||||||
status-im.ui.components.bottom-sheet.core
|
status-im.ui.components.bottom-sheet.core
|
||||||
|
status-im.ui.screens.intro.db
|
||||||
[status-im.wallet.db :as wallet.db]))
|
[status-im.wallet.db :as wallet.db]))
|
||||||
|
|
||||||
;; initial state of app-db
|
;; initial state of app-db
|
||||||
|
@ -314,4 +315,5 @@
|
||||||
::collectibles
|
::collectibles
|
||||||
:registry/registry
|
:registry/registry
|
||||||
::two-pane-ui-enabled?
|
::two-pane-ui-enabled?
|
||||||
::add-account]))
|
::add-account
|
||||||
|
:intro-wizard/intro-wizard]))
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
(ns status-im.ui.screens.intro.db
|
||||||
|
(:require [cljs.spec.alpha :as spec]
|
||||||
|
status-im.multiaccounts.db))
|
||||||
|
|
||||||
|
(spec/def :intro-wizrad/encrypt-with-password? boolean?)
|
||||||
|
(spec/def :intro-wizard/multiaccounts
|
||||||
|
(spec/coll-of :multiaccounts/generated-multiaccount))
|
||||||
|
(spec/def :intro-wizard/selected-storage-type? keyword?)
|
||||||
|
(spec/def :intro-wizard/selected-id :generated-multiaccounts/id)
|
||||||
|
(spec/def :intro-wizard/back-action keyword?)
|
||||||
|
(spec/def :intro-wizard/weak-password? boolean?)
|
||||||
|
(spec/def :intro-wizard/forward-action keyword?)
|
||||||
|
(spec/def :intro-wizard/first-time-setup? boolean?)
|
||||||
|
(spec/def :intro-wizard/step (spec/nilable keyword?))
|
||||||
|
(spec/def :intro-wizard/root-key :multiaccounts/generated-multiaccount)
|
||||||
|
(spec/def :intro-wizard/passphrase string?)
|
||||||
|
(spec/def :intro-wizard/recovering? boolean?)
|
||||||
|
(spec/def :intro-wizard/passphrase-word-count int?)
|
||||||
|
(spec/def :intro-wizard/derived :generated-multiaccounts/derived)
|
||||||
|
(spec/def :intro-wizard/next-button-disabled? boolean?)
|
||||||
|
|
||||||
|
(spec/def :intro-wizard/intro-wizard
|
||||||
|
(spec/keys :req-un [:intro-wizrad/encrypt-with-password?
|
||||||
|
:intro-wizard/back-action
|
||||||
|
:intro-wizard/weak-password?
|
||||||
|
:intro-wizard/forward-action
|
||||||
|
:intro-wizard/first-time-setup?
|
||||||
|
:intro-wizard/step]
|
||||||
|
:opt-un [:intro-wizard/selected-id
|
||||||
|
:intro-wizard/selected-storage-type?
|
||||||
|
:intro-wizard/multiaccounts
|
||||||
|
:intro-wizard/root-key
|
||||||
|
:intro-wizard/passphrase
|
||||||
|
:intro-wizard/passphrase-word-count
|
||||||
|
:intro-wizard/derived
|
||||||
|
:intro-wizard/next-button-disabled?]))
|
|
@ -131,7 +131,7 @@
|
||||||
{:content-container-style {:justify-content :flex-start}}
|
{:content-container-style {:justify-content :flex-start}}
|
||||||
(for [[acc accessibility-n] (map vector multiaccounts (range (count multiaccounts)))]
|
(for [[acc accessibility-n] (map vector multiaccounts (range (count multiaccounts)))]
|
||||||
(let [selected? (= (:id acc) selected-id)
|
(let [selected? (= (:id acc) selected-id)
|
||||||
public-key (get-in acc [:derived constants/path-whisper-keyword :publicKey])]
|
public-key (get-in acc [:derived constants/path-whisper-keyword :public-key])]
|
||||||
^{:key public-key}
|
^{:key public-key}
|
||||||
[react/touchable-highlight
|
[react/touchable-highlight
|
||||||
{:accessibility-label (keyword (str "select-account-button-" accessibility-n))
|
{:accessibility-label (keyword (str "select-account-button-" accessibility-n))
|
||||||
|
|
|
@ -5,8 +5,12 @@
|
||||||
(defn valid-public-key? [s]
|
(defn valid-public-key? [s]
|
||||||
(boolean (re-matches #"0x04[0-9a-f]{128}" s)))
|
(boolean (re-matches #"0x04[0-9a-f]{128}" s)))
|
||||||
|
|
||||||
|
(defn valid-key-uid? [s]
|
||||||
|
(boolean (re-matches #"0x[0-9a-f]{64}" s)))
|
||||||
|
|
||||||
(spec/def :global/not-empty-string (spec/and string? not-empty))
|
(spec/def :global/not-empty-string (spec/and string? not-empty))
|
||||||
(spec/def :global/public-key (spec/and :global/not-empty-string valid-public-key?))
|
(spec/def :global/public-key (spec/and :global/not-empty-string valid-public-key?))
|
||||||
|
(spec/def :global/key-uid (spec/and :global/not-empty-string valid-key-uid?))
|
||||||
(spec/def :global/address ethereum/address?)
|
(spec/def :global/address ethereum/address?)
|
||||||
|
|
||||||
(spec/def :status/tag (spec/and :global/not-empty-string
|
(spec/def :status/tag (spec/and :global/not-empty-string
|
||||||
|
|
|
@ -52,3 +52,17 @@
|
||||||
(is (= (i18n/label :recovery-typo-dialog-title) (-> new-cofx :ui/show-confirmation :title)))
|
(is (= (i18n/label :recovery-typo-dialog-title) (-> new-cofx :ui/show-confirmation :title)))
|
||||||
(is (= (i18n/label :recovery-typo-dialog-description) (-> new-cofx :ui/show-confirmation :content)))
|
(is (= (i18n/label :recovery-typo-dialog-description) (-> new-cofx :ui/show-confirmation :content)))
|
||||||
(is (= (i18n/label :recovery-confirm-phrase) (-> new-cofx :ui/show-confirmation :confirm-button-text)))))
|
(is (= (i18n/label :recovery-confirm-phrase) (-> new-cofx :ui/show-confirmation :confirm-button-text)))))
|
||||||
|
|
||||||
|
(deftest on-import-multiaccount-success
|
||||||
|
(testing "importing a new multiaccount"
|
||||||
|
(let [res (models/on-import-multiaccount-success
|
||||||
|
{:db {:multiaccounts/multiaccounts {:acc1 {}}}}
|
||||||
|
{:key-uid :acc2}
|
||||||
|
nil)]
|
||||||
|
(is (nil? (:utils/show-confirmation res)))))
|
||||||
|
(testing "importing an existing multiaccount"
|
||||||
|
(let [res (models/on-import-multiaccount-success
|
||||||
|
{:db {:multiaccounts/multiaccounts {:acc1 {}}}}
|
||||||
|
{:key-uid :acc1}
|
||||||
|
nil)]
|
||||||
|
(is (contains? res :utils/show-confirmation)))))
|
||||||
|
|
Loading…
Reference in New Issue