[#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 (handlers/register-handler-fx
:hardwallet.ui/pair-code-next-button-pressed :hardwallet.ui/pair-code-next-button-pressed
(fn [cofx] (fn [cofx]
(hardwallet/pair cofx))) (hardwallet/pair-code-next-button-pressed cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/recovery-phrase-next-button-pressed :hardwallet.ui/recovery-phrase-next-button-pressed
@ -1366,6 +1366,31 @@
(fn [cofx _] (fn [cofx _]
(hardwallet/proceed-to-generate-mnemonic 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 (handlers/register-handler-fx
:hardwallet/generate-mnemonic :hardwallet/generate-mnemonic
(fn [cofx _] (fn [cofx _]

View File

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

View File

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

View File

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

View File

@ -91,6 +91,24 @@
{:on-press #(re-frame/dispatch [:hardwallet.ui/card-ready-next-button-pressed]) {:on-press #(re-frame/dispatch [:hardwallet.ui/card-ready-next-button-pressed])
:forward? true}]]]]])) :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 [] (defview display-recovery-phrase []
(letsubs [mnemonic [:hardwallet-mnemonic]] (letsubs [mnemonic [:hardwallet-mnemonic]]
(let [mnemonic-vec (vec (map-indexed vector (clojure.string/split mnemonic #" ")))] (let [mnemonic-vec (vec (map-indexed vector (clojure.string/split mnemonic #" ")))]
@ -419,6 +437,17 @@
:estimated-time-seconds 30 :estimated-time-seconds 30
:step-number 3}]) :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] (defn- content [step]
(case step (case step
:begin [begin] :begin [begin]
@ -438,6 +467,8 @@
:recovery-phrase-confirm-word1 [recovery-phrase-confirm-word step] :recovery-phrase-confirm-word1 [recovery-phrase-confirm-word step]
:recovery-phrase-confirm-word2 [recovery-phrase-confirm-word step] :recovery-phrase-confirm-word2 [recovery-phrase-confirm-word step]
:error [error] :error [error]
:import-account [import-account]
:importing-account [importing-account]
[begin])) [begin]))
(defview hardwallet-setup [] (defview hardwallet-setup []

View File

@ -843,6 +843,8 @@
"generating-mnemonic": "Generating mnemonic phrase", "generating-mnemonic": "Generating mnemonic phrase",
"next-step-generating-mnemonic": "Next step is generating mnemonic phrase for your card", "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", "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", "this-will-take-few-seconds": "This will take a few seconds",
"finishing-card-setup": "Finishing card setup", "finishing-card-setup": "Finishing card setup",
"finishing-card-setup-steps": "> Loading keys to the card\n> Generating account", "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": "Enter pair code",
"enter-pair-code-description": "SECURITY NOTE: Use only the code you wrote down during card setup.", "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", "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", "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.", "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", "no-account-on-card": "No account on this card",