Skip to content

Commit

Permalink
Fix wallet account creation: derivation paths and keypairs
Browse files Browse the repository at this point in the history
  • Loading branch information
ulisesmac committed May 21, 2024
1 parent 4e23829 commit 5bbc9d5
Show file tree
Hide file tree
Showing 11 changed files with 410 additions and 251 deletions.
2 changes: 2 additions & 0 deletions src/status_im/constants.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@
(def ^:const path-ledger-live "m/44'/60'")
(def ^:const path-keepkey "m/44'/60'")

(def ^:const wallet-initial-derivation-path "m/44'/60'/0'/0/0")

(def ^:const path-default-wallet-keyword (keyword path-default-wallet))
(def ^:const path-whisper-keyword (keyword path-whisper))
(def ^:const path-wallet-root-keyword (keyword path-wallet-root))
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
:type :watch
{:type :watch
:account-name @account-name
:emoji @account-emoji
:color @account-color}
Expand Down
119 changes: 99 additions & 20 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,15 @@

(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 +48,42 @@
{: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]]]})
(defn store-account-generated
[{:keys [db]} [{:keys [new-account-data keypair-name]}]]
(let [new-account (update new-account-data :mnemonic security/mask-data)]
{: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/new-keypair-created new-keypair-created)
(rf/reg-event-fx :wallet/store-account-generated store-account-generated)

(defn new-keypair-continue
(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/wallet-initial-derivation-path]
: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 +94,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}))}]]]}))

(defn get-derived-addresses-success
[{:keys [db]} [response]]
(let [derived-address (first response)]
Expand All @@ -105,3 +134,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
(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"
: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
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
{: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,9 +108,8 @@
: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
{:seed-phrase (security/mask-data
@seed-phrase)
:on-press #(rf/dispatch [:wallet/store-new-seed-phrase
{:seed-phrase (security/mask-data @seed-phrase)
:random-phrase @random-phrase}])}}]
[quo/text
{:size :paragraph-2
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
45 changes: 27 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,28 @@
(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/wallet-initial-derivation-path
:public-key (:publicKey account-to-create)
:name account-name
:emoji emoji
:colorID color
:hidden false}]
{:key-uid keyUid
:name keypair-name
:type :seed
:derived-from address
:last-used-derivation-index 0
:accounts [account-config]}))
Loading

0 comments on commit 5bbc9d5

Please sign in to comment.