close send screen and show alert if error

This commit is contained in:
Andrey Shovkoplyas 2017-10-18 15:40:48 +03:00 committed by Roman Volosovskyi
parent e8602eb3bd
commit fd09a16ca5
8 changed files with 118 additions and 139 deletions

View File

@ -384,6 +384,7 @@
:usd-currency "USD" :usd-currency "USD"
:transactions "Transactions" :transactions "Transactions"
:transaction-details "Transaction details" :transaction-details "Transaction details"
:transaction-failed "Transaction failed"
:transactions-sign "Sign" :transactions-sign "Sign"
:transactions-sign-all "Sign all" :transactions-sign-all "Sign all"
:transactions-sign-transaction "Sign Transaction" :transactions-sign-transaction "Sign Transaction"

View File

@ -18,7 +18,6 @@
status-im.ui.screens.wallet.events status-im.ui.screens.wallet.events
status-im.ui.screens.wallet.send.events status-im.ui.screens.wallet.send.events
status-im.ui.screens.wallet.choose-recipient.events status-im.ui.screens.wallet.choose-recipient.events
status-im.ui.screens.wallet.transactions.events
[re-frame.core :refer [dispatch reg-fx reg-cofx] :as re-frame] [re-frame.core :refer [dispatch reg-fx reg-cofx] :as re-frame]
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.components.permissions :as permissions] [status-im.components.permissions :as permissions]

View File

@ -19,11 +19,9 @@
(spec/def ::camera-permitted? boolean?) (spec/def ::camera-permitted? boolean?)
(spec/def ::in-progress? boolean?) (spec/def ::in-progress? boolean?)
(spec/def ::from-chat? (spec/nilable boolean?)) (spec/def ::from-chat? (spec/nilable boolean?))
(spec/def ::signing-error (spec/nilable string?))
(spec/def :wallet/send-transaction (allowed-keys (spec/def :wallet/send-transaction (allowed-keys
:opt-un [::amount ::to-address ::to-name ::amount-error ::password :opt-un [::amount ::to-address ::to-name ::amount-error ::password
::waiting-signal? ::signing? ::id ::later? ::waiting-signal? ::signing? ::id ::later?
::camera-dimensions ::camera-flashlight ::in-progress? ::camera-dimensions ::camera-flashlight ::in-progress?
::wrong-password? ::camera-permitted? ::from-chat? ::wrong-password? ::camera-permitted? ::from-chat?]))
::signing-error]))

View File

@ -7,7 +7,9 @@
[status-im.ui.screens.wallet.db :as wallet.db] [status-im.ui.screens.wallet.db :as wallet.db]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[status-im.utils.money :as money] [status-im.utils.money :as money]
[status-im.utils.utils :as utils])) [status-im.utils.utils :as utils]
[status-im.utils.hex :as utils.hex]
[status-im.constants :as constants]))
;;;; FX ;;;; FX
@ -29,6 +31,24 @@
(fn [] (fn []
(utils/show-popup (i18n/label :t/transaction-moved-title) (i18n/label :t/transaction-moved-text)))) (utils/show-popup (i18n/label :t/transaction-moved-title) (i18n/label :t/transaction-moved-text))))
(re-frame/reg-fx
::show-transaction-error
(fn [message]
;; (andrey) we need this timeout because modal window conflicts with alert
(js/setTimeout #(utils/show-popup (i18n/label :t/transaction-failed) message) 1000)))
(re-frame/reg-fx
:discard-transaction
(fn [id]
(status/discard-transaction id)))
;;Helper functions
(defn transaction-valid? [{{:keys [to data]} :args}]
(or (and to (utils.hex/valid-hex? to)) (and data (not= data "0x"))))
(defn dispatch-transaction-completed [result & [modal?]]
(re-frame/dispatch [::transaction-completed {:id (name (key result)) :response (second result)} modal?]))
;;;; Handlers ;;;; Handlers
(handlers/register-handler-fx (handlers/register-handler-fx
@ -40,59 +60,101 @@
(assoc-in [:wallet :send-transaction :amount-error] error))}))) (assoc-in [:wallet :send-transaction :amount-error] error))})))
(def ^:private clear-send-properties {:id nil (def ^:private clear-send-properties {:id nil
:signing-error nil
:signing? false :signing? false
:wrong-password? false :wrong-password? false
:waiting-signal? false :waiting-signal? false
:from-chat? false}) :from-chat? false})
(handlers/register-handler-fx
::transaction-completed
(fn [{db :db} [_ {:keys [id response]}]]
(let [{:keys [hash error]} response
db' (assoc-in db [:wallet :send-transaction :in-progress?] false)]
(if-not (and error (string? error) (not (string/blank? error)))
{:db (-> db'
(update-in [:wallet :transactions-unsigned] dissoc id)
(update-in [:wallet :send-transaction] merge clear-send-properties))
:dispatch [:navigate-to :wallet-transaction-sent]}
{:db (assoc-in db' [:wallet :send-transaction :signing-error] error)}))))
(defn on-transactions-completed [raw-results] (defn on-transactions-completed [raw-results]
(let [results (:results (types/json->clj raw-results))] (let [results (:results (types/json->clj raw-results))]
(doseq [result results] (doseq [result results]
(re-frame/dispatch [::transaction-completed {:id (name (key result)) :response (second result)}])))) (dispatch-transaction-completed result))))
;;TRANSACTION QUEUED signal from status-go
(handlers/register-handler-fx
:transaction-queued
[(re-frame/inject-cofx :now)]
(fn [{:keys [db now]} [_ {:keys [id message_id args] :as transaction}]]
(if (transaction-valid? transaction)
(let [{:keys [from to value data gas gasPrice]} args
;;TODO (andrey) revisit this map later (this map from old transactions, idk if we need all these fields)
transaction {:id id
:from from
:to to
:value (money/bignumber value)
:data data
:gas (money/to-decimal gas)
:gas-price (money/to-decimal gasPrice)
:timestamp now
:message-id message_id}
sending-from-chat? (not (get-in db [:wallet :send-transaction :waiting-signal?]))
new-db (assoc-in db [:wallet :transactions-unsigned id] transaction)
sending-db {:id id
:from-chat? sending-from-chat?}]
(if sending-from-chat?
;;SENDING FROM CHAT
{:db (assoc-in new-db [:wallet :send-transaction] sending-db) ; we need to completly reset sending state here
:dispatch [:navigate-to-modal :wallet-send-transaction-modal]}
;;SEND SCREEN WAITING SIGNAL
(let [{:keys [later? password]} (get-in db [:wallet :send-transaction])
new-db' (update-in new-db [:wallet :send-transaction] merge sending-db)] ; just update sending state as we are in wallet flow
(if later?
;;SIGN LATER
{:db (assoc-in new-db' [:wallet :send-transaction :waiting-signal?] false)
:dispatch [:navigate-back]
::show-transaction-moved nil}
;;SIGN NOW
{:db new-db'
::accept-transaction {:id id
:password password
:on-completed on-transactions-completed}}))))
{:discard-transaction id})))
(defn this-transaction-signing? [id signing-id view-id modal]
(and (= signing-id id)
(or (= view-id :wallet-send-transaction)
(= modal :wallet-send-transaction-modal))))
;;TRANSACTION FAILED signal from status-go
(handlers/register-handler-fx
:transaction-failed
(fn [{{:keys [view-id modal] :as db} :db} [_ {:keys [id error_code error_message] :as event}]]
(let [send-transaction (get-in db [:wallet :send-transaction])]
(case error_code
;;WRONG PASSWORD
constants/send-transaction-password-error-code
{:db (assoc-in db [:wallet :send-transaction :wrong-password?] true)}
;;NO ERROR, DISCARDED, TIMEOUT or DEFAULT ERROR
(if (this-transaction-signing? id (:id send-transaction) view-id modal)
{:db (-> db
(update-in [:wallet :transactions-unsigned] dissoc id)
(update-in [:wallet :send-transaction] merge clear-send-properties))
:dispatch [:navigate-back]
::show-transaction-error error_message}
{:db (update-in db [:wallet :transactions-unsigned] dissoc id)})))))
(handlers/register-handler-fx (handlers/register-handler-fx
::transaction-modal-completed ::transaction-completed
(fn [{db :db} [_ {:keys [id response]}]] (fn [{db :db} [_ {:keys [id response]} modal?]]
(let [{:keys [hash error]} response (let [{:keys [hash error]} response
db' (assoc-in db [:wallet :send-transaction :in-progress?] false) db' (assoc-in db [:wallet :send-transaction :in-progress?] false)]
has-error? (and error (string? error) (not (string/blank? error)))] (if (and error (string? error) (not (string/blank? error))) ;; ignore error here, error will be handled in :transaction-failed
(if has-error? {:db db'}
{:db (assoc-in db' [:wallet :send-transaction :signing-error] error)} (merge
{:db (-> db' {:db (-> db'
(update-in [:wallet :transactions-unsigned] dissoc id) (update-in [:wallet :transactions-unsigned] dissoc id)
(update-in [:wallet :send-transaction] merge clear-send-properties)) (update-in [:wallet :send-transaction] merge clear-send-properties))}
:dispatch-n [[:navigate-back] (if modal?
[:navigate-to :wallet-transaction-sent]]})))) {:dispatch-n [[:navigate-back]
[:navigate-to :wallet-transaction-sent]]}
{:dispatch [:navigate-to :wallet-transaction-sent]}))))))
(defn on-transactions-modal-completed [raw-results] (defn on-transactions-modal-completed [raw-results]
(let [results (:results (types/json->clj raw-results))] (let [results (:results (types/json->clj raw-results))]
(doseq [result results] (doseq [result results]
(re-frame/dispatch [::transaction-modal-completed {:id (name (key result)) :response (second result)}])))) (dispatch-transaction-completed result true))))
(handlers/register-handler-fx
:wallet.send-transaction/transaction-queued
(fn [{:keys [db]} _]
(let [{:keys [later? password id]} (get-in db [:wallet :send-transaction])]
(if later?
{:db (assoc-in db [:wallet :send-transaction :waiting-signal?] false)
:dispatch [:navigate-back]
::show-transaction-moved nil}
{::accept-transaction {:id id
:password password
:on-completed on-transactions-completed}}))))
(handlers/register-handler-fx (handlers/register-handler-fx
:wallet/sign-transaction :wallet/sign-transaction
@ -104,11 +166,11 @@
{::accept-transaction {:id id {::accept-transaction {:id id
:password password :password password
:on-completed on-transactions-completed} :on-completed on-transactions-completed}
:db (assoc-in db' [:wallet :send-transaction :in-progress?] true)} :db (assoc-in db' [:wallet :send-transaction :in-progress?] true)}
{:db (update-in db' [:wallet :send-transaction] assoc {:db (update-in db' [:wallet :send-transaction] assoc
:waiting-signal? true :waiting-signal? true
:later? later? :later? later?
:in-progress? true) :in-progress? true)
::send-transaction {:web3 web3 ::send-transaction {:web3 web3
:from (get-in accounts [current-account-id :address]) :from (get-in accounts [current-account-id :address])
:to to-address :to to-address
@ -119,7 +181,7 @@
(fn [{{:keys [web3] (fn [{{:keys [web3]
:accounts/keys [accounts current-account-id] :as db} :db} [_ later?]] :accounts/keys [accounts current-account-id] :as db} :db} [_ later?]]
(let [{:keys [id password]} (get-in db [:wallet :send-transaction])] (let [{:keys [id password]} (get-in db [:wallet :send-transaction])]
{:db (assoc-in db [:wallet :send-transaction :in-progress?] true) {:db (assoc-in db [:wallet :send-transaction :in-progress?] true)
::accept-transaction {:id id ::accept-transaction {:id id
:password password :password password
:on-completed on-transactions-modal-completed}}))) :on-completed on-transactions-modal-completed}})))
@ -148,7 +210,6 @@
(fn [{:keys [db]} _] (fn [{:keys [db]} _]
{:db (update-in db [:wallet :send-transaction] assoc {:db (update-in db [:wallet :send-transaction] assoc
:signing? false :signing? false
:signing-error nil
:wrong-password? false)})) :wrong-password? false)}))
(handlers/register-handler-fx (handlers/register-handler-fx

View File

@ -36,11 +36,6 @@
(fn [send-transaction] (fn [send-transaction]
(:wrong-password? send-transaction))) (:wrong-password? send-transaction)))
(re-frame/reg-sub :wallet.send/signing-error
:<- [::send-transaction]
(fn [send-transaction]
(:signing-error send-transaction)))
(re-frame/reg-sub :wallet.send/sign-password-enabled? (re-frame/reg-sub :wallet.send/sign-password-enabled?
:<- [::send-transaction] :<- [::send-transaction]
(fn [{:keys [password]}] (fn [{:keys [password]}]

View File

@ -24,12 +24,13 @@
[react/view styles/gap] [react/view styles/gap]
[react/text {:style styles/transaction-sent-description} (i18n/label :t/transaction-description)]] [react/text {:style styles/transaction-sent-description} (i18n/label :t/transaction-description)]]
[react/view components.styles/flex] [react/view components.styles/flex]
[react/touchable-highlight {:on-press #()}; TODO (andrey) #(re-frame/dispatch [:navigate-to-clean :wallet-transaction-details])} ;; TODO (andrey) uncomment when will be implemented
[react/view styles/transaction-details-container #_[react/touchable-highlight {:on-press #()}; TODO (andrey) #(re-frame/dispatch [:navigate-to-clean :wallet-transaction-details])}
[react/text {:style styles/transaction-details [react/view styles/transaction-details-container
:font (if platform/android? :medium :default) [react/text {:style styles/transaction-details
:uppercase? (get-in platform/platform-specific [:uppercase?])} :font (if platform/android? :medium :default)
(i18n/label :t/view-transaction-details)]]] :uppercase? (get-in platform/platform-specific [:uppercase?])}
(i18n/label :t/view-transaction-details)]]]
[components/separator] [components/separator]
[react/touchable-highlight {:on-press #(re-frame/dispatch close-transaction-screen-event)} [react/touchable-highlight {:on-press #(re-frame/dispatch close-transaction-screen-event)}
[react/view styles/got-it-container [react/view styles/got-it-container

View File

@ -38,7 +38,6 @@
(defview sign-panel [] (defview sign-panel []
(letsubs [account [:get-current-account] (letsubs [account [:get-current-account]
wrong-password? [:wallet.send/wrong-password?] wrong-password? [:wallet.send/wrong-password?]
signing-error [:wallet.send/signing-error]
signing-phrase (:signing-phrase @account) signing-phrase (:signing-phrase @account)
bottom-value (animation/create-value -250) bottom-value (animation/create-value -250)
opacity-value (animation/create-value 0)] opacity-value (animation/create-value 0)]
@ -56,10 +55,8 @@
:placeholder-text-color "#939ba1" :placeholder-text-color "#939ba1"
:on-change-text #(re-frame/dispatch [:wallet.send/set-password %]) :on-change-text #(re-frame/dispatch [:wallet.send/set-password %])
:style send.styles/password}]]] :style send.styles/password}]]]
(when (or wrong-password? signing-error) (when wrong-password?
[components/tooltip (if wrong-password? [components/tooltip (i18n/label :t/wrong-password)])]))
(i18n/label :t/wrong-password)
signing-error)])]))
;; "Cancel" and "Sign Transaction >" buttons, signing with password ;; "Cancel" and "Sign Transaction >" buttons, signing with password
(defview signing-buttons [cancel-handler sign-handler in-progress?] (defview signing-buttons [cancel-handler sign-handler in-progress?]

View File

@ -1,73 +0,0 @@
(ns status-im.ui.screens.wallet.transactions.events
(:require [status-im.utils.handlers :as handlers]
[status-im.constants :as constants]
[status-im.utils.money :as money]
[status-im.native-module.core :as status]
[re-frame.core :as re-frame]
[status-im.utils.hex :as utils.hex]
[clojure.string :as string]))
;;FX
(re-frame/reg-fx
:discard-transaction
(fn [id]
(status/discard-transaction id)))
;;Helper functions
(defn transaction-valid? [{{:keys [to data]} :args}]
(or (and to (utils.hex/valid-hex? to)) (and data (not= data "0x"))))
;;Handlers
;;TRANSACTION QUEUED signal from status-go
(handlers/register-handler-fx
:transaction-queued
[(re-frame/inject-cofx :now)]
(fn [{:keys [db now]} [_ {:keys [id message_id args] :as transaction}]]
(if (transaction-valid? transaction)
(let [{:keys [from to value data gas gasPrice]} args
;;TODO (andrey) revisit this map later (this map from old transactions, idk if we need all these fields)
transaction {:id id
:from from
:to to
:value (money/bignumber value)
:data data
:gas (money/to-decimal gas)
:gas-price (money/to-decimal gasPrice)
:timestamp now
:message-id message_id}
sending-from-chat? (not (get-in db [:wallet :send-transaction :waiting-signal?]))
new-db (assoc-in db [:wallet :transactions-unsigned id] transaction)
sending-db {:id id
:from-chat? sending-from-chat?}]
(if sending-from-chat?
{:db (assoc-in new-db [:wallet :send-transaction] sending-db) ; we need to completly reset sending state here
:dispatch [:navigate-to-modal :wallet-send-transaction-modal]}
{:db (update-in new-db [:wallet :send-transaction] merge sending-db) ; just update sending state as we are in wallet flow
:dispatch [:wallet.send-transaction/transaction-queued id]}))
{:discard-transaction id})))
;;TRANSACTION FAILED signal from status-go
(handlers/register-handler-fx
:transaction-failed
(fn [{{:accounts/keys [accounts current-account-id] :as db} :db} [_ {:keys [id args message_id error_code error_message] :as event}]]
(let [current-account-address (:address (get accounts current-account-id))
transaction-initiator-address (utils.hex/normalize-hex (:from args))]
(case error_code
;;WRONG PASSWORD
constants/send-transaction-password-error-code
{:db (assoc-in db [:wallet :send-transaction :wrong-password?] true)}
;;TODO (andrey) something weird here below, revisit
;;DISCARDED
constants/send-transaction-discarded-error-code
{:db (update-in db [:wallet :transactions-unsigned] dissoc id)
:dispatch [:set-chat-ui-props {:validation-messages nil}]}
constants/send-transaction-timeout-error-code
{:db (update-in db [:wallet :transactions-unsigned] dissoc id)}
nil))))