Using Keycard with the new Endpoints for Send/Bridge (#21705)

* fix: routes component annoying warning

* feat: replaced keycard sign with sign-hashes

* feat: using the keycard to sign transactions

* fix: removed unused and weird imports

* chore: removed debug logs

* chore: linting

* fix: removed clearing data on send error
This commit is contained in:
Lungu Cristian 2024-11-29 09:18:12 +02:00 committed by GitHub
parent 874f07bd77
commit 53d5ac4ea2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 119 additions and 92 deletions

View File

@ -2,7 +2,9 @@
(:require
["react-native" :as rn]
["react-native-status-keycard" :default status-keycard]
[oops.core :as oops]
[react-native.platform :as platform]
[schema.core :as schema]
[taoensso.timbre :as log]))
(defonce event-emitter
@ -254,17 +256,19 @@
(catch on-failure))))
(defn sign
[{pin :pin path :path card-hash :hash on-success :on-success on-failure :on-failure}]
(when (and pin card-hash)
(if path
(.. status-keycard
(signWithPath pin path card-hash)
(then on-success)
(catch on-failure))
(.. status-keycard
(sign pin card-hash)
(then on-success)
(catch on-failure)))))
[{:keys [pin path hash-data]}]
(if path
(oops/ocall status-keycard "signWithPath" pin path hash-data)
(oops/ocall status-keycard "sign" pin hash-data)))
(schema/=> sign
[:=>
[:cat
[:map
[:pin :string]
[:hash-data :string]
[:path {:optional true} [:maybe :string]]]]
:any])
(defn sign-typed-data
[{card-hash :hash on-success :on-success on-failure :on-failure}]

View File

@ -1,6 +1,6 @@
(ns status-im.common.log
(:require
[clojure.pprint :as promesa]
[clojure.pprint :as pprint]
[clojure.string :as string]
[native-module.core :as native-module]
[re-frame.core :as re-frame]
@ -46,7 +46,7 @@
(update data
:vargs
(partial mapv
#(if (string? %) % (with-out-str (promesa/pprint %))))))]})
#(if (string? %) % (with-out-str (pprint/pprint %))))))]})
(native-module/init-status-go-logging logging-params)))))
(re-frame/reg-fx

View File

@ -36,12 +36,6 @@
"wallet"
{:fx [[:dispatch [:wallet/signal-received event-js]]]}
"wallet.sign.transactions"
{:fx [[:dispatch
[:standard-auth/authorize-with-keycard
{:on-complete #(rf/dispatch [:keycard/sign-hash %
(first (transforms/js->clj event-js))])}]]]}
"wallet.suggested.routes"
{:fx [[:dispatch [:wallet/handle-suggested-routes (transforms/js->clj event-js)]]]}

View File

@ -1,11 +1,13 @@
(ns status-im.contexts.keycard.effects
(:require [keycard.keycard :as keycard]
[native-module.core :as native-module]
[promesa.core :as promesa]
[react-native.async-storage :as async-storage]
[react-native.platform :as platform]
status-im.contexts.keycard.nfc.effects
[status-im.contexts.keycard.utils :as keycard.utils]
[status-im.contexts.profile.config :as profile.config]
[utils.hex :as hex]
[utils.re-frame :as rf]))
(defonce ^:private active-listeners (atom []))
@ -50,7 +52,22 @@
(rf/reg-fx :effects.keycard/sign
(fn [args]
(keycard/sign (keycard.utils/wrap-handlers args))))
(-> (keycard/sign args)
(promesa/then (keycard.utils/get-on-success args))
(promesa/catch (keycard.utils/get-on-failure args)))))
(rf/reg-fx :effects.keycard/sign-hashes
(fn [{:keys [hashes pin path on-success] :as args}]
(-> (promesa/all
(for [hash-data hashes]
(-> (keycard/sign {:pin pin
:path path
:hash-data (hex/normalize-hex hash-data)})
(promesa/then (fn [signature]
{:signature signature
:message hash-data})))))
(promesa/then on-success)
(promesa/catch (keycard.utils/get-on-failure args)))))
(rf/reg-fx :keycard/init-card
(fn [args]

View File

@ -2,33 +2,24 @@
(:require [utils.address]
[utils.re-frame :as rf]))
(defn get-signature-map
[tx-hash signature]
{tx-hash {:r (subs signature 0 64)
:s (subs signature 64 128)
:v (subs signature 128 130)}})
(rf/reg-event-fx :keycard/sign
(rf/reg-event-fx :keycard/sign-hashes
(fn [_ [data]]
{:effects.keycard/sign data}))
{:effects.keycard/sign-hashes data}))
(rf/reg-event-fx :keycard/sign-hash
(fn [{:keys [db]} [pin-text tx-hash]]
(let [current-address (get-in db [:wallet :current-viewing-account-address])
path (get-in db [:wallet :accounts current-address :path])
key-uid (get-in db [:profile/profile :key-uid])]
(rf/reg-event-fx :keycard/connect-and-sign-hashes
(fn [{:keys [db]} [{:keys [keycard-pin address hashes on-success on-failure]}]]
(let [{:keys [path key-uid]} (get-in db [:wallet :accounts address])]
{:fx [[:dispatch
[:keycard/connect
{:key-uid key-uid
:on-success
(fn []
(rf/dispatch
[:keycard/sign
{:pin pin-text
[:keycard/sign-hashes
{:pin keycard-pin
:path path
:hash (utils.address/naked-address tx-hash)
:on-success (fn [signature]
:hashes hashes
:on-success (fn [signatures]
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:wallet/proceed-with-transactions-signatures
(get-signature-map tx-hash signature)]))
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]))}]]]})))
(when on-success (on-success signatures)))
:on-failure on-failure}]))}]]]})))

View File

@ -57,9 +57,13 @@
data
(update data :key-uid address/normalized-hex)))
(defn format-success-data
[data]
(normalize-key-uid (transforms/js->clj data)))
(defn get-on-success
[{:keys [on-success]}]
#(when on-success (on-success (normalize-key-uid (transforms/js->clj %)))))
#(when on-success (on-success (format-success-data %))))
(defn get-on-failure
[{:keys [on-failure]}]

View File

@ -647,22 +647,38 @@
(rf/reg-event-fx
:wallet/prepare-signatures-for-transactions
(fn [{:keys [db]} [type sha3-pwd]]
(let [transaction-for-signing (get-in db [:wallet :ui type :transaction-for-signing])]
{:fx [[:effects.wallet/sign-transaction-hashes
{:hashes (get-in transaction-for-signing [:signingDetails :hashes])
:address (get-in transaction-for-signing [:signingDetails :address])
:password (security/safe-unmask-data sha3-pwd)
:on-success (fn [signatures]
(rf/dispatch [:wallet/send-router-transactions-with-signatures type
signatures]))
:on-error (fn [error]
(log/error "failed to prepare signatures for transactions"
{:event :wallet/prepare-signatures-for-transactions
:error error})
(rf/dispatch [:toasts/upsert
{:id :prepare-signatures-for-transactions-error
:type :negative
:text (:message error)}]))}]]})))
(let [{:keys [hashes address signOnKeycard]} (get-in db
[:wallet :ui type :transaction-for-signing
:signingDetails])
on-success (fn [signatures]
(rf/dispatch
[:wallet/send-router-transactions-with-signatures type
signatures]))
on-error (fn [error]
(log/error
"failed to prepare signatures for transactions"
{:event :wallet/prepare-signatures-for-transactions
:error error})
(rf/dispatch
[:toasts/upsert
{:id :prepare-signatures-for-transactions-error
:type :negative
:text (:message error)}]))]
(if signOnKeycard
{:fx [[:dispatch
[:standard-auth/authorize-with-keycard
{:on-complete #(rf/dispatch [:keycard/connect-and-sign-hashes
{:keycard-pin %
:address address
:hashes hashes
:on-success on-success
:on-failure on-error}])}]]]}
{:fx [[:effects.wallet/sign-transaction-hashes
{:hashes hashes
:address address
:password (security/safe-unmask-data sha3-pwd)
:on-success on-success
:on-error on-error}]]}))))
(rf/reg-event-fx
:wallet/send-router-transactions-with-signatures
@ -678,6 +694,7 @@
:params [{:uuid (get-in transaction-for-signing [:sendDetails :uuid])
:signatures signatures-map}]
:on-success (fn []
(rf/dispatch [:wallet/clean-send-data])
(rf/dispatch [:hide-bottom-sheet]))
:on-error (fn [error]
(log/error "failed to send router transactions with signatures"

View File

@ -84,39 +84,40 @@
[{:keys [network-values token-symbol on-press on-long-press receiver? loading-routes?
token-not-supported-in-receiver-networks?]}]
[rn/view
(map-indexed (fn [index
{chain-id :chain-id
network-value-type :type
total-amount :total-amount}]
(let [status (cond (and (= network-value-type :not-available)
loading-routes?
token-not-supported-in-receiver-networks?)
:loading
(= network-value-type :not-available)
:disabled
:else network-value-type)
amount-formatted (-> (rf/sub [:wallet/send-amount-fixed total-amount])
(str " " token-symbol))]
[rn/view
{:key (str (if receiver? "to" "from") "-" chain-id)
:style {:margin-top (if (pos? index) 11 7.5)}}
[quo/network-bridge
{:amount (if (= network-value-type :not-available)
(i18n/label :t/not-available)
amount-formatted)
:network (network-utils/id->network chain-id)
:status status
:on-press #(when (not loading-routes?)
(cond
(= network-value-type :edit)
(open-preferences)
on-press (on-press chain-id total-amount)))
:on-long-press #(when (and (not loading-routes?) (not= status :disabled))
(cond
(= network-value-type :add)
(open-preferences)
on-long-press (on-long-press chain-id total-amount)))}]]))
network-values)])
(doall
(map-indexed (fn [index
{chain-id :chain-id
network-value-type :type
total-amount :total-amount}]
(let [status (cond (and (= network-value-type :not-available)
loading-routes?
token-not-supported-in-receiver-networks?)
:loading
(= network-value-type :not-available)
:disabled
:else network-value-type)
amount-formatted (-> (rf/sub [:wallet/send-amount-fixed total-amount])
(str " " token-symbol))]
[rn/view
{:key (str (if receiver? "to" "from") "-" chain-id)
:style {:margin-top (if (pos? index) 11 7.5)}}
[quo/network-bridge
{:amount (if (= network-value-type :not-available)
(i18n/label :t/not-available)
amount-formatted)
:network (network-utils/id->network chain-id)
:status status
:on-press #(when (not loading-routes?)
(cond
(= network-value-type :edit)
(open-preferences)
on-press (on-press chain-id total-amount)))
:on-long-press #(when (and (not loading-routes?) (not= status :disabled))
(cond
(= network-value-type :add)
(open-preferences)
on-long-press (on-long-press chain-id total-amount)))}]]))
network-values))])
(defn render-network-links
[{:keys [network-links sender-network-values]}]

View File

@ -268,8 +268,7 @@
:transaction-type transaction-type}]
(when (and (not loading-suggested-routes?) route (seq route))
[standard-auth/slide-button
{:keycard-supported? (get-in transaction-for-signing
[:signingDetails :signOnKeycard])
{:keycard-supported? true
:size :size-48
:track-text (if (= transaction-type :tx/bridge)
(i18n/label :t/slide-to-bridge)