Add web3.keycard.signTypedData

Signed-off-by: Vitaliy Vlasov <siphiuel@gmail.com>
This commit is contained in:
Vitaliy Vlasov 2019-11-04 11:51:56 +02:00
parent 1b43e4c16b
commit e11385e350
No known key found for this signature in database
GPG Key ID: A7D57C347F2B2964
26 changed files with 369 additions and 44 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -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 () {},

View File

@ -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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

View File

@ -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

View File

@ -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")

View File

@ -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)]))}))

View File

@ -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?

View File

@ -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)

View File

@ -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]))

View File

@ -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)))

View File

@ -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}]

View File

@ -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

View File

@ -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

View File

@ -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)))))

View File

@ -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."

View File

@ -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])]]]]])))})))

View File

@ -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})

View File

@ -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]))]

View File

@ -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...",