[#7216] import account to keycard

Signed-off-by: Dmitry Novotochinov <dmitry.novot@gmail.com>
This commit is contained in:
Dmitry Novotochinov 2019-02-25 23:01:37 +03:00
parent 4c2054afd4
commit 908e80eb0b
No known key found for this signature in database
GPG Key ID: 43D1DAF5AD39C927
13 changed files with 272 additions and 135 deletions

View File

@ -17,4 +17,4 @@ POW_TARGET=0.002
POW_TIME=1 POW_TIME=1
RN_BRIDGE_THRESHOLD_WARNINGS=0 RN_BRIDGE_THRESHOLD_WARNINGS=0
RPC_NETWORKS_ONLY=0 RPC_NETWORKS_ONLY=0
STICKERS_ENABLED=1 STICKERS_ENABLED=1

View File

@ -53,7 +53,7 @@
"react-native-safe-area-view": "0.9.0", "react-native-safe-area-view": "0.9.0",
"react-native-securerandom": "git+https://github.com/status-im/react-native-securerandom.git#0.1.1-2", "react-native-securerandom": "git+https://github.com/status-im/react-native-securerandom.git#0.1.1-2",
"react-native-splash-screen": "3.1.1", "react-native-splash-screen": "3.1.1",
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.3.7", "react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.3.8",
"react-native-svg": "6.5.2", "react-native-svg": "6.5.2",
"react-native-tcp": "git+https://github.com/status-im/react-native-tcp.git#v3.3.0-1-status", "react-native-tcp": "git+https://github.com/status-im/react-native-tcp.git#v3.3.0-1-status",
"react-native-udp": "git+https://github.com/status-im/react-native-udp.git#2.3.1-1", "react-native-udp": "git+https://github.com/status-im/react-native-udp.git#2.3.1-1",

View File

@ -5845,9 +5845,9 @@ react-native-splash-screen@3.1.1:
resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.1.1.tgz#1a4e46c9fdce53ff52af2a2cb4181788c4e30b30" resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.1.1.tgz#1a4e46c9fdce53ff52af2a2cb4181788c4e30b30"
integrity sha512-PU2YocOSGbLjL9Vgcq/cwMNuHHKNjjuPpa1IPMuWo+6EB/fSZ5VOmxSa7+eucQe3631s3NhGuk3eHKahU03a4Q== integrity sha512-PU2YocOSGbLjL9Vgcq/cwMNuHHKNjjuPpa1IPMuWo+6EB/fSZ5VOmxSa7+eucQe3631s3NhGuk3eHKahU03a4Q==
"react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.3.7": "react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.3.8":
version "2.3.7" version "2.3.8"
resolved "git+https://github.com/status-im/react-native-status-keycard.git#9e6df66bfd9288584031cff5455445230059720b" resolved "git+https://github.com/status-im/react-native-status-keycard.git#e0448b0960a5b4041d2a04dda55bb39e2aa6b191"
react-native-svg@6.5.2: react-native-svg@6.5.2:
version "6.5.2" version "6.5.2"

View File

@ -11,7 +11,8 @@
[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.fx :as fx] [status-im.utils.fx :as fx]
[status-im.node.core :as node])) [status-im.node.core :as node]
[clojure.string :as str]))
(defn check-password-errors [password] (defn check-password-errors [password]
(cond (string/blank? password) :required-field (cond (string/blank? password) :required-field
@ -67,12 +68,25 @@
(fx/defn validate-recover-result (fx/defn validate-recover-result
[{:keys [db] :as cofx} {:keys [error pubkey address]} password] [{:keys [db] :as cofx} {:keys [error pubkey address]} password]
(if (empty? error) (if (empty? error)
(let [account {:pubkey pubkey (let [account-address (-> address
:address address (str/lower-case)
:photo-path (identicon/identicon pubkey) (str/replace-first "0x" ""))
:mnemonic ""}] keycard-account? (boolean (get-in db [:accounts/accounts account-address :keycard-instance-uid]))]
(accounts.create/on-account-created (if keycard-account?
cofx account password {:seed-backed-up? true})) ;; trying to recover account created with keycard
{:db (-> db
(update :accounts/recover assoc
:processing? false
:passphrase-error :recover-keycard-account-not-supported)
(update :accounts/recover dissoc
:passphrase-valid?))
:node/stop nil}
(let [account {:pubkey pubkey
:address address
:photo-path (identicon/identicon pubkey)
:mnemonic ""}]
(accounts.create/on-account-created
cofx account password {:seed-backed-up? true}))))
{:db (-> db {:db (-> db
(update :accounts/recover assoc (update :accounts/recover assoc
:processing? false :processing? false

View File

@ -227,7 +227,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.recover.ui/recover-account-button-pressed :accounts.recover.ui/recover-account-button-pressed
(fn [cofx _] (fn [cofx _]
(accounts.recover/navigate-to-recover-account-screen cofx))) (hardwallet/navigate-to-recover-method cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.recover.ui/passphrase-input-changed :accounts.recover.ui/passphrase-input-changed
@ -912,8 +912,8 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet/get-application-info :hardwallet/get-application-info
(fn [_ _] (fn [cofx _]
{:hardwallet/get-application-info nil})) (hardwallet/get-application-info cofx nil)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.callback/on-get-application-info-success :hardwallet.callback/on-get-application-info-success
@ -1081,7 +1081,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/password-option-pressed :hardwallet.ui/password-option-pressed
(fn [cofx _] (fn [cofx _]
(accounts.create/navigate-to-create-account-screen cofx))) (hardwallet/password-option-pressed cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/go-to-settings-button-pressed :hardwallet.ui/go-to-settings-button-pressed
@ -1116,7 +1116,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/recovery-phrase-next-button-pressed :hardwallet.ui/recovery-phrase-next-button-pressed
(fn [cofx _] (fn [cofx _]
(hardwallet/recovery-phrase-start-confirmation cofx))) (hardwallet/recovery-phrase-next-button-pressed cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/recovery-phrase-confirm-word-next-button-pressed :hardwallet.ui/recovery-phrase-confirm-word-next-button-pressed
@ -1201,7 +1201,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/card-ready-next-button-pressed :hardwallet.ui/card-ready-next-button-pressed
(fn [cofx _] (fn [cofx _]
(hardwallet/load-generating-mnemonic-screen cofx))) (hardwallet/card-ready-next-button-pressed cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet/generate-mnemonic :hardwallet/generate-mnemonic

View File

@ -12,16 +12,18 @@
[status-im.utils.datetime :as utils.datetime] [status-im.utils.datetime :as utils.datetime]
[status-im.data-store.accounts :as accounts-store] [status-im.data-store.accounts :as accounts-store]
[clojure.string :as string] [clojure.string :as string]
[status-im.accounts.login.core :as accounts.login])) [status-im.accounts.login.core :as accounts.login]
[status-im.accounts.recover.core :as accounts.recover]))
(def default-pin "000000") (def default-pin "000000")
(defn- find-account-by-keycard-instance-uid (defn- find-account-by-keycard-instance-uid
[db keycard-instance-uid] [db keycard-instance-uid]
(->> (:accounts/accounts db) (when keycard-instance-uid
vals (->> (:accounts/accounts db)
(filter #(= keycard-instance-uid (:keycard-instance-uid %))) vals
first)) (filter #(= keycard-instance-uid (:keycard-instance-uid %)))
first)))
(defn get-pairing (defn get-pairing
([db] ([db]
@ -67,7 +69,8 @@
(fx/defn show-keycard-has-account-alert (fx/defn show-keycard-has-account-alert
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(fx/merge cofx (fx/merge cofx
{:utils/show-confirmation {:title nil {:db (assoc-in db [:hardwallet :setup-step] nil)
:utils/show-confirmation {:title nil
:content (i18n/label :t/keycard-has-account-on-it) :content (i18n/label :t/keycard-has-account-on-it)
:cancel-button-text "" :cancel-button-text ""
:confirm-button-text :t/okay}} :confirm-button-text :t/okay}}
@ -117,14 +120,16 @@
(fx/defn check-card-state (fx/defn check-card-state
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [app-info (get-in db [:hardwallet :application-info]) (let [app-info (get-in db [:hardwallet :application-info])
card-state (get-card-state app-info)] card-state (get-card-state app-info)
setup-running? (boolean (get-in db [:hardwallet :setup-step]))]
(fx/merge cofx (fx/merge cofx
{:db (assoc-in db [:hardwallet :card-state] card-state)} {:db (assoc-in db [:hardwallet :card-state] card-state)}
(when (= card-state :blank) (when setup-running?
(show-no-keycard-applet-alert)) (when (= card-state :blank)
(if (= card-state :account) (show-no-keycard-applet-alert))
(show-keycard-has-account-alert) (if (= card-state :account)
(set-setup-step card-state))))) (show-keycard-has-account-alert)
(set-setup-step card-state))))))
(fx/defn navigate-to-keycard-settings (fx/defn navigate-to-keycard-settings
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
@ -148,11 +153,27 @@
(unauthorized-operation cofx)))) (unauthorized-operation cofx))))
(fx/defn navigate-to-authentication-method (fx/defn navigate-to-authentication-method
[cofx] [{:keys [db] :as cofx}]
(if (hardwallet-supported? cofx) (if (hardwallet-supported? cofx)
(navigation/navigate-to-cofx cofx :hardwallet-authentication-method nil) (fx/merge cofx
{:db (assoc-in db [:hardwallet :flow] :create)}
(navigation/navigate-to-cofx :hardwallet-authentication-method nil))
(accounts.create/navigate-to-create-account-screen cofx))) (accounts.create/navigate-to-create-account-screen cofx)))
(fx/defn navigate-to-recover-method
[{:keys [db] :as cofx}]
(if (hardwallet-supported? cofx)
(fx/merge cofx
{:db (assoc-in db [:hardwallet :flow] :import)}
(navigation/navigate-to-cofx :hardwallet-authentication-method nil))
(accounts.recover/navigate-to-recover-account-screen cofx)))
(fx/defn password-option-pressed
[{:keys [db] :as cofx}]
(if (= (get-in db [:hardwallet :flow]) :create)
(accounts.create/navigate-to-create-account-screen cofx)
(accounts.recover/navigate-to-recover-account-screen cofx)))
(defn settings-screen-did-load (defn settings-screen-did-load
[{:keys [db]}] [{:keys [db]}]
{:db (-> db {:db (-> db
@ -175,6 +196,12 @@
{:db (assoc-in db [:hardwallet :card-read-in-progress?] false)}) {:db (assoc-in db [:hardwallet :card-read-in-progress?] false)})
(defn accounts-screen-did-load (defn accounts-screen-did-load
[{:keys [db]}]
{:db (-> db
(assoc-in [:hardwallet :setup-step] nil)
(dissoc :accounts/login))})
(defn authentication-method-screen-did-load
[{:keys [db]}] [{:keys [db]}]
{:db (assoc-in db [:hardwallet :setup-step] nil)}) {:db (assoc-in db [:hardwallet :setup-step] nil)})
@ -182,6 +209,58 @@
[{:keys [db]} listeners] [{:keys [db]} listeners]
{:db (update-in db [:hardwallet :listeners] merge listeners)}) {:db (update-in db [:hardwallet :listeners] merge listeners)})
(fx/defn get-keys-from-keycard
[{:keys [db]}]
(let [account-address (get-in db [:accounts/login :address])
pairing (get-in db [:accounts/accounts account-address :keycard-pairing])
pin (string/join (get-in db [:hardwallet :pin :login]))]
(when (and pairing
(not (empty? pin)))
{:db (-> db
(assoc-in [:hardwallet :pin :status] :verifying))
:hardwallet/get-keys {:pairing pairing
:pin pin}})))
(fx/defn login-with-keycard
[{:keys [db] :as cofx} auto-login?]
(let [account-login-address (get-in db [:accounts/login :address])
account-was-manually-selected? account-login-address
account-instance-uid (get-in db [:accounts/accounts account-login-address :keycard-instance-uid])
keycard-instance-uid (get-in db [:hardwallet :application-info :instance-uid])
account (find-account-by-keycard-instance-uid db keycard-instance-uid)
account-mismatch? (if account-was-manually-selected?
(not= account-instance-uid keycard-instance-uid)
(nil? account))
pairing (:keycard-pairing account)]
(cond
(empty? keycard-instance-uid)
(fx/merge cofx
{:utils/show-popup {:title (i18n/label :t/no-account-on-card)
:content (i18n/label :t/no-account-on-card-text)}}
(navigation/navigate-to-cofx :accounts nil))
account-mismatch?
(fx/merge cofx
{:db (dissoc db :accounts/login)
:utils/show-popup {:title (i18n/label (if auto-login? :t/account-not-listed :t/wrong-card))
:content (i18n/label (if auto-login? :t/account-not-listed-text :t/wrong-card-text))}}
(navigation/navigate-to-cofx :accounts nil))
(empty? pairing)
{:utils/show-popup {:title (i18n/label :t/error)
:content (i18n/label :t/no-pairing-on-device)}}
auto-login?
(fx/merge cofx
{:db (-> db
(assoc :accounts/login (select-keys account [:address :name :photo-path]))
(assoc-in [:hardwallet :pin :enter-step] :login))}
(navigation/navigate-to-cofx :enter-pin nil))
:else
(get-keys-from-keycard cofx))))
(fx/defn clear-on-card-read (fx/defn clear-on-card-read
[{:keys [db]}] [{:keys [db]}]
{:db (assoc-in db [:hardwallet :on-card-read] nil)}) {:db (assoc-in db [:hardwallet :on-card-read] nil)})
@ -195,6 +274,11 @@
(let [info' (js->clj info :keywordize-keys true) (let [info' (js->clj info :keywordize-keys true)
{:keys [pin-retry-counter puk-retry-counter]} info' {:keys [pin-retry-counter puk-retry-counter]} info'
connect-screen? (= (:view-id db) :hardwallet-connect) connect-screen? (= (:view-id db) :hardwallet-connect)
card-state (get-in db [:hardwallet :card-state])
instance-uid (get-in db [:hardwallet :application-info :instance-uid])
accounts-screen? (= :accounts (:view-id db))
auto-login? (and accounts-screen?
(not= on-success :hardwallet/auto-login))
enter-step (if (zero? pin-retry-counter) enter-step (if (zero? pin-retry-counter)
:puk :puk
(get-in db [:hardwallet :pin :enter-step]))] (get-in db [:hardwallet :pin :enter-step]))]
@ -204,8 +288,13 @@
(assoc-in [:hardwallet :application-info] info') (assoc-in [:hardwallet :application-info] info')
(assoc-in [:hardwallet :application-info :applet-installed?] true) (assoc-in [:hardwallet :application-info :applet-installed?] true)
(assoc-in [:hardwallet :application-info-error] nil))} (assoc-in [:hardwallet :application-info-error] nil))}
(when auto-login?
(login-with-keycard true))
(when-not connect-screen? (when-not connect-screen?
(clear-on-card-read)) (clear-on-card-read))
(when (and (nil? card-state)
instance-uid)
(check-card-state))
(if (zero? puk-retry-counter) (if (zero? puk-retry-counter)
(navigation/navigate-to-cofx :keycard-settings nil) (navigation/navigate-to-cofx :keycard-settings nil)
(when on-success (when on-success
@ -467,8 +556,13 @@
:error-label :t/puk-mismatch :error-label :t/puk-mismatch
:enter-step :puk :enter-step :puk
:puk []})})) :puk []})}))
(fx/defn get-application-info [cofx pairing] (fx/defn get-application-info
{:hardwallet/get-application-info {:pairing pairing}}) [{:keys [db]} pairing]
(let [instance-uid (get-in db [:hardwallet :application-info :instance-uid])
pairing' (or pairing
(when instance-uid
(get-pairing db instance-uid)))]
{:hardwallet/get-application-info {:pairing pairing'}}))
(fx/defn on-verify-pin-success (fx/defn on-verify-pin-success
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
@ -592,18 +686,6 @@
:original [] :original []
:confirmation []})) :confirmation []}))
(fx/defn get-keys-from-keycard
[{:keys [db]}]
(let [account-address (get-in db [:accounts/login :address])
pairing (get-in db [:accounts/accounts account-address :keycard-pairing])
pin (string/join (get-in db [:hardwallet :pin :login]))]
(when (and pairing
(not (empty? pin)))
{:db (-> db
(assoc-in [:hardwallet :pin :status] :verifying))
:hardwallet/get-keys {:pairing pairing
:pin pin}})))
(fx/defn wait-for-card-tap (fx/defn wait-for-card-tap
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(fx/merge cofx (fx/merge cofx
@ -670,44 +752,6 @@
(let [{:keys [pairing]} (get-in cofx [:db :hardwallet :secrets])] (let [{:keys [pairing]} (get-in cofx [:db :hardwallet :secrets])]
{:hardwallet/generate-mnemonic {:pairing pairing}})) {:hardwallet/generate-mnemonic {:pairing pairing}}))
(defn login-with-keycard
[{:keys [db] :as cofx} auto-login?]
(let [account-login-address (get-in db [:accounts/login :address])
account-was-manually-selected? account-login-address
account-instance-uid (get-in db [:accounts/accounts account-login-address :keycard-instance-uid])
keycard-instance-uid (get-in db [:hardwallet :application-info :instance-uid])
account (find-account-by-keycard-instance-uid db keycard-instance-uid)
account-mismatch? (if account-was-manually-selected?
(not= account-instance-uid keycard-instance-uid)
(nil? account))
pairing (:keycard-pairing account)]
(cond
(empty? keycard-instance-uid)
(fx/merge cofx
{:utils/show-popup {:title (i18n/label :t/no-account-on-card)
:content (i18n/label :t/no-account-on-card-text)}}
(navigation/navigate-to-cofx :accounts nil))
account-mismatch?
(fx/merge cofx
{:db (dissoc db :accounts/login)
:utils/show-popup {:title (i18n/label (if auto-login? :t/account-not-listed :t/wrong-card))
:content (i18n/label (if auto-login? :t/account-not-listed-text :t/wrong-card-text))}}
(navigation/navigate-to-cofx :accounts nil))
(empty? pairing)
{:utils/show-popup {:title (i18n/label :t/error)
:content (i18n/label :t/no-pairing-on-device)}}
auto-login?
(fx/merge cofx
{:db (assoc db :accounts/login (select-keys account [:address :name :photo-path]))}
(navigation/navigate-to-cofx :enter-pin nil))
:else
(get-keys-from-keycard cofx))))
(fx/defn on-card-connected (fx/defn on-card-connected
[{:keys [db] :as cofx} data] [{:keys [db] :as cofx} data]
(log/debug "[hardwallet] card connected " data) (log/debug "[hardwallet] card connected " data)
@ -716,14 +760,14 @@
setup-running? (boolean setup-step) setup-running? (boolean setup-step)
pin-enter-step (get-in db [:hardwallet :pin :enter-step]) pin-enter-step (get-in db [:hardwallet :pin :enter-step])
login? (= :login pin-enter-step) login? (= :login pin-enter-step)
accounts-screen? (= :accounts (:view-id db))
auto-login? accounts-screen?
instance-uid (get-in db [:hardwallet :application-info :instance-uid]) instance-uid (get-in db [:hardwallet :application-info :instance-uid])
accounts-screen? (= :accounts (:view-id db))
auto-login? (and accounts-screen? instance-uid)
should-read-instance-uid? (nil? instance-uid) should-read-instance-uid? (nil? instance-uid)
on-card-connected (get-in db [:hardwallet :on-card-connected]) on-card-connected (get-in db [:hardwallet :on-card-connected])
on-card-read (cond on-card-read (cond
auto-login? :hardwallet/auto-login
should-read-instance-uid? :hardwallet/get-application-info should-read-instance-uid? :hardwallet/get-application-info
auto-login? :hardwallet/auto-login
:else (get-in db [:hardwallet :on-card-read])) :else (get-in db [:hardwallet :on-card-read]))
pairing (get-pairing db instance-uid)] pairing (get-pairing db instance-uid)]
(fx/merge cofx (fx/merge cofx
@ -762,7 +806,7 @@
(assoc-in [:hardwallet :pin :confirmation] []))}) (assoc-in [:hardwallet :pin :confirmation] []))})
(fx/defn start-installation (fx/defn start-installation
[{:keys [db]}] [{:keys [db] :as cofx}]
(let [card-state (get-in db [:hardwallet :card-state]) (let [card-state (get-in db [:hardwallet :card-state])
pin (vector->string (get-in db [:hardwallet :pin :original]))] pin (vector->string (get-in db [:hardwallet :pin :original]))]
(case card-state (case card-state
@ -778,15 +822,18 @@
(do (do
(log/debug (str "Cannot start keycard installation from state: " card-state)) (log/debug (str "Cannot start keycard installation from state: " card-state))
{:utils/show-popup {:title (i18n/label :t/error) (fx/merge cofx
:content (i18n/label :t/something-went-wrong)}})))) {:utils/show-popup {:title (i18n/label :t/error)
:content (i18n/label :t/something-went-wrong)}}
(navigation/navigate-to-cofx :hardwallet-authentication-method nil))))))
(fx/defn on-install-applet-and-init-card-success (fx/defn on-install-applet-and-init-card-success
[{:keys [db]} secrets] [{:keys [db]} secrets]
(let [secrets' (js->clj secrets :keywordize-keys true)] (let [secrets' (js->clj secrets :keywordize-keys true)]
{:db (-> db {:hardwallet/get-application-info nil
(assoc-in [:hardwallet :setup-step] :secret-keys) :db (-> db
(assoc-in [:hardwallet :secrets] secrets'))})) (assoc-in [:hardwallet :setup-step] :secret-keys)
(assoc-in [:hardwallet :secrets] secrets'))}))
(def on-init-card-success on-install-applet-and-init-card-success) (def on-init-card-success on-install-applet-and-init-card-success)
@ -814,7 +861,7 @@
(let [account' (assoc account :keycard-pairing pairing (let [account' (assoc account :keycard-pairing pairing
:keycard-paired-on paired-on)] :keycard-paired-on paired-on)]
{:db (-> db {:db (-> db
(assoc db :accounts/account account') (assoc :accounts/account account')
(assoc-in [:accounts/accounts address] account')) (assoc-in [:accounts/accounts address] account'))
:data-store/base-tx [(accounts-store/save-account-tx account')]})) :data-store/base-tx [(accounts-store/save-account-tx account')]}))
@ -905,6 +952,21 @@
(show-recover-confirmation)) (show-recover-confirmation))
{:db (assoc-in db [:hardwallet :recovery-phrase :confirm-error] (i18n/label :t/wrong-word))}))) {:db (assoc-in db [:hardwallet :recovery-phrase :confirm-error] (i18n/label :t/wrong-word))})))
(fx/defn card-ready-next-button-pressed
[{:keys [db] :as cofx}]
(if (= (get-in db [:hardwallet :flow]) :create)
(load-generating-mnemonic-screen cofx)
{:db (assoc-in db [:hardwallet :setup-step] :recovery-phrase)}))
(fx/defn recovery-phrase-next-button-pressed
[{:keys [db] :as cofx}]
(if (= (get-in db [:hardwallet :flow]) :create)
(recovery-phrase-start-confirmation cofx)
(let [mnemonic (get-in db [:accounts/recover :passphrase])]
(fx/merge cofx
{:db (assoc-in db [:hardwallet :secrets :mnemonic] mnemonic)}
(load-loading-keys-screen)))))
(fx/defn generate-and-load-key (fx/defn generate-and-load-key
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [{:keys [mnemonic pairing]} (get-in db [:hardwallet :secrets]) (let [{:keys [mnemonic pairing]} (get-in db [:hardwallet :secrets])

View File

@ -178,5 +178,6 @@
:reset-card (hardwallet/reset-card-screen-did-load %) :reset-card (hardwallet/reset-card-screen-did-load %)
:enter-pin (hardwallet/enter-pin-screen-did-load %) :enter-pin (hardwallet/enter-pin-screen-did-load %)
:hardwallet-connect (hardwallet/hardwallet-connect-screen-did-load %) :hardwallet-connect (hardwallet/hardwallet-connect-screen-did-load %)
:hardwallet-authentication-method (hardwallet/authentication-method-screen-did-load %)
:accounts (hardwallet/accounts-screen-did-load %) :accounts (hardwallet/accounts-screen-did-load %)
nil)))) nil))))

View File

@ -49,7 +49,7 @@
:number 4 :number 4
:next-step :recovery-phrase} :next-step :recovery-phrase}
:card-ready {:label :t/pairing :card-ready {:label :t/pairing
:number 5 :number 4
:next-step :recovery-phrase} :next-step :recovery-phrase}
:generating-mnemonic {:label :t/recovery-phrase :generating-mnemonic {:label :t/recovery-phrase
:number 5} :number 5}

View File

@ -6,9 +6,7 @@
(re-frame/reg-sub (re-frame/reg-sub
:keycard-paired-on :keycard-paired-on
(fn [db] (fn [db]
(some-> (or (some-> (get-in db [:account/account :keycard-paired-on])
(get-in db [:hardwallet :secrets :paired-on])
(get-in db [:account/account :keycard-paired-on]))
(utils.datetime/timestamp->year-month-day-date)))) (utils.datetime/timestamp->year-month-day-date))))
(re-frame/reg-sub (re-frame/reg-sub
@ -16,6 +14,11 @@
(fn [db] (fn [db]
(core/get-pairing db))) (core/get-pairing db)))
(re-frame/reg-sub
:keycard-account-pairing
(fn [db]
(get-in db [:account/account :keycard-pairing])))
(re-frame/reg-sub (re-frame/reg-sub
:hardwallet/pin-retry-counter :hardwallet/pin-retry-counter
(fn [db] (fn [db]

View File

@ -95,7 +95,7 @@
(defview keycard-settings [] (defview keycard-settings []
(letsubs [paired-on [:keycard-paired-on] (letsubs [paired-on [:keycard-paired-on]
puk-retry-counter [:hardwallet/puk-retry-counter] puk-retry-counter [:hardwallet/puk-retry-counter]
pairing [:keycard-pairing]] pairing [:keycard-account-pairing]]
[react/view {:flex 1} [react/view {:flex 1}
[status-bar/status-bar] [status-bar/status-bar]
[toolbar/simple-toolbar [toolbar/simple-toolbar

View File

@ -11,6 +11,11 @@
(fn [db] (fn [db]
(get-in db [:hardwallet :card-state]))) (get-in db [:hardwallet :card-state])))
(re-frame/reg-sub
:hardwallet-flow
(fn [db]
(get-in db [:hardwallet :flow])))
(re-frame/reg-sub (re-frame/reg-sub
:hardwallet-pair-code :hardwallet-pair-code
(fn [db] (fn [db]

View File

@ -1,6 +1,7 @@
(ns status-im.ui.screens.hardwallet.setup.views (ns status-im.ui.screens.hardwallet.setup.views
(:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[goog.functions :refer [debounce]]
[status-im.react-native.js-dependencies :as js-dependencies] [status-im.react-native.js-dependencies :as js-dependencies]
[status-im.ui.screens.profile.seed.views :as seed.views] [status-im.ui.screens.profile.seed.views :as seed.views]
[status-im.ui.screens.hardwallet.components :as components] [status-im.ui.screens.hardwallet.components :as components]
@ -16,7 +17,8 @@
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[status-im.ui.components.colors :as colors] [status-im.ui.components.colors :as colors]
[status-im.ui.screens.hardwallet.setup.styles :as styles])) [status-im.ui.screens.hardwallet.setup.styles :as styles]
[status-im.utils.security :as security]))
(defonce event-emitter (.-DeviceEventEmitter js-dependencies/react-native)) (defonce event-emitter (.-DeviceEventEmitter js-dependencies/react-native))
@ -71,24 +73,27 @@
:uppercase? false :uppercase? false
:forward? true}]]]]])) :forward? true}]]]]]))
(defn card-ready [] (defview card-ready []
[react/view styles/card-ready-container (letsubs [flow [:hardwallet-flow]]
[react/view styles/card-ready-inner-container [react/view styles/card-ready-container
[react/view (assoc styles/center-container :margin-top 68) [react/view styles/card-ready-inner-container
[react/text {:style styles/center-title-text} [react/view (assoc styles/center-container :margin-top 68)
(i18n/label :t/card-is-paired)] [react/text {:style styles/center-title-text}
[react/text {:style styles/estimated-time-text} (i18n/label :t/card-is-paired)]
(i18n/label :t/next-step-generating-mnemonic)]] [react/text {:style styles/estimated-time-text}
[react/view] (if (= flow :create)
[react/view styles/next-button-container (i18n/label :t/next-step-generating-mnemonic)
[react/view components.styles/flex] (i18n/label :t/next-step-entering-mnemonic))]]
[react/view {:margin-right 20} [react/view]
[components.common/bottom-button [react/view styles/next-button-container
{:on-press #(re-frame/dispatch [:hardwallet.ui/card-ready-next-button-pressed]) [react/view components.styles/flex]
:uppercase? false [react/view {:margin-right 20}
:forward? true}]]]]]) [components.common/bottom-button
{:on-press #(re-frame/dispatch [:hardwallet.ui/card-ready-next-button-pressed])
:uppercase? false
:forward? true}]]]]]))
(defview recovery-phrase [] (defview display-recovery-phrase []
(letsubs [mnemonic [:hardwallet-mnemonic]] (letsubs [mnemonic [:hardwallet-mnemonic]]
(let [mnemonic-vec (vec (map-indexed vector (clojure.string/split mnemonic #" ")))] (let [mnemonic-vec (vec (map-indexed vector (clojure.string/split mnemonic #" ")))]
[react/view styles/card-ready-container [react/view styles/card-ready-container
@ -98,21 +103,22 @@
:number-of-lines 2 :number-of-lines 2
:font :bold} :font :bold}
(i18n/label :t/your-recovery-phrase)] (i18n/label :t/your-recovery-phrase)]
[react/view {:style {:margin-top 17 [react/view
:margin-bottom 16 [react/view {:style {:margin-top 17
:margin-horizontal 16 :margin-bottom 16
:flex-direction :row :margin-horizontal 16
:border-radius 8 :flex-direction :row
:background-color colors/white :border-radius 8
:border-width 1 :background-color colors/white
:border-color colors/gray-lighter}} :border-width 1
[seed.views/six-words (subvec mnemonic-vec 0 6)] :border-color colors/gray-lighter}}
[react/view {:style {:width 1 [seed.views/six-words (subvec mnemonic-vec 0 6)]
:background-color colors/gray-lighter}}] [react/view {:style {:width 1
[seed.views/six-words (subvec mnemonic-vec 6 12)]] :background-color colors/gray-lighter}}]
[react/view styles/recovery-phrase-description [seed.views/six-words (subvec mnemonic-vec 6 12)]]
[react/text {:style styles/recovery-phrase-description-text} [react/view styles/recovery-phrase-description
(i18n/label :t/your-recovery-phrase-description)]]]] [react/text {:style styles/recovery-phrase-description-text}
(i18n/label :t/your-recovery-phrase-description)]]]]]
[react/view styles/next-button-container [react/view styles/next-button-container
[react/view components.styles/flex] [react/view components.styles/flex]
[react/view {:margin-right 20} [react/view {:margin-right 20}
@ -161,6 +167,51 @@
:uppercase? false :uppercase? false
:forward? true}]]]))) :forward? true}]]])))
(defview enter-recovery-phrase []
(letsubs [width [:dimensions/window-width]
recovered-account [:get-recover-account]]
(let [{:keys [passphrase passphrase-valid? passphrase-error passphrase-warning]} recovered-account
disabled? (not passphrase-valid?)
validate-passphrase (debounce
#(re-frame/dispatch [:accounts.recover.ui/passphrase-input-blured])
1000)]
[react/view styles/enter-pair-code-container
[react/view styles/enter-pair-code-title-container
[react/view
[react/text {:style styles/center-title-text
:number-of-lines 2}
(i18n/label :t/your-recovery-phrase)]
[react/view (styles/enter-pair-code-input-container width)
[text-input/text-input-with-label
{:style {:flex 1
:text-align-vertical :top}
:height 92
:accessibility-label :enter-12-words
:placeholder (i18n/label :t/enter-12-words)
:multiline true
:default-value passphrase
:auto-correct false
:on-change-text #(do
(re-frame/dispatch [:accounts.recover.ui/passphrase-input-changed (security/mask-data %)])
(validate-passphrase))
:error (cond passphrase-error (i18n/label passphrase-error)
passphrase-warning (i18n/label passphrase-warning))}]]]]
[react/view styles/next-button-container
[react/view components.styles/flex]
[react/view {:margin-right 20}
[components.common/bottom-button
{:on-press #(re-frame/dispatch [:hardwallet.ui/recovery-phrase-next-button-pressed])
:label (i18n/label :t/next)
:disabled? disabled?
:uppercase? false
:forward? true}]]]])))
(defview recovery-phrase []
(letsubs [flow [:hardwallet-flow]]
(if (= flow :create)
(display-recovery-phrase)
(enter-recovery-phrase))))
(defview enter-pair-code [] (defview enter-pair-code []
(letsubs [pair-code [:hardwallet-pair-code] (letsubs [pair-code [:hardwallet-pair-code]
width [:dimensions/window-width]] width [:dimensions/window-width]]
@ -174,9 +225,8 @@
(i18n/label :t/enter-pair-code-description)]] (i18n/label :t/enter-pair-code-description)]]
[react/view (styles/enter-pair-code-input-container width) [react/view (styles/enter-pair-code-input-container width)
[text-input/text-input-with-label [text-input/text-input-with-label
{:on-change-text #(re-frame/dispatch [:hardwallet.ui/pair-code-input-changed %]) {:on-change-text #(re-frame/dispatch [:hardwallet.ui/pair-code-input-changed %])
:secure-text-entry true :placeholder ""}]]]
:placeholder ""}]]]
[react/view styles/next-button-container [react/view styles/next-button-container
[react/view components.styles/flex] [react/view components.styles/flex]
[react/view {:margin-right 20} [react/view {:margin-right 20}

View File

@ -776,6 +776,7 @@
"currency-display-name-uah": "Ukraine Hryvnia", "currency-display-name-uah": "Ukraine Hryvnia",
"web3-opt-in": "Browser privacy mode", "web3-opt-in": "Browser privacy mode",
"recover-password-invalid": "This account already exists but passwords do not match", "recover-password-invalid": "This account already exists but passwords do not match",
"recover-keycard-account-not-supported": "Recovering keycard account with password is not supported",
"members-active-none": "no members", "members-active-none": "no members",
"members-none": "no members", "members-none": "no members",
"default-dapps-exchanges": "Exchanges", "default-dapps-exchanges": "Exchanges",
@ -830,6 +831,7 @@
"completing-card-setup": "Completing card setup", "completing-card-setup": "Completing card setup",
"generating-mnemonic": "Generating mnemonic phrase", "generating-mnemonic": "Generating mnemonic phrase",
"next-step-generating-mnemonic": "Next step is generating mnemonic phrase for your card", "next-step-generating-mnemonic": "Next step is generating mnemonic phrase for your card",
"next-step-entering-mnemonic": "Next step is entering mnemonic phrase to import your account",
"this-will-take-few-seconds": "This will take a few seconds", "this-will-take-few-seconds": "This will take a few seconds",
"finishing-card-setup": "Finishing card setup", "finishing-card-setup": "Finishing card setup",
"finishing-card-setup-steps": "> Loading keys to the card\n> Generating account", "finishing-card-setup-steps": "> Loading keys to the card\n> Generating account",