Skip to content

Commit

Permalink
Add web3.keycard.signTypedData
Browse files Browse the repository at this point in the history
  • Loading branch information
Vitaliy Vlasov committed Feb 18, 2020
1 parent a2af83f commit 33b993a
Show file tree
Hide file tree
Showing 25 changed files with 319 additions and 73 deletions.
Binary file added android/app/src/main/res/drawable-hdpi/nfc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/app/src/main/res/drawable-mdpi/nfc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/app/src/main/res/drawable-xhdpi/nfc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/app/src/main/res/drawable-xxhdpi/nfc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions externs.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ var TopLevel = {
"injectJavaScript" : function () {},
"installApplet" : function () {},
"installAppletAndInitCard" : function () {},
"installCashApplet" : function () {},
"Int8Array" : function () {},
"integer" : function () {},
"interpolate" : function () {},
Expand Down Expand Up @@ -491,6 +492,7 @@ var TopLevel = {
"sign" : function () {},
"signGroupMembership" : function () {},
"signMessage" : function () {},
"signPinless" : function () {},
"signTypedData" : function () {},
"slice" : function () {},
"SplashScreen" : function () {},
Expand Down
23 changes: 23 additions & 0 deletions ios/StatusIm/Images.xcassets/nfc.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "nfc.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "nfc-1.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "nfc-2.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ios/StatusIm/Images.xcassets/nfc.imageset/nfc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@
:optimize-constants true
:optimizations :advanced
:stable-names true
:pseudo-names false
:pseudo-names true
:pretty-print false
:closure-defines {"goog.DEBUG" false}
:parallel-build false
Expand Down
10 changes: 7 additions & 3 deletions src/status_im/browser/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,12 @@
(when (or (not message?) (and address data))
(signing/sign cofx (merge
(if message?
{:message {:address address :data data :typed? (not= constants/web3-personal-sign method)
:from dapps-address}}
{:tx-obj (update (first params) :from #(or % dapps-address))})
{:message {:address address
:data data
:typed? (not= constants/web3-personal-sign method)
:pinless? (= method constants/web3-keycard-sign-typed-data)
:from dapps-address}}
{:tx-obj (update (first params) :from #(or % dapps-address))})
{:on-result [:browser.dapp/transaction-on-result message-id id]
:on-error [:browser.dapp/transaction-on-error message-id]}))))
(if (#{"eth_accounts" "eth_coinbase"} method)
Expand All @@ -349,6 +352,7 @@
[{:keys [db] :as cofx} dapp-name {:keys [method] :as payload} message-id]
(let [{:dapps/keys [permissions]} db]
(if (and (#{"eth_accounts" "eth_coinbase" "eth_sendTransaction" "eth_sign"
"keycard_signTypedData"
"eth_signTypedData" "personal_sign" "personal_ecRecover"} method)
(not (some #{constants/dapp-permission-web3} (get-in permissions [dapp-name :permissions]))))
(send-to-bridge cofx
Expand Down
6 changes: 5 additions & 1 deletion src/status_im/constants.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,12 @@
(def ^:const web3-shh-get-filter-changes "shh_getFilterChanges")
(def ^:const web3-shh-get-messages "shh_getMessages")

;; Keycard ns

(def ^:const web3-keycard-sign-typed-data "keycard_signTypedData")

(defn web3-sign-message? [method]
(#{web3-sign-typed-data web3-sign-typed-data-v3 web3-personal-sign} method))
(#{web3-sign-typed-data web3-sign-typed-data-v3 web3-personal-sign web3-keycard-sign-typed-data} method))

(def ^:const status-create-address "status_createaddress")

Expand Down
16 changes: 16 additions & 0 deletions src/status_im/hardwallet/card.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@
(then #(re-frame/dispatch [:hardwallet.callback/on-install-applet-success %]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-install-applet-error (error-object->map %)])))))

(defn install-cash-applet []
(log/debug "[keycard] install-cash-applet")
(when config/hardwallet-enabled?
(.. keycard
installCashApplet
(then #(re-frame/dispatch [:hardwallet.callback/on-install-applet-success %]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-install-applet-error (error-object->map %)])))))

(defn init-card [pin]
(log/debug "[keycard] init-card")
(when config/hardwallet-enabled?
Expand Down Expand Up @@ -207,3 +215,11 @@
(sign pairing pin hash)
(then #(re-frame/dispatch [:hardwallet.callback/on-sign-success %]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-sign-error (error-object->map %)])))))

(defn sign-typed-data
[{:keys [hash]}]
(when hash
(.. keycard
(signPinless hash)
(then #(re-frame/dispatch [:hardwallet.callback/on-sign-success %]))
(catch #(re-frame/dispatch [:hardwallet.callback/on-sign-error (error-object->map %)])))))
72 changes: 49 additions & 23 deletions src/status_im/hardwallet/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,28 @@
(when-not keycard-match?
(show-wrong-keycard-alert card-connected?))))))

(fx/defn sign-typed-data
{:events [:hardwallet/sign-typed-data]}
[{:keys [db] :as cofx}]
(let [card-connected? (get-in db [:hardwallet :card-connected?])
hash (get-in db [:hardwallet :hash])]
(if card-connected?
{:db (-> db
(assoc-in [:hardwallet :card-read-in-progress?] true)
(assoc-in [:signing/sign :keycard-step] :signing))
:hardwallet/sign-typed-data {:hash (ethereum/naked-address hash)}}
(fx/merge cofx
(set-on-card-connected :hardwallet/sign-typed-data)
{:db (assoc-in db [:signing/sign :keycard-step] :signing)}))))

(fx/defn store-hash-and-sign-typed
{:events [:hardwallet/store-hash-and-sign-typed]}
[{:keys [db] :as cofx} result]
(let [{:keys [result error]} (types/json->clj result)]
(fx/merge cofx
{:db (assoc-in db [:hardwallet :hash] result)}
sign-typed-data)))

(fx/defn prepare-to-sign
{:events [:hardwallet/prepare-to-sign]}
[{:keys [db] :as cofx}]
Expand Down Expand Up @@ -2026,15 +2048,16 @@
(fx/defn on-sign-success
{:events [:hardwallet.callback/on-sign-success]}
[{:keys [db] :as cofx} signature]
(log/debug "[hardwallet] sign success: " signature)
(log/info "[hardwallet] sign success: " signature)
(let [transaction (get-in db [:hardwallet :transaction])
tx-obj (select-keys transaction [:from :to :value :gas :gasPrice])]
(fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :pin :sign] [])
(assoc-in [:hardwallet :pin :status] nil)
(assoc-in [:hardwallet :hash] nil)
(assoc-in [:hardwallet :transaction] nil))}
(assoc-in [:hardwallet :transaction] nil)
(assoc-in [:signing/sign :keycard-step] :success))}
(clear-on-card-connected)
(get-application-info (get-pairing db) nil)
(if transaction
Expand All @@ -2046,25 +2069,28 @@
(fx/defn on-sign-error
[{:keys [db] :as cofx} error]
(log/debug "[hardwallet] sign error: " error)
(let [tag-was-lost? (= "Tag was lost." (:error error))]
(fx/merge cofx
(when tag-was-lost?
(fn [{:keys [db] :as cofx}]
(fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :pin :status] nil)
(assoc-in [:signing/sign :keycard-step] :connect))
:utils/show-popup {:title (i18n/label :t/error)
:content (i18n/label :t/cannot-read-card)}}
(set-on-card-connected :hardwallet/prepare-to-sign))))
(if (re-matches pin-mismatch-error (:error error))
(fn [{:keys [db] :as cofx}]
(fx/merge cofx
{:db (-> db
(update-in [:hardwallet :pin] merge {:status :error
:sign []
:error-label :t/pin-mismatch})
(assoc-in [:signing/sign :keycard-step] :pin))}
(get-application-info (get-pairing db) nil)))
(show-wrong-keycard-alert true)))))
(let [tag-was-lost? (= "Tag was lost." (:error error))
pinless? (= :pinless (get-in db [:signing/sign :type]))]
(fx/merge
cofx
(when tag-was-lost?
(fn [{:keys [db] :as cofx}]
(fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :pin :status] nil)
(assoc-in [:signing/sign :keycard-step] (when pinless? :error :connect)))
:utils/show-popup {:title (i18n/label :t/error)
:content (i18n/label :t/cannot-read-card)}}
(set-on-card-connected (if pinless? :hardwallet/sign-typed-data
:hardwallet/prepare-to-sign)))))
(if (re-matches pin-mismatch-error (:error error))
(fn [{:keys [db] :as cofx}]
(fx/merge cofx
{:db (-> db
(update-in [:hardwallet :pin] merge {:status :error
:sign []
:error-label :t/pin-mismatch})
(assoc-in [:signing/sign :keycard-step] :pin))}
(get-application-info (get-pairing db) nil)))
(show-wrong-keycard-alert true)))))

4 changes: 4 additions & 0 deletions src/status_im/hardwallet/fx.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@
:hardwallet/sign
card/sign)

(re-frame/reg-fx
:hardwallet/sign-typed-data
card/sign-typed-data)

(re-frame/reg-fx
:hardwallet/login-with-keycard
status/login-with-keycard)
Expand Down
34 changes: 26 additions & 8 deletions src/status_im/signing/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
[re-frame.core :as re-frame]
[status-im.constants :as constants]
[status-im.utils.config :as config]
[taoensso.timbre :as log]
[status-im.ethereum.abi-spec :as abi-spec]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.eip55 :as eip55]
[status-im.ethereum.tokens :as tokens]
[status-im.i18n :as i18n]
[status-im.signing.keycard :as signing.keycard]
[status-im.native-module.core :as status]
[status-im.utils.fx :as fx]
[status-im.utils.hex :as utils.hex]
Expand Down Expand Up @@ -174,17 +176,24 @@

(fx/defn show-sign [{:keys [db] :as cofx}]
(let [{:signing/keys [queue]} db
{{:keys [gas gasPrice] :as tx-obj} :tx-obj {:keys [data typed?] :as message} :message :as tx} (last queue)
{{:keys [gas gasPrice] :as tx-obj} :tx-obj {:keys [data typed? pinless?] :as message} :message :as tx} (last queue)
keycard-multiaccount? (boolean (get-in db [:multiaccount :keycard-pairing]))
wallet-set-up-passed? (get-in db [:multiaccount :wallet-set-up-passed?])
updated-db (if wallet-set-up-passed? db (assoc db :popover/popover {:view :signing-phrase}))]
(if message
{:db (assoc updated-db
:signing/in-progress? true
:signing/queue (drop-last queue)
:signing/tx tx
:signing/sign {:type (if keycard-multiaccount? :keycard :password)
:formatted-data (if typed? (types/json->clj data) (ethereum/hex-to-utf8 data))})}
(fx/merge
cofx
{:db (assoc updated-db
:signing/in-progress? true
:signing/queue (drop-last queue)
:signing/tx tx
:signing/sign {:type (cond pinless? :pinless
keycard-multiaccount? :keycard
:else :password)
:formatted-data (if typed? (types/json->clj data) (ethereum/hex-to-utf8 data))
:keycard-step (when pinless? :connect)})}
(when pinless?
(signing.keycard/hash-message message :hardwallet/store-hash-and-sign-typed)))
(fx/merge
cofx
{:db
Expand Down Expand Up @@ -277,6 +286,11 @@
(when on-error
{:dispatch (conj on-error message)})))))

(fx/defn dissoc-signing-db-entries
{:events [:signing/dissoc-entries]}
[{:keys [db] :as cofx}]
{:db (dissoc db :signing/tx :signing/in-progress? :signing/sign)})

(fx/defn sign-message-completed
{:events [:signing/sign-message-completed]}
[{:keys [db] :as cofx} result]
Expand All @@ -285,7 +299,11 @@
(if error
{:db (update db :signing/sign assoc :error (i18n/label :t/wrong-password) :in-progress? false)}
(fx/merge cofx
{:db (dissoc db :signing/tx :signing/in-progress? :signing/sign)}
(when-not (= (-> db :signing/sign :type) :pinless)
dissoc-signing-db-entries)
#(when (= (-> db :signing/sign :type) :pinless)
{:dispatch-later [{:ms 3000
:dispatch [:signing/dissoc-entries]}]})
(check-queue)
#(if on-result
{:dispatch (conj on-result result)})))))
Expand Down
22 changes: 11 additions & 11 deletions src/status_im/signing/keycard.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@
(assoc :nonce nonce))))

(fx/defn hash-message
[_ {:keys [data typed?]}]
[_ {:keys [data typed?]} callback-event]
(if typed?
{::hash-typed-data {:data data
:on-completed #(re-frame/dispatch [:signing.keycard.callback/hash-message-completed %])}}
:on-completed #(re-frame/dispatch [(or callback-event :signing.keycard.callback/hash-message-completed) %])}}
{::hash-message {:message (ethereum/naked-address data)
:on-completed #(re-frame/dispatch [:signing.keycard.callback/hash-message-completed %])}}))
:on-completed #(re-frame/dispatch [(or callback-event :signing.keycard.callback/hash-message-completed) %])}}))

(fx/defn hash-message-completed
{:events [:signing.keycard.callback/hash-message-completed]}
Expand All @@ -66,11 +66,11 @@
{:events [:signing.ui/sign-with-keycard-pressed]}
[{:keys [db] :as cofx}]
(let [message (get-in db [:signing/tx :message])]
(fx/merge cofx
{:db (-> db
(assoc-in [:hardwallet :pin :enter-step] :sign)
(assoc-in [:signing/sign :keycard-step] :pin)
(assoc-in [:signing/sign :type] :keycard))}
(if message
(hash-message message)
(hash-transaction)))))
(fx/merge
cofx
{:db (-> db
(assoc-in [:hardwallet :pin :enter-step] :sign)
(assoc-in [:signing/sign :keycard-step] :pin))}
(if message
(hash-message message nil)
(hash-transaction)))))
16 changes: 15 additions & 1 deletion src/status_im/subs.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,6 @@

;;signing
(reg-root-key-sub :signing/tx :signing/tx)
(reg-root-key-sub :signing/sign :signing/sign)
(reg-root-key-sub :signing/edit-fee :signing/edit-fee)

;;intro-wizard
Expand Down Expand Up @@ -2045,6 +2044,21 @@
(fn [{:keys [signing-phrase]}]
signing-phrase))

(re-frame/reg-sub
:signing/sign
(fn [db]
(let [sign (:signing/sign db)]
(if (= :pinless (:type sign))
(let [message (get-in sign [:formatted-data :message])]
(if (and (:amount message) (:currency message))
(assoc sign :fiat-amount
(money/fiat-amount-value (:amount message)
(:currency message)
:USD (:prices db))
:fiat-currency "USD")
sign))
sign))))

(defn- too-precise-amount?
"Checks if number has any extra digit beyond the allowed number of decimals.
It does so by checking the number against its rounded value."
Expand Down
22 changes: 11 additions & 11 deletions src/status_im/ui/components/button.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
Spec: https://www.figma.com/file/cb4p8AxLtTF3q1L6JYDnKN15/Index?node-id=858%3A0"

[{:keys [label type theme disabled? on-press accessibility-label style container-style] :or {type :main theme :blue}}]
[{:keys [label type theme disabled? on-press accessibility-label style label-style container-style] :or {type :main theme :blue}}]
(let [label (utils.label/stringify label)]
[react/touchable-opacity (cond-> {:on-press on-press
:active-opacity 0.5
Expand All @@ -66,16 +66,16 @@
(when (= type :previous)
[vector-icons/icon :main-icons/back {:container-style {:width 24 :height 24 :margin-right 4}
:color (if disabled? colors/gray colors/blue)}])
[react/text {:style {:color (cond
disabled?
colors/gray
(#{:main :secondary :next :previous} type)
(case theme
:green colors/green
:red colors/red
colors/blue)
:else
"")}}
[react/text {:style (merge {:color (cond
disabled?
colors/gray
(#{:main :secondary :next :previous} type)
(case theme
:green colors/green
:red colors/red
colors/blue)
:else
"")} label-style)}
label]
(when (= type :next)
[vector-icons/icon :main-icons/next {:container-style {:width 24 :height 24 :margin-left 4}
Expand Down
Loading

0 comments on commit 33b993a

Please sign in to comment.