Skip to content

Commit 8ac9cc0

Browse files
authored
Keycard signing for dapp interactions (#21785)
* feat: wip dapps signing with keycard Signed-off-by: Cristian Lungu <[email protected]> * fix: hide the pin sheet before showing the connection sheet Signed-off-by: Cristian Lungu <[email protected]> * fix: signing dapp request with password Signed-off-by: Cristian Lungu <[email protected]> * fix: logic for getting the current dapp Signed-off-by: Cristian Lungu <[email protected]> * fix: issues after endpoints update Signed-off-by: Cristian Lungu <[email protected]> * feat: removed support for eth_sign and signTransaction Signed-off-by: Cristian Lungu <[email protected]> * fix: removed unused event Signed-off-by: Cristian Lungu <[email protected]> * feat: re-enable dapps interactions with keycard Signed-off-by: Cristian Lungu <[email protected]> * fix: adapted to latest standard-auth changes Signed-off-by: Cristian Lungu <[email protected]> * feat: enable connected dapps for keycard Signed-off-by: Cristian Lungu <[email protected]> * ref: removed threading (->) Signed-off-by: Cristian Lungu <[email protected]> * fix: get keycard keypair addresses manually Signed-off-by: Cristian Lungu <[email protected]> * fix: wrong condition on utils/keycard-address? --------- Signed-off-by: Cristian Lungu <[email protected]>
1 parent c123031 commit 8ac9cc0

File tree

16 files changed

+152
-236
lines changed

16 files changed

+152
-236
lines changed

src/native_module/core.cljs

+10-6
Original file line numberDiff line numberDiff line change
@@ -253,15 +253,19 @@
253253

254254
(defn hash-typed-data
255255
"used for keycard"
256-
[data callback]
257-
(log/debug "[native-module] hash-typed-data")
258-
(.hashTypedData ^js (encryption) data callback))
256+
([data]
257+
(native-utils/promisify-native-module-call hash-typed-data data))
258+
([data callback]
259+
(log/debug "[native-module] hash-typed-data")
260+
(.hashTypedData ^js (encryption) data callback)))
259261

260262
(defn hash-typed-data-v4
261263
"used for keycard"
262-
[data callback]
263-
(log/debug "[native-module] hash-typed-data-v4")
264-
(.hashTypedDataV4 ^js (encryption) data callback))
264+
([data]
265+
(native-utils/promisify-native-module-call hash-typed-data-v4 data))
266+
([data callback]
267+
(log/debug "[native-module] hash-typed-data-v4")
268+
(.hashTypedDataV4 ^js (encryption) data callback)))
265269

266270
(defn send-transaction-with-signature
267271
"used for keycard"

src/status_im/constants.cljs

+1-6
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,7 @@
221221
(def ^:const wallet-connect-eth-sign-typed-v4-method "eth_signTypedData_v4")
222222
(def ^:const wallet-connect-supported-methods
223223
#{wallet-connect-personal-sign-method
224-
wallet-connect-eth-sign-method
225224
wallet-connect-eth-send-transaction-method
226-
;; NOTE: disabled, as we have no clear use cases for it and other wallets don't support it
227-
;; wallet-connect-eth-sign-transaction-method
228225
wallet-connect-eth-sign-typed-method
229226
wallet-connect-eth-sign-typed-v4-method})
230227
(def ^:const wallet-connect-supported-events #{"accountsChanged" "chainChanged"})
@@ -237,11 +234,9 @@
237234
(def ^:const wallet-connect-message-signing-methods
238235
#{wallet-connect-personal-sign-method
239236
wallet-connect-eth-sign-typed-method
240-
wallet-connect-eth-sign-method
241237
wallet-connect-eth-sign-typed-v4-method})
242238
(def ^:const wallet-connect-transaction-methods
243-
#{wallet-connect-eth-send-transaction-method
244-
wallet-connect-eth-sign-transaction-method})
239+
#{wallet-connect-eth-send-transaction-method})
245240

246241
(def ^:const transaction-pending-type-wallet-connect-transfer "WalletConnectTransfer")
247242

src/status_im/contexts/keycard/utils.cljs

+13
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,16 @@
7676
args
7777
:on-success (get-on-success args)
7878
:on-failure (get-on-failure args)))
79+
80+
(defn keycard-address?
81+
[keypairs address]
82+
(let [find-keycard-keypair (fn [kps] (some #(when-not (empty? (:keycards %)) %) kps))
83+
keypair-addresses (fn [kp]
84+
(->> (:accounts kp)
85+
(map :address)
86+
set))]
87+
(-> keypairs
88+
vals
89+
find-keycard-keypair
90+
keypair-addresses
91+
(contains? (string/lower-case address)))))

src/status_im/contexts/wallet/common/account_switcher/view.cljs

+2-7
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@
3030
type :no-title}}]
3131
(let [{:keys [color emoji watch-only?]} (rf/sub [:wallet/current-viewing-account])
3232
networks (rf/sub [:wallet/selected-network-details])
33-
sending-collectible? (rf/sub [:wallet/sending-collectible?])
34-
keycard? (rf/sub [:wallet/selected-keypair-keycard?])]
33+
sending-collectible? (rf/sub [:wallet/sending-collectible?])]
3534
[quo/page-nav
3635
{:type type
3736
:icon-name icon-name
@@ -46,11 +45,7 @@
4645
(not watch-only?)
4746
show-dapps-button?)
4847
{:icon-name :i/dapps
49-
:on-press #(rf/dispatch
50-
(if keycard?
51-
[:keycard/feature-unavailable-show
52-
{:feature-name :wallet.show-connected-dapps}]
53-
[:navigate-to :screen/wallet.connected-dapps]))})
48+
:on-press #(rf/dispatch [:navigate-to :screen/wallet.connected-dapps])})
5449
(when-not sending-collectible?
5550
{:content-type :account-switcher
5651
:customization-color color

src/status_im/contexts/wallet/effects.cljs

+7
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,10 @@
123123
(-> (sign-transaction-hashes hashes address password)
124124
(promesa/then on-success)
125125
(promesa/catch on-error))))
126+
127+
(rf/reg-fx
128+
:effects.wallet/sign-message
129+
(fn [{:keys [message address password on-success on-error]}]
130+
(-> (wallet-rpc/sign-message message address (security/safe-unmask-data password))
131+
(promesa/then on-success)
132+
(promesa/catch on-error))))

src/status_im/contexts/wallet/rpc.cljs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
chain-id
4848
constants/transaction-pending-type-wallet-connect-transfer
4949
(transforms/js-stringify tx-args 0)
50-
signature))
50+
(utils.hex/normalize-hex signature)))
5151

5252
(defn sign-message
5353
[message address password]

src/status_im/contexts/wallet/wallet_connect/events/effects.cljs

+21-44
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
(ns status-im.contexts.wallet.wallet-connect.events.effects
22
(:require
3+
[native-module.core :as native-module]
34
[promesa.core :as promesa]
45
[react-native.wallet-connect :as wallet-connect]
56
[status-im.config :as config]
67
[status-im.constants :as constants]
8+
[status-im.contexts.wallet.rpc :as wallet-rpc]
79
[status-im.contexts.wallet.wallet-connect.utils.sessions :as sessions]
8-
[status-im.contexts.wallet.wallet-connect.utils.signing :as signing]
910
[status-im.contexts.wallet.wallet-connect.utils.transactions :as transactions]
10-
[status-im.contexts.wallet.wallet-connect.utils.typed-data :as typed-data]
1111
[utils.i18n :as i18n]
1212
[utils.re-frame :as rf]
13-
[utils.security.core :as security]))
13+
[utils.transforms :as transforms]))
1414

1515
(rf/reg-fx
1616
:effects.wallet-connect/init
@@ -69,20 +69,21 @@
6969
(promesa/catch (partial rf/call-continuation on-fail)))))
7070

7171
(rf/reg-fx
72-
:effects.wallet-connect/sign-message
73-
(fn [{:keys [password address data rpc-method on-success on-error]}]
74-
(let [password (security/safe-unmask-data password)]
75-
(-> (condp =
76-
rpc-method
77-
:personal-sign
78-
(signing/personal-sign password address data)
79-
80-
:eth-sign
81-
(signing/eth-sign password address data)
72+
:effects.wallet-connect/hash-message
73+
(fn [{:keys [message on-success on-fail]}]
74+
(-> (wallet-rpc/hash-message-eip-191 message)
75+
(promesa/then (partial rf/call-continuation on-success))
76+
(promesa/catch (partial rf/call-continuation on-fail)))))
8277

83-
(signing/personal-sign password address data))
84-
(promesa/then (partial rf/call-continuation on-success))
85-
(promesa/catch (partial rf/call-continuation on-error))))))
78+
(rf/reg-fx
79+
:effects.wallet-connect/hash-typed-data
80+
(fn [{:keys [message legacy? on-success on-fail]}]
81+
(-> (if legacy?
82+
(native-module/hash-typed-data message)
83+
(native-module/hash-typed-data-v4 message))
84+
(promesa/then (fn [response] (-> response transforms/json->clj :result)))
85+
(promesa/then (partial rf/call-continuation on-success))
86+
(promesa/catch (partial rf/call-continuation on-fail)))))
8687

8788
(rf/reg-fx
8889
:effects.wallet-connect/prepare-transaction
@@ -93,36 +94,12 @@
9394
(promesa/then on-success)
9495
(promesa/catch on-error))))
9596

96-
(rf/reg-fx
97-
:effects.wallet-connect/sign-transaction
98-
(fn [{:keys [password address chain-id tx-hash tx-args on-success on-error]}]
99-
(-> (transactions/sign-transaction (security/safe-unmask-data password)
100-
address
101-
tx-hash
102-
tx-args
103-
chain-id)
104-
(promesa/then (partial rf/call-continuation on-success))
105-
(promesa/catch (partial rf/call-continuation on-error)))))
106-
10797
(rf/reg-fx
10898
:effects.wallet-connect/send-transaction
109-
(fn [{:keys [password address chain-id tx-hash tx-args on-success on-error]}]
110-
(-> (transactions/send-transaction (security/safe-unmask-data password)
111-
address
112-
tx-hash
113-
tx-args
114-
chain-id)
115-
(promesa/then (partial rf/call-continuation on-success))
116-
(promesa/catch (partial rf/call-continuation on-error)))))
117-
118-
(rf/reg-fx
119-
:effects.wallet-connect/sign-typed-data
120-
(fn [{:keys [password address data version chain-id on-success on-error]}]
121-
(-> (typed-data/sign (security/safe-unmask-data password)
122-
address
123-
data
124-
chain-id
125-
version)
99+
(fn [{:keys [chain-id signature tx-args on-success on-error]}]
100+
(-> (wallet-rpc/send-transaction-with-signature chain-id
101+
tx-args
102+
signature)
126103
(promesa/then (partial rf/call-continuation on-success))
127104
(promesa/catch (partial rf/call-continuation on-error)))))
128105

src/status_im/contexts/wallet/wallet_connect/events/session_proposals.cljs

+1-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
(:require [clojure.string :as string]
33
[re-frame.core :as rf]
44
[react-native.wallet-connect :as wallet-connect]
5-
[status-im.contexts.wallet.data-store :as wallet-data-store]
65
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
76
data-store]
87
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
@@ -46,15 +45,8 @@
4645
expired? (-> parsed-uri
4746
:expiryTimestamp
4847
uri/timestamp-expired?)
49-
version-supported? (uri/version-supported? version)
50-
keycard? (wallet-data-store/selected-keypair-keycard? db)]
48+
version-supported? (uri/version-supported? version)]
5149
(cond
52-
53-
keycard?
54-
{:fx [[:dispatch
55-
[:keycard/feature-unavailable-show
56-
{:feature-name :wallet.scan-dapp-connection}]]]}
57-
5850
(or (not valid-wc-uri?)
5951
(not version-supported?)
6052
(= network-status :offline)

src/status_im/contexts/wallet/wallet_connect/events/session_requests.cljs

+28-41
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,6 @@
4141
[:wallet-connect/process-eth-send-transaction
4242
{:on-success (fn [] (rf/dispatch [:wallet-connect/show-request-modal]))}]]
4343

44-
constants/wallet-connect-eth-sign-method
45-
[:dispatch [:wallet-connect/process-eth-sign]]
46-
47-
constants/wallet-connect-eth-sign-transaction-method
48-
[:dispatch [:wallet-connect/process-eth-sign-transaction]]
49-
5044
constants/wallet-connect-eth-sign-typed-method
5145
[:dispatch [:wallet-connect/process-sign-typed]]
5246

@@ -57,46 +51,44 @@
5751
[:dispatch [:wallet-connect/process-personal-sign]])]}))))
5852

5953
(rf/reg-event-fx
60-
:wallet-connect/process-personal-sign
61-
(fn [{:keys [db]}]
62-
(let [[raw-data address] (data-store/get-db-current-request-params db)
63-
parsed-data (native-module/hex-to-utf8 raw-data)]
64-
{:db (update-in db
65-
[:wallet-connect/current-request]
66-
assoc
67-
:address (string/lower-case address)
68-
:raw-data raw-data
69-
:display-data (or parsed-data raw-data))
70-
:fx [[:dispatch [:wallet-connect/show-request-modal]]]})))
54+
:wallet-connect/store-prepared-hash
55+
(fn [{:keys [db]} [prepared-hash]]
56+
{:db (assoc-in db
57+
[:wallet-connect/current-request :prepared-hash]
58+
prepared-hash)}))
7159

7260
(rf/reg-event-fx
73-
:wallet-connect/process-eth-sign
61+
:wallet-connect/process-personal-sign
7462
(fn [{:keys [db]}]
75-
(let [[address raw-data] (data-store/get-db-current-request-params db)
63+
(let [[raw-data address] (data-store/get-db-current-request-params db)
7664
parsed-data (native-module/hex-to-utf8 raw-data)]
7765
{:db (update-in db
7866
[:wallet-connect/current-request]
7967
assoc
8068
:address (string/lower-case address)
81-
:raw-data raw-data
8269
:display-data (or parsed-data raw-data))
83-
:fx [[:dispatch [:wallet-connect/show-request-modal]]]})))
70+
:fx [[:effects.wallet-connect/hash-message
71+
{:message raw-data
72+
:on-success #(rf/dispatch [:wallet-connect/store-prepared-hash %])
73+
:on-fail #(rf/dispatch [:wallet-connect/on-processing-error %])}]
74+
[:dispatch [:wallet-connect/show-request-modal]]]})))
8475

8576
(rf/reg-event-fx
8677
:wallet-connect/prepare-transaction-success
8778
(fn [{:keys [db]} [prepared-tx chain-id]]
88-
(let [{:keys [tx-args]} prepared-tx
89-
tx (bean/->clj tx-args)
90-
address (-> tx :from string/lower-case)
91-
display-data (transactions/beautify-transaction tx)]
79+
(let [{:keys [tx-args tx-hash]} prepared-tx
80+
tx (bean/->clj tx-args)
81+
address (-> tx :from string/lower-case)
82+
display-data (transactions/beautify-transaction tx)]
9283
{:db (update-in db
9384
[:wallet-connect/current-request]
9485
assoc
9586
:address address
9687
:raw-data prepared-tx
9788
:transaction tx
9889
:chain-id chain-id
99-
:display-data display-data)})))
90+
:display-data display-data)
91+
:fx [[:dispatch [:wallet-connect/store-prepared-hash tx-hash]]]})))
10092

10193
(rf/reg-event-fx
10294
:wallet-connect/process-eth-send-transaction
@@ -116,25 +108,14 @@
116108
(rf/call-continuation on-success)))
117109
:on-error #(rf/dispatch [:wallet-connect/on-processing-error %])}]]}))))
118110

119-
(rf/reg-event-fx
120-
:wallet-connect/process-eth-sign-transaction
121-
(fn [{:keys [db]}]
122-
(let [event (data-store/get-db-current-request-event db)
123-
tx (-> event data-store/get-request-params first)
124-
chain-id (-> event
125-
(get-in [:params :chainId])
126-
networks/eip155->chain-id)]
127-
{:fx [[:effects.wallet-connect/prepare-transaction
128-
{:tx tx
129-
:chain-id chain-id
130-
:on-success #(rf/dispatch [:wallet-connect/prepare-transaction-success % chain-id])
131-
:on-error #(rf/dispatch [:wallet-connect/on-processing-error %])}]]})))
132-
133111
(rf/reg-event-fx
134112
:wallet-connect/process-sign-typed
135113
(fn [{:keys [db]}]
136114
(try
137115
(let [[address raw-data] (data-store/get-db-current-request-params db)
116+
method (-> db
117+
data-store/get-db-current-request-event
118+
data-store/get-request-method)
138119
session-chain-id (-> (data-store/get-db-current-request-event db)
139120
(get-in [:params :chainId])
140121
networks/eip155->chain-id)
@@ -154,7 +135,13 @@
154135
:address (string/lower-case address)
155136
:display-data (typed-data/flatten-typed-data typed-data)
156137
:raw-data raw-data)
157-
:fx [[:dispatch [:wallet-connect/show-request-modal]]]}))
138+
:fx [[:effects.wallet-connect/hash-typed-data
139+
{:message raw-data
140+
:legacy? (not= constants/wallet-connect-eth-sign-typed-v4-method
141+
method)
142+
:on-success #(rf/dispatch [:wallet-connect/store-prepared-hash %])
143+
:on-fail #(rf/dispatch [:wallet-connect/on-processing-error %])}]
144+
[:dispatch [:wallet-connect/show-request-modal]]]}))
158145
(catch js/Error err
159146
{:fx [[:dispatch
160147
[:wallet-connect/on-processing-error

0 commit comments

Comments
 (0)