From 908e80eb0bccfdf6f99bccf0302b5b8d9a6c468d Mon Sep 17 00:00:00 2001 From: Dmitry Novotochinov Date: Mon, 25 Feb 2019 23:01:37 +0300 Subject: [PATCH] [#7216] import account to keycard Signed-off-by: Dmitry Novotochinov --- .env.jenkins | 2 +- mobile_files/package.json.orig | 2 +- mobile_files/yarn.lock | 6 +- src/status_im/accounts/recover/core.cljs | 28 ++- src/status_im/events.cljs | 12 +- src/status_im/hardwallet/core.cljs | 214 +++++++++++------- src/status_im/ui/screens/events.cljs | 1 + .../ui/screens/hardwallet/components.cljs | 2 +- .../ui/screens/hardwallet/settings/subs.cljs | 9 +- .../ui/screens/hardwallet/settings/views.cljs | 2 +- .../ui/screens/hardwallet/setup/subs.cljs | 5 + .../ui/screens/hardwallet/setup/views.cljs | 122 +++++++--- translations/en.json | 2 + 13 files changed, 272 insertions(+), 135 deletions(-) diff --git a/.env.jenkins b/.env.jenkins index 844ab8bba3..c228c3a7e5 100644 --- a/.env.jenkins +++ b/.env.jenkins @@ -17,4 +17,4 @@ POW_TARGET=0.002 POW_TIME=1 RN_BRIDGE_THRESHOLD_WARNINGS=0 RPC_NETWORKS_ONLY=0 -STICKERS_ENABLED=1 \ No newline at end of file +STICKERS_ENABLED=1 diff --git a/mobile_files/package.json.orig b/mobile_files/package.json.orig index a503df1c58..e355309e2c 100644 --- a/mobile_files/package.json.orig +++ b/mobile_files/package.json.orig @@ -53,7 +53,7 @@ "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-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-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", diff --git a/mobile_files/yarn.lock b/mobile_files/yarn.lock index bee9c99dba..ce1e9cb00b 100644 --- a/mobile_files/yarn.lock +++ b/mobile_files/yarn.lock @@ -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" 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": - version "2.3.7" - resolved "git+https://github.com/status-im/react-native-status-keycard.git#9e6df66bfd9288584031cff5455445230059720b" +"react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.3.8": + version "2.3.8" + resolved "git+https://github.com/status-im/react-native-status-keycard.git#e0448b0960a5b4041d2a04dda55bb39e2aa6b191" react-native-svg@6.5.2: version "6.5.2" diff --git a/src/status_im/accounts/recover/core.cljs b/src/status_im/accounts/recover/core.cljs index 81dfee6c1d..5171246210 100644 --- a/src/status_im/accounts/recover/core.cljs +++ b/src/status_im/accounts/recover/core.cljs @@ -11,7 +11,8 @@ [status-im.utils.security :as security] [status-im.utils.types :as types] [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] (cond (string/blank? password) :required-field @@ -67,12 +68,25 @@ (fx/defn validate-recover-result [{:keys [db] :as cofx} {:keys [error pubkey address]} password] (if (empty? error) - (let [account {:pubkey pubkey - :address address - :photo-path (identicon/identicon pubkey) - :mnemonic ""}] - (accounts.create/on-account-created - cofx account password {:seed-backed-up? true})) + (let [account-address (-> address + (str/lower-case) + (str/replace-first "0x" "")) + keycard-account? (boolean (get-in db [:accounts/accounts account-address :keycard-instance-uid]))] + (if keycard-account? + ;; 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 (update :accounts/recover assoc :processing? false diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 0d7202d2af..1315acac3b 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -227,7 +227,7 @@ (handlers/register-handler-fx :accounts.recover.ui/recover-account-button-pressed (fn [cofx _] - (accounts.recover/navigate-to-recover-account-screen cofx))) + (hardwallet/navigate-to-recover-method cofx))) (handlers/register-handler-fx :accounts.recover.ui/passphrase-input-changed @@ -912,8 +912,8 @@ (handlers/register-handler-fx :hardwallet/get-application-info - (fn [_ _] - {:hardwallet/get-application-info nil})) + (fn [cofx _] + (hardwallet/get-application-info cofx nil))) (handlers/register-handler-fx :hardwallet.callback/on-get-application-info-success @@ -1081,7 +1081,7 @@ (handlers/register-handler-fx :hardwallet.ui/password-option-pressed (fn [cofx _] - (accounts.create/navigate-to-create-account-screen cofx))) + (hardwallet/password-option-pressed cofx))) (handlers/register-handler-fx :hardwallet.ui/go-to-settings-button-pressed @@ -1116,7 +1116,7 @@ (handlers/register-handler-fx :hardwallet.ui/recovery-phrase-next-button-pressed (fn [cofx _] - (hardwallet/recovery-phrase-start-confirmation cofx))) + (hardwallet/recovery-phrase-next-button-pressed cofx))) (handlers/register-handler-fx :hardwallet.ui/recovery-phrase-confirm-word-next-button-pressed @@ -1201,7 +1201,7 @@ (handlers/register-handler-fx :hardwallet.ui/card-ready-next-button-pressed (fn [cofx _] - (hardwallet/load-generating-mnemonic-screen cofx))) + (hardwallet/card-ready-next-button-pressed cofx))) (handlers/register-handler-fx :hardwallet/generate-mnemonic diff --git a/src/status_im/hardwallet/core.cljs b/src/status_im/hardwallet/core.cljs index fca08fba9d..1a5c4b09b5 100644 --- a/src/status_im/hardwallet/core.cljs +++ b/src/status_im/hardwallet/core.cljs @@ -12,16 +12,18 @@ [status-im.utils.datetime :as utils.datetime] [status-im.data-store.accounts :as accounts-store] [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") (defn- find-account-by-keycard-instance-uid [db keycard-instance-uid] - (->> (:accounts/accounts db) - vals - (filter #(= keycard-instance-uid (:keycard-instance-uid %))) - first)) + (when keycard-instance-uid + (->> (:accounts/accounts db) + vals + (filter #(= keycard-instance-uid (:keycard-instance-uid %))) + first))) (defn get-pairing ([db] @@ -67,7 +69,8 @@ (fx/defn show-keycard-has-account-alert [{:keys [db] :as 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) :cancel-button-text "" :confirm-button-text :t/okay}} @@ -117,14 +120,16 @@ (fx/defn check-card-state [{:keys [db] :as cofx}] (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 {:db (assoc-in db [:hardwallet :card-state] card-state)} - (when (= card-state :blank) - (show-no-keycard-applet-alert)) - (if (= card-state :account) - (show-keycard-has-account-alert) - (set-setup-step card-state))))) + (when setup-running? + (when (= card-state :blank) + (show-no-keycard-applet-alert)) + (if (= card-state :account) + (show-keycard-has-account-alert) + (set-setup-step card-state)))))) (fx/defn navigate-to-keycard-settings [{:keys [db] :as cofx}] @@ -148,11 +153,27 @@ (unauthorized-operation cofx)))) (fx/defn navigate-to-authentication-method - [cofx] + [{:keys [db] :as 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))) +(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 [{:keys [db]}] {:db (-> db @@ -175,6 +196,12 @@ {:db (assoc-in db [:hardwallet :card-read-in-progress?] false)}) (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]}] {:db (assoc-in db [:hardwallet :setup-step] nil)}) @@ -182,6 +209,58 @@ [{:keys [db]} 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 [{:keys [db]}] {:db (assoc-in db [:hardwallet :on-card-read] nil)}) @@ -195,6 +274,11 @@ (let [info' (js->clj info :keywordize-keys true) {:keys [pin-retry-counter puk-retry-counter]} info' 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) :puk (get-in db [:hardwallet :pin :enter-step]))] @@ -204,8 +288,13 @@ (assoc-in [:hardwallet :application-info] info') (assoc-in [:hardwallet :application-info :applet-installed?] true) (assoc-in [:hardwallet :application-info-error] nil))} + (when auto-login? + (login-with-keycard true)) (when-not connect-screen? (clear-on-card-read)) + (when (and (nil? card-state) + instance-uid) + (check-card-state)) (if (zero? puk-retry-counter) (navigation/navigate-to-cofx :keycard-settings nil) (when on-success @@ -467,8 +556,13 @@ :error-label :t/puk-mismatch :enter-step :puk :puk []})})) -(fx/defn get-application-info [cofx pairing] - {:hardwallet/get-application-info {:pairing pairing}}) +(fx/defn get-application-info + [{: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 [{:keys [db] :as cofx}] @@ -592,18 +686,6 @@ :original [] :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 [{:keys [db] :as cofx}] (fx/merge cofx @@ -670,44 +752,6 @@ (let [{:keys [pairing]} (get-in cofx [:db :hardwallet :secrets])] {: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 [{:keys [db] :as cofx} data] (log/debug "[hardwallet] card connected " data) @@ -716,14 +760,14 @@ setup-running? (boolean setup-step) pin-enter-step (get-in db [:hardwallet :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]) + accounts-screen? (= :accounts (:view-id db)) + auto-login? (and accounts-screen? instance-uid) should-read-instance-uid? (nil? instance-uid) on-card-connected (get-in db [:hardwallet :on-card-connected]) on-card-read (cond - auto-login? :hardwallet/auto-login should-read-instance-uid? :hardwallet/get-application-info + auto-login? :hardwallet/auto-login :else (get-in db [:hardwallet :on-card-read])) pairing (get-pairing db instance-uid)] (fx/merge cofx @@ -762,7 +806,7 @@ (assoc-in [:hardwallet :pin :confirmation] []))}) (fx/defn start-installation - [{:keys [db]}] + [{:keys [db] :as cofx}] (let [card-state (get-in db [:hardwallet :card-state]) pin (vector->string (get-in db [:hardwallet :pin :original]))] (case card-state @@ -778,15 +822,18 @@ (do (log/debug (str "Cannot start keycard installation from state: " card-state)) - {:utils/show-popup {:title (i18n/label :t/error) - :content (i18n/label :t/something-went-wrong)}})))) + (fx/merge cofx + {: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 [{:keys [db]} secrets] (let [secrets' (js->clj secrets :keywordize-keys true)] - {:db (-> db - (assoc-in [:hardwallet :setup-step] :secret-keys) - (assoc-in [:hardwallet :secrets] secrets'))})) + {:hardwallet/get-application-info nil + :db (-> db + (assoc-in [:hardwallet :setup-step] :secret-keys) + (assoc-in [:hardwallet :secrets] secrets'))})) (def on-init-card-success on-install-applet-and-init-card-success) @@ -814,7 +861,7 @@ (let [account' (assoc account :keycard-pairing pairing :keycard-paired-on paired-on)] {:db (-> db - (assoc db :accounts/account account') + (assoc :accounts/account account') (assoc-in [:accounts/accounts address] account')) :data-store/base-tx [(accounts-store/save-account-tx account')]})) @@ -905,6 +952,21 @@ (show-recover-confirmation)) {: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 [{:keys [db] :as cofx}] (let [{:keys [mnemonic pairing]} (get-in db [:hardwallet :secrets]) diff --git a/src/status_im/ui/screens/events.cljs b/src/status_im/ui/screens/events.cljs index fe13e74458..b9b716c5ec 100644 --- a/src/status_im/ui/screens/events.cljs +++ b/src/status_im/ui/screens/events.cljs @@ -178,5 +178,6 @@ :reset-card (hardwallet/reset-card-screen-did-load %) :enter-pin (hardwallet/enter-pin-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 %) nil)))) diff --git a/src/status_im/ui/screens/hardwallet/components.cljs b/src/status_im/ui/screens/hardwallet/components.cljs index 79d5135989..2455daba67 100644 --- a/src/status_im/ui/screens/hardwallet/components.cljs +++ b/src/status_im/ui/screens/hardwallet/components.cljs @@ -49,7 +49,7 @@ :number 4 :next-step :recovery-phrase} :card-ready {:label :t/pairing - :number 5 + :number 4 :next-step :recovery-phrase} :generating-mnemonic {:label :t/recovery-phrase :number 5} diff --git a/src/status_im/ui/screens/hardwallet/settings/subs.cljs b/src/status_im/ui/screens/hardwallet/settings/subs.cljs index 10afee4608..6b8ff69387 100644 --- a/src/status_im/ui/screens/hardwallet/settings/subs.cljs +++ b/src/status_im/ui/screens/hardwallet/settings/subs.cljs @@ -6,9 +6,7 @@ (re-frame/reg-sub :keycard-paired-on (fn [db] - (some-> (or - (get-in db [:hardwallet :secrets :paired-on]) - (get-in db [:account/account :keycard-paired-on])) + (some-> (get-in db [:account/account :keycard-paired-on]) (utils.datetime/timestamp->year-month-day-date)))) (re-frame/reg-sub @@ -16,6 +14,11 @@ (fn [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 :hardwallet/pin-retry-counter (fn [db] diff --git a/src/status_im/ui/screens/hardwallet/settings/views.cljs b/src/status_im/ui/screens/hardwallet/settings/views.cljs index b0f8bb4584..42e060fad7 100644 --- a/src/status_im/ui/screens/hardwallet/settings/views.cljs +++ b/src/status_im/ui/screens/hardwallet/settings/views.cljs @@ -95,7 +95,7 @@ (defview keycard-settings [] (letsubs [paired-on [:keycard-paired-on] puk-retry-counter [:hardwallet/puk-retry-counter] - pairing [:keycard-pairing]] + pairing [:keycard-account-pairing]] [react/view {:flex 1} [status-bar/status-bar] [toolbar/simple-toolbar diff --git a/src/status_im/ui/screens/hardwallet/setup/subs.cljs b/src/status_im/ui/screens/hardwallet/setup/subs.cljs index 4b72534ca2..a885efeff4 100644 --- a/src/status_im/ui/screens/hardwallet/setup/subs.cljs +++ b/src/status_im/ui/screens/hardwallet/setup/subs.cljs @@ -11,6 +11,11 @@ (fn [db] (get-in db [:hardwallet :card-state]))) +(re-frame/reg-sub + :hardwallet-flow + (fn [db] + (get-in db [:hardwallet :flow]))) + (re-frame/reg-sub :hardwallet-pair-code (fn [db] diff --git a/src/status_im/ui/screens/hardwallet/setup/views.cljs b/src/status_im/ui/screens/hardwallet/setup/views.cljs index b005efbe1e..6870abd950 100644 --- a/src/status_im/ui/screens/hardwallet/setup/views.cljs +++ b/src/status_im/ui/screens/hardwallet/setup/views.cljs @@ -1,6 +1,7 @@ (ns status-im.ui.screens.hardwallet.setup.views (:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require [re-frame.core :as re-frame] + [goog.functions :refer [debounce]] [status-im.react-native.js-dependencies :as js-dependencies] [status-im.ui.screens.profile.seed.views :as seed.views] [status-im.ui.screens.hardwallet.components :as components] @@ -16,7 +17,8 @@ [status-im.i18n :as i18n] [status-im.utils.utils :as utils] [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)) @@ -71,24 +73,27 @@ :uppercase? false :forward? true}]]]]])) -(defn card-ready [] - [react/view styles/card-ready-container - [react/view styles/card-ready-inner-container - [react/view (assoc styles/center-container :margin-top 68) - [react/text {:style styles/center-title-text} - (i18n/label :t/card-is-paired)] - [react/text {:style styles/estimated-time-text} - (i18n/label :t/next-step-generating-mnemonic)]] - [react/view] - [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/card-ready-next-button-pressed]) - :uppercase? false - :forward? true}]]]]]) +(defview card-ready [] + (letsubs [flow [:hardwallet-flow]] + [react/view styles/card-ready-container + [react/view styles/card-ready-inner-container + [react/view (assoc styles/center-container :margin-top 68) + [react/text {:style styles/center-title-text} + (i18n/label :t/card-is-paired)] + [react/text {:style styles/estimated-time-text} + (if (= flow :create) + (i18n/label :t/next-step-generating-mnemonic) + (i18n/label :t/next-step-entering-mnemonic))]] + [react/view] + [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/card-ready-next-button-pressed]) + :uppercase? false + :forward? true}]]]]])) -(defview recovery-phrase [] +(defview display-recovery-phrase [] (letsubs [mnemonic [:hardwallet-mnemonic]] (let [mnemonic-vec (vec (map-indexed vector (clojure.string/split mnemonic #" ")))] [react/view styles/card-ready-container @@ -98,21 +103,22 @@ :number-of-lines 2 :font :bold} (i18n/label :t/your-recovery-phrase)] - [react/view {:style {:margin-top 17 - :margin-bottom 16 - :margin-horizontal 16 - :flex-direction :row - :border-radius 8 - :background-color colors/white - :border-width 1 - :border-color colors/gray-lighter}} - [seed.views/six-words (subvec mnemonic-vec 0 6)] - [react/view {:style {:width 1 - :background-color colors/gray-lighter}}] - [seed.views/six-words (subvec mnemonic-vec 6 12)]] - [react/view styles/recovery-phrase-description - [react/text {:style styles/recovery-phrase-description-text} - (i18n/label :t/your-recovery-phrase-description)]]]] + [react/view + [react/view {:style {:margin-top 17 + :margin-bottom 16 + :margin-horizontal 16 + :flex-direction :row + :border-radius 8 + :background-color colors/white + :border-width 1 + :border-color colors/gray-lighter}} + [seed.views/six-words (subvec mnemonic-vec 0 6)] + [react/view {:style {:width 1 + :background-color colors/gray-lighter}}] + [seed.views/six-words (subvec mnemonic-vec 6 12)]] + [react/view styles/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 components.styles/flex] [react/view {:margin-right 20} @@ -161,6 +167,51 @@ :uppercase? false :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 [] (letsubs [pair-code [:hardwallet-pair-code] width [:dimensions/window-width]] @@ -174,9 +225,8 @@ (i18n/label :t/enter-pair-code-description)]] [react/view (styles/enter-pair-code-input-container width) [text-input/text-input-with-label - {:on-change-text #(re-frame/dispatch [:hardwallet.ui/pair-code-input-changed %]) - :secure-text-entry true - :placeholder ""}]]] + {:on-change-text #(re-frame/dispatch [:hardwallet.ui/pair-code-input-changed %]) + :placeholder ""}]]] [react/view styles/next-button-container [react/view components.styles/flex] [react/view {:margin-right 20} diff --git a/translations/en.json b/translations/en.json index c36f0b09fe..7cf1fb2d8b 100644 --- a/translations/en.json +++ b/translations/en.json @@ -776,6 +776,7 @@ "currency-display-name-uah": "Ukraine Hryvnia", "web3-opt-in": "Browser privacy mode", "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-none": "no members", "default-dapps-exchanges": "Exchanges", @@ -830,6 +831,7 @@ "completing-card-setup": "Completing card setup", "generating-mnemonic": "Generating mnemonic phrase", "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", "finishing-card-setup": "Finishing card setup", "finishing-card-setup-steps": "> Loading keys to the card\n> Generating account",