Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add web3.keycard.signTypedData #9390

Merged
merged 1 commit into from
Apr 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
10 changes: 7 additions & 3 deletions src/status_im/browser/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,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 @@ -347,6 +350,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 @@ -225,8 +225,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
37 changes: 37 additions & 0 deletions src/status_im/hardwallet/card.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -423,3 +423,40 @@
(re-frame/dispatch
[:hardwallet.callback/on-sign-error
(error-object->map response)])))})))

(defn install-cash-applet []
(log/info "[keycard] install-cash-applet")
(keycard/install-cash-applet
card
{:on-success
(fn [response]
(log/info "[keycard response succ] install-cash-applet"
(js->clj response :keywordize-keys true))
(re-frame/dispatch
[:hardwallet.callback/on-install-applet-success response]))
:on-failure
(fn [response]
(log/info "[keycard response fail] install-cash-applet"
(error-object->map response))
(re-frame/dispatch
[:hardwallet.callback/on-install-applet-error
(error-object->map response)]))}))

(defn sign-typed-data
[{:keys [hash] :as args}]
(log/info "[keycard] sign-typed-data" args)
(keycard/sign-typed-data
card
{:hash hash
:on-success
(fn [response]
(log/info "[keycard response succ] sign-typed-data" (js->clj response :keywordize-keys true))
(re-frame/dispatch [:hardwallet.callback/on-sign-success
response]))
:on-failure
(fn [response]
(log/info "[keycard response fail] sign-typed-data"
(error-object->map response))
(re-frame/dispatch
[:hardwallet.callback/on-sign-error
(error-object->map response)]))}))
2 changes: 1 addition & 1 deletion src/status_im/hardwallet/common.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@
[{:keys [db] :as cofx} error]
(log/debug "[hardwallet] application info error " error)
(let [on-card-read (get-in db [:hardwallet :on-card-read])
on-card-connected (get-in db [:hardwallet :on-card-conncted])
on-card-connected (get-in db [:hardwallet :on-card-connected])
login? (= on-card-read :hardwallet/login-with-keycard)
tag-was-lost? (tag-lost? (:error error))]
(when-not tag-was-lost?
Expand Down
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
4 changes: 3 additions & 1 deletion src/status_im/hardwallet/keycard.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
(remove-event-listeners [this])
(get-application-info [this args])
(install-applet [this args])
(install-cash-applet [this args])
(init-card [this args])
(install-applet-and-init-card [this args])
(pair [this args])
Expand All @@ -26,4 +27,5 @@
(export-key [this args])
(unpair-and-delete [this args])
(get-keys [this args])
(sign [this args]))
(sign [this args])
(sign-typed-data [this args]))
20 changes: 19 additions & 1 deletion src/status_im/hardwallet/real_keycard.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@
(then on-success)
(catch on-failure)))

(defn install-cash-applet [{:keys [on-success on-failure]}]
(.. status-keycard
installCashApplet
(then on-success)
(catch on-failure)))

(defn init-card [{:keys [pin on-success on-failure]}]
(.. status-keycard
(init pin)
Expand Down Expand Up @@ -178,6 +184,14 @@
(then on-success)
(catch on-failure))))

(defn sign-typed-data
[{:keys [hash on-success on-failure]}]
(when hash
(.. status-keycard
(signPinless hash)
(then on-success)
(catch on-failure))))

(defrecord RealKeycard []
keycard/Keycard
(keycard/check-nfc-support [this args]
Expand All @@ -200,6 +214,8 @@
(get-application-info args))
(keycard/install-applet [this args]
(install-applet args))
(keycard/install-cash-applet [this args]
(install-cash-applet args))
(keycard/init-card [this args]
(init-card args))
(keycard/install-applet-and-init-card [this args]
Expand Down Expand Up @@ -231,4 +247,6 @@
(keycard/get-keys [this args]
(get-keys args))
(keycard/sign [this args]
(sign args)))
(sign args))
(keycard/sign-typed-data [this args]
(sign-typed-data args)))
60 changes: 60 additions & 0 deletions src/status_im/hardwallet/sign.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.hardwallet.card :as card]
[status-im.utils.fx :as fx]
[status-im.utils.money :as money]
[status-im.utils.types :as types]
[taoensso.timbre :as log]
[status-im.hardwallet.common :as common]))
Expand Down Expand Up @@ -74,6 +77,63 @@
(common/get-application-info (common/get-pairing db) nil)
(common/hide-connection-sheet)))

(def sign-typed-data-listener (atom nil))

(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?
(do
(when @sign-typed-data-listener
(card/remove-event-listener @sign-typed-data-listener))
{: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)}})
(do
(reset! sign-typed-data-listener
(card/on-card-connected #(re-frame/dispatch [:hardwallet/sign-typed-data])))
(fx/merge cofx
(common/set-on-card-connected :hardwallet/sign-typed-data)
{:db (assoc-in db [:signing/sign :keycard-step] :signing)})))))

(fx/defn fetch-currency-symbol-on-success
{:events [:hardwallet/fetch-currency-symbol-on-success]}
[{:keys [db] :as cofx} currency]
{:db (assoc-in db [:signing/sign :formatted-data :message :formatted-currency] currency)})

(fx/defn fetch-currency-decimals-on-success
{:events [:hardwallet/fetch-currency-decimals-on-success]}
[{:keys [db] :as cofx} decimals]
{:db (update-in db [:signing/sign :formatted-data :message]
#(assoc % :formatted-amount (.dividedBy (money/bignumber (:amount %))
(money/bignumber (money/from-decimal decimals)))))})

(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)
message (get-in db [:signing/sign :formatted-data :message])
currency-contract (:currency message)]
(when-not (or (:receiver message) (:code message))
(json-rpc/eth-call {:contract currency-contract
:method "decimals()"
:outputs ["uint8"]
:on-success (fn [[decimals]]
(re-frame/dispatch [:hardwallet/fetch-currency-decimals-on-success decimals]))})

(json-rpc/eth-call {:contract currency-contract
:method "symbol()"
:outputs ["string"]
:on-success (fn [[currency]]
(re-frame/dispatch [:hardwallet/fetch-currency-symbol-on-success currency]))}))

(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
2 changes: 2 additions & 0 deletions src/status_im/hardwallet/simulated_keycard.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
(later #(on-success (get @state :application-info))))

(defn install-applet [args])
(defn install-cash-applet [args])

(def kk1-password "6d9ZHjn94kFP4bPm")

Expand Down Expand Up @@ -121,6 +122,7 @@
(defn unpair-and-delete [args])
(defn get-keys [args])
(defn sign [args])
(defn sign-typed-data [args])

(defrecord SimulatedKeycard []
keycard/Keycard
Expand Down
46 changes: 33 additions & 13 deletions src/status_im/signing/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
[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.hardwallet.common :as hardwallet.common]
Expand Down Expand Up @@ -179,17 +180,26 @@

(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 {:data data
:typed? true
:on-completed #(re-frame/dispatch [:hardwallet/store-hash-and-sign-typed %])})))
(fx/merge
cofx
{:db (assoc updated-db
Expand Down Expand Up @@ -295,26 +305,36 @@
(when on-error
{:dispatch (conj on-error message)})))))

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

(fx/defn sign-message-completed
{:events [:signing/sign-message-completed]}
[{:keys [db] :as cofx} result]
(let [{:keys [result error]} (types/json->clj result)
on-result (get-in db [:signing/tx :on-result])]
(if error
{:db (update db :signing/sign assoc
:error (if (= 5 (:code error)) (i18n/label :t/wrong-password) (:message error))
:in-progress? false)}
{:db (-> db
(assoc-in [:signing/sign :error] (if (= 5 (:code error)) (i18n/label :t/wrong-password) (:message error)))
(assoc :signing/in-progress? false))}
(fx/merge cofx
{:db (dissoc db :signing/tx :signing/in-progress? :signing/sign)}
(check-queue)
(when-not (= (-> db :signing/sign :type) :pinless)
(dissoc-signing-db-entries-and-check-queue))
#(when (= (-> db :signing/sign :type) :pinless)
{:dispatch-later [{:ms 3000
:dispatch [:signing/dissoc-entries-and-check-queue]}]})
#(when on-result
{:dispatch (conj on-result result)})))))

(fx/defn transaction-completed
{:events [:signing/transaction-completed]
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
[cofx response tx-obj hashed-password]
(let [cofx-in-progress-false (assoc-in cofx [:db :signing/sign :in-progress?] false)
(let [cofx-in-progress-false (assoc-in cofx [:db :signing/in-progress?] false)
{:keys [result error]} (types/json->clj response)]
(log/debug "transaction-completed" error tx-obj)
(if error
Expand Down
17 changes: 9 additions & 8 deletions src/status_im/signing/keycard.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,12 @@
{: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 :type] :keycard)
(assoc-in [:signing/sign :keycard-step] :pin))}
(if message
(hash-message message nil)
(hash-transaction)))))
Loading