From a2da4dec6383cbf621e5be96f9507a2675d008fa Mon Sep 17 00:00:00 2001 From: Dmitry Novotochinov Date: Mon, 1 Jul 2019 20:21:44 +0300 Subject: [PATCH] [#8502] recover key to keycard Signed-off-by: Dmitry Novotochinov --- src/status_im/events.cljs | 10 - src/status_im/hardwallet/core.cljs | 78 ++++-- .../ui/screens/hardwallet/setup/subs.cljs | 7 + .../ui/screens/keycard/onboarding/views.cljs | 254 ++++++++++++------ .../ui/screens/routing/intro_login_stack.cljs | 6 +- src/status_im/ui/screens/routing/screens.cljs | 1 + 6 files changed, 240 insertions(+), 116 deletions(-) diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index ccdb17f264..d92bbb8c04 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -282,11 +282,6 @@ ;; accounts recover module -(handlers/register-handler-fx - :accounts.recover.ui/recover-account-button-pressed - (fn [cofx _] - (hardwallet/navigate-to-recover-method cofx))) - (handlers/register-handler-fx :accounts.recover.ui/passphrase-input-changed (fn [cofx [_ recovery-phrase]] @@ -1171,11 +1166,6 @@ {:db (assoc-in db [:hardwallet :setup-step] :begin)} (navigation/navigate-to-cofx :hardwallet-setup nil)))) -(handlers/register-handler-fx - :hardwallet/load-pairing-screen - (fn [cofx _] - (hardwallet/load-pairing-screen cofx))) - (handlers/register-handler-fx :hardwallet/load-generating-mnemonic-screen (fn [cofx _] diff --git a/src/status_im/hardwallet/core.cljs b/src/status_im/hardwallet/core.cljs index 49f77bca68..a14ca5756f 100644 --- a/src/status_im/hardwallet/core.cljs +++ b/src/status_im/hardwallet/core.cljs @@ -302,6 +302,18 @@ (navigation/navigate-to-cofx cofx :keycard-onboarding-recovery-phrase nil) (navigation/navigate-to-cofx cofx :keycard-onboarding-recovery-phrase-confirm-word1 nil))) +(fx/defn proceed-with-generating-key + [{:keys [db] :as cofx}] + (let [pin (or (get-in db [:hardwallet :secrets :pin]) + (vector->string (get-in db [:hardwallet :pin :current])))] + (if (empty? pin) + (fx/merge cofx + {:db (assoc-in db [:hardwallet :pin] {:enter-step :current + :on-verified :hardwallet/generate-and-load-key + :current []})} + (navigation/navigate-to-cofx :keycard-onboarding-pin nil)) + (load-finishing-screen cofx)))) + (fx/defn recovery-phrase-confirm-word-next-pressed {:events [:keycard.onboarding.recovery-phrase-confirm-word.ui/next-pressed :keycard.onboarding.recovery-phrase-confirm-word.ui/input-submitted]} @@ -314,16 +326,7 @@ (fx/merge cofx (recovery-phrase-next-word) (navigation/navigate-to-cofx :keycard-onboarding-recovery-phrase-confirm-word2 nil)) - (let [pin (or (get-in db [:hardwallet :secrets :pin]) - (vector->string (get-in db [:hardwallet :pin :current])))] - (if (empty? pin) - (fx/merge cofx - {:db (-> db - (assoc-in [:hardwallet :pin] {:enter-step :current - :on-verified :hardwallet/generate-and-load-key - :current []}))} - (navigation/navigate-to-cofx :keycard-onboarding-pin nil)) - (load-finishing-screen cofx)))) + (proceed-with-generating-key cofx)) {:db (assoc-in db [:hardwallet :recovery-phrase :confirm-error] (i18n/label :t/wrong-word))}))) (fx/defn recovery-phrase-confirm-word-input-changed @@ -357,7 +360,7 @@ (when (= card-state :blank) (show-no-keycard-applet-alert)) (when (and (= card-state :account) - (= flow :create)) + (#{:create :recovery} flow)) (show-keycard-has-account-alert))) {:db db'}))) @@ -390,14 +393,37 @@ (navigation/navigate-to-cofx :hardwallet-authentication-method nil)) (accounts.create/intro-wizard cofx false))) -(fx/defn navigate-to-recover-method +(fx/defn navigate-to-enter-mnemonic + {:events [:accounts.recover.ui/recover-account-button-pressed]} [{: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)) + {:db (assoc-in db [:hardwallet :flow] :recovery)} + (navigation/navigate-to-cofx :keycard-recovery-enter-mnemonic nil)) (accounts.recover/navigate-to-recover-account-screen cofx))) +(fx/defn recovery-keycard-selected + {:events [:recovery.ui/keycard-option-pressed]} + [{:keys [db] :as cofx}] + (fx/merge cofx + {:db (assoc-in db [:hardwallet :flow] :recovery) + :hardwallet/check-nfc-enabled nil + :hardwallet/register-card-events nil} + (navigation/navigate-to-cofx :keycard-onboarding-intro nil))) + +;NOTE to be removed when Recovery flow will be implemented +(fx/defn enter-mnemonic-next-button-pressed + {:events [:keycard.recovery.enter-mnemonic.ui/input-submitted + :keycard.recovery.enter-mnemonic.ui/next-pressed]} + [cofx] + (recovery-keycard-selected cofx)) + +;NOTE to be removed when Recovery flow will be implemented +(fx/defn enter-mnemonic-input-changed + {:events [:keycard.recovery.enter-mnemonic.ui/input-changed]} + [{:keys [db]} input] + {:db (assoc-in db [:hardwallet :secrets :mnemonic] input)}) + (fx/defn password-option-pressed [{:keys [db] :as cofx}] (if (= (get-in db [:hardwallet :flow]) :create) @@ -591,11 +617,13 @@ (fx/defn keycard-option-pressed {:events [:onboarding.ui/keycard-option-pressed]} - [cofx] - (fx/merge cofx - {:hardwallet/check-nfc-enabled nil - :hardwallet/register-card-events nil} - (navigation/navigate-to-cofx :keycard-onboarding-intro nil))) + [{:keys [db] :as cofx}] + (let [flow (get-in db [:hardwallet :flow] :create)] + (fx/merge cofx + {:db (assoc-in db [:hardwallet :flow] flow) + :hardwallet/check-nfc-enabled nil + :hardwallet/register-card-events nil} + (navigation/navigate-to-cofx :keycard-onboarding-intro nil)))) (fx/defn begin-setup-pressed {:events [:keycard.onboarding.intro.ui/begin-setup-pressed]} @@ -823,8 +851,10 @@ card-connected? (get-in db [:hardwallet :card-connected?])] (fx/merge cofx {:db (assoc-in db [:hardwallet :on-card-connected] :hardwallet/pair)} + (when card-connected? + (pair* password)) (if card-connected? - (pair* password) + (navigation/navigate-to-cofx :keycard-onboarding-pairing nil) (navigation/navigate-to-cofx :keycard-onboarding-connection-lost nil))))) (fx/defn pair-code-next-button-pressed @@ -838,8 +868,7 @@ {:db (-> db (assoc-in [:hardwallet :setup-step] :import-account) (assoc-in [:hardwallet :secrets :paired-on] paired-on))} - (pair)) - (navigation/navigate-to-cofx :keycard-onboarding-pairing nil)))) + (pair))))) (fx/defn return-back-from-nfc-settings [{:keys [db]}] (when (= (:view-id db) @@ -938,6 +967,7 @@ (update-in [:hardwallet :pin] merge {:status nil :error-label nil}))} (when-not (contains? #{:hardwallet/unpair + :hardwallet/generate-and-load-key :hardwallet/remove-key-with-unpair :hardwallet/unpair-and-delete} on-verified) (get-application-info pairing nil)) @@ -1343,7 +1373,7 @@ (assoc-in [:hardwallet :card-state] :init) (assoc-in [:hardwallet :on-card-connected] nil) (assoc-in [:hardwallet :setup-step] :secret-keys) - (assoc-in [:hardwallet :secrets] secrets'))} + (update-in [:hardwallet :secrets] merge secrets'))} (navigation/navigate-to-cofx :keycard-onboarding-puk-code nil)))) (def on-init-card-success on-install-applet-and-init-card-success) @@ -1392,6 +1422,8 @@ (assoc-in [:hardwallet :secrets :paired-on] paired-on))} (when account (set-account-pairing account pairing paired-on)) + (when (= flow :recovery) + (proceed-with-generating-key)) (when (= flow :create) (generate-mnemonic))))) diff --git a/src/status_im/ui/screens/hardwallet/setup/subs.cljs b/src/status_im/ui/screens/hardwallet/setup/subs.cljs index b64d7fb445..06055d4a5c 100644 --- a/src/status_im/ui/screens/hardwallet/setup/subs.cljs +++ b/src/status_im/ui/screens/hardwallet/setup/subs.cljs @@ -16,6 +16,13 @@ (fn [db] (get-in db [:hardwallet :flow]))) +(re-frame/reg-sub + :hardwallet-flow-steps + (fn [db] + (case (get-in db [:hardwallet :flow]) + :recovery "2" + "3"))) + (re-frame/reg-sub :hardwallet-pair-code (fn [db] diff --git a/src/status_im/ui/screens/keycard/onboarding/views.cljs b/src/status_im/ui/screens/keycard/onboarding/views.cljs index 4a5d8b8f0d..e0dbd6dd32 100644 --- a/src/status_im/ui/screens/keycard/onboarding/views.cljs +++ b/src/status_im/ui/screens/keycard/onboarding/views.cljs @@ -66,73 +66,76 @@ [react/text {:style {:color colors/blue}} (i18n/label :t/begin-set-up)]]]]]]) -(defn start [] - [react/view styles/container - [toolbar/toolbar - {:transparent? true - :style {:margin-top 32}} - toolbar/default-nav-back - nil] - [react/scroll-view - [react/view {:flex 1 - :flex-direction :column - :justify-content :space-between - :align-items :center} - [react/view {:flex-direction :column - :align-items :center} - [react/view {:margin-top 16} - [react/text {:style {:typography :header - :text-align :center}} - (i18n/label :t/keycard-onboarding-start-header)]] - [react/view {:margin-top 16 - :width 311} - [react/text {:style {:font-size 15 - :line-height 22 - :color colors/gray - :text-align :center}} - (i18n/label :t/keycard-onboarding-start-text)]] - [react/view {:margin-top 20 - :width "80%"} - (for [[number header text] [["1" - (i18n/label :t/keycard-onboarding-start-step1) - (i18n/label :t/keycard-onboarding-start-step1-text)] - ["2" - (i18n/label :t/keycard-onboarding-start-step2) - (i18n/label :t/keycard-onboarding-start-step2-text)] - ["3" - (i18n/label :t/keycard-onboarding-start-step3) - (i18n/label :t/keycard-onboarding-start-step3-text)]]] - ^{:key number} [react/view {:flex-direction :row - :margin-top 15} - [react/view {:border-width 1 - :border-radius 20 - :border-color colors/gray-light - :align-items :center - :justify-content :center - :width 40 - :height 40} - [react/text {:style {:typography :title}} - number]] - [react/view {:align-items :flex-start - :justify-content :flex-start - :margin-left 11} - [react/view - [react/text {:style {:typography :main-medium}} - header]] - [react/view - [react/text {:style {:color colors/gray - :padding-right 35}} - text]]]])]] - [react/view {:margin-bottom 12 - :align-items :center - :justify-content :center} - [react/image {:source (resources/get-image :keycard-phone) - :resize-mode :center - :style {:width 160 - :height 170}}]]]]]) +(defview start [] + (letsubs [flow [:hardwallet-flow]] + [react/view styles/container + [toolbar/toolbar + {:transparent? true + :style {:margin-top 32}} + toolbar/default-nav-back + nil] + [react/scroll-view + [react/view {:flex 1 + :flex-direction :column + :justify-content :space-between + :align-items :center} + [react/view {:flex-direction :column + :align-items :center} + [react/view {:margin-top 16} + [react/text {:style {:typography :header + :text-align :center}} + (i18n/label :t/keycard-onboarding-start-header)]] + [react/view {:margin-top 16 + :width 311} + [react/text {:style {:color colors/gray + :text-align :center}} + (i18n/label :t/keycard-onboarding-start-text)]] + [react/view {:margin-top 20 + :width "80%"} + (for [[number header text] [["1" + (i18n/label :t/keycard-onboarding-start-step1) + (i18n/label :t/keycard-onboarding-start-step1-text)] + ["2" + (i18n/label :t/keycard-onboarding-start-step2) + (i18n/label :t/keycard-onboarding-start-step2-text)] + (when (not= flow :recovery) + ["3" + (i18n/label :t/keycard-onboarding-start-step3) + (i18n/label :t/keycard-onboarding-start-step3-text)])]] + (when number + ^{:key number} [react/view {:flex-direction :row + :margin-top 15} + [react/view {:border-width 1 + :border-radius 20 + :border-color colors/gray-light + :align-items :center + :justify-content :center + :width 40 + :height 40} + [react/text {:style {:typography :title}} + number]] + [react/view {:align-items :flex-start + :justify-content :flex-start + :margin-left 11} + [react/view + [react/text {:style {:typography :main-medium}} + header]] + [react/view + [react/text {:style {:color colors/gray + :padding-right 35}} + text]]]]))]] + [react/view {:margin-bottom 12 + :margin-top (if (= flow :recovery) 20 0) + :align-items :center + :justify-content :center} + [react/image {:source (resources/get-image :keycard-phone) + :resize-mode :center + :style {:width 160 + :height 170}}]]]]])) (defview puk-code [] - (letsubs [secrets [:hardwallet-secrets]] + (letsubs [secrets [:hardwallet-secrets] + steps [:hardwallet-flow-steps]] [react/view styles/container [toolbar/toolbar {:transparent? true @@ -142,7 +145,8 @@ :style {:padding-left 21}} (i18n/label :t/cancel)] [react/text {:style {:color colors/gray}} - "Step 2 of 3"]] + (i18n/label :t/step-i-of-n {:step "2" + :number steps})]] [react/scroll-view {:content-container-style {:flex-grow 1 :justify-content :space-between}} [react/view {:flex 1 @@ -239,10 +243,8 @@ (i18n/label title-label)]] [react/view {:margin-top 16 :width 311} - [react/text {:style {:font-size 15 - :line-height 22 - :color colors/gray - :text-align :center}} + [react/text {:style {:color colors/gray + :text-align :center}} (i18n/label :t/this-will-take-few-seconds)]]] [react/view {:flex 1 :align-items :center @@ -252,10 +254,8 @@ :style {:width 160 :height 170}}] [react/view {:margin-top 10} - [react/text {:style {:text-align :center - :color colors/gray - :font-size 15 - :line-height 22}} + [react/text {:style {:text-align :center + :color colors/gray}} (i18n/label :t/hold-card)]]]]]) (defn preparing [] @@ -331,7 +331,40 @@ :margin-bottom 30}} (i18n/label :t/open-nfc-settings)]]]]]) -(def pin pin.views/create-pin) +(defview pin [] + (letsubs [pin [:hardwallet/pin] + enter-step [:hardwallet/pin-enter-step] + status [:hardwallet/pin-status] + error-label [:hardwallet/pin-error-label] + steps [:hardwallet-flow-steps]] + [react/view styles/container + [toolbar/toolbar + {:transparent? true + :style {:margin-top 32}} + [toolbar/nav-text + {:handler #(re-frame/dispatch [:keycard.onboarding.ui/cancel-pressed]) + :style {:padding-left 21}} + (i18n/label :t/cancel)] + [react/text {:style {:color colors/gray}} + (i18n/label :t/step-i-of-n {:number steps + :step 1})]] + [react/view {:flex 1 + :flex-direction :column + :justify-content :space-between + :align-items :center} + [react/view {:flex-direction :column + :align-items :center} + [react/view {:margin-top 16} + [react/text {:style {:typography :header + :text-align :center}} + (i18n/label (if (= :original enter-step) + :t/intro-wizard-title4 + :t/intro-wizard-title5))]]] + [status-im.ui.screens.hardwallet.pin.views/pin-view + {:pin pin + :status status + :error-label error-label + :step enter-step}]]])) (defview recovery-phrase [] (letsubs [mnemonic [:hardwallet-mnemonic]] @@ -344,7 +377,8 @@ :style {:padding-left 21}} (i18n/label :t/cancel)] [react/text {:style {:color colors/gray}} - "Step 3 of 3"]] + (i18n/label :t/step-i-of-n {:step "3" + :number "3"})]] [react/scroll-view {:content-container-style {:flex-grow 1 :justify-content :space-between}} [react/view {:flex-direction :column @@ -366,12 +400,13 @@ [react/text {:style {:color colors/blue}} (i18n/label :t/learn-more)]]]]] - [react/view + [react/view {:padding-horizontal 24} [react/view (for [[i row] mnemonic] ^{:key (str "row" i)} - [react/view {:flex-direction :row - :margin-top 12} + [react/view {:flex-direction :row + :justify-content :center + :margin-top 12} (for [[i word] row] ^{:key (str "word" i)} [react/view {:flex-direction :row @@ -413,7 +448,8 @@ :style {:padding-left 21}} (i18n/label :t/cancel)] [react/text {:style {:color colors/gray}} - "Step 3 of 3"]] + (i18n/label :t/step-i-of-n {:step "3" + :number "3"})]] [react/view {:flex 1 :flex-direction :column :justify-content :space-between @@ -474,7 +510,8 @@ :style {:padding-left 21}} (i18n/label :t/cancel)] [react/text {:style {:color colors/gray}} - "Step 3 of 3"]] + (i18n/label :t/step-i-of-n {:step "3" + :number "3"})]] [react/view {:flex 1 :flex-direction :column :justify-content :space-between @@ -514,3 +551,58 @@ :label (i18n/label :t/pair-card) :disabled? (empty? pair-code) :forward? true}]]]]])) + +;NOTE temporary screen, to be removed after Recovery will be implemented +(defview enter-mnemonic [] + (letsubs [mnemonic [:hardwallet-mnemonic]] + [react/view styles/container + [toolbar/toolbar + {:transparent? true + :style {:margin-top 32}} + [toolbar/nav-text + {:handler #(re-frame/dispatch [:keycard.onboarding.ui/cancel-pressed]) + :style {:padding-left 21}} + (i18n/label :t/cancel)] + [react/text {:style {:color colors/gray}} + (i18n/label :t/step-i-of-n {:step "1" + :number "2"})]] + [react/view {:flex 1 + :flex-direction :column + :justify-content :space-between + :align-items :center} + [react/view {:flex-direction :column + :align-items :center} + [react/view {:margin-top 16} + [react/text {:style {:typography :header + :text-align :center}} + "Enter your seed phrase"]] + [react/view {:margin-top 16 + :width "85%" + :align-items :center} + [react/text {:style {:color colors/gray + :text-align :center}} + "Enter your seed phrase, separate the words by single spaces"]]] + [react/view + [text-input/text-input-with-label + {:on-change-text #(re-frame/dispatch [:keycard.recovery.enter-mnemonic.ui/input-changed %]) + :auto-focus true + :on-submit-editing #(re-frame/dispatch [:keycard.recovery.enter-mnemonic.ui/input-submitted]) + :placeholder nil + :height 125 + :multiline true + :auto-correct false + :container {:background-color :white} + :style {:background-color :white + :typography :header}}]] + [react/view {:flex-direction :row + :justify-content :space-between + :align-items :center + :width "100%" + :height 86} + [react/view] + [react/view {:margin-right 20} + [components.common/bottom-button + {:on-press #(re-frame/dispatch [:keycard.recovery.enter-mnemonic.ui/next-pressed]) + :label (i18n/label :t/next) + :disabled? (empty? mnemonic) + :forward? true}]]]]])) diff --git a/src/status_im/ui/screens/routing/intro_login_stack.cljs b/src/status_im/ui/screens/routing/intro_login_stack.cljs index 074c2b31ac..a7502e92f8 100644 --- a/src/status_im/ui/screens/routing/intro_login_stack.cljs +++ b/src/status_im/ui/screens/routing/intro_login_stack.cljs @@ -26,7 +26,8 @@ :keycard-onboarding-nfc-on :keycard-onboarding-recovery-phrase :keycard-onboarding-recovery-phrase-confirm-word1 - :keycard-onboarding-recovery-phrase-confirm-word2}) + :keycard-onboarding-recovery-phrase-confirm-word2 + :keycard-recovery-enter-mnemonic}) (defn login-stack [view-id] {:name :login-stack @@ -66,6 +67,7 @@ :keycard-onboarding-nfc-on :keycard-onboarding-recovery-phrase :keycard-onboarding-recovery-phrase-confirm-word1 - :keycard-onboarding-recovery-phrase-confirm-word2) + :keycard-onboarding-recovery-phrase-confirm-word2 + :keycard-recovery-enter-mnemonic) (assoc :name :intro-stack) (assoc :config {:initialRouteName :intro}))) diff --git a/src/status_im/ui/screens/routing/screens.cljs b/src/status_im/ui/screens/routing/screens.cljs index 89fa4cee4a..976978f32d 100644 --- a/src/status_im/ui/screens/routing/screens.cljs +++ b/src/status_im/ui/screens/routing/screens.cljs @@ -96,6 +96,7 @@ :keycard-onboarding-recovery-phrase keycard.onboarding/recovery-phrase :keycard-onboarding-recovery-phrase-confirm-word1 keycard.onboarding/recovery-phrase-confirm-word :keycard-onboarding-recovery-phrase-confirm-word2 keycard.onboarding/recovery-phrase-confirm-word + :keycard-recovery-enter-mnemonic keycard.onboarding/enter-mnemonic :home home/home-wrapper :chat chat/chat :select-chat chat/select-chat