Add web3.keycard.signTypedData
Signed-off-by: Vitaliy Vlasov <siphiuel@gmail.com>
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 940 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 3.2 KiB |
|
@ -218,6 +218,7 @@ var TopLevel = {
|
||||||
"injectJavaScript" : function () {},
|
"injectJavaScript" : function () {},
|
||||||
"installApplet" : function () {},
|
"installApplet" : function () {},
|
||||||
"installAppletAndInitCard" : function () {},
|
"installAppletAndInitCard" : function () {},
|
||||||
|
"installCashApplet" : function () {},
|
||||||
"Int8Array" : function () {},
|
"Int8Array" : function () {},
|
||||||
"integer" : function () {},
|
"integer" : function () {},
|
||||||
"interpolate" : function () {},
|
"interpolate" : function () {},
|
||||||
|
@ -491,6 +492,7 @@ var TopLevel = {
|
||||||
"sign" : function () {},
|
"sign" : function () {},
|
||||||
"signGroupMembership" : function () {},
|
"signGroupMembership" : function () {},
|
||||||
"signMessage" : function () {},
|
"signMessage" : function () {},
|
||||||
|
"signPinless" : function () {},
|
||||||
"signTypedData" : function () {},
|
"signTypedData" : function () {},
|
||||||
"slice" : function () {},
|
"slice" : function () {},
|
||||||
"SplashScreen" : function () {},
|
"SplashScreen" : function () {},
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 940 B |
|
@ -325,9 +325,12 @@
|
||||||
(when (or (not message?) (and address data))
|
(when (or (not message?) (and address data))
|
||||||
(signing/sign cofx (merge
|
(signing/sign cofx (merge
|
||||||
(if message?
|
(if message?
|
||||||
{:message {:address address :data data :typed? (not= constants/web3-personal-sign method)
|
{:message {:address address
|
||||||
:from dapps-address}}
|
:data data
|
||||||
{:tx-obj (update (first params) :from #(or % dapps-address))})
|
: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-result [:browser.dapp/transaction-on-result message-id id]
|
||||||
:on-error [:browser.dapp/transaction-on-error message-id]}))))
|
:on-error [:browser.dapp/transaction-on-error message-id]}))))
|
||||||
(if (#{"eth_accounts" "eth_coinbase"} method)
|
(if (#{"eth_accounts" "eth_coinbase"} method)
|
||||||
|
@ -347,6 +350,7 @@
|
||||||
[{:keys [db] :as cofx} dapp-name {:keys [method] :as payload} message-id]
|
[{:keys [db] :as cofx} dapp-name {:keys [method] :as payload} message-id]
|
||||||
(let [{:dapps/keys [permissions]} db]
|
(let [{:dapps/keys [permissions]} db]
|
||||||
(if (and (#{"eth_accounts" "eth_coinbase" "eth_sendTransaction" "eth_sign"
|
(if (and (#{"eth_accounts" "eth_coinbase" "eth_sendTransaction" "eth_sign"
|
||||||
|
"keycard_signTypedData"
|
||||||
"eth_signTypedData" "personal_sign" "personal_ecRecover"} method)
|
"eth_signTypedData" "personal_sign" "personal_ecRecover"} method)
|
||||||
(not (some #{constants/dapp-permission-web3} (get-in permissions [dapp-name :permissions]))))
|
(not (some #{constants/dapp-permission-web3} (get-in permissions [dapp-name :permissions]))))
|
||||||
(send-to-bridge cofx
|
(send-to-bridge cofx
|
||||||
|
|
|
@ -225,8 +225,12 @@
|
||||||
(def ^:const web3-shh-get-filter-changes "shh_getFilterChanges")
|
(def ^:const web3-shh-get-filter-changes "shh_getFilterChanges")
|
||||||
(def ^:const web3-shh-get-messages "shh_getMessages")
|
(def ^:const web3-shh-get-messages "shh_getMessages")
|
||||||
|
|
||||||
|
;; Keycard ns
|
||||||
|
|
||||||
|
(def ^:const web3-keycard-sign-typed-data "keycard_signTypedData")
|
||||||
|
|
||||||
(defn web3-sign-message? [method]
|
(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")
|
(def ^:const status-create-address "status_createaddress")
|
||||||
|
|
||||||
|
|
|
@ -423,3 +423,40 @@
|
||||||
(re-frame/dispatch
|
(re-frame/dispatch
|
||||||
[:hardwallet.callback/on-sign-error
|
[:hardwallet.callback/on-sign-error
|
||||||
(error-object->map response)])))})))
|
(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)]))}))
|
||||||
|
|
|
@ -411,7 +411,7 @@
|
||||||
[{:keys [db] :as cofx} error]
|
[{:keys [db] :as cofx} error]
|
||||||
(log/debug "[hardwallet] application info error " error)
|
(log/debug "[hardwallet] application info error " error)
|
||||||
(let [on-card-read (get-in db [:hardwallet :on-card-read])
|
(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)
|
login? (= on-card-read :hardwallet/login-with-keycard)
|
||||||
tag-was-lost? (tag-lost? (:error error))]
|
tag-was-lost? (tag-lost? (:error error))]
|
||||||
(when-not tag-was-lost?
|
(when-not tag-was-lost?
|
||||||
|
|
|
@ -94,6 +94,10 @@
|
||||||
:hardwallet/sign
|
:hardwallet/sign
|
||||||
card/sign)
|
card/sign)
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:hardwallet/sign-typed-data
|
||||||
|
card/sign-typed-data)
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
:hardwallet/login-with-keycard
|
:hardwallet/login-with-keycard
|
||||||
status/login-with-keycard)
|
status/login-with-keycard)
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
(remove-event-listeners [this])
|
(remove-event-listeners [this])
|
||||||
(get-application-info [this args])
|
(get-application-info [this args])
|
||||||
(install-applet [this args])
|
(install-applet [this args])
|
||||||
|
(install-cash-applet [this args])
|
||||||
(init-card [this args])
|
(init-card [this args])
|
||||||
(install-applet-and-init-card [this args])
|
(install-applet-and-init-card [this args])
|
||||||
(pair [this args])
|
(pair [this args])
|
||||||
|
@ -26,4 +27,5 @@
|
||||||
(export-key [this args])
|
(export-key [this args])
|
||||||
(unpair-and-delete [this args])
|
(unpair-and-delete [this args])
|
||||||
(get-keys [this args])
|
(get-keys [this args])
|
||||||
(sign [this args]))
|
(sign [this args])
|
||||||
|
(sign-typed-data [this args]))
|
||||||
|
|
|
@ -59,6 +59,12 @@
|
||||||
(then on-success)
|
(then on-success)
|
||||||
(catch on-failure)))
|
(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]}]
|
(defn init-card [{:keys [pin on-success on-failure]}]
|
||||||
(.. status-keycard
|
(.. status-keycard
|
||||||
(init pin)
|
(init pin)
|
||||||
|
@ -178,6 +184,14 @@
|
||||||
(then on-success)
|
(then on-success)
|
||||||
(catch on-failure))))
|
(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 []
|
(defrecord RealKeycard []
|
||||||
keycard/Keycard
|
keycard/Keycard
|
||||||
(keycard/check-nfc-support [this args]
|
(keycard/check-nfc-support [this args]
|
||||||
|
@ -200,6 +214,8 @@
|
||||||
(get-application-info args))
|
(get-application-info args))
|
||||||
(keycard/install-applet [this args]
|
(keycard/install-applet [this args]
|
||||||
(install-applet args))
|
(install-applet args))
|
||||||
|
(keycard/install-cash-applet [this args]
|
||||||
|
(install-cash-applet args))
|
||||||
(keycard/init-card [this args]
|
(keycard/init-card [this args]
|
||||||
(init-card args))
|
(init-card args))
|
||||||
(keycard/install-applet-and-init-card [this args]
|
(keycard/install-applet-and-init-card [this args]
|
||||||
|
@ -231,4 +247,6 @@
|
||||||
(keycard/get-keys [this args]
|
(keycard/get-keys [this args]
|
||||||
(get-keys args))
|
(get-keys args))
|
||||||
(keycard/sign [this args]
|
(keycard/sign [this args]
|
||||||
(sign args)))
|
(sign args))
|
||||||
|
(keycard/sign-typed-data [this args]
|
||||||
|
(sign-typed-data args)))
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.ethereum.core :as ethereum]
|
[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.fx :as fx]
|
||||||
|
[status-im.utils.money :as money]
|
||||||
[status-im.utils.types :as types]
|
[status-im.utils.types :as types]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[status-im.hardwallet.common :as common]))
|
[status-im.hardwallet.common :as common]))
|
||||||
|
@ -74,6 +77,63 @@
|
||||||
(common/get-application-info (common/get-pairing db) nil)
|
(common/get-application-info (common/get-pairing db) nil)
|
||||||
(common/hide-connection-sheet)))
|
(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
|
(fx/defn prepare-to-sign
|
||||||
{:events [:hardwallet/prepare-to-sign]}
|
{:events [:hardwallet/prepare-to-sign]}
|
||||||
[{:keys [db] :as cofx}]
|
[{:keys [db] :as cofx}]
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
(later #(on-success (get @state :application-info))))
|
(later #(on-success (get @state :application-info))))
|
||||||
|
|
||||||
(defn install-applet [args])
|
(defn install-applet [args])
|
||||||
|
(defn install-cash-applet [args])
|
||||||
|
|
||||||
(def kk1-password "6d9ZHjn94kFP4bPm")
|
(def kk1-password "6d9ZHjn94kFP4bPm")
|
||||||
|
|
||||||
|
@ -121,6 +122,7 @@
|
||||||
(defn unpair-and-delete [args])
|
(defn unpair-and-delete [args])
|
||||||
(defn get-keys [args])
|
(defn get-keys [args])
|
||||||
(defn sign [args])
|
(defn sign [args])
|
||||||
|
(defn sign-typed-data [args])
|
||||||
|
|
||||||
(defrecord SimulatedKeycard []
|
(defrecord SimulatedKeycard []
|
||||||
keycard/Keycard
|
keycard/Keycard
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
[status-im.ethereum.eip55 :as eip55]
|
[status-im.ethereum.eip55 :as eip55]
|
||||||
[status-im.ethereum.tokens :as tokens]
|
[status-im.ethereum.tokens :as tokens]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.signing.keycard :as signing.keycard]
|
||||||
[status-im.native-module.core :as status]
|
[status-im.native-module.core :as status]
|
||||||
[status-im.utils.fx :as fx]
|
[status-im.utils.fx :as fx]
|
||||||
[status-im.hardwallet.common :as hardwallet.common]
|
[status-im.hardwallet.common :as hardwallet.common]
|
||||||
|
@ -179,17 +180,26 @@
|
||||||
|
|
||||||
(fx/defn show-sign [{:keys [db] :as cofx}]
|
(fx/defn show-sign [{:keys [db] :as cofx}]
|
||||||
(let [{:signing/keys [queue]} db
|
(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]))
|
keycard-multiaccount? (boolean (get-in db [:multiaccount :keycard-pairing]))
|
||||||
wallet-set-up-passed? (get-in db [:multiaccount :wallet-set-up-passed?])
|
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}))]
|
updated-db (if wallet-set-up-passed? db (assoc db :popover/popover {:view :signing-phrase}))]
|
||||||
(if message
|
(if message
|
||||||
{:db (assoc updated-db
|
(fx/merge
|
||||||
:signing/in-progress? true
|
cofx
|
||||||
:signing/queue (drop-last queue)
|
{:db (assoc updated-db
|
||||||
:signing/tx tx
|
:signing/in-progress? true
|
||||||
:signing/sign {:type (if keycard-multiaccount? :keycard :password)
|
:signing/queue (drop-last queue)
|
||||||
:formatted-data (if typed? (types/json->clj data) (ethereum/hex-to-utf8 data))})}
|
: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
|
(fx/merge
|
||||||
cofx
|
cofx
|
||||||
{:db (assoc updated-db
|
{:db (assoc updated-db
|
||||||
|
@ -295,18 +305,28 @@
|
||||||
(when on-error
|
(when on-error
|
||||||
{:dispatch (conj on-error message)})))))
|
{: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
|
(fx/defn sign-message-completed
|
||||||
{:events [:signing/sign-message-completed]}
|
{:events [:signing/sign-message-completed]}
|
||||||
[{:keys [db] :as cofx} result]
|
[{:keys [db] :as cofx} result]
|
||||||
(let [{:keys [result error]} (types/json->clj result)
|
(let [{:keys [result error]} (types/json->clj result)
|
||||||
on-result (get-in db [:signing/tx :on-result])]
|
on-result (get-in db [:signing/tx :on-result])]
|
||||||
(if error
|
(if error
|
||||||
{:db (update db :signing/sign assoc
|
{:db (-> db
|
||||||
:error (if (= 5 (:code error)) (i18n/label :t/wrong-password) (:message error))
|
(assoc-in [:signing/sign :error] (if (= 5 (:code error)) (i18n/label :t/wrong-password) (:message error)))
|
||||||
:in-progress? false)}
|
(assoc :signing/in-progress? false))}
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (dissoc db :signing/tx :signing/in-progress? :signing/sign)}
|
(when-not (= (-> db :signing/sign :type) :pinless)
|
||||||
(check-queue)
|
(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
|
#(when on-result
|
||||||
{:dispatch (conj on-result result)})))))
|
{:dispatch (conj on-result result)})))))
|
||||||
|
|
||||||
|
@ -314,7 +334,7 @@
|
||||||
{:events [:signing/transaction-completed]
|
{:events [:signing/transaction-completed]
|
||||||
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
|
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
|
||||||
[cofx response tx-obj hashed-password]
|
[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)]
|
{:keys [result error]} (types/json->clj response)]
|
||||||
(log/debug "transaction-completed" error tx-obj)
|
(log/debug "transaction-completed" error tx-obj)
|
||||||
(if error
|
(if error
|
||||||
|
|
|
@ -79,11 +79,12 @@
|
||||||
{:events [:signing.ui/sign-with-keycard-pressed]}
|
{:events [:signing.ui/sign-with-keycard-pressed]}
|
||||||
[{:keys [db] :as cofx}]
|
[{:keys [db] :as cofx}]
|
||||||
(let [message (get-in db [:signing/tx :message])]
|
(let [message (get-in db [:signing/tx :message])]
|
||||||
(fx/merge cofx
|
(fx/merge
|
||||||
{:db (-> db
|
cofx
|
||||||
(assoc-in [:hardwallet :pin :enter-step] :sign)
|
{:db (-> db
|
||||||
(assoc-in [:signing/sign :keycard-step] :pin)
|
(assoc-in [:hardwallet :pin :enter-step] :sign)
|
||||||
(assoc-in [:signing/sign :type] :keycard))}
|
(assoc-in [:signing/sign :type] :keycard)
|
||||||
(if message
|
(assoc-in [:signing/sign :keycard-step] :pin))}
|
||||||
(hash-message message)
|
(if message
|
||||||
(hash-transaction)))))
|
(hash-message message nil)
|
||||||
|
(hash-transaction)))))
|
||||||
|
|
|
@ -177,7 +177,6 @@
|
||||||
|
|
||||||
;;signing
|
;;signing
|
||||||
(reg-root-key-sub :signing/tx :signing/tx)
|
(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)
|
(reg-root-key-sub :signing/edit-fee :signing/edit-fee)
|
||||||
|
|
||||||
;;intro-wizard
|
;;intro-wizard
|
||||||
|
@ -2069,6 +2068,21 @@
|
||||||
(fn [{:keys [signing-phrase]}]
|
(fn [{:keys [signing-phrase]}]
|
||||||
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?
|
(defn- too-precise-amount?
|
||||||
"Checks if number has any extra digit beyond the allowed number of decimals.
|
"Checks if number has any extra digit beyond the allowed number of decimals.
|
||||||
It does so by checking the number against its rounded value."
|
It does so by checking the number against its rounded value."
|
||||||
|
|
|
@ -10,8 +10,9 @@
|
||||||
[status-im.ui.screens.profile.user.views :as profile.user]
|
[status-im.ui.screens.profile.user.views :as profile.user]
|
||||||
[status-im.ui.screens.multiaccounts.recover.views :as multiaccounts.recover]
|
[status-im.ui.screens.multiaccounts.recover.views :as multiaccounts.recover]
|
||||||
[status-im.react-native.js-dependencies :as js-dependencies]
|
[status-im.react-native.js-dependencies :as js-dependencies]
|
||||||
[status-im.ui.screens.biometric.views :as biometric]
|
[status-im.ui.components.colors :as colors]
|
||||||
[status-im.ui.components.colors :as colors]))
|
[status-im.ui.screens.signing.views :as signing]
|
||||||
|
[status-im.ui.screens.biometric.views :as biometric]))
|
||||||
|
|
||||||
(defn hide-panel-anim
|
(defn hide-panel-anim
|
||||||
[bottom-anim-value alpha-value window-height]
|
[bottom-anim-value alpha-value window-height]
|
||||||
|
@ -133,6 +134,9 @@
|
||||||
(= :disable-password-saving view)
|
(= :disable-password-saving view)
|
||||||
[biometric/disable-password-saving-popover]
|
[biometric/disable-password-saving-popover]
|
||||||
|
|
||||||
|
(= :transaction-data view)
|
||||||
|
[signing/transaction-data]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
[view])]]]]])))})))
|
[view])]]]]])))})))
|
||||||
|
|
||||||
|
|
|
@ -58,3 +58,22 @@
|
||||||
:color (if disabled? colors/black colors/white)
|
:color (if disabled? colors/black colors/white)
|
||||||
:padding-horizontal 16
|
:padding-horizontal 16
|
||||||
:padding-vertical 10})
|
:padding-vertical 10})
|
||||||
|
|
||||||
|
(defn sheet-title [small-screen?]
|
||||||
|
{:font-weight "500"
|
||||||
|
:font-size (if small-screen? 16 19)
|
||||||
|
:margin-top 16})
|
||||||
|
|
||||||
|
(defn sheet-subtitle [small-screen?]
|
||||||
|
{:font-size (if small-screen? 16 19)
|
||||||
|
:text-align :center
|
||||||
|
:margin-bottom 12
|
||||||
|
:color colors/gray})
|
||||||
|
|
||||||
|
(defn sheet-icon [bg-color]
|
||||||
|
{:height 64
|
||||||
|
:width 64
|
||||||
|
:border-radius 32
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:background-color bg-color})
|
||||||
|
|
|
@ -133,6 +133,105 @@
|
||||||
[react/view {:align-items :center :margin-top 16 :margin-bottom 40}
|
[react/view {:align-items :center :margin-top 16 :margin-bottom 40}
|
||||||
[sign-with-keycard-button nil nil]])])
|
[sign-with-keycard-button nil nil]])])
|
||||||
|
|
||||||
|
(defn signature-request [{:keys [error formatted-data
|
||||||
|
fiat-amount fiat-currency
|
||||||
|
keycard-step
|
||||||
|
in-progress? enabled?] :as sign} small-screen?]
|
||||||
|
(let [message (:message formatted-data)
|
||||||
|
title (case keycard-step
|
||||||
|
:connect :t/looking-for-cards
|
||||||
|
:signing :t/processing
|
||||||
|
:error :t/lost-connection
|
||||||
|
:success :t/success)
|
||||||
|
subtitle (case keycard-step
|
||||||
|
:connect :t/hold-card
|
||||||
|
:signing :t/try-keeping-the-card-still
|
||||||
|
:error :t/tap-card-again
|
||||||
|
:success :t/transaction-signed)]
|
||||||
|
[react/view (assoc styles/message :padding-vertical 16 :align-items :center)
|
||||||
|
[react/view {:style {:align-self :flex-start :padding-left 16 :margin-bottom 24}}
|
||||||
|
[react/text {:style {:font-size (if small-screen? 15 17) :font-weight "700"}}
|
||||||
|
(i18n/label :t/confirmation-request)]]
|
||||||
|
(when (and (:formatted-amount message) (:formatted-currency message))
|
||||||
|
[react/view {:style {:margin-bottom 24 :align-self :stretch}}
|
||||||
|
[react/nested-text {:style {:font-weight "500" :font-size (if small-screen? 34 44)
|
||||||
|
:text-align :center}}
|
||||||
|
(str (:formatted-amount message) " ")
|
||||||
|
[{:style {:color colors/gray}} (:formatted-currency message)]]
|
||||||
|
[react/text {:style {:font-size 19 :text-align :center
|
||||||
|
:margin-bottom 16}}
|
||||||
|
(str fiat-amount " " fiat-currency)]
|
||||||
|
[separator]])
|
||||||
|
[react/view {:style (styles/sheet-icon (case keycard-step
|
||||||
|
(:connect :signing) colors/blue-transparent-10
|
||||||
|
:error colors/red-transparent-10
|
||||||
|
:success colors/green-transparent-10))}
|
||||||
|
(case keycard-step
|
||||||
|
:connect
|
||||||
|
[icons/icon :main-icons/nfc {:color colors/blue :width 27 :height 21}]
|
||||||
|
:signing
|
||||||
|
[react/activity-indicator {:animating true :color colors/blue}]
|
||||||
|
:error
|
||||||
|
[icons/icon :main-icons/close {:color colors/red}]
|
||||||
|
:success
|
||||||
|
[icons/icon :main-icons/check {:color colors/green}])]
|
||||||
|
[react/text {:style (styles/sheet-title small-screen?)} (i18n/label title)]
|
||||||
|
[react/text {:style (styles/sheet-subtitle small-screen?)} (i18n/label subtitle)]
|
||||||
|
[button/button {:type :main
|
||||||
|
:disabled? (= keycard-step :success)
|
||||||
|
:text-style {:font-size (if small-screen? 18 20)}
|
||||||
|
:style {:align-self :stretch}
|
||||||
|
:container-style {:height (if small-screen? 52 64)}
|
||||||
|
:label (i18n/label :t/show-transaction-data)
|
||||||
|
:on-press #(re-frame/dispatch [:show-popover {:view :transaction-data}])}]
|
||||||
|
[button/button {:type :main
|
||||||
|
:theme :red
|
||||||
|
:disabled? (= keycard-step :success)
|
||||||
|
:container-style {:margin-top 8
|
||||||
|
:height 64 :margin-bottom 16}
|
||||||
|
:style {:align-self :stretch}
|
||||||
|
:text-style {:font-size 20}
|
||||||
|
:label (i18n/label :t/decline)
|
||||||
|
:on-press #(re-frame/dispatch [:signing.ui/cancel-is-pressed])}]]))
|
||||||
|
|
||||||
|
(defn- transaction-data-item [{:keys [label data]}]
|
||||||
|
[react/view
|
||||||
|
[react/text {:style {:font-size 17
|
||||||
|
:line-height 20
|
||||||
|
:margin-bottom 8
|
||||||
|
:color colors/gray}}
|
||||||
|
label]
|
||||||
|
[react/text {:style {:font-size 17
|
||||||
|
:line-height 20
|
||||||
|
:margin-bottom 24}}
|
||||||
|
data]])
|
||||||
|
|
||||||
|
(views/defview transaction-data []
|
||||||
|
(views/letsubs
|
||||||
|
[{:keys [formatted-data]} [:signing/sign]]
|
||||||
|
[react/view {:style {:flex 1}}
|
||||||
|
[react/view {:style {:margin-horizontal 24
|
||||||
|
:margin-top 24}}
|
||||||
|
[react/text {:style {:font-size 17
|
||||||
|
:font-weight "700"}}
|
||||||
|
(i18n/label :t/transaction-data)]]
|
||||||
|
[react/scroll-view {:style {:flex 1
|
||||||
|
:margin-horizontal 8
|
||||||
|
:padding-horizontal 16
|
||||||
|
:padding-vertical 10
|
||||||
|
:margin-vertical 14}}
|
||||||
|
[transaction-data-item {:label "Label"
|
||||||
|
:data formatted-data}]]
|
||||||
|
[separator]
|
||||||
|
[react/view {:style {:margin-horizontal 8
|
||||||
|
:margin-vertical 16}}
|
||||||
|
[button/button {:type :main
|
||||||
|
:text-style {:font-size 20}
|
||||||
|
:style {:margin-horizontal 0}
|
||||||
|
:container-style {:height 64}
|
||||||
|
:label (i18n/label :t/close)
|
||||||
|
:on-press #(re-frame/dispatch [:hide-popover])}]]]))
|
||||||
|
|
||||||
(views/defview password-view [{:keys [type error in-progress? enabled?] :as sign}]
|
(views/defview password-view [{:keys [type error in-progress? enabled?] :as sign}]
|
||||||
(views/letsubs [phrase [:signing/phrase]]
|
(views/letsubs [phrase [:signing/phrase]]
|
||||||
(case type
|
(case type
|
||||||
|
@ -160,19 +259,22 @@
|
||||||
[react/view])))
|
[react/view])))
|
||||||
|
|
||||||
(views/defview message-sheet []
|
(views/defview message-sheet []
|
||||||
(views/letsubs [{:keys [formatted-data type] :as sign} [:signing/sign]]
|
(views/letsubs [{:keys [formatted-data type] :as sign} [:signing/sign]
|
||||||
[react/view styles/message
|
small-screen? [:dimensions/small-screen?]]
|
||||||
[react/view styles/message-header
|
(if (= type :pinless)
|
||||||
[react/text {:style {:typography :title-bold}} (i18n/label :t/signing-a-message)]
|
[signature-request sign small-screen?]
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:signing.ui/cancel-is-pressed])}
|
[react/view styles/message
|
||||||
[react/view {:padding 6}
|
[react/view styles/message-header
|
||||||
[react/text {:style {:color colors/blue}} (i18n/label :t/cancel)]]]]
|
[react/text {:style {:typography :title-bold}} (i18n/label :t/signing-a-message)]
|
||||||
[separator]
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:signing.ui/cancel-is-pressed])}
|
||||||
[react/view {:padding-top 16 :flex 1}
|
[react/view {:padding 6}
|
||||||
[react/view styles/message-border
|
[react/text {:style {:color colors/blue}} (i18n/label :t/cancel)]]]]
|
||||||
[react/scroll-view
|
[separator]
|
||||||
[react/text (or formatted-data "")]]]
|
[react/view {:padding-top 16 :flex 1}
|
||||||
[password-view sign]]]))
|
[react/view styles/message-border
|
||||||
|
[react/scroll-view
|
||||||
|
[react/text (or formatted-data "")]]]
|
||||||
|
[password-view sign]]])))
|
||||||
|
|
||||||
(defn amount-item [prices wallet-currency amount amount-error display-symbol fee-display-symbol prices-loading?]
|
(defn amount-item [prices wallet-currency amount amount-error display-symbol fee-display-symbol prices-loading?]
|
||||||
(let [converted-value (* amount (get-in prices [(keyword display-symbol) (keyword (:code wallet-currency)) :price]))]
|
(let [converted-value (* amount (get-in prices [(keyword display-symbol) (keyword (:code wallet-currency)) :price]))]
|
||||||
|
|
|
@ -135,6 +135,7 @@
|
||||||
"clear-history-confirmation": "Clear history?",
|
"clear-history-confirmation": "Clear history?",
|
||||||
"clear-history-confirmation-content": "Are you sure you want to clear this chat history?",
|
"clear-history-confirmation-content": "Are you sure you want to clear this chat history?",
|
||||||
"clear-history-title": "Clear history?",
|
"clear-history-title": "Clear history?",
|
||||||
|
"close": "Close",
|
||||||
"close-app-button": "Confirm",
|
"close-app-button": "Confirm",
|
||||||
"close-app-content": "The app will stop and close. When you reopen it, the selected network will be used",
|
"close-app-content": "The app will stop and close. When you reopen it, the selected network will be used",
|
||||||
"close-app-title": "Warning!",
|
"close-app-title": "Warning!",
|
||||||
|
@ -142,6 +143,7 @@
|
||||||
"complete-hardwallet-setup": "This card is now an essential part your multiaccount security. Transactions can't be sent without it.",
|
"complete-hardwallet-setup": "This card is now an essential part your multiaccount security. Transactions can't be sent without it.",
|
||||||
"completed": "Completed",
|
"completed": "Completed",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
|
"confirmation-request": "Confirmation request",
|
||||||
"confirmations": "Confirmations",
|
"confirmations": "Confirmations",
|
||||||
"confirmations-helper-text": "When the transaction has 12 confirmations you can consider it settled.",
|
"confirmations-helper-text": "When the transaction has 12 confirmations you can consider it settled.",
|
||||||
"connect": "Connect",
|
"connect": "Connect",
|
||||||
|
@ -593,6 +595,8 @@
|
||||||
"logout-app-content": "The account will be logged out. When you unlock it again, the selected network will be used",
|
"logout-app-content": "The account will be logged out. When you unlock it again, the selected network will be used",
|
||||||
"logout-are-you-sure": "Are you sure you want\nto log out?",
|
"logout-are-you-sure": "Are you sure you want\nto log out?",
|
||||||
"logout-title": "Log out?",
|
"logout-title": "Log out?",
|
||||||
|
"looking-for-cards": "Looking for cards...",
|
||||||
|
"lost-connection": "Lost connection",
|
||||||
"mailserver-address": "Mailserver address",
|
"mailserver-address": "Mailserver address",
|
||||||
"mailserver-automatic": "Automatic selection",
|
"mailserver-automatic": "Automatic selection",
|
||||||
"mailserver-connection-error": "Could not connect to mailserver",
|
"mailserver-connection-error": "Could not connect to mailserver",
|
||||||
|
@ -875,6 +879,7 @@
|
||||||
"show-less": "Show less",
|
"show-less": "Show less",
|
||||||
"show-more": "Show more",
|
"show-more": "Show more",
|
||||||
"show-qr": "Show QR code",
|
"show-qr": "Show QR code",
|
||||||
|
"show-transaction-data": "Show transaction data",
|
||||||
"sign-and-send": "Sign and send",
|
"sign-and-send": "Sign and send",
|
||||||
"sign-in": "Unlock",
|
"sign-in": "Unlock",
|
||||||
"sign-message": "Sign Message",
|
"sign-message": "Sign Message",
|
||||||
|
@ -916,6 +921,7 @@
|
||||||
"sync-synced": "In sync",
|
"sync-synced": "In sync",
|
||||||
"syncing-devices": "Syncing...",
|
"syncing-devices": "Syncing...",
|
||||||
"tag-was-lost": "Tag was lost",
|
"tag-was-lost": "Tag was lost",
|
||||||
|
"tap-card-again": "Tap the card to the back of your phone again",
|
||||||
"test-networks": "Test networks",
|
"test-networks": "Test networks",
|
||||||
"text-input-disabled": "Please wait a moment...",
|
"text-input-disabled": "Please wait a moment...",
|
||||||
"this-device": "This device",
|
"this-device": "This device",
|
||||||
|
@ -934,6 +940,7 @@
|
||||||
"token-details": "Token details",
|
"token-details": "Token details",
|
||||||
"topic-name-error": "Use only lowercase letters (a to z), numbers & dashes (-). Do not use chat keys",
|
"topic-name-error": "Use only lowercase letters (a to z), numbers & dashes (-). Do not use chat keys",
|
||||||
"transaction": "Transaction",
|
"transaction": "Transaction",
|
||||||
|
"transaction-data": "Transaction data",
|
||||||
"transaction-declined": "Transaction declined",
|
"transaction-declined": "Transaction declined",
|
||||||
"transaction-description": "Consider it complete after 12 confirmations on the network.",
|
"transaction-description": "Consider it complete after 12 confirmations on the network.",
|
||||||
"transaction-details": "Transaction details",
|
"transaction-details": "Transaction details",
|
||||||
|
@ -941,6 +948,7 @@
|
||||||
"transaction-history": "Transaction history",
|
"transaction-history": "Transaction history",
|
||||||
"transaction-request": "Transaction Request",
|
"transaction-request": "Transaction Request",
|
||||||
"transaction-sent": "Transaction sent",
|
"transaction-sent": "Transaction sent",
|
||||||
|
"transaction-signed": "The transaction has been successfully signed",
|
||||||
"transactions": "Transactions",
|
"transactions": "Transactions",
|
||||||
"transactions-filter-select-all": "Select all",
|
"transactions-filter-select-all": "Select all",
|
||||||
"transactions-filter-title": "Filter history",
|
"transactions-filter-title": "Filter history",
|
||||||
|
@ -978,6 +986,7 @@
|
||||||
"tribute-to-talk-tribute-received2": " are now contacts and can securely chat with each other.",
|
"tribute-to-talk-tribute-received2": " are now contacts and can securely chat with each other.",
|
||||||
"tribute-to-talk-you-require-snt": "You require SNT for new people to start a chat.",
|
"tribute-to-talk-you-require-snt": "You require SNT for new people to start a chat.",
|
||||||
"try-again": "Try again",
|
"try-again": "Try again",
|
||||||
|
"try-keeping-the-card-still": "Try keeping the card still",
|
||||||
"turn-nfc-on": "Turn NFC on to continue",
|
"turn-nfc-on": "Turn NFC on to continue",
|
||||||
"turn-nfc-description": "NFC is disabled on yor device. You can enable it in settings",
|
"turn-nfc-description": "NFC is disabled on yor device. You can enable it in settings",
|
||||||
"keycard-init-title": "Looking for cards...",
|
"keycard-init-title": "Looking for cards...",
|
||||||
|
|