diff --git a/android/app/src/main/res/drawable-hdpi/nfc.png b/android/app/src/main/res/drawable-hdpi/nfc.png new file mode 100644 index 00000000000..57429ac2c51 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/nfc.png differ diff --git a/android/app/src/main/res/drawable-mdpi/nfc.png b/android/app/src/main/res/drawable-mdpi/nfc.png new file mode 100644 index 00000000000..685858afa1f Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/nfc.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/nfc.png b/android/app/src/main/res/drawable-xhdpi/nfc.png new file mode 100644 index 00000000000..f4d8a14600d Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/nfc.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/nfc.png b/android/app/src/main/res/drawable-xxhdpi/nfc.png new file mode 100644 index 00000000000..36535b29a65 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/nfc.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/nfc.png b/android/app/src/main/res/drawable-xxxhdpi/nfc.png new file mode 100644 index 00000000000..5dad02d58b8 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/nfc.png differ diff --git a/externs.js b/externs.js index 08fc9b21280..cf3023d512e 100644 --- a/externs.js +++ b/externs.js @@ -218,6 +218,7 @@ var TopLevel = { "injectJavaScript" : function () {}, "installApplet" : function () {}, "installAppletAndInitCard" : function () {}, + "installCashApplet" : function () {}, "Int8Array" : function () {}, "integer" : function () {}, "interpolate" : function () {}, @@ -491,6 +492,7 @@ var TopLevel = { "sign" : function () {}, "signGroupMembership" : function () {}, "signMessage" : function () {}, + "signPinless" : function () {}, "signTypedData" : function () {}, "slice" : function () {}, "SplashScreen" : function () {}, diff --git a/ios/StatusIm/Images.xcassets/nfc.imageset/Contents.json b/ios/StatusIm/Images.xcassets/nfc.imageset/Contents.json new file mode 100644 index 00000000000..6df42d7746b --- /dev/null +++ b/ios/StatusIm/Images.xcassets/nfc.imageset/Contents.json @@ -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" + } +} \ No newline at end of file diff --git a/ios/StatusIm/Images.xcassets/nfc.imageset/nfc-1.png b/ios/StatusIm/Images.xcassets/nfc.imageset/nfc-1.png new file mode 100644 index 00000000000..f4d8a14600d Binary files /dev/null and b/ios/StatusIm/Images.xcassets/nfc.imageset/nfc-1.png differ diff --git a/ios/StatusIm/Images.xcassets/nfc.imageset/nfc-2.png b/ios/StatusIm/Images.xcassets/nfc.imageset/nfc-2.png new file mode 100644 index 00000000000..36535b29a65 Binary files /dev/null and b/ios/StatusIm/Images.xcassets/nfc.imageset/nfc-2.png differ diff --git a/ios/StatusIm/Images.xcassets/nfc.imageset/nfc.png b/ios/StatusIm/Images.xcassets/nfc.imageset/nfc.png new file mode 100644 index 00000000000..685858afa1f Binary files /dev/null and b/ios/StatusIm/Images.xcassets/nfc.imageset/nfc.png differ diff --git a/project.clj b/project.clj index d630ae4fed3..616662f6799 100644 --- a/project.clj +++ b/project.clj @@ -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 diff --git a/src/status_im/browser/core.cljs b/src/status_im/browser/core.cljs index 1a9b5eee8a5..64cbc118b66 100644 --- a/src/status_im/browser/core.cljs +++ b/src/status_im/browser/core.cljs @@ -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) @@ -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 diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index 91c6837ca10..1d1a9f0fab0 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -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") diff --git a/src/status_im/hardwallet/card.cljs b/src/status_im/hardwallet/card.cljs index 0e5bc4addc8..aab9e5e871e 100644 --- a/src/status_im/hardwallet/card.cljs +++ b/src/status_im/hardwallet/card.cljs @@ -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? @@ -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 %)]))))) diff --git a/src/status_im/hardwallet/core.cljs b/src/status_im/hardwallet/core.cljs index 10e0fc58a83..63b69b1333d 100644 --- a/src/status_im/hardwallet/core.cljs +++ b/src/status_im/hardwallet/core.cljs @@ -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}] @@ -2026,7 +2048,7 @@ (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 @@ -2034,7 +2056,8 @@ (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 @@ -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))))) diff --git a/src/status_im/hardwallet/fx.cljs b/src/status_im/hardwallet/fx.cljs index 003afc051bc..e361f6927ee 100644 --- a/src/status_im/hardwallet/fx.cljs +++ b/src/status_im/hardwallet/fx.cljs @@ -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) diff --git a/src/status_im/signing/core.cljs b/src/status_im/signing/core.cljs index c2267703139..000933d2762 100644 --- a/src/status_im/signing/core.cljs +++ b/src/status_im/signing/core.cljs @@ -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] @@ -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 @@ -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] @@ -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)}))))) diff --git a/src/status_im/signing/keycard.cljs b/src/status_im/signing/keycard.cljs index 34ad3b5222b..3f6eaa7b33d 100644 --- a/src/status_im/signing/keycard.cljs +++ b/src/status_im/signing/keycard.cljs @@ -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]} @@ -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))))) diff --git a/src/status_im/subs.cljs b/src/status_im/subs.cljs index 7734cb04fb7..a9f2f731287 100644 --- a/src/status_im/subs.cljs +++ b/src/status_im/subs.cljs @@ -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 @@ -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." diff --git a/src/status_im/ui/components/button.cljs b/src/status_im/ui/components/button.cljs index b7ade915628..1adc1703ea0 100644 --- a/src/status_im/ui/components/button.cljs +++ b/src/status_im/ui/components/button.cljs @@ -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 @@ -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} diff --git a/src/status_im/ui/screens/popover/views.cljs b/src/status_im/ui/screens/popover/views.cljs index 5cb9a32c8c8..ce7254b1826 100644 --- a/src/status_im/ui/screens/popover/views.cljs +++ b/src/status_im/ui/screens/popover/views.cljs @@ -8,6 +8,7 @@ [status-im.ui.screens.wallet.request.views :as request] [status-im.ui.screens.profile.user.views :as profile.user] [status-im.ui.screens.multiaccounts.recover.views :as multiaccounts.recover] + [status-im.ui.screens.signing.views :as signing] [status-im.ui.screens.biometric.views :as biometric])) (defn hide-panel-anim @@ -112,6 +113,9 @@ (= :disable-password-saving view) [biometric/disable-password-saving-popover] + (= :transaction-data view) + [signing/transaction-data] + :else [view])]]]]])))}))) diff --git a/src/status_im/ui/screens/routing/screens.cljs b/src/status_im/ui/screens/routing/screens.cljs index 9dadd52eaf8..7e66d76f516 100644 --- a/src/status_im/ui/screens/routing/screens.cljs +++ b/src/status_im/ui/screens/routing/screens.cljs @@ -18,6 +18,7 @@ [status-im.ui.screens.privacy-and-security-settings.views :as privacy-and-security] [status-im.ui.screens.language-settings.views :as language-settings] [status-im.ui.screens.notifications-settings.views :as notifications-settings] + [status-im.ui.screens.signing.views :as signing] [status-im.ui.screens.sync-settings.views :as sync-settings] [status-im.ui.screens.advanced-settings.views :as advanced-settings] [status-im.ui.screens.fleet-settings.views :as fleet-settings] diff --git a/src/status_im/ui/screens/signing/styles.cljs b/src/status_im/ui/screens/signing/styles.cljs index 31e7d724b85..f7bc256af59 100644 --- a/src/status_im/ui/screens/signing/styles.cljs +++ b/src/status_im/ui/screens/signing/styles.cljs @@ -58,3 +58,22 @@ :color (if disabled? colors/black colors/white) :padding-horizontal 16 :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}) diff --git a/src/status_im/ui/screens/signing/views.cljs b/src/status_im/ui/screens/signing/views.cljs index 46b74ec8a24..908f9d69275 100644 --- a/src/status_im/ui/screens/signing/views.cljs +++ b/src/status_im/ui/screens/signing/views.cljs @@ -160,6 +160,105 @@ [react/view {:align-items :center :margin-top 16 :margin-bottom 40} [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 (:amount message) (: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 (:amount message) " ") + [{:style {:color colors/gray}} (: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) + :label-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} + :label-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 + :label-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/letsubs [phrase [:signing/phrase]] (case type @@ -187,19 +286,22 @@ [react/view]))) (views/defview message-sheet [] - (views/letsubs [{:keys [formatted-data type] :as sign} [:signing/sign]] - [react/view styles/message - [react/view styles/message-header - [react/text {:style {:typography :title-bold}} (i18n/label :t/signing-a-message)] - [react/touchable-highlight {:on-press #(re-frame/dispatch [:signing.ui/cancel-is-pressed])} - [react/view {:padding 6} - [react/text {:style {:color colors/blue}} (i18n/label :t/cancel)]]]] - [separator] - [react/view {:padding-top 16 :flex 1} - [react/view styles/message-border - [react/scroll-view - [react/text (or formatted-data "")]]] - [password-view sign]]])) + (views/letsubs [{:keys [formatted-data type] :as sign} [:signing/sign] + small-screen? [:dimensions/small-screen?]] + (if (= type :pinless) + [signature-request sign small-screen?] + [react/view styles/message + [react/view styles/message-header + [react/text {:style {:typography :title-bold}} (i18n/label :t/signing-a-message)] + [react/touchable-highlight {:on-press #(re-frame/dispatch [:signing.ui/cancel-is-pressed])} + [react/view {:padding 6} + [react/text {:style {:color colors/blue}} (i18n/label :t/cancel)]]]] + [separator] + [react/view {:padding-top 16 :flex 1} + [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] (let [converted-value (* amount (get-in prices [(keyword display-symbol) (keyword (:code wallet-currency)) :price]))] @@ -302,4 +404,4 @@ (when tx (select-keys tx [:from :contact :amount :token :approve? :message])) #(if (:message %) [message-sheet] - [sheet %])])) \ No newline at end of file + [sheet %])])) diff --git a/translations/en.json b/translations/en.json index 362ce553b97..8886a27ae14 100644 --- a/translations/en.json +++ b/translations/en.json @@ -146,6 +146,7 @@ "clear-history-confirmation": "Clear history?", "clear-history-confirmation-content": "Are you sure you want to clear this chat history?", "clear-history-title": "Clear history?", + "close": "Close", "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-title": "Warning!", @@ -159,6 +160,7 @@ "completing-card-setup": "Completing card setup", "confirm": "Confirm", "confirm-install": "Confirm Install", + "confirmation-request": "Confirmation request", "confirmations": "Confirmations", "confirmations-helper-text": "When the transaction has 12 confirmations you can consider it settled.", "connect": "Connect", @@ -633,6 +635,8 @@ "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-title": "Log out?", + "looking-for-cards": "Looking for cards...", + "lost-connection": "Lost connection", "mailserver-address": "Mailserver address", "mailserver-automatic": "Automatic selection", "mailserver-connection-error": "Could not connect to mailserver", @@ -954,6 +958,7 @@ "show-less": "Show less", "show-more": "Show more", "show-qr": "Show QR code", + "show-transaction-data": "Show transaction data", "sidechain-text": "You’re on the {{sidechain}} Sidechain.", "sign-and-send": "Sign and send", "sign-in": "Unlock", @@ -1000,6 +1005,7 @@ "sync-synced": "In sync", "syncing-devices": "Syncing...", "tag-was-lost": "Tag was lost", + "tap-card-again": "Tap the card to the back of your phone again", "taking-long-hold-phone-connected": "This will take a few seconds.\n Hold card connected to the phone.", "test-networks": "Test networks", "testnet-text": "You’re on the {{testnet}} Testnet. Do not send real ETH or SNT to your address", @@ -1020,6 +1026,7 @@ "token-details": "Token details", "topic-name-error": "Use only lowercase letters (a to z), numbers & dashes (-). Do not use chat keys", "transaction": "Transaction", + "transaction-data": "Transaction data", "transaction-declined": "Transaction declined", "transaction-description": "Consider it complete after 12 confirmations on the network.", "transaction-details": "Transaction details", @@ -1027,6 +1034,7 @@ "transaction-history": "Transaction history", "transaction-request": "Transaction Request", "transaction-sent": "Transaction sent", + "transaction-signed": "The transaction has been successfully signed", "transactions": "Transactions", "transactions-filter-select-all": "Select all", "transactions-filter-title": "Filter history", @@ -1065,6 +1073,7 @@ "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.", "try-again": "Try again", + "try-keeping-the-card-still": "Try keeping the card still", "turn-nfc-on": "Turn NFC on to continue", "type-a-message": "Type a message...", "ulc-enabled": "ULC enabled",