Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#19232] - Fix derivation path generation #19531

Merged
merged 9 commits into from
May 24, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
:on-auth-success on-auth-success
:on-auth-fail on-auth-fail
:auth-button-label auth-button-label}]))
(into [] (concat [theme] dependencies)))]
(vec (conj dependencies on-auth-success on-auth-fail)))]
ulisesmac marked this conversation as resolved.
Show resolved Hide resolved
[quo/slide-button
{:container-style container-style
:size size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
:disabled? (string/blank? @account-name)
:accessibility-label :confirm-button-label
:on-press #(rf/dispatch [:wallet/add-account
{:sha3-pwd nil
ulisesmac marked this conversation as resolved.
Show resolved Hide resolved
:type :watch
{:type :watch
ulisesmac marked this conversation as resolved.
Show resolved Hide resolved
:account-name @account-name
:emoji @account-emoji
:color @account-color}
Expand Down
129 changes: 107 additions & 22 deletions src/status_im/contexts/wallet/add_account/create_account/events.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
(ns status-im.contexts.wallet.add-account.create-account.events
(:require [camel-snake-kebab.extras :as cske]
[clojure.string :as string]
[status-im.constants :as constants]
[status-im.contexts.wallet.add-account.create-account.utils :as create-account.utils]
[status-im.contexts.wallet.data-store :as data-store]
[taoensso.timbre :as log]
[utils.re-frame :as rf]
[utils.security.core :as security]
[utils.transforms :as transforms]))
Expand All @@ -22,14 +26,18 @@

(rf/reg-event-fx :wallet/confirm-account-origin confirm-account-origin)

(defn store-seed-phrase
(defn store-new-seed-phrase
[{:keys [db]} [{:keys [seed-phrase random-phrase]}]]
{:db (-> db
(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.confirm-backup]}]]]})
{:db (update-in db
[:wallet :ui :create-account :new-keypair]
assoc
:seed-phrase seed-phrase
:random-phrase random-phrase)
:fx [[:dispatch-later
[{:ms 20
:dispatch [:navigate-to :screen/wallet.confirm-backup]}]]]})

(rf/reg-event-fx :wallet/store-seed-phrase store-seed-phrase)
(rf/reg-event-fx :wallet/store-new-seed-phrase store-new-seed-phrase)

(defn seed-phrase-validated
[{:keys [db]} [seed-phrase]]
Expand All @@ -43,33 +51,45 @@
{:fx [[:multiaccount/validate-mnemonic
[seed-phrase
(fn [mnemonic key-uid]
(rf/dispatch [:wallet/seed-phrase-validated
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]}]]
{:db (assoc-in db [:wallet :ui :create-account :new-keypair] new-keypair)
:fx [[:dispatch [:navigate-back-to :screen/wallet.create-account]]]})

(rf/reg-event-fx :wallet/new-keypair-created new-keypair-created)

(defn new-keypair-continue
(defn store-account-generated
[{:keys [db]} [{:keys [new-account-data keypair-name]}]]
(let [new-account (update new-account-data :mnemonic security/mask-data)]
ulisesmac marked this conversation as resolved.
Show resolved Hide resolved
{:db (-> db
(update-in [:wallet :ui :create-account :new-keypair]
assoc
:new-account-data new-account
:keypair-name keypair-name)
(update-in [:wallet :ui :create-account :new-keypair]
dissoc
:seed-phrase
:random-phrase))
:fx [[:dispatch [:navigate-back-to :screen/wallet.create-account]]]}))

(rf/reg-event-fx :wallet/store-account-generated store-account-generated)

(defn generate-account-for-keypair
[{:keys [db]} [{:keys [keypair-name]}]]
(let [seed-phrase (get-in db [:wallet :ui :create-account :seed-phrase])]
(let [seed-phrase (-> db :wallet :ui :create-account :new-keypair :seed-phrase)]
{:fx [[:effects.wallet/create-account-from-mnemonic
{:seed-phrase (security/safe-unmask-data seed-phrase)
:keypair-name keypair-name}]]}))
{:mnemonic-phrase (security/safe-unmask-data seed-phrase)
:paths [constants/path-default-wallet]
:on-success (fn [new-account-data]
(rf/dispatch [:wallet/store-account-generated
{:new-account-data new-account-data
:keypair-name keypair-name}]))}]]}))

(rf/reg-event-fx :wallet/new-keypair-continue new-keypair-continue)
(rf/reg-event-fx :wallet/generate-account-for-keypair generate-account-for-keypair)

(defn clear-new-keypair
(defn clear-create-account-data
[{:keys [db]}]
{:db (update-in db [:wallet :ui :create-account] dissoc :new-keypair)})

(rf/reg-event-fx :wallet/clear-new-keypair clear-new-keypair)
(rf/reg-event-fx :wallet/clear-create-account clear-create-account-data)

(defn get-derived-addresses
[{:keys [db]} [{:keys [password derived-from paths]}]]
Expand All @@ -80,6 +100,21 @@

(rf/reg-event-fx :wallet/get-derived-addresses get-derived-addresses)

(rf/reg-event-fx
:wallet/next-derivation-path
(fn [_ [{:keys [on-success keypair-uid]}]]
{:fx [[:json-rpc/call
[{:method "accounts_resolveSuggestedPathForKeypair"
:params [keypair-uid]
:on-success on-success
:on-error (fn [error]
(log/error
"Failed to resolve next path derivation path"
{:event :wallet/next-derivation-path
:method "accounts_resolveSuggestedPathForKeypair"
:error error
:params keypair-uid}))}]]]}))
ulisesmac marked this conversation as resolved.
Show resolved Hide resolved

(defn get-derived-addresses-success
[{:keys [db]} [response]]
(let [derived-address (first response)]
Expand All @@ -105,3 +140,53 @@
:wallet/clear-private-key-data
(fn [{:keys [db]} _]
{:db (update-in db [:wallet :ui :create-account] dissoc :private-key :public-address)}))

(rf/reg-event-fx
:wallet/create-keypair-with-account
ulisesmac marked this conversation as resolved.
Show resolved Hide resolved
(fn [{db :db} [password account-preferences]]
(let [{:keys [keypair-name
new-account-data]} (-> db :wallet :ui :create-account :new-keypair)
keypair-with-account (create-account.utils/prepare-new-account
{:keypair-name keypair-name
:account-data new-account-data
:account-preferences account-preferences})
new-address (some-> new-account-data
(create-account.utils/first-derived-account)
(:address)
(string/lower-case))
unmasked-password (security/safe-unmask-data password)]
{:fx [[:json-rpc/call
[{:method "accounts_addKeypair"
:params [unmasked-password keypair-with-account]
:on-success [:wallet/add-account-success new-address]
:on-error #(log/error "Failed to add Keypair and create account" %)}]]]})))

(defn import-and-create-keypair-with-account
[{db :db} [{:keys [password account-preferences]}]]
(let [account-data (-> db :wallet :ui :create-account :new-keypair :new-account-data)
unmasked-mnemonic (security/safe-unmask-data (:mnemonic account-data))
unmasked-password (security/safe-unmask-data password)]
{:fx [[:json-rpc/call
[{:method "accounts_importMnemonic"
ulisesmac marked this conversation as resolved.
Show resolved Hide resolved
:params [unmasked-mnemonic unmasked-password]
:on-success #(rf/dispatch
[:wallet/create-keypair-with-account password account-preferences])}]]]}))

(rf/reg-event-fx :wallet/import-and-create-keypair-with-account import-and-create-keypair-with-account)

(rf/reg-event-fx
:wallet/derive-address-and-add-account
(fn [_ [{:keys [password derived-from-address derivation-path account-preferences]}]]
{:fx [[:json-rpc/call
[{:method "wallet_getDerivedAddresses"
:params [(security/safe-unmask-data password)
derived-from-address
[derivation-path]]
:on-success (fn [[derived-account]]
(rf/dispatch [:wallet/add-account
(assoc account-preferences :password password)
derived-account]))
:on-error #(log/info "Failed to get derived addresses"
derived-from-address
%)}]]]}))

Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
(ns status-im.contexts.wallet.add-account.create-account.events-test
(:require
[cljs.test :refer-macros [deftest is]]
matcher-combinators.test
[status-im.contexts.wallet.add-account.create-account.events :as events]))
[matcher-combinators.test]
[status-im.constants :as constants]
[status-im.contexts.wallet.add-account.create-account.events :as events]
[utils.security.core :as security]))

(deftest confirm-account-origin
(let [db {:wallet {:ui {:create-account {}}}}
Expand All @@ -15,32 +17,60 @@
(deftest store-seed-phrase
(let [db {}
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-seed-phrase {:db db} props)
expected-db {:wallet {:ui {:create-account {:new-keypair {:seed-phrase "test-secret"
:random-phrase "random-test"}}}}}
effects (events/store-new-seed-phrase {:db db} props)
result-db (:db effects)]
(is (match? result-db expected-db))))

(deftest new-keypair-created
(let [db {}
props [{:new-keypair "test-keypair"}]
expected-db {:wallet {:ui {:create-account {:new-keypair "test-keypair"}}}}
effects (events/new-keypair-created {:db db} props)
result-db (:db effects)]
(is (match? result-db expected-db))))
(deftest store-account-generated
(let [db {:wallet {:ui {:create-account
{:new-keypair {:seed-phrase "test-secret"
:random-phrase "random-test"}}}}}
mnemonic "my mnemonic"
masked-mnemonic (security/mask-data mnemonic)
props [{:new-account-data {"test" "data"
:mnemonic mnemonic}
:keypair-name "new-keypair-name"}]
expected-db {:wallet {:ui {:create-account
{:new-keypair
{:new-account-data {"test" "data"
:mnemonic masked-mnemonic}
:keypair-name "new-keypair-name"}}}}}
effects (events/store-account-generated {:db db} props)
result-db (:db effects)
remove-mnemonic #(update-in %
[:wallet :ui :create-account :new-keypair :new-account-data]
dissoc
:mnemonic)
unmask-mnemonic #(-> %
:wallet
:ui
:create-account
:new-keypair
:new-account-data
:mnemonic
security/safe-unmask-data)]
(is (= (remove-mnemonic result-db) (remove-mnemonic expected-db)))
(is (= (unmask-mnemonic result-db) (unmask-mnemonic expected-db)))))


(deftest new-keypair-continue
(let [db {:wallet {:ui {:create-account {:seed-phrase "test-secret"}}}}
(deftest generate-account-for-keypair
(let [db {:wallet {:ui {:create-account {:new-keypair {:seed-phrase "test-secret"}}}}}
props [{:keypair-name "test-keypair"}]
expected-effects [[:effects.wallet/create-account-from-mnemonic
{:seed-phrase "test-secret" :keypair-name "test-keypair"}]]
effects (events/new-keypair-continue {:db db} props)]
(is (match? effects {:fx expected-effects}))))
{:mnemonic-phrase "test-secret"
:paths [constants/path-default-wallet]}]]
effects (events/generate-account-for-keypair {:db db} props)]
(is (match?
(update-in effects [:fx 0 1] dissoc :on-success)
{:fx expected-effects}))
(is (some? (get-in effects [:fx 0 1 :on-success])))))

(deftest clear-new-keypair
(deftest clear-create-account-data
(let [db {:wallet {:ui {:create-account {:new-keypair "test-keypair"}}}}
expected-db {:wallet {:ui {:create-account {}}}}
effects (events/clear-new-keypair {:db db})]
effects (events/clear-create-account-data {:db db})]
(is (match? (:db effects) expected-db))))

(deftest get-derived-addresses-test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
:import-private-key
(not-implemented/alert)

:new-key-pair
(rf/dispatch [:wallet/new-keypair-continue
:new-keypair
(rf/dispatch [:wallet/generate-account-for-keypair
ulisesmac marked this conversation as resolved.
Show resolved Hide resolved
{:keypair-name key-pair-name}])
(js/alert "Unknown workflow")))
[workflow key-pair-name])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
: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-seed-phrase
:on-press #(rf/dispatch [:wallet/store-new-seed-phrase
{:seed-phrase (security/mask-data
@seed-phrase)
:random-phrase @random-phrase}])}}]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
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])
{:keys [seed-phrase random-phrase]} (rf/sub [:wallet/create-account-new-keypair])
unmasked-seed-phrase (security/safe-unmask-data seed-phrase)]
(fn []
(let [current-word-index (get random-indices
Expand All @@ -82,7 +82,7 @@
(when (= @quiz-index questions-count)
(rf/dispatch [:navigate-to
:screen/wallet.keypair-name
{:workflow :new-key-pair}])))
{:workflow :new-keypair}])))
(do
(when (> @incorrect-count 0)
(rf/dispatch [:show-bottom-sheet
Expand Down
46 changes: 28 additions & 18 deletions src/status_im/contexts/wallet/add_account/create_account/utils.cljs
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
(ns status-im.contexts.wallet.add-account.create-account.utils)
(ns status-im.contexts.wallet.add-account.create-account.utils
(:require [status-im.constants :as constants]))

(defn prepare-new-keypair
[{:keys [new-keypair address account-name account-color emoji derivation-path]}]
(assoc new-keypair
:name (:keypair-name new-keypair)
:key-uid (:keyUid new-keypair)
:type :seed
:derived-from address
:accounts [{:keypair-name (:keypair-name new-keypair)
:key-uid (:keyUid new-keypair)
:seed-phrase (:mnemonic new-keypair)
:public-key (:publicKey new-keypair)
:name account-name
:type :seed
:emoji emoji
:colorID account-color
:path derivation-path
:address (:address new-keypair)}]))
(defn first-derived-account
[account-data]
(-> account-data :derived first val))

(defn prepare-new-account
[{keypair-name :keypair-name
{:keys [keyUid address] :as account} :account-data
{:keys [account-name color emoji]} :account-preferences}]
(let [account-to-create (first-derived-account account)
account-config {:address (:address account-to-create)
:key-uid keyUid
:wallet false
:chat false
:type :seed
:path constants/path-default-wallet
:public-key (:publicKey account-to-create)
:name account-name
:emoji emoji
:colorID color
:hidden false}]
{:key-uid keyUid
:name keypair-name
:type :seed
ulisesmac marked this conversation as resolved.
Show resolved Hide resolved
:derived-from address
:last-used-derivation-index 0
:accounts [account-config]}))
Loading