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"
:transactions "Transactions"
:transaction-details "Transaction details"
:transaction-failed "Transaction failed"
:transactions-sign "Sign"
:transactions-sign-all "Sign all"
:transactions-sign-transaction "Sign Transaction"

View File

@ -18,7 +18,6 @@
status-im.ui.screens.wallet.events
status-im.ui.screens.wallet.send.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]
[status-im.native-module.core :as status]
[status-im.components.permissions :as permissions]

View File

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

View File

@ -7,7 +7,9 @@
[status-im.ui.screens.wallet.db :as wallet.db]
[status-im.utils.types :as types]
[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
@ -29,6 +31,24 @@
(fn []
(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/register-handler-fx
@ -40,59 +60,101 @@
(assoc-in [:wallet :send-transaction :amount-error] error))})))
(def ^:private clear-send-properties {:id nil
:signing-error nil
:signing? false
:wrong-password? false
:waiting-signal? 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]
(let [results (:results (types/json->clj raw-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-modal-completed
(fn [{db :db} [_ {:keys [id response]}]]
(let [{:keys [hash error]} response
db' (assoc-in db [:wallet :send-transaction :in-progress?] false)
has-error? (and error (string? error) (not (string/blank? error)))]
(if has-error?
{:db (assoc-in db' [:wallet :send-transaction :signing-error] error)}
{:db (-> db'
: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-n [[:navigate-back]
[:navigate-to :wallet-transaction-sent]]}))))
:dispatch [:navigate-back]
::show-transaction-error error_message}
{:db (update-in db [:wallet :transactions-unsigned] dissoc id)})))))
(handlers/register-handler-fx
::transaction-completed
(fn [{db :db} [_ {:keys [id response]} modal?]]
(let [{:keys [hash error]} response
db' (assoc-in db [:wallet :send-transaction :in-progress?] false)]
(if (and error (string? error) (not (string/blank? error))) ;; ignore error here, error will be handled in :transaction-failed
{:db db'}
(merge
{:db (-> db'
(update-in [:wallet :transactions-unsigned] dissoc id)
(update-in [:wallet :send-transaction] merge clear-send-properties))}
(if modal?
{:dispatch-n [[:navigate-back]
[:navigate-to :wallet-transaction-sent]]}
{:dispatch [:navigate-to :wallet-transaction-sent]}))))))
(defn on-transactions-modal-completed [raw-results]
(let [results (:results (types/json->clj raw-results))]
(doseq [result results]
(re-frame/dispatch [::transaction-modal-completed {:id (name (key result)) :response (second result)}]))))
(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}}))))
(dispatch-transaction-completed result true))))
(handlers/register-handler-fx
:wallet/sign-transaction
@ -148,7 +210,6 @@
(fn [{:keys [db]} _]
{:db (update-in db [:wallet :send-transaction] assoc
:signing? false
:signing-error nil
:wrong-password? false)}))
(handlers/register-handler-fx

View File

@ -36,11 +36,6 @@
(fn [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?
:<- [::send-transaction]
(fn [{:keys [password]}]

View File

@ -24,7 +24,8 @@
[react/view styles/gap]
[react/text {:style styles/transaction-sent-description} (i18n/label :t/transaction-description)]]
[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/touchable-highlight {:on-press #()}; TODO (andrey) #(re-frame/dispatch [:navigate-to-clean :wallet-transaction-details])}
[react/view styles/transaction-details-container
[react/text {:style styles/transaction-details
:font (if platform/android? :medium :default)

View File

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