From 61d465a343e29c6f3796d8111c2411f713c46876 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Fri, 13 Mar 2020 14:42:26 +0200 Subject: [PATCH] Ensure that keycard flows continue when card is already connected This commit ensures that a user can flawlessly interact with a keycard, regardless of the moment when the card was tapped to the device. To make it so: - in case if the card was tapped before the interaction the user doesn't need to re-connect card to continue - in case if the connection with the card was lost during the interaction the application restarts that interaction as soon as the card was connected again (unless the user canceled the flow) --- src/status_im/hardwallet/change_pin.cljs | 40 +++++---- src/status_im/hardwallet/common.cljs | 85 ++++++++++++------- src/status_im/hardwallet/core.cljs | 70 +++++++-------- src/status_im/hardwallet/export_key.cljs | 6 +- src/status_im/hardwallet/login.cljs | 24 +++--- src/status_im/hardwallet/mnemonic.cljs | 26 +++--- src/status_im/hardwallet/onboarding.cljs | 68 +++++++-------- src/status_im/hardwallet/recovery.cljs | 53 ++++++------ src/status_im/hardwallet/sign.cljs | 20 ++--- src/status_im/hardwallet/unpair.cljs | 21 ++--- src/status_im/hardwallet/wallet.cljs | 41 ++++----- src/status_im/signing/core.cljs | 2 +- .../keycard/components/keycard_animation.cljs | 3 +- .../status_im/test/hardwallet/common.cljs | 43 ++++++++++ test/cljs/status_im/test/runner.cljs | 2 + 15 files changed, 288 insertions(+), 216 deletions(-) create mode 100644 test/cljs/status_im/test/hardwallet/common.cljs diff --git a/src/status_im/hardwallet/change_pin.cljs b/src/status_im/hardwallet/change_pin.cljs index 6526257ee3..e50da9483a 100644 --- a/src/status_im/hardwallet/change_pin.cljs +++ b/src/status_im/hardwallet/change_pin.cljs @@ -37,7 +37,7 @@ [{:keys [db] :as cofx}] (fx/merge cofx (common/clear-pin) - (common/hide-pair-sheet) + (common/hide-connection-sheet) (if (get-in db [:hardwallet :pin :puk-restore?]) (navigation/navigate-to-cofx :multiaccounts nil) (navigation/navigate-to-cofx :keycard-settings nil)))) @@ -45,22 +45,30 @@ (fx/defn change-pin {:events [:hardwallet/change-pin]} [{:keys [db] :as cofx}] - (let [pairing (common/get-pairing db) - new-pin (common/vector->string (get-in db [:hardwallet :pin :original])) - current-pin (common/vector->string (get-in db [:hardwallet :pin :current])) - setup-step (get-in db [:hardwallet :setup-step]) - card-connected? (get-in db [:hardwallet :card-connected?])] + (let [setup-step (get-in db [:hardwallet :setup-step])] + (log/debug "[hardwallet] change-pin" + "setup-step" setup-step) (if (= setup-step :pin) (onboarding/load-preparing-screen cofx) - (if card-connected? - (fx/merge cofx - {:db (assoc-in db [:hardwallet :pin :status] :verifying) - :hardwallet/change-pin {:new-pin new-pin - :current-pin current-pin - :pairing pairing}}) - (fx/merge cofx - (common/set-on-card-connected :hardwallet/change-pin) - (common/show-pair-sheet {:on-cancel [::on-cancel]})))))) + (common/show-connection-sheet + cofx + {:sheet-options {:on-cancel [::on-cancel]} + :on-card-connected :hardwallet/change-pin + :handler + (fn [{:keys [db] :as cofx}] + (let [pairing (common/get-pairing db) + new-pin (common/vector->string + (get-in db [:hardwallet :pin :original])) + current-pin (common/vector->string + (get-in db [:hardwallet :pin :current]))] + (fx/merge + cofx + {:db (assoc-in db [:hardwallet :pin :status] :verifying) + + :hardwallet/change-pin + {:new-pin new-pin + :current-pin current-pin + :pairing pairing}})))})))) (fx/defn on-change-pin-success {:events [:hardwallet.callback/on-change-pin-success]} @@ -74,7 +82,7 @@ :error-label nil}) :utils/show-popup {:title "" :content (i18n/label :t/pin-changed)}} - (common/hide-pair-sheet) + (common/hide-connection-sheet) (if puk-restore? (navigation/navigate-to-cofx :multiaccounts nil) (navigation/navigate-to-cofx :keycard-settings nil)) diff --git a/src/status_im/hardwallet/common.cljs b/src/status_im/hardwallet/common.cljs index 2762f27b45..537769ca75 100644 --- a/src/status_im/hardwallet/common.cljs +++ b/src/status_im/hardwallet/common.cljs @@ -104,6 +104,7 @@ (fx/defn set-on-card-connected [{:keys [db]} on-connect] + (log/debug "[hardwallet] set-on-card-connected" on-connect) {:db (-> db (assoc-in [:hardwallet :on-card-connected] on-connect) (assoc-in [:hardwallet :last-on-card-connected] nil))}) @@ -111,6 +112,7 @@ (fx/defn stash-on-card-connected [{:keys [db]}] (let [on-connect (get-in db [:hardwallet :on-card-connected])] + (log/debug "[hardwallet] stash-on-card-connected" on-connect) {:db (-> db (assoc-in [:hardwallet :last-on-card-connected] on-connect) (assoc-in [:hardwallet :on-card-connected] nil))})) @@ -120,18 +122,21 @@ (let [on-connect (or (get-in db [:hardwallet :on-card-connected]) (get-in db [:hardwallet :last-on-card-connected]))] + (log/debug "[hardwallet] restore-on-card-connected" on-connect) {:db (-> db (assoc-in [:hardwallet :on-card-connected] on-connect) (assoc-in [:hardwallet :last-on-card-connect] nil))})) (fx/defn clear-on-card-connected [{:keys [db]}] + (log/debug "[hardwallet] clear-on-card-connected") {:db (-> db (assoc-in [:hardwallet :on-card-connected] nil) (assoc-in [:hardwallet :last-on-card-connected] nil))}) (fx/defn set-on-card-read [{:keys [db]} on-connect] + (log/debug "[hardwallet] set-on-card-read" on-connect) {:db (-> db (assoc-in [:hardwallet :on-card-read] on-connect) (assoc-in [:hardwallet :last-on-card-read] nil))}) @@ -139,6 +144,7 @@ (fx/defn stash-on-card-read [{:keys [db]}] (let [on-connect (get-in db [:hardwallet :on-card-read])] + (log/debug "[hardwallet] stash-on-card-read" on-connect) {:db (-> db (assoc-in [:hardwallet :last-on-card-read] on-connect) (assoc-in [:hardwallet :on-card-read] nil))})) @@ -148,12 +154,14 @@ (let [on-connect (or (get-in db [:hardwallet :on-card-read]) (get-in db [:hardwallet :last-on-card-read]))] + (log/debug "[hardwallet] restore-on-card-read" on-connect) {:db (-> db (assoc-in [:hardwallet :on-card-read] on-connect) (assoc-in [:hardwallet :last-on-card-connect] nil))})) (fx/defn clear-on-card-read [{:keys [db]}] + (log/debug "[hardwallet] clear-on-card-read") {:db (-> db (assoc-in [:hardwallet :on-card-read] nil) (assoc-in [:hardwallet :last-on-card-read] nil))}) @@ -166,26 +174,36 @@ :on-connect ::on-card-connected :on-disconnect ::on-card-disconnected}))) -(fx/defn show-pair-sheet - [cofx {:keys [on-cancel] - :or {on-cancel [::cancel-sheet-confirm]}}] - (log/debug "[hardwallet] show-pair-sheet") - (let [connected? (get-in cofx [:db :hardwallet :card-connected?])] - (fx/merge cofx - {:dismiss-keyboard true} - (bottom-sheet/show-bottom-sheet - {:view {:show-handle? false - :backdrop-dismiss? false - :disable-drag? true - :content (keycard-sheet-content on-cancel - connected?)}})))) +(fx/defn show-connection-sheet + [{:keys [db] :as cofx} {:keys [on-card-connected on-card-read handler] + {:keys [on-cancel] + :or {on-cancel [::cancel-sheet-confirm]}} + :sheet-options}] + (assert (keyword? on-card-connected)) + (assert (fn? handler)) + (let [connected? (get-in db [:hardwallet :card-connected?])] + (log/debug "[hardwallet] show-sheet-with-connection-check" + "card-connected?" connected?) + (fx/merge + cofx + {:dismiss-keyboard true} + (bottom-sheet/show-bottom-sheet + {:view {:show-handle? false + :backdrop-dismiss? false + :disable-drag? true + :content (keycard-sheet-content on-cancel connected?)}}) + (when on-card-read + (set-on-card-read on-card-read)) + (set-on-card-connected on-card-connected) + (when connected? + (stash-on-card-connected)) + (when connected? + handler)))) -(fx/defn hide-pair-sheet +(fx/defn hide-connection-sheet [{:keys [db] :as cofx}] (fx/merge cofx - {:db (-> db - (assoc-in [:hardwallet :card-connected?] false) - (assoc-in [:hardwallet :card-read-in-progress?] false))} + {:db (assoc-in db [:hardwallet :card-read-in-progress?] false)} (restore-on-card-connected) (restore-on-card-read) (bottom-sheet/hide-bottom-sheet))) @@ -211,7 +229,7 @@ :hardwallet/back-button-pressed]} [cofx] (fx/merge cofx - (hide-pair-sheet) + (hide-connection-sheet) (clear-pin))) (fx/defn cancel-sheet @@ -320,7 +338,7 @@ (keychain/save-hardwallet-keys key-uid encryption-public-key whisper-private-key)) (clear-on-card-connected) (clear-on-card-read) - (hide-pair-sheet)))) + (hide-connection-sheet)))) (fx/defn on-get-keys-error {:events [:hardwallet.callback/on-get-keys-error]} @@ -338,7 +356,7 @@ :login [] :import-multiaccount [] :error-label :t/pin-mismatch})} - (hide-pair-sheet) + (hide-connection-sheet) (when (= flow :import) (navigation/navigate-to-cofx :keycard-recovery-pin nil))) (show-wrong-keycard-alert true))))) @@ -350,6 +368,8 @@ [{:keys [db]} pairing on-card-read] (let [key-uid (get-in db [:hardwallet :application-info :key-uid]) pairing' (or pairing (some->> key-uid (get-pairing db)))] + (log/debug "[hardwallet] get-application-info" + "pairing" pairing') {:hardwallet/get-application-info {:pairing pairing' :on-success on-card-read}})) @@ -410,7 +430,6 @@ (fx/defn on-card-connected {:events [::on-card-connected]} [{:keys [db] :as cofx} _] - (log/debug "[hardwallet] card connected") (let [instance-uid (get-in db [:hardwallet :application-info :instance-uid]) key-uid (get-in db [:hardwallet :application-info :key-uid]) should-read-instance-uid? (nil? instance-uid) @@ -419,23 +438,23 @@ should-read-instance-uid? :hardwallet/get-application-info :else (get-in db [:hardwallet :on-card-read])) pairing (get-pairing db key-uid)] - (log/debug "[hardwallet] on-card-connected" - "on-card-connected" on-card-connected + (log/debug "[hardwallet] on-card-connected" on-card-connected "on-card-read" on-card-read) - (fx/merge cofx - {:db (-> db - (assoc-in [:hardwallet :card-read-in-progress?] (boolean on-card-read)))} - (when on-card-connected - (dispatch-event on-card-connected)) - (stash-on-card-connected) - (when (and on-card-read - (nil? on-card-connected)) - (get-application-info pairing on-card-read))))) + (when on-card-connected + (fx/merge cofx + {:db (-> db + (assoc-in [:hardwallet :card-read-in-progress?] (boolean on-card-read)))} + (when on-card-connected + (dispatch-event on-card-connected)) + (stash-on-card-connected) + (when (and on-card-read + (nil? on-card-connected)) + (get-application-info pairing on-card-read)))))) (fx/defn on-card-disconnected {:events [::on-card-disconnected]} [{:keys [db] :as cofx} _] - (log/debug "[hardwallet] card disconnected ") + (log/debug "[hardwallet] card disconnected") (fx/merge cofx {:db (-> db (assoc-in [:hardwallet :card-read-in-progress?] false))} diff --git a/src/status_im/hardwallet/core.cljs b/src/status_im/hardwallet/core.cljs index b91931b6fc..7bee4c1eec 100644 --- a/src/status_im/hardwallet/core.cljs +++ b/src/status_im/hardwallet/core.cljs @@ -140,7 +140,7 @@ :puk [] :puk-restore? true :error-label nil}))} - (common/hide-pair-sheet) + (common/hide-connection-sheet) (navigation/navigate-to-cofx :enter-pin-settings nil)))) (fx/defn on-unblock-pin-error @@ -156,7 +156,7 @@ :error-label :t/puk-mismatch :enter-step :puk :puk []})} - (common/hide-pair-sheet))))) + (common/hide-connection-sheet))))) (fx/defn dispatch-on-verified-event [{:keys [db]} event] @@ -177,7 +177,7 @@ ;; now for simplicity do not hide bottom sheet when generating key ;; but should be refactored. (when-not (= on-verified :hardwallet/generate-and-load-key) - (common/hide-pair-sheet)) + (common/hide-connection-sheet)) (when-not (contains? #{:hardwallet/unpair :hardwallet/generate-and-load-key :hardwallet/remove-key-with-unpair @@ -204,7 +204,7 @@ :confirmation [] :sign [] :error-label :t/pin-mismatch})} - (common/hide-pair-sheet) + (common/hide-connection-sheet) (when-not setup? (if exporting? (navigation/navigate-back) @@ -212,39 +212,41 @@ (common/get-application-info (common/get-pairing db) nil)) (fx/merge cofx - (common/hide-pair-sheet) + (common/hide-connection-sheet) (common/show-wrong-keycard-alert true)))))) (fx/defn verify-pin {:events [:hardwallet/verify-pin]} - [{:keys [db] :as cofx}] - (let [pin (common/vector->string (get-in db [:hardwallet :pin :current])) - pairing (common/get-pairing db) - card-connected? (get-in db [:hardwallet :card-connected?])] - (if card-connected? - (fx/merge cofx - {:db (assoc-in db [:hardwallet :pin :status] :verifying) - :hardwallet/verify-pin {:pin pin - :pairing pairing}}) - (fx/merge cofx - (common/set-on-card-connected :hardwallet/verify-pin) - (common/show-pair-sheet {}))))) + [cofx] + (common/show-connection-sheet + cofx + {:on-card-connected :hardwallet/verify-pin + :handler + (fn [{:keys [db] :as cofx}] + (let [pin (common/vector->string (get-in db [:hardwallet :pin :current])) + pairing (common/get-pairing db)] + (fx/merge + cofx + {:db (assoc-in db [:hardwallet :pin :status] :verifying) + :hardwallet/verify-pin {:pin pin + :pairing pairing}})))})) (fx/defn unblock-pin {:events [:hardwallet/unblock-pin]} - [{:keys [db] :as cofx}] - (let [puk (common/vector->string (get-in db [:hardwallet :pin :puk])) - key-uid (get-in db [:hardwallet :application-info :key-uid]) - card-connected? (get-in db [:hardwallet :card-connected?]) - pairing (common/get-pairing db key-uid)] - (if card-connected? - {:db (assoc-in db [:hardwallet :pin :status] :verifying) - :hardwallet/unblock-pin {:puk puk - :new-pin common/default-pin - :pairing pairing}} - (fx/merge cofx - (common/set-on-card-connected :hardwallet/unblock-pin) - (common/show-pair-sheet {}))))) + [cofx] + (common/show-connection-sheet + cofx + {:on-card-connected :hardwallet/unblock-pin + :handler + (fn [{:keys [db]}] + (let [puk (common/vector->string (get-in db [:hardwallet :pin :puk])) + key-uid (get-in db [:hardwallet :application-info :key-uid]) + pairing (common/get-pairing db key-uid)] + {:db (assoc-in db [:hardwallet :pin :status] :verifying) + :hardwallet/unblock-pin + {:puk puk + :new-pin common/default-pin + :pairing pairing}}))})) (def pin-code-length 6) (def puk-code-length 12) @@ -377,7 +379,7 @@ (assoc-in [:hardwallet :setup-step] next-step) (assoc-in [:hardwallet :secrets :pairing] pairing) (assoc-in [:hardwallet :secrets :paired-on] paired-on))} - (common/hide-pair-sheet) + (common/hide-connection-sheet) (when multiaccount (set-multiaccount-pairing multiaccount pairing paired-on)) (when (= flow :login) @@ -405,7 +407,7 @@ (common/set-on-card-connected (if (= setup-step :pairing) :hardwallet/load-pairing-screen :hardwallet/pair)) - (common/hide-pair-sheet) + (common/hide-connection-sheet) (when (= flow :import) (navigation/navigate-to-cofx :keycard-recovery-pair nil)) (when (not= setup-step :enter-pair-code) @@ -444,7 +446,7 @@ (fx/merge cofx {:db (assoc-in db [:hardwallet :card-state] card-state)} (set-setup-step card-state) - (common/hide-pair-sheet) + (common/hide-connection-sheet) (when (and flow (= card-state :init)) @@ -485,7 +487,7 @@ (fx/defn on-card-disconnected {:events [:hardwallet.callback/on-card-disconnected]} [{:keys [db]} _] - (log/debug "[hardwallet] card disconnected ") + (log/debug "[hardwallet] card disconnected") {:db (assoc-in db [:hardwallet :card-connected?] false)}) (fx/defn on-register-card-events diff --git a/src/status_im/hardwallet/export_key.cljs b/src/status_im/hardwallet/export_key.cljs index cc0270f8fd..f29ec0f4eb 100644 --- a/src/status_im/hardwallet/export_key.cljs +++ b/src/status_im/hardwallet/export_key.cljs @@ -24,14 +24,14 @@ :sign [] :export-key [] :error-label :t/pin-mismatch})} - (common/hide-pair-sheet) + (common/hide-connection-sheet) (common/get-application-info (common/get-pairing db) nil)) :else (fx/merge cofx (common/show-wrong-keycard-alert true) (common/clear-pin) - (common/hide-pair-sheet))))) + (common/hide-connection-sheet))))) (fx/defn on-export-key-success {:events [:hardwallet.callback/on-export-key-success]} @@ -40,4 +40,4 @@ (fx/merge cofx {:dispatch (callback-fn pubkey)} (common/clear-pin) - (common/hide-pair-sheet)))) + (common/hide-connection-sheet)))) diff --git a/src/status_im/hardwallet/login.cljs b/src/status_im/hardwallet/login.cljs index dbf305588a..eb1db00957 100644 --- a/src/status_im/hardwallet/login.cljs +++ b/src/status_im/hardwallet/login.cljs @@ -62,36 +62,36 @@ (cond (empty? application-info) (fx/merge cofx - (common/hide-pair-sheet) + (common/hide-connection-sheet) (navigation/navigate-to-cofx :not-keycard nil)) (empty? key-uid) (fx/merge cofx - (common/hide-pair-sheet) + (common/hide-connection-sheet) (navigation/navigate-to-cofx :keycard-blank nil)) multiaccount-mismatch? (fx/merge cofx - (common/hide-pair-sheet) + (common/hide-connection-sheet) (navigation/navigate-to-cofx :keycard-wrong nil)) (empty? pairing) (fx/merge cofx - (common/hide-pair-sheet) + (common/hide-connection-sheet) (navigation/navigate-to-cofx :keycard-unpaired nil)) :else (common/get-keys-from-keycard cofx)))) (fx/defn proceed-to-login - [{:keys [db] :as cofx}] - (let [{:keys [card-connected?]} (:hardwallet db)] - (fx/merge cofx - (common/set-on-card-connected :hardwallet/get-application-info) - (common/set-on-card-read :hardwallet/login-with-keycard) - (if card-connected? - (login-with-keycard) - (common/show-pair-sheet {:on-cancel [::common/cancel-sheet-confirm]}))))) + [cofx] + (log/debug "[hardwallet] proceed-to-login") + (common/show-connection-sheet + cofx + {:sheet-options {:on-cancel [::common/cancel-sheet-confirm]} + :on-card-connected :hardwallet/get-application-info + :on-card-read :hardwallet/login-with-keycard + :handler (common/get-application-info nil :hardwallet/login-with-keycard)})) (fx/defn on-hardwallet-keychain-keys {:events [:multiaccounts.login.callback/get-hardwallet-keys-success]} diff --git a/src/status_im/hardwallet/mnemonic.cljs b/src/status_im/hardwallet/mnemonic.cljs index 70aaadfa93..ea4299ea87 100644 --- a/src/status_im/hardwallet/mnemonic.cljs +++ b/src/status_im/hardwallet/mnemonic.cljs @@ -53,13 +53,12 @@ (fx/defn load-generating-mnemonic-screen {:events [:hardwallet/load-generating-mnemonic-screen]} [{:keys [db] :as cofx}] - (let [card-connected? (get-in db [:hardwallet :card-connected?])] - (fx/merge cofx - {:db (assoc-in db [:hardwallet :setup-step] :generating-mnemonic)} - (common/set-on-card-connected :hardwallet/load-generating-mnemonic-screen) - (if card-connected? - (common/dispatch-event :hardwallet/generate-mnemonic) - (common/show-pair-sheet {}))))) + (fx/merge + cofx + {:db (assoc-in db [:hardwallet :setup-step] :generating-mnemonic)} + (common/show-connection-sheet + {:on-card-connected :hardwallet/load-generating-mnemonic-screen + :handler (common/dispatch-event :hardwallet/generate-mnemonic)}))) (fx/defn on-generate-mnemonic-error {:events [:hardwallet.callback/on-generate-mnemonic-error]} @@ -81,10 +80,9 @@ {:events [:hardwallet.ui/recovery-phrase-confirm-pressed :hardwallet/load-loading-keys-screen]} [{:keys [db] :as cofx}] - (let [card-connected? (get-in db [:hardwallet :card-connected?])] - (fx/merge cofx - {:db (assoc-in db [:hardwallet :setup-step] :loading-keys)} - (common/set-on-card-connected :hardwallet/load-loading-keys-screen) - (if card-connected? - (common/dispatch-event :hardwallet/generate-and-load-key) - (common/show-pair-sheet {}))))) + (fx/merge + cofx + {:db (assoc-in db [:hardwallet :setup-step] :loading-keys)} + (common/show-connection-sheet + {:on-card-connected :hardwallet/load-loading-keys-screen + :handler (common/dispatch-event :hardwallet/generate-and-load-key)}))) diff --git a/src/status_im/hardwallet/onboarding.cljs b/src/status_im/hardwallet/onboarding.cljs index 847eea627d..66eb1b62ec 100644 --- a/src/status_im/hardwallet/onboarding.cljs +++ b/src/status_im/hardwallet/onboarding.cljs @@ -38,26 +38,24 @@ (fx/defn load-preparing-screen {:events [:hardwallet/load-preparing-screen]} - [{:keys [db] :as cofx}] - (let [card-connected? (get-in db [:hardwallet :card-connected?])] - (fx/merge cofx - {:db (assoc-in db [:hardwallet :setup-step] :preparing)} - (common/set-on-card-connected :hardwallet/load-preparing-screen) - (if card-connected? - (start-installation) - (common/show-pair-sheet {:on-cancel [::cancel-pressed]}))))) + [cofx] + (common/show-connection-sheet + cofx + {:sheet-options {:on-cancel [::cancel-pressed]} + :on-card-connected :hardwallet/load-preparing-screen + :handler start-installation})) (fx/defn load-pairing-screen {:events [:hardwallet/load-pairing-screen :keycard.onboarding.puk-code.ui/confirm-pressed]} [{:keys [db] :as cofx}] - (let [card-connected? (get-in db [:hardwallet :card-connected?])] - (fx/merge cofx - {:db (assoc-in db [:hardwallet :setup-step] :pairing)} - (common/set-on-card-connected :hardwallet/load-pairing-screen) - (if card-connected? - (common/dispatch-event :hardwallet/pair) - (common/show-pair-sheet {:on-cancel [::cancel-pressed]}))))) + (fx/merge + cofx + {:db (assoc-in db [:hardwallet :setup-step] :pairing)} + (common/show-connection-sheet + {:sheet-options {:on-cancel [::cancel-pressed]} + :on-card-connected :hardwallet/load-pairing-screen + :handler (common/dispatch-event :hardwallet/pair)}))) (fx/defn puk-code-next-pressed {:events [:keycard.onboarding.puk-code.ui/next-pressed]} @@ -73,13 +71,13 @@ {:events [:keycard.onboarding.recovery-phrase-confirm-word2.ui/next-pressed :hardwallet/load-finishing-screen]} [{:keys [db] :as cofx}] - (let [card-connected? (get-in db [:hardwallet :card-connected?])] - (fx/merge cofx - {:db (assoc-in db [:hardwallet :setup-step] :loading-keys)} - (common/set-on-card-connected :hardwallet/load-finishing-screen) - (if card-connected? - (common/dispatch-event :hardwallet/generate-and-load-key) - (common/show-pair-sheet {:on-cancel [::cancel-pressed]}))))) + (fx/merge + cofx + {:db (assoc-in db [:hardwallet :setup-step] :loading-keys)} + (common/show-connection-sheet + {:sheet-options {:on-cancel [::cancel-pressed]} + :on-card-connected :hardwallet/load-finishing-screen + :handler (common/dispatch-event :hardwallet/generate-and-load-key)}))) (fx/defn recovery-phrase-learn-more-pressed {:events [:keycard.onboarding.recovery-phrase.ui/learn-more-pressed]} @@ -254,7 +252,7 @@ (assoc-in [:hardwallet :card-state] :init) (assoc-in [:hardwallet :setup-step] :secret-keys) (update-in [:hardwallet :secrets] merge secrets'))} - (common/hide-pair-sheet) + (common/hide-connection-sheet) (common/listen-to-hardware-back-button) (navigation/navigate-replace-cofx :keycard-onboarding-puk-code nil)))) @@ -288,17 +286,19 @@ (fx/defn begin-setup-pressed {:events [:keycard.onboarding.intro.ui/begin-setup-pressed]} [{:keys [db] :as cofx}] - (fx/merge cofx - {:db (-> db - (update :hardwallet - dissoc :secrets :card-state :multiaccount-wallet-address - :multiaccount-whisper-public-key - :application-info) - (assoc-in [:hardwallet :setup-step] :begin) - (assoc-in [:hardwallet :pin :on-verified] nil))} - (common/set-on-card-connected :hardwallet/get-application-info) - (common/set-on-card-read :hardwallet/check-card-state) - (common/show-pair-sheet {}))) + (fx/merge + cofx + {:db (-> db + (update :hardwallet + dissoc :secrets :card-state :multiaccount-wallet-address + :multiaccount-whisper-public-key + :application-info) + (assoc-in [:hardwallet :setup-step] :begin) + (assoc-in [:hardwallet :pin :on-verified] nil))} + (common/show-connection-sheet + {:on-card-connected :hardwallet/get-application-info + :on-card-read :hardwallet/check-card-state + :handler (common/get-application-info nil :hardwallet/check-card-state)}))) (fx/defn cancel-confirm {:events [::cancel-confirm]} diff --git a/src/status_im/hardwallet/recovery.cljs b/src/status_im/hardwallet/recovery.cljs index b993ff3333..5756284300 100644 --- a/src/status_im/hardwallet/recovery.cljs +++ b/src/status_im/hardwallet/recovery.cljs @@ -18,14 +18,12 @@ (fx/defn pair {:events [:hardwallet/pair]} - [{:keys [db] :as cofx}] - (let [{:keys [password]} (get-in cofx [:db :hardwallet :secrets]) - card-connected? (get-in db [:hardwallet :card-connected?])] - (fx/merge cofx - (common/set-on-card-connected :hardwallet/pair) - (if card-connected? - (pair* password) - (common/show-pair-sheet {}))))) + [cofx] + (let [{:keys [password]} (get-in cofx [:db :hardwallet :secrets])] + (common/show-connection-sheet + cofx + {:on-card-connected :hardwallet/pair + :handler (pair* password)}))) (fx/defn pair-code-next-button-pressed {:events [:keycard.onboarding.pair.ui/input-submitted @@ -100,17 +98,20 @@ (fx/defn begin-setup-pressed {:events [:keycard.recovery.intro.ui/begin-recovery-pressed]} [{:keys [db] :as cofx}] - (fx/merge cofx - {:db (-> db - (update :hardwallet - dissoc :secrets :card-state :multiaccount-wallet-address - :multiaccount-whisper-public-key - :application-info) - (assoc-in [:hardwallet :setup-step] :begin) - (assoc-in [:hardwallet :pin :on-verified] nil))} - (common/set-on-card-connected :hardwallet/get-application-info) - (common/set-on-card-read :hardwallet/check-card-state) - (common/show-pair-sheet {:on-cancel [::cancel-pressed]}))) + (fx/merge + cofx + {:db (-> db + (update :hardwallet + dissoc :secrets :card-state :multiaccount-wallet-address + :multiaccount-whisper-public-key + :application-info) + (assoc-in [:hardwallet :setup-step] :begin) + (assoc-in [:hardwallet :pin :on-verified] nil))} + (common/show-connection-sheet + {:on-card-connected :hardwallet/get-application-info + :on-card-read :hardwallet/check-card-state + :sheet-options {:on-cancel [::cancel-pressed]} + :handler (common/get-application-info nil :hardwallet/check-card-state)}))) (fx/defn recovery-success-finish-pressed {:events [:keycard.recovery.success/finish-pressed]} @@ -215,7 +216,7 @@ (assoc :multiaccounts/new-installation-id (random-guid-generator)) (update-in [:hardwallet :secrets] dissoc :mnemonic))} (common/remove-listener-to-hardware-back-button) - (common/hide-pair-sheet) + (common/hide-connection-sheet) (create-keycard-multiaccount)))) (fx/defn on-generate-and-load-key-error @@ -247,13 +248,11 @@ (fx/defn load-recovering-key-screen {:events [:hardwallet/load-recovering-key-screen]} - [{:keys [db] :as cofx}] - (let [card-connected? (get-in db [:hardwallet :card-connected?])] - (fx/merge cofx - (common/set-on-card-connected :hardwallet/load-recovering-key-screen) - (if card-connected? - (common/dispatch-event :hardwallet/import-multiaccount) - (common/show-pair-sheet {}))))) + [cofx] + (common/show-connection-sheet + cofx + {:on-card-connected :hardwallet/load-recovering-key-screen + :handler (common/dispatch-event :hardwallet/import-multiaccount)})) (fx/defn on-name-and-photo-generated {:events [::on-name-and-photo-generated] diff --git a/src/status_im/hardwallet/sign.cljs b/src/status_im/hardwallet/sign.cljs index c3672aabf1..458cca50d3 100644 --- a/src/status_im/hardwallet/sign.cljs +++ b/src/status_im/hardwallet/sign.cljs @@ -34,15 +34,11 @@ (fx/defn prepare-to-sign {:events [:hardwallet/prepare-to-sign]} [{:keys [db] :as cofx}] - (let [card-connected? (get-in db [:hardwallet :card-connected?]) - pairing (common/get-pairing db)] - (fx/merge cofx - (if card-connected? - (common/get-application-info pairing :hardwallet/sign) - (fn [cofx] - (fx/merge cofx - (common/set-on-card-connected :hardwallet/prepare-to-sign) - (common/show-pair-sheet {}))))))) + (let [pairing (common/get-pairing db)] + (common/show-connection-sheet + cofx + {:on-card-connected :hardwallet/prepare-to-sign + :handler (common/get-application-info pairing :hardwallet/sign)}))) (fx/defn sign-message-completed [_ signature] @@ -73,7 +69,7 @@ (assoc-in [:hardwallet :transaction] nil))} (common/clear-on-card-connected) (common/get-application-info (common/get-pairing db) nil) - (common/hide-pair-sheet) + (common/hide-connection-sheet) (if transaction (send-transaction-with-signature {:transaction (types/clj->json transaction) :signature signature @@ -93,8 +89,8 @@ :sign [] :error-label :t/pin-mismatch}) (assoc-in [:signing/sign :keycard-step] :pin))} - (common/hide-pair-sheet) + (common/hide-connection-sheet) (common/get-application-info (common/get-pairing db) nil)) (fx/merge cofx - (common/hide-pair-sheet) + (common/hide-connection-sheet) (common/show-wrong-keycard-alert true)))))) diff --git a/src/status_im/hardwallet/unpair.cljs b/src/status_im/hardwallet/unpair.cljs index 90e6b54144..cef34e11d7 100644 --- a/src/status_im/hardwallet/unpair.cljs +++ b/src/status_im/hardwallet/unpair.cljs @@ -94,16 +94,17 @@ (fx/defn remove-key-with-unpair {:events [:hardwallet/remove-key-with-unpair]} - [{:keys [db] :as cofx}] - (let [pin (common/vector->string (get-in db [:hardwallet :pin :current])) - pairing (common/get-pairing db) - card-connected? (get-in db [:hardwallet :card-connected?])] - (if card-connected? - {:hardwallet/remove-key-with-unpair {:pin pin - :pairing pairing}} - (fx/merge cofx - (common/set-on-card-connected :hardwallet/remove-key-with-unpair) - (common/show-pair-sheet {}))))) + [cofx] + (common/show-connection-sheet + cofx + {:on-card-connected :hardwallet/remove-key-with-unpair + :handler + (fn [{:keys [db]}] + (let [pin (common/vector->string (get-in db [:hardwallet :pin :current])) + pairing (common/get-pairing db)] + {:hardwallet/remove-key-with-unpair + {:pin pin + :pairing pairing}}))})) (fx/defn on-remove-key-success {:events [:hardwallet.callback/on-remove-key-success]} diff --git a/src/status_im/hardwallet/wallet.cljs b/src/status_im/hardwallet/wallet.cljs index f1163769c4..42b901b0a8 100644 --- a/src/status_im/hardwallet/wallet.cljs +++ b/src/status_im/hardwallet/wallet.cljs @@ -1,6 +1,5 @@ (ns status-im.hardwallet.wallet (:require [status-im.ethereum.core :as ethereum] - [status-im.ui.components.colors :as colors] [status-im.utils.fx :as fx] [status-im.hardwallet.common :as common] [status-im.constants :as constants] @@ -9,21 +8,25 @@ (fx/defn generate-new-keycard-account {:events [:wallet.accounts/generate-new-keycard-account]} [{:keys [db] :as cofx}] - (let [path-num (inc (get-in db [:multiaccount :latest-derived-path])) - path (str constants/path-wallet-root "/" path-num) - card-connected? (get-in db [:hardwallet :card-connected?]) - pin (common/vector->string (get-in db [:hardwallet :pin :export-key])) - pairing (common/get-pairing db)] - (if card-connected? - (fx/merge cofx - {:db (assoc-in db [:hardwallet :on-export-success] - #(vector :wallet.accounts/account-stored - {;; Strip leading 04 prefix denoting uncompressed key format - :address (eip55/address->checksum (str "0x" (ethereum/public-key->address (subs % 2)))) - :public-key (str "0x" %) - :path path})) - :hardwallet/export-key {:pin pin :pairing pairing :path path}} - (common/set-on-card-connected :wallet.accounts/generate-new-keycard-account)) - (fx/merge cofx - (common/set-on-card-connected :wallet.accounts/generate-new-keycard-account) - (common/show-pair-sheet {}))))) + (let [path-num (inc (get-in db [:multiaccount :latest-derived-path])) + path (str constants/path-wallet-root "/" path-num) + pin (common/vector->string (get-in db [:hardwallet :pin :export-key])) + pairing (common/get-pairing db)] + (common/show-connection-sheet + cofx + {:on-card-connected :hardwallet/load-loading-keys-screen + :handler + (fn [cofx] + (fx/merge + cofx + {:db + (assoc-in + db [:hardwallet :on-export-success] + #(vector :wallet.accounts/account-stored + {;; Strip leading 04 prefix denoting uncompressed key format + :address (eip55/address->checksum (str "0x" (ethereum/public-key->address (subs % 2)))) + :public-key (str "0x" %) + :path path})) + + :hardwallet/export-key {:pin pin :pairing pairing :path path}} + (common/set-on-card-connected :wallet.accounts/generate-new-keycard-account)))}))) diff --git a/src/status_im/signing/core.cljs b/src/status_im/signing/core.cljs index b3cdc21847..319992dae5 100644 --- a/src/status_im/signing/core.cljs +++ b/src/status_im/signing/core.cljs @@ -310,7 +310,7 @@ (assoc-in [:hardwallet :pin :status] nil) (dissoc :signing/tx :signing/in-progress? :signing/sign))} (check-queue) - (hardwallet.common/hide-pair-sheet) + (hardwallet.common/hide-connection-sheet) (hardwallet.common/clear-pin) #(when on-error {:dispatch (conj on-error "transaction was cancelled by user")})))) diff --git a/src/status_im/ui/screens/keycard/components/keycard_animation.cljs b/src/status_im/ui/screens/keycard/components/keycard_animation.cljs index 584cd6bd15..53189a5f5b 100644 --- a/src/status_im/ui/screens/keycard/components/keycard_animation.cljs +++ b/src/status_im/ui/screens/keycard/components/keycard_animation.cljs @@ -5,7 +5,8 @@ [status-im.ui.components.animation :as animation] [status-im.hardwallet.card :as keycard-nfc] [status-im.react-native.resources :as resources] - [status-im.ui.components.colors :as colors])) + [status-im.ui.components.colors :as colors] + [taoensso.timbre :as log])) (defn circle [{:keys [animation-value color size]}] [react/animated-view diff --git a/test/cljs/status_im/test/hardwallet/common.cljs b/test/cljs/status_im/test/hardwallet/common.cljs new file mode 100644 index 0000000000..1e29990755 --- /dev/null +++ b/test/cljs/status_im/test/hardwallet/common.cljs @@ -0,0 +1,43 @@ +(ns status-im.test.hardwallet.common + (:require [cljs.test :refer-macros [deftest is testing]] + [status-im.hardwallet.common :as common])) + +(deftest test-show-connection-sheet + (testing "the card is not connected yet" + (let [db {:hardwallet {:card-connected? false}} + res (common/show-connection-sheet + {:db db} + {:on-card-connected :do-something + :handler (fn [{:keys [db]}] + {:db (assoc db :some-key :some-value)})})] + (is (= :do-something + (get-in res [:db :hardwallet :on-card-connected]))) + (is (nil? (get-in res [:db :some-key]))) + (is (true? (get-in res [:db :bottom-sheet/show?]))))) + (testing "the card is connected before the interaction" + (let [db {:hardwallet {:card-connected? true}} + res (common/show-connection-sheet + {:db db} + {:on-card-connected :do-something + :handler (fn [{:keys [db]}] + {:db (assoc db :some-key :some-value)})})] + (is (nil? (get-in res [:db :hardwallet :on-card-connected]))) + (is (= :do-something + (get-in res [:db :hardwallet :last-on-card-connected]))) + (is (= :some-value (get-in res [:db :some-key]))) + (is (true? (get-in res [:db :bottom-sheet/show?]))))) + (testing "on-card-connected is not specified" + (is + (thrown? + js/Error + (common/show-connection-sheet + {:db {}} + {:handler (fn [_])})))) + (testing "handler is not specified" + (is + (thrown? + js/Error + (common/show-connection-sheet + {:db {}} + {:on-card-connected :do-something}))))) + diff --git a/test/cljs/status_im/test/runner.cljs b/test/cljs/status_im/test/runner.cljs index a5a5eac254..b76c72b292 100644 --- a/test/cljs/status_im/test/runner.cljs +++ b/test/cljs/status_im/test/runner.cljs @@ -21,6 +21,7 @@ [status-im.test.ethereum.stateofus] [status-im.test.fleet.core] [status-im.test.hardwallet.core] + [status-im.test.hardwallet.common] [status-im.test.i18n] [status-im.test.mailserver.core] [status-im.test.mailserver.topics] @@ -92,6 +93,7 @@ 'status-im.test.ethereum.stateofus 'status-im.test.fleet.core 'status-im.test.hardwallet.core + 'status-im.test.hardwallet.common 'status-im.test.i18n 'status-im.test.mailserver.core 'status-im.test.mailserver.topics