[#21559] Keycard - Fresh instal sign in (#21612)

00a8a72a...79e662e4
[#21592] No Oops, this isn't a Keycard screen when scanning not a Keycard
This commit is contained in:
flexsurfer 2024-11-20 12:57:46 +01:00 committed by GitHub
parent a1e3bb3bd6
commit 45cd66f908
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 148 additions and 62 deletions

View File

@ -8,6 +8,7 @@
(defn view (defn view
[] []
(let [{:keys [on-press]} (rf/sub [:get-screen-params])]
[:<> [:<>
[quo/page-nav [quo/page-nav
{:icon-name :i/arrow-left {:icon-name :i/arrow-left
@ -26,4 +27,4 @@
[quo/bottom-actions [quo/bottom-actions
{:actions :one-action {:actions :one-action
:button-one-label (i18n/label :t/ready-to-scan) :button-one-label (i18n/label :t/ready-to-scan)
:button-one-props {:on-press #(rf/dispatch [:keycard/migration.check-empty-card])}}]]) :button-one-props {:on-press on-press}}]]))

View File

@ -40,6 +40,14 @@
(fn [args] (fn [args]
(keycard/get-keys (keycard.utils/wrap-handlers args)))) (keycard/get-keys (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/get-more-keys
(fn [args]
(keycard/import-keys (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/export-key
(fn [args]
(keycard/export-key (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/sign (rf/reg-fx :effects.keycard/sign
(fn [args] (fn [args]
(keycard/sign (keycard.utils/wrap-handlers args)))) (keycard/sign (keycard.utils/wrap-handlers args))))

View File

@ -41,8 +41,7 @@
(fn [{:keys [db]} [error]] (fn [{:keys [db]} [error]]
(let [tag-was-lost? (keycard.utils/tag-lost? (:error error)) (let [tag-was-lost? (keycard.utils/tag-lost? (:error error))
pin-retries-count (keycard.utils/pin-retries (:error error))] pin-retries-count (keycard.utils/pin-retries (:error error))]
(if (or tag-was-lost? (nil? pin-retries-count)) (when-not (or tag-was-lost? (nil? pin-retries-count))
{:db (assoc-in db [:keycard :pin :status] nil)}
{:db (-> db {:db (-> db
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries-count) (assoc-in [:keycard :application-info :pin-retry-counter] pin-retries-count)
(assoc-in [:keycard :pin :status] :error)) (assoc-in [:keycard :pin :status] :error))
@ -56,9 +55,22 @@
(fn [_ [data]] (fn [_ [data]]
{:effects.keycard/get-keys data})) {:effects.keycard/get-keys data}))
(rf/reg-event-fx :keycard/get-more-keys
(fn [_ [data]]
{:effects.keycard/get-more-keys data}))
(rf/reg-event-fx :keycard/export-key
(fn [_ [data]]
{:effects.keycard/export-key data}))
(rf/reg-event-fx :keycard/cancel-connection (rf/reg-event-fx :keycard/cancel-connection
(fn [{:keys [db]}] (fn [{:keys [db]}]
{:db (update db :keycard dissoc :on-card-connected-event-vector :on-nfc-cancelled-event-vector)})) {:db (update db
:keycard
dissoc
:card-connected?
:on-card-connected-event-vector
:on-nfc-cancelled-event-vector)}))
(rf/reg-event-fx :keycard/disconnect (rf/reg-event-fx :keycard/disconnect
(fn [_ _] (fn [_ _]
@ -95,11 +107,12 @@
(on-error error) (on-error error)
(rf/dispatch [:keycard/on-application-info-error error])) (rf/dispatch [:keycard/on-application-info-error error]))
(when on-success (on-success app-info)))) (when on-success (on-success app-info))))
:on-error (fn [] :on-failure (fn [error]
(when-not (keycard.utils/tag-lost? (:error error))
(if on-error (if on-error
(on-error :keycard/error.not-keycard) (on-error :keycard/error.not-keycard)
(rf/dispatch [:keycard/on-application-info-error (rf/dispatch [:keycard/on-application-info-error
:keycard/error.not-keycard])))}})) :keycard/error.not-keycard]))))}}))
(rf/reg-event-fx :keycard/connect (rf/reg-event-fx :keycard/connect
(fn [{:keys [db]} [{:keys [key-uid on-success on-error on-connect-event-vector]}]] (fn [{:keys [db]} [{:keys [key-uid on-success on-error on-connect-event-vector]}]]

View File

@ -1,5 +1,8 @@
(ns status-im.contexts.keycard.login.events (ns status-im.contexts.keycard.login.events
(:require [utils.re-frame :as rf])) (:require [status-im.constants :as constants]
[status-im.contexts.profile.config :as profile.config]
[utils.address :as address]
[utils.re-frame :as rf]))
(rf/reg-event-fx :keycard.login/on-get-keys-success (rf/reg-event-fx :keycard.login/on-get-keys-success
(fn [{:keys [db]} [data]] (fn [{:keys [db]} [data]]
@ -35,3 +38,60 @@
{:password encryption-public-key {:password encryption-public-key
:whisper-private-key whisper-private-key :whisper-private-key whisper-private-key
:key-uid key-uid}]]})))) :key-uid key-uid}]]}))))
(rf/reg-event-fx :keycard.login/check-card
(fn []
{:fx [[:dispatch
[:keycard/connect
{:on-error
(fn [error]
(if (= error :keycard/error.keycard-wrong-profile)
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.pin.enter
{:on-complete #(rf/dispatch [:keycard.login/prepare-for-profile-recovery
%])}]))
(rf/dispatch [:keycard/on-application-info-error error])))}]]]}))
(rf/reg-event-fx :keycard.login/prepare-for-profile-recovery
(fn [{:keys [db]} [pin]]
{:fx [[:dispatch
[:keycard/connect
{:key-uid (get-in db [:keycard :application-info :key-uid])
:on-success (fn []
(rf/dispatch
[:keycard/get-more-keys
{:pin pin
:on-success #(rf/dispatch [:keycard.login/recover-profile-and-login %])
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]))}]]]}))
(rf/reg-event-fx :keycard.login/recover-profile-and-login
(fn [{:keys [db]}
[{:keys [key-uid encryption-public-key whisper-private-key instance-uid whisper-public-key
whisper-address address wallet-public-key wallet-address wallet-root-address]}]]
(let [{:keys [pairing]} (get-in db [:keycard :pairings instance-uid])]
{:db
(-> db
(assoc :onboarding/recovered-account? true)
(assoc-in [:syncing :login-sha3-password] encryption-public-key))
:fx [[:dispatch [:keycard/disconnect]]
[:dispatch [:navigate-to :screen/onboarding.preparing-status]]
[:effects.profile/restore-and-login
(assoc (profile.config/create)
:keycardInstanceUID instance-uid
:keycardPairingKey pairing
:keycard {:keyUID key-uid
:address (address/normalized-hex address)
:whisperPrivateKey (address/normalized-hex whisper-private-key)
:whisperPublicKey (address/normalized-hex whisper-public-key)
:whisperAddress (address/normalized-hex whisper-address)
:walletPublicKey (address/normalized-hex wallet-public-key)
:walletAddress (address/normalized-hex wallet-address)
:walletRootAddress (address/normalized-hex wallet-root-address)
:encryptionPublicKey encryption-public-key
:eip1581Address ""}
:displayName ""
:password encryption-public-key
:customizationColor constants/profile-default-color
:fetchBackup true)]]})))

View File

@ -20,8 +20,6 @@
(rf/reg-event-fx :keycard.ios/on-nfc-user-cancelled (rf/reg-event-fx :keycard.ios/on-nfc-user-cancelled
(fn [{:keys [db]}] (fn [{:keys [db]}]
{:db (-> db {:db (assoc-in db [:keycard :on-nfc-cancelled-event-vector] nil)
(assoc-in [:keycard :pin :status] nil)
(assoc-in [:keycard :on-nfc-cancelled-event-vector] nil))
:fx [(when-let [on-nfc-cancelled-event-vector (get-in db [:keycard :on-nfc-cancelled-event-vector])] :fx [(when-let [on-nfc-cancelled-event-vector (get-in db [:keycard :on-nfc-cancelled-event-vector])]
[:dispatch on-nfc-cancelled-event-vector])]})) [:dispatch on-nfc-cancelled-event-vector])]}))

View File

@ -1,5 +1,6 @@
(ns status-im.contexts.keycard.pin.view (ns status-im.contexts.keycard.pin.view
(:require [quo.core :as quo] (:require [clojure.string :as string]
[quo.core :as quo]
[react-native.core :as rn] [react-native.core :as rn]
[status-im.constants :as constants] [status-im.constants :as constants]
[utils.i18n :as i18n] [utils.i18n :as i18n]
@ -20,7 +21,7 @@
:number-of-filled-pins (count text) :number-of-filled-pins (count text)
:error? error? :error? error?
:info (when error? :info (when error?
(if error-message (if (not (string/blank? error-message))
error-message error-message
(i18n/label :t/pin-retries-left {:number pin-retry-counter})))}]] (i18n/label :t/pin-retries-left {:number pin-retry-counter})))}]]
[quo/numbered-keyboard [quo/numbered-keyboard

View File

@ -15,6 +15,7 @@
(or (or
(= error "Tag was lost.") (= error "Tag was lost.")
(= error "NFCError:100") (= error "NFCError:100")
(= error "Malformed card response")
(re-matches #".*NFCError:100.*" error))) (re-matches #".*NFCError:100.*" error)))
(defn validate-application-info (defn validate-application-info
@ -28,12 +29,6 @@
(not has-master-key?) (not has-master-key?)
:keycard/error.keycard-blank :keycard/error.keycard-blank
(not= profile-key-uid key-uid)
:keycard/error.keycard-wrong-profile
(not paired?)
:keycard/error.keycard-unpaired
(and (zero? pin-retry-counter) (and (zero? pin-retry-counter)
(or (nil? puk-retry-counter) (or (nil? puk-retry-counter)
(pos? puk-retry-counter))) (pos? puk-retry-counter)))
@ -42,6 +37,12 @@
(zero? puk-retry-counter) (zero? puk-retry-counter)
:keycard/error.keycard-locked :keycard/error.keycard-locked
(not paired?)
:keycard/error.keycard-unpaired
(not= profile-key-uid key-uid)
:keycard/error.keycard-wrong-profile
:else :else
nil)) nil))

View File

@ -6,7 +6,6 @@
[react-native.safe-area :as safe-area] [react-native.safe-area :as safe-area]
[status-im.common.check-before-syncing.view :as check-before-syncing] [status-im.common.check-before-syncing.view :as check-before-syncing]
[status-im.common.metrics-confirmation-modal.view :as metrics-modal] [status-im.common.metrics-confirmation-modal.view :as metrics-modal]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.resources :as resources] [status-im.common.resources :as resources]
[status-im.config :as config] [status-im.config :as config]
[status-im.contexts.onboarding.create-or-sync-profile.style :as style] [status-im.contexts.onboarding.create-or-sync-profile.style :as style]
@ -109,14 +108,17 @@
:image (resources/get-image :ethereum-address) :image (resources/get-image :ethereum-address)
:on-press nav-to-seed-phrase-with-cur-screen}] :on-press nav-to-seed-phrase-with-cur-screen}]
[rn/view {:style style/space-between-suboptions}] [rn/view {:style style/space-between-suboptions}]
(when config/show-not-implemented-features?
[quo/small-option-card [quo/small-option-card
{:variant :icon {:variant :icon
:title (i18n/label :t/use-keycard) :title (i18n/label :t/use-keycard)
:subtitle (i18n/label :t/use-keycard-subtitle) :subtitle (i18n/label :t/profile-keys-on-keycard)
:accessibility-label :use-keycard-option-card :accessibility-label :use-keycard-option-card
:image (resources/get-image :use-keycard) :image (resources/get-image :use-keycard)
:on-press status-im.common.not-implemented/alert}])]])) :on-press (fn []
(rf/dispatch [:open-modal :screen/keycard.check
{:on-press
#(rf/dispatch
[:keycard.login/check-card])}]))}]]]))
(defn- navigate-back (defn- navigate-back
[] []

View File

@ -1,7 +1,6 @@
(ns status-im.contexts.profile.settings.list-items (ns status-im.contexts.profile.settings.list-items
(:require [status-im.common.not-implemented :as not-implemented] (:require [status-im.common.not-implemented :as not-implemented]
[status-im.config :as config] [status-im.config :as config]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
@ -55,13 +54,12 @@
:image :icon :image :icon
:blur? true :blur? true
:action :arrow}) :action :arrow})
(when (ff/enabled? ::ff/keycard.migrate-profile)
{:title (i18n/label :t/keycard) {:title (i18n/label :t/keycard)
:on-press #(rf/dispatch [:open-modal :screen/settings.keycard]) :on-press #(rf/dispatch [:open-modal :screen/settings.keycard])
:image-props :i/keycard :image-props :i/keycard
:image :icon :image :icon
:blur? true :blur? true
:action :arrow})] :action :arrow}]
[{:title (i18n/label :t/privacy-and-security) [{:title (i18n/label :t/privacy-and-security)
:on-press #(rf/dispatch [:open-modal :screen/settings-privacy-and-security]) :on-press #(rf/dispatch [:open-modal :screen/settings-privacy-and-security])
:image-props :i/privacy :image-props :i/privacy

View File

@ -43,4 +43,8 @@
:subtitle (i18n/label :t/ready-keycard) :subtitle (i18n/label :t/ready-keycard)
:accessibility-label :setup-keycard :accessibility-label :setup-keycard
:image (resources/get-image :use-keycard) :image (resources/get-image :use-keycard)
:on-press #(rf/dispatch [:open-modal :screen/keycard.check])}]])])) :on-press (fn []
(rf/dispatch [:open-modal :screen/keycard.check
{:on-press
#(rf/dispatch
[:keycard/migration.check-empty-card])}]))}]])]))

View File

@ -30,8 +30,7 @@
::wallet.long-press-watch-only-asset (enabled-in-env? :FLAG_LONG_PRESS_WATCH_ONLY_ASSET_ENABLED) ::wallet.long-press-watch-only-asset (enabled-in-env? :FLAG_LONG_PRESS_WATCH_ONLY_ASSET_ENABLED)
::wallet.saved-addresses (enabled-in-env? :WALLET_SAVED_ADDRESSES) ::wallet.saved-addresses (enabled-in-env? :WALLET_SAVED_ADDRESSES)
::wallet.wallet-connect (enabled-in-env? :FLAG_WALLET_CONNECT_ENABLED) ::wallet.wallet-connect (enabled-in-env? :FLAG_WALLET_CONNECT_ENABLED)
::wallet.custom-network-amounts (enabled-in-env? :FLAG_WALLET_CUSTOM_NETWORK_AMOUNTS_ENABLED) ::wallet.custom-network-amounts (enabled-in-env? :FLAG_WALLET_CUSTOM_NETWORK_AMOUNTS_ENABLED)})
::keycard.migrate-profile false})
(defonce ^:private feature-flags-config (defonce ^:private feature-flags-config
(reagent/atom initial-flags)) (reagent/atom initial-flags))

View File

@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>", "_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im", "owner": "status-im",
"repo": "status-go", "repo": "status-go",
"version": "v3.8.0", "version": "v3.9.0",
"commit-sha1": "b3dbe91b5fab4fdab475ee94549629a6d2988ccc", "commit-sha1": "79e662e4a563d650358e778871dc20ed71b0eb33",
"src-sha256": "0p104qd799rwhiqxfdkd6gh4phsby6zyay98mv0sapjxim3nz4xi" "src-sha256": "035hz6pn0hkbb2383bdzmzdg214yjkv3aax6bq3dzvyxz002p0m7"
} }

View File

@ -2010,6 +2010,7 @@
"profile-deleted-keycard": "You can now restore another key pair on your Keycard", "profile-deleted-keycard": "You can now restore another key pair on your Keycard",
"profile-deleted-title": "Profile deleted", "profile-deleted-title": "Profile deleted",
"profile-details": "Profile details", "profile-details": "Profile details",
"profile-keys-on-keycard": "If your profile keys are stored on a Keycard",
"profile-name": "Profile name", "profile-name": "Profile name",
"profile-name-is-too-long": "Profile name is too long", "profile-name-is-too-long": "Profile name is too long",
"profile-not-found": "Profile not found", "profile-not-found": "Profile not found",