[#9435] Prevent multiaccount duplication

Currently we have two ways to restore a multiaccount:
- by entering a mnemonic phrase
- by pairing a keycard with an existing multiaccount

In both cases, when we detect that a user tries to recover an existing
multiaccount we interrupt recovering and propose them to unlock that
multiaccount instead.
This commit is contained in:
Roman Volosovskyi 2019-11-20 16:41:21 +02:00
parent 507cc5cf39
commit 67e6ab6055
No known key found for this signature in database
GPG Key ID: 0238A4B5ECEE70DE
30 changed files with 189 additions and 127 deletions

View File

@ -38,7 +38,7 @@
"react-native-screens": "^1.0.0-alpha.23", "react-native-screens": "^1.0.0-alpha.23",
"react-native-shake": "^3.3.1", "react-native-shake": "^3.3.1",
"react-native-splash-screen": "^3.2.0", "react-native-splash-screen": "^3.2.0",
"react-native-status-keycard": "^2.5.12", "react-native-status-keycard": "^2.5.14",
"react-native-svg": "^9.8.4", "react-native-svg": "^9.8.4",
"react-native-touch-id": "^4.4.1", "react-native-touch-id": "^4.4.1",
"react-native-webview": "^6.11.1", "react-native-webview": "^6.11.1",

View File

@ -4877,10 +4877,10 @@ react-native-splash-screen@^3.2.0:
resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.2.0.tgz#d47ec8557b1ba988ee3ea98d01463081b60fff45" resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.2.0.tgz#d47ec8557b1ba988ee3ea98d01463081b60fff45"
integrity sha512-Ls9qiNZzW/OLFoI25wfjjAcrf2DZ975hn2vr6U9gyuxi2nooVbzQeFoQS5vQcbCt9QX5NY8ASEEAtlLdIa6KVg== integrity sha512-Ls9qiNZzW/OLFoI25wfjjAcrf2DZ975hn2vr6U9gyuxi2nooVbzQeFoQS5vQcbCt9QX5NY8ASEEAtlLdIa6KVg==
react-native-status-keycard@^2.5.12: react-native-status-keycard@^2.5.14:
version "2.5.12" version "2.5.14"
resolved "https://registry.yarnpkg.com/react-native-status-keycard/-/react-native-status-keycard-2.5.12.tgz#96cf98f955d3a354d0c4e9324e25fd359b99206c" resolved "https://registry.yarnpkg.com/react-native-status-keycard/-/react-native-status-keycard-2.5.14.tgz#105ac4642ae3df777b87020dd5d484445fff46ba"
integrity sha512-QCGiL5Sir8Gm53dG+PXB7fFGWLozej3GPt12dj9aU5EdNUPL7qG5gYCKFRlKMV/nPlpvKBikY4h1dDxwoCEcBg== integrity sha512-qt8+BcDMwtjhAwVahF5WryeLRU0auUcYrRhCci+O6rX/Roz0a+NHZ8a23NAducvNco7uOBuleYL7yyhMbwxXQw==
react-native-svg@^9.8.4: react-native-svg@^9.8.4:
version "9.11.1" version "9.11.1"

View File

@ -308,7 +308,7 @@
current-chat-id (:current-chat-id db) current-chat-id (:current-chat-id db)
amount-hex (str "0x" (abi-spec/number-to-hex (money/formatted->internal value symbol decimals))) amount-hex (str "0x" (abi-spec/number-to-hex (money/formatted->internal value symbol decimals)))
to (ethereum/public-key->address current-chat-id) to (ethereum/public-key->address current-chat-id)
to-norm (ethereum/normalized-address (if (= symbol :ETH) to address)) to-norm (ethereum/normalized-hex (if (= symbol :ETH) to address))
tx-obj (if (= symbol :ETH) tx-obj (if (= symbol :ETH)
{:to to-norm {:to to-norm
:value amount-hex} :value amount-hex}

View File

@ -55,15 +55,15 @@
(def hex-prefix "0x") (def hex-prefix "0x")
(defn normalized-address [address] (defn normalized-hex [hex]
(when address (when hex
(if (string/starts-with? address hex-prefix) (if (string/starts-with? hex hex-prefix)
address hex
(str hex-prefix address)))) (str hex-prefix hex))))
(defn current-address [db] (defn current-address [db]
(-> (get-in db [:multiaccount :address]) (-> (get-in db [:multiaccount :address])
normalized-address)) normalized-hex))
(defn get-default-account [accounts] (defn get-default-account [accounts]
(some #(when (:wallet %) %) accounts)) (some #(when (:wallet %) %) accounts))
@ -82,8 +82,8 @@
(defn coordinates [public-key] (defn coordinates [public-key]
(when-let [hex (naked-address public-key)] (when-let [hex (naked-address public-key)]
(when (= public-key-length (count (subs hex 2))) (when (= public-key-length (count (subs hex 2)))
{:x (normalized-address (subs hex 2 66)) {:x (normalized-hex (subs hex 2 66))
:y (normalized-address (subs hex 66))}))) :y (normalized-hex (subs hex 66))})))
(defn address? [s] (defn address? [s]
(when s (when s
@ -126,8 +126,8 @@
(defn address= [address1 address2] (defn address= [address1 address2]
(and address1 address2 (and address1 address2
(= (normalized-address address1) (= (normalized-hex address1)
(normalized-address address2)))) (normalized-hex address2))))
(defn public-key->address [public-key] (defn public-key->address [public-key]
(let [length (count public-key) (let [length (count public-key)

View File

@ -21,7 +21,7 @@
(defn namehash (defn namehash
[s] [s]
(ethereum/normalized-address (ethereum/normalized-hex
(if (string/blank? s) (if (string/blank? s)
default-namehash default-namehash
(let [[label remainder] (-> s (let [[label remainder] (-> s

View File

@ -157,8 +157,13 @@
;; multiaccounts login module ;; multiaccounts login module
(handlers/register-handler-fx (handlers/register-handler-fx
:multiaccounts.login.ui/multiaccount-selected :multiaccounts.login.ui/multiaccount-selected
(fn [cofx [_ address photo-path name public-key]] (fn [{:keys [db] :as cofx} [_ address]]
(multiaccounts.login/open-login cofx address photo-path name public-key))) (let [{:keys [photo-path name public-key]}
(get-in db [:multiaccounts/multiaccounts address])]
(fx/merge
cofx
{:db (dissoc db :intro-wizard)}
(multiaccounts.login/open-login address photo-path name public-key)))))
;; multiaccounts logout module ;; multiaccounts logout module

View File

@ -21,7 +21,8 @@
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.multiaccounts.update.core :as multiaccounts.update] [status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.ui.components.bottom-sheet.core :as bottom-sheet])) [status-im.ui.components.bottom-sheet.core :as bottom-sheet]
[status-im.multiaccounts.recover.core :as recover]))
(def default-pin "000000") (def default-pin "000000")
@ -38,12 +39,12 @@
(filter #(= keycard-instance-uid (:keycard-instance-uid %))) (filter #(= keycard-instance-uid (:keycard-instance-uid %)))
first))) first)))
(defn- find-multiaccount-by-keycard-key-uid (defn- find-multiaccount-by-key-uid
[db keycard-key-uid] [db key-uid]
(when keycard-key-uid (when key-uid
(->> (:multiaccounts/multiaccounts db) (->> (:multiaccounts/multiaccounts db)
vals vals
(filter #(= keycard-key-uid (:keycard-key-uid %))) (filter #(= (ethereum/normalized-hex key-uid) (:key-uid %)))
first))) first)))
(defn get-pairing (defn get-pairing
@ -55,7 +56,7 @@
(get-in db [:hardwallet :secrets :pairing]) (get-in db [:hardwallet :secrets :pairing])
(when key-uid (when key-uid
(:keycard-pairing (:keycard-pairing
(find-multiaccount-by-keycard-key-uid db key-uid)))))) (find-multiaccount-by-key-uid db key-uid))))))
(fx/defn listen-to-hardware-back-button (fx/defn listen-to-hardware-back-button
[{:keys [db]}] [{:keys [db]}]
@ -514,9 +515,9 @@
(load-pin-screen))) (load-pin-screen)))
(when (and (= card-state :multiaccount) (when (and (= card-state :multiaccount)
(= flow :import)) (= flow :import))
(let [existing-multiaccount (find-multiaccount-by-keycard-key-uid db key-uid)] (let [{:keys [address]} (find-multiaccount-by-key-uid db key-uid)]
(if existing-multiaccount (if address
(show-existing-multiaccount-alert) (recover/show-existing-multiaccount-alert address)
(if pairing (if pairing
(load-recovery-pin-screen) (load-recovery-pin-screen)
(load-pair-screen))))) (load-pair-screen)))))
@ -539,11 +540,12 @@
(fx/defn navigate-to-enter-pin-screen (fx/defn navigate-to-enter-pin-screen
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [keycard-key-uid (get-in db [:hardwallet :application-info :key-uid]) (let [key-uid (get-in db [:hardwallet :application-info :key-uid])
multiaccount-key-uid (get-in db [:multiaccount :keycard-key-uid])] multiaccount-key-uid (get-in db [:multiaccount :key-uid])
(if (or (nil? multiaccount-key-uid) keycard-multiaccount? (boolean (get-in db [:multiaccount :keycard-pairing]))]
(and keycard-key-uid (if (or (nil? keycard-multiaccount?)
(= keycard-key-uid multiaccount-key-uid))) (and key-uid
(= key-uid multiaccount-key-uid)))
(fx/merge cofx (fx/merge cofx
{:db (assoc-in db [:hardwallet :pin :current] [])} {:db (assoc-in db [:hardwallet :pin :current] [])}
(navigation/navigate-to-cofx :enter-pin-settings nil)) (navigation/navigate-to-cofx :enter-pin-settings nil))
@ -635,17 +637,17 @@
{:events [:hardwallet/login-with-keycard]} {:events [:hardwallet/login-with-keycard]}
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [application-info (get-in db [:hardwallet :application-info]) (let [application-info (get-in db [:hardwallet :application-info])
keycard-key-uid (get-in db [:hardwallet :application-info :key-uid]) key-uid (get-in db [:hardwallet :application-info :key-uid])
multiaccount (get-in db [:multiaccounts/multiaccounts (get-in db [:multiaccounts/login :address])]) multiaccount (get-in db [:multiaccounts/multiaccounts (get-in db [:multiaccounts/login :address])])
multiaccount-key-uid (get multiaccount :keycard-key-uid) multiaccount-key-uid (get multiaccount :key-uid)
multiaccount-mismatch? (or (nil? multiaccount) multiaccount-mismatch? (or (nil? multiaccount)
(not= multiaccount-key-uid keycard-key-uid)) (not= multiaccount-key-uid key-uid))
pairing (:keycard-pairing multiaccount)] pairing (:keycard-pairing multiaccount)]
(cond (cond
(empty? application-info) (empty? application-info)
(navigation/navigate-to-cofx cofx :not-keycard nil) (navigation/navigate-to-cofx cofx :not-keycard nil)
(empty? keycard-key-uid) (empty? key-uid)
(navigation/navigate-to-cofx cofx :keycard-blank nil) (navigation/navigate-to-cofx cofx :keycard-blank nil)
multiaccount-mismatch? multiaccount-mismatch?
@ -665,13 +667,15 @@
(fx/defn on-get-application-info-success (fx/defn on-get-application-info-success
[{:keys [db] :as cofx} info on-success] [{:keys [db] :as cofx} info on-success]
(let [info' (js->clj info :keywordize-keys true) (let [info' (-> info
{:keys [pin-retry-counter puk-retry-counter instance-uid]} info' (js->clj :keywordize-keys true)
(update :key-uid ethereum/normalized-hex))
{:keys [pin-retry-counter puk-retry-counter]} info'
view-id (:view-id db) view-id (:view-id db)
connect-screen? (contains? #{:hardwallet-connect connect-screen? (contains? #{:hardwallet-connect
:hardwallet-connect-sign :hardwallet-connect-sign
:hardwallet-connect-settings} view-id) :hardwallet-connect-settings} view-id)
{:keys [card-state on-card-read]} (:hardwallet db) {:keys [on-card-read]} (:hardwallet db)
on-success' (or on-success on-card-read) on-success' (or on-success on-card-read)
enter-step (if (zero? pin-retry-counter) enter-step (if (zero? pin-retry-counter)
:puk :puk
@ -1006,11 +1010,10 @@
(fx/defn delete-card (fx/defn delete-card
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [keycard-key-uid (get-in db [:hardwallet :application-info :key-uid]) (let [key-uid (get-in db [:hardwallet :application-info :key-uid])
multiaccount-key-uid (get-in db [:multiaccount :keycard-key-uid])] multiaccount-key-uid (get-in db [:multiaccount :key-uid])]
(if (or (nil? multiaccount-key-uid) (if (and key-uid
(and keycard-key-uid (= key-uid multiaccount-key-uid))
(= keycard-key-uid multiaccount-key-uid)))
{:hardwallet/delete nil} {:hardwallet/delete nil}
(unauthorized-operation cofx)))) (unauthorized-operation cofx))))
@ -1752,7 +1755,7 @@
:address address :address address
:publicKey public-key :publicKey public-key
:keycard-instance-uid instance-uid :keycard-instance-uid instance-uid
:keycard-key-uid key-uid :keyUid (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}
@ -1858,7 +1861,7 @@
; https://github.com/ethereum/go-ethereum/blob/master/internal/ethapi/api.go#L431 ; https://github.com/ethereum/go-ethereum/blob/master/internal/ethapi/api.go#L431
(clojure.string/replace-first #"00$", "1b") (clojure.string/replace-first #"00$", "1b")
(clojure.string/replace-first #"01$", "1c") (clojure.string/replace-first #"01$", "1c")
(ethereum/normalized-address))] (ethereum/normalized-hex))]
{:dispatch {:dispatch
[:signing/sign-message-completed (types/clj->json {:result signature'})]})) [:signing/sign-message-completed (types/clj->json {:result signature'})]}))

View File

@ -41,10 +41,10 @@
(fx/defn initialize-multiaccounts (fx/defn initialize-multiaccounts
{:events [::initialize-multiaccounts]} {:events [::initialize-multiaccounts]}
[{:keys [db] :as cofx} all-multiaccounts] [{:keys [db] :as cofx} all-multiaccounts]
(let [multiaccounts (reduce (fn [acc {:keys [address keycard-key-uid keycard-pairing] :as multiaccount}] (let [multiaccounts (reduce (fn [acc {:keys [address key-uid keycard-pairing] :as multiaccount}]
(-> (assoc acc address multiaccount) (-> (assoc acc address multiaccount)
(assoc-in [address :keycard-key-uid] (when-not (string/blank? keycard-key-uid) (assoc-in [address :key-uid] (when-not (string/blank? key-uid)
keycard-key-uid)) key-uid))
(assoc-in [address :keycard-pairing] (when-not (string/blank? keycard-pairing) (assoc-in [address :keycard-pairing] (when-not (string/blank? keycard-pairing)
keycard-pairing)))) keycard-pairing))))
{} {}

View File

@ -205,35 +205,42 @@
(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 keycard-key-uid keycard-pairing keycard-paired-on mnemonic] :as multiaccount} {:keys [address chat-key keycard-instance-uid keyUid
keycard-pairing keycard-paired-on mnemonic public-key]
:as multiaccount}
password password
{:keys [seed-backed-up? login?] :or {login? true}}] {:keys [seed-backed-up? login?] :or {login? true}}]
(let [[wallet-account {:keys [publicKey]} :as accounts-data] (prepare-accounts-data multiaccount) (let [[wallet-account {:keys [publicKey]} :as accounts-data] (prepare-accounts-data multiaccount)
name (gfycat/generate-gfy publicKey) name (gfycat/generate-gfy publicKey)
photo-path (identicon/identicon publicKey) photo-path (identicon/identicon publicKey)
multiaccount-data {:name name :address address :photo-path photo-path} multiaccount-data {:name name
new-multiaccount (cond-> {; address of the master key
:address address :address address
:photo-path photo-path
:key-uid keyUid}
keycard-multiaccount? (boolean keycard-pairing)
new-multiaccount (cond-> {;; address of the master key
:address address
;; sha256 of master public key
:key-uid keyUid
;; The address from which we derive any wallet ;; The address from which we derive any wallet
:wallet-root-address (get-in multiaccount [:derived constants/path-wallet-root-keyword :address]) :wallet-root-address (get-in multiaccount [:derived constants/path-wallet-root-keyword :address])
;; The address from which we derive any chat account/encryption keys ;; The address from which we derive any chat account/encryption keys
:eip1581-address (get-in multiaccount [:derived constants/path-eip1581-keyword :address]) :eip1581-address (get-in multiaccount [:derived constants/path-eip1581-keyword :address])
:name name :name name
:photo-path photo-path :photo-path photo-path
; public key of the chat account ;; public key of the chat account
:public-key publicKey :public-key publicKey
; default address for Dapps ;; default address for Dapps
:dapps-address (:address wallet-account) :dapps-address (:address wallet-account)
:latest-derived-path 0 :latest-derived-path 0
:accounts [wallet-account] :accounts [wallet-account]
:signing-phrase signing-phrase :signing-phrase signing-phrase
:installation-id (random-guid-generator) :installation-id (random-guid-generator)
:mnemonic mnemonic :mnemonic mnemonic
:settings constants/default-multiaccount-settings} :settings constants/default-multiaccount-settings}
keycard-key-uid (assoc :keycard-instance-uid keycard-instance-uid keycard-multiaccount?
:keycard-key-uid keycard-key-uid (assoc :keycard-instance-uid keycard-instance-uid
: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
@ -250,7 +257,7 @@
{:db (cond-> db {:db (cond-> db
seed-backed-up? seed-backed-up?
(assoc-in [:multiaccount :seed-backed-up?] true))} (assoc-in [:multiaccount :seed-backed-up?] true))}
(if keycard-key-uid (if keycard-multiaccount?
(save-account-and-login-with-keycard new-multiaccount (save-account-and-login-with-keycard new-multiaccount
password password
(node/get-new-config db) (node/get-new-config db)

View File

@ -38,10 +38,9 @@
(spec/def :multiaccount/hide-home-tooltip? (spec/nilable boolean?)) (spec/def :multiaccount/hide-home-tooltip? (spec/nilable boolean?))
(spec/def :multiaccount/desktop-alpha-release-warning-shown? (spec/nilable boolean?)) (spec/def :multiaccount/desktop-alpha-release-warning-shown? (spec/nilable boolean?))
(spec/def :multiaccount/keycard-instance-uid (spec/nilable string?)) (spec/def :multiaccount/keycard-instance-uid (spec/nilable string?))
(spec/def :multiaccount/keycard-key-uid (spec/nilable string?)) (spec/def :multiaccount/key-uid (spec/nilable string?))
(spec/def :multiaccount/keycard-pairing (spec/nilable string?)) (spec/def :multiaccount/keycard-pairing (spec/nilable string?))
(spec/def :multiaccount/keycard-paired-on (spec/nilable int?)) (spec/def :multiaccount/keycard-paired-on (spec/nilable int?))
(spec/def :multiaccount/multiaccount (spec/keys :opt-un [:multiaccount/name :multiaccount/address (spec/def :multiaccount/multiaccount (spec/keys :opt-un [:multiaccount/name :multiaccount/address
:multiaccount/photo-path :multiaccount/photo-path
:multiaccount/signing-phrase :multiaccount/signing-phrase
@ -57,7 +56,7 @@
:multiaccount/bootnodes :multiaccount/bootnodes
:multiaccount/desktop-alpha-release-warning-shown? :multiaccount/desktop-alpha-release-warning-shown?
:multiaccount/keycard-instance-uid :multiaccount/keycard-instance-uid
:multiaccount/keycard-key-uid :multiaccount/key-uid
:multiaccount/keycard-pairing :multiaccount/keycard-pairing
:multiaccount/keycard-paired-on :multiaccount/keycard-paired-on
:multiaccount/root-address :multiaccount/root-address

View File

@ -248,12 +248,15 @@
(fx/defn multiaccount-login-success (fx/defn multiaccount-login-success
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [{:keys [address password save-password? name photo-path creating?]} (:multiaccounts/login db) (let [{:keys [address password save-password? creating?]} (:multiaccounts/login db)
recovering? (get-in db [:intro-wizard :recovering?]) recovering? (get-in db [:intro-wizard :recovering?])
login-only? (not (or creating? login-only? (not (or creating?
recovering? recovering?
(keycard-setup? cofx))) (keycard-setup? cofx)))
nodes nil] nodes nil]
(log/debug "[multiaccount] multiaccount-login-success"
"login-only?" login-only?
"recovering?" recovering?)
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db
(dissoc :multiaccounts/login) (dissoc :multiaccounts/login)
@ -288,7 +291,7 @@
(fx/defn open-login (fx/defn open-login
[{:keys [db] :as cofx} address photo-path name public-key] [{:keys [db] :as cofx} address photo-path name public-key]
(let [keycard-multiaccount? (get-in db [:multiaccounts/multiaccounts address :keycard-key-uid])] (let [keycard-multiaccount? (boolean (get-in db [:multiaccounts/multiaccounts address :keycard-pairing]))]
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db
(update :multiaccounts/login assoc (update :multiaccounts/login assoc

View File

@ -14,7 +14,13 @@
[status-im.utils.security :as security] [status-im.utils.security :as security]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[status-im.utils.utils :as utils])) [status-im.utils.utils :as utils]
[status-im.ethereum.eip55 :as eip55]))
(defn existing-account?
[root-key multiaccounts]
(contains? multiaccounts ((fnil clojure.string/lower-case "")
(:address root-key))))
(defn check-phrase-warnings [recovery-phrase] (defn check-phrase-warnings [recovery-phrase]
(cond (string/blank? recovery-phrase) :required-field (cond (string/blank? recovery-phrase) :required-field
@ -47,7 +53,7 @@
multiaccount-address (-> (:address multiaccount) multiaccount-address (-> (:address multiaccount)
(string/lower-case) (string/lower-case)
(string/replace-first "0x" "")) (string/replace-first "0x" ""))
keycard-multiaccount? (boolean (get-in db [:multiaccounts/multiaccounts multiaccount-address :keycard-key-uid]))] keycard-multiaccount? (boolean (get-in db [:multiaccounts/multiaccounts multiaccount-address :keycard-pairing]))]
(if keycard-multiaccount? (if keycard-multiaccount?
;; trying to recover multiaccount created with keycard ;; trying to recover multiaccount created with keycard
{:db (-> db {:db (-> db
@ -105,16 +111,31 @@
(re-frame/dispatch [::import-multiaccount-success (re-frame/dispatch [::import-multiaccount-success
root-data derived-data]))))))))) root-data derived-data])))))))))
(fx/defn show-existing-multiaccount-alert
[_ address]
{:utils/show-confirmation
{:title (i18n/label :t/multiaccount-exists-title)
:content (i18n/label :t/multiaccount-exists-content)
:confirm-button-text (i18n/label :t/unlock)
:on-accept #(re-frame/dispatch
[:multiaccounts.login.ui/multiaccount-selected
(clojure.string/lower-case address)])
:on-cancel #(re-frame/dispatch [:navigate-to :multiaccounts])}})
(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 [address] :as root-data} derived-data]
(fx/merge cofx (let [multiaccounts (:multiaccounts/multiaccounts db)]
(fx/merge
cofx
{:db (update db :intro-wizard {:db (update db :intro-wizard
assoc :root-key root-data assoc :root-key root-data
: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)}
(navigation/navigate-to-cofx :recover-multiaccount-success nil))) (when (existing-account? root-data multiaccounts)
(show-existing-multiaccount-alert address))
(navigation/navigate-to-cofx :recover-multiaccount-success nil))))
(fx/defn enter-phrase-pressed (fx/defn enter-phrase-pressed
{:events [::enter-phrase-pressed]} {:events [::enter-phrase-pressed]}

View File

@ -47,7 +47,7 @@
(let [to (utils.hex/normalize-hex to)] (let [to (utils.hex/normalize-hex to)]
(or (or
(get-in db [:contacts/contacts to]) (get-in db [:contacts/contacts to])
{:address (ethereum/normalized-address to)}))) {:address (ethereum/normalized-hex to)})))
(fx/defn change-password (fx/defn change-password
{:events [:signing.ui/password-is-changed]} {:events [:signing.ui/password-is-changed]}
@ -156,7 +156,7 @@
token token
:else :else
{:to to {:to to
:contact {:address (ethereum/normalized-address to)}}))))) :contact {:address (ethereum/normalized-hex to)}})))))
(defn prepare-tx [db {{:keys [data gas gasPrice] :as tx-obj} :tx-obj :as tx}] (defn prepare-tx [db {{:keys [data gas gasPrice] :as tx-obj} :tx-obj :as tx}]
(merge (merge
@ -169,7 +169,7 @@
(fx/defn show-sign [{:keys [db] :as cofx}] (fx/defn show-sign [{:keys [db] :as cofx}]
(let [{:signing/keys [queue]} db (let [{:signing/keys [queue]} db
{{:keys [gas gasPrice] :as tx-obj} :tx-obj {:keys [data typed?] :as message} :message :as tx} (last queue) {{:keys [gas gasPrice] :as tx-obj} :tx-obj {:keys [data typed?] :as message} :message :as tx} (last queue)
keycard-multiaccount? (boolean (get-in db [:multiaccount :keycard-key-uid])) keycard-multiaccount? (boolean (get-in db [:multiaccount :keycard-pairing]))
wallet-set-up-passed? (get-in db [:multiaccount :wallet-set-up-passed?]) wallet-set-up-passed? (get-in db [:multiaccount :wallet-set-up-passed?])
updated-db (if wallet-set-up-passed? db (assoc db :popover/popover {:view :signing-phrase}))] updated-db (if wallet-set-up-passed? db (assoc db :popover/popover {:view :signing-phrase}))]
(if message (if message

View File

@ -22,6 +22,7 @@
[status-im.multiaccounts.model :as multiaccounts.model] [status-im.multiaccounts.model :as multiaccounts.model]
[status-im.multiaccounts.core :as multiaccounts] [status-im.multiaccounts.core :as multiaccounts]
[status-im.multiaccounts.db :as multiaccounts.db] [status-im.multiaccounts.db :as multiaccounts.db]
[status-im.multiaccounts.recover.core :as recover]
[status-im.pairing.core :as pairing] [status-im.pairing.core :as pairing]
[status-im.tribute-to-talk.core :as tribute-to-talk] [status-im.tribute-to-talk.core :as tribute-to-talk]
[status-im.tribute-to-talk.db :as tribute-to-talk.db] [status-im.tribute-to-talk.db :as tribute-to-talk.db]
@ -264,6 +265,13 @@
{:pubkey (get-in wizard-state [:derived constants/path-whisper-keyword :publicKey]) {:pubkey (get-in wizard-state [:derived constants/path-whisper-keyword :publicKey])
:processing? (:processing? wizard-state)})) :processing? (:processing? wizard-state)}))
(re-frame/reg-sub
:intro-wizard/recover-existing-account?
:<- [:intro-wizard]
:<- [:multiaccounts/multiaccounts]
(fn [[intro-wizard multiaccounts]]
(recover/existing-account? (:root-key intro-wizard) multiaccounts)))
(re-frame/reg-sub (re-frame/reg-sub
:settings/logging-enabled :settings/logging-enabled
:<- [:desktop/desktop] :<- [:desktop/desktop]
@ -446,7 +454,7 @@
:multiaccount/default-address :multiaccount/default-address
:<- [:multiaccount] :<- [:multiaccount]
(fn [{:keys [accounts]}] (fn [{:keys [accounts]}]
(ethereum/normalized-address (ethereum/normalized-hex
(:address (ethereum/get-default-account accounts))))) (:address (ethereum/get-default-account accounts)))))
(re-frame/reg-sub (re-frame/reg-sub

View File

@ -497,7 +497,7 @@
[react/view {:style {:margin-top 22}} [react/view {:style {:margin-top 22}}
(when-not pending? (when-not pending?
[section {:title (i18n/label :t/wallet-address) [section {:title (i18n/label :t/wallet-address)
:content (ethereum/normalized-address address)}]) :content (ethereum/normalized-hex address)}])
(when-not pending? (when-not pending?
[react/view {:style {:margin-top 14}} [react/view {:style {:margin-top 14}}
[section {:title (i18n/label :t/key) [section {:title (i18n/label :t/key)

View File

@ -50,4 +50,4 @@
:keycard-multiaccount? :keycard-multiaccount?
(fn [db] (fn [db]
(boolean (boolean
(get-in db [:multiaccount :keycard-key-uid])))) (get-in db [:multiaccount :keycard-pairing]))))

View File

@ -89,6 +89,12 @@
:align-items :center :align-items :center
:flex-direction :row}) :flex-direction :row})
(def disabled-bottom-button
(assoc bottom-button :background-color colors/gray-transparent-10))
(def disabled-bottom-button-text
{:color colors/gray-transparent-40})
(def bottom-button-container (def bottom-button-container
{:margin-bottom 24 {:margin-bottom 24
:margin-top 16}) :margin-top 16})

View File

@ -253,7 +253,7 @@
(defn bottom-bar [{:keys [step weak-password? encrypt-with-password? (defn bottom-bar [{:keys [step weak-password? encrypt-with-password?
forward-action forward-action
next-button-disabled? next-button-disabled?
processing?] :as wizard-state}] processing? existing-account?] :as wizard-state}]
[react/view {:style {:margin-bottom (if (or (#{:choose-key :select-key-storage [react/view {:style {:margin-bottom (if (or (#{:choose-key :select-key-storage
:enter-phrase :recovery-success} step) :enter-phrase :recovery-success} step)
(and (#{:create-code :confirm-code} step) (and (#{:create-code :confirm-code} step)
@ -271,11 +271,16 @@
:recovery-success :re-encrypt-key :recovery-success :re-encrypt-key
:intro-wizard-title6)] :intro-wizard-title6)]
[react/view {:min-height 46 :max-height 46} [react/view {:min-height 46 :max-height 46}
[components.common/button {:button-style styles/bottom-button [components.common/button
:on-press #(re-frame/dispatch {:button-style (if existing-account?
[forward-action]) styles/disabled-bottom-button
styles/bottom-button)
:on-press (when-not existing-account?
#(re-frame/dispatch [forward-action]))
:accessibility-label :onboarding-next-button :accessibility-label :onboarding-next-button
:label (i18n/label label-kw)}]]) :label (i18n/label label-kw)
:label-style (when existing-account?
styles/disabled-bottom-button-text)}]])
(and (#{:create-code :confirm-code} step) (and (#{:create-code :confirm-code} step)
(not encrypt-with-password?)) (not encrypt-with-password?))
[components.common/button {:button-style styles/bottom-button [components.common/button {:button-style styles/bottom-button
@ -555,7 +560,8 @@
wizard-state)]]])) wizard-state)]]]))
(defview wizard-recovery-success [] (defview wizard-recovery-success []
(letsubs [{:keys [pubkey processing?]} [:intro-wizard/recovery-success]] (letsubs [{:keys [pubkey processing?]} [:intro-wizard/recovery-success]
existing-account? [:intro-wizard/recover-existing-account?]]
[react/view {:style {:flex 1}} [react/view {:style {:flex 1}}
[toolbar/toolbar [toolbar/toolbar
{:style {:border-bottom-width 0 {:style {:border-bottom-width 0
@ -569,4 +575,5 @@
[recovery-success pubkey] [recovery-success pubkey]
[bottom-bar {:step :recovery-success [bottom-bar {:step :recovery-success
:forward-action :multiaccounts.recover/re-encrypt-pressed :forward-action :multiaccounts.recover/re-encrypt-pressed
:processing? processing?}]]])) :processing? processing?
:existing-account? existing-account?}]]]))

View File

@ -15,8 +15,9 @@
[status-im.ui.screens.privacy-policy.views :as privacy-policy] [status-im.ui.screens.privacy-policy.views :as privacy-policy]
[status-im.react-native.resources :as resources])) [status-im.react-native.resources :as resources]))
(defn multiaccount-view [{:keys [address photo-path name public-key keycard-key-uid]}] (defn multiaccount-view
[react/touchable-highlight {:on-press #(re-frame/dispatch [:multiaccounts.login.ui/multiaccount-selected address photo-path name public-key])} [{:keys [address photo-path name public-key keycard-pairing]}]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:multiaccounts.login.ui/multiaccount-selected address])}
[react/view styles/multiaccount-view [react/view styles/multiaccount-view
[photos/photo photo-path {:size styles/multiaccount-image-size}] [photos/photo photo-path {:size styles/multiaccount-image-size}]
[react/view styles/multiaccount-badge-text-view [react/view styles/multiaccount-badge-text-view
@ -28,7 +29,7 @@
[react/text {:style styles/multiaccount-badge-pub-key-text} [react/text {:style styles/multiaccount-badge-pub-key-text}
(utils/get-shortened-address public-key)]] (utils/get-shortened-address public-key)]]
[react/view {:flex 1}] [react/view {:flex 1}]
(when keycard-key-uid (when keycard-pairing
[react/view {:justify-content :center [react/view {:justify-content :center
:align-items :center :align-items :center
:margin-right 7 :margin-right 7

View File

@ -85,7 +85,7 @@
settings [:multiaccount-settings] settings [:multiaccount-settings]
supported-biometric-auth [:supported-biometric-auth] supported-biometric-auth [:supported-biometric-auth]
auth-method [:auth-method] auth-method [:auth-method]
{:keys [keycard-key-uid]} [:multiaccount]] keycard-multiaccount? [:keycard-multiaccount?]]
(let [show-backup-seed? (and (not seed-backed-up?) (let [show-backup-seed? (and (not seed-backed-up?)
(not (string/blank? mnemonic)))] (not (string/blank? mnemonic)))]
[react/view {:flex 1 :background-color colors/white} [react/view {:flex 1 :background-color colors/white}
@ -93,6 +93,6 @@
(i18n/label :t/privacy-and-security)] (i18n/label :t/privacy-and-security)]
[list/flat-list [list/flat-list
{:data (list-data show-backup-seed? settings supported-biometric-auth {:data (list-data show-backup-seed? settings supported-biometric-auth
(= auth-method "biometric") (boolean keycard-key-uid)) (= auth-method "biometric") keycard-multiaccount?)
:key-fn (fn [_ i] (str i)) :key-fn (fn [_ i] (str i))
:render-fn list/flat-list-generic-render-fn}]]))) :render-fn list/flat-list-generic-render-fn}]])))

View File

@ -218,7 +218,7 @@
preferred-name preferred-name
seed-backed-up? seed-backed-up?
mnemonic mnemonic
keycard-key-uid keycard-pairing
address address
notifications-enabled?] notifications-enabled?]
:as multiaccount} @(re-frame/subscribe [:multiaccount]) :as multiaccount} @(re-frame/subscribe [:multiaccount])
@ -233,7 +233,7 @@
(flat-list-content (flat-list-content
preferred-name registrar tribute-to-talk preferred-name registrar tribute-to-talk
active-contacts-count show-backup-seed? active-contacts-count show-backup-seed?
keycard-key-uid notifications-enabled?) keycard-pairing notifications-enabled?)
list-ref list-ref
scroll-y])) scroll-y]))

View File

@ -55,7 +55,7 @@
:line-height 22 :font-size 13 :line-height 22 :font-size 13
:font-family "monospace" :font-family "monospace"
:color colors/white-transparent-70}} :color colors/white-transparent-70}}
(ethereum/normalized-address address)]] (ethereum/normalized-hex address)]]
[react/view {:position :absolute :top 12 :right 12} [react/view {:position :absolute :top 12 :right 12}
[react/touchable-highlight {:on-press #(re-frame/dispatch [:show-popover {:view :share-account :address address}])} [react/touchable-highlight {:on-press #(re-frame/dispatch [:show-popover {:view :share-account :address address}])}
[icons/icon :main-icons/share {:color colors/white [icons/icon :main-icons/share {:color colors/white

View File

@ -122,14 +122,14 @@
[icons/icon :main-icons/more {:accessibility-label :accounts-more-options}]]]])) [icons/icon :main-icons/more {:accessibility-label :accounts-more-options}]]]]))
(views/defview accounts [] (views/defview accounts []
(views/letsubs [{:keys [accounts keycard-key-uid]} [:multiaccount]] (views/letsubs [{:keys [accounts keycard-pairing]} [:multiaccount]]
[react/scroll-view {:horizontal true} [react/scroll-view {:horizontal true}
[react/view {:flex-direction :row :padding-top 11 :padding-bottom 12} [react/view {:flex-direction :row :padding-top 11 :padding-bottom 12}
(for [account accounts] (for [account accounts]
^{:key account} ^{:key account}
[account-card account]) [account-card account])
; TODO: enable keycard support for adding new accounts ; TODO: enable keycard support for adding new accounts
(when-not keycard-key-uid (when-not keycard-pairing
[add-card])]])) [add-card])]]))
(defn accounts-overview [] (defn accounts-overview []

View File

@ -100,7 +100,7 @@
:render-fn render-token-wrapper}]]])) :render-fn render-token-wrapper}]]]))
(defn- create-payload [address] (defn- create-payload [address]
{:address (ethereum/normalized-address address)}) {:address (ethereum/normalized-hex address)})
(defview settings-hook [] (defview settings-hook []
(letsubs [{:keys [label view on-close]} [:get-screen-params :wallet-settings-hook] (letsubs [{:keys [label view on-close]} [:get-screen-params :wallet-settings-hook]

View File

@ -56,7 +56,7 @@
b58/encode))}))) b58/encode))})))
(defn url [hex] (defn url [hex]
(let [{:keys [namespace hash]} (decode (ethereum/normalized-address hex))] (let [{:keys [namespace hash]} (decode (ethereum/normalized-hex hex))]
(case namespace (case namespace
:ipfs (str "https://ipfs.infura.io/ipfs/" hash) :ipfs (str "https://ipfs.infura.io/ipfs/" hash)
""))) "")))

View File

@ -86,7 +86,7 @@
(defn get-shortened-checksum-address [address] (defn get-shortened-checksum-address [address]
(when address (when address
(get-shortened-address (eip55/address->checksum (ethereum/normalized-address address))))) (get-shortened-address (eip55/address->checksum (ethereum/normalized-hex address)))))
;; debounce, taken from https://github.com/johnswanson/re-frame-debounce-fx ;; debounce, taken from https://github.com/johnswanson/re-frame-debounce-fx
; {:dispatch-debounce {:key :search ; {:dispatch-debounce {:key :search

View File

@ -362,7 +362,7 @@
[{:keys [db] :as cofx} {:keys [to amount from token from-chat? gas gasPrice]}] [{:keys [db] :as cofx} {:keys [to amount from token from-chat? gas gasPrice]}]
(let [{:keys [symbol address]} token (let [{:keys [symbol address]} token
amount-hex (str "0x" (abi-spec/number-to-hex amount)) amount-hex (str "0x" (abi-spec/number-to-hex amount))
to-norm (ethereum/normalized-address (if (string? to) to (:address to))) to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))
from-address (:address from)] from-address (:address from)]
(fx/merge cofx (fx/merge cofx
{:db (dissoc db :wallet/prepare-transaction)} {:db (dissoc db :wallet/prepare-transaction)}
@ -372,7 +372,7 @@
{:to to-norm {:to to-norm
:from from-address :from from-address
:value amount-hex} :value amount-hex}
{:to (ethereum/normalized-address address) {:to (ethereum/normalized-hex address)
:from from-address :from from-address
:data (abi-spec/encode :data (abi-spec/encode
"transfer(address,uint256)" "transfer(address,uint256)"

View File

@ -2,7 +2,7 @@
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead", "_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
"owner": "status-im", "owner": "status-im",
"repo": "status-go", "repo": "status-go",
"version": "v0.35.0", "version": "develop",
"commit-sha1": "2dd74da23d9fcca116e02a2a35d964172c98ffdf", "commit-sha1": "5f6c7008e19227392589a917def8db3780fcc5db",
"src-sha256": "16zb6a5svh7hqm77jnsf5dyrl173mvddd6rxhmvcs6prblg4j7f8" "src-sha256": "0akpf4k7i5rpna0vb2m6lsy7lgsgv19g5lszxhysiacpf37q0hxv"
} }

View File

@ -679,6 +679,8 @@
"mobile-syncing-sheet-details": "Status tends to use a lot of data when syncing chats. You can choose not to sync when on mobile network", "mobile-syncing-sheet-details": "Status tends to use a lot of data when syncing chats. You can choose not to sync when on mobile network",
"mobile-syncing-sheet-title": "Sync using Mobile data", "mobile-syncing-sheet-title": "Sync using Mobile data",
"more": "more", "more": "more",
"multiaccount-exists-title": "Multiaccount already exists",
"multiaccount-exists-content": "This multiaccount already exists. You just need to unlock it",
"multiaccounts-recover-enter-phrase-text": "Enter 12, 15, 18, 21 or 24 words.\nSeparate words by a single space.", "multiaccounts-recover-enter-phrase-text": "Enter 12, 15, 18, 21 or 24 words.\nSeparate words by a single space.",
"multiaccounts-recover-enter-phrase-title": "Enter your seed phrase", "multiaccounts-recover-enter-phrase-title": "Enter your seed phrase",
"name": "Name", "name": "Name",