[#18817] Import private key: UI for key pair name (#19747)

This commit is contained in:
Nikolay 2024-05-13 12:39:42 +03:00 committed by GitHub
parent 439edc39a6
commit 2618a55dbc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 209 additions and 138 deletions

View File

@ -3,6 +3,7 @@
(def container
{:flex-direction :row
:flex 1
:justify-content :space-between})
(def right-counter

View File

@ -90,3 +90,18 @@
(cske/transform-keys transforms/->kebab-case-keyword derived-address)))}))
(rf/reg-event-fx :wallet/get-derived-addresses-success get-derived-addresses-success)
(rf/reg-event-fx
:wallet/set-private-key
(fn [{:keys [db]} [value]]
{:db (assoc-in db [:wallet :ui :create-account :private-key] (security/mask-data value))}))
(rf/reg-event-fx
:wallet/set-public-address
(fn [{:keys [db]} [value]]
{:db (assoc-in db [:wallet :ui :create-account :public-address] value)}))
(rf/reg-event-fx
:wallet/clear-private-key-data
(fn [{:keys [db]} _]
{:db (update-in db [:wallet :ui :create-account] dissoc :private-key :public-address)}))

View File

@ -1,5 +1,6 @@
(ns status-im.contexts.wallet.add-account.create-account.import-private-key.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.theme :as theme]
[react-native.clipboard :as clipboard]
@ -12,45 +13,50 @@
[utils.re-frame :as rf]))
(defn- address-input
[{:keys [input-value set-input-value set-flow-state error?]}]
(let [check-address (rn/use-callback
(debounce/debounce (fn [v]
(if (empty? v)
(set-flow-state nil)
;; TODO check for validation
(if-not (v/private-key? v)
(set-flow-state :invalid-private-key)
;; TODO add real requests
(do
(set-flow-state :scanning)
(js/setTimeout
set-flow-state
400
(rand-nth [:active-address :inactive-address]))))))
500))
on-change (rn/use-callback
(fn [v]
(set-input-value v)
(check-address v)))
on-paste (rn/use-callback
(fn []
(clipboard/get-string
(fn [clipboard]
(when-not (empty? clipboard)
(on-change clipboard))))))]
[{:keys [input-value set-flow-state error?]}]
(let [check-address
(rn/use-callback
(debounce/debounce
(fn [v]
(if (empty? v)
(set-flow-state nil)
;; TODO check for validation
(if-not (v/private-key? v)
(set-flow-state :invalid-private-key)
;; TODO add real requests
(do
(set-flow-state :scanning)
;; TODO get real address
;; Should be fixed in #18819
(rf/dispatch [:wallet/set-public-address
"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"])
(js/setTimeout set-flow-state 400 (rand-nth [:active-address :inactive-address]))))))
500))
on-change (rn/use-callback
(fn [v]
(rf/dispatch [:wallet/set-private-key v])
(check-address v)))
on-paste (rn/use-callback
(fn []
(clipboard/get-string
(fn [clipboard]
(when-not (empty? clipboard)
(on-change clipboard))))))]
[quo/input
{:accessibility-label :add-address-to-watch
{:accessibility-label :import-private-key
:placeholder (i18n/label :t/enter-private-key-placeholder)
:container-style style/input
:label (i18n/label :t/private-key)
:type :password
:error? error?
:return-key-type :done
:auto-focus true
:on-change-text on-change
:button (when (empty? input-value)
{:on-press on-paste
:text (i18n/label :t/paste)})
:value input-value}]))
:default-value input-value}]))
(defn- activity-indicator
[state]
@ -84,13 +90,29 @@
:style style/indicator)
(i18n/label message)])))
(defn on-unmount
[]
(rf/dispatch [:wallet/clear-private-key-data]))
(defn navigate-back
[]
(rf/dispatch [:navigate-back]))
(defn navigate-to-keypair-import
[]
(rf/dispatch [:navigate-to
:screen/wallet.keypair-name
{:workflow :import-private-key}]))
(defn view
[]
(let [theme (theme/use-theme)
customization-color (rf/sub [:profile/customization-color])
[input-value set-input-value] (rn/use-state "")
[flow-state set-flow-state] (rn/use-state)
error? (= :invalid-private-key flow-state)]
(let [theme (theme/use-theme)
customization-color (rf/sub [:profile/customization-color])
private-key (rf/sub [:wallet/import-private-key])
public-address (rf/sub [:wallet/public-address])
[flow-state set-flow-state] (rn/use-state nil)
error? (= :invalid-private-key flow-state)]
(rn/use-unmount on-unmount)
[rn/view {:flex 1}
[floating-button-page/view
{:customization-color customization-color
@ -98,7 +120,7 @@
{:background :white
:type :no-title
:icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])}]
:on-press navigate-back}]
:footer [:<>
(when-not (#{:active-address :inactive-address} flow-state)
[quo/information-box
@ -108,8 +130,8 @@
(i18n/label :t/import-private-key-info)])
[quo/button
{:customization-color customization-color
:disabled? (or (empty? input-value) error?)
:on-press #()}
:disabled? (or (string/blank? private-key) error?)
:on-press navigate-to-keypair-import}
(i18n/label :t/continue)]]}
[quo/page-top
{:container-style style/page-top
@ -117,17 +139,16 @@
:description :text
:description-text (i18n/label :t/enter-private-key)}]
[address-input
{:input-value input-value
:set-input-value set-input-value
:set-flow-state set-flow-state
:error? error?}]
{:input-value private-key
:set-flow-state set-flow-state
:error? error?}]
(when (#{:scanning :active-address :inactive-address} flow-state)
[rn/view {:style style/key-section}
[quo/section-label
{:section (i18n/label :t/private-key-public-address)
:container-style style/section-label}]
;; TODO Get real address
[rn/view {:style (style/public-address flow-state theme)}
[quo/text "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"]]])
(when (seq input-value)
(when (seq public-address)
[rn/view {:style (style/public-address flow-state theme)}
[quo/text public-address]])])
(when (seq private-key)
[activity-indicator flow-state])]]))

View File

@ -0,0 +1,12 @@
(ns status-im.contexts.wallet.add-account.create-account.key-pair-name.style)
(def page-top
{:margin-top 2})
(def input
{:padding-top 12
:padding-horizontal 20})
(def error-container
{:padding-horizontal 20
:padding-vertical 8})

View File

@ -0,0 +1,94 @@
(ns status-im.contexts.wallet.add-account.create-account.key-pair-name.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.floating-button-page.view :as floating-button-page]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.validation.general :as validators]
[status-im.contexts.wallet.add-account.create-account.key-pair-name.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def ^:private key-pair-name-max-length 15)
(def ^:private key-pair-name-min-length 5)
(def error-messages
{:too-long (i18n/label :t/key-name-error-length)
:too-short (i18n/label :t/key-name-error-too-short {:count key-pair-name-min-length})
:emoji (i18n/label :t/key-name-error-emoji)
:special-char (i18n/label :t/key-name-error-special-char)})
(defn navigate-back
[]
(rf/dispatch [:navigate-back]))
(defn view
[]
(let [{:keys [workflow]} (rf/sub [:get-screen-params])
customization-color (rf/sub [:profile/customization-color])
[key-pair-name set-key-pair-name] (rn/use-state "")
[error set-error] (rn/use-state nil)
on-change-text (rn/use-callback
(fn [value]
(set-key-pair-name value)
(cond
(> (count value) key-pair-name-max-length)
(set-error :too-long)
(< 0 (count value) key-pair-name-min-length)
(set-error :too-short)
(validators/has-emojis? value)
(set-error :emoji)
(validators/has-special-characters? value)
(set-error :special-char)
:else (set-error nil))))
on-continue (rn/use-callback
(fn [_]
(case workflow
;; TODO issue #19759. Implement creation account from
;; private key
:import-private-key
(not-implemented/alert)
:new-key-pair
(rf/dispatch [:wallet/new-keypair-continue
{:keypair-name key-pair-name}])
(js/alert "Unknown workflow")))
[workflow key-pair-name])
disabled? (or (some? error) (string/blank? key-pair-name))]
[rn/view {:style {:flex 1}}
[floating-button-page/view
{:customization-color customization-color
:header [quo/page-nav
{:icon-name :i/arrow-left
:on-press navigate-back
:accessibility-label :top-bar}]
:footer [quo/button
{:customization-color customization-color
:disabled? disabled?
:on-press on-continue}
(i18n/label :t/continue)]}
[quo/page-top
{:title (i18n/label :t/keypair-name)
:description-text (i18n/label :t/keypair-name-description)
:description :text
:container-style style/page-top}]
[quo/input
{:container-style style/input
:placeholder (i18n/label :t/keypair-name-input-placeholder)
:label (i18n/label :t/keypair-name)
:char-limit key-pair-name-max-length
:auto-focus true
:on-change-text on-change-text
:error error}]
(when error
[quo/info-message
{:type :error
:size :default
:icon :i/info
:container-style style/error-container}
(get error-messages error)])]]))

View File

@ -81,7 +81,8 @@
(reset! show-error? false)
(when (= @quiz-index questions-count)
(rf/dispatch [:navigate-to
:screen/wallet.keypair-name])))
:screen/wallet.keypair-name
{:workflow :new-key-pair}])))
(do
(when (> @incorrect-count 0)
(rf/dispatch [:show-bottom-sheet

View File

@ -1,13 +0,0 @@
(ns status-im.contexts.wallet.add-account.create-account.new-keypair.keypair-name.style)
(def header-container
{:margin-horizontal 20
:margin-top 12
:margin-bottom 20})
(def bottom-action
{:margin-horizontal -20})
(def error-container
{:margin-left 20
:margin-vertical 8})

View File

@ -1,75 +0,0 @@
(ns status-im.contexts.wallet.add-account.create-account.new-keypair.keypair-name.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.floating-button-page.view :as floating-button-page]
[status-im.common.validation.general :as validators]
[status-im.contexts.wallet.add-account.create-account.new-keypair.keypair-name.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def keypair-name-max-length 15)
(def keypair-name-min-length 5)
(def error-messages
{:length (i18n/label :t/key-name-error-length)
:emoji (i18n/label :t/key-name-error-emoji)
:special-char (i18n/label :t/key-name-error-special-char)})
(defn navigate-back [] (rf/dispatch [:navigate-back]))
(defn view
[]
(let [[keypair-name set-keypair-name] (rn/use-state "")
customization-color (rf/sub [:profile/customization-color])
[error set-error] (rn/use-state false)
on-change-text (rn/use-callback (fn [value]
(set-keypair-name value)
(cond
(> (count value) keypair-name-max-length)
(set-error :length)
(validators/has-emojis? value) (set-error
:emoji)
(validators/has-special-characters? value)
(set-error :special-char)
:else (set-error nil))))
on-continue (rn/use-callback #(rf/dispatch [:wallet/new-keypair-continue
{:keypair-name
keypair-name}])
[keypair-name])]
[rn/view {:style {:flex 1}}
[floating-button-page/view
{:header [quo/page-nav
{:icon-name :i/arrow-left
:on-press navigate-back
:accessibility-label :top-bar}]
:footer [quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/continue)
:button-one-props {:disabled? (or (pos? error)
(< (count keypair-name)
keypair-name-min-length)
(> (count keypair-name)
keypair-name-max-length))
:customization-color customization-color
:on-press on-continue}
:container-style style/bottom-action}]}
[quo/text-combinations
{:container-style style/header-container
:title (i18n/label :t/keypair-name)
:description (i18n/label :t/keypair-name-description)}]
[quo/input
{:container-style {:margin-horizontal 20}
:placeholder (i18n/label :t/keypair-name-input-placeholder)
:label (i18n/label :t/keypair-name)
:char-limit keypair-name-max-length
:auto-focus true
:on-change-text on-change-text
:error error}]
(when error
[quo/info-message
{:type :error
:size :default
:icon :i/info
:container-style style/error-container}
(get error-messages error)])]]))

View File

@ -79,12 +79,12 @@
wallet-edit-derivation-path]
[status-im.contexts.wallet.add-account.create-account.import-private-key.view :as
wallet-import-private-key]
[status-im.contexts.wallet.add-account.create-account.key-pair-name.view :as
wallet-key-pair-name]
[status-im.contexts.wallet.add-account.create-account.new-keypair.backup-recovery-phrase.view :as
wallet-backup-recovery-phrase]
[status-im.contexts.wallet.add-account.create-account.new-keypair.check-your-backup.view :as
wallet-check-your-backup]
[status-im.contexts.wallet.add-account.create-account.new-keypair.keypair-name.view :as
wallet-keypair-name]
[status-im.contexts.wallet.add-account.create-account.select-keypair.view :as wallet-select-keypair]
[status-im.contexts.wallet.add-account.create-account.view :as wallet-create-account]
[status-im.contexts.wallet.bridge.bridge-to.view :as wallet-bridge-to]
@ -428,8 +428,8 @@
:component wallet-check-your-backup/view}
{:name :screen/wallet.keypair-name
:options {:insets {:top? true :bottom? true}}
:component wallet-keypair-name/view}
:options {:insets {:top? true}}
:component wallet-key-pair-name/view}
{:name :screen/wallet.enter-seed-phrase
:component enter-seed-phrase/view}

View File

@ -5,7 +5,8 @@
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.subs.wallet.add-account.address-to-watch]
[utils.number]))
[utils.number]
[utils.security.core :as security]))
(defn- filter-networks
[chain-ids network-details]
@ -421,3 +422,16 @@
{:tokens tokens
:currency currency
:currency-symbol currency-symbol})))
(rf/reg-sub
:wallet/import-private-key
:<- [:wallet/create-account]
(fn [create-account]
(some-> create-account
:private-key
security/unmask)))
(rf/reg-sub
:wallet/public-address
:<- [:wallet/create-account]
:-> :public-address)

View File

@ -2593,6 +2593,7 @@
"key-name-error-length": "Key name too long",
"key-name-error-emoji": "Emojis are not allowed",
"key-name-error-special-char": "Special characters are not allowed",
"key-name-error-too-short": "Key pair name must be at least {{count}} characters",
"display": "Display",
"testnet-mode-enabled": "Testnet mode enabled",
"online-community-member": "Online",