[#10452] Keycard: updated PUK flow
This commit is contained in:
parent
4021e957ea
commit
a1027cdfcc
|
@ -348,7 +348,8 @@
|
|||
response]))
|
||||
:on-failure
|
||||
(fn [response]
|
||||
(log/info "[keycard response fail] get-keys")
|
||||
(log/info "[keycard response fail] get-keys"
|
||||
(error-object->map response))
|
||||
(re-frame/dispatch [:hardwallet.callback/on-get-keys-error
|
||||
(error-object->map response)]))})))
|
||||
|
||||
|
|
|
@ -4,24 +4,27 @@
|
|||
[status-im.hardwallet.onboarding :as onboarding]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.hardwallet.common :as common]))
|
||||
[status-im.hardwallet.common :as common]
|
||||
[status-im.hardwallet.login :as hardwallet.login]))
|
||||
|
||||
(fx/defn change-pin-pressed
|
||||
{:events [:keycard-settings.ui/change-pin-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [pin-retry-counter (get-in db [:hardwallet :application-info :pin-retry-counter])
|
||||
enter-step (if (zero? pin-retry-counter) :puk :current)]
|
||||
(fx/merge cofx
|
||||
{:db
|
||||
(assoc-in db [:hardwallet :pin] {:enter-step enter-step
|
||||
:current []
|
||||
:puk []
|
||||
:original []
|
||||
:confirmation []
|
||||
:status nil
|
||||
:error-label nil
|
||||
:on-verified :hardwallet/proceed-to-change-pin})}
|
||||
(common/navigate-to-enter-pin-screen))))
|
||||
(if (= enter-step :puk)
|
||||
(hardwallet.login/reset-pin cofx)
|
||||
(fx/merge cofx
|
||||
{:db
|
||||
(assoc-in db [:hardwallet :pin] {:enter-step enter-step
|
||||
:current []
|
||||
:puk []
|
||||
:original []
|
||||
:confirmation []
|
||||
:status nil
|
||||
:error-label nil
|
||||
:on-verified :hardwallet/proceed-to-change-pin})}
|
||||
(common/navigate-to-enter-pin-screen)))))
|
||||
|
||||
(fx/defn proceed-to-change-pin
|
||||
{:events [:hardwallet/proceed-to-change-pin]}
|
||||
|
|
|
@ -204,27 +204,30 @@
|
|||
|
||||
(fx/defn clear-pin
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (update-in db
|
||||
[:hardwallet :pin]
|
||||
merge
|
||||
{:status nil
|
||||
:login (get-in db [:hardwallet :pin :original])
|
||||
:export-key []
|
||||
:sign []
|
||||
:puk []
|
||||
:current []
|
||||
:original []
|
||||
:confirmation []
|
||||
:error-label nil})}))
|
||||
(fx/merge
|
||||
cofx
|
||||
{:db (assoc-in db
|
||||
[:hardwallet :pin]
|
||||
{:status nil
|
||||
:login (get-in db [:hardwallet :pin :original])
|
||||
:export-key []
|
||||
:sign []
|
||||
:puk []
|
||||
:current []
|
||||
:original []
|
||||
:confirmation []
|
||||
:error-label nil
|
||||
:on-verified (get-in db [:hardwallet :pin :on-verified])
|
||||
:on-verified-failure (get-in db [:hardwallet :pin :on-verified])})}))
|
||||
|
||||
(fx/defn cancel-sheet-confirm
|
||||
{:events [::cancel-sheet-confirm
|
||||
:hardwallet/back-button-pressed]}
|
||||
[cofx]
|
||||
(fx/merge cofx
|
||||
(hide-connection-sheet)
|
||||
(clear-pin)))
|
||||
[{:keys [db] :as cofx}]
|
||||
(when-not (get-in db [:hardwallet :card-connected?])
|
||||
(fx/merge cofx
|
||||
(hide-connection-sheet)
|
||||
(clear-pin))))
|
||||
|
||||
(fx/defn cancel-sheet
|
||||
{:events [::cancel-sheet]}
|
||||
|
@ -293,6 +296,9 @@
|
|||
(let [key-uid (get-in db [:multiaccounts/login :key-uid])
|
||||
pairing (get-in db [:multiaccounts/multiaccounts key-uid :keycard-pairing])
|
||||
pin (string/join (get-in db [:hardwallet :pin :login]))]
|
||||
(log/debug "[keycard] get-keys-from-keycard"
|
||||
"not nil pairing:" (boolean pairing)
|
||||
", not empty pin:" (boolean (seq pin)))
|
||||
(when (and pairing
|
||||
(seq pin))
|
||||
{:db (assoc-in db [:hardwallet :pin :status] :verifying)
|
||||
|
@ -344,15 +350,20 @@
|
|||
(if tag-was-lost?
|
||||
{:db (assoc-in db [:hardwallet :pin :status] nil)}
|
||||
(if (re-matches pin-mismatch-error (:error error))
|
||||
(fx/merge cofx
|
||||
{:hardwallet/get-application-info {:pairing (get-pairing db key-uid)}
|
||||
:db (update-in db [:hardwallet :pin] merge {:status :error
|
||||
:login []
|
||||
:import-multiaccount []
|
||||
:error-label :t/pin-mismatch})}
|
||||
(hide-connection-sheet)
|
||||
(when (= flow :import)
|
||||
(navigation/navigate-to-cofx :keycard-recovery-pin nil)))
|
||||
(fx/merge
|
||||
cofx
|
||||
{:hardwallet/get-application-info
|
||||
{:pairing (get-pairing db key-uid)}
|
||||
|
||||
:db
|
||||
(update-in db [:hardwallet :pin] merge
|
||||
{:status :error
|
||||
:login []
|
||||
:import-multiaccount []
|
||||
:error-label :t/pin-mismatch})}
|
||||
(hide-connection-sheet)
|
||||
(when (= flow :import)
|
||||
(navigation/navigate-to-cofx :keycard-recovery-pin nil)))
|
||||
(show-wrong-keycard-alert true)))))
|
||||
|
||||
;; Get application info
|
||||
|
@ -360,44 +371,57 @@
|
|||
(fx/defn get-application-info
|
||||
{:events [:hardwallet/get-application-info]}
|
||||
[{:keys [db]} pairing on-card-read]
|
||||
(let [key-uid (get-in db [:hardwallet :application-info :key-uid])
|
||||
(let [key-uid (get-in
|
||||
db [:hardwallet :application-info :key-uid]
|
||||
(get-in db [:multiaccounts/login :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}}))
|
||||
|
||||
(fx/defn frozen-keycard-popup
|
||||
[{:keys [db] :as cofx}]
|
||||
(if (:multiaccounts/login db)
|
||||
(fx/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:hardwallet :pin :status] :frozen-card)}
|
||||
hide-connection-sheet)
|
||||
{:db (assoc db :popover/popover {:view :frozen-card})}))
|
||||
|
||||
(fx/defn on-get-application-info-success
|
||||
{:events [:hardwallet.callback/on-get-application-info-success]}
|
||||
[{:keys [db] :as cofx} info on-success]
|
||||
(let [info' (-> info
|
||||
(js->clj :keywordize-keys true)
|
||||
(update :key-uid ethereum/normalized-hex))
|
||||
{:keys [pin-retry-counter puk-retry-counter]} info'
|
||||
(let [{:keys [pin-retry-counter puk-retry-counter]} info
|
||||
view-id (:view-id db)
|
||||
|
||||
{:keys [on-card-read]} (:hardwallet db)
|
||||
on-success' (or on-success on-card-read)
|
||||
enter-step (if (zero? pin-retry-counter)
|
||||
:puk
|
||||
(get-in db [:hardwallet :pin :enter-step]))]
|
||||
enter-step (get-in db [:hardwallet :pin :enter-step])]
|
||||
(log/debug "[hardwallet] on-get-application-info-success"
|
||||
"on-success" on-success')
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:hardwallet :pin :enter-step] enter-step)
|
||||
(update-in [:hardwallet :pin :error-label] #(if (= :puk enter-step)
|
||||
:t/enter-puk-code-description
|
||||
%))
|
||||
(assoc-in [:hardwallet :application-info] info')
|
||||
(assoc-in [:hardwallet :application-info :applet-installed?] true)
|
||||
(assoc-in [:hardwallet :application-info-error] nil))}
|
||||
(stash-on-card-read)
|
||||
(if (zero? puk-retry-counter)
|
||||
{:utils/show-popup {:title (i18n/label :t/error)
|
||||
:content (i18n/label :t/keycard-blocked)}}
|
||||
(when on-success'
|
||||
(dispatch-event on-success'))))))
|
||||
"on-success" on-success'
|
||||
"pin-retry-counter" pin-retry-counter
|
||||
"puk-retry-counter" puk-retry-counter)
|
||||
(fx/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:hardwallet :pin :enter-step] enter-step)
|
||||
(assoc-in [:hardwallet :application-info] info)
|
||||
(assoc-in [:hardwallet :application-info :applet-installed?] true)
|
||||
(assoc-in [:hardwallet :application-info-error] nil))}
|
||||
(stash-on-card-read)
|
||||
(when (and (zero? pin-retry-counter)
|
||||
(pos? puk-retry-counter)
|
||||
(not= enter-step :puk))
|
||||
(frozen-keycard-popup))
|
||||
(fn [{:keys [db] :as cofx}]
|
||||
(if (zero? puk-retry-counter)
|
||||
(fx/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:hardwallet :pin :status] :blocked-card)}
|
||||
hide-connection-sheet)
|
||||
(when on-success'
|
||||
(dispatch-event cofx on-success')))))))
|
||||
|
||||
(fx/defn on-get-application-info-error
|
||||
{:events [:hardwallet.callback/on-get-application-info-error]}
|
||||
|
@ -484,3 +508,12 @@
|
|||
{:db (assoc-in db [:hardwallet :pin :status] :verifying)
|
||||
:hardwallet/verify-pin {:pin pin
|
||||
:pairing pairing}})))}))))
|
||||
|
||||
(fx/defn navigete-to-keycard-settings
|
||||
{:events [::navigate-to-keycard-settings]}
|
||||
[cofx]
|
||||
(navigation/navigate-reset
|
||||
cofx
|
||||
{:index 1
|
||||
:routes [{:name :my-profile}
|
||||
{:name :keycard-settings}]}))
|
||||
|
|
|
@ -120,22 +120,35 @@
|
|||
(defn- proceed-to-pin-confirmation [fx]
|
||||
(assoc-in fx [:db :hardwallet :pin :enter-step] :confirmation))
|
||||
|
||||
(defn- proceed-to-pin-reset-confirmation [fx]
|
||||
(-> fx
|
||||
(update-in [:db :hardwallet :pin] dissoc :reset-confirmation)
|
||||
(assoc-in [:db :hardwallet :pin :enter-step] :reset-confirmation)))
|
||||
|
||||
(defn- proceed-to-puk-confirmation [fx]
|
||||
(assoc-in fx [:db :hardwallet :pin :enter-step] :puk))
|
||||
|
||||
(fx/defn on-unblock-pin-success
|
||||
{:events [:hardwallet.callback/on-unblock-pin-success]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [pairing (common/get-pairing db)]
|
||||
(let [pairing (common/get-pairing db)
|
||||
reset-pin (get-in db [:hardwallet :pin :reset])]
|
||||
(fx/merge cofx
|
||||
{:hardwallet/get-application-info {:pairing pairing}
|
||||
:db (-> db
|
||||
(update-in [:hardwallet :pin] merge {:status nil
|
||||
:enter-step :original
|
||||
:current [0 0 0 0 0 0]
|
||||
:confirmation []
|
||||
:puk []
|
||||
:puk-restore? true
|
||||
:error-label nil}))}
|
||||
{:hardwallet/get-application-info
|
||||
{:pairing pairing}
|
||||
|
||||
:db
|
||||
(update-in db [:hardwallet :pin] merge
|
||||
{:status :after-unblocking
|
||||
:enter-step :login
|
||||
:login reset-pin
|
||||
:confirmation []
|
||||
:puk []
|
||||
:puk-restore? true
|
||||
:error-label nil})}
|
||||
(common/hide-connection-sheet)
|
||||
(navigation/navigate-to-cofx :enter-pin-settings nil))))
|
||||
(common/clear-on-card-connected)
|
||||
(common/clear-on-card-read))))
|
||||
|
||||
(fx/defn on-unblock-pin-error
|
||||
{:events [:hardwallet.callback/on-unblock-pin-error]}
|
||||
|
@ -145,11 +158,15 @@
|
|||
(log/debug "[hardwallet] unblock pin error" error)
|
||||
(when-not tag-was-lost?
|
||||
(fx/merge cofx
|
||||
{:hardwallet/get-application-info {:pairing pairing}
|
||||
:db (update-in db [:hardwallet :pin] merge {:status :error
|
||||
:error-label :t/puk-mismatch
|
||||
:enter-step :puk
|
||||
:puk []})}
|
||||
{:hardwallet/get-application-info
|
||||
{:pairing pairing}
|
||||
|
||||
:db
|
||||
(update-in db [:hardwallet :pin] merge
|
||||
{:status :error
|
||||
:error-label :t/puk-mismatch
|
||||
:enter-step :puk
|
||||
:puk []})}
|
||||
(common/hide-connection-sheet)))))
|
||||
|
||||
(fx/defn clear-on-verify-handlers
|
||||
|
@ -215,7 +232,7 @@
|
|||
(fn [_] {:utils/dispatch-later
|
||||
[{:dispatch [on-verified-failure]
|
||||
:ms 200}]}))
|
||||
(clear-on-verify-handlers))
|
||||
#_(clear-on-verify-handlers))
|
||||
|
||||
(fx/merge cofx
|
||||
(common/hide-connection-sheet)
|
||||
|
@ -231,12 +248,13 @@
|
|||
:handler
|
||||
(fn [{:keys [db]}]
|
||||
(let [puk (common/vector->string (get-in db [:hardwallet :pin :puk]))
|
||||
pin (common/vector->string (get-in db [:hardwallet :pin :reset]))
|
||||
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
|
||||
:new-pin pin
|
||||
:pairing pairing}}))}))
|
||||
|
||||
(def pin-code-length 6)
|
||||
|
@ -252,12 +270,15 @@
|
|||
(fx/defn update-pin
|
||||
{:events [:hardwallet.ui/pin-numpad-button-pressed]}
|
||||
[{:keys [db] :as cofx} number enter-step]
|
||||
(log/debug "update-pin" enter-step)
|
||||
(let [numbers-entered (count (get-in db [:hardwallet :pin enter-step]))
|
||||
need-update? (if (= enter-step :puk)
|
||||
(< numbers-entered puk-code-length)
|
||||
(< numbers-entered pin-code-length))]
|
||||
(fx/merge cofx
|
||||
{:db (cond-> (assoc-in db [:hardwallet :pin :status] nil)
|
||||
{:db (cond-> (-> db
|
||||
(assoc-in [:hardwallet :pin :enter-step] enter-step)
|
||||
(assoc-in [:hardwallet :pin :status] nil))
|
||||
need-update? (update-in [:hardwallet :pin enter-step] (fnil conj []) number))}
|
||||
(when need-update?
|
||||
(handle-pin-input enter-step)))))
|
||||
|
@ -269,6 +290,13 @@
|
|||
:original []
|
||||
:confirmation []}))
|
||||
|
||||
(defn- pin-reset-error [fx error-label]
|
||||
(update-in fx [:db :hardwallet :pin] merge {:status :error
|
||||
:error-label error-label
|
||||
:enter-step :reset
|
||||
:reset []
|
||||
:reset-confirmation []}))
|
||||
|
||||
; PIN enter steps:
|
||||
; login - PIN is used to login
|
||||
; sign - PIN for transaction sign
|
||||
|
@ -309,7 +337,7 @@
|
|||
|
||||
(and (= enter-step :export-key)
|
||||
(= pin-code-length numbers-entered))
|
||||
(wallet/hide-pin-sheet)
|
||||
(wallet/verify-pin-with-delay)
|
||||
|
||||
(and (= enter-step :sign)
|
||||
(= pin-code-length numbers-entered))
|
||||
|
@ -328,7 +356,21 @@
|
|||
(= pin-code-length numbers-entered)
|
||||
(not= (get-in db [:hardwallet :pin :original])
|
||||
(get-in db [:hardwallet :pin :confirmation])))
|
||||
(pin-enter-error :t/pin-mismatch))))
|
||||
(pin-enter-error :t/pin-mismatch)
|
||||
|
||||
(= enter-step :reset)
|
||||
(proceed-to-pin-reset-confirmation)
|
||||
|
||||
(and (= enter-step :reset-confirmation)
|
||||
(= (get-in db [:hardwallet :pin :reset])
|
||||
(get-in db [:hardwallet :pin :reset-confirmation])))
|
||||
(proceed-to-puk-confirmation)
|
||||
|
||||
(and (= enter-step :reset-confirmation)
|
||||
(= pin-code-length numbers-entered)
|
||||
(not= (get-in db [:hardwallet :pin :reset])
|
||||
(get-in db [:hardwallet :pin :reset-confirmation])))
|
||||
(pin-reset-error :t/pin-mismatch))))
|
||||
|
||||
(fx/defn set-multiaccount-pairing
|
||||
[cofx _ pairing paired-on]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.hardwallet.export-key
|
||||
(:require [status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.hardwallet.wallet :as wallet]
|
||||
[status-im.hardwallet.common :as common]))
|
||||
|
||||
(fx/defn on-export-key-error
|
||||
|
@ -39,5 +40,6 @@
|
|||
(let [callback-fn (get-in db [:hardwallet :on-export-success])]
|
||||
(fx/merge cofx
|
||||
{:dispatch (callback-fn pubkey)}
|
||||
(wallet/hide-pin-sheet)
|
||||
(common/clear-pin)
|
||||
(common/hide-connection-sheet))))
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
[status-im.hardwallet.recovery :as recovery]
|
||||
[status-im.hardwallet.onboarding :as onboarding]
|
||||
status-im.hardwallet.fx
|
||||
[status-im.ui.components.bottom-sheet.core :as bottom-sheet]))
|
||||
[status-im.ui.components.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.signing.core :as signing.core]))
|
||||
|
||||
(fx/defn login-got-it-pressed
|
||||
{:events [:keycard.login.pin.ui/got-it-pressed
|
||||
|
@ -49,16 +50,56 @@
|
|||
{:db (assoc-in db [:hardwallet :flow] :login)}
|
||||
(navigation/navigate-to-cofx :keycard-recovery-pair nil)))
|
||||
|
||||
(fx/defn frozen-keycard-popup
|
||||
[{:keys [db]}]
|
||||
{:db (assoc db :popover/popover {:view :frozen-card})})
|
||||
|
||||
(fx/defn reset-pin
|
||||
{:events [::reset-pin]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
cofx
|
||||
{:db (assoc db :hardwallet/new-account-sheet? false)}
|
||||
(signing.core/discard)
|
||||
(fn [{:keys [db]}]
|
||||
{:db (-> db
|
||||
(dissoc :popover/popover)
|
||||
(update-in [:hardwallet :pin] dissoc
|
||||
:reset :puk)
|
||||
(update-in [:hardwallet :pin] assoc
|
||||
:enter-step :reset
|
||||
:error nil
|
||||
:status nil))})
|
||||
(when-not (:multiaccounts/login db)
|
||||
(navigation/navigate-to-cofx
|
||||
:profile-stack
|
||||
{:screen :keycard-pin}))))
|
||||
|
||||
(fx/defn dismiss-frozen-keycard-popover
|
||||
{:events [::frozen-keycard-popover-dismissed]}
|
||||
[{:keys [db]}]
|
||||
{:db (-> db
|
||||
(dissoc :popover/popover)
|
||||
(update :hardwallet dissoc :setup-step))})
|
||||
|
||||
(fx/defn login-with-keycard
|
||||
{:events [:hardwallet/login-with-keycard]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [application-info (get-in db [:hardwallet :application-info])
|
||||
(let [{:keys [:pin-retry-counter :puk-retry-counter]
|
||||
:as application-info}
|
||||
(get-in db [:hardwallet :application-info])
|
||||
|
||||
key-uid (get-in db [:hardwallet :application-info :key-uid])
|
||||
multiaccount (get-in db [:multiaccounts/multiaccounts (get-in db [:multiaccounts/login :key-uid])])
|
||||
multiaccount-key-uid (get multiaccount :key-uid)
|
||||
multiaccount-mismatch? (or (nil? multiaccount)
|
||||
(not= multiaccount-key-uid key-uid))
|
||||
pairing (:keycard-pairing multiaccount)]
|
||||
(log/debug "[keycard] login-with-keycard"
|
||||
"empty application info" (empty? application-info)
|
||||
"no key-uid" (empty? key-uid)
|
||||
"multiaccount-mismatch?" multiaccount-mismatch?
|
||||
"no pairing" (empty? pairing))
|
||||
(cond
|
||||
(empty? application-info)
|
||||
(fx/merge cofx
|
||||
|
@ -80,10 +121,16 @@
|
|||
(common/hide-connection-sheet)
|
||||
(navigation/navigate-to-cofx :keycard-unpaired nil))
|
||||
|
||||
(and (zero? pin-retry-counter)
|
||||
(or (nil? puk-retry-counter)
|
||||
(= 5 puk-retry-counter)))
|
||||
nil #_(frozen-keycard-popup cofx)
|
||||
|
||||
:else
|
||||
(common/get-keys-from-keycard cofx))))
|
||||
|
||||
(fx/defn proceed-to-login
|
||||
{:events [::login-after-reset]}
|
||||
[cofx]
|
||||
(log/debug "[hardwallet] proceed-to-login")
|
||||
(common/show-connection-sheet
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
["react-native" :as rn]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.hardwallet.keycard :as keycard]))
|
||||
|
||||
(defonce event-emitter (.-DeviceEventEmitter rn))
|
||||
|
@ -57,9 +58,20 @@
|
|||
|
||||
(defn get-application-info
|
||||
[{:keys [pairing on-success on-failure]}]
|
||||
;; NOTE: if the card fails to get application info in the middle of the call
|
||||
;; it doesn't returns a Tar was lost. error properly
|
||||
;; https://github.com/status-im/react-native-status-keycard/blob/master/android/src/main/java/im/status/ethereum/keycard/SmartCard.java#L235
|
||||
|
||||
(.. status-keycard
|
||||
(getApplicationInfo (str pairing))
|
||||
(then on-success)
|
||||
(then (fn [response]
|
||||
(let [info (-> response
|
||||
(js->clj :keywordize-keys true)
|
||||
(update :key-uid ethereum/normalized-hex))]
|
||||
(if (and pairing (nil? (:pin-retry-counter info)))
|
||||
(on-failure (clj->js {:message "Tag was lost."
|
||||
:code "android.nfc.TagLostException"}))
|
||||
(on-success info)))))
|
||||
(catch on-failure)))
|
||||
|
||||
(defn install-applet [{:keys [on-success on-failure]}]
|
||||
|
|
|
@ -197,17 +197,21 @@
|
|||
{:events [:hardwallet.callback/on-sign-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(log/debug "[hardwallet] sign error: " error)
|
||||
(let [tag-was-lost? (common/tag-lost? (:error error))]
|
||||
(let [tag-was-lost? (common/tag-lost? (:error error))
|
||||
pin-retries (get-in db [:hardwallet :application-info :pin-retry-counter])]
|
||||
(when-not tag-was-lost?
|
||||
(if (re-matches common/pin-mismatch-error (:error error))
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:hardwallet :application-info :pin-retry-counter] (dec pin-retries))
|
||||
(update-in [:hardwallet :pin] merge {:status :error
|
||||
:sign []
|
||||
:error-label :t/pin-mismatch})
|
||||
(assoc-in [:signing/sign :keycard-step] :pin))}
|
||||
(common/hide-connection-sheet)
|
||||
(common/get-application-info (common/get-pairing db) nil))
|
||||
(common/get-application-info (common/get-pairing db) nil)
|
||||
(when (zero? (dec pin-retries))
|
||||
(common/frozen-keycard-popup)))
|
||||
(fx/merge cofx
|
||||
(common/hide-connection-sheet)
|
||||
(common/show-wrong-keycard-alert true))))))
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
:paired? true
|
||||
:has-master-key? true
|
||||
:initialized? true
|
||||
:pin-retry-counter 3
|
||||
:puk-retry-counter 5
|
||||
:key-uid (get-in @re-frame.db/app-db [:multiaccounts/login :key-uid])})
|
||||
(connect-card))
|
||||
|
||||
|
@ -84,7 +86,7 @@
|
|||
(defn install-cash-applet [_])
|
||||
|
||||
(def kk1-password "000000")
|
||||
|
||||
(def default-puk "000000000000")
|
||||
(defn init-card [{:keys [pin on-success]}]
|
||||
(swap! state assoc :application-info
|
||||
{:free-pairing-slots 5
|
||||
|
@ -98,7 +100,7 @@
|
|||
(swap! state assoc :pin pin)
|
||||
(later
|
||||
#(on-success {:password kk1-password
|
||||
:puk "000000000000"
|
||||
:puk default-puk
|
||||
:pin pin})))
|
||||
|
||||
(defn install-applet-and-init-card [_])
|
||||
|
@ -141,12 +143,34 @@
|
|||
password
|
||||
#(on-success response)))))
|
||||
|
||||
(defn unblock-pin [_])
|
||||
(defn unblock-pin
|
||||
[{:keys [puk on-success on-failure]}]
|
||||
(if (= puk default-puk)
|
||||
(do
|
||||
(swap! state update :application-info assoc
|
||||
:pin-retry-counter 3
|
||||
:puk-retry-counter 5)
|
||||
(later #(on-success true)))
|
||||
(do
|
||||
(swap! state update-in
|
||||
[:application-info :puk-retry-counter]
|
||||
(fnil dec 5))
|
||||
(later
|
||||
#(on-failure
|
||||
#js {:code "EUNSPECIFIED"
|
||||
:message "Unexpected error SW, 0x63C2"})))))
|
||||
|
||||
(defn verify-pin [{:keys [pin pairing on-success]}]
|
||||
(when (and (= pairing kk1-pair)
|
||||
(= pin (get @state :pin)))
|
||||
(later #(on-success 3))))
|
||||
(defn verify-pin [{:keys [pin pairing on-success on-failure]}]
|
||||
(if (and (= pairing kk1-pair)
|
||||
(= pin (get @state :pin)))
|
||||
(later #(on-success 3))
|
||||
(do
|
||||
(swap! state update-in
|
||||
[:application-info :pin-retry-counter]
|
||||
(fnil dec 3))
|
||||
(later #(on-failure
|
||||
#js {:code "EUNSPECIFIED"
|
||||
:message "Unexpected error SW, 0x63C2"})))))
|
||||
|
||||
(defn change-pin [args]
|
||||
(log/warn "change-pin not implemented" args))
|
||||
|
@ -199,16 +223,42 @@
|
|||
(on-success publicKey)))))))))))))))
|
||||
|
||||
(defn unpair-and-delete [_])
|
||||
(defn get-keys [{:keys [on-success pin]}]
|
||||
(swap! state assoc :pin pin)
|
||||
;;TODO(rasom): verify password before callback
|
||||
(later
|
||||
#(on-success
|
||||
{:key-uid (get-in @state [:application-info :key-uid])
|
||||
:encryption-public-key (ethereum/sha3 pin)})))
|
||||
|
||||
(defn sign [{:keys [on-success]}]
|
||||
(on-success "123"))
|
||||
;; It is a bit complicated to verify password before we have multiaccs main
|
||||
;; wallet address, so we just define a set of "allowed" pins
|
||||
(def allowed-pins
|
||||
#{"121212" "111111" "222222" "123123"})
|
||||
|
||||
(defn get-keys [{:keys [on-success on-failure pin]}]
|
||||
(if (contains? allowed-pins pin)
|
||||
(do
|
||||
(swap! state assoc :pin pin)
|
||||
(later
|
||||
#(on-success
|
||||
{:key-uid (get-in @state [:application-info :key-uid])
|
||||
:encryption-public-key (ethereum/sha3 pin)})))
|
||||
(do
|
||||
(log/debug "Incorrect PIN" pin)
|
||||
(swap! state update-in
|
||||
[:application-info :pin-retry-counter]
|
||||
(fnil dec 3))
|
||||
(later
|
||||
#(on-failure
|
||||
#js {:code "EUNSPECIFIED"
|
||||
:message "Unexpected error SW, 0x63C2"})))))
|
||||
|
||||
(defn sign [{:keys [pin on-success on-failure]}]
|
||||
(if (= pin (get @state :pin))
|
||||
(later
|
||||
#(on-success "123"))
|
||||
(do
|
||||
(swap! state update-in
|
||||
[:application-info :pin-retry-counter]
|
||||
(fnil dec 3))
|
||||
(later
|
||||
#(on-failure
|
||||
#js {:code "EUNSPECIFIED"
|
||||
:message "Unexpected error SW, 0x63C2"})))))
|
||||
|
||||
(defn sign-typed-data [args]
|
||||
(log/warn "sign-typed-data not implemented" args))
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
(ns status-im.hardwallet.wallet
|
||||
(:require [status-im.ethereum.core :as ethereum]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.ui.screens.wallet.add-new.views :as add-new.views]
|
||||
[status-im.hardwallet.common :as common]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.ui.components.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.utils.hex :as utils.hex]))
|
||||
|
||||
(fx/defn show-pin-sheet
|
||||
|
@ -15,21 +13,20 @@
|
|||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:hardwallet :pin :enter-step] :export-key)
|
||||
(update-in [:hardwallet :pin] dissoc :export-key))}
|
||||
(bottom-sheet/show-bottom-sheet
|
||||
{:view {:content add-new.views/pin
|
||||
:height 256}})))
|
||||
(update-in [:hardwallet :pin] dissoc :export-key)
|
||||
(assoc :hardwallet/new-account-sheet? true))}))
|
||||
|
||||
(fx/defn verify-pin-with-delay
|
||||
[cofx]
|
||||
{:utils/dispatch-later
|
||||
;; We need to give previous sheet some time to be fully hidden
|
||||
[{:ms 200
|
||||
:dispatch [:wallet.accounts/verify-pin]}]})
|
||||
|
||||
(fx/defn hide-pin-sheet
|
||||
{:events [:hardwallet/hide-new-account-pin-sheet]}
|
||||
[cofx]
|
||||
(fx/merge
|
||||
cofx
|
||||
{:utils/dispatch-later
|
||||
;; We need to give previous sheet some time to be fully hidden
|
||||
[{:ms 200
|
||||
:dispatch [:wallet.accounts/verify-pin]}]}
|
||||
(bottom-sheet/hide-bottom-sheet)))
|
||||
{:events [:hardwallet/new-account-pin-sheet-hide]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc db :hardwallet/new-account-sheet? false)})
|
||||
|
||||
(fx/defn generate-new-keycard-account
|
||||
{:events [:wallet.accounts/generate-new-keycard-account]}
|
||||
|
@ -59,6 +56,6 @@
|
|||
(common/verify-pin
|
||||
cofx
|
||||
{:pin-step :export-key
|
||||
:on-card-connected :wallet.accounts/generate-new-keycard-account
|
||||
:on-card-connected :wallet.accounts/verify-pin
|
||||
:on-success :wallet.accounts/generate-new-keycard-account
|
||||
:on-failure :hardwallet/new-account-pin-sheet}))
|
||||
|
|
|
@ -716,7 +716,6 @@
|
|||
:pin-changed
|
||||
:pin-code
|
||||
:pin-mismatch
|
||||
:pin-retries-left
|
||||
:preview-privacy
|
||||
:privacy
|
||||
:privacy-and-security
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.hardwallet.common :as hardwallet.common]
|
||||
[status-im.fleet.core :as fleet]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.multiaccounts.biometric.core :as biometric]
|
||||
|
@ -367,16 +368,18 @@
|
|||
(log/debug "[login] get-auth-method-success"
|
||||
"auth-method" auth-method
|
||||
"keycard-multiacc?" keycard-multiaccount?)
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :auth-method auth-method)}
|
||||
#(cond
|
||||
(= auth-method
|
||||
keychain/auth-method-biometric)
|
||||
(biometric/biometric-auth %)
|
||||
(= auth-method
|
||||
keychain/auth-method-password)
|
||||
(get-credentials % key-uid))
|
||||
(open-login-callback nil))))
|
||||
(fx/merge
|
||||
cofx
|
||||
{:db (assoc db :auth-method auth-method)}
|
||||
#(cond
|
||||
(= auth-method keychain/auth-method-biometric)
|
||||
(biometric/biometric-auth %)
|
||||
(= auth-method keychain/auth-method-password)
|
||||
(get-credentials % key-uid)
|
||||
(and keycard-multiaccount?
|
||||
(get-in db [:hardwallet :card-connected?]))
|
||||
(hardwallet.common/get-application-info % nil nil))
|
||||
(open-login-callback nil))))
|
||||
|
||||
(fx/defn biometric-auth-done
|
||||
{:events [:biometric-auth-done]}
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
(navigate-to-cofx cofx view-id params))
|
||||
|
||||
(fx/defn navigate-replace
|
||||
{:events [:navigate-replace]}
|
||||
[{:keys [db]} go-to-view-id screen-params]
|
||||
(let [db (cond-> (assoc db :view-id go-to-view-id)
|
||||
(seq screen-params)
|
||||
|
|
|
@ -188,6 +188,9 @@
|
|||
(reg-root-key-sub ::message-lists :message-lists)
|
||||
(reg-root-key-sub ::pagination-info :pagination-info)
|
||||
|
||||
;; keycard
|
||||
(reg-root-key-sub :hardwallet/new-account-sheet? :hardwallet/new-account-sheet?)
|
||||
|
||||
;;GENERAL ==============================================================================================================
|
||||
|
||||
(re-frame/reg-sub
|
||||
|
|
|
@ -49,7 +49,28 @@
|
|||
update? (atom nil)
|
||||
current-obj (reagent/atom nil)]
|
||||
(reagent/create-class
|
||||
{:component-will-update (fn [_ [_ obj _ _]]
|
||||
{:component-will-mount (fn [args]
|
||||
(let [[_ obj _ _] (.-argv (.-props args))]
|
||||
(when @clear-timeout (js/clearTimeout @clear-timeout))
|
||||
(when (or (not= obj @current-obj) @update?)
|
||||
(cond
|
||||
@update?
|
||||
(do (reset! update? false)
|
||||
(show-panel-anim bottom-anim-value alpha-value))
|
||||
|
||||
(and @current-obj obj)
|
||||
(do (reset! update? true)
|
||||
(js/setTimeout #(reset! current-obj obj) 600)
|
||||
(hide-panel-anim bottom-anim-value alpha-value (- window-height)))
|
||||
|
||||
obj
|
||||
(do (reset! current-obj obj)
|
||||
(show-panel-anim bottom-anim-value alpha-value))
|
||||
|
||||
:else
|
||||
(do (reset! clear-timeout (js/setTimeout #(reset! current-obj nil) 600))
|
||||
(hide-panel-anim bottom-anim-value alpha-value (- window-height)))))))
|
||||
:component-will-update (fn [_ [_ obj _ _]]
|
||||
(when @clear-timeout (js/clearTimeout @clear-timeout))
|
||||
(when (or (not= obj @current-obj) @update?)
|
||||
(cond
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
(ns status-im.ui.screens.hardwallet.frozen-card.view
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.icons.vector-icons :as icons]
|
||||
[status-im.ui.components.common.common :as components.common]
|
||||
[status-im.hardwallet.login :as login]
|
||||
[status-im.i18n :as i18n]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(views/defview frozen-card
|
||||
[{:keys [show-dismiss-button?]
|
||||
:or {show-dismiss-button? true}}]
|
||||
[react/view {:style (when-not show-dismiss-button?
|
||||
{:flex 1})}
|
||||
[react/view {:margin-top 24
|
||||
:margin-horizontal 24
|
||||
:align-items :center}
|
||||
[react/view {:background-color colors/blue-light
|
||||
:width 32 :height 32
|
||||
:border-radius 16
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
[icons/icon :main-icons/warning {:color colors/blue}]]
|
||||
[react/text {:style {:typography :title-bold
|
||||
:margin-top 16
|
||||
:margin-bottom 8}}
|
||||
(i18n/label :t/keycard-is-frozen-title)]
|
||||
[react/text {:style {:color colors/gray
|
||||
:text-align :center}}
|
||||
(i18n/label :t/keycard-is-frozen-details)]]
|
||||
[react/view {:margin-bottom 24
|
||||
:margin-horizontal 24
|
||||
:align-items :center}
|
||||
[components.common/button
|
||||
{:on-press #(re-frame/dispatch [::login/reset-pin])
|
||||
:button-style {:margin-top 24}
|
||||
:label (i18n/label :t/keycard-is-frozen-reset)}]
|
||||
(when show-dismiss-button?
|
||||
[components.common/button
|
||||
{:on-press #(re-frame/dispatch [::login/frozen-keycard-popover-dismissed])
|
||||
:button-style {:margin-top 24}
|
||||
:background? false
|
||||
:label (i18n/label :t/dismiss)}])]])
|
|
@ -1,22 +1,41 @@
|
|||
(ns status-im.ui.screens.hardwallet.pin.styles
|
||||
(:require [status-im.ui.components.colors :as colors]
|
||||
[status-im.utils.styles :as styles]))
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(styles/def pin-container
|
||||
(def pin-container
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :space-between})
|
||||
|
||||
(defn error-container [small-screen?]
|
||||
{:height (when small-screen? 18)
|
||||
:margin-top (if small-screen? 14 10)
|
||||
:margin-bottom (if small-screen? 10 0)})
|
||||
(defn info-container [small-screen?]
|
||||
{:height 44
|
||||
:width "100%"
|
||||
:justify-content :center
|
||||
:margin-top (if small-screen? 14 10)})
|
||||
|
||||
(defn error-container [y-translation opacity]
|
||||
{:left 0
|
||||
:right 0
|
||||
:align-items :center
|
||||
:position :absolute
|
||||
:transform [{:translateY y-translation}]
|
||||
:opacity opacity
|
||||
:justify-content :center})
|
||||
|
||||
(defn error-text [small-screen?]
|
||||
{:color colors/red
|
||||
{:position :absolute
|
||||
:color colors/red
|
||||
:font-size (if small-screen? 12 15)
|
||||
:text-align :center})
|
||||
|
||||
(defn retry-container [y-translation opacity]
|
||||
{:left 0
|
||||
:right 0
|
||||
:align-items :center
|
||||
:position :absolute
|
||||
:transform [{:translateY y-translation}]
|
||||
:opacity opacity
|
||||
:justify-content :center})
|
||||
|
||||
(defn center-container [title]
|
||||
{:flex-direction :column
|
||||
:align-items :center
|
||||
|
@ -34,16 +53,18 @@
|
|||
(def pin-indicator-container
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:margin-top 16})
|
||||
:align-items :center
|
||||
:height 22
|
||||
:margin-top 5})
|
||||
|
||||
(def pin-indicator-group-container
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between})
|
||||
|
||||
(defn pin-indicator [pressed? status]
|
||||
(defn pin-indicator [pressed? error?]
|
||||
{:width 8
|
||||
:height 8
|
||||
:background-color (if (= status :error)
|
||||
:background-color (if error?
|
||||
colors/red
|
||||
(if pressed?
|
||||
colors/blue
|
||||
|
@ -51,6 +72,15 @@
|
|||
:border-radius 50
|
||||
:margin-horizontal 5})
|
||||
|
||||
(defn puk-indicator [error?]
|
||||
{:width 8
|
||||
:height 8
|
||||
:background-color (if error?
|
||||
colors/red
|
||||
colors/black-transparent)
|
||||
:border-radius 50
|
||||
:margin-horizontal 5})
|
||||
|
||||
(def waiting-indicator-container
|
||||
{:margin-top 26})
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
(re-frame/reg-sub
|
||||
:hardwallet/pin-enter-step
|
||||
(fn [db]
|
||||
(get-in db [:hardwallet :pin :enter-step] :original)))
|
||||
(get-in db [:hardwallet :pin :enter-step])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:hardwallet/pin-operation
|
||||
|
@ -47,3 +47,10 @@
|
|||
:hardwallet/pin-error-label
|
||||
(fn [db]
|
||||
(get-in db [:hardwallet :pin :error-label])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:hardwallet/frozen-card?
|
||||
(fn [db]
|
||||
(let [{:keys [pin-retry-counter]}
|
||||
(get-in db [:hardwallet :application-info])]
|
||||
(zero? pin-retry-counter))))
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
(ns status-im.ui.screens.hardwallet.pin.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||
|
@ -8,9 +10,11 @@
|
|||
[status-im.ui.screens.hardwallet.pin.styles :as styles]
|
||||
[status-im.ui.components.checkbox.view :as checkbox]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.ui.components.topbar :as topbar]))
|
||||
|
||||
(def default-pin-retries-number 3)
|
||||
(def default-puk-retries-number 5)
|
||||
|
||||
(defn numpad-button [n step enabled? small-screen?]
|
||||
[react/touchable-highlight
|
||||
|
@ -40,32 +44,36 @@
|
|||
[react/view (styles/numpad-delete-button small-screen?)
|
||||
[vector-icons/icon :main-icons/backspace {:color colors/blue}]]]]])
|
||||
|
||||
(defn pin-indicator [pressed? status]
|
||||
[react/view (styles/pin-indicator pressed? status)])
|
||||
|
||||
(defn pin-indicators [pin status style]
|
||||
[react/view (merge styles/pin-indicator-container style)
|
||||
(defn pin-indicators [pin error?]
|
||||
[react/view styles/pin-indicator-container
|
||||
(map-indexed
|
||||
(fn [i group]
|
||||
^{:key i}
|
||||
[react/view styles/pin-indicator-group-container
|
||||
group])
|
||||
(partition 3
|
||||
(map-indexed
|
||||
(fn [i n]
|
||||
^{:key i}
|
||||
[pin-indicator (number? n) status])
|
||||
(concat pin
|
||||
(repeat (- 6 (count pin))
|
||||
nil)))))])
|
||||
(fn [i n]
|
||||
(let [pressed? (number? n)]
|
||||
^{:key i} [react/view (styles/pin-indicator pressed? error?)]))
|
||||
(concat pin (repeat (- 6 (count pin)) nil)))])
|
||||
|
||||
(defn puk-indicators [puk status]
|
||||
[react/view {:margin-top 28}
|
||||
(defn puk-indicators [puk error?]
|
||||
[react/view {:margin-top 28
|
||||
:flex-direction :row
|
||||
:justify-content :space-between}
|
||||
(map-indexed
|
||||
(fn [i puk-group]
|
||||
^{:key i}
|
||||
[pin-indicators puk-group status {:margin-top 8}])
|
||||
(partition 6
|
||||
[react/view (merge styles/pin-indicator-container
|
||||
{:margin-top 8
|
||||
:margin 12})
|
||||
(map-indexed
|
||||
(fn [j n]
|
||||
(if (number? n)
|
||||
^{:key j} [react/text {:style {:font-size 20
|
||||
:width 18
|
||||
:color (if error?
|
||||
colors/red
|
||||
colors/black)}}
|
||||
n]
|
||||
^{:key j} [react/view (styles/puk-indicator error?)]))
|
||||
puk-group)])
|
||||
(partition 4
|
||||
(concat puk
|
||||
(repeat (- 12 (count puk))
|
||||
nil))))])
|
||||
|
@ -82,38 +90,142 @@
|
|||
:on-value-change #(re-frame/dispatch [:multiaccounts/save-password %])}]
|
||||
[react/text (i18n/label :t/hardwallet-dont-ask-card)]])))
|
||||
|
||||
(defn bezier-easing []
|
||||
(.bezier ^js animation/easing 0.77, 0.000, 0.175, 1))
|
||||
|
||||
(defn animate-info-in
|
||||
"animation that makes the error message appear for a few seconds, then
|
||||
replaces it with the number of attempts left"
|
||||
[error-y-translation error-opacity retries-y-translation retries-opacity]
|
||||
(animation/start
|
||||
(animation/anim-sequence
|
||||
[(animation/parallel
|
||||
[(animation/timing error-opacity
|
||||
{:toValue 1
|
||||
:easing (bezier-easing)
|
||||
:duration 400
|
||||
:useNativeDriver true})
|
||||
(animation/timing error-y-translation
|
||||
{:toValue 0
|
||||
:easing (bezier-easing)
|
||||
:duration 400
|
||||
:useNativeDriver true})])
|
||||
(animation/anim-delay 2200)
|
||||
(animation/parallel
|
||||
[(animation/timing error-opacity
|
||||
{:toValue 0
|
||||
:easing (bezier-easing)
|
||||
:duration 400
|
||||
:useNativeDriver true})
|
||||
(animation/timing error-y-translation
|
||||
{:toValue 8
|
||||
:easing (bezier-easing)
|
||||
:duration 400
|
||||
:useNativeDriver true})
|
||||
(animation/timing retries-opacity
|
||||
{:toValue 1
|
||||
:easing (bezier-easing)
|
||||
:duration 400
|
||||
:useNativeDriver true})
|
||||
(animation/timing retries-y-translation
|
||||
{:toValue 0
|
||||
:easing (bezier-easing)
|
||||
:duration 400
|
||||
:useNativeDriver true})])])))
|
||||
|
||||
(defn animate-info-out
|
||||
[retries-y-translation retries-opacity]
|
||||
(animation/start
|
||||
(animation/parallel
|
||||
[(animation/timing retries-opacity
|
||||
{:toValue 0
|
||||
:easing (bezier-easing)
|
||||
:duration 400
|
||||
:useNativeDriver true})
|
||||
(animation/timing retries-y-translation
|
||||
{:toValue -8
|
||||
:easing (bezier-easing)
|
||||
:duration 400
|
||||
:useNativeDriver true})])))
|
||||
|
||||
(defn pin-view
|
||||
[{:keys [pin title-label description-label step status error-label
|
||||
retry-counter small-screen? save-password-checkbox?]}]
|
||||
(let [enabled? (not= status :verifying)]
|
||||
[react/scroll-view
|
||||
[react/view styles/pin-container
|
||||
[react/view (styles/center-container title-label)
|
||||
(when title-label
|
||||
[react/text {:style styles/center-title-text}
|
||||
(i18n/label title-label)])
|
||||
(when description-label
|
||||
[react/text {:style styles/create-pin-text
|
||||
:number-of-lines 2}
|
||||
(i18n/label description-label)])
|
||||
[react/view {:flex 1}
|
||||
(case status
|
||||
:verifying [react/view styles/waiting-indicator-container
|
||||
[react/activity-indicator {:animating true
|
||||
:size :small}]]
|
||||
:error [react/view (styles/error-container small-screen?)
|
||||
[react/text {:style (styles/error-text small-screen?)}
|
||||
(i18n/label error-label)]]
|
||||
(when (and retry-counter (< retry-counter default-pin-retries-number))
|
||||
[react/view {:margin-top (if (= step :puk) 24 8)}
|
||||
[react/text {:style {:text-align :center}}
|
||||
(i18n/label :t/pin-retries-left {:number retry-counter})]]))]
|
||||
(when save-password-checkbox?
|
||||
[save-password])
|
||||
(if (= step :puk)
|
||||
[puk-indicators pin status]
|
||||
[pin-indicators pin status nil])
|
||||
[numpad step enabled? small-screen?]]]]))
|
||||
[{:keys [retry-counter]}]
|
||||
(let [error-y-translation (animation/create-value -8)
|
||||
error-opacity (animation/create-value 0)
|
||||
retries-y-translation (animation/create-value (if retry-counter 8 0))
|
||||
retries-opacity (animation/create-value (if retry-counter 0 1))
|
||||
!error? (reagent/atom false)]
|
||||
(reagent/create-class
|
||||
{:component-did-update
|
||||
(fn [this [_ previous-props]]
|
||||
(let [[_ props] (.-argv (.-props ^js this))
|
||||
previous-status (:status previous-props)
|
||||
new-status (:status props)]
|
||||
(case new-status
|
||||
:error (when (or (nil? previous-status)
|
||||
(= :verifying previous-status))
|
||||
(utils/vibrate)
|
||||
(reset! !error? true)
|
||||
(animate-info-in error-y-translation
|
||||
error-opacity
|
||||
retries-y-translation
|
||||
retries-opacity)
|
||||
(js/setTimeout (fn [] (reset! !error? false)) 3000))
|
||||
:verifying (do
|
||||
(animation/set-value error-y-translation -8)
|
||||
(animate-info-out retries-y-translation
|
||||
retries-opacity))
|
||||
nil)))
|
||||
:reagent-render
|
||||
(fn [{:keys [pin title-label description-label step error-label status
|
||||
retry-counter small-screen? save-password-checkbox?]}]
|
||||
(let [enabled? (and (not= status :verifying)
|
||||
(not @!error?))
|
||||
puk? (= step :puk)]
|
||||
[react/scroll-view
|
||||
[react/view styles/pin-container
|
||||
[react/view (styles/center-container title-label)
|
||||
(when title-label
|
||||
[react/text {:style styles/center-title-text}
|
||||
(i18n/label title-label)])
|
||||
(when description-label
|
||||
[react/text {:style styles/create-pin-text
|
||||
:number-of-lines 2}
|
||||
(i18n/label description-label)])
|
||||
(when save-password-checkbox?
|
||||
[save-password])
|
||||
[react/view {:style (styles/info-container small-screen?)}
|
||||
(when error-label
|
||||
[react/animated-view {:style (styles/error-container error-y-translation error-opacity)}
|
||||
[react/text {:style (styles/error-text small-screen?)}
|
||||
(i18n/label error-label)]])
|
||||
[react/animated-view {:style (styles/retry-container retries-y-translation retries-opacity)}
|
||||
(cond
|
||||
(and retry-counter (= retry-counter 1))
|
||||
[react/nested-text {:style {:text-align :center
|
||||
:color colors/gray}}
|
||||
(i18n/label (if puk?
|
||||
:t/pin-one-attempt-blocked-before
|
||||
:t/pin-one-attempt-frozen-before))
|
||||
[{:style {:color colors/black
|
||||
:font-weight "700"}}
|
||||
(i18n/label :t/pin-one-attempt)]
|
||||
(i18n/label (if puk?
|
||||
:t/pin-one-attempt-blocked-after
|
||||
:t/pin-one-attempt-frozen-after))]
|
||||
|
||||
(and retry-counter (< retry-counter (if puk?
|
||||
default-puk-retries-number
|
||||
default-pin-retries-number)))
|
||||
[react/text {:style {:text-align :center
|
||||
:color colors/gray}}
|
||||
(i18n/label :t/pin-retries-left {:number retry-counter})]
|
||||
:else
|
||||
nil)]]
|
||||
(if puk?
|
||||
[puk-indicators pin @!error?]
|
||||
[pin-indicators pin @!error?])
|
||||
[numpad step enabled? small-screen?]]]]))})))
|
||||
|
||||
(def pin-retries 3)
|
||||
(def puk-retries 5)
|
||||
|
@ -125,32 +237,37 @@
|
|||
pin-retry-counter [:hardwallet/pin-retry-counter]
|
||||
puk-retry-counter [:hardwallet/puk-retry-counter]
|
||||
error-label [:hardwallet/pin-error-label]]
|
||||
[react/view {:flex 1
|
||||
:background-color colors/white}
|
||||
[topbar/topbar {}]
|
||||
(if (zero? pin-retry-counter)
|
||||
[pin-view {:pin pin
|
||||
:retry-counter (when (< puk-retry-counter puk-retries) puk-retry-counter)
|
||||
:title-label :t/enter-puk-code
|
||||
:description-label :t/enter-puk-code-description
|
||||
:step step
|
||||
:status status
|
||||
:error-label error-label}]
|
||||
[pin-view {:pin pin
|
||||
:retry-counter (when (< pin-retry-counter pin-retries) pin-retry-counter)
|
||||
:title-label (case step
|
||||
:current :t/current-pin
|
||||
:login :t/current-pin
|
||||
:import-multiaccount :t/current-pin
|
||||
:original :t/create-a-pin
|
||||
:confirmation :t/repeat-pin
|
||||
:t/current-pin)
|
||||
:description-label (case step
|
||||
:current :t/current-pin-description
|
||||
:sign :t/current-pin-description
|
||||
:import-multiaccount :t/current-pin-description
|
||||
:login :t/login-pin-description
|
||||
:t/new-pin-description)
|
||||
:step step
|
||||
:status status
|
||||
:error-label error-label}])]))
|
||||
(let [;; TODO(rasom): retarded hack to prevent state mess on opening pin
|
||||
;; sheet on another tab and returning back to this screen. Should be
|
||||
;; properly rewritten so that different instances of pin-view do not
|
||||
;; mess with state unrelated to them.
|
||||
step (or step :current)]
|
||||
[react/view {:flex 1
|
||||
:background-color colors/white}
|
||||
[topbar/topbar {}]
|
||||
(if (zero? pin-retry-counter)
|
||||
[pin-view {:pin pin
|
||||
:retry-counter (when (< puk-retry-counter puk-retries) puk-retry-counter)
|
||||
:title-label :t/enter-puk-code
|
||||
:description-label :t/enter-puk-code-description
|
||||
:step step
|
||||
:status status
|
||||
:error-label error-label}]
|
||||
[pin-view {:pin pin
|
||||
:retry-counter (when (< pin-retry-counter pin-retries) pin-retry-counter)
|
||||
:title-label (case step
|
||||
:current :t/current-pin
|
||||
:login :t/current-pin
|
||||
:import-multiaccount :t/current-pin
|
||||
:original :t/create-a-pin
|
||||
:confirmation :t/repeat-pin
|
||||
:t/current-pin)
|
||||
:description-label (case step
|
||||
:current :t/current-pin-description
|
||||
:sign :t/current-pin-description
|
||||
:import-multiaccount :t/current-pin-description
|
||||
:login :t/login-pin-description
|
||||
:t/new-pin-description)
|
||||
:step step
|
||||
:status status
|
||||
:error-label error-label}])])))
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.common.common :as components.common]
|
||||
[status-im.ui.components.topbar :as topbar]
|
||||
[status-im.constants :as constants]))
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ui.screens.keycard.views :as keycard.views]
|
||||
[status-im.hardwallet.common :as hardwallet.common]))
|
||||
|
||||
(defn- action-row [{:keys [icon label on-press color-theme]}]
|
||||
[react/touchable-highlight
|
||||
|
@ -131,3 +133,10 @@
|
|||
:color-theme :red
|
||||
:label :t/reset-card
|
||||
:on-press #(re-frame/dispatch [:keycard-settings.ui/reset-card-pressed])}]])]]))
|
||||
|
||||
(defn reset-pin []
|
||||
[keycard.views/login-pin
|
||||
{:back-button-handler
|
||||
::hardwallet.common/navigate-to-keycard-settings
|
||||
:hide-login-actions? true
|
||||
:default-enter-step :reset}])
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
[status-im.ui.screens.keycard.styles :as styles]
|
||||
[status-im.utils.core :as utils.core]
|
||||
[status-im.utils.gfycat.core :as gfy]
|
||||
[status-im.utils.identicon :as identicon]
|
||||
[status-im.constants :as constants])
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ui.screens.keycard.views :as keycard.views]
|
||||
[status-im.utils.identicon :as identicon])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defn intro []
|
||||
|
@ -83,26 +84,34 @@
|
|||
{:handler #(re-frame/dispatch [::hardwallet.recovery/cancel-pressed])
|
||||
:style {:padding-left 21}}
|
||||
(i18n/label :t/cancel)]
|
||||
[react/text {:style {:color colors/gray}}
|
||||
(i18n/label :t/step-i-of-n {:number 2
|
||||
:step 2})]]
|
||||
[react/view {:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :space-between
|
||||
:align-items :center}
|
||||
[react/view {:flex-direction :column
|
||||
:align-items :center}
|
||||
[react/view {:margin-top 16}
|
||||
[react/text {:style {:typography :header
|
||||
:text-align :center}}
|
||||
(i18n/label :t/enter-your-code)]]]
|
||||
[pin.views/pin-view
|
||||
{:pin pin
|
||||
:retry-counter retry-counter
|
||||
:small-screen? small-screen?
|
||||
:status status
|
||||
:error-label error-label
|
||||
:step :import-multiaccount}]]]))
|
||||
(when-not (#{:frozen-card :blocked-card} status)
|
||||
[react/text {:style {:color colors/gray}}
|
||||
(i18n/label :t/step-i-of-n {:number 2
|
||||
:step 2})])]
|
||||
(case status
|
||||
:frozen-card
|
||||
[keycard.views/frozen-card]
|
||||
|
||||
:blocked-card
|
||||
[keycard.views/blocked-card]
|
||||
|
||||
[react/view {:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :space-between
|
||||
:align-items :center}
|
||||
[react/view {:flex-direction :column
|
||||
:align-items :center}
|
||||
[react/view {:margin-top 16}
|
||||
[react/text {:style {:typography :header
|
||||
:text-align :center}}
|
||||
(i18n/label :t/enter-your-code)]]]
|
||||
[pin.views/pin-view
|
||||
{:pin pin
|
||||
:retry-counter retry-counter
|
||||
:small-screen? small-screen?
|
||||
:status status
|
||||
:error-label error-label
|
||||
:step :import-multiaccount}]])]))
|
||||
|
||||
(defview pair []
|
||||
(letsubs [pair-code [:hardwallet-pair-code]
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.ui.screens.hardwallet.pin.views :as pin.views]
|
||||
[status-im.ui.screens.keycard.styles :as styles]
|
||||
[status-im.constants :as constants])
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ui.components.button :as button]
|
||||
[status-im.hardwallet.login :as hardwallet.login]
|
||||
[status-im.ui.screens.hardwallet.frozen-card.view :as frozen-card.view])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
;; NOTE(Ferossgp): Seems like it should be in popover
|
||||
|
@ -208,74 +211,199 @@
|
|||
[photos/photo (multiaccounts/displayed-photo account)
|
||||
{:size (if small-screen? 45 61)}])}))
|
||||
|
||||
(defview login-pin []
|
||||
(defn access-is-reset [{:keys [hide-login-actions?]}]
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:align-items :center}}
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:align-items :center
|
||||
:justify-content :center}}
|
||||
[react/view
|
||||
{:style
|
||||
{:background-color colors/green-transparent-10
|
||||
:margin-bottom 32
|
||||
:width 40
|
||||
:height 40
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:border-radius 20}}
|
||||
[vector-icons/icon
|
||||
:main-icons/check
|
||||
{:color colors/green}]]
|
||||
[react/text {:style {:typography :header}}
|
||||
(i18n/label :t/keycard-access-reset)]
|
||||
[react/text (i18n/label :t/keycard-can-use-with-new-passcode)]]
|
||||
(when-not hide-login-actions?
|
||||
[react/view
|
||||
{:style {:width 160
|
||||
:margin-bottom 15}}
|
||||
[button/button
|
||||
{:type :main
|
||||
:style {:align-self :stretch}
|
||||
:container-style {:height 52}
|
||||
:label (i18n/label :t/open)
|
||||
:on-press #(re-frame/dispatch
|
||||
[::hardwallet.login/login-after-reset])}]])])
|
||||
|
||||
(defn frozen-card []
|
||||
[frozen-card.view/frozen-card
|
||||
{:show-dismiss-button? false}])
|
||||
|
||||
(defn blocked-card []
|
||||
[react/view {:style {:flex 1
|
||||
:align-items :center}}
|
||||
[react/view {:margin-top 24
|
||||
:margin-horizontal 24
|
||||
:align-items :center}
|
||||
[react/view {:background-color colors/red-transparent-10
|
||||
:width 32
|
||||
:height 32
|
||||
:border-radius 16
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
[vector-icons/icon
|
||||
:main-icons/cancel
|
||||
{:color colors/red
|
||||
:width 20
|
||||
:height 20}]]
|
||||
[react/text {:style {:typography :title-bold
|
||||
:margin-top 16
|
||||
:margin-bottom 8}}
|
||||
(i18n/label :t/keycard-is-blocked-title)]
|
||||
[react/text {:style {:color colors/gray
|
||||
:text-align :center}}
|
||||
(i18n/label :t/keycard-is-blocked-details)]
|
||||
[react/text "\n"]
|
||||
[react/nested-text
|
||||
{:style {:color colors/gray
|
||||
:text-align :center}}
|
||||
(i18n/label :t/keycard-is-blocked-instructions)
|
||||
[{} " "]
|
||||
[{:style {:color colors/blue}
|
||||
:on-press #(.openURL ^js react/linking "https://status.im/faq/#keycard")}
|
||||
(i18n/label :t/learn-more)]]]])
|
||||
|
||||
(defn- step-view [step]
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
[react/text {:style {:typography :title-bold :text-align :center}}
|
||||
(i18n/label :t/keycard-reset-passcode)]
|
||||
[react/text {:style {:color colors/gray}}
|
||||
(i18n/label :t/keycard-enter-new-passcode {:step step})]])
|
||||
|
||||
(defview login-pin [{:keys [back-button-handler
|
||||
hide-login-actions?
|
||||
default-enter-step]
|
||||
:or {default-enter-step :login}}]
|
||||
(letsubs [pin [:hardwallet/pin]
|
||||
enter-step [:hardwallet/pin-enter-step]
|
||||
status [:hardwallet/pin-status]
|
||||
error-label [:hardwallet/pin-error-label]
|
||||
{:keys [name] :as account} [:multiaccounts/login]
|
||||
login-multiaccount [:multiaccounts/login]
|
||||
multiaccount [:multiaccount]
|
||||
small-screen? [:dimensions/small-screen?]
|
||||
retry-counter [:hardwallet/retry-counter]]
|
||||
[react/view styles/container
|
||||
[topbar/topbar
|
||||
{:accessories [{:icon :main-icons/more
|
||||
:handler #(re-frame/dispatch [:keycard.login.pin.ui/more-icon-pressed])}]
|
||||
:navigation
|
||||
{:icon :main-icons/back
|
||||
:accessibility-label :back-button
|
||||
:handler #(re-frame/dispatch [:keycard.login.pin.ui/cancel-pressed])}}]
|
||||
[react/view {:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :space-between
|
||||
:align-items :center}
|
||||
[react/view {:flex-direction :column
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:height 140}
|
||||
[react/view {:margin-horizontal 16
|
||||
:flex-direction :column}
|
||||
[react/view {:justify-content :center
|
||||
(let [{:keys [name] :as account} (or login-multiaccount multiaccount)
|
||||
;; TODO(rasom): this hack fixes state mess when more then two
|
||||
;; pin-view instances are used at the same time. Should be properly
|
||||
;; refactored instead
|
||||
enter-step (or enter-step default-enter-step)]
|
||||
[react/view styles/container
|
||||
[topbar/topbar
|
||||
{:accessories [(when-not hide-login-actions?
|
||||
{:icon :main-icons/more
|
||||
:handler #(re-frame/dispatch [:keycard.login.pin.ui/more-icon-pressed])})]
|
||||
:content (cond
|
||||
(= :reset enter-step)
|
||||
[step-view 1]
|
||||
|
||||
(= :reset-confirmation enter-step)
|
||||
[step-view 2]
|
||||
|
||||
(and (= :puk enter-step)
|
||||
(not= :blocked-card status))
|
||||
[react/view
|
||||
{:style {:flex 1
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
[react/text {:style {:color colors/gray}}
|
||||
(i18n/label :t/enter-puk-code)]])
|
||||
:navigation
|
||||
{:icon :main-icons/back
|
||||
:accessibility-label :back-button
|
||||
:handler #(re-frame/dispatch
|
||||
[(or back-button-handler
|
||||
:keycard.login.pin.ui/cancel-pressed)])}}]
|
||||
[react/view {:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :space-between
|
||||
:align-items :center}
|
||||
[react/view {:flex-direction :column
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:flex-direction :row}
|
||||
[react/view {:width (if small-screen? 50 69)
|
||||
:height (if small-screen? 50 69)
|
||||
:justify-content :center
|
||||
:align-items :center}
|
||||
[photo account small-screen?]
|
||||
[react/view {:justify-content :center
|
||||
:align-items :center
|
||||
:width (if small-screen? 18 24)
|
||||
:height (if small-screen? 18 24)
|
||||
:border-radius (if small-screen? 18 24)
|
||||
:position :absolute
|
||||
:right 0
|
||||
:bottom 0
|
||||
:background-color colors/white
|
||||
:border-width 1
|
||||
:border-color colors/black-transparent}
|
||||
[react/image {:source (resources/get-image :keycard-key)
|
||||
:style {:width (if small-screen? 6 8)
|
||||
:height (if small-screen? 11 14)}}]]]]
|
||||
[react/text {:style {:text-align :center
|
||||
:margin-top (if small-screen? 8 12)
|
||||
:color colors/black
|
||||
:font-weight "500"}
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :middle}
|
||||
name]]]
|
||||
[pin.views/pin-view
|
||||
{:pin pin
|
||||
:retry-counter retry-counter
|
||||
:small-screen? small-screen?
|
||||
:status status
|
||||
:error-label error-label
|
||||
:step enter-step
|
||||
:save-password-checkbox? true}]
|
||||
[react/view {:margin-bottom (if small-screen? 25 32)}
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:multiaccounts.recover.ui/recover-multiaccount-button-pressed])}
|
||||
[react/text {:style {:color colors/blue}}
|
||||
(i18n/label :t/recover-key)]]]]]))
|
||||
:height 140}
|
||||
[react/view {:margin-horizontal 16
|
||||
:flex-direction :column}
|
||||
[react/view {:justify-content :center
|
||||
:align-items :center
|
||||
:flex-direction :row}
|
||||
[react/view {:width (if small-screen? 50 69)
|
||||
:height (if small-screen? 50 69)
|
||||
:justify-content :center
|
||||
:align-items :center}
|
||||
[photo account small-screen?]
|
||||
[react/view {:justify-content :center
|
||||
:align-items :center
|
||||
:width (if small-screen? 18 24)
|
||||
:height (if small-screen? 18 24)
|
||||
:border-radius (if small-screen? 18 24)
|
||||
:position :absolute
|
||||
:right 0
|
||||
:bottom 0
|
||||
:background-color colors/white
|
||||
:border-width 1
|
||||
:border-color colors/black-transparent}
|
||||
[react/image {:source (resources/get-image :keycard-key)
|
||||
:style {:width (if small-screen? 6 8)
|
||||
:height (if small-screen? 11 14)}}]]]]
|
||||
[react/text {:style {:text-align :center
|
||||
:margin-top (if small-screen? 8 12)
|
||||
:color colors/black
|
||||
:font-weight "500"}
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :middle}
|
||||
name]]]
|
||||
(cond
|
||||
(= :after-unblocking status)
|
||||
[access-is-reset
|
||||
{:hide-login-actions? hide-login-actions?}]
|
||||
|
||||
(= :frozen-card status)
|
||||
[frozen-card]
|
||||
|
||||
(= :blocked-card status)
|
||||
[blocked-card]
|
||||
|
||||
:else
|
||||
[pin.views/pin-view
|
||||
{:pin pin
|
||||
:retry-counter retry-counter
|
||||
:small-screen? small-screen?
|
||||
:status status
|
||||
:error-label error-label
|
||||
:step enter-step
|
||||
:save-password-checkbox? (not (contains?
|
||||
#{:reset :reset-confirmation :puk}
|
||||
enter-step))}])
|
||||
(when-not hide-login-actions?
|
||||
[react/view {:margin-bottom (if small-screen? 25 32)}
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:multiaccounts.recover.ui/recover-multiaccount-button-pressed])}
|
||||
[react/text {:style {:color colors/blue}}
|
||||
(i18n/label :t/recover-key)]]])]])))
|
||||
|
||||
(defn- more-sheet-content []
|
||||
[react/view {:flex 1}
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
[status-im.ui.screens.multiaccounts.recover.views :as multiaccounts.recover]
|
||||
[status-im.ui.screens.signing.views :as signing]
|
||||
[status-im.ui.screens.biometric.views :as biometric]
|
||||
[status-im.ui.components.colors :as colors]))
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.screens.hardwallet.frozen-card.view :as frozen-card]))
|
||||
|
||||
(defn hide-panel-anim
|
||||
[bottom-anim-value alpha-value window-height]
|
||||
|
@ -137,6 +138,9 @@
|
|||
(= :transaction-data view)
|
||||
[signing/transaction-data]
|
||||
|
||||
(= :frozen-card view)
|
||||
[frozen-card/frozen-card]
|
||||
|
||||
:else
|
||||
[view])]]]]])))})))
|
||||
|
||||
|
|
|
@ -126,5 +126,7 @@
|
|||
:component hardwallet.settings/keycard-settings}
|
||||
{:name :reset-card
|
||||
:component hardwallet.settings/reset-card}
|
||||
{:name :keycard-pin
|
||||
:component hardwallet.settings/reset-pin}
|
||||
{:name :enter-pin-settings
|
||||
:component hardwallet.pin/enter-pin}]])
|
||||
|
|
|
@ -96,14 +96,15 @@
|
|||
enter-step [:hardwallet/pin-enter-step]
|
||||
status [:hardwallet/pin-status]
|
||||
retry-counter [:hardwallet/retry-counter]]
|
||||
[react/view
|
||||
[pin.views/pin-view
|
||||
{:pin pin
|
||||
:retry-counter retry-counter
|
||||
:step enter-step
|
||||
:small-screen? small-screen?
|
||||
:status status
|
||||
:error-label error-label}]]))
|
||||
(let [enter-step (or enter-step :sign)]
|
||||
[react/view
|
||||
[pin.views/pin-view
|
||||
{:pin pin
|
||||
:retry-counter retry-counter
|
||||
:step enter-step
|
||||
:small-screen? small-screen?
|
||||
:status status
|
||||
:error-label error-label}]])))
|
||||
|
||||
(defn sign-with-keycard-button
|
||||
[amount-error gas-error]
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
[status-im.ui.screens.wallet.accounts.sheets :as sheets]
|
||||
[status-im.ui.screens.wallet.accounts.styles :as styles]
|
||||
[status-im.utils.utils :as utils.utils]
|
||||
[status-im.wallet.utils :as wallet.utils])
|
||||
[status-im.wallet.utils :as wallet.utils]
|
||||
[status-im.hardwallet.login :as hardwallet.login])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(views/defview account-card [{:keys [name color address type] :as account}]
|
||||
|
@ -130,14 +131,21 @@
|
|||
(views/letsubs [currency [:wallet/currency]
|
||||
portfolio-value [:portfolio-value]
|
||||
empty-balances? [:empty-balances?]
|
||||
frozen-card? [:hardwallet/frozen-card?]
|
||||
{:keys [mnemonic]} [:multiaccount]]
|
||||
[reanimated/view {:style (styles/container {:minimized minimized})}
|
||||
(when (and mnemonic minimized (not empty-balances?))
|
||||
(when (or
|
||||
(and frozen-card? minimized)
|
||||
(and mnemonic minimized (not empty-balances?)))
|
||||
[reanimated/view {:style (styles/accounts-mnemonic {:animation animation})}
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:navigate-to :profile-stack {:screen :backup-seed
|
||||
:initial false}])}
|
||||
[react/view {:flex-direction :row :align-items :center}
|
||||
{:on-press #(re-frame/dispatch
|
||||
(if frozen-card?
|
||||
[::hardwallet.login/reset-pin]
|
||||
[:navigate-to :profile-stack {:screen :backup-seed
|
||||
:initial false}]))}
|
||||
[react/view {:flex-direction :row
|
||||
:align-items :center}
|
||||
[react/view {:width 14
|
||||
:height 14
|
||||
:background-color colors/gray
|
||||
|
@ -151,7 +159,9 @@
|
|||
"!"]]
|
||||
[react/text {:style {:color colors/gray}
|
||||
:accessibility-label :back-up-your-seed-phrase-warning}
|
||||
(i18n/label :t/back-up-your-seed-phrase)]]]])
|
||||
(if frozen-card?
|
||||
(i18n/label :t/your-card-is-frozen)
|
||||
(i18n/label :t/back-up-your-seed-phrase))]]]])
|
||||
|
||||
[reanimated/view {:style (styles/value-container {:minimized minimized
|
||||
:animation animation})
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.utils.security :as security]
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.platform :as platform]))
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.components.bottom-panel.views :as bottom-panel]))
|
||||
|
||||
(defn- request-camera-permissions []
|
||||
(let [options {:handler :wallet.add-new/qr-scanner-result}]
|
||||
|
@ -127,23 +128,40 @@
|
|||
(re-frame/dispatch [:set-in [:add-account :private-key] (security/mask-data %)]))}])])
|
||||
|
||||
(defview pin []
|
||||
(letsubs [pin [:hardwallet/pin]
|
||||
status [:hardwallet/pin-status]
|
||||
error-label [:hardwallet/pin-error-label]]
|
||||
(letsubs [pin [:hardwallet/pin]
|
||||
status [:hardwallet/pin-status]
|
||||
error-label [:hardwallet/pin-error-label]
|
||||
retry-counter [:hardwallet/retry-counter]]
|
||||
[react/keyboard-avoiding-view {:style {:flex 1}}
|
||||
[topbar/topbar
|
||||
{:navigation :none
|
||||
:accessories
|
||||
[{:label :t/cancel
|
||||
:handler #(re-frame/dispatch [:bottom-sheet/hide])}]}]
|
||||
:handler #(re-frame/dispatch [:hardwallet/new-account-pin-sheet-hide])}]}]
|
||||
[pin.views/pin-view
|
||||
{:pin pin
|
||||
:status status
|
||||
:retry-counter retry-counter
|
||||
:title-label :t/current-pin
|
||||
:description-label :t/current-pin-description
|
||||
:error-label error-label
|
||||
:step :export-key}]]))
|
||||
|
||||
(defn pin-sheet []
|
||||
(let [show-sheet? @(re-frame/subscribe [:hardwallet/new-account-sheet?])
|
||||
{window-height :height} @(re-frame/subscribe [:dimensions/window])]
|
||||
[bottom-panel/bottom-panel
|
||||
show-sheet?
|
||||
(fn [_]
|
||||
[react/view {:style
|
||||
{:background-color colors/white
|
||||
:border-top-right-radius 16
|
||||
:border-top-left-radius 16
|
||||
:padding-bottom 40
|
||||
:flex 1}}
|
||||
[pin]])
|
||||
window-height]))
|
||||
|
||||
(defview add-account []
|
||||
(letsubs [{:keys [type account] :as add-account} [:add-account]
|
||||
add-account-disabled? [:add-account-disabled?]
|
||||
|
@ -164,7 +182,8 @@
|
|||
:label :t/add-account
|
||||
:accessibility-label :add-account-add-account-button
|
||||
:on-press
|
||||
(if keycard?
|
||||
(if (and keycard?
|
||||
(not= type :watch))
|
||||
#(re-frame/dispatch [:hardwallet/new-account-pin-sheet
|
||||
{:view {:content pin
|
||||
:height 256}}])
|
||||
|
@ -177,5 +196,6 @@
|
|||
(and
|
||||
(not keycard?)
|
||||
(not (spec/valid? ::multiaccounts.db/password
|
||||
@entered-password)))))}}]]))
|
||||
@entered-password)))))}}]
|
||||
[pin-sheet]]))
|
||||
|
||||
|
|
|
@ -543,11 +543,15 @@
|
|||
"joined-group-chat-description": "You've joined {{group-name}} from invitation by {{username}}",
|
||||
"key": "Key",
|
||||
"keycard": "Keycard",
|
||||
"keycard-access-reset": "Keycard access is reset",
|
||||
"keycard-can-use-with-new-passcode": "You can use this card with your new passcode",
|
||||
"keycard-applet-install-instructions": "To install the applet please follow the instructions on https://github.com/status-im/keycard-cli#keycard-applet-installation",
|
||||
"keycard-blocked": "Keycard has been blocked.\nYou need to reset card to continue using it.",
|
||||
"keycard-cancel-setup-text": "This will cancel keycard setup. It's highly recommended to finish the setup in order to use keycard. Do you really want to cancel?",
|
||||
"keycard-cancel-setup-title": "Dangerous operation",
|
||||
"keycard-desc": "Own a Keycard? Store your keys on it; you’ll need it for transactions",
|
||||
"keycard-reset-passcode": "Reset passcode",
|
||||
"keycard-enter-new-passcode": "Enter new passcode {{step}}/2",
|
||||
"keycard-has-multiaccount-on-it": "This card is full. Each card can hold one main keypair",
|
||||
"keycard-onboarding-finishing-header": "Finishing up",
|
||||
"keycard-onboarding-intro-header": "Store your keys on Keycard",
|
||||
|
@ -576,6 +580,13 @@
|
|||
"keycard-recovery-phrase-confirmation-title": "Written the seed phrase down?",
|
||||
"keycard-recovery-success-header": "Your keys have been\n successfully recovered",
|
||||
"keycard-unauthorized-operation": "You're unauthorized to perform this operation.\n Please tap valid card and try again.",
|
||||
"keycard-is-frozen-title": "Keycard is frozen",
|
||||
"keycard-is-frozen-details": "To protect your assets, your card is frozen. Reset card access to unlock keys and send transactions. Create a new passcode and enter your PUK to access your account(s) on this card",
|
||||
"keycard-is-frozen-reset": "Reset card access",
|
||||
"your-card-is-frozen": "Your Keycard is frozen. Reset card access",
|
||||
"keycard-is-blocked-title": "Keycard is blocked",
|
||||
"keycard-is-blocked-details": "You can no longer use this card to access or sign for this account. There have been too many failed passcode and PUK attempts.",
|
||||
"keycard-is-blocked-instructions": "To access your account reinstall Status and use a new Keycard, use a different wallet or reset Keycard manually.",
|
||||
"language": "Language",
|
||||
"learn-more": "Learn more",
|
||||
"learn-more-about-keycard": "Learn more about Keycard",
|
||||
|
@ -772,7 +783,12 @@
|
|||
"pin-changed": "6-digit passcode has been changed",
|
||||
"pin-code": "6-digit passcode",
|
||||
"pin-mismatch": "Wrong passcode",
|
||||
"pin-retries-left": "You have {{number}} retries left",
|
||||
"pin-retries-left": "{{number}} attemps left",
|
||||
"pin-one-attempt-blocked-before": "Be careful, you have only",
|
||||
"pin-one-attempt-frozen-before": "Be careful, you have only",
|
||||
"pin-one-attempt": " one attempt ",
|
||||
"pin-one-attempt-blocked-after": "before your Keycard gets blocked",
|
||||
"pin-one-attempt-frozen-after": "before your Keycard gets frozen",
|
||||
"preview-privacy": "Preview privacy mode",
|
||||
"privacy": "Privacy",
|
||||
"privacy-and-security": "Privacy and security",
|
||||
|
@ -789,7 +805,7 @@
|
|||
"puk-and-pairing-codes-displayed": "PUK and pairing codes displayed",
|
||||
"puk-code": "PUK code",
|
||||
"puk-code-explanation": "If you forget your 6-digit passcode or enter it incorrectly 3 times, you'll need this code to unlock your card.",
|
||||
"puk-mismatch": "PUK code does not match",
|
||||
"puk-mismatch": "Wrong PUK code",
|
||||
"quiet-days": "{{quiet-days}} days",
|
||||
"quiet-hours": "{{quiet-hours}} hours",
|
||||
"re-encrypt-key": "Re-encrypt your keys",
|
||||
|
|
Loading…
Reference in New Issue