[#7927] import keycard account to new device

Signed-off-by: Dmitry Novotochinov <dmitry.novot@gmail.com>
This commit is contained in:
Dmitry Novotochinov 2019-04-30 13:52:14 +03:00
parent 5762967a44
commit 5d6d549511
No known key found for this signature in database
GPG Key ID: 43D1DAF5AD39C927
6 changed files with 160 additions and 29 deletions

View File

@ -1229,7 +1229,7 @@
(handlers/register-handler-fx
:hardwallet.ui/pair-code-next-button-pressed
(fn [cofx]
(hardwallet/pair cofx)))
(hardwallet/pair-code-next-button-pressed cofx)))
(handlers/register-handler-fx
:hardwallet.ui/recovery-phrase-next-button-pressed
@ -1366,6 +1366,31 @@
(fn [cofx _]
(hardwallet/proceed-to-generate-mnemonic cofx)))
(handlers/register-handler-fx
:hardwallet.ui/import-account-back-button-pressed
(fn [cofx _]
(hardwallet/import-account-back-button-pressed cofx)))
(handlers/register-handler-fx
:hardwallet.ui/import-account-next-button-pressed
(fn [cofx _]
(hardwallet/import-account-next-button-pressed cofx)))
(handlers/register-handler-fx
:hardwallet/load-importing-account-screen
(fn [cofx _]
(hardwallet/load-importing-account-screen cofx)))
(handlers/register-handler-fx
:hardwallet/import-account
(fn [cofx _]
(hardwallet/import-account cofx)))
(handlers/register-handler-fx
:hardwallet/verify-pin
(fn [cofx _]
(hardwallet/verify-pin cofx)))
(handlers/register-handler-fx
:hardwallet/generate-mnemonic
(fn [cofx _]

View File

@ -111,7 +111,7 @@
(defn verify-pin
[{:keys [pin pairing]}]
(when (and pairing pin)
(when (and pairing (not-empty pin))
(.. keycard
(verifyPin pairing pin)
(then #(re-frame/dispatch [:hardwallet.callback/on-verify-pin-success %]))
@ -163,11 +163,12 @@
(catch #(re-frame/dispatch [:hardwallet.callback/on-delete-error (error-object->map %)])))))
(defn get-keys
[{:keys [pairing pin]}]
(.. keycard
(getKeys pairing pin)
(then #(re-frame/dispatch [:hardwallet.callback/on-get-keys-success %]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-get-keys-error (error-object->map %)]))))
[{:keys [pairing pin on-success]}]
(when (and pairing (not-empty pin))
(.. keycard
(getKeys pairing pin)
(then #(re-frame/dispatch [(or on-success :hardwallet.callback/on-get-keys-success) %]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-get-keys-error (error-object->map %)])))))
(defn sign
[{:keys [pairing pin hash]}]

View File

@ -92,20 +92,12 @@
:cancel-button-text ""
:confirm-button-text :t/okay}})
(fx/defn show-keycard-has-account-alert
[{:keys [db] :as cofx}]
(fx/merge cofx
{:db (assoc-in db [:hardwallet :setup-step] nil)
:utils/show-confirmation {:title nil
:content (i18n/label :t/keycard-has-account-on-it)
:cancel-button-text ""
:confirm-button-text :t/okay}}))
(defn- card-state->setup-step [state]
(case state
:not-paired :pair
:no-pairing-slots :no-slots
:init :card-ready
:account :import-account
:begin))
(defn- get-card-state
@ -140,23 +132,39 @@
[{:keys [db]} card-state]
{:db (assoc-in db [:hardwallet :setup-step] (card-state->setup-step card-state))})
(fx/defn show-keycard-has-account-alert
[{:keys [db] :as cofx}]
(fx/merge cofx
{:db (assoc-in db [:hardwallet :setup-step] nil)
:utils/show-confirmation {:title nil
:content (i18n/label :t/keycard-has-account-on-it)
:cancel-button-text ""
:confirm-button-text :t/okay}}))
(fx/defn check-card-state
[{:keys [db] :as cofx}]
(let [app-info (get-in db [:hardwallet :application-info])
card-state (get-card-state app-info)
flow (get-in db [:hardwallet :flow])
instance-uid (:instance-uid app-info)
pairing (get-pairing db instance-uid)
app-info' (if pairing (assoc app-info :paired? true) app-info)
card-state (get-card-state app-info')
setup-running? (boolean (get-in db [:hardwallet :setup-step]))
db' (assoc-in db [:hardwallet :card-state] card-state)]
(if setup-running?
(fx/merge cofx
{:db db'}
(set-setup-step card-state)
(if (contains? #{:init :pre-init} card-state)
(if (or (contains? #{:init :pre-init} card-state)
(and (= :account card-state)
(= :import flow)))
(navigation/navigate-to-cofx :hardwallet-setup nil)
(when-not (= :not-paired card-state)
(navigation/navigate-to-cofx :hardwallet-authentication-method nil)))
(when (= card-state :blank)
(show-no-keycard-applet-alert))
(when (= card-state :account)
(when (and (= card-state :account)
(= flow :create))
(show-keycard-has-account-alert)))
{:db db'})))
@ -307,10 +315,13 @@
[{:keys [db] :as cofx} info on-success]
(let [info' (js->clj info :keywordize-keys true)
{:keys [pin-retry-counter puk-retry-counter instance-uid]} info'
connect-screen? (= (:view-id db) :hardwallet-connect)
view-id (:view-id db)
connect-screen? (contains? #{:hardwallet-connect
:hardwallet-connect-sign
:hardwallet-connect-settings} view-id)
{:keys [card-state on-card-read]} (:hardwallet db)
on-success' (or on-success on-card-read)
accounts-screen? (= :accounts (:view-id db))
accounts-screen? (= :accounts view-id)
auto-login? (and accounts-screen?
(not= on-success :hardwallet/auto-login))
setup-starting? (= :begin (get-in db [:hardwallet :setup-step]))
@ -580,16 +591,29 @@
(dispatch-event :hardwallet/pair)
(navigation/navigate-to-cofx :hardwallet-connect nil)))))
(fx/defn pair* [_ password]
{:hardwallet/pair {:password password}})
(fx/defn pair
[{:keys [db] :as cofx}]
(let [{:keys [password]} (get-in cofx [:db :hardwallet :secrets])
card-connected? (get-in db [:hardwallet :card-connected?])]
(if card-connected?
{:hardwallet/pair {:password password}}
(fx/merge cofx
{:db (assoc-in db [:hardwallet :on-card-connected] :hardwallet/pair)}
(fx/merge cofx
{:db (assoc-in db [:hardwallet :on-card-connected] :hardwallet/pair)}
(if card-connected?
(pair* password)
(navigation/navigate-to-cofx :hardwallet-connect nil)))))
(fx/defn pair-code-next-button-pressed
[{:keys [db] :as cofx}]
(let [pairing (get-in db [:hardwallet :secrets :pairing])
paired-on (get-in db [:hardwallet :secrets :paired-on] (utils.datetime/timestamp))]
(if pairing
{:db (-> db
(assoc-in [:hardwallet :setup-step] :import-account)
(assoc-in [:hardwallet :secrets :paired-on] paired-on))}
(pair cofx))))
(fx/defn return-back-from-nfc-settings [{:keys [db]}]
(when (contains? #{:hardwallet-connect
:hardwallet-connect-sign
@ -801,7 +825,7 @@
(defn- unblock-pin
[{:keys [db] :as cofx}]
(let [puk (vector->string (get-in cofx [:db :hardwallet :pin :puk]))
(let [puk (vector->string (get-in db [:hardwallet :pin :puk]))
instance-uid (get-in db [:hardwallet :application-info :instance-uid])
card-connected? (get-in db [:hardwallet :card-connected?])
pairing (get-pairing db instance-uid)]
@ -899,6 +923,34 @@
:hardwallet-connect-sign)
nil)))))
(fx/defn import-account
[{:keys [db] :as cofx}]
(let [{:keys [pairing]} (get-in db [:hardwallet :secrets])
instance-uid (get-in db [:hardwallet :application-info :instance-uid])
pairing' (or pairing (get-pairing db instance-uid))
pin (vector->string (get-in db [:hardwallet :pin :import-account]))]
(fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :keycard-instance-uid] instance-uid)
(assoc-in [:hardwallet :secrets] {:pairing pairing'
:paired-on (utils.datetime/timestamp)}))
:hardwallet/get-keys {:pairing pairing'
:pin pin
:on-success :hardwallet.callback/on-generate-and-load-key-success}})))
(fx/defn load-importing-account-screen
[{:keys [db] :as cofx}]
(let [card-connected? (get-in db [:hardwallet :card-connected?])]
(fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :on-card-connected] :hardwallet/load-importing-account-screen)
(assoc-in [:hardwallet :setup-step] :importing-account))}
(when card-connected?
(import-account))
(navigation/navigate-to-cofx (if card-connected?
:hardwallet-setup
:hardwallet-connect) nil))))
; PIN enter steps:
; login - PIN is used to login
; sign - PIN for transaction sign
@ -908,6 +960,7 @@
(fx/defn process-pin-input
[{:keys [db]}]
(let [enter-step (get-in db [:hardwallet :pin :enter-step])
setup-step (get-in db [:hardwallet :setup-step])
pin (get-in db [:hardwallet :pin enter-step])
numbers-entered (count pin)]
(cond-> {:db (assoc-in db [:hardwallet :pin :status] nil)}
@ -925,6 +978,11 @@
(= default-pin (vector->string pin)))
(pin-enter-error :t/cannot-use-default-pin)
(and (= setup-step :import-account)
(= enter-step :import-account)
(= pin-code-length numbers-entered))
(load-importing-account-screen)
(and (= enter-step :current)
(= pin-code-length numbers-entered))
(verify-pin)
@ -1193,6 +1251,17 @@
{:db (assoc-in db [:hardwallet :secrets :mnemonic] mnemonic)}
(load-loading-keys-screen)))))
(fx/defn import-account-back-button-pressed
[cofx]
(navigation/navigate-to-cofx cofx :hardwallet-authentication-method nil))
(fx/defn import-account-next-button-pressed
[{:keys [db] :as cofx}]
(fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :pin :enter-step] :import-account))}
(navigation/navigate-to-cofx :enter-pin-login nil)))
(fx/defn generate-and-load-key
[{:keys [db] :as cofx}]
(let [{:keys [mnemonic pairing pin]} (get-in db [:hardwallet :secrets])
@ -1233,7 +1302,8 @@
wallet-address
instance-uid
encryption-public-key]} (js->clj data :keywordize-keys true)
whisper-public-key' (str "0x" whisper-public-key)]
whisper-public-key' (str "0x" whisper-public-key)
instance-uid' (get-in db [:hardwallet :keycard-instance-uid])]
(fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :whisper-public-key] whisper-public-key')
@ -1241,7 +1311,7 @@
(assoc-in [:hardwallet :whisper-address] whisper-address)
(assoc-in [:hardwallet :wallet-address] wallet-address)
(assoc-in [:hardwallet :encryption-public-key] encryption-public-key)
(assoc-in [:hardwallet :keycard-instance-uid] instance-uid)
(assoc-in [:hardwallet :keycard-instance-uid] (or instance-uid' instance-uid))
(assoc-in [:hardwallet :on-card-connected] nil)
(update :hardwallet dissoc :recovery-phrase)
(update-in [:hardwallet :secrets] dissoc :pin :puk :password)

View File

@ -147,12 +147,14 @@
:title-label (case step
:current :t/current-pin
:login :t/current-pin
:import-account :t/current-pin
:original :t/create-a-pin
:confirmation :t/repeat-pin
:t/current-pin)
:description-label (case step
:current :t/current-pin-description
:sign :t/current-pin-description
:import-account :t/current-pin-description
:login :t/login-pin-description
:t/new-pin-description)
:step step

View File

@ -91,6 +91,24 @@
{:on-press #(re-frame/dispatch [:hardwallet.ui/card-ready-next-button-pressed])
:forward? true}]]]]]))
(defn- import-account []
[react/view styles/card-ready-container
[react/view styles/card-ready-inner-container
[react/view (assoc styles/center-container :margin-top 68)
[react/text {:style styles/center-title-text}
(i18n/label :t/card-is-paired)]
[react/text {:style styles/estimated-time-text}
(i18n/label :t/ready-to-import-keycard-account)]]
[react/view]]
[react/view styles/back-and-next-buttons-container
[components.common/bottom-button
{:on-press #(re-frame/dispatch [:hardwallet.ui/import-account-back-button-pressed])
:back? true
:label (i18n/label :t/back)}]
[components.common/bottom-button
{:on-press #(re-frame/dispatch [:hardwallet.ui/import-account-next-button-pressed])
:forward? true}]]])
(defview display-recovery-phrase []
(letsubs [mnemonic [:hardwallet-mnemonic]]
(let [mnemonic-vec (vec (map-indexed vector (clojure.string/split mnemonic #" ")))]
@ -419,6 +437,17 @@
:estimated-time-seconds 30
:step-number 3}])
(defn- importing-account []
[react/view styles/loading-view-container
[react/view styles/center-container
[react/text {:style styles/center-title-text}
(i18n/label :t/importing-keycard-account)]
[react/text {:style styles/estimated-time-text}
(i18n/label :t/this-will-take-few-seconds)]]
[react/view styles/waiting-indicator-container
[react/activity-indicator {:animating true
:size :large}]]])
(defn- content [step]
(case step
:begin [begin]
@ -438,6 +467,8 @@
:recovery-phrase-confirm-word1 [recovery-phrase-confirm-word step]
:recovery-phrase-confirm-word2 [recovery-phrase-confirm-word step]
:error [error]
:import-account [import-account]
:importing-account [importing-account]
[begin]))
(defview hardwallet-setup []

View File

@ -843,6 +843,8 @@
"generating-mnemonic": "Generating mnemonic phrase",
"next-step-generating-mnemonic": "Next step is generating mnemonic phrase for your card",
"next-step-entering-mnemonic": "Next step is entering mnemonic phrase to import your account",
"importing-keycard-account": "Importing keycard account",
"ready-to-import-keycard-account": "We are ready to import keycard account",
"this-will-take-few-seconds": "This will take a few seconds",
"finishing-card-setup": "Finishing card setup",
"finishing-card-setup-steps": "> Loading keys to the card\n> Generating account",
@ -891,7 +893,7 @@
"enter-pair-code": "Enter pair code",
"enter-pair-code-description": "SECURITY NOTE: Use only the code you wrote down during card setup.",
"no-pairing-slots-available": "This card is already paired to 5 devices and cannot pair to this one. Please use one of the paired devices, log in with this card and free up pairing slots on the card",
"keycard-has-account-on-it": "This card has already an account on it. If you wish to change it, login first and reset your card.",
"keycard-has-account-on-it": "This card has already an account on it. If you wish to change it, login first and reset your card. If you want to import keycard account, please use \"Add existing account\"",
"card-already-linked": "Card is already linked to another account",
"keycard-unauthorized-operation": "You're unauthorized to perform this operation.\n Please tap valid card and try again.",
"no-account-on-card": "No account on this card",