From 55a99da2f5c87884ac6fdb052cc532419c37fd53 Mon Sep 17 00:00:00 2001 From: Jamie Caprani Date: Thu, 7 Dec 2023 16:44:16 +0000 Subject: [PATCH] feat: enable biometrics for standard-auth (#17992) --- src/status_im/events.cljs | 1 + .../common/standard_authentication/core.cljs | 4 +- .../enter_password/view.cljs | 37 ++++----- .../standard_authentication/events.cljs | 8 ++ .../password_input/style.cljs | 4 + .../password_input/view.cljs | 36 +++++---- .../standard_auth/authorize.cljs | 78 ++++++++++++------- .../standard_auth/button/view.cljs | 44 ----------- .../standard_auth/slide_button/view.cljs | 17 ++-- .../onboarding/enable_biometrics/view.cljs | 7 +- .../contexts/onboarding/events.cljs | 13 +++- .../contexts/profile/profiles/view.cljs | 4 +- src/status_im2/contexts/syncing/events.cljs | 6 +- .../contexts/syncing/setup_syncing/view.cljs | 5 +- .../confirm_address/view.cljs | 4 +- .../contexts/wallet/create_account/view.cljs | 8 +- src/status_im2/contexts/wallet/events.cljs | 16 ++-- 17 files changed, 143 insertions(+), 149 deletions(-) create mode 100644 src/status_im2/common/standard_authentication/events.cljs delete mode 100644 src/status_im2/common/standard_authentication/standard_auth/button/view.cljs diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 0da1201df6..c8ccb8536a 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -46,6 +46,7 @@ [status-im.wallet.core :as wallet] status-im.wallet.custom-tokens.core [status-im2.common.biometric.events :as biometric] + status-im2.common.standard-authentication.events [status-im2.common.theme.core :as theme] [status-im2.common.universal-links :as universal-links] [status-im2.constants :as constants] diff --git a/src/status_im2/common/standard_authentication/core.cljs b/src/status_im2/common/standard_authentication/core.cljs index 3df688ca51..70a1376479 100644 --- a/src/status_im2/common/standard_authentication/core.cljs +++ b/src/status_im2/common/standard_authentication/core.cljs @@ -1,7 +1,7 @@ (ns status-im2.common.standard-authentication.core (:require - status-im2.common.standard-authentication.standard-auth.button.view + status-im2.common.standard-authentication.password-input.view status-im2.common.standard-authentication.standard-auth.slide-button.view)) -(def button status-im2.common.standard-authentication.standard-auth.button.view/view) +(def password-input status-im2.common.standard-authentication.password-input.view/view) (def slide-button status-im2.common.standard-authentication.standard-auth.slide-button.view/view) diff --git a/src/status_im2/common/standard_authentication/enter_password/view.cljs b/src/status_im2/common/standard_authentication/enter_password/view.cljs index 04df0a2378..124fe931a3 100644 --- a/src/status_im2/common/standard_authentication/enter_password/view.cljs +++ b/src/status_im2/common/standard_authentication/enter_password/view.cljs @@ -9,7 +9,7 @@ [utils.re-frame :as rf])) (defn view - [{:keys [on-enter-password button-label button-icon-left]}] + [{:keys [on-enter-password on-press-biometrics button-label button-icon-left]}] (let [{:keys [key-uid customization-color] :as profile} (rf/sub [:profile/profile-with-image]) {:keys [error processing password]} (rf/sub [:profile/login]) sign-in-enabled? (rf/sub [:sign-in-enabled?])] @@ -32,20 +32,21 @@ :customization-color customization-color :size 24}]] [password-input/view - {:processing processing - :error error - :default-password password - :sign-in-enabled? sign-in-enabled?}] - [rn/view {:style style/enter-password-button} - [quo/button - {:size 40 - :type :primary - :customization-color (or customization-color :primary) - :accessibility-label :login-button - :icon-left button-icon-left - :disabled? (or (not sign-in-enabled?) processing) - :on-press (fn [] - (rf/dispatch [:set-in [:profile/login :key-uid] key-uid]) - (rf/dispatch [:profile.login/verify-database-password password - #(on-enter-password password)]))} - button-label]]]]])) + {:on-press-biometrics on-press-biometrics + :processing processing + :error error + :default-password password + :sign-in-enabled? sign-in-enabled?}] + [quo/button + {:size 40 + :container-style style/enter-password-button + :type :primary + :customization-color (or customization-color :primary) + :accessibility-label :login-button + :icon-left button-icon-left + :disabled? (or (not sign-in-enabled?) processing) + :on-press (fn [] + (rf/dispatch [:set-in [:profile/login :key-uid] key-uid]) + (rf/dispatch [:profile.login/verify-database-password password + #(on-enter-password password)]))} + button-label]]]])) diff --git a/src/status_im2/common/standard_authentication/events.cljs b/src/status_im2/common/standard_authentication/events.cljs new file mode 100644 index 0000000000..cdee99547d --- /dev/null +++ b/src/status_im2/common/standard_authentication/events.cljs @@ -0,0 +1,8 @@ +(ns status-im2.common.standard-authentication.events + (:require + [utils.re-frame :as rf])) + +(rf/reg-event-fx :standard-auth/on-biometric-success + (fn [{:keys [db]} [callback]] + (let [key-uid (get-in db [:profile/profile :key-uid])] + {:fx [[:keychain/get-user-password [key-uid callback]]]}))) diff --git a/src/status_im2/common/standard_authentication/password_input/style.cljs b/src/status_im2/common/standard_authentication/password_input/style.cljs index b15a6ed222..2a7c1b4170 100644 --- a/src/status_im2/common/standard_authentication/password_input/style.cljs +++ b/src/status_im2/common/standard_authentication/password_input/style.cljs @@ -4,3 +4,7 @@ {:margin-top 8 :flex-direction :row :align-items :center}) + +(def auth-button + {:align-self :flex-end + :margin-left 8}) diff --git a/src/status_im2/common/standard_authentication/password_input/view.cljs b/src/status_im2/common/standard_authentication/password_input/view.cljs index 5f0760eefa..e4914adc40 100644 --- a/src/status_im2/common/standard_authentication/password_input/view.cljs +++ b/src/status_im2/common/standard_authentication/password_input/view.cljs @@ -27,21 +27,30 @@ (rf/dispatch [:set-in [:profile/login :error] ""])) (defn- view-internal - [{:keys [default-password theme shell?]}] + [{:keys [default-password theme shell? on-press-biometrics]}] (let [{:keys [error processing]} (rf/sub [:profile/login]) error-message (get-error-message error) error? (boolean (seq error-message))] [:<> - [quo/input - {:type :password - :blur? true - :disabled? processing - :placeholder (i18n/label :t/type-your-password) - :auto-focus true - :error? error? - :label (i18n/label :t/profile-password) - :on-change-text on-change-password - :default-value (security/safe-unmask-data default-password)}] + [rn/view {:style {:flex-direction :row}} + [quo/input + {:container-style {:flex 1} + :type :password + :blur? true + :disabled? processing + :placeholder (i18n/label :t/type-your-password) + :auto-focus true + :error? error? + :label (i18n/label :t/profile-password) + :on-change-text on-change-password + :default-value (security/safe-unmask-data default-password)}] + (when on-press-biometrics + [quo/button + {:container-style style/auth-button + :on-press on-press-biometrics + :icon-only? true + :type :outline} + :i/face-id])] (when error? [rn/view {:style style/error-message} [quo/info-message @@ -60,10 +69,7 @@ :shell? shell?}]))} [rn/text {:style {:text-decoration-line :underline - :color (colors/theme-colors - (colors/custom-color :danger 50) - (colors/custom-color :danger 60) - theme)} + :color (colors/resolve-color :danger theme)} :size :paragraph-2 :suppress-highlighting true} (i18n/label :t/forgot-password)]]])])) diff --git a/src/status_im2/common/standard_authentication/standard_auth/authorize.cljs b/src/status_im2/common/standard_authentication/standard_auth/authorize.cljs index 0f518d6775..bc913a29c6 100644 --- a/src/status_im2/common/standard_authentication/standard_auth/authorize.cljs +++ b/src/status_im2/common/standard_authentication/standard_auth/authorize.cljs @@ -1,10 +1,12 @@ (ns status-im2.common.standard-authentication.standard-auth.authorize (:require + [native-module.core :as native-module] [react-native.touch-id :as biometric] [status-im2.common.standard-authentication.enter-password.view :as enter-password] [taoensso.timbre :as log] [utils.i18n :as i18n] - [utils.re-frame :as rf])) + [utils.re-frame :as rf] + [utils.security.core :as security])) (defn reset-password [] @@ -12,33 +14,49 @@ (rf/dispatch [:set-in [:profile/login :error] ""])) (defn authorize - [{:keys [on-enter-password biometric-auth? on-auth-success on-auth-fail on-close + [{:keys [biometric-auth? on-auth-success on-auth-fail on-close auth-button-label theme blur? auth-button-icon-left]}] - (biometric/get-supported-type - (fn [biometric-type] - (if (and biometric-auth? biometric-type) - (biometric/authenticate - {:reason (i18n/label :t/biometric-auth-confirm-message) - :on-success (fn [response] - (when on-auth-success (on-auth-success response)) - (log/info "response" response)) - :on-fail (fn [error] - (log/error "Authentication Failed. Error:" error) - (when on-auth-fail (on-auth-fail error)) - (rf/dispatch [:show-bottom-sheet - {:theme theme - :shell? blur? - :content (fn [] - [enter-password/view - {:on-enter-password on-enter-password}])}]))}) - (do - (reset-password) - (rf/dispatch [:show-bottom-sheet - {:on-close on-close - :theme theme - :shell? blur? - :content (fn [] - [enter-password/view - {:on-enter-password on-enter-password - :button-icon-left auth-button-icon-left - :button-label auth-button-label}])}])))))) + (let [handle-auth-success (fn [biometric?] + (fn [entered-password] + (let [sha3-pwd (if biometric? + (str (security/safe-unmask-data entered-password)) + (native-module/sha3 (str (security/safe-unmask-data + entered-password))))] + (on-auth-success sha3-pwd)))) + password-login (fn [{:keys [on-press-biometrics]}] + (rf/dispatch [:show-bottom-sheet + {:on-close on-close + :theme theme + :shell? blur? + :content (fn [] + [enter-password/view + {:on-enter-password (handle-auth-success + false) + :on-press-biometrics on-press-biometrics + :button-icon-left auth-button-icon-left + :button-label auth-button-label}])}])) + ; biometrics-login recursively passes itself as a parameter because if the user + ; fails biometric auth they will be shown the password bottom sheet with an option + ; to retrigger biometric auth, so they can endlessly repeat this cycle. + biometrics-login (fn [on-press-biometrics] + (rf/dispatch [:dismiss-keyboard]) + (biometric/authenticate + {:reason (i18n/label :t/biometric-auth-confirm-message) + :on-success (fn [_response] + (on-close) + (rf/dispatch [:standard-auth/on-biometric-success + (handle-auth-success true)])) + :on-fail (fn [error] + (on-close) + (log/error "Authentication Failed. Error:" error) + (when on-auth-fail (on-auth-fail error)) + (password-login {:on-press-biometrics + #(on-press-biometrics + on-press-biometrics)}))}))] + (biometric/get-supported-type + (fn [biometric-type] + (if (and biometric-auth? biometric-type) + (biometrics-login biometrics-login) + (do + (reset-password) + (password-login {}))))))) diff --git a/src/status_im2/common/standard_authentication/standard_auth/button/view.cljs b/src/status_im2/common/standard_authentication/standard_auth/button/view.cljs deleted file mode 100644 index de633574bc..0000000000 --- a/src/status_im2/common/standard_authentication/standard_auth/button/view.cljs +++ /dev/null @@ -1,44 +0,0 @@ -(ns status-im2.common.standard-authentication.standard-auth.button.view - (:require - [quo.core :as quo] - [quo.theme :as quo.theme] - [reagent.core :as reagent] - [status-im2.common.standard-authentication.standard-auth.authorize :as authorize])) - -(defn- view-internal - [_] - (let [reset-slider? (reagent/atom false) - on-close #(reset! reset-slider? true)] - (fn [{:keys [biometric-auth? - customization-color - auth-button-label - on-enter-password - on-auth-success - on-press - on-auth-fail - auth-button-icon-left - size - button-label - theme - blur? - container-style - icon-left]}] - [quo/button - {:size size - :container-style container-style - :customization-color customization-color - :icon-left icon-left - :on-press (if on-press - on-press - #(authorize/authorize {:on-close on-close - :auth-button-icon-left auth-button-icon-left - :theme theme - :blur? blur? - :on-enter-password on-enter-password - :biometric-auth? biometric-auth? - :on-auth-success on-auth-success - :on-auth-fail on-auth-fail - :auth-button-label auth-button-label}))} - button-label]))) - -(def view (quo.theme/with-theme view-internal)) diff --git a/src/status_im2/common/standard_authentication/standard_auth/slide_button/view.cljs b/src/status_im2/common/standard_authentication/standard_auth/slide_button/view.cljs index ef295456d5..30944ed503 100644 --- a/src/status_im2/common/standard_authentication/standard_auth/slide_button/view.cljs +++ b/src/status_im2/common/standard_authentication/standard_auth/slide_button/view.cljs @@ -4,17 +4,21 @@ [quo.theme :as quo.theme] [react-native.core :as rn] [reagent.core :as reagent] - [status-im2.common.standard-authentication.standard-auth.authorize :as authorize])) + [status-im2.common.standard-authentication.standard-auth.authorize :as authorize] + [utils.re-frame :as rf])) (defn- view-internal [_] - (let [reset-slider? (reagent/atom false) - on-close #(reset! reset-slider? true)] - (fn [{:keys [biometric-auth? - track-text + (let [reset-slider? (reagent/atom false) + on-close (fn [] + (js/setTimeout + #(reset! reset-slider? true) + 200)) + auth-method (rf/sub [:auth-method]) + biometric-auth? (= auth-method "biometric")] + (fn [{:keys [track-text customization-color auth-button-label - on-enter-password on-auth-success on-auth-fail auth-button-icon-left @@ -32,7 +36,6 @@ :auth-button-icon-left auth-button-icon-left :theme theme :blur? blur? - :on-enter-password on-enter-password :biometric-auth? biometric-auth? :on-auth-success on-auth-success :on-auth-fail on-auth-fail diff --git a/src/status_im2/contexts/onboarding/enable_biometrics/view.cljs b/src/status_im2/contexts/onboarding/enable_biometrics/view.cljs index f794a8bb8c..d93a6f1abe 100644 --- a/src/status_im2/contexts/onboarding/enable_biometrics/view.cljs +++ b/src/status_im2/contexts/onboarding/enable_biometrics/view.cljs @@ -7,7 +7,6 @@ [status-im2.common.parallax.view :as parallax] [status-im2.common.parallax.whitelist :as whitelist] [status-im2.common.resources :as resources] - [status-im2.common.standard-authentication.core :as standard-auth] [status-im2.contexts.onboarding.enable-biometrics.style :as style] [status-im2.navigation.state :as state] [utils.i18n :as i18n] @@ -31,13 +30,13 @@ (rf/sub [:profile/customization-color])) syncing-results? (= :syncing-results @state/root-id)] [rn/view {:style (style/buttons insets)} - [standard-auth/button + [quo/button {:size 40 :accessibility-label :enable-biometrics-button :icon-left :i/face-id :customization-color profile-color - :on-press #(rf/dispatch [:onboarding/enable-biometrics]) - :button-label (i18n/label :t/biometric-enable-button {:bio-type-label bio-type-label})}] + :on-press #(rf/dispatch [:onboarding/enable-biometrics])} + (i18n/label :t/biometric-enable-button {:bio-type-label bio-type-label})] [quo/button {:accessibility-label :maybe-later-button :background :blur diff --git a/src/status_im2/contexts/onboarding/events.cljs b/src/status_im2/contexts/onboarding/events.cljs index 9aa07ea822..1fcd422e50 100644 --- a/src/status_im2/contexts/onboarding/events.cljs +++ b/src/status_im2/contexts/onboarding/events.cljs @@ -133,13 +133,18 @@ {:db (dissoc db :onboarding/profile) :dispatch [:navigate-to-within-stack [:create-profile :new-to-status]]}) +(rf/reg-event-fx :onboarding/set-auth-method + (fn [{:keys [db]} [auth-method]] + {:db (assoc db :auth-method auth-method)})) + (rf/defn onboarding-new-account-finalize-setup {:events [:onboarding/finalize-setup]} [{:keys [db]}] (let [masked-password (get-in db [:onboarding/profile :password]) key-uid (get-in db [:profile/profile :key-uid]) syncing? (get-in db [:onboarding/profile :syncing?]) - biometric-enabled? (= (get-in db [:onboarding/profile :auth-method]) + auth-method (get-in db [:onboarding/profile :auth-method]) + biometric-enabled? (= auth-method constants/auth-method-biometric)] (cond-> {:db (assoc db :onboarding/generated-keys? true)} biometric-enabled? @@ -149,9 +154,9 @@ masked-password (security/hash-masked-password masked-password)) :on-success (fn [] - (if syncing? - (rf/dispatch [:onboarding/navigate-to-enable-notifications]) - (log/error "successfully saved biometrics"))) + (rf/dispatch [:onboarding/set-auth-method auth-method]) + (when syncing? + (rf/dispatch [:onboarding/navigate-to-enable-notifications]))) :on-error #(log/error "failed to save biometrics" {:key-uid key-uid :error %})})))) diff --git a/src/status_im2/contexts/profile/profiles/view.cljs b/src/status_im2/contexts/profile/profiles/view.cljs index 8022d8a899..11d0338d06 100644 --- a/src/status_im2/contexts/profile/profiles/view.cljs +++ b/src/status_im2/contexts/profile/profiles/view.cljs @@ -7,7 +7,7 @@ [react-native.safe-area :as safe-area] [reagent.core :as reagent] [status-im2.common.confirmation-drawer.view :as confirmation-drawer] - [status-im2.common.standard-authentication.password-input.view :as password-input] + [status-im2.common.standard-authentication.core :as standard-authentication] [status-im2.config :as config] [status-im2.constants :as constants] [status-im2.contexts.onboarding.common.background.view :as background] @@ -205,7 +205,7 @@ :customization-color (or customization-color :primary) :profile-picture profile-picture :card-style style/login-profile-card}] - [password-input/view + [standard-authentication/password-input {:shell? true :default-password password}]] [quo/button diff --git a/src/status_im2/contexts/syncing/events.cljs b/src/status_im2/contexts/syncing/events.cljs index 6764f9ffb9..4618b5e74c 100644 --- a/src/status_im2/contexts/syncing/events.cljs +++ b/src/status_im2/contexts/syncing/events.cljs @@ -12,7 +12,6 @@ [status-im2.contexts.syncing.utils :as sync-utils] [taoensso.timbre :as log] [utils.re-frame :as rf] - [utils.security.core :as security] [utils.transforms :as transforms])) (rf/defn local-pairing-update-role @@ -97,7 +96,7 @@ (rf/defn preparations-for-connection-string {:events [:syncing/get-connection-string]} - [{:keys [db] :as cofx} entered-password on-valid-connection-string] + [{:keys [db] :as cofx} sha3-pwd on-valid-connection-string] (let [error (get-in db [:profile/login :error]) handle-connection (fn [response] (when (sync-utils/valid-connection-string? response) @@ -105,8 +104,7 @@ (rf/dispatch [:syncing/update-role constants/local-pairing-role-sender]) (rf/dispatch [:hide-bottom-sheet])))] (when-not (and error (string/blank? error)) - (let [key-uid (get-in db [:profile/login :key-uid]) - sha3-pwd (native-module/sha3 (str (security/safe-unmask-data entered-password))) + (let [key-uid (get-in db [:profile/profile :key-uid]) config-map (.stringify js/JSON (clj->js {:senderConfig {:keyUID key-uid :keystorePath "" diff --git a/src/status_im2/contexts/syncing/setup_syncing/view.cljs b/src/status_im2/contexts/syncing/setup_syncing/view.cljs index 36796e7fff..453d0ea26b 100644 --- a/src/status_im2/contexts/syncing/setup_syncing/view.cljs +++ b/src/status_im2/contexts/syncing/setup_syncing/view.cljs @@ -53,7 +53,7 @@ (reset! code nil) (reset! timestamp nil) (reset! valid-for-ms code-valid-for-ms)) - on-enter-password (fn [entered-password] + on-auth-success (fn [entered-password] (rf/dispatch [:syncing/get-connection-string entered-password set-code]))] (fn [] @@ -124,8 +124,7 @@ :size :size-40 :track-text (i18n/label :t/slide-to-reveal-code) :customization-color customization-color - :on-enter-password on-enter-password - :biometric-auth? false + :on-auth-success on-auth-success :auth-button-label (i18n/label :t/reveal-sync-code) :auth-button-icon-left :i/reveal}]])]] [rn/view {:style style/sync-code} diff --git a/src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/view.cljs b/src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/view.cljs index 0fc3fa041c..755a1ae926 100644 --- a/src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/view.cljs +++ b/src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/view.cljs @@ -43,8 +43,8 @@ :bottom-action-props {:customization-color @account-color :disabled? (string/blank? @account-name) :on-press #(rf/dispatch [:wallet/add-account - nil - {:type :watch + {:sha3-pwd nil + :type :watch :account-name @account-name :emoji @account-emoji :color @account-color} diff --git a/src/status_im2/contexts/wallet/create_account/view.cljs b/src/status_im2/contexts/wallet/create_account/view.cljs index 32b0003094..9aa9d74e19 100644 --- a/src/status_im2/contexts/wallet/create_account/view.cljs +++ b/src/status_im2/contexts/wallet/create_account/view.cljs @@ -118,14 +118,14 @@ {:size :size-48 :track-text (i18n/label :t/slide-to-create-account) :customization-color @account-color - :on-enter-password (fn [entered-password] + :on-auth-success (fn [entered-password] + (prn entered-password) (rf/dispatch [:wallet/derive-address-and-add-account - entered-password - {:emoji @emoji + {:sha3-pwd entered-password + :emoji @emoji :color @account-color :path @derivation-path :account-name @account-name}])) - :biometric-auth? false :auth-button-label (i18n/label :t/confirm) :container-style (style/slide-button-container bottom)}]]))) diff --git a/src/status_im2/contexts/wallet/events.cljs b/src/status_im2/contexts/wallet/events.cljs index 8f2a4bbe6d..db959d5558 100644 --- a/src/status_im2/contexts/wallet/events.cljs +++ b/src/status_im2/contexts/wallet/events.cljs @@ -3,7 +3,6 @@ [camel-snake-kebab.core :as csk] [camel-snake-kebab.extras :as cske] [clojure.string :as string] - [native-module.core :as native-module] [quo.foundations.colors :as colors] [react-native.background-timer :as background-timer] [status-im2.common.data-store.wallet :as data-store] @@ -15,7 +14,6 @@ [utils.i18n :as i18n] [utils.number] [utils.re-frame :as rf] - [utils.security.core :as security] [utils.transforms :as types])) (rf/reg-event-fx :wallet/show-account-created-toast @@ -143,9 +141,8 @@ {:db (dissoc db :wallet/scanned-address :wallet/send-address)}) (rf/reg-event-fx :wallet/create-derived-addresses - (fn [{:keys [db]} [password {:keys [path]} on-success]] - (let [{:keys [wallet-root-address]} (:profile/profile db) - sha3-pwd (native-module/sha3 (str (security/safe-unmask-data password)))] + (fn [{:keys [db]} [{:keys [sha3-pwd path]} on-success]] + (let [{:keys [wallet-root-address]} (:profile/profile db)] {:fx [[:json-rpc/call [{:method "wallet_getDerivedAddresses" :params [sha3-pwd wallet-root-address [path]] @@ -162,11 +159,10 @@ (rf/reg-event-fx :wallet/add-account (fn [{:keys [db]} - [password {:keys [emoji account-name color type] :or {type :generated}} + [{:keys [sha3-pwd emoji account-name color type] :or {type :generated}} {:keys [public-key address path]}]] (let [lowercase-address (if address (string/lower-case address) address) key-uid (get-in db [:profile/profile :key-uid]) - sha3-pwd (native-module/sha3 (security/safe-unmask-data password)) account-config {:key-uid (when (= type :generated) key-uid) :wallet false :chat false @@ -185,11 +181,11 @@ (rf/reg-event-fx :wallet/derive-address-and-add-account - (fn [_ [password account-details]] + (fn [_ [account-details]] (let [on-success (fn [derived-address-details] - (rf/dispatch [:wallet/add-account password account-details + (rf/dispatch [:wallet/add-account account-details (first derived-address-details)]))] - {:fx [[:dispatch [:wallet/create-derived-addresses password account-details on-success]]]}))) + {:fx [[:dispatch [:wallet/create-derived-addresses account-details on-success]]]}))) (rf/defn get-ethereum-chains {:events [:wallet/get-ethereum-chains]}