* Add more default dependencies to slide button * Fix wallet account creation: derivation paths and keypairs
This commit is contained in:
parent
f65c10502b
commit
49a41f4787
|
@ -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)))]
|
||||
[quo/slide-button
|
||||
{:container-style container-style
|
||||
:size size
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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]))
|
||||
|
@ -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]]
|
||||
|
@ -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]]]})
|
||||
(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/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]}]]
|
||||
|
@ -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}))}]]]}))
|
||||
|
||||
(defn get-derived-addresses-success
|
||||
[{:keys [db]} [response]]
|
||||
(let [derived-address (first response)]
|
||||
|
@ -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
|
||||
(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
|
||||
%)}]]]}))
|
||||
|
||||
|
|
|
@ -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 {}}}}
|
||||
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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}])}}]
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
:derived-from address
|
||||
:last-used-derivation-index 0
|
||||
:accounts [account-config]}))
|
||||
|
|
|
@ -12,14 +12,11 @@
|
|||
[status-im.common.standard-authentication.core :as standard-auth]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.add-account.create-account.style :as style]
|
||||
[status-im.contexts.wallet.add-account.create-account.utils :as create-account.utils]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.sheets.account-origin.view :as account-origin]
|
||||
[status-im.feature-flags :as ff]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.responsiveness :as responsiveness]
|
||||
[utils.security.core :as security]
|
||||
[utils.string]))
|
||||
|
||||
(defn- get-keypair-data
|
||||
|
@ -57,107 +54,47 @@
|
|||
:description :text
|
||||
:description-props {:text formatted-path}}]))
|
||||
|
||||
(defn view
|
||||
(defn- avatar
|
||||
[{:keys [account-color emoji on-select-emoji]}]
|
||||
[rn/view {:style style/account-avatar-container}
|
||||
[quo/account-avatar
|
||||
{:customization-color account-color
|
||||
:size 80
|
||||
:emoji emoji
|
||||
:type :default}]
|
||||
[quo/button
|
||||
{:size 32
|
||||
:type :grey
|
||||
:background :photo
|
||||
:icon-only? true
|
||||
:on-press #(rf/dispatch [:emoji-picker/open {:on-select on-select-emoji}])
|
||||
:container-style style/reaction-button-container}
|
||||
:i/reaction]])
|
||||
|
||||
(defn- input
|
||||
[_]
|
||||
(let [top (safe-area/get-top)
|
||||
bottom (safe-area/get-bottom)
|
||||
{window-width :width} (rn/get-window)
|
||||
account-color (reagent/atom (rand-nth colors/account-colors))
|
||||
emoji (reagent/atom (emoji-picker.utils/random-emoji))
|
||||
account-name (reagent/atom "")
|
||||
on-change-text #(reset! account-name %)
|
||||
show-account-origin #(rf/dispatch [:show-bottom-sheet
|
||||
{:content account-origin/view}])]
|
||||
(fn []
|
||||
(let [theme (quo.theme/use-theme)
|
||||
number-of-accounts (count (rf/sub
|
||||
[:wallet/accounts-without-watched-accounts]))
|
||||
{:keys [address customization-color]} (rf/sub [:profile/profile])
|
||||
{:keys [new-keypair]} (rf/sub [:wallet/create-account])
|
||||
keypairs (rf/sub [:wallet/keypairs])
|
||||
selected-keypair-uid (rf/sub [:wallet/selected-keypair-uid])
|
||||
placeholder (i18n/label :t/default-account-placeholder)
|
||||
derivation-path (utils/get-derivation-path
|
||||
number-of-accounts)
|
||||
keypair (some #(when (= (:key-uid %) selected-keypair-uid)
|
||||
%)
|
||||
keypairs)
|
||||
primary-keypair? (= selected-keypair-uid (:key-uid (first keypairs)))
|
||||
create-new-keypair-account #(rf/dispatch
|
||||
[:wallet/add-keypair-and-create-account
|
||||
{:sha3-pwd (security/safe-unmask-data %)
|
||||
:new-keypair
|
||||
(create-account.utils/prepare-new-keypair
|
||||
{:new-keypair new-keypair
|
||||
:address address
|
||||
:account-name @account-name
|
||||
:account-color @account-color
|
||||
:emoji @emoji
|
||||
:derivation-path
|
||||
derivation-path})}])
|
||||
create-existing-keypair-account #(rf/dispatch [:wallet/derive-address-and-add-account
|
||||
{:sha3-pwd (security/safe-unmask-data %)
|
||||
:emoji @emoji
|
||||
:color @account-color
|
||||
:path derivation-path
|
||||
:account-name @account-name}])
|
||||
keypair-title (or (:keypair-name new-keypair)
|
||||
(if primary-keypair?
|
||||
(i18n/label :t/keypair-title
|
||||
{:name (:name keypair)})
|
||||
(:name keypair)))]
|
||||
(rn/use-unmount #(rf/dispatch [:wallet/clear-new-keypair]))
|
||||
[floating-button-page/view
|
||||
{:gradient-cover? true
|
||||
:footer-container-padding 0
|
||||
:header-container-style {:padding-top top}
|
||||
:customization-color @account-color
|
||||
:header [quo/page-nav
|
||||
{:type :no-title
|
||||
:background :blur
|
||||
:right-side [{:icon-name :i/info
|
||||
:on-press show-account-origin}]
|
||||
:icon-name :i/close
|
||||
:on-press #(rf/dispatch [:navigate-back])}]
|
||||
:footer [standard-auth/slide-button
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-create-account)
|
||||
:customization-color @account-color
|
||||
:on-auth-success (fn [password]
|
||||
(if new-keypair
|
||||
(create-new-keypair-account password)
|
||||
(create-existing-keypair-account
|
||||
password)))
|
||||
:auth-button-label (i18n/label :t/confirm)
|
||||
:disabled? (empty? @account-name)
|
||||
:container-style (style/slide-button-container bottom)
|
||||
:dependencies [new-keypair]}]}
|
||||
[rn/view {:style style/account-avatar-container}
|
||||
[quo/account-avatar
|
||||
{:customization-color @account-color
|
||||
:size 80
|
||||
:emoji @emoji
|
||||
:type :default}]
|
||||
[quo/button
|
||||
{:size 32
|
||||
:type :grey
|
||||
:background :photo
|
||||
:icon-only? true
|
||||
:on-press #(rf/dispatch [:emoji-picker/open
|
||||
{:on-select (fn [selected-emoji]
|
||||
(reset! emoji selected-emoji))}])
|
||||
:container-style style/reaction-button-container}
|
||||
:i/reaction]]
|
||||
[quo/title-input
|
||||
{:customization-color @account-color
|
||||
:placeholder placeholder
|
||||
:on-change-text on-change-text
|
||||
:max-length constants/wallet-account-name-max-length
|
||||
:blur? true
|
||||
:disabled? false
|
||||
:default-value @account-name
|
||||
:container-style style/title-input-container}]
|
||||
[quo/divider-line]
|
||||
(let [placeholder (i18n/label :t/default-account-placeholder)]
|
||||
(fn [{:keys [account-color account-name on-change-text]}]
|
||||
[quo/title-input
|
||||
{:customization-color account-color
|
||||
:placeholder placeholder
|
||||
:on-change-text on-change-text
|
||||
:max-length constants/wallet-account-name-max-length
|
||||
:blur? true
|
||||
:disabled? false
|
||||
:default-value account-name
|
||||
:container-style style/title-input-container}])))
|
||||
|
||||
(defn- color-picker
|
||||
[_]
|
||||
(let [{window-width :width} (rn/get-window)
|
||||
color-picker-style {:padding-vertical 12
|
||||
:padding-left (responsiveness/iphone-11-Pro-20-pixel-from-width
|
||||
window-width)}]
|
||||
(fn [{:keys [account-color set-account-color]}]
|
||||
[:<>
|
||||
[quo/divider-line]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view {:style style/color-picker-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
|
@ -165,17 +102,168 @@
|
|||
:style (style/color-label theme)}
|
||||
(i18n/label :t/colour)]
|
||||
[quo/color-picker
|
||||
{:default-selected @account-color
|
||||
:on-change #(reset! account-color %)
|
||||
:container-style {:padding-vertical 12
|
||||
:padding-left (responsiveness/iphone-11-Pro-20-pixel-from-width
|
||||
window-width)}}]]
|
||||
[quo/divider-line]
|
||||
[quo/category
|
||||
{:list-type :settings
|
||||
:label (i18n/label :t/origin)
|
||||
:data (get-keypair-data {:title keypair-title
|
||||
:primary-keypair? primary-keypair?
|
||||
:new-keypair? (boolean new-keypair)
|
||||
:derivation-path derivation-path
|
||||
:customization-color customization-color})}]]))))
|
||||
{:default-selected account-color
|
||||
:on-change set-account-color
|
||||
:container-style color-picker-style}]])])))
|
||||
|
||||
(defn- new-account-origin
|
||||
[{:keys [keypair-title derivation-path customization-color]}]
|
||||
(let [{keypair-name :name} (rf/sub [:wallet/selected-keypair])
|
||||
primary? (rf/sub [:wallet/selected-primary-keypair?])
|
||||
keypair-name (or keypair-title
|
||||
(if primary?
|
||||
(i18n/label :t/keypair-title {:name keypair-name})
|
||||
keypair-name))]
|
||||
[:<>
|
||||
[quo/divider-line]
|
||||
[quo/category
|
||||
{:list-type :settings
|
||||
:label (i18n/label :t/origin)
|
||||
:data (get-keypair-data {:primary-keypair? primary?
|
||||
:title keypair-name
|
||||
:derivation-path derivation-path
|
||||
:customization-color customization-color})}]]))
|
||||
|
||||
(defn- floating-button
|
||||
[_ & _]
|
||||
(let [top (safe-area/get-top)
|
||||
bottom (safe-area/get-bottom)
|
||||
header [quo/page-nav
|
||||
{:type :no-title
|
||||
:background :blur
|
||||
:right-side [{:icon-name :i/info
|
||||
:on-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content account-origin/view}])}]
|
||||
:icon-name :i/close
|
||||
:on-press #(rf/dispatch [:navigate-back])}]]
|
||||
(fn [{:keys [slide-button-props account-color]} & children]
|
||||
(into
|
||||
[floating-button-page/view
|
||||
{:gradient-cover? true
|
||||
:footer-container-padding 0
|
||||
:header-container-style {:padding-top top}
|
||||
:customization-color account-color
|
||||
:header header
|
||||
:footer [standard-auth/slide-button
|
||||
(assoc slide-button-props
|
||||
:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-create-account)
|
||||
:customization-color account-color
|
||||
:auth-button-label (i18n/label :t/confirm)
|
||||
:container-style (style/slide-button-container bottom))]}]
|
||||
children))))
|
||||
|
||||
(defn add-new-keypair-variant
|
||||
[{:keys [on-change-text set-account-color set-emoji]
|
||||
{:keys [account-name account-color emoji]}
|
||||
:state}]
|
||||
(let [on-auth-success (fn [password]
|
||||
(rf/dispatch
|
||||
[:wallet/import-and-create-keypair-with-account
|
||||
{:password password
|
||||
:account-preferences {:account-name @account-name
|
||||
:color @account-color
|
||||
:emoji @emoji}}]))]
|
||||
(fn [{:keys [customization-color keypair-name]}]
|
||||
(let [{:keys [new-account-data]} (rf/sub [:wallet/create-account-new-keypair])]
|
||||
[floating-button
|
||||
{:account-color @account-color
|
||||
:slide-button-props {:on-auth-success on-auth-success
|
||||
:disabled? (empty? @account-name)
|
||||
:dependencies [new-account-data]}}
|
||||
[avatar
|
||||
{:account-color @account-color
|
||||
:emoji @emoji
|
||||
:on-select-emoji set-emoji}]
|
||||
[input
|
||||
{:account-color @account-color
|
||||
:account-name @account-name
|
||||
:on-change-text on-change-text}]
|
||||
[color-picker
|
||||
{:account-color @account-color
|
||||
:set-account-color set-account-color}]
|
||||
[new-account-origin
|
||||
{:derivation-path constants/path-default-wallet
|
||||
:customization-color customization-color
|
||||
:keypair-title keypair-name}]]))))
|
||||
|
||||
(defn derive-account-variant
|
||||
[{:keys [on-change-text set-account-color set-emoji]
|
||||
{:keys [account-name account-color emoji]}
|
||||
:state}]
|
||||
(let [derivation-path (reagent/atom "")
|
||||
set-derivation-path #(reset! derivation-path %)]
|
||||
(fn [{:keys [customization-color]}]
|
||||
(let [{:keys [derived-from
|
||||
key-uid]} (rf/sub [:wallet/selected-keypair])
|
||||
on-auth-success (rn/use-callback
|
||||
(fn [password]
|
||||
(let [preferences {:account-name @account-name
|
||||
:color @account-color
|
||||
:emoji @emoji}]
|
||||
(rf/dispatch
|
||||
[:wallet/derive-address-and-add-account
|
||||
{:password password
|
||||
:derived-from-address derived-from
|
||||
:derivation-path @derivation-path
|
||||
:account-preferences preferences}])))
|
||||
[derived-from])]
|
||||
(rn/use-effect
|
||||
#(rf/dispatch
|
||||
[:wallet/next-derivation-path
|
||||
{:on-success set-derivation-path
|
||||
:keypair-uid key-uid}])
|
||||
[key-uid])
|
||||
|
||||
[floating-button
|
||||
{:account-color @account-color
|
||||
:slide-button-props {:on-auth-success on-auth-success
|
||||
:disabled? (or (empty? @account-name)
|
||||
(= "" @derivation-path))}}
|
||||
[avatar
|
||||
{:account-color @account-color
|
||||
:emoji @emoji
|
||||
:on-select-emoji set-emoji}]
|
||||
[input
|
||||
{:account-color @account-color
|
||||
:account-name @account-name
|
||||
:on-change-text on-change-text}]
|
||||
[color-picker
|
||||
{:account-color @account-color
|
||||
:set-account-color set-account-color}]
|
||||
[new-account-origin
|
||||
{:derivation-path @derivation-path
|
||||
:customization-color customization-color}]]))))
|
||||
|
||||
(defn view
|
||||
[_]
|
||||
(let [account-name (reagent/atom "")
|
||||
account-color (reagent/atom (rand-nth colors/account-colors))
|
||||
emoji (reagent/atom (emoji-picker.utils/random-emoji))
|
||||
on-change-text #(reset! account-name %)
|
||||
set-account-color #(reset! account-color %)
|
||||
set-emoji #(reset! emoji %)
|
||||
state {:account-name account-name
|
||||
:account-color account-color
|
||||
:emoji emoji}]
|
||||
(fn []
|
||||
(let [customization-color (rf/sub [:profile/customization-color])
|
||||
;; Having a keypair means the user is importing it or creating it.
|
||||
{:keys [keypair-name]} (rf/sub [:wallet/create-account-new-keypair])]
|
||||
|
||||
(rn/use-unmount #(rf/dispatch [:wallet/clear-create-account]))
|
||||
|
||||
(if keypair-name
|
||||
[add-new-keypair-variant
|
||||
{:customization-color customization-color
|
||||
:on-change-text on-change-text
|
||||
:set-account-color set-account-color
|
||||
:set-emoji set-emoji
|
||||
:state state
|
||||
:keypair-name keypair-name}]
|
||||
[derive-account-variant
|
||||
{:customization-color customization-color
|
||||
:on-change-text on-change-text
|
||||
:set-account-color set-account-color
|
||||
:set-emoji set-emoji
|
||||
:state state}])))))
|
||||
|
|
|
@ -2,15 +2,18 @@
|
|||
(:require
|
||||
[clojure.string :as string]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as rf]))
|
||||
[re-frame.core :as rf]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.wallet/create-account-from-mnemonic
|
||||
(fn [{:keys [seed-phrase keypair-name]}]
|
||||
(native-module/create-account-from-mnemonic
|
||||
{: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)}])))))
|
||||
(fn [{:keys [mnemonic-phrase paths on-success]
|
||||
:or {paths []}}]
|
||||
(let [phrase (condp #(%1 %2) mnemonic-phrase
|
||||
string? mnemonic-phrase
|
||||
coll? (string/join " " mnemonic-phrase)
|
||||
(log/error "Unexpected value " mnemonic-phrase))]
|
||||
(native-module/create-account-from-mnemonic
|
||||
{:MnemonicPhrase phrase
|
||||
:paths paths}
|
||||
on-success))))
|
||||
|
|
|
@ -16,17 +16,18 @@
|
|||
[utils.i18n :as i18n]
|
||||
[utils.number]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(rf/reg-event-fx :wallet/show-account-created-toast
|
||||
(fn [{:keys [db]} [address]]
|
||||
(let [account (get-in db [:wallet :accounts address])]
|
||||
(let [account-name (get-in db [:wallet :accounts address :name])]
|
||||
{:db (update db :wallet dissoc :navigate-to-account :new-account?)
|
||||
:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:id :new-wallet-account-created
|
||||
:type :positive
|
||||
:text (i18n/label :t/account-created {:name (:name account)})}]]]})))
|
||||
:text (i18n/label :t/account-created {:name account-name})}]]]})))
|
||||
|
||||
(rf/reg-event-fx :wallet/navigate-to-account
|
||||
(fn [{:keys [db]} [address]]
|
||||
|
@ -173,30 +174,22 @@
|
|||
[{:keys [db]}]
|
||||
{:db (update-in db [:wallet :ui] dissoc :scanned-address)})
|
||||
|
||||
(rf/reg-event-fx :wallet/create-derived-addresses
|
||||
(fn [{:keys [db]} [{:keys [sha3-pwd path]} on-success]]
|
||||
(let [{:keys [address]} (:profile/profile db)]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_getDerivedAddresses"
|
||||
:params [sha3-pwd address [path]]
|
||||
:on-success on-success
|
||||
:on-error #(log/info "failed to derive address " %)}]]]})))
|
||||
|
||||
(rf/reg-event-fx :wallet/add-account-success
|
||||
(fn [{:keys [db]} [address]]
|
||||
{:db (update db
|
||||
:wallet assoc
|
||||
:navigate-to-account address
|
||||
:new-account? true)
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :navigate-to-account] address)
|
||||
(assoc-in [:wallet :new-account?] true))
|
||||
:fx [[:dispatch [:wallet/get-accounts]]
|
||||
[:dispatch [:wallet/get-keypairs]]
|
||||
[:dispatch [:wallet/clear-new-keypair]]]}))
|
||||
[:dispatch [:wallet/clear-create-account]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/add-account
|
||||
(fn [{:keys [db]}
|
||||
[{: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)
|
||||
[{:keys [password account-name emoji color type]
|
||||
:or {type :generated}}
|
||||
{:keys [public-key address path] :as _derived-account}]]
|
||||
(let [lowercase-address (some-> address
|
||||
(string/lower-case))
|
||||
key-uid (get-in db [:wallet :ui :create-account :selected-keypair-uid])
|
||||
account-config {:key-uid (when (= type :generated) key-uid)
|
||||
:wallet false
|
||||
|
@ -210,30 +203,11 @@
|
|||
:colorID color}]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "accounts_addAccount"
|
||||
:params [(when (= type :generated) sha3-pwd) account-config]
|
||||
:params [(when (= type :generated)
|
||||
(security/safe-unmask-data password))
|
||||
account-config]
|
||||
:on-success [:wallet/add-account-success lowercase-address]
|
||||
:on-error #(log/info "failed to create account " %)}]]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/derive-address-and-add-account
|
||||
(fn [_ [account-details]]
|
||||
(let [on-success (fn [derived-address-details]
|
||||
(rf/dispatch [:wallet/add-account account-details
|
||||
(first derived-address-details)]))]
|
||||
{:fx [[:dispatch [:wallet/create-derived-addresses account-details on-success]]]})))
|
||||
|
||||
(defn add-keypair-and-create-account
|
||||
[_ [{:keys [sha3-pwd new-keypair]}]]
|
||||
(let [lowercase-address (if (:address new-keypair)
|
||||
(string/lower-case (:address new-keypair))
|
||||
(:address new-keypair))]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "accounts_addKeypair"
|
||||
:params [sha3-pwd new-keypair]
|
||||
:on-success [:wallet/add-account-success lowercase-address]
|
||||
:on-error #(log/info "failed to create keypair " %)}]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/add-keypair-and-create-account add-keypair-and-create-account)
|
||||
:on-error #(log/info "failed to create account " % account-config)}]]]})))
|
||||
|
||||
(defn get-keypairs
|
||||
[_]
|
||||
|
|
|
@ -47,6 +47,11 @@
|
|||
:<- [:wallet/ui]
|
||||
:-> :create-account)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/create-account-new-keypair
|
||||
:<- [:wallet/create-account]
|
||||
:-> :new-keypair)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/network-filter
|
||||
:<- [:wallet/ui]
|
||||
|
@ -165,6 +170,25 @@
|
|||
:<- [:wallet/create-account]
|
||||
:-> :selected-keypair-uid)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/selected-keypair
|
||||
:<- [:wallet/keypairs]
|
||||
:<- [:wallet/selected-keypair-uid]
|
||||
(fn [[keypairs selected-keypair-uid]]
|
||||
(some #(when (= (:key-uid %) selected-keypair-uid)
|
||||
%)
|
||||
keypairs)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/selected-primary-keypair?
|
||||
:<- [:wallet/keypairs]
|
||||
:<- [:wallet/selected-keypair-uid]
|
||||
(fn [[keypairs selected-keypair-uid]]
|
||||
(let [primary-keypair-uid (->> keypairs
|
||||
(some #(when (= (:type %) "profile") %))
|
||||
(:key-uid))]
|
||||
(= selected-keypair-uid primary-keypair-uid))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/selected-networks->chain-ids
|
||||
:<- [:wallet/selected-networks]
|
||||
|
|
Loading…
Reference in New Issue