[#7217] check card state before installation

Signed-off-by: Dmitry Novotochinov <dmitry.novot@gmail.com>
This commit is contained in:
Dmitry Novotochinov 2019-02-08 16:30:44 +03:00
parent 7a6a508696
commit bae935d3e4
No known key found for this signature in database
GPG Key ID: 43D1DAF5AD39C927
15 changed files with 419 additions and 264 deletions

View File

@ -55,7 +55,7 @@
"react-native-safe-area-view": "0.9.0", "react-native-safe-area-view": "0.9.0",
"react-native-securerandom": "git+https://github.com/status-im/react-native-securerandom.git#0.1.1-2", "react-native-securerandom": "git+https://github.com/status-im/react-native-securerandom.git#0.1.1-2",
"react-native-splash-screen": "3.1.1", "react-native-splash-screen": "3.1.1",
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.3.4", "react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.3.7",
"react-native-svg": "6.5.2", "react-native-svg": "6.5.2",
"react-native-tcp": "git+https://github.com/status-im/react-native-tcp.git#v3.3.0-1-status", "react-native-tcp": "git+https://github.com/status-im/react-native-tcp.git#v3.3.0-1-status",
"react-native-udp": "git+https://github.com/status-im/react-native-udp.git#2.3.1-1", "react-native-udp": "git+https://github.com/status-im/react-native-udp.git#2.3.1-1",

View File

@ -6010,9 +6010,9 @@ react-native-splash-screen@3.1.1:
resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.1.1.tgz#1a4e46c9fdce53ff52af2a2cb4181788c4e30b30" resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.1.1.tgz#1a4e46c9fdce53ff52af2a2cb4181788c4e30b30"
integrity sha512-PU2YocOSGbLjL9Vgcq/cwMNuHHKNjjuPpa1IPMuWo+6EB/fSZ5VOmxSa7+eucQe3631s3NhGuk3eHKahU03a4Q== integrity sha512-PU2YocOSGbLjL9Vgcq/cwMNuHHKNjjuPpa1IPMuWo+6EB/fSZ5VOmxSa7+eucQe3631s3NhGuk3eHKahU03a4Q==
"react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.3.4": "react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.3.7":
version "2.3.4" version "2.3.7"
resolved "git+https://github.com/status-im/react-native-status-keycard.git#04b0fb6fcbe588bd7fa076e1b0379e661bf1bddc" resolved "git+https://github.com/status-im/react-native-status-keycard.git#9e6df66bfd9288584031cff5455445230059720b"
react-native-svg@6.5.2: react-native-svg@6.5.2:
version "6.5.2" version "6.5.2"

View File

@ -1,7 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="path-1-inside-1" fill="white"> <path fill-rule="evenodd" clip-rule="evenodd" d="M4 6H20C20.5523 6 21 6.44772 21 7V17C21 17.5523 20.5523 18 20 18H4C3.44769 18 3 17.5523 3 17V7C3 6.44772 3.44769 6 4 6ZM1 7C1 5.34314 2.34314 4 4 4H20C21.6569 4 23 5.34314 23 7V17C23 18.6569 21.6569 20 20 20H4C2.34314 20 1 18.6569 1 17V7ZM6 10C5.44769 10 5 10.4477 5 11V13C5 13.5523 5.44769 14 6 14H8C8.55231 14 9 13.5523 9 13V11C9 10.4477 8.55231 10 8 10H6Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20 6H4C3.44772 6 3 6.44772 3 7V17C3 17.5523 3.44772 18 4 18H20C20.5523 18 21 17.5523 21 17V7C21 6.44772 20.5523 6 20 6ZM4 4C2.34315 4 1 5.34315 1 7V17C1 18.6569 2.34315 20 4 20H20C21.6569 20 23 18.6569 23 17V7C23 5.34315 21.6569 4 20 4H4Z"/> </svg>
</mask>
<path d="M4 8H20V4H4V8ZM5 7C5 7.55228 4.55228 8 4 8V4C2.34315 4 1 5.34315 1 7H5ZM5 17V7H1V17H5ZM4 16C4.55228 16 5 16.4477 5 17H1C1 18.6569 2.34315 20 4 20V16ZM20 16H4V20H20V16ZM19 17C19 16.4477 19.4477 16 20 16V20C21.6569 20 23 18.6569 23 17H19ZM19 7V17H23V7H19ZM20 8C19.4477 8 19 7.55229 19 7H23C23 5.34314 21.6569 4 20 4V8ZM3 7C3 6.44772 3.44772 6 4 6V2C1.23858 2 -1 4.23858 -1 7H3ZM3 17V7H-1V17H3ZM4 18C3.44772 18 3 17.5523 3 17H-1C-1 19.7614 1.23858 22 4 22V18ZM20 18H4V22H20V18ZM21 17C21 17.5523 20.5523 18 20 18V22C22.7614 22 25 19.7614 25 17H21ZM21 7V17H25V7H21ZM20 6C20.5523 6 21 6.44772 21 7H25C25 4.23858 22.7614 2 20 2V6ZM4 6H20V2H4V6Z" fill="black" mask="url(#path-1-inside-1)"/>
<rect x="5" y="10" width="4" height="4" rx="1" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 526 B

View File

@ -893,22 +893,16 @@
;; hardwallet module ;; hardwallet module
(handlers/register-handler-fx
:hardwallet.ui/get-application-info
(fn [{:keys [db]} _]
{:hardwallet/get-application-info (get-in db [:hardwallet :secrets :pairing])}))
(handlers/register-handler-fx
:hardwallet.callback/on-retrieve-pairing-success
(fn [{:keys [db]} [_ pairing-data]]
{:db (update-in db [:hardwallet :secrets] merge (select-keys pairing-data
[:pairing :paired-on]))}))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.callback/on-register-card-events :hardwallet.callback/on-register-card-events
(fn [cofx [_ listeners]] (fn [cofx [_ listeners]]
(hardwallet/on-register-card-events cofx listeners))) (hardwallet/on-register-card-events cofx listeners)))
(handlers/register-handler-fx
:hardwallet/get-application-info
(fn [_ _]
{:hardwallet/get-application-info nil}))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.callback/on-get-application-info-success :hardwallet.callback/on-get-application-info-success
(fn [cofx [_ info on-success]] (fn [cofx [_ info on-success]]
@ -939,6 +933,16 @@
(fn [cofx [_ data]] (fn [cofx [_ data]]
(hardwallet/on-card-disconnected cofx data))) (hardwallet/on-card-disconnected cofx data)))
(handlers/register-handler-fx
:hardwallet.callback/on-init-card-success
(fn [cofx [_ secrets]]
(hardwallet/on-init-card-success cofx secrets)))
(handlers/register-handler-fx
:hardwallet.callback/on-init-card-error
(fn [cofx [_ error]]
(hardwallet/on-init-card-error cofx error)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.callback/on-install-applet-and-init-card-success :hardwallet.callback/on-install-applet-and-init-card-success
(fn [cofx [_ secrets]] (fn [cofx [_ secrets]]
@ -1047,6 +1051,11 @@
(fn [cofx _] (fn [cofx _]
(hardwallet/login-with-keycard cofx false))) (hardwallet/login-with-keycard cofx false)))
(handlers/register-handler-fx
:hardwallet/check-card-state
(fn [cofx _]
(hardwallet/check-card-state cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.callback/on-get-keys-error :hardwallet.callback/on-get-keys-error
(fn [cofx [_ error]] (fn [cofx [_ error]]
@ -1067,32 +1076,15 @@
(fn [_ _] (fn [_ _]
{:hardwallet/open-nfc-settings nil})) {:hardwallet/open-nfc-settings nil}))
(handlers/register-handler-fx
:hardwallet.ui/hold-card-button-pressed
(fn [{:keys [db] :as cofx} _]
(fx/merge cofx
{:db (assoc-in db [:hardwallet :setup-step] :begin)}
(navigation/navigate-to-cofx :hardwallet-setup nil))))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/begin-setup-button-pressed :hardwallet.ui/begin-setup-button-pressed
(fn [_ _] (fn [cofx _]
{:ui/show-confirmation {:title "" (hardwallet/begin-setup-button-pressed cofx)))
:content (i18n/label :t/begin-keycard-setup-confirmation-text)
:confirm-button-text (i18n/label :t/yes)
:cancel-button-text (i18n/label :t/no)
:on-accept #(re-frame/dispatch [:hardwallet.ui/begin-setup-confirm-button-pressed])
:on-cancel #()}}))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/begin-setup-confirm-button-pressed :hardwallet/start-installation
(fn [cofx _] (fn [cofx _]
(hardwallet/load-preparing-screen cofx))) (hardwallet/start-installation cofx)))
(handlers/register-handler-fx
:hardwallet/install-applet-and-init-card
(fn [cofx _]
(hardwallet/install-applet-and-init-card cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/pair-card-button-pressed :hardwallet.ui/pair-card-button-pressed
@ -1102,11 +1094,12 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/pair-code-input-changed :hardwallet.ui/pair-code-input-changed
(fn [{:keys [db]} [_ pair-code]] (fn [{:keys [db]} [_ pair-code]]
{:db (assoc-in db [:hardwallet :pair-code] pair-code)})) {:db (assoc-in db [:hardwallet :secrets :password] pair-code)}))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/pair-code-next-button-pressed :hardwallet.ui/pair-code-next-button-pressed
(fn [{:keys [db]} _])) (fn [cofx]
(hardwallet/pair cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/recovery-phrase-next-button-pressed :hardwallet.ui/recovery-phrase-next-button-pressed

View File

@ -56,10 +56,24 @@
(then #(re-frame/dispatch [:hardwallet.callback/on-get-application-info-success % on-success])) (then #(re-frame/dispatch [:hardwallet.callback/on-get-application-info-success % on-success]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-get-application-info-error (error-object->map %)])))) (catch #(re-frame/dispatch [:hardwallet.callback/on-get-application-info-error (error-object->map %)]))))
(defn install-applet-and-init-card [] (defn install-applet []
(when config/hardwallet-enabled? (when config/hardwallet-enabled?
(.. keycard (.. keycard
installAppletAndInitCard installApplet
(then #(re-frame/dispatch [:hardwallet.callback/on-install-applet-success %]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-install-applet-error (error-object->map %)])))))
(defn init-card [pin]
(when config/hardwallet-enabled?
(.. keycard
(init pin)
(then #(re-frame/dispatch [:hardwallet.callback/on-init-card-success %]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-init-card-error (error-object->map %)])))))
(defn install-applet-and-init-card [pin]
(when config/hardwallet-enabled?
(.. keycard
(installAppletAndInitCard pin)
(then #(re-frame/dispatch [:hardwallet.callback/on-install-applet-and-init-card-success %])) (then #(re-frame/dispatch [:hardwallet.callback/on-install-applet-and-init-card-success %]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-install-applet-and-init-card-error (error-object->map %)]))))) (catch #(re-frame/dispatch [:hardwallet.callback/on-install-applet-and-init-card-error (error-object->map %)])))))

View File

@ -16,20 +16,34 @@
(def default-pin "000000") (def default-pin "000000")
(defn get-pairing [db] (defn- find-account-by-keycard-instance-uid
(or [db keycard-instance-uid]
(get-in db [:hardwallet :secrets :pairing]) (->> (:accounts/accounts db)
(get-in db [:account/account :pairing]))) vals
(filter #(= keycard-instance-uid (:keycard-instance-uid %)))
first))
(defn get-pairing
([db]
(get-pairing db nil))
([db instance-uid]
(or
(get-in db [:account/account :keycard-pairing])
(get-in db [:hardwallet :secrets :pairing])
(when instance-uid
(:keycard-pairing
(find-account-by-keycard-instance-uid db instance-uid))))))
(fx/defn remove-pairing-from-account (fx/defn remove-pairing-from-account
[{:keys [db]}] [{:keys [db]} {:keys [remove-instance-uid?]}]
(let [account (-> db (let [account (cond-> (:account/account db)
(get :account/account) true (assoc :keycard-pairing nil
(assoc :keycard-pairing nil) :keycard-paired-on nil)
(assoc :keycard-paired-on nil))] remove-instance-uid? (assoc :keycard-instance-uid nil))]
;TODO remove remove-pairing when keycard login will be ready {:db (-> db
{:hardwallet/remove-pairing nil (assoc :account/account account)
:data-store/base-tx [(accounts-store/save-account-tx account)]})) (assoc-in [:accounts/accounts (:address account)] account))
:data-store/base-tx [(accounts-store/save-account-tx account)]}))
(defn hardwallet-supported? [{:keys [db]}] (defn hardwallet-supported? [{:keys [db]}]
(and config/hardwallet-enabled? (and config/hardwallet-enabled?
@ -44,6 +58,74 @@
:content (i18n/label :t/keycard-unauthorized-operation)}} :content (i18n/label :t/keycard-unauthorized-operation)}}
(navigation/navigate-to-cofx :keycard-settings nil))) (navigation/navigate-to-cofx :keycard-settings nil)))
(fx/defn show-no-keycard-applet-alert [_]
{:utils/show-confirmation {:title (i18n/label :t/no-keycard-applet-on-card)
:content (i18n/label :t/keycard-applet-will-be-installed)
:cancel-button-text ""
:confirm-button-text :t/next}})
(fx/defn show-keycard-has-account-alert
[{:keys [db] :as cofx}]
(fx/merge cofx
{:utils/show-confirmation {:title nil
:content (i18n/label :t/keycard-has-account-on-it)
:cancel-button-text ""
:confirm-button-text :t/okay}}
(if (empty? (:accounts/accounts db))
(navigation/navigate-to-cofx :intro nil)
(navigation/navigate-to-cofx :accounts nil))))
(defn- card-state->setup-step [state]
(case state
:not-paired :pair
:no-pairing-slots :no-slots
:begin))
(defn- get-card-state
[{:keys [has-master-key?
applet-installed?
initialized?
free-pairing-slots
paired?]}]
(cond
(and (not paired?)
(zero? free-pairing-slots))
:no-pairing-slots
(and (not paired?)
has-master-key?
(pos? free-pairing-slots))
:not-paired
(not applet-installed?)
:blank
(not initialized?)
:pre-init
(not has-master-key?)
:init
has-master-key?
:account))
(fx/defn set-setup-step
[{:keys [db]} card-state]
{:db (assoc-in db [:hardwallet :setup-step] (card-state->setup-step card-state))})
(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)]
(fx/merge cofx
{:db (assoc-in db [:hardwallet :card-state] card-state)}
(when (= card-state :blank)
(show-no-keycard-applet-alert))
(if (= card-state :account)
(show-keycard-has-account-alert)
(set-setup-step card-state)))))
(fx/defn navigate-to-keycard-settings (fx/defn navigate-to-keycard-settings
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(fx/merge cofx (fx/merge cofx
@ -104,15 +186,19 @@
[{:keys [db]}] [{:keys [db]}]
{:db (assoc-in db [:hardwallet :on-card-read] nil)}) {:db (assoc-in db [:hardwallet :on-card-read] nil)})
(fx/defn dispatch-event
[_ event]
{:dispatch [event]})
(fx/defn on-get-application-info-success (fx/defn on-get-application-info-success
[{:keys [db]} 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]} info' {:keys [pin-retry-counter puk-retry-counter]} info'
connect-screen? (= (:view-id db) :hardwallet-connect) connect-screen? (= (:view-id db) :hardwallet-connect)
enter-step (if (zero? pin-retry-counter) enter-step (if (zero? pin-retry-counter)
:puk :puk
(get-in db [:hardwallet :pin :enter-step]))] (get-in db [:hardwallet :pin :enter-step]))]
(fx/merge {} (fx/merge cofx
{:db (-> db {:db (-> db
(assoc-in [:hardwallet :pin :enter-step] enter-step) (assoc-in [:hardwallet :pin :enter-step] enter-step)
(assoc-in [:hardwallet :application-info] info') (assoc-in [:hardwallet :application-info] info')
@ -123,22 +209,26 @@
(if (zero? puk-retry-counter) (if (zero? puk-retry-counter)
(navigation/navigate-to-cofx :keycard-settings nil) (navigation/navigate-to-cofx :keycard-settings nil)
(when on-success (when on-success
#(assoc % :dispatch [on-success])))))) (dispatch-event on-success))))))
(fx/defn on-get-application-info-error (fx/defn on-get-application-info-error
[{:keys [db] :as cofx} error] [{:keys [db] :as cofx} error]
(log/debug "[hardwallet] application info error " error) (log/debug "[hardwallet] application info error " error)
(let [on-card-read (get-in db [:hardwallet :on-card-read]) (let [on-card-read (get-in db [:hardwallet :on-card-read])
connect-screen? (= (:view-id db) :hardwallet-connect)
login? (= on-card-read :hardwallet/login-with-keycard)] login? (= on-card-read :hardwallet/login-with-keycard)]
(if login? (if login?
(fx/merge cofx (fx/merge cofx
{:db (assoc-in db [:hardwallet :on-card-read] nil) {:utils/show-popup {:title (i18n/label :t/wrong-card)
:utils/show-popup {:title (i18n/label :t/wrong-card)
:content (i18n/label :t/wrong-card-text)}} :content (i18n/label :t/wrong-card-text)}}
(clear-on-card-read)
(navigation/navigate-to-cofx :accounts nil)) (navigation/navigate-to-cofx :accounts nil))
{:db (-> db (fx/merge cofx
(assoc-in [:hardwallet :application-info-error] error) {:db (assoc-in db [:hardwallet :application-info-error] error)}
(assoc-in [:hardwallet :application-info :applet-installed?] false))}))) (when-not connect-screen?
(clear-on-card-read))
(when on-card-read
(dispatch-event on-card-read))))))
(fx/defn set-nfc-support (fx/defn set-nfc-support
[{:keys [db]} supported?] [{:keys [db]} supported?]
@ -155,7 +245,7 @@
:db (-> db :db (-> db
(assoc-in [:hardwallet :setup-step] :begin) (assoc-in [:hardwallet :setup-step] :begin)
(assoc-in [:hardwallet :on-card-connected] nil) (assoc-in [:hardwallet :on-card-connected] nil)
(assoc-in [:hardwallet :on-card-read] nil) (assoc-in [:hardwallet :on-card-read] :hardwallet/check-card-state)
(assoc-in [:hardwallet :pin :on-verified] nil))} (assoc-in [:hardwallet :pin :on-verified] nil))}
(navigation/navigate-to-cofx :hardwallet-connect nil))) (navigation/navigate-to-cofx :hardwallet-connect nil)))
@ -246,7 +336,7 @@
:on-verified nil})) :on-verified nil}))
:utils/show-popup {:title "" :utils/show-popup {:title ""
:content (i18n/label :t/card-reseted)}} :content (i18n/label :t/card-reseted)}}
(remove-pairing-from-account) (remove-pairing-from-account {:remove-instance-uid? true})
(navigation/navigate-to-cofx :keycard-settings nil))) (navigation/navigate-to-cofx :keycard-settings nil)))
(fx/defn on-delete-error (fx/defn on-delete-error
@ -294,25 +384,20 @@
(fx/defn proceed-to-reset-card (fx/defn proceed-to-reset-card
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [card-connected? (get-in db [:hardwallet :card-connected?]) (let [card-connected? (get-in db [:hardwallet :card-connected?])
puk-retry-counter (get-in db [:hardwallet :application-info :puk-retry-counter])
pin-retry-counter (get-in db [:hardwallet :application-info :pin-retry-counter]) pin-retry-counter (get-in db [:hardwallet :application-info :pin-retry-counter])
pairing (get-pairing db)
enter-step (if (zero? pin-retry-counter) :puk :current)] enter-step (if (zero? pin-retry-counter) :puk :current)]
(if (or (zero? puk-retry-counter) (fx/merge cofx
(empty? pairing)) {:db (-> db
(delete-card cofx) (assoc-in [:hardwallet :on-card-connected] :hardwallet/navigate-to-enter-pin-screen)
(fx/merge cofx (assoc-in [:hardwallet :pin] {:enter-step enter-step
{:db (-> db :current []
(assoc-in [:hardwallet :on-card-connected] :hardwallet/navigate-to-enter-pin-screen) :puk []
(assoc-in [:hardwallet :pin] {:enter-step enter-step :status nil
:current [] :error-label nil
:puk [] :on-verified :hardwallet/unpair-and-delete}))}
:status nil (if card-connected?
:error-label nil (navigate-to-enter-pin-screen)
:on-verified :hardwallet/unpair-and-delete}))} (navigation/navigate-to-cofx :hardwallet-connect nil)))))
(if card-connected?
(navigate-to-enter-pin-screen)
(navigation/navigate-to-cofx :hardwallet-connect nil))))))
(fx/defn error-button-pressed [{:keys [db] :as cofx}] (fx/defn error-button-pressed [{:keys [db] :as cofx}]
(let [return-to-step (get-in db [:hardwallet :return-to-step] :begin)] (let [return-to-step (get-in db [:hardwallet :return-to-step] :begin)]
@ -336,16 +421,24 @@
(defn- proceed-to-pin-confirmation [fx] (defn- proceed-to-pin-confirmation [fx]
(assoc-in fx [:db :hardwallet :pin :enter-step] :confirmation)) (assoc-in fx [:db :hardwallet :pin :enter-step] :confirmation))
(fx/defn load-preparing-screen
[{:keys [db]}]
{:db (assoc-in db [:hardwallet :setup-step] :preparing)
:dispatch [:hardwallet/start-installation]})
(fx/defn pin-match (fx/defn pin-match
[{:keys [db] :as fx}] [{:keys [db] :as fx}]
(let [pairing (get-pairing db) (let [pairing (get-pairing db)
new-pin (vector->string (get-in db [:hardwallet :pin :original])) new-pin (vector->string (get-in db [:hardwallet :pin :original]))
current-pin (vector->string (get-in db [:hardwallet :pin :current]))] current-pin (vector->string (get-in db [:hardwallet :pin :current]))
(fx/merge fx setup-step (get-in db [:hardwallet :setup-step])]
{:db (assoc-in db [:hardwallet :pin :status] :verifying) (if (= setup-step :pin)
:hardwallet/change-pin {:new-pin new-pin (load-preparing-screen fx)
:current-pin current-pin (fx/merge fx
:pairing pairing}}))) {:db (assoc-in db [:hardwallet :pin :status] :verifying)
:hardwallet/change-pin {:new-pin new-pin
:current-pin current-pin
:pairing pairing}}))))
(fx/defn dispatch-on-verified-event (fx/defn dispatch-on-verified-event
[{:keys [db]} event] [{:keys [db]} event]
@ -385,7 +478,7 @@
{:db (-> db {:db (-> db
(update-in [:hardwallet :pin] merge {:status nil (update-in [:hardwallet :pin] merge {:status nil
:error-label nil}))} :error-label nil}))}
(when (not= on-verified :hardwallet/unpair) (when-not (contains? #{:hardwallet/unpair :hardwallet/unpair-and-delete} on-verified)
(get-application-info pairing)) (get-application-info pairing))
(when on-verified (when on-verified
(dispatch-on-verified-event on-verified))))) (dispatch-on-verified-event on-verified)))))
@ -428,15 +521,15 @@
(fx/defn on-unpair-success (fx/defn on-unpair-success
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db
(assoc-in [:hardwallet :secrets] nil) (assoc-in [:hardwallet :secrets] nil)
(assoc-in [:hardwallet :on-card-connected] nil) (assoc-in [:hardwallet :on-card-connected] nil)
(assoc-in [:hardwallet :pin] {:status nil (assoc-in [:hardwallet :pin] {:status nil
:error-label nil :error-label nil
:on-verified nil})) :on-verified nil}))
:utils/show-popup {:title "" :utils/show-popup {:title ""
:content (i18n/label :t/card-unpaired)}} :content (i18n/label :t/card-unpaired)}}
(remove-pairing-from-account) (remove-pairing-from-account nil)
(navigation/navigate-to-cofx :keycard-settings nil))) (navigation/navigate-to-cofx :keycard-settings nil)))
(fx/defn on-unpair-error (fx/defn on-unpair-error
@ -501,7 +594,8 @@
(fx/defn get-keys-from-keycard (fx/defn get-keys-from-keycard
[{:keys [db]}] [{:keys [db]}]
(let [{:keys [pairing]} (get-in db [:hardwallet :secrets]) (let [account-address (get-in db [:accounts/login :address])
pairing (get-in db [:accounts/accounts account-address :keycard-pairing])
pin (string/join (get-in db [:hardwallet :pin :login]))] pin (string/join (get-in db [:hardwallet :pin :login]))]
(when (and pairing (when (and pairing
(not (empty? pin))) (not (empty? pin)))
@ -576,23 +670,17 @@
(let [{:keys [pairing]} (get-in cofx [:db :hardwallet :secrets])] (let [{:keys [pairing]} (get-in cofx [:db :hardwallet :secrets])]
{:hardwallet/generate-mnemonic {:pairing pairing}})) {:hardwallet/generate-mnemonic {:pairing pairing}}))
(fx/defn dispatch-on-card-connected-event
[_ event]
{:dispatch [event]})
(defn login-with-keycard (defn login-with-keycard
[{:keys [db] :as cofx} auto-login?] [{:keys [db] :as cofx} auto-login?]
(let [pairing (get-pairing db) (let [account-login-address (get-in db [:accounts/login :address])
account-login-address (get-in db [:accounts/login :address])
account-was-manually-selected? account-login-address account-was-manually-selected? account-login-address
account-instance-uid (get-in db [:accounts/accounts account-login-address :keycard-instance-uid]) account-instance-uid (get-in db [:accounts/accounts account-login-address :keycard-instance-uid])
keycard-instance-uid (get-in db [:hardwallet :application-info :instance-uid]) keycard-instance-uid (get-in db [:hardwallet :application-info :instance-uid])
account (find-account-by-keycard-instance-uid db keycard-instance-uid)
account-mismatch? (if account-was-manually-selected? account-mismatch? (if account-was-manually-selected?
(not= account-instance-uid keycard-instance-uid) (not= account-instance-uid keycard-instance-uid)
(->> (:accounts/accounts db) (nil? account))
vals pairing (:keycard-pairing account)]
(filter #(= keycard-instance-uid (:keycard-instance-uid %)))
empty?))]
(cond (cond
(empty? keycard-instance-uid) (empty? keycard-instance-uid)
@ -613,7 +701,9 @@
:content (i18n/label :t/no-pairing-on-device)}} :content (i18n/label :t/no-pairing-on-device)}}
auto-login? auto-login?
(navigation/navigate-to-cofx cofx :enter-pin nil) (fx/merge cofx
{:db (assoc db :accounts/login (select-keys account [:address :name :photo-path]))}
(navigation/navigate-to-cofx :enter-pin nil))
:else :else
(get-keys-from-keycard cofx)))) (get-keys-from-keycard cofx))))
@ -622,27 +712,31 @@
[{:keys [db] :as cofx} data] [{:keys [db] :as cofx} data]
(log/debug "[hardwallet] card connected " data) (log/debug "[hardwallet] card connected " data)
(let [return-to-step (get-in db [:hardwallet :return-to-step]) (let [return-to-step (get-in db [:hardwallet :return-to-step])
setup-running? (get-in db [:hardwallet :setup-step]) setup-step (get-in db [:hardwallet :setup-step])
setup-running? (boolean setup-step)
pin-enter-step (get-in db [:hardwallet :pin :enter-step]) pin-enter-step (get-in db [:hardwallet :pin :enter-step])
login? (= :login pin-enter-step) login? (= :login pin-enter-step)
accounts-screen? (= :accounts (:view-id db)) accounts-screen? (= :accounts (:view-id db))
auto-login? accounts-screen? auto-login? accounts-screen?
instance-uid (get-in db [:hardwallet :application-info :instance-uid])
should-read-instance-uid? (nil? instance-uid)
on-card-connected (get-in db [:hardwallet :on-card-connected]) on-card-connected (get-in db [:hardwallet :on-card-connected])
on-card-read (if auto-login? on-card-read (cond
:hardwallet/auto-login auto-login? :hardwallet/auto-login
(get-in db [:hardwallet :on-card-read])) should-read-instance-uid? :hardwallet/get-application-info
pairing (get-pairing db)] :else (get-in db [:hardwallet :on-card-read]))
pairing (get-pairing db instance-uid)]
(fx/merge cofx (fx/merge cofx
{:db (cond-> db {:db (cond-> db
return-to-step (assoc-in [:hardwallet :setup-step] return-to-step) return-to-step (assoc-in [:hardwallet :setup-step] return-to-step)
true (assoc-in [:hardwallet :card-connected?] true) true (assoc-in [:hardwallet :card-connected?] true)
true (assoc-in [:hardwallet :card-read-in-progress?] (boolean on-card-read)) true (assoc-in [:hardwallet :card-read-in-progress?] (boolean on-card-read))
true (assoc-in [:hardwallet :return-to-step] nil)) true (assoc-in [:hardwallet :return-to-step] nil))
:hardwallet/get-application-info {:pairing pairing :hardwallet/get-application-info {:pairing pairing
:on-success on-card-read}} :on-success on-card-read}}
(when (and on-card-connected (when (and on-card-connected
(not login?)) (not login?))
(dispatch-on-card-connected-event on-card-connected)) (dispatch-event on-card-connected))
(when setup-running? (when setup-running?
(navigation/navigate-to-cofx :hardwallet-setup nil))))) (navigation/navigate-to-cofx :hardwallet-setup nil)))))
@ -659,14 +753,33 @@
on-card-connected) on-card-connected)
(navigation/navigate-to-cofx :hardwallet-connect nil))))) (navigation/navigate-to-cofx :hardwallet-connect nil)))))
(fx/defn load-preparing-screen (fx/defn begin-setup-button-pressed
[{:keys [db]}] [{:keys [db]}]
{:db (assoc-in db [:hardwallet :setup-step] :preparing) {:db (-> db
:dispatch [:hardwallet/install-applet-and-init-card]}) (assoc-in [:hardwallet :setup-step] :pin)
(assoc-in [:hardwallet :pin :enter-step] :original)
(assoc-in [:hardwallet :pin :original] [])
(assoc-in [:hardwallet :pin :confirmation] []))})
(fx/defn install-applet-and-init-card (fx/defn start-installation
[{:keys [db]}] [{:keys [db]}]
{:hardwallet/install-applet-and-init-card nil}) (let [card-state (get-in db [:hardwallet :card-state])
pin (vector->string (get-in db [:hardwallet :pin :original]))]
(case card-state
:blank
{:hardwallet/install-applet-and-init-card pin}
:pre-init
{:hardwallet/init-card pin}
:init
{:hardwallet/install-applet-and-init-card pin}
(do
(log/debug (str "Cannot start keycard installation from state: " card-state))
{:utils/show-popup {:title (i18n/label :t/error)
:content (i18n/label :t/something-went-wrong)}}))))
(fx/defn on-install-applet-and-init-card-success (fx/defn on-install-applet-and-init-card-success
[{:keys [db]} secrets] [{:keys [db]} secrets]
@ -675,6 +788,8 @@
(assoc-in [:hardwallet :setup-step] :secret-keys) (assoc-in [:hardwallet :setup-step] :secret-keys)
(assoc-in [:hardwallet :secrets] secrets'))})) (assoc-in [:hardwallet :secrets] secrets'))}))
(def on-init-card-success on-install-applet-and-init-card-success)
(defn- tag-lost-exception? [code] (defn- tag-lost-exception? [code]
(= code "android.nfc.TagLostException")) (= code "android.nfc.TagLostException"))
@ -692,23 +807,49 @@
(assoc-in [:hardwallet :setup-error] error))} (assoc-in [:hardwallet :setup-error] error))}
(process-error code))) (process-error code)))
(def on-init-card-error on-install-applet-and-init-card-error)
(fx/defn set-account-pairing
[{:keys [db]} {:keys [address] :as account} pairing paired-on]
(let [account' (assoc account :keycard-pairing pairing
:keycard-paired-on paired-on)]
{:db (-> db
(assoc db :accounts/account account')
(assoc-in [:accounts/accounts address] account'))
:data-store/base-tx [(accounts-store/save-account-tx account')]}))
(fx/defn on-pairing-success (fx/defn on-pairing-success
[{:keys [db]} pairing] [{:keys [db] :as cofx} pairing]
;TODO remove persistence to async storage when keycard login will be ready (let [setup-step (get-in db [:hardwallet :setup-step])
{:hardwallet/persist-pairing pairing instance-uid (get-in db [:hardwallet :application-info :instance-uid])
:db (-> db account (find-account-by-keycard-instance-uid db instance-uid)
(assoc-in [:hardwallet :setup-step] :card-ready) paired-on (utils.datetime/timestamp)
(assoc-in [:hardwallet :secrets :pairing] pairing) next-step (if (= setup-step :enter-pair-code)
(assoc-in [:hardwallet :secrets :paired-on] (utils.datetime/timestamp)))}) :begin
:card-ready)]
(fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :application-info :paired?] true)
(assoc-in [:hardwallet :setup-step] next-step)
(assoc-in [:hardwallet :secrets :pairing] pairing)
(assoc-in [:hardwallet :secrets :paired-on] paired-on))}
(when account
(set-account-pairing account pairing paired-on))
(when (= next-step :begin)
(check-card-state)))))
(fx/defn on-pairing-error (fx/defn on-pairing-error
[{:keys [db] :as cofx} {:keys [error code]}] [{:keys [db] :as cofx} {:keys [error code]}]
(log/debug "[hardwallet] pairing error: " error) (log/debug "[hardwallet] pairing error: " error)
(fx/merge cofx (let [setup-step (get-in db [:hardwallet :setup-step])
{:db (-> db next-step (if (= setup-step :enter-pair-code)
(assoc-in [:hardwallet :return-to-step] :secret-keys) :enter-pair-code
(assoc-in [:hardwallet :setup-error] error))} :secret-keys)]
(process-error code))) (fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :return-to-step] next-step)
(assoc-in [:hardwallet :setup-error] error))}
(process-error code))))
(fx/defn on-generate-mnemonic-success (fx/defn on-generate-mnemonic-success
[{:keys [db]} mnemonic] [{:keys [db]} mnemonic]
@ -766,7 +907,8 @@
(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]} (get-in db [:hardwallet :secrets])
pin (vector->string (get-in db [:hardwallet :pin :original]))]
(fx/merge cofx (fx/merge cofx
{:hardwallet/generate-and-load-key {:mnemonic mnemonic {:hardwallet/generate-and-load-key {:mnemonic mnemonic
:pairing pairing :pairing pairing

View File

@ -25,6 +25,10 @@
:hardwallet/install-applet-and-init-card :hardwallet/install-applet-and-init-card
card/install-applet-and-init-card) card/install-applet-and-init-card)
(re-frame/reg-fx
:hardwallet/init-card
card/init-card)
(re-frame/reg-fx (re-frame/reg-fx
:hardwallet/register-card-events :hardwallet/register-card-events
card/register-card-events) card/register-card-events)
@ -73,37 +77,6 @@
:hardwallet/get-keys :hardwallet/get-keys
card/get-keys) card/get-keys)
;TODO remove when keycard login will be ready
(re-frame/reg-fx
:hardwallet/persist-pairing
(fn [pairing]
(.. js-dependencies/react-native
-AsyncStorage
(setItem "status-keycard-pairing"
(js/JSON.stringify
#js {"pairing" pairing
"paired-on" (utils.datetime/timestamp)})))))
;TODO remove when keycard login will be ready
(re-frame/reg-fx
:hardwallet/retrieve-pairing
(fn []
(.. js-dependencies/react-native
-AsyncStorage
(getItem "status-keycard-pairing")
(then #(re-frame/dispatch [:hardwallet.callback/on-retrieve-pairing-success
(-> %
(js/JSON.parse)
(js->clj :keywordize-keys true))])))))
;TODO remove when keycard login will be ready
(re-frame/reg-fx
:hardwallet/remove-pairing
(fn []
(.. js-dependencies/react-native
-AsyncStorage
(removeItem "status-keycard-pairing"))))
(re-frame/reg-fx (re-frame/reg-fx
:hardwallet/login-with-keycard :hardwallet/login-with-keycard
statusgo/login-with-keycard) statusgo/login-with-keycard)

View File

@ -91,22 +91,20 @@
push-notifications/stored network/type] push-notifications/stored network/type]
:node/keys [status] :node/keys [status]
:or {network (get app-db :network)}} :db}] :or {network (get app-db :network)}} :db}]
;TODO remove retrieve-pairing when keycard login will be ready {:db (assoc app-db
{:hardwallet/retrieve-pairing nil :contacts/contacts {}
:db (assoc app-db :initial-props initial-props
:contacts/contacts {} :desktop/desktop (merge desktop (:desktop/desktop app-db))
:initial-props initial-props :network-status network-status
:desktop/desktop (merge desktop (:desktop/desktop app-db)) :peers-count (or peers-count 0)
:network-status network-status :peers-summary (or peers-summary [])
:peers-count (or peers-count 0) :node/status status
:peers-summary (or peers-summary []) :network network
:node/status status :network/type type
:network network :hardwallet hardwallet
:network/type type :device-UUID device-UUID
:hardwallet hardwallet :view-id view-id
:device-UUID device-UUID :push-notifications/stored stored)})
:view-id view-id
:push-notifications/stored stored)})
(fx/defn initialize-app (fx/defn initialize-app
[cofx encryption-key] [cofx encryption-key]

View File

@ -36,28 +36,31 @@
"Close window"]]]]])) "Close window"]]]]]))
(def step-name (def step-name
{:preparing {:label :t/initialization {:pin {:label :t/pin-code
:number 1 :number 1
:next-step :preparing}
:preparing {:label :t/initialization
:number 2
:next-step :secret-keys} :next-step :secret-keys}
:secret-keys {:label :t/puk-and-pair-codes :secret-keys {:label :t/puk-and-pair-codes
:number 2 :number 3
:next-step :pairing} :next-step :pairing}
:pairing {:label :t/pairing :pairing {:label :t/pairing
:number 3 :number 4
:next-step :recovery-phrase} :next-step :recovery-phrase}
:card-ready {:label :t/pairing :card-ready {:label :t/pairing
:number 3 :number 5
:next-step :recovery-phrase} :next-step :recovery-phrase}
:generating-mnemonic {:label :t/recovery-phrase :generating-mnemonic {:label :t/recovery-phrase
:number 4} :number 5}
:recovery-phrase-confirm-word1 {:label :t/recovery-phrase :recovery-phrase-confirm-word1 {:label :t/recovery-phrase
:number 4} :number 5}
:recovery-phrase-confirm-word2 {:label :t/recovery-phrase :recovery-phrase-confirm-word2 {:label :t/recovery-phrase
:number 4} :number 5}
:loading-keys {:label :t/recovery-phrase :loading-keys {:label :t/recovery-phrase
:number 4} :number 5}
:recovery-phrase {:label :t/recovery-phrase :recovery-phrase {:label :t/recovery-phrase
:number 4}}) :number 5}})
(defn- setup-steps [step] (defn- setup-steps [step]
(let [current-step (step-name step) (let [current-step (step-name step)
@ -96,21 +99,17 @@
(animation/start))) (animation/start)))
:display-name "maintain-card" :display-name "maintain-card"
:reagent-render (fn [step] [react/view styles/maintain-card-container :reagent-render (fn [step] [react/view styles/maintain-card-container
[react/touchable-highlight [react/view styles/hardwallet-icon-container
{:on-press #(do [vector-icons/icon :main-icons/keycard {:color colors/blue}]
(re-frame/dispatch [:hardwallet.ui/get-application-info]) [vector-icons/icon :icons/indicator-small {:color colors/blue
(reset! modal-visible? true))} :container-style (styles/hardwallet-icon-indicator-small-container
[react/view styles/hardwallet-icon-container (interpolate-fn [0 0.5 1 0.5 0]))}]
[vector-icons/icon :main-icons/keycard {:color colors/blue}] [vector-icons/icon :icons/indicator-middle {:color colors/blue
[vector-icons/icon :icons/indicator-small {:color colors/blue :container-style (styles/hardwallet-icon-indicator-middle-container
:container-style (styles/hardwallet-icon-indicator-small-container (interpolate-fn [1 0.4 0 0.4 0.8]))}]
(interpolate-fn [0 0.5 1 0.5 0]))}] [vector-icons/icon :icons/indicator-big {:color colors/blue
[vector-icons/icon :icons/indicator-middle {:color colors/blue :container-style (styles/hardwallet-icon-indicator-big-container
:container-style (styles/hardwallet-icon-indicator-middle-container (interpolate-fn [0.5 0.8 0.5 0.8 0.4]))}]]
(interpolate-fn [1 0.4 0 0.4 0.8]))}]
[vector-icons/icon :icons/indicator-big {:color colors/blue
:container-style (styles/hardwallet-icon-indicator-big-container
(interpolate-fn [0.5 0.8 0.5 0.8 0.4]))}]]]
[setup-steps step] [setup-steps step]
[application-info modal-visible?]])}))) [application-info modal-visible?]])})))

View File

@ -104,6 +104,20 @@
(def pin-retries 3) (def pin-retries 3)
(def puk-retries 5) (def puk-retries 5)
(defview create-pin []
(letsubs [pin [:hardwallet/pin]
step [:hardwallet/pin-enter-step]
status [:hardwallet/pin-status]
error-label [:hardwallet/pin-error-label]]
[pin-view {:pin pin
:title-label (case step
:confirmation :t/repeat-pin
:t/create-a-pin)
:description-label :t/create-pin-description
:step step
:status status
:error-label error-label}]))
(defview enter-pin [] (defview enter-pin []
(letsubs [pin [:hardwallet/pin] (letsubs [pin [:hardwallet/pin]
step [:hardwallet/pin-enter-step] step [:hardwallet/pin-enter-step]
@ -128,7 +142,7 @@
:title-label (case step :title-label (case step
:current :t/current-pin :current :t/current-pin
:login :t/current-pin :login :t/current-pin
:original :t/create-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

View File

@ -130,9 +130,10 @@
[action-row {:icon :main-icons/close [action-row {:icon :main-icons/close
:label :t/unpair-card :label :t/unpair-card
:on-press #(re-frame/dispatch [:keycard-settings.ui/unpair-card-pressed])}]])])] :on-press #(re-frame/dispatch [:keycard-settings.ui/unpair-card-pressed])}]])])]
[react/view {:margin-bottom 20 (when pairing
:margin-left 16} [react/view {:margin-bottom 20
[action-row {:icon :main-icons/logout :margin-left 16}
:color-theme :red [action-row {:icon :main-icons/logout
:label :t/reset-card :color-theme :red
:on-press #(re-frame/dispatch [:keycard-settings.ui/reset-card-pressed])}]]]])) :label :t/reset-card
:on-press #(re-frame/dispatch [:keycard-settings.ui/reset-card-pressed])}]])]]))

View File

@ -115,7 +115,8 @@
:color colors/black}) :color colors/black})
(def bottom-container (def bottom-container
{:height 60 {:height 52
:width "100%"
:justify-content :center :justify-content :center
:align-items :center :align-items :center
:border-top-width 1 :border-top-width 1
@ -128,8 +129,7 @@
:flex-direction :row :flex-direction :row
:width 160 :width 160
:height 44 :height 44
:border-radius 10 :border-radius 10})
:margin-bottom 14})
(def begin-button-container (def begin-button-container
{:background-color colors/gray-background {:background-color colors/gray-background
@ -143,8 +143,7 @@
(def bottom-button-text (def bottom-button-text
{:font-size 15 {:font-size 15
:color colors/blue :color colors/blue})
:line-height 20})
(def next-button-container (def next-button-container
{:flex-direction :row {:flex-direction :row
@ -313,9 +312,11 @@
:color colors/black}) :color colors/black})
(def enter-pair-code-explanation-text (def enter-pair-code-explanation-text
{:font-size 15 {:font-size 15
:padding-top 5 :padding-top 5
:color colors/gray}) :text-align :center
:padding-horizontal 60
:color colors/gray})
(def card-is-empty-text (def card-is-empty-text
{:color colors/black {:color colors/black

View File

@ -6,10 +6,15 @@
(fn [db] (fn [db]
(get-in db [:hardwallet :setup-step]))) (get-in db [:hardwallet :setup-step])))
(re-frame/reg-sub
:hardwallet-card-state
(fn [db]
(get-in db [:hardwallet :card-state])))
(re-frame/reg-sub (re-frame/reg-sub
:hardwallet-pair-code :hardwallet-pair-code
(fn [db] (fn [db]
(get-in db [:hardwallet :pair-code]))) (get-in db [:hardwallet :secrets :password])))
(re-frame/reg-sub (re-frame/reg-sub
:hardwallet-recovery-phrase-word :hardwallet-recovery-phrase-word

View File

@ -187,7 +187,7 @@
:forward? true}]]]])) :forward? true}]]]]))
(defn- card-with-button-view (defn- card-with-button-view
[{:keys [text-label button-label button-container-style on-press]}] [{:keys [text-label button-label button-container-style on-press show-icon?]}]
"Generic view with centered card image and button at the bottom. "Generic view with centered card image and button at the bottom.
Used by 'Prepare', 'Pair', 'No slots', 'Card is linked' screens" Used by 'Prepare', 'Pair', 'No slots', 'Card is linked' screens"
[react/view styles/card-with-button-view-container [react/view styles/card-with-button-view-container
@ -195,13 +195,17 @@
[react/image {:source (:hardwallet-card resources/ui) [react/image {:source (:hardwallet-card resources/ui)
:style styles/hardwallet-card-image}] :style styles/hardwallet-card-image}]
[react/view styles/center-text-container [react/view styles/center-text-container
[react/text {:style styles/center-text} [react/text {:style (assoc styles/center-text :padding-horizontal 60)}
(i18n/label text-label)]]] (i18n/label text-label)]]]
[react/touchable-highlight [react/view styles/bottom-container
{:on-press on-press} [react/touchable-highlight
[react/view (merge styles/bottom-button-container button-container-style) {:on-press on-press}
[react/text {:style styles/bottom-button-text} [react/view (merge styles/bottom-button-container button-container-style)
(i18n/label button-label)]]]]) [react/text {:style styles/bottom-button-text}
(i18n/label button-label)]
(when show-icon?
[vector-icons/icon :icons/link {:color colors/blue
:container-style {:margin-left 5}}])]]]])
(defn begin [] (defn begin []
[react/view styles/card-blank-container [react/view styles/card-blank-container
@ -219,10 +223,11 @@
[react/text {:style styles/remaining-steps-text} [react/text {:style styles/remaining-steps-text}
(i18n/label :t/remaining-steps)] (i18n/label :t/remaining-steps)]
[react/view {:margin-bottom 25} [react/view {:margin-bottom 25}
(for [[number text] [["1" (i18n/label :t/initialization-of-the-card)] (for [[number text] [["1" (i18n/label :t/create-pin)]
["2" (i18n/label :t/puk-and-pairing-codes-displayed)] ["2" (i18n/label :t/initialization-of-the-card)]
["3" (i18n/label :t/device-pairing)] ["3" (i18n/label :t/puk-and-pairing-codes-displayed)]
["4" (i18n/label :t/recovery-phrase)]]] ["4" (i18n/label :t/device-pairing)]
["5" (i18n/label :t/recovery-phrase)]]]
^{:key number} [react/view styles/remaining-step-row ^{:key number} [react/view styles/remaining-step-row
[react/view styles/remaining-step-row-text [react/view styles/remaining-step-row-text
[react/text {:style {:color colors/black}} [react/text {:style {:color colors/black}}
@ -238,21 +243,23 @@
(i18n/label :t/begin-set-up)]]]]]]) (i18n/label :t/begin-set-up)]]]]]])
(defn pair [] (defn pair []
[card-with-button-view {:text-label :t/pair-card-question [card-with-button-view {:text-label :t/pair-card-question
:button-label :t/pair-card :button-label :t/pair-card
:on-press-event #(re-frame/dispatch [:hardwallet.ui/pair-card-button-pressed])}]) :on-press #(re-frame/dispatch [:hardwallet.ui/pair-card-button-pressed])}])
(defn no-slots [] (defn no-slots []
[card-with-button-view {:text-label :t/no-pairing-slots-available [card-with-button-view {:text-label :t/no-pairing-slots-available
:button-label :t/help :button-label :t/help-capitalized
:show-icon? true
:button-container-style {:background-color colors/white} :button-container-style {:background-color colors/white}
:on-press-event (.openURL react/linking "https://hardwallet.status.im")}]) :on-press #(.openURL react/linking "https://hardwallet.status.im")}])
(defn card-already-linked [] (defn card-already-linked []
[card-with-button-view {:text-label :t/card-already-linked [card-with-button-view {:text-label :t/card-already-linked
:button-label :t/help :button-label :t/help-capitalized
:show-icon? true
:button-container-style {:background-color colors/white} :button-container-style {:background-color colors/white}
:on-press-event (.openURL react/linking "https://hardwallet.status.im")}]) :on-press #(.openURL react/linking "https://hardwallet.status.im")}])
(defview error [] (defview error []
(letsubs [error [:hardwallet-setup-error]] (letsubs [error [:hardwallet-setup-error]]
@ -263,15 +270,20 @@
[react/view styles/center-text-container [react/view styles/center-text-container
[react/text {:style styles/center-text} [react/text {:style styles/center-text}
(i18n/label :t/something-went-wrong)] (i18n/label :t/something-went-wrong)]
[react/text {:style styles/center-text} [react/view {:padding-horizontal 20
(str (:code error) "\n" (:error error))]]] :margin-top 20}
[react/touchable-highlight [react/text {:style styles/center-text}
{:on-press #(re-frame/dispatch [:hardwallet.ui/error-button-pressed])} (if (map? error)
[react/view styles/bottom-button-container (str (:code error) "\n" (:error error))
[react/text {:style styles/bottom-button-text (str error))]]]]
:font :medium [react/view styles/bottom-container
:uppercase? false} [react/touchable-highlight
(i18n/label :t/try-again)]]]])) {:on-press #(re-frame/dispatch [:hardwallet.ui/error-button-pressed])}
[react/view styles/bottom-button-container
[react/text {:style styles/bottom-button-text
:font :medium
:uppercase? false}
(i18n/label :t/try-again)]]]]]))
(defn- loading-view [{:keys [title-label text-label estimated-time-seconds step-number]}] (defn- loading-view [{:keys [title-label text-label estimated-time-seconds step-number]}]
"Generic view with waiting time estimate and loading indicator. "Generic view with waiting time estimate and loading indicator.
@ -293,7 +305,8 @@
(defview preparing [] (defview preparing []
(letsubs [progress-bar (atom nil) (letsubs [progress-bar (atom nil)
listener (atom nil)] listener (atom nil)
card-state [:hardwallet-card-state]]
{:component-will-mount (fn [] {:component-will-mount (fn []
(when @listener (when @listener
(.removeListener @listener))) (.removeListener @listener)))
@ -315,10 +328,13 @@
[react/text {:style styles/estimated-time-text} [react/text {:style styles/estimated-time-text}
(i18n/label :t/taking-long-hold-phone-connected)]] (i18n/label :t/taking-long-hold-phone-connected)]]
[react/view styles/progress-bar-container [react/view styles/progress-bar-container
[react/progress-bar {:styleAttr "Horizontal" (if (contains? #{:blank :init} card-state)
:indeterminate false [react/progress-bar {:styleAttr "Horizontal"
:progress 0 :indeterminate false
:ref #(reset! progress-bar %)}]]])) :progress 0
:ref #(reset! progress-bar %)}]
[react/activity-indicator {:animating true
:size :large}])]]))
(defn- generating-mnemonic [] (defn- generating-mnemonic []
[react/view styles/loading-view-container [react/view styles/loading-view-container
@ -378,7 +394,7 @@
:no-slots [no-slots] :no-slots [no-slots]
:card-already-linked [card-already-linked] :card-already-linked [card-already-linked]
:pairing [pairing] :pairing [pairing]
:pin [pin.views/enter-pin] :pin [pin.views/create-pin]
:recovery-phrase [recovery-phrase] :recovery-phrase [recovery-phrase]
: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]

View File

@ -797,6 +797,8 @@
"card-is-blank": "This card is blank", "card-is-blank": "This card is blank",
"card-setup-prepare-text": "The whole process will take a few minutes.", "card-setup-prepare-text": "The whole process will take a few minutes.",
"card-is-paired": "Card is paired", "card-is-paired": "Card is paired",
"no-keycard-applet-on-card": "No Keycard applet on card",
"keycard-applet-will-be-installed": "Keycard applet will automatically be installed",
"begin-set-up": "Begin setup", "begin-set-up": "Begin setup",
"maintain-card-to-phone-contact": "Maintain card-to-phone contact during process.", "maintain-card-to-phone-contact": "Maintain card-to-phone contact during process.",
"preparing-card": "Preparing card", "preparing-card": "Preparing card",
@ -842,7 +844,8 @@
"change-pin": "Change PIN", "change-pin": "Change PIN",
"enter-pin": "Enter PIN", "enter-pin": "Enter PIN",
"enter-pin-description": "Enter your PIN code to login\n to your account", "enter-pin-description": "Enter your PIN code to login\n to your account",
"create-pin": "Create a PIN", "create-pin": "Create PIN",
"create-a-pin": "Create a PIN",
"create-pin-description": "You'll need your card + this PIN to log in and to confirm transactions", "create-pin-description": "You'll need your card + this PIN to log in and to confirm transactions",
"repeat-pin": "Repeat new PIN", "repeat-pin": "Repeat new PIN",
"puk-mismatch": "PUK code does not match", "puk-mismatch": "PUK code does not match",
@ -858,11 +861,12 @@
"card-unpaired": "Card has been unpaired from current device", "card-unpaired": "Card has been unpaired from current device",
"card-reseted": "Card has been reseted", "card-reseted": "Card has been reseted",
"unpair-card-confirmation": "This operation will unpair card from current device. Requires PIN authorization. Do you want to proceed?", "unpair-card-confirmation": "This operation will unpair card from current device. Requires PIN authorization. Do you want to proceed?",
"pair-card": "pair card", "pair-card": "Pair to this device",
"pair-card-question": "Do you want to pair card to this device?", "pair-card-question": "Card is ready to pair",
"enter-pair-code": "Enter pair code", "enter-pair-code": "Enter pair code",
"enter-pair-code-description": "Needed to link your card to this device", "enter-pair-code-description": "SECURITY NOTE: Use only the code you wrote down during card setup.",
"no-pairing-slots-available": "No pairing slots are available.\n You could unpair the device\n that already paired with 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.",
"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.", "keycard-unauthorized-operation": "You're unauthorized to perform this operation.",
"no-account-on-card": "No account on this card", "no-account-on-card": "No account on this card",
@ -871,7 +875,6 @@
"wrong-card-text": "You have tapped a card that does not correspond to the account you selected. Please try again.", "wrong-card-text": "You have tapped a card that does not correspond to the account you selected. Please try again.",
"account-not-listed": "Account not listed", "account-not-listed": "Account not listed",
"account-not-listed-text": "The account on this card is not listed on your phone. Would you like to login with this new account?", "account-not-listed-text": "The account on this card is not listed on your phone. Would you like to login with this new account?",
"wrong-card-text": "You have tapped a card that does not correspond to the account you selected. Please try again.",
"no-pairing-on-device": "Card is not paired to this device", "no-pairing-on-device": "Card is not paired to this device",
"help": "help", "help": "help",
"help-capitalized": "Help", "help-capitalized": "Help",