diff --git a/src/status_im/contexts/onboarding/enter_seed_phrase/style.cljs b/src/status_im/common/enter_seed_phrase/style.cljs similarity index 92% rename from src/status_im/contexts/onboarding/enter_seed_phrase/style.cljs rename to src/status_im/common/enter_seed_phrase/style.cljs index c0087bfaa0..1fb6a9b471 100644 --- a/src/status_im/contexts/onboarding/enter_seed_phrase/style.cljs +++ b/src/status_im/common/enter_seed_phrase/style.cljs @@ -1,4 +1,4 @@ -(ns status-im.contexts.onboarding.enter-seed-phrase.style +(ns status-im.common.enter-seed-phrase.style (:require [react-native.safe-area :as safe-area])) diff --git a/src/status_im/contexts/onboarding/enter_seed_phrase/view.cljs b/src/status_im/common/enter_seed_phrase/view.cljs similarity index 83% rename from src/status_im/contexts/onboarding/enter_seed_phrase/view.cljs rename to src/status_im/common/enter_seed_phrase/view.cljs index bdb6ed9033..613250a7f1 100644 --- a/src/status_im/contexts/onboarding/enter_seed_phrase/view.cljs +++ b/src/status_im/common/enter_seed_phrase/view.cljs @@ -1,4 +1,4 @@ -(ns status-im.contexts.onboarding.enter-seed-phrase.view +(ns status-im.common.enter-seed-phrase.view (:require [clojure.string :as string] [legacy.status-im.ethereum.mnemonic :as mnemonic] @@ -7,8 +7,8 @@ [react-native.core :as rn] [react-native.safe-area :as safe-area] [reagent.core :as reagent] + [status-im.common.enter-seed-phrase.style :as style] [status-im.constants :as constants] - [status-im.contexts.onboarding.enter-seed-phrase.style :as style] [utils.i18n :as i18n] [utils.re-frame :as rf] [utils.security.core :as security])) @@ -86,7 +86,7 @@ (take 7))) (defn screen - [] + [recovering-keypair?] (reagent/with-let [keyboard-shown? (reagent/atom false) keyboard-show-listener (.addListener rn/keyboard "keyboardDidShow" @@ -103,9 +103,14 @@ (reset! seed-phrase new-phrase)) on-submit (fn [] (swap! seed-phrase clean-seed-phrase) - (rf/dispatch [:onboarding/seed-phrase-entered - (security/mask-data @seed-phrase) - set-invalid-seed-phrase]))] + (if recovering-keypair? + (rf/dispatch [:wallet/seed-phrase-entered + (security/mask-data + @seed-phrase) + set-invalid-seed-phrase]) + (rf/dispatch [:onboarding/seed-phrase-entered + (security/mask-data @seed-phrase) + set-invalid-seed-phrase])))] (let [words-coll (mnemonic/passphrase->words @seed-phrase) last-word (peek words-coll) pick-suggested-word (fn [pressed-word] @@ -147,7 +152,7 @@ [rn/view {:style style/keyboard-container} [quo/predictive-keyboard {:type suggestions-state - :blur? true + :blur? (not recovering-keypair?) :text suggestions-text :words (keyboard-suggestions last-word) :on-press pick-suggested-word}]])]) @@ -155,14 +160,16 @@ (.remove keyboard-show-listener) (.remove keyboard-hide-listener)))) -(defn enter-seed-phrase +(defn view [] (let [{navigation-bar-top :top} (safe-area/get-insets)] - [rn/view {:style style/full-layout} - [rn/keyboard-avoiding-view {:style style/page-container} - [quo/page-nav - {:margin-top navigation-bar-top - :background :blur - :icon-name :i/arrow-left - :on-press #(rf/dispatch [:navigate-back])}] - [screen]]])) + (fn [] + (let [{:keys [recovering-keypair?]} (rf/sub [:get-screen-params])] + [rn/view {:style style/full-layout} + [rn/keyboard-avoiding-view {:style style/page-container} + [quo/page-nav + {:margin-top navigation-bar-top + :background :blur + :icon-name (if recovering-keypair? :i/close :i/arrow-left) + :on-press #(rf/dispatch [:navigate-back])}] + [screen recovering-keypair?]]])))) diff --git a/src/status_im/contexts/wallet/add_account/create_account/events.cljs b/src/status_im/contexts/wallet/add_account/create_account/events.cljs index 3f4d912e8c..9c25e72aec 100644 --- a/src/status_im/contexts/wallet/add_account/create_account/events.cljs +++ b/src/status_im/contexts/wallet/add_account/create_account/events.cljs @@ -2,6 +2,7 @@ (:require [camel-snake-kebab.extras :as cske] [status-im.contexts.wallet.data-store :as data-store] [utils.re-frame :as rf] + [utils.security.core :as security] [utils.transforms :as transforms])) (defn get-keypairs-success @@ -21,14 +22,32 @@ (rf/reg-event-fx :wallet/confirm-account-origin confirm-account-origin) -(defn store-secret-phrase - [{:keys [db]} [{:keys [secret-phrase random-phrase]}]] +(defn store-seed-phrase + [{:keys [db]} [{:keys [seed-phrase random-phrase]}]] {:db (-> db - (assoc-in [:wallet :ui :create-account :secret-phrase] secret-phrase) + (assoc-in [:wallet :ui :create-account :seed-phrase] seed-phrase) (assoc-in [:wallet :ui :create-account :random-phrase] random-phrase)) :fx [[:dispatch-later [{:ms 20 :dispatch [:navigate-to :screen/wallet.check-your-backup]}]]]}) -(rf/reg-event-fx :wallet/store-secret-phrase store-secret-phrase) +(rf/reg-event-fx :wallet/store-seed-phrase store-seed-phrase) + +(defn seed-phrase-validated + [{:keys [db]} [seed-phrase]] + {:db (assoc-in db [:wallet :ui :create-account :seed-phrase] seed-phrase) + :fx [[:dispatch [:navigate-to :screen/wallet.keypair-name]]]}) + +(rf/reg-event-fx :wallet/seed-phrase-validated seed-phrase-validated) + +(defn seed-phrase-entered + [_ [seed-phrase on-error]] + {:fx [[:multiaccount/validate-mnemonic + [seed-phrase + (fn [mnemonic key-uid] + (rf/dispatch [:wallet/seed-phrase-validated + mnemonic key-uid])) + on-error]]]}) + +(rf/reg-event-fx :wallet/seed-phrase-entered seed-phrase-entered) (defn new-keypair-created [{:keys [db]} [{:keys [new-keypair]}]] @@ -39,10 +58,10 @@ (defn new-keypair-continue [{:keys [db]} [{:keys [keypair-name]}]] - (let [secret-phrase (get-in db [:wallet :ui :create-account :secret-phrase])] + (let [seed-phrase (get-in db [:wallet :ui :create-account :seed-phrase])] {:fx [[:effects.wallet/create-account-from-mnemonic - {:secret-phrase secret-phrase - :keypair-name keypair-name}]]})) + {:seed-phrase (security/safe-unmask-data seed-phrase) + :keypair-name keypair-name}]]})) (rf/reg-event-fx :wallet/new-keypair-continue new-keypair-continue) diff --git a/src/status_im/contexts/wallet/add_account/create_account/events_test.cljs b/src/status_im/contexts/wallet/add_account/create_account/events_test.cljs index b1d9b9647c..3e124d8686 100644 --- a/src/status_im/contexts/wallet/add_account/create_account/events_test.cljs +++ b/src/status_im/contexts/wallet/add_account/create_account/events_test.cljs @@ -12,12 +12,12 @@ result-db (:db effects)] (is (match? result-db expected-db)))) -(deftest store-secret-phrase +(deftest store-seed-phrase (let [db {} - props [{:secret-phrase "test-secret" :random-phrase "random-test"}] - expected-db {:wallet {:ui {:create-account {:secret-phrase "test-secret" + props [{:seed-phrase "test-secret" :random-phrase "random-test"}] + expected-db {:wallet {:ui {:create-account {:seed-phrase "test-secret" :random-phrase "random-test"}}}} - effects (events/store-secret-phrase {:db db} props) + effects (events/store-seed-phrase {:db db} props) result-db (:db effects)] (is (match? result-db expected-db)))) @@ -30,10 +30,10 @@ (is (match? result-db expected-db)))) (deftest new-keypair-continue - (let [db {:wallet {:ui {:create-account {:secret-phrase "test-secret"}}}} + (let [db {:wallet {:ui {:create-account {:seed-phrase "test-secret"}}}} props [{:keypair-name "test-keypair"}] expected-effects [[:effects.wallet/create-account-from-mnemonic - {:secret-phrase "test-secret" :keypair-name "test-keypair"}]] + {:seed-phrase "test-secret" :keypair-name "test-keypair"}]] effects (events/new-keypair-continue {:db db} props)] (is (match? effects {:fx expected-effects})))) diff --git a/src/status_im/contexts/wallet/add_account/create_account/new_keypair/backup_recovery_phrase/view.cljs b/src/status_im/contexts/wallet/add_account/create_account/new_keypair/backup_recovery_phrase/view.cljs index ce0a8522ad..450366d251 100644 --- a/src/status_im/contexts/wallet/add_account/create_account/new_keypair/backup_recovery_phrase/view.cljs +++ b/src/status_im/contexts/wallet/add_account/create_account/new_keypair/backup_recovery_phrase/view.cljs @@ -10,7 +10,8 @@ [status-im.contexts.wallet.add-account.create-account.new-keypair.backup-recovery-phrase.style :as style] [utils.i18n :as i18n] - [utils.re-frame :as rf])) + [utils.re-frame :as rf] + [utils.security.core :as security])) (defn- word-item [item index _ increment] @@ -54,14 +55,14 @@ :3 false}) revealed? (reagent/atom false) customization-color (rf/sub [:profile/customization-color]) - secret-phrase (reagent/atom []) + seed-phrase (reagent/atom []) random-phrase (reagent/atom [])] (fn [] (let [theme (quo.theme/use-theme)] (rn/use-mount (fn [] - (native-module/get-random-mnemonic #(reset! secret-phrase (string/split % #"\s"))) + (native-module/get-random-mnemonic #(reset! seed-phrase (string/split % #"\s"))) (native-module/get-random-mnemonic #(reset! random-phrase (string/split % #"\s"))))) [rn/view {:style {:flex 1}} [quo/page-nav @@ -74,14 +75,14 @@ :description-text (i18n/label :t/backup-recovery-phrase-description) :container-style {:padding-bottom 8}}] [rn/view {:style (style/seed-phrase-container theme)} - (when (pos? (count @secret-phrase)) + (when (pos? (count @seed-phrase)) [:<> [words-column - {:words @secret-phrase + {:words @seed-phrase :first-half? true}] [rn/view {:style (style/separator theme)}] [words-column - {:words @secret-phrase + {:words @seed-phrase :first-half? false}]]) (when-not @revealed? [rn/view {:style style/blur-container} @@ -107,8 +108,9 @@ :button-one-label (i18n/label :t/i-have-written) :button-one-props {:disabled? (some false? (vals @checked?)) :customization-color customization-color - :on-press #(rf/dispatch [:wallet/store-secret-phrase - {:secret-phrase @secret-phrase + :on-press #(rf/dispatch [:wallet/store-seed-phrase + {:seed-phrase (security/mask-data + @seed-phrase) :random-phrase @random-phrase}])}}] [quo/text {:size :paragraph-2 diff --git a/src/status_im/contexts/wallet/add_account/create_account/new_keypair/check_your_backup/view.cljs b/src/status_im/contexts/wallet/add_account/create_account/new_keypair/check_your_backup/view.cljs index acf6eb08a5..be3c382074 100644 --- a/src/status_im/contexts/wallet/add_account/create_account/new_keypair/check_your_backup/view.cljs +++ b/src/status_im/contexts/wallet/add_account/create_account/new_keypair/check_your_backup/view.cljs @@ -5,7 +5,8 @@ [reagent.core :as reagent] [status-im.contexts.wallet.add-account.create-account.new-keypair.check-your-backup.style :as style] [utils.i18n :as i18n] - [utils.re-frame :as rf])) + [utils.re-frame :as rf] + [utils.security.core :as security])) (def secret-words-count 12) @@ -60,15 +61,16 @@ (defn view [] - (let [random-indices (random-selection) - quiz-index (reagent/atom 0) - incorrect-count (reagent/atom 0) - show-error? (reagent/atom false) - {:keys [secret-phrase random-phrase]} (rf/sub [:wallet/create-account])] + (let [random-indices (random-selection) + quiz-index (reagent/atom 0) + incorrect-count (reagent/atom 0) + show-error? (reagent/atom false) + {:keys [seed-phrase random-phrase]} (rf/sub [:wallet/create-account]) + unmasked-seed-phrase (security/safe-unmask-data seed-phrase)] (fn [] (let [current-word-index (get random-indices (min @quiz-index (dec questions-count))) - current-word (get secret-phrase current-word-index) + current-word (get unmasked-seed-phrase current-word-index) [options-row-0 options-row-1] (random-words-with-string random-phrase current-word) on-button-press (fn [word] (if (= word current-word) @@ -113,7 +115,7 @@ :else :disabled) - :word (get secret-phrase num) + :word (get unmasked-seed-phrase num) :number (inc num) :on-press #(when (= @quiz-index index) (reset! show-error? false))}]) diff --git a/src/status_im/contexts/wallet/add_account/create_account/new_keypair/keypair_name/view.cljs b/src/status_im/contexts/wallet/add_account/create_account/new_keypair/keypair_name/view.cljs index a30a8489cc..cb9d4c046a 100644 --- a/src/status_im/contexts/wallet/add_account/create_account/new_keypair/keypair_name/view.cljs +++ b/src/status_im/contexts/wallet/add_account/create_account/new_keypair/keypair_name/view.cljs @@ -47,8 +47,8 @@ {:actions :one-action :button-one-label (i18n/label :t/continue) :button-one-props {:disabled? (or (pos? error) - (<= (count keypair-name) - keypair-name-min-length)) + (< (count keypair-name) + keypair-name-min-length)) :customization-color customization-color :on-press on-continue} :container-style style/bottom-action}]} diff --git a/src/status_im/contexts/wallet/add_account/create_account/select_keypair/view.cljs b/src/status_im/contexts/wallet/add_account/create_account/select_keypair/view.cljs index 76abc4379a..f414ec8439 100644 --- a/src/status_im/contexts/wallet/add_account/create_account/select_keypair/view.cljs +++ b/src/status_im/contexts/wallet/add_account/create_account/select_keypair/view.cljs @@ -20,7 +20,9 @@ {:icon :i/seed :accessibility-label :import-using-phrase :label (i18n/label :t/import-using-phrase) - :add-divider? true} + :add-divider? true + :on-press #(rf/dispatch [:navigate-to :screen/wallet.enter-seed-phrase + {:recovering-keypair? true}])} {:icon :i/key :accessibility-label :import-private-key :label (i18n/label :t/import-private-key) diff --git a/src/status_im/contexts/wallet/effects.cljs b/src/status_im/contexts/wallet/effects.cljs index af5ab290f1..9da556fbc2 100644 --- a/src/status_im/contexts/wallet/effects.cljs +++ b/src/status_im/contexts/wallet/effects.cljs @@ -6,9 +6,11 @@ (rf/reg-fx :effects.wallet/create-account-from-mnemonic - (fn [{:keys [secret-phrase keypair-name]}] + (fn [{:keys [seed-phrase keypair-name]}] (native-module/create-account-from-mnemonic - {:MnemonicPhrase (string/join " " secret-phrase)} + {:MnemonicPhrase (if (string? seed-phrase) + seed-phrase + (string/join " " seed-phrase))} (fn [new-keypair] (rf/dispatch [:wallet/new-keypair-created {:new-keypair (assoc new-keypair :keypair-name keypair-name)}]))))) diff --git a/src/status_im/navigation/screens.cljs b/src/status_im/navigation/screens.cljs index b638697527..42c75588d7 100644 --- a/src/status_im/navigation/screens.cljs +++ b/src/status_im/navigation/screens.cljs @@ -3,6 +3,7 @@ [legacy.status-im.ui.screens.screens :as old-screens] [quo.foundations.colors :as colors] [status-im.common.emoji-picker.view :as emoji-picker] + [status-im.common.enter-seed-phrase.view :as enter-seed-phrase] [status-im.common.lightbox.view :as lightbox] [status-im.config :as config] [status-im.contexts.chat.group-create.view :as group-create] @@ -29,7 +30,6 @@ [status-im.contexts.onboarding.create-profile.view :as create-profile] [status-im.contexts.onboarding.enable-biometrics.view :as enable-biometrics] [status-im.contexts.onboarding.enable-notifications.view :as enable-notifications] - [status-im.contexts.onboarding.enter-seed-phrase.view :as enter-seed-phrase] [status-im.contexts.onboarding.generating-keys.view :as generating-keys] [status-im.contexts.onboarding.identifiers.view :as identifiers] [status-im.contexts.onboarding.intro.view :as intro] @@ -304,7 +304,7 @@ :layout options/onboarding-transparent-layout :animations transitions/push-animations-for-transparent-background :popGesture false} - :component enter-seed-phrase/enter-seed-phrase} + :component enter-seed-phrase/view} {:name :screen/onboarding.enable-notifications :options {:theme :dark @@ -429,6 +429,9 @@ :options {:insets {:top? true :bottom? true}} :component wallet-keypair-name/view} + {:name :screen/wallet.enter-seed-phrase + :component enter-seed-phrase/view} + {:name :screen/wallet.share-address :options options/transparent-screen-options :component wallet-share-address/view} diff --git a/translations/en.json b/translations/en.json index dcd87b374e..1b5eaf40ad 100644 --- a/translations/en.json +++ b/translations/en.json @@ -2546,8 +2546,8 @@ "derivation-path-desc": "Derivation paths are the routes your Status Wallet uses to generate addresses from your private key.", "select-networks": "Select networks", "generating-keypair": "Generating keypair...", - "keypair-name": "Keypair name", - "keypair-name-description": "Name keypair for your own personal reference", + "keypair-name": "Key pair name", + "keypair-name-description": "Name key pair for your own personal reference", "keypair-name-input-placeholder": "Collectibles account, Old vault....", "goerli-testnet-toggle-confirmation": "Are you sure you want to toggle Goerli? This will log you out and you will have to login again.", "bridged-to": "Bridged to {{network}}", @@ -2582,7 +2582,6 @@ "one-user-was-invited": "1 user was invited", "n-users-were-invited": "{{count}} users were invited", "invite-friend-to-status": "Invite friends to Status", - "send-community-link": "Send community link", "enter-private-key": "Enter the private key of an address", "enter-private-key-placeholder": "Enter your private key", "import-private-key-info": "New addresses cannot be derived from an account imported from a private key. Import using a seed phrase if you wish to derive addresses.", @@ -2590,5 +2589,6 @@ "private-key-public-address": "Public address of private key", "this-account-has-no-activity": "This account has no activity", "this-address-has-activity": "This address has activity", - "scanning-for-activity": "Scanning for activity..." + "scanning-for-activity": "Scanning for activity...", + "send-community-link": "Send community link" }