diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index 9ff1a8177d..13b6f8d94a 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -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" diff --git a/src/status_im/ui/screens/events.cljs b/src/status_im/ui/screens/events.cljs index f110e6eff4..d8454a2206 100644 --- a/src/status_im/ui/screens/events.cljs +++ b/src/status_im/ui/screens/events.cljs @@ -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] diff --git a/src/status_im/ui/screens/wallet/send/db.cljs b/src/status_im/ui/screens/wallet/send/db.cljs index 0c63149acd..fa42f5f006 100644 --- a/src/status_im/ui/screens/wallet/send/db.cljs +++ b/src/status_im/ui/screens/wallet/send/db.cljs @@ -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?])) diff --git a/src/status_im/ui/screens/wallet/send/events.cljs b/src/status_im/ui/screens/wallet/send/events.cljs index 160288c119..8a548b924e 100644 --- a/src/status_im/ui/screens/wallet/send/events.cljs +++ b/src/status_im/ui/screens/wallet/send/events.cljs @@ -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-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 - ::transaction-modal-completed - (fn [{db :db} [_ {:keys [id response]}]] + ::transaction-completed + (fn [{db :db} [_ {:keys [id response]} modal?]] (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' - (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]]})))) + 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 @@ -104,11 +166,11 @@ {::accept-transaction {:id id :password password :on-completed on-transactions-completed} - :db (assoc-in db' [:wallet :send-transaction :in-progress?] true)} - {:db (update-in db' [:wallet :send-transaction] assoc - :waiting-signal? true - :later? later? - :in-progress? true) + :db (assoc-in db' [:wallet :send-transaction :in-progress?] true)} + {:db (update-in db' [:wallet :send-transaction] assoc + :waiting-signal? true + :later? later? + :in-progress? true) ::send-transaction {:web3 web3 :from (get-in accounts [current-account-id :address]) :to to-address @@ -119,7 +181,7 @@ (fn [{{:keys [web3] :accounts/keys [accounts current-account-id] :as db} :db} [_ later?]] (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 :password password :on-completed on-transactions-modal-completed}}))) @@ -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 diff --git a/src/status_im/ui/screens/wallet/send/subs.cljs b/src/status_im/ui/screens/wallet/send/subs.cljs index 5f13948916..4d0202a2c5 100644 --- a/src/status_im/ui/screens/wallet/send/subs.cljs +++ b/src/status_im/ui/screens/wallet/send/subs.cljs @@ -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]}] diff --git a/src/status_im/ui/screens/wallet/send/transaction_sent/views.cljs b/src/status_im/ui/screens/wallet/send/transaction_sent/views.cljs index c852ae8bb8..402fbdeaf2 100644 --- a/src/status_im/ui/screens/wallet/send/transaction_sent/views.cljs +++ b/src/status_im/ui/screens/wallet/send/transaction_sent/views.cljs @@ -24,12 +24,13 @@ [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])} - [react/view styles/transaction-details-container - [react/text {:style styles/transaction-details - :font (if platform/android? :medium :default) - :uppercase? (get-in platform/platform-specific [:uppercase?])} - (i18n/label :t/view-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) + :uppercase? (get-in platform/platform-specific [:uppercase?])} + (i18n/label :t/view-transaction-details)]]] [components/separator] [react/touchable-highlight {:on-press #(re-frame/dispatch close-transaction-screen-event)} [react/view styles/got-it-container diff --git a/src/status_im/ui/screens/wallet/send/views.cljs b/src/status_im/ui/screens/wallet/send/views.cljs index ed46788444..241de897c4 100644 --- a/src/status_im/ui/screens/wallet/send/views.cljs +++ b/src/status_im/ui/screens/wallet/send/views.cljs @@ -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?] diff --git a/src/status_im/ui/screens/wallet/transactions/events.cljs b/src/status_im/ui/screens/wallet/transactions/events.cljs deleted file mode 100644 index d6fb7c1084..0000000000 --- a/src/status_im/ui/screens/wallet/transactions/events.cljs +++ /dev/null @@ -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)))) \ No newline at end of file