[#7006] login with keycard

Signed-off-by: Dmitry Novotochinov <dmitry.novot@gmail.com>
This commit is contained in:
Dmitry Novotochinov 2018-12-04 16:49:09 +03:00
parent b96063ce56
commit 1b836bf7ec
No known key found for this signature in database
GPG Key ID: 43D1DAF5AD39C927
27 changed files with 534 additions and 152 deletions

View File

@ -1 +1 @@
0.19.0-beta.9 0.20.0-beta.0

View File

@ -54,7 +54,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.2", "react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.3.4",
"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

@ -6012,9 +6012,10 @@ 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.2": "react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.3.4":
version "2.3.2" version "2.3.4"
resolved "git+https://github.com/status-im/react-native-status-keycard#4c2aada5dc3b9d106935ab1747ab33ad4e94547e" resolved "git+https://github.com/status-im/react-native-status-keycard.git#04b0fb6fcbe588bd7fa076e1b0379e661bf1bddc"
react-native-svg@6.5.2: react-native-svg@6.5.2:
version "6.5.2" version "6.5.2"

View File

@ -413,6 +413,26 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
StatusThreadPoolExecutor.getInstance().execute(r); StatusThreadPoolExecutor.getInstance().execute(r);
} }
@ReactMethod
public void loginWithKeycard(final String whisperPrivateKey, final String encryptionPublicKey, final Callback callback) {
Log.d(TAG, "loginWithKeycard");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String result = Statusgo.LoginWithKeycard(whisperPrivateKey, encryptionPublicKey);
callback.invoke(result);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod @ReactMethod
public void createAccount(final String password, final Callback callback) { public void createAccount(final String password, final Callback callback) {
Log.d(TAG, "createAccount"); Log.d(TAG, "createAccount");

View File

@ -41,8 +41,13 @@
;;;; Handlers ;;;; Handlers
(fx/defn login [cofx] (fx/defn login [cofx]
(let [{:keys [address password]} (accounts.db/credentials cofx)] (if (get-in cofx [:db :hardwallet :whisper-private-key])
{:accounts.login/login [address password]})) {:hardwallet/login-with-keycard (-> cofx
(get-in [:db :hardwallet])
(select-keys [:whisper-private-key :encryption-public-key])
(assoc :on-result #(re-frame/dispatch [:accounts.login.callback/login-success %])))}
(let [{:keys [address password]} (accounts.db/credentials cofx)]
{:accounts.login/login [address password]})))
(fx/defn initialize-wallet [cofx] (fx/defn initialize-wallet [cofx]
(fx/merge cofx (fx/merge cofx
@ -88,7 +93,14 @@
(if success (if success
(fx/merge (fx/merge
cofx cofx
{:db (dissoc db :accounts/login) {:db (-> db
(dissoc :accounts/login)
(update :hardwallet dissoc
:on-card-read
:card-read-in-progress?
:pin
:whisper-private-key
:encryption-public-key))
:web3/set-default-account [web3 address] :web3/set-default-account [web3 address]
:web3/fetch-node-version [web3 :web3/fetch-node-version [web3
#(re-frame/dispatch #(re-frame/dispatch
@ -202,18 +214,35 @@
(unknown-realm-error {:realm-error realm-error (unknown-realm-error {:realm-error realm-error
:erase-button erase-button}))))) :erase-button erase-button})))))
(fx/defn open-login [{:keys [db]} address photo-path name] (fx/defn open-keycard-login
{:db (-> db [{:keys [db] :as cofx}]
(update :accounts/login assoc (let [navigation-stack (:navigation-stack db)]
:address address (fx/merge cofx
:photo-path photo-path {:db (assoc-in db [:hardwallet :pin :enter-step] :login)}
:name name) (if (empty? navigation-stack)
(update :accounts/login dissoc (navigation/navigate-to-cofx :accounts nil)
:error (navigation/navigate-to-cofx :enter-pin nil)))))
:password))
:keychain/can-save-user-password? nil (fx/defn get-user-password
:keychain/get-user-password [address [_ address]
#(re-frame/dispatch [:accounts.login.callback/get-user-password-success %])]}) {:keychain/can-save-user-password? nil
:keychain/get-user-password [address
#(re-frame/dispatch [:accounts.login.callback/get-user-password-success %])]})
(fx/defn open-login [{:keys [db] :as cofx} address photo-path name]
(let [keycard-account? (get-in db [:accounts/accounts address :keycard-instance-uid])]
(fx/merge cofx
{:db (-> db
(update :accounts/login assoc
:address address
:photo-path photo-path
:name name)
(update :accounts/login dissoc
:error
:password))}
(if keycard-account?
(open-keycard-login)
(get-user-password address)))))
(fx/defn open-login-callback (fx/defn open-login-callback
[{:keys [db] :as cofx} password] [{:keys [db] :as cofx} password]

View File

@ -891,8 +891,8 @@
(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]] (fn [cofx [_ info on-success]]
(hardwallet/on-get-application-info-success cofx info))) (hardwallet/on-get-application-info-success cofx info on-success)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.callback/on-get-application-info-error :hardwallet.callback/on-get-application-info-error
@ -1012,6 +1012,26 @@
(fn [cofx [_ error]] (fn [cofx [_ error]]
(hardwallet/on-delete-error cofx error))) (hardwallet/on-delete-error cofx error)))
(handlers/register-handler-fx
:hardwallet.callback/on-get-keys-success
(fn [cofx [_ data]]
(hardwallet/on-get-keys-success cofx data)))
(handlers/register-handler-fx
:hardwallet/auto-login
(fn [cofx _]
(hardwallet/login-with-keycard cofx true)))
(handlers/register-handler-fx
:hardwallet/login-with-keycard
(fn [cofx _]
(hardwallet/login-with-keycard cofx false)))
(handlers/register-handler-fx
:hardwallet.callback/on-get-keys-error
(fn [cofx [_ error]]
(hardwallet/on-get-keys-error cofx error)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/status-hardwallet-option-pressed :hardwallet.ui/status-hardwallet-option-pressed
(fn [cofx _] (fn [cofx _]

View File

@ -50,10 +50,10 @@
"keyCardOnDisconnected" "keyCardOnDisconnected"
#(re-frame/dispatch [:hardwallet.callback/on-card-disconnected %]))}]))) #(re-frame/dispatch [:hardwallet.callback/on-card-disconnected %]))}])))
(defn get-application-info [pairing] (defn get-application-info [{:keys [pairing on-success]}]
(.. keycard (.. keycard
(getApplicationInfo (str pairing)) (getApplicationInfo (str pairing))
(then #(re-frame/dispatch [:hardwallet.callback/on-get-application-info-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-and-init-card []
@ -133,3 +133,10 @@
(unpairAndDelete pairing pin) (unpairAndDelete pairing pin)
(then #(re-frame/dispatch [:hardwallet.callback/on-delete-success %])) (then #(re-frame/dispatch [:hardwallet.callback/on-delete-success %]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-delete-error (error-object->map %)]))))) (catch #(re-frame/dispatch [:hardwallet.callback/on-delete-error (error-object->map %)])))))
(defn get-keys
[{:keys [pairing pin]}]
(.. keycard
(getKeys pairing pin)
(then #(re-frame/dispatch [:hardwallet.callback/on-get-keys-success %]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-get-keys-error (error-object->map %)]))))

View File

@ -11,7 +11,8 @@
[status-im.node.core :as node] [status-im.node.core :as node]
[status-im.utils.datetime :as utils.datetime] [status-im.utils.datetime :as utils.datetime]
[status-im.data-store.accounts :as accounts-store] [status-im.data-store.accounts :as accounts-store]
[clojure.string :as string])) [clojure.string :as string]
[status-im.accounts.login.core :as accounts.login]))
(def default-pin "000000") (def default-pin "000000")
@ -81,31 +82,63 @@
[{:keys [db]}] [{:keys [db]}]
{:db (assoc-in db [:hardwallet :reset-card :disabled?] false)}) {:db (assoc-in db [:hardwallet :reset-card :disabled?] false)})
(defn enter-pin-screen-did-load
[{:keys [db]}]
{:db (-> db
(assoc-in [:hardwallet :pin :login] [])
(assoc-in [:hardwallet :pin :current] []))})
(defn hardwallet-connect-screen-did-load
[{:keys [db]}]
{:db (assoc-in db [:hardwallet :card-read-in-progress?] false)})
(defn accounts-screen-did-load
[{:keys [db]}]
{:db (assoc-in db [:hardwallet :setup-step] nil)})
(fx/defn on-register-card-events (fx/defn on-register-card-events
[{:keys [db]} listeners] [{:keys [db]} listeners]
{:db (update-in db [:hardwallet :listeners] merge listeners)}) {:db (update-in db [:hardwallet :listeners] merge listeners)})
(fx/defn clear-on-card-read
[{:keys [db]}]
{:db (assoc-in db [:hardwallet :on-card-read] nil)})
(fx/defn on-get-application-info-success (fx/defn on-get-application-info-success
[{:keys [db] :as cofx} info] [{:keys [db]} 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'
enter-step (get-in db [:hardwallet :pin :enter-step]) connect-screen? (= (:view-id db) :hardwallet-connect)
enter-step' (if (zero? pin-retry-counter) :puk enter-step)] enter-step (if (zero? pin-retry-counter)
(fx/merge cofx :puk
(get-in db [:hardwallet :pin :enter-step]))]
(fx/merge {}
{: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')
(assoc-in [:hardwallet :application-info :applet-installed?] true) (assoc-in [:hardwallet :application-info :applet-installed?] true)
(assoc-in [:hardwallet :application-info-error] nil))} (assoc-in [:hardwallet :application-info-error] nil))}
(when (zero? puk-retry-counter) (when-not connect-screen?
(navigation/navigate-to-cofx :keycard-settings nil))))) (clear-on-card-read))
(if (zero? puk-retry-counter)
(navigation/navigate-to-cofx :keycard-settings nil)
(when on-success
#(assoc % :dispatch [on-success]))))))
(fx/defn on-get-application-info-error (fx/defn on-get-application-info-error
[{:keys [db]} error] [{:keys [db] :as cofx} error]
(log/debug "[hardwallet] application info error " error) (log/debug "[hardwallet] application info error " error)
{:db (-> db (let [on-card-read (get-in db [:hardwallet :on-card-read])
(assoc-in [:hardwallet :application-info-error] error) login? (= on-card-read :hardwallet/login-with-keycard)]
(assoc-in [:hardwallet :application-info :applet-installed?] false))}) (if login?
(fx/merge cofx
{:db (assoc-in db [:hardwallet :on-card-read] nil)
:utils/show-popup {:title (i18n/label :t/wrong-card)
:content (i18n/label :t/wrong-card-text)}}
(navigation/navigate-to-cofx :accounts nil))
{:db (-> db
(assoc-in [:hardwallet :application-info-error] error)
(assoc-in [:hardwallet :application-info :applet-installed?] false))})))
(fx/defn set-nfc-support (fx/defn set-nfc-support
[{:keys [db]} supported?] [{:keys [db]} supported?]
@ -122,12 +155,12 @@
: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 :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)))
(fx/defn success-button-pressed [cofx] (fx/defn success-button-pressed [cofx]
;; login not implemented yet (navigation/navigate-to-cofx cofx :home nil))
)
(fx/defn change-pin-pressed (fx/defn change-pin-pressed
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
@ -323,7 +356,7 @@
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [pairing (get-pairing db)] (let [pairing (get-pairing db)]
(fx/merge cofx (fx/merge cofx
{:hardwallet/get-application-info pairing {:hardwallet/get-application-info {:pairing pairing}
:db (-> db :db (-> db
(update-in [:hardwallet :pin] merge {:status nil (update-in [:hardwallet :pin] merge {:status nil
:enter-step :original :enter-step :original
@ -336,13 +369,13 @@
[{:keys [db]} error] [{:keys [db]} error]
(let [pairing (get-pairing db)] (let [pairing (get-pairing db)]
(log/debug "[hardwallet] unblock pin error" error) (log/debug "[hardwallet] unblock pin error" error)
{:hardwallet/get-application-info pairing {:hardwallet/get-application-info {:pairing pairing}
:db (update-in db [:hardwallet :pin] merge {:status :error :db (update-in db [:hardwallet :pin] merge {:status :error
:error-label :t/puk-mismatch :error-label :t/puk-mismatch
:enter-step :puk :enter-step :puk
:puk []})})) :puk []})}))
(fx/defn get-application-info [cofx pairing] (fx/defn get-application-info [cofx pairing]
{:hardwallet/get-application-info pairing}) {:hardwallet/get-application-info {:pairing pairing}})
(fx/defn on-verify-pin-success (fx/defn on-verify-pin-success
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
@ -361,7 +394,7 @@
[{:keys [db]} error] [{:keys [db]} error]
(let [pairing (get-pairing db)] (let [pairing (get-pairing db)]
(log/debug "[hardwallet] verify pin error" error) (log/debug "[hardwallet] verify pin error" error)
{:hardwallet/get-application-info pairing {:hardwallet/get-application-info {:pairing pairing}
:db (update-in db [:hardwallet :pin] merge {:status :error :db (update-in db [:hardwallet :pin] merge {:status :error
:error-label :t/pin-mismatch :error-label :t/pin-mismatch
:enter-step :current :enter-step :current
@ -449,11 +482,15 @@
(fx/defn update-pin (fx/defn update-pin
[{:keys [db] :as cofx} number enter-step] [{:keys [db] :as cofx} number enter-step]
(fx/merge cofx (let [numbers-entered (count (get-in db [:hardwallet :pin enter-step]))
{:db (-> db need-update? (if (= enter-step :puk)
(update-in [:hardwallet :pin enter-step] (fnil conj []) number) (< numbers-entered puk-code-length)
(assoc-in [:hardwallet :pin :status] nil))} (< numbers-entered pin-code-length))]
(handle-pin-input enter-step))) (fx/merge cofx
{:db (cond-> (assoc-in db [:hardwallet :pin :status] nil)
need-update? (update-in [:hardwallet :pin enter-step] (fnil conj []) number))}
(when need-update?
(handle-pin-input enter-step)))))
(defn- pin-enter-error [fx error-label] (defn- pin-enter-error [fx error-label]
(update-in fx [:db :hardwallet :pin] merge {:status :error (update-in fx [:db :hardwallet :pin] merge {:status :error
@ -462,7 +499,26 @@
:original [] :original []
:confirmation []})) :confirmation []}))
(fx/defn get-keys-from-keycard
[{:keys [db]}]
(let [{:keys [pairing]} (get-in db [:hardwallet :secrets])
pin (string/join (get-in db [:hardwallet :pin :login]))]
(when (and pairing
(not (empty? pin)))
{:db (-> db
(assoc-in [:hardwallet :pin :status] :verifying))
:hardwallet/get-keys {:pairing pairing
:pin pin}})))
(fx/defn wait-for-card-tap
[{:keys [db] :as cofx}]
(fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :on-card-read] :hardwallet/login-with-keycard))}
(navigation/navigate-to-cofx :hardwallet-connect nil)))
; PIN enter steps: ; PIN enter steps:
; login - PIN is used to login
; current - current PIN to perform actions which require PIN auth ; current - current PIN to perform actions which require PIN auth
; original - new PIN when user changes it or creates new one ; original - new PIN when user changes it or creates new one
; confirmation - confirmation for new PIN ; confirmation - confirmation for new PIN
@ -473,6 +529,10 @@
numbers-entered (count pin)] numbers-entered (count pin)]
(cond-> {:db (assoc-in db [:hardwallet :pin :status] nil)} (cond-> {:db (assoc-in db [:hardwallet :pin :status] nil)}
(and (= enter-step :login)
(= 6 numbers-entered))
(wait-for-card-tap)
(and (= enter-step :original) (and (= enter-step :original)
(= pin-code-length numbers-entered)) (= pin-code-length numbers-entered))
(proceed-to-pin-confirmation) (proceed-to-pin-confirmation)
@ -517,24 +577,71 @@
{:hardwallet/generate-mnemonic {:pairing pairing}})) {:hardwallet/generate-mnemonic {:pairing pairing}}))
(fx/defn dispatch-on-card-connected-event (fx/defn dispatch-on-card-connected-event
[{:keys [db]} event] [_ event]
{;:db (assoc-in db [:hardwallet :on-card-connected] nil) {:dispatch [event]})
:dispatch [event]})
(defn login-with-keycard
[{:keys [db] :as cofx} auto-login?]
(let [pairing (get-pairing db)
account-login-address (get-in db [:accounts/login :address])
account-was-manually-selected? account-login-address
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])
account-mismatch? (if account-was-manually-selected?
(not= account-instance-uid keycard-instance-uid)
(->> (:accounts/accounts db)
vals
(filter #(= keycard-instance-uid (:keycard-instance-uid %)))
empty?))]
(cond
(empty? keycard-instance-uid)
(fx/merge cofx
{:utils/show-popup {:title (i18n/label :t/no-account-on-card)
:content (i18n/label :t/no-account-on-card-text)}}
(navigation/navigate-to-cofx :accounts nil))
account-mismatch?
(fx/merge cofx
{:db (dissoc db :accounts/login)
:utils/show-popup {:title (i18n/label (if auto-login? :t/account-not-listed :t/wrong-card))
:content (i18n/label (if auto-login? :t/account-not-listed-text :t/wrong-card-text))}}
(navigation/navigate-to-cofx :accounts nil))
(empty? pairing)
{:utils/show-popup {:title (i18n/label :t/error)
:content (i18n/label :t/no-pairing-on-device)}}
auto-login?
(navigation/navigate-to-cofx cofx :enter-pin nil)
:else
(get-keys-from-keycard cofx))))
(fx/defn on-card-connected (fx/defn on-card-connected
[{: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-running? (get-in db [:hardwallet :setup-step])
pin-enter-step (get-in db [:hardwallet :pin :enter-step])
login? (= :login pin-enter-step)
accounts-screen? (= :accounts (:view-id db))
auto-login? accounts-screen?
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?
:hardwallet/auto-login
(get-in db [:hardwallet :on-card-read]))
pairing (get-pairing db)] pairing (get-pairing db)]
(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 :return-to-step] nil)) true (assoc-in [:hardwallet :return-to-step] nil))
:hardwallet/get-application-info pairing} :hardwallet/get-application-info {:pairing pairing
(when on-card-connected :on-success on-card-read}}
(when (and on-card-connected
(not login?))
(dispatch-on-card-connected-event on-card-connected)) (dispatch-on-card-connected-event on-card-connected))
(when setup-running? (when setup-running?
(navigation/navigate-to-cofx :hardwallet-setup nil))))) (navigation/navigate-to-cofx :hardwallet-setup nil)))))
@ -545,7 +652,9 @@
(let [setup-running? (get-in db [:hardwallet :setup-step]) (let [setup-running? (get-in db [:hardwallet :setup-step])
on-card-connected (get-in db [:hardwallet :on-card-connected])] on-card-connected (get-in db [:hardwallet :on-card-connected])]
(fx/merge cofx (fx/merge cofx
{:db (assoc-in db [:hardwallet :card-connected?] false)} {:db (-> db
(assoc-in [:hardwallet :card-connected?] false)
(assoc-in [:hardwallet :card-read-in-progress?] false))}
(when (or setup-running? (when (or setup-running?
on-card-connected) on-card-connected)
(navigation/navigate-to-cofx :hardwallet-connect nil))))) (navigation/navigate-to-cofx :hardwallet-connect nil)))))
@ -683,7 +792,7 @@
:keycard-paired-on paired-on} :keycard-paired-on paired-on}
encryption-public-key encryption-public-key
{:seed-backed-up? true {:seed-backed-up? true
:login? false}) :login? true})
(navigation/navigate-to-cofx :hardwallet-success nil)))) (navigation/navigate-to-cofx :hardwallet-success nil))))
(fx/defn on-generate-and-load-key-success (fx/defn on-generate-and-load-key-success
@ -692,9 +801,9 @@
whisper-private-key whisper-private-key
whisper-address whisper-address
wallet-address wallet-address
instance-uid
encryption-public-key]} (js->clj data :keywordize-keys true) encryption-public-key]} (js->clj data :keywordize-keys true)
whisper-public-key' (str "0x" whisper-public-key) whisper-public-key' (str "0x" whisper-public-key)]
keycard-instance-uid (get-in db [:hardwallet :application-info :instance-uid])]
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db
(assoc-in [:hardwallet :whisper-public-key] whisper-public-key') (assoc-in [:hardwallet :whisper-public-key] whisper-public-key')
@ -702,7 +811,9 @@
(assoc-in [:hardwallet :whisper-address] whisper-address) (assoc-in [:hardwallet :whisper-address] whisper-address)
(assoc-in [:hardwallet :wallet-address] wallet-address) (assoc-in [:hardwallet :wallet-address] wallet-address)
(assoc-in [:hardwallet :encryption-public-key] encryption-public-key) (assoc-in [:hardwallet :encryption-public-key] encryption-public-key)
(assoc-in [:hardwallet :keycard-instance-uid] keycard-instance-uid) (assoc-in [:hardwallet :keycard-instance-uid] instance-uid)
(update :hardwallet dissoc :recovery-phrase)
(update-in [:hardwallet :secrets] dissoc :pin :puk :password)
(assoc :node/on-ready :create-keycard-account) (assoc :node/on-ready :create-keycard-account)
(assoc :accounts/new-installation-id (random-guid-generator)) (assoc :accounts/new-installation-id (random-guid-generator))
(update-in [:hardwallet :secrets] dissoc :mnemonic))} (update-in [:hardwallet :secrets] dissoc :mnemonic))}
@ -716,3 +827,39 @@
(assoc-in [:hardwallet :return-to-step] :recovery-phrase) (assoc-in [:hardwallet :return-to-step] :recovery-phrase)
(assoc-in [:hardwallet :setup-error] error))} (assoc-in [:hardwallet :setup-error] error))}
(process-error code))) (process-error code)))
(fx/defn on-get-keys-success
[{:keys [db] :as cofx} data]
(let [{:keys [whisper-public-key
whisper-private-key
wallet-address
encryption-public-key]} (js->clj data :keywordize-keys true)
whisper-public-key' (str "0x" whisper-public-key)
{:keys [photo-path name]} (get-in db [:accounts/accounts wallet-address])
password encryption-public-key]
(fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :pin :status] nil)
(assoc-in [:hardwallet :whisper-public-key] whisper-public-key')
(assoc-in [:hardwallet :whisper-private-key] whisper-private-key)
(assoc-in [:hardwallet :wallet-address] wallet-address)
(assoc-in [:hardwallet :encryption-public-key] encryption-public-key)
(update :accounts/login assoc
:password password
:address wallet-address
:photo-path photo-path
:name name))}
(accounts.login/user-login true))))
(fx/defn on-get-keys-error
[{:keys [db] :as cofx} error]
(log/debug "[hardwallet] get keys error: " error)
(let [tag-was-lost? (= "Tag was lost." (:error error))]
(if tag-was-lost?
{:utils/show-popup {:title (i18n/label :t/error)
:content (i18n/label :t/tag-was-lost)}}
(fx/merge cofx
{:hardwallet/get-application-info {:pairing (get-pairing db)}
:db (update-in db [:hardwallet :pin] merge {:status :error
:error-label :t/pin-mismatch})}
(navigation/navigate-to-cofx :enter-pin nil)))))

View File

@ -1,8 +1,9 @@
(ns status-im.hardwallet.fx (ns status-im.hardwallet.fx
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.hardwallet.card :as card] [status-im.hardwallet.card :as card]
[status-im.react-native.js-dependencies :as js-dependencies] [status-im.utils.datetime :as utils.datetime]
[status-im.utils.datetime :as utils.datetime])) [status-im.native-module.core :as statusgo]
[status-im.react-native.js-dependencies :as js-dependencies]))
(re-frame/reg-fx (re-frame/reg-fx
:hardwallet/get-application-info :hardwallet/get-application-info
@ -68,6 +69,10 @@
:hardwallet/unpair-and-delete :hardwallet/unpair-and-delete
card/unpair-and-delete) card/unpair-and-delete)
(re-frame/reg-fx
:hardwallet/get-keys
card/get-keys)
;TODO remove when keycard login will be ready ;TODO remove when keycard login will be ready
(re-frame/reg-fx (re-frame/reg-fx
:hardwallet/persist-pairing :hardwallet/persist-pairing
@ -98,3 +103,7 @@
(.. js-dependencies/react-native (.. js-dependencies/react-native
-AsyncStorage -AsyncStorage
(removeItem "status-keycard-pairing")))) (removeItem "status-keycard-pairing"))))
(re-frame/reg-fx
:hardwallet/login-with-keycard
statusgo/login-with-keycard)

View File

@ -28,6 +28,10 @@
(defn verify [address password callback] (defn verify [address password callback]
(native-module/verify address password callback)) (native-module/verify address password callback))
(defn login-with-keycard
[{:keys [whisper-private-key encryption-public-key on-result]}]
(native-module/login-with-keycard whisper-private-key encryption-public-key on-result))
(defn set-soft-input-mode [mode] (defn set-soft-input-mode [mode]
(native-module/set-soft-input-mode mode)) (native-module/set-soft-input-mode mode))

View File

@ -75,6 +75,10 @@
(when (and @node-started status) (when (and @node-started status)
(.verify status address password on-result))) (.verify status address password on-result)))
(defn login-with-keycard [whisper-private-key encryption-public-key on-result]
(when (and @node-started status)
(.loginWithKeycard status whisper-private-key encryption-public-key on-result)))
(defn set-soft-input-mode [mode] (defn set-soft-input-mode [mode]
(when status (when status
(.setSoftInputMode status mode))) (.setSoftInputMode status mode)))

View File

@ -37,7 +37,7 @@
(def account-badge-text-view (def account-badge-text-view
{:margin-left 16 {:margin-left 16
:margin-right 21 :margin-right 31
:flex-shrink 1}) :flex-shrink 1})
(def account-badge-text (def account-badge-text

View File

@ -10,6 +10,11 @@
(fn [db] (fn [db]
(:accounts/accounts db))) (:accounts/accounts db)))
(re-frame/reg-sub
:accounts/login
(fn [db]
(:accounts/login db)))
(re-frame/reg-sub (re-frame/reg-sub
:account/account :account/account
(fn [db] (fn [db]

View File

@ -14,14 +14,18 @@
[status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.screens.privacy-policy.views :as privacy-policy])) [status-im.ui.screens.privacy-policy.views :as privacy-policy]))
(defn account-view [{:keys [address photo-path name public-key]}] (defn account-view [{:keys [address photo-path name public-key keycard-instance-uid]}]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:accounts.login.ui/account-selected address photo-path name])} [react/touchable-highlight {:on-press #(re-frame/dispatch [:accounts.login.ui/account-selected address photo-path name])}
[react/view styles/account-view [react/view styles/account-view
[photos/photo photo-path {:size styles/account-image-size}] [photos/photo photo-path {:size styles/account-image-size}]
[react/view styles/account-badge-text-view [react/view styles/account-badge-text-view
[react/text {:style styles/account-badge-text [react/view {:flex-direction :row}
:numberOfLines 1} [react/text {:style styles/account-badge-text
name] :numberOfLines 1}
name]
(when keycard-instance-uid
[icons/icon :icons/hardwallet {:color colors/blue
:container-style {:margin-left 7}}])]
[react/text {:style styles/account-badge-pub-key-text [react/text {:style styles/account-badge-pub-key-text
:ellipsize-mode :middle :ellipsize-mode :middle
:numberOfLines 1} :numberOfLines 1}

View File

@ -176,4 +176,7 @@
#(case view-id #(case view-id
:keycard-settings (hardwallet/settings-screen-did-load %) :keycard-settings (hardwallet/settings-screen-did-load %)
:reset-card (hardwallet/reset-card-screen-did-load %) :reset-card (hardwallet/reset-card-screen-did-load %)
:enter-pin (hardwallet/enter-pin-screen-did-load %)
:hardwallet-connect (hardwallet/hardwallet-connect-screen-did-load %)
:accounts (hardwallet/accounts-screen-did-load %)
nil)))) nil))))

View File

@ -4,4 +4,9 @@
(re-frame/reg-sub (re-frame/reg-sub
:hardwallet/nfc-enabled? :hardwallet/nfc-enabled?
(fn [db] (fn [db]
(get-in db [:hardwallet :nfc-enabled?]))) (get-in db [:hardwallet :nfc-enabled?])))
(re-frame/reg-sub
:hardwallet/card-read-in-progress?
(fn [db]
(get-in db [:hardwallet :card-read-in-progress?] false)))

View File

@ -11,15 +11,20 @@
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors])) [status-im.ui.components.colors :as colors]))
(defn nfc-enabled [] (defview nfc-enabled []
[react/view styles/nfc-enabled-container (letsubs [card-read-in-progress? [:hardwallet/card-read-in-progress?]]
[react/view [react/view styles/nfc-enabled-container
[react/image {:source (:hold-card-animation resources/ui) [react/view
:style styles/phone-nfc-on-image}]] [react/image {:source (:hold-card-animation resources/ui)
[react/view styles/turn-nfc-text-container :style styles/phone-nfc-on-image}]]
[react/text {:style styles/status-hardwallet-text [react/view styles/turn-nfc-text-container
:number-of-lines 2} [react/text {:style styles/status-hardwallet-text
(i18n/label :t/hold-card)]]]) :number-of-lines 2}
(i18n/label :t/hold-card)]]
(when card-read-in-progress?
[react/view {:margin-top 35}
[react/activity-indicator {:animating true
:size :large}]])]))
(defn nfc-disabled [] (defn nfc-disabled []
[react/view styles/nfc-disabled-container [react/view styles/nfc-disabled-container

View File

@ -0,0 +1,45 @@
(ns status-im.ui.screens.hardwallet.login.styles
(:require [status-im.ui.components.colors :as colors]))
(def container
{:flex 1
:background-color colors/white})
(def inner-container
{:flex-direction :column
:flex 1
:align-items :center
:justify-content :space-between})
(def login-view
{:flex 1
:margin-horizontal 16})
(def login-badge-container
{:margin-top 24})
(def processing-view
{:flex 1
:align-items :center
:justify-content :center})
(def sign-you-in
{:margin-top 16
:font-size 13
:color colors/black})
(def bottom-button-container
{:flex-direction :row
:margin-horizontal 12
:margin-vertical 15
:align-items :center})
(def login-badge
{:align-items :center})
(def login-badge-image-size 56)
(def login-badge-name
{:font-size 15
:color colors/black
:margin-top 8})

View File

@ -0,0 +1,48 @@
(ns status-im.ui.screens.hardwallet.login.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [status-im.ui.screens.hardwallet.pin.views :as pin.views]
[status-im.ui.screens.hardwallet.connect.views :as connect.views]
[status-im.ui.screens.hardwallet.components :as components]
[status-im.ui.screens.hardwallet.login.styles :as styles]
[status-im.ui.screens.hardwallet.settings.views :as settings.views]
[status-im.ui.components.react :as react]
[status-im.ui.components.styles :as components.styles]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.screens.chat.photos :as photos]
[status-im.i18n :as i18n]
[status-im.ui.components.toolbar.actions :as toolbar.actions]
[status-im.ui.components.react :as react.components]
[re-frame.core :as re-frame]))
(defview hardwallet-login []
(letsubs [{:keys [photo-path name processing]} [:get :accounts/login]
nfc-enabled? [:hardwallet/nfc-enabled?]]
[react/keyboard-avoiding-view styles/container
[status-bar/status-bar]
[toolbar/toolbar
nil
[toolbar/nav-button
(toolbar.actions/back #(re-frame/dispatch [:navigate-to-clean :accounts]))]
[toolbar/content-title (i18n/label :t/sign-in-to-status)]]
[components.common/separator]
[react/view styles/login-view
[react/view styles/login-badge-container
[react/view styles/login-badge
[photos/photo photo-path {:size styles/login-badge-image-size}]
[react/view
[react/text {:style styles/login-badge-name
:numberOfLines 1}
name]]]
[react/view
(if nfc-enabled?
[connect.views/nfc-enabled]
[connect.views/nfc-disabled])]]]
(when processing
[react/view styles/processing-view
[react.components/activity-indicator {:animating true}]
[react/i18n-text {:style styles/sign-you-in :key :sign-you-in}]])
(when-not processing
[react/view {:style styles/bottom-button-container}
[react/view {:style {:flex 1}}]])]))

View File

@ -2,6 +2,10 @@
(:require-macros [status-im.utils.styles :refer [defstyle]]) (:require-macros [status-im.utils.styles :refer [defstyle]])
(:require [status-im.ui.components.colors :as colors])) (:require [status-im.ui.components.colors :as colors]))
(def container
{:flex 1
:background-color colors/white})
(defstyle pin-container (defstyle pin-container
{:flex 1 {:flex 1
:flex-direction :column :flex-direction :column

View File

@ -6,6 +6,11 @@
(fn [db] (fn [db]
(get-in db [:hardwallet :pin :original]))) (get-in db [:hardwallet :pin :original])))
(re-frame/reg-sub
:hardwallet/login-pin
(fn [db]
(get-in db [:hardwallet :pin :login])))
(re-frame/reg-sub (re-frame/reg-sub
:hardwallet/pin-confirmation :hardwallet/pin-confirmation
(fn [db] (fn [db]

View File

@ -6,7 +6,10 @@
[status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.screens.hardwallet.pin.styles :as styles] [status-im.ui.screens.hardwallet.pin.styles :as styles]
[status-im.ui.screens.hardwallet.components :as components])) [status-im.ui.screens.hardwallet.components :as components]
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.actions :as actions]))
(defn numpad-button [n step enabled?] (defn numpad-button [n step enabled?]
[react/touchable-highlight [react/touchable-highlight
@ -98,22 +101,40 @@
[pin-indicators pin])) [pin-indicators pin]))
[numpad step enabled?]]]])) [numpad step enabled?]]]]))
(defview main [] (def pin-retries 3)
(letsubs [original [:hardwallet/original-pin] (def puk-retries 5)
confirmation [:hardwallet/pin-confirmation]
enter-step [:hardwallet/pin-enter-step] (defview enter-pin []
(letsubs [pin [:hardwallet/pin]
step [:hardwallet/pin-enter-step]
status [:hardwallet/pin-status] status [:hardwallet/pin-status]
pin-retry-counter [:hardwallet/pin-retry-counter]
puk-retry-counter [:hardwallet/puk-retry-counter]
error-label [:hardwallet/pin-error-label]] error-label [:hardwallet/pin-error-label]]
(case enter-step [react/view {:flex 1
:original [pin-view {:pin original :background-color colors/white}
:title-label :t/create-pin [status-bar/status-bar]
:description-label :t/create-pin-description [toolbar/toolbar nil toolbar/default-nav-back nil]
:step :original (if (zero? pin-retry-counter)
:status status [pin-view {:pin pin
:error-label error-label}] :retry-counter (when (< puk-retry-counter puk-retries) puk-retry-counter)
:confirmation [pin-view {:pin confirmation :title-label :t/enter-puk-code
:title-label :t/repeat-pin :description-label :t/enter-puk-code-description
:description-label :t/create-pin-description :step step
:step :confirmation :status status
:status status :error-label error-label}]
: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
:original :t/create-pin
:confirmation :t/repeat-pin
:t/current-pin)
:description-label (case step
:current :t/current-pin-description
:login :t/login-pin-description
:t/new-pin-description)
:step step
:status status
:error-label error-label}])]))

View File

@ -13,46 +13,6 @@
[status-im.ui.components.common.common :as components.common] [status-im.ui.components.common.common :as components.common]
[reagent.core :as reagent])) [reagent.core :as reagent]))
(def pin-retries 3)
(def puk-retries 5)
(defview enter-pin []
(letsubs [pin [:hardwallet/pin]
step [:hardwallet/pin-enter-step]
status [:hardwallet/pin-status]
pin-retry-counter [:hardwallet/pin-retry-counter]
puk-retry-counter [:hardwallet/puk-retry-counter]
error-label [:hardwallet/pin-error-label]]
[react/keyboard-avoiding-view {:flex 1}
[react/view {:flex 1
:background-color colors/white}
[react/view {:flex-direction :column
:flex 1
:align-items :center
:justify-content :space-between}
[components/maintain-card nil]
(if (zero? pin-retry-counter)
[pin.views/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.views/pin-view {:pin pin
:retry-counter (when (< pin-retry-counter pin-retries) pin-retry-counter)
:title-label (case step
:current :t/current-pin
:original :t/create-pin
:confirmation :t/repeat-pin
:t/current-pin)
:description-label (case step
:current :t/current-pin-description
:t/new-pin-description)
:step step
:status status
:error-label error-label}])]]]))
(defn- action-row [{:keys [icon label on-press color-theme]}] (defn- action-row [{:keys [icon label on-press color-theme]}]
[react/touchable-highlight [react/touchable-highlight
{:on-press on-press} {:on-press on-press}

View File

@ -378,7 +378,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/main] :pin [pin.views/enter-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

@ -53,7 +53,7 @@
[status-im.ui.screens.pairing.views :refer [installations]] [status-im.ui.screens.pairing.views :refer [installations]]
[status-im.ui.screens.bootnodes-settings.edit-bootnode.views :refer [edit-bootnode]] [status-im.ui.screens.bootnodes-settings.edit-bootnode.views :refer [edit-bootnode]]
[status-im.ui.screens.currency-settings.views :refer [currency-settings]] [status-im.ui.screens.currency-settings.views :refer [currency-settings]]
[status-im.ui.screens.hardwallet.settings.views :refer [keycard-settings enter-pin reset-card]] [status-im.ui.screens.hardwallet.settings.views :refer [keycard-settings reset-card]]
[status-im.ui.screens.help-center.views :refer [help-center]] [status-im.ui.screens.help-center.views :refer [help-center]]
[status-im.ui.screens.browser.views :refer [browser]] [status-im.ui.screens.browser.views :refer [browser]]
[status-im.ui.screens.add-new.open-dapp.views :refer [open-dapp dapp-description]] [status-im.ui.screens.add-new.open-dapp.views :refer [open-dapp dapp-description]]
@ -61,6 +61,7 @@
[status-im.ui.screens.accounts.create.views :refer [create-account]] [status-im.ui.screens.accounts.create.views :refer [create-account]]
[status-im.ui.screens.hardwallet.authentication-method.views :refer [hardwallet-authentication-method]] [status-im.ui.screens.hardwallet.authentication-method.views :refer [hardwallet-authentication-method]]
[status-im.ui.screens.hardwallet.connect.views :refer [hardwallet-connect]] [status-im.ui.screens.hardwallet.connect.views :refer [hardwallet-connect]]
[status-im.ui.screens.hardwallet.pin.views :refer [enter-pin]]
[status-im.ui.screens.hardwallet.setup.views :refer [hardwallet-setup]] [status-im.ui.screens.hardwallet.setup.views :refer [hardwallet-setup]]
[status-im.ui.screens.hardwallet.success.views :refer [hardwallet-success]] [status-im.ui.screens.hardwallet.success.views :refer [hardwallet-success]]
[status-im.ui.screens.profile.seed.views :refer [backup-seed]] [status-im.ui.screens.profile.seed.views :refer [backup-seed]]
@ -144,10 +145,12 @@
config/hardwallet-enabled? config/hardwallet-enabled?
(assoc :hardwallet-authentication-method hardwallet-authentication-method (assoc :hardwallet-authentication-method hardwallet-authentication-method
:hardwallet-connect hardwallet-connect :hardwallet-connect hardwallet-connect
:enter-pin enter-pin
:hardwallet-setup hardwallet-setup :hardwallet-setup hardwallet-setup
:hardwallet-success hardwallet-success))) :hardwallet-success hardwallet-success)))
(cond-> {:headerMode "none"} (cond-> {:headerMode "none"}
(#{:intro :login :progress} view-id) ; add view-id here if you'd like that view to be first view when app is started
(#{:intro :login :progress :accounts} view-id)
(assoc :initialRouteName (name view-id))))} (assoc :initialRouteName (name view-id))))}
:chat-stack :chat-stack
{:screen {:screen
@ -155,23 +158,28 @@
(stack-screens (stack-screens
{:main-stack {:main-stack
{:screens {:screens
{:home (main-tabs/get-main-tab :home) (cond->
:chat chat {:home (main-tabs/get-main-tab :home)
:profile profile.contact/profile :chat chat
:new add-new :profile profile.contact/profile
:new-chat new-chat :new add-new
:qr-scanner qr-scanner :new-chat new-chat
:new-group new-group :qr-scanner qr-scanner
:add-participants-toggle-list add-participants-toggle-list :new-group new-group
:contact-toggle-list contact-toggle-list :add-participants-toggle-list add-participants-toggle-list
:group-chat-profile profile.group-chat/group-chat-profile :contact-toggle-list contact-toggle-list
:new-public-chat new-public-chat :group-chat-profile profile.group-chat/group-chat-profile
:open-dapp open-dapp :new-public-chat new-public-chat
:dapp-description dapp-description :open-dapp open-dapp
:browser browser :dapp-description dapp-description
:stickers stickers/packs :browser browser
:stickers-pack stickers/pack :stickers stickers/packs
:login login} :stickers-pack stickers/pack
:login login}
config/hardwallet-enabled?
(assoc :hardwallet-connect hardwallet-connect
:enter-pin enter-pin))
:config :config
{:headerMode "none" {:headerMode "none"
:initialRouteName "home"}} :initialRouteName "home"}}

View File

@ -233,3 +233,19 @@
(is (contains? efx :utils/show-popup))) (is (contains? efx :utils/show-popup)))
(testing "Logout." (testing "Logout."
(is (= [:accounts.logout.ui/logout-confirmed] (:dispatch efx))))))) (is (= [:accounts.logout.ui/logout-confirmed] (:dispatch efx)))))))
(deftest login
(testing "login with keycard"
(let [wpk "c56c7ac797c27b3790ce02c2459e9957c5d20d7a2c55320535526ce9e4dcbbef"
epk "04f43da85ff1c333f3e7277b9ac4df92c9120fbb251f1dede7d41286e8c055acfeb845f6d2654821afca25da119daff9043530b296ee0e28e202ba92ec5842d617"
db {:hardwallet {:encryption-public-key epk
:whisper-private-key wpk
:wallet-address "83278851e290d2488b6add2a257259f5741a3b7d"
:whisper-public-key "0x04491c1272149d7fa668afa45968c9914c0661641ace7dbcbc585c15070257840a0b4b1f71ce66c2147e281e1a44d6231b4731a26f6cc0a49e9616bbc7fc2f1a93"
:whisper-address "b8bec30855ff20c2ddab32282e2b2c8c8baca70d"}}
result (login.core/login {:db db})]
(is (= (-> result (get :hardwallet/login-with-keycard) keys count)
3))
(is (= (get-in result [:hardwallet/login-with-keycard :whisper-private-key wpk])))
(is (= (get-in result [:hardwallet/login-with-keycard :encryption-public-key epk])))
(is (fn? (get-in result [:hardwallet/login-with-keycard :on-result]))))))

View File

@ -838,13 +838,17 @@
"pin-unblocked-description": "Your new PIN {{pin}}", "pin-unblocked-description": "Your new PIN {{pin}}",
"current-pin": "Enter PIN", "current-pin": "Enter PIN",
"current-pin-description": "Enter your PIN to proceed", "current-pin-description": "Enter your PIN to proceed",
"login-pin-description": "Enter your PIN code to login\nto your account",
"new-pin-description": "Enter new PIN code", "new-pin-description": "Enter new PIN code",
"change-pin": "Change PIN", "change-pin": "Change PIN",
"enter-pin": "Enter PIN",
"enter-pin-description": "Enter your PIN code to login\n to your account",
"create-pin": "Create a PIN", "create-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",
"pin-mismatch": "PIN does not match", "pin-mismatch": "PIN does not match",
"tag-was-lost": "Tag was lost",
"cannot-use-default-pin": "PIN 000000 is not allowed.\nPlease use another number", "cannot-use-default-pin": "PIN 000000 is not allowed.\nPlease use another number",
"pin-changed": "PIN has been changed to {{pin}}", "pin-changed": "PIN has been changed to {{pin}}",
"pin-retries-left": "You have {{number}} retries left", "pin-retries-left": "You have {{number}} retries left",
@ -862,6 +866,14 @@
"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": "No pairing slots are available.\n You could unpair the device\n that already paired with the 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-text": "The card you are presenting does not hold any account. Please try again with the right card",
"wrong-card": "Wrong card",
"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-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",
"help": "help", "help": "help",
"help-capitalized": "Help", "help-capitalized": "Help",
"pairing-card": "Pairing card", "pairing-card": "Pairing card",