Wallet: finalize kp (#18991)

Wallet: finalize kp
This commit is contained in:
Omar Basem 2024-03-01 08:09:36 +04:00 committed by GitHub
parent ac78dea8ef
commit abd2b43ce6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 189 additions and 66 deletions

View File

@ -55,7 +55,7 @@
:action :selector :action :selector
:details other-details}] :details other-details}]
theme) theme)
(h/is-truthy (h/get-by-label-text :radio-on))) (h/is-truthy (h/get-by-label-text :radio-off)))
(h/test "Options action renders" (h/test "Options action renders"
(h/render-with-theme-provider [keypair/view (h/render-with-theme-provider [keypair/view

View File

@ -1,6 +1,7 @@
(ns quo.components.wallet.keypair.style (ns quo.components.wallet.keypair.style
(:require (:require
[quo.foundations.colors :as colors])) [quo.foundations.colors :as colors]
[react-native.platform :as platform]))
(defn container (defn container
[{:keys [blur? customization-color theme selected?]}] [{:keys [blur? customization-color theme selected?]}]
@ -34,3 +35,8 @@
{:color (if blur? {:color (if blur?
colors/white-opa-40 colors/white-opa-40
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}) (colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
(defn dot
[blur? theme]
(merge (subtitle blur? theme)
{:bottom (if platform/ios? 2 -2)}))

View File

@ -11,7 +11,6 @@
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.platform :as platform]
[reagent.core :as reagent] [reagent.core :as reagent]
[utils.i18n :as i18n])) [utils.i18n :as i18n]))
@ -60,7 +59,7 @@
:accessibility-label :options-button}]])])) :accessibility-label :options-button}]])]))
(defn details-view (defn details-view
[{:keys [details stored blur? theme]}] [{:keys [details stored type blur? theme]}]
(let [{:keys [address]} details] (let [{:keys [address]} details]
[rn/view [rn/view
{:style {:flex-direction :row {:style {:flex-direction :row
@ -70,10 +69,11 @@
{:size :paragraph-2 {:size :paragraph-2
:style (style/subtitle blur? theme)} :style (style/subtitle blur? theme)}
address] address]
[text/text (when (= type :default-keypair)
{:size :paragraph-2 [text/text
:style (merge (style/subtitle blur? theme) {:bottom (if platform/ios? 2 -2)})} {:size :paragraph-2
" ∙ "] :style (style/dot blur? theme)}
" ∙ "])
[text/text [text/text
{:size :paragraph-2 {:size :paragraph-2
:style (style/subtitle blur? theme)} :style (style/subtitle blur? theme)}
@ -87,8 +87,8 @@
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}]])])) (colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}]])]))
(defn- view-internal (defn- view-internal
[] [{:keys [default-selected?]}]
(let [selected? (reagent/atom true)] (let [selected? (reagent/atom default-selected?)]
(fn [{:keys [accounts action container-style] :as props}] (fn [{:keys [accounts action container-style] :as props}]
[rn/pressable [rn/pressable
{:style (merge (style/container (merge props {:selected? @selected?})) container-style) {:style (merge (style/container (merge props {:selected? @selected?})) container-style)

View File

@ -49,7 +49,7 @@
secret-phrase (reagent/atom []) secret-phrase (reagent/atom [])
random-phrase (reagent/atom [])] random-phrase (reagent/atom [])]
(fn [] (fn []
(rn/use-effect (rn/use-mount
(fn [] (fn []
(native-module/get-random-mnemonic #(reset! secret-phrase (string/split % #"\s"))) (native-module/get-random-mnemonic #(reset! secret-phrase (string/split % #"\s")))
(native-module/get-random-mnemonic #(reset! random-phrase (string/split % #"\s"))))) (native-module/get-random-mnemonic #(reset! random-phrase (string/split % #"\s")))))

View File

@ -1,14 +1,16 @@
(ns status-im.contexts.wallet.create-account.select-keypair.view (ns status-im.contexts.wallet.create-account.select-keypair.view
(:require (:require
[clojure.string :as string]
[quo.core :as quo] [quo.core :as quo]
[react-native.core :as rn] [react-native.core :as rn]
[status-im.constants :as constants]
[status-im.contexts.profile.utils :as profile.utils] [status-im.contexts.profile.utils :as profile.utils]
[status-im.contexts.wallet.create-account.select-keypair.style :as style] [status-im.contexts.wallet.create-account.select-keypair.style :as style]
[utils.address :as utils] [utils.address :as utils]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
(defn keypair-options (defn- keypair-options
[] []
[quo/action-drawer [quo/action-drawer
[[{:icon :i/add [[{:icon :i/add
@ -26,25 +28,51 @@
:accessibility-label :import-private-key :accessibility-label :import-private-key
:label (i18n/label :t/import-private-key)}]]]) :label (i18n/label :t/import-private-key)}]]])
(def accounts (defn- parse-accounts
[{:account-props {:customization-color :turquoise [given-accounts]
:size 32 (->> given-accounts
:emoji "\uD83C\uDFB2" (filter (fn [{:keys [path]}]
:type :default (not (string/starts-with? path constants/path-eip1581))))
:name "Trip to Vegas" (map (fn [{:keys [customization-color emoji name address]}]
:address "0x0ah...71a"} {:account-props {:customization-color customization-color
:networks [{:network-name :ethereum :short-name "eth"} :size 32
{:network-name :optimism :short-name "opt"}] :emoji emoji
:state :default :type :default
:action :none}]) :name name
:address address}
:networks [{:network-name :ethereum :short-name "eth"}
{:network-name :optimism :short-name "opt"}
{:network-name :arbitrum :short-name "arb1"}]
:state :default
:action :none}))))
(defn- keypair
[item index _ {:keys [profile-picture compressed-key]}]
(let [main-account (first (:accounts item))
color (:customization-color main-account)
accounts (parse-accounts (:accounts item))]
[quo/keypair
{:customization-color color
:profile-picture (when (zero? index) profile-picture)
:status-indicator false
:type (if (zero? index) :default-keypair :other)
:stored :on-device
:on-options-press #(js/alert "Options pressed")
:action :selector
:blur? false
:details {:full-name (:name item)
:address (when (zero? index)
(utils/get-shortened-compressed-key compressed-key))}
:accounts accounts
:default-selected? (zero? index)
:container-style {:margin-horizontal 20
:margin-vertical 8}}]))
(defn view (defn view
[] []
(let [{:keys [public-key compressed-key (let [{:keys [compressed-key customization-color]} (rf/sub [:profile/profile])
customization-color]} (rf/sub [:profile/profile]) profile-with-image (rf/sub [:profile/profile-with-image])
[display-name _] (rf/sub [:contacts/contact-two-names-by-identity public-key]) keypairs (rf/sub [:wallet/keypairs])
profile-with-image (rf/sub [:profile/profile-with-image]) profile-picture (profile.utils/photo profile-with-image)]
profile-picture (profile.utils/photo profile-with-image)]
[rn/view {:style {:flex 1}} [rn/view {:style {:flex 1}}
[quo/page-nav [quo/page-nav
{:icon-name :i/close {:icon-name :i/close
@ -60,20 +88,12 @@
[:show-bottom-sheet {:content keypair-options}])} [:show-bottom-sheet {:content keypair-options}])}
:description :text :description :text
:description-text (i18n/label :t/keypairs-description)}] :description-text (i18n/label :t/keypairs-description)}]
[quo/keypair [rn/flat-list
{:customization-color customization-color {:data keypairs
:profile-picture profile-picture :render-fn keypair
:status-indicator false :render-data {:profile-picture profile-picture
:type :default-keypair :compressed-key compressed-key}
:stored :on-device :content-container-style {:padding-bottom 60}}]
:on-options-press #(js/alert "Options pressed")
:action :selector
:blur? false
:details {:full-name display-name
:address (utils/get-shortened-compressed-key compressed-key)}
:accounts accounts
:container-style {:margin-horizontal 20
:margin-vertical 8}}]
[quo/bottom-actions [quo/bottom-actions
{:actions :one-action {:actions :one-action
:button-one-label (i18n/label :t/confirm-account-origin) :button-one-label (i18n/label :t/confirm-account-origin)

View File

@ -0,0 +1,19 @@
(ns status-im.contexts.wallet.create-account.utils)
(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)}]))

View File

@ -13,13 +13,14 @@
[status-im.contexts.wallet.common.sheets.account-origin.view :as account-origin] [status-im.contexts.wallet.common.sheets.account-origin.view :as account-origin]
[status-im.contexts.wallet.common.utils :as utils] [status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.create-account.style :as style] [status-im.contexts.wallet.create-account.style :as style]
[status-im.feature-flags :as ff] [status-im.contexts.wallet.create-account.utils :as create-account.utils]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[utils.responsiveness :refer [iphone-11-Pro-20-pixel-from-width]] [utils.responsiveness :refer [iphone-11-Pro-20-pixel-from-width]]
[utils.security.core :as security] [utils.security.core :as security]
[utils.string])) [utils.string]))
(defn- get-keypair-data (defn- get-keypair-data
[primary-name derivation-path account-color {:keys [keypair-name]}] [primary-name derivation-path account-color {:keys [keypair-name]}]
[{:title (or keypair-name (i18n/label :t/keypair-title {:name primary-name})) [{:title (or keypair-name (i18n/label :t/keypair-title {:name primary-name}))
@ -30,9 +31,8 @@
:size :xxs :size :xxs
:customization-color account-color}) :customization-color account-color})
:action (when-not keypair-name :button) :action (when-not keypair-name :button)
:action-props {:on-press #(ff/alert ::ff/wallet.edit-default-keypair :action-props {:on-press (fn []
(fn [] (rf/dispatch [:navigate-to :wallet-select-keypair]))
(rf/dispatch [:navigate-to :wallet-select-keypair])))
:button-text (i18n/label :t/edit) :button-text (i18n/label :t/edit)
:alignment :flex-start} :alignment :flex-start}
:description :text :description :text
@ -50,22 +50,23 @@
(defn- f-view (defn- f-view
[] []
(let [top (safe-area/get-top) (let [top (safe-area/get-top)
bottom (safe-area/get-bottom) bottom (safe-area/get-bottom)
account-color (reagent/atom (rand-nth colors/account-colors)) account-color (reagent/atom (rand-nth colors/account-colors))
emoji (reagent/atom (emoji-picker.utils/random-emoji)) emoji (reagent/atom (emoji-picker.utils/random-emoji))
number-of-accounts (count (rf/sub [:wallet/accounts-without-watched-accounts])) number-of-accounts (count (rf/sub [:wallet/accounts-without-watched-accounts]))
account-name (reagent/atom "") account-name (reagent/atom "")
placeholder (i18n/label :t/default-account-placeholder placeholder (i18n/label :t/default-account-placeholder
{:number (inc number-of-accounts)}) {:number (inc number-of-accounts)})
derivation-path (reagent/atom (utils/get-derivation-path number-of-accounts)) derivation-path (reagent/atom (utils/get-derivation-path number-of-accounts))
{:keys [public-key]} (rf/sub [:profile/profile]) {:keys [public-key address]} (rf/sub [:profile/profile])
on-change-text #(reset! account-name %) on-change-text #(reset! account-name %)
primary-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key])) primary-name (first (rf/sub [:contacts/contact-two-names-by-identity
{window-width :width} (rn/get-window)] public-key]))
{window-width :width} (rn/get-window)]
(fn [{:keys [theme]}] (fn [{:keys [theme]}]
(let [{:keys [new-keypair]} (rf/sub [:wallet/create-account])] (let [{:keys [new-keypair]} (rf/sub [:wallet/create-account])]
(rn/use-effect (fn [] #(rf/dispatch [:wallet/clear-new-keypair]))) (rn/use-unmount #(rf/dispatch [:wallet/clear-new-keypair]))
[rn/view {:style {:flex 1}} [rn/view {:style {:flex 1}}
[quo/page-nav [quo/page-nav
{:type :no-title {:type :no-title
@ -127,7 +128,18 @@
:customization-color @account-color :customization-color @account-color
:on-auth-success (fn [entered-password] :on-auth-success (fn [entered-password]
(if new-keypair (if new-keypair
(js/alert "Feature under development") (rf/dispatch
[:wallet/add-keypair-and-create-account
{:sha3-pwd (security/safe-unmask-data
entered-password)
: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})}])
(rf/dispatch [:wallet/derive-address-and-add-account (rf/dispatch [:wallet/derive-address-and-add-account
{:sha3-pwd (security/safe-unmask-data {:sha3-pwd (security/safe-unmask-data
entered-password) entered-password)

View File

@ -104,3 +104,23 @@
:blockExplorerUrl :block-explorer-url :blockExplorerUrl :block-explorer-url
:nativeCurrencySymbol :native-currency-symbol :nativeCurrencySymbol :native-currency-symbol
:nativeCurrencyName :native-currency-symbol}))) :nativeCurrencyName :native-currency-symbol})))
(defn rename-color-id-in-data
[data]
(map (fn [item]
(update item
:accounts
(fn [accounts]
(map (fn [account]
(let [renamed-account (set/rename-keys account
{:colorId :customization-color})]
(if (contains? account :colorId)
renamed-account
(assoc renamed-account :customization-color :blue))))
accounts))))
data))
(defn parse-keypairs
[keypairs]
(let [renamed-data (rename-color-id-in-data keypairs)]
(cske/transform-keys csk/->kebab-case-keyword renamed-data)))

View File

@ -202,6 +202,35 @@
(first derived-address-details)]))] (first derived-address-details)]))]
{:fx [[:dispatch [:wallet/create-derived-addresses account-details on-success]]]}))) {: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)
(defn get-keypairs
[_]
{:fx [[:json-rpc/call
[{:method "accounts_getKeypairs"
:params []
:on-success [:wallet/get-keypairs-success]
:on-error #(log/info "failed to get keypairs " %)}]]]})
(rf/reg-event-fx :wallet/get-keypairs get-keypairs)
(defn get-keypairs-success
[{:keys [db]} [keypairs]]
{:db (assoc-in db [:wallet :keypairs] (data-store/parse-keypairs keypairs))})
(rf/reg-event-fx :wallet/get-keypairs-success get-keypairs-success)
(rf/reg-event-fx :wallet/bridge-select-token (rf/reg-event-fx :wallet/bridge-select-token
(fn [{:keys [db]} [{:keys [token stack-id]}]] (fn [{:keys [db]} [{:keys [token stack-id]}]]
(let [to-address (get-in db [:wallet :current-viewing-account-address])] (let [to-address (get-in db [:wallet :current-viewing-account-address])]
@ -371,7 +400,8 @@
(fn [] (fn []
{:fx [[:dispatch [:wallet/start-wallet]] {:fx [[:dispatch [:wallet/start-wallet]]
[:dispatch [:wallet/get-ethereum-chains]] [:dispatch [:wallet/get-ethereum-chains]]
[:dispatch [:wallet/get-accounts]]]})) [:dispatch [:wallet/get-accounts]]
[:dispatch [:wallet/get-keypairs]]]}))
(rf/reg-event-fx :wallet/share-account (rf/reg-event-fx :wallet/share-account
(fn [_ [{:keys [content title]}]] (fn [_ [{:keys [content title]}]]

View File

@ -55,7 +55,6 @@
effects (events/clear-new-keypair {:db db})] effects (events/clear-new-keypair {:db db})]
(is (match? (:db effects) expected-db)))) (is (match? (:db effects) expected-db))))
(deftest store-collectibles (deftest store-collectibles
(testing "(displayable-collectible?) helper function" (testing "(displayable-collectible?) helper function"
(let [expected-results [[true (let [expected-results [[true

View File

@ -10,7 +10,7 @@
(defonce ^:private feature-flags-config (defonce ^:private feature-flags-config
(reagent/atom (reagent/atom
{::wallet.edit-default-keypair (enabled-in-env? :FLAG_EDIT_DEFAULT_KEYPAIR_ENABLED) {::wallet.edit-default-keypair true
::wallet.bridge-token (enabled-in-env? :FLAG_BRIDGE_TOKEN_ENABLED) ::wallet.bridge-token (enabled-in-env? :FLAG_BRIDGE_TOKEN_ENABLED)
::wallet.remove-account (enabled-in-env? :FLAG_REMOVE_ACCOUNT_ENABLED) ::wallet.remove-account (enabled-in-env? :FLAG_REMOVE_ACCOUNT_ENABLED)
::wallet.network-filter (enabled-in-env? :FLAG_NETWORK_FILTER_ENABLED) ::wallet.network-filter (enabled-in-env? :FLAG_NETWORK_FILTER_ENABLED)

View File

@ -93,6 +93,11 @@
:<- [:wallet/ui] :<- [:wallet/ui]
:-> :watch-address-activity-state) :-> :watch-address-activity-state)
(rf/reg-sub
:wallet/keypairs
:<- [:wallet]
:-> :keypairs)
(rf/reg-sub (rf/reg-sub
:wallet/accounts :wallet/accounts
:<- [:wallet] :<- [:wallet]

View File

@ -497,3 +497,15 @@
(get "0x3") (get "0x3")
(assoc :network-preferences-names #{}))] (assoc :network-preferences-names #{}))]
(rf/sub [sub-name]))))) (rf/sub [sub-name])))))
(def keypairs
[{:key-uid "abc"}])
(h/deftest-sub :wallet/keypairs
[sub-name]
(testing "returns all keypairs"
(swap! rf-db/app-db
#(assoc-in % [:wallet :keypairs] keypairs))
(is
(= keypairs
(rf/sub [sub-name])))))