From 54d68081b4cf57035c0804a48021f83b3b78eab8 Mon Sep 17 00:00:00 2001 From: Andrey Shovkoplyas Date: Wed, 4 Oct 2017 17:50:17 +0300 Subject: [PATCH] send command and remove old wallet --- src/status_im/components/drawer/view.cljs | 41 --- src/status_im/constants.cljs | 6 + src/status_im/transactions/handlers.cljs | 233 ------------------ .../screens/confirmation_success.cljs | 25 -- .../screens/transaction_details.cljs | 80 ------ .../screens/unsigned_transactions.cljs | 72 ------ src/status_im/transactions/specs.cljs | 12 - .../transactions/styles/list_item.cljs | 52 ---- .../transactions/styles/password_form.cljs | 9 - .../transactions/styles/screens.cljs | 134 ---------- src/status_im/transactions/subs.cljs | 24 -- .../transactions/views/list_item.cljs | 40 --- .../transactions/views/password_form.cljs | 21 -- src/status_im/ui/screens/db.cljs | 10 - src/status_im/ui/screens/events.cljs | 7 +- src/status_im/ui/screens/subs.cljs | 1 - src/status_im/ui/screens/views.cljs | 14 +- .../wallet/choose_recipient/events.cljs | 26 ++ .../ui/screens/wallet/components/styles.cljs | 10 +- .../ui/screens/wallet/components/views.cljs | 27 ++ src/status_im/ui/screens/wallet/events.cljs | 5 + .../ui/screens/wallet/navigation.cljs | 6 +- src/status_im/ui/screens/wallet/send/db.cljs | 3 +- .../ui/screens/wallet/send/events.cljs | 98 ++++---- .../ui/screens/wallet/send/views.cljs | 63 ++++- .../screens/wallet/transactions/events.cljs | 77 ++++++ .../ui/screens/wallet/transactions/subs.cljs | 34 ++- .../ui/screens/wallet/transactions/views.cljs | 52 ++-- src/status_im/utils/money.cljs | 3 + 29 files changed, 314 insertions(+), 871 deletions(-) delete mode 100644 src/status_im/transactions/handlers.cljs delete mode 100644 src/status_im/transactions/screens/confirmation_success.cljs delete mode 100644 src/status_im/transactions/screens/transaction_details.cljs delete mode 100644 src/status_im/transactions/screens/unsigned_transactions.cljs delete mode 100644 src/status_im/transactions/specs.cljs delete mode 100644 src/status_im/transactions/styles/list_item.cljs delete mode 100644 src/status_im/transactions/styles/password_form.cljs delete mode 100644 src/status_im/transactions/styles/screens.cljs delete mode 100644 src/status_im/transactions/subs.cljs delete mode 100644 src/status_im/transactions/views/list_item.cljs delete mode 100644 src/status_im/transactions/views/password_form.cljs create mode 100644 src/status_im/ui/screens/wallet/choose_recipient/events.cljs create mode 100644 src/status_im/ui/screens/wallet/transactions/events.cljs diff --git a/src/status_im/components/drawer/view.cljs b/src/status_im/components/drawer/view.cljs index d3260f2c6e..f76edab031 100644 --- a/src/status_im/components/drawer/view.cljs +++ b/src/status_im/components/drawer/view.cljs @@ -101,26 +101,6 @@ status) :on-press #(rf/dispatch [:my-profile.drawer/edit-status])}])]))) -(defview transaction-list-item [{:keys [to value timestamp] :as transaction}] - [recipient [:contact-by-address to]] - (let [eth-value (str (money/wei->ether value)) - value (i18n/label-number eth-value) - recipient-name (or (:name recipient) to)] - [touchable-highlight {:on-press #(rf/dispatch [:navigate-to-modal :transaction-details transaction])} - [view {:style st/transaction} - [vi/icon :icons/arrow-right {:container-style st/transaction-icon}] - [view {:style st/transaction-info} - [view {:style st/transaction-value-container} - [text {:style st/transaction-value :font :medium} value] - [text {:style st/transaction-unit} "ETH"]] - [view {:style st/transaction-details-container} - [text {:style st/transaction-to} (i18n/label :t/to)] - [text {:style st/transaction-recipient :number-of-lines 1} recipient-name] - [text {:style st/transaction-time} (time/format-date "dd MMM HH:mm" (time/to-date timestamp))]]] - [view {:style st/transaction-picture} - (when recipient - [ci/chat-icon (:photo-path recipient) {:size 40}])]]])) - (defn render-separator-fn [transactions-count] (fn [_ row-id _] (when (< row-id (dec transactions-count)) @@ -128,26 +108,6 @@ ^{:key row-id} [common/separator {} st/transactions-list-separator])))) -(defview unsigned-transactions [] - [all-transactions [:transactions]] - (let [transactions (take 2 (sort-by :timestamp > all-transactions))] - (if (empty? transactions) - [view {:style st/empty-transactions-title-container} - [text {:style st/transactions-title} (i18n/label :t/no-unsigned-transactions)]] - - [view - [view {:style st/transactions-title-container} - [text {:style st/transactions-title} (i18n/label :t/unsigned-transactions)]] - [list-view {:dataSource (lw/to-datasource transactions) - :renderSeparator (render-separator-fn (count transactions)) - :renderRow (fn [row _ _] (list-item [transaction-list-item row]))}] - [touchable-opacity {:style st/view-all-transactions-button - :on-press #(rf/dispatch [:navigate-to-modal :unsigned-transactions])} - [text {:style st/view-all-transactions-text - :font (if platform/android? :medium :default) - :uppercase? platform/android?} - (i18n/label :t/view-all)]]]))) - (defview current-network [] (letsubs [network [:get-current-account-network]] [view {:style st/network-label-container} @@ -182,7 +142,6 @@ [options-btn]] [current-network]] [view - [unsigned-transactions] [switch-account]]]])) (defn drawer-view [items] diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index 753e9556e9..180c2ed641 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -70,3 +70,9 @@ :DataDir "/ethereum/mainnet_rpc" :UpstreamConfig {:Enabled true :URL "https://mainnet.infura.io/z6GCTmjdP3FETEJmMBI4 "}}}})) + +(def ^:const send-transaction-no-error-code "0") +(def ^:const send-transaction-default-error-code "1") +(def ^:const send-transaction-password-error-code "2") +(def ^:const send-transaction-timeout-error-code "3") +(def ^:const send-transaction-discarded-error-code "4") diff --git a/src/status_im/transactions/handlers.cljs b/src/status_im/transactions/handlers.cljs deleted file mode 100644 index d858fbc446..0000000000 --- a/src/status_im/transactions/handlers.cljs +++ /dev/null @@ -1,233 +0,0 @@ -(ns status-im.transactions.handlers - (:require [re-frame.core :refer [after dispatch debug enrich]] - [status-im.utils.handlers :refer [register-handler]] - [status-im.ui.screens.navigation :as nav] - [status-im.utils.datetime :as time] - [status-im.utils.handlers :as u] - [status-im.utils.types :as t] - [status-im.utils.hex :refer [valid-hex? normalize-hex]] - [status-im.native-module.core :as status] - [clojure.string :as s] - [taoensso.timbre :as log])) - -;; flow: -;; :accept-transactions -;; ↓ -;; :transaction-completed -;; ↓ -;; ::remove-transaction && [:set :wrong-password? false] <- on error -;; ::remove-transaction <- when transaction is -;; not from the jail -;; ::add-transactions-hash -;; && ::check-completed-transaction! -;; && :navigation-replace <- on success - - -(defmethod nav/preload-data! :unsigned-transactions - [{:keys [transactions-queue] :as db} _] - (-> db - (assoc :transactions transactions-queue - :wrong-password-counter 0 - :wrong-password? false) - (assoc-in [:confirm-transactions :password] ""))) - -(defmethod nav/preload-data! :transaction-details - [db [_ _ transaction]] - (-> db - (assoc :selected-transaction transaction - :wrong-password-counter 0 - :wrong-password? false) - (assoc-in [:confirm-transactions :password] ""))) - -(defn on-transactions-completed [raw-results] - (let [results (:results (t/json->clj raw-results))] - (doseq [result results] - (dispatch [:transaction-completed {:id (name (key result)) :response (second result)}])))) - -(register-handler :accept-transactions - (u/side-effect! - (fn [{:keys [transactions]} [_ password]] - (dispatch [:set :wrong-password? false]) - (status/complete-transactions (keys transactions) password on-transactions-completed)))) - -(register-handler :accept-transaction - (u/side-effect! - (fn [_ [_ password id]] - (dispatch [:set :wrong-password? false]) - (status/complete-transactions (list id) password on-transactions-completed)))) - -(register-handler :deny-transactions - (u/side-effect! - (fn [{:keys [transactions]}] - (let [transactions' (vals transactions) - messages-ids (map :message-id transactions') - ids (map :id transactions')] - (dispatch [::remove-pending-messages messages-ids]) - (dispatch [::remove-transactions ids]) - (doseq [id ids] - (dispatch [::discard-transaction id])))))) - -(register-handler :deny-transaction - (u/side-effect! - (fn [{:keys [transactions]} [_ id]] - (let [{:keys [message-id] :as transaction} (get transactions id)] - (when transaction - (dispatch [::remove-pending-message message-id]) - (dispatch [::remove-transaction id]) - (dispatch [::discard-transaction id])))))) - -(register-handler ::discard-transaction - (u/side-effect! - (fn [_ [_ id]] - (status/discard-transaction id)))) - -(register-handler ::remove-transactions - (fn [db [_ hashes]] - (-> db - (dissoc :transactions) - (update :transactions-queue #(apply dissoc % hashes))))) - -(register-handler ::remove-transaction - (fn [db [_ hash]] - (-> db - (update :transactions dissoc hash) - (update :transactions-queue dissoc hash)))) - -(register-handler :wait-for-transaction - (after (fn [_ [_ message-id]] - (dispatch [::check-completed-transaction! - {:message-id message-id}]))) - (fn [db [_ message-id params]] - (assoc-in db [:transaction-subscribers message-id] params))) - -(defn remove-pending-message - [{:keys [command->chat] :as db} message-id] - (let [chat-id (get command->chat message-id)] - (if chat-id - (update db :transaction-subscribers dissoc message-id) - db))) - -(register-handler ::remove-pending-messages - (fn [db [_ ids]] - (log/debug :message-ids ids) - (reduce remove-pending-message db ids))) - -(register-handler ::remove-pending-message - (fn [db [_ message-id]] - (remove-pending-message db message-id))) - -(defn transaction-valid? [{{:keys [to data]} :args}] - (or (and to (valid-hex? to)) (and data (not= data "0x")))) - -(register-handler :transaction-queued - (u/side-effect! - (fn [_ [_ {:keys [id] :as transaction}]] - (if (transaction-valid? transaction) - (dispatch [::transaction-queued transaction]) - (status/discard-transaction id))))) - -(register-handler ::transaction-queued - (fn [{:wallet/keys [send-transaction] :as db} [_ {:keys [id message_id args] :as transaction}]] - (let [{:keys [from to value data gas gasPrice]} args] - (if (transaction-valid? transaction) - (let [transaction {:id id - :from from - :to to - :value (.toDecimal js/Web3.prototype value) - :data data - :gas (.toDecimal js/Web3.prototype gas) - :gas-price (.toDecimal js/Web3.prototype gasPrice) - :timestamp (time/now-ms) - :message-id message_id}] - (if (:waiting-signal? send-transaction) - (dispatch [:wallet/transaction-queued id]) - (dispatch [:navigate-to-modal :unsigned-transactions])) - (assoc-in db [:transactions-queue id] transaction)) - db)))) - -(register-handler :transaction-completed - (u/side-effect! - (fn [{:keys [transactions modal]} [_ {:keys [id response]}]] - (let [{:keys [hash error]} response - {:keys [message-id]} (get transactions id)] - (log/debug :parsed-response response) - (when-not (and error (string? error) (not (s/blank? error))) - (if (and message-id (not (s/blank? message-id))) - (do (dispatch [::add-transactions-hash {:id id - :hash hash - :message-id message-id}]) - (dispatch [::check-completed-transaction! {:message-id message-id}])) - (dispatch [::remove-transaction id])) - (when (#{:unsigned-transactions :transaction-details} modal) - (dispatch [:navigate-to-modal :confirmation-success]))))))) - -(register-handler ::add-transactions-hash - (fn [db [_ {:keys [id hash message-id]}]] - (-> db - (assoc-in [:transactions id :hash] hash) - (assoc-in [:message-id->transaction-id message-id] id)))) - -(register-handler ::send-pending-message - (u/side-effect! - (fn [{:keys [transaction-subscribers]} [_ message-id hash]] - (when-let [{:keys [chat-id] :as params} (transaction-subscribers message-id)] - (let [params' (assoc-in params [:handler-data :transaction-hash] hash)] - (dispatch [:prepare-command! chat-id params'])) - (dispatch [::remove-transaction-subscriber message-id]))))) - -(register-handler ::remove-transaction-subscriber - (fn [db [_ old-hash]] - (update db :transaction-subscribers dissoc old-hash))) - -(register-handler ::check-completed-transaction! - (u/side-effect! - (fn [{:keys [message-id->transaction-id transactions transaction-subscribers]} - [_ {:keys [message-id]}]] - (let [id (get message-id->transaction-id message-id) - {:keys [hash]} (get transactions id) - pending-message (get transaction-subscribers message-id)] - (when (and pending-message id hash) - (dispatch [::send-pending-message message-id hash])) - ;; todo revisit this - (dispatch [::remove-transaction id]))))) - -(def wrong-password-code "2") -(def discard-code "4") - -(register-handler :transaction-failed - (u/side-effect! - (fn [{:accounts/keys [accounts current-account-id]} [_ {:keys [id args message_id error_code error_message] :as event}]] - (let [current-account-address (:address (get accounts current-account-id)) - transaction-initiator-address (normalize-hex (:from args))] - (cond - - (= error_code wrong-password-code) - (dispatch [:set-wrong-password!]) - - (not= discard-code error_code) - (do (when message_id - (dispatch [::remove-pending-message message_id])) - (dispatch [:clear-selected-transaction]) - (dispatch [::remove-transaction id]) - (when (= current-account-address transaction-initiator-address) - (dispatch [:set-chat-ui-props {:validation-messages error_message}]))) - - :else - (dispatch [:set-chat-ui-props {:validation-messages nil}])))))) - -(register-handler :clear-selected-transaction - (fn [db _] - (dissoc db :selected-transaction))) - -(def attempts-limit 3) - -(register-handler :set-wrong-password! - (after (fn [{:keys [wrong-password-counter]}] - (when (>= wrong-password-counter attempts-limit) - (dispatch [:set :wrong-password? false]) - (dispatch [:set :wrong-password-counter 0]) - (dispatch [:set-in [:confirm-transactions :password] ""])))) - (fn [db] - (-> db - (assoc :wrong-password? true) - (update :wrong-password-counter (fnil inc 0))))) diff --git a/src/status_im/transactions/screens/confirmation_success.cljs b/src/status_im/transactions/screens/confirmation_success.cljs deleted file mode 100644 index 3a04b4e0dd..0000000000 --- a/src/status_im/transactions/screens/confirmation_success.cljs +++ /dev/null @@ -1,25 +0,0 @@ -(ns status-im.transactions.screens.confirmation-success - (:require-macros [status-im.utils.views :refer [defview]]) - (:require [re-frame.core :as rf] - [status-im.components.react :as rn] - [status-im.components.sticky-button :as sticky-button] - [status-im.components.status-bar :as status-bar] - [status-im.transactions.views.list-item :as transactions-list-item] - [status-im.transactions.styles.screens :as st] - [status-im.i18n :as i18n])) - -(defview confirmation-success [] - [quantity [:get :confirmed-transactions-count]] - [rn/view {:style st/success-screen} - [status-bar/status-bar {:type :transaction}] - [rn/view {:style st/success-screen-content-container} - [rn/view {:style st/success-icon-container} - [rn/image {:source {:uri :icon_ok_white} - :style st/success-icon}]] - [rn/view - [rn/text {:style st/success-text} - (i18n/label-pluralize quantity :t/transactions-confirmed)]]] - [sticky-button/sticky-button - (i18n/label :t/got-it) - #(do (rf/dispatch [:navigate-back]) - (rf/dispatch [:set :confirmed-transactions-count 0]))]]) diff --git a/src/status_im/transactions/screens/transaction_details.cljs b/src/status_im/transactions/screens/transaction_details.cljs deleted file mode 100644 index 844d73047a..0000000000 --- a/src/status_im/transactions/screens/transaction_details.cljs +++ /dev/null @@ -1,80 +0,0 @@ -(ns status-im.transactions.screens.transaction-details - (:require-macros [status-im.utils.views :refer [defview]]) - (:require [re-frame.core :as rf] - [status-im.components.react :as rn] - [status-im.components.common.common :as common] - [status-im.components.sticky-button :as sticky-button] - [status-im.components.status-bar :as status-bar] - [status-im.components.sync-state.offline :as offline-view] - [status-im.components.toolbar-new.actions :as act] - [status-im.components.toolbar-new.view :as toolbar] - [status-im.i18n :as i18n] - [status-im.transactions.styles.screens :as st] - [status-im.transactions.views.list-item :as transactions-list-item] - [status-im.transactions.views.password-form :as password-form] - [status-im.utils.platform :as platform] - [status-im.utils.money :as money])) - -(defn toolbar-view [] - [toolbar/toolbar2 - {:background-color st/transactions-toolbar-background - :border-style st/toolbar-border} - [toolbar/nav-button (act/back-white #(rf/dispatch [:navigate-to-modal :unsigned-transactions]))] - [rn/view {:style st/toolbar-title-container} - [rn/text {:style st/toolbar-title-text - :font :toolbar-title} - (i18n/label :t/transaction)]]]) - -(defn detail-item [title content name?] - [rn/view {:style st/details-item} - [rn/text {:style st/details-item-title} title] - [rn/text {:style (st/details-item-content name?) - :number-of-lines 1} - content]]) - -(defn detail-data [content] - [rn/view {:style st/details-data} - [rn/text {:style st/details-data-title} (i18n/label :t/data)] - [rn/text {:style st/details-data-content} content]]) - -(defview details [{:keys [to data gas gas-price] :as transaction}] - [current-account [:get-current-account] - recipient [:contact-by-address to]] - (let [recipient-name (or (:name recipient) to (i18n/label :t/contract-creation)) - gas-price' (money/wei->ether gas-price) - fee-value (money/fee-value gas gas-price') - estimated-fee (str fee-value " ETH")] - [rn/view st/details-container - [detail-item (i18n/label :t/to) recipient-name true] - [detail-item (i18n/label :t/from) (:name current-account) true] - [detail-item (i18n/label :t/estimated-fee) estimated-fee] - [detail-data data]])) - -(defview transaction-details [] - [{:keys [id] :as transaction} [:get :selected-transaction] - {:keys [password]} [:get :confirm-transactions] - confirmed? [:get-in [:transaction-details-ui-props :confirmed?]] - sync-state [:sync-state] - network-status [:get :network-status]] - {:component-did-update #(when-not transaction (rf/dispatch [:navigate-to-modal :unsigned-transactions])) - :component-will-unmount #(rf/dispatch [:set-in [:transaction-details-ui-props :confirmed?] false])} - (let [offline? (or (= network-status :offline) (= sync-state :offline))] - [rn/keyboard-avoiding-view {:style st/transactions-screen} - [status-bar/status-bar {:type :transaction}] - [toolbar-view] - [rn/scroll-view st/details-screen-content-container - [transactions-list-item/view transaction #(rf/dispatch [:navigate-to-modal :unsigned-transactions])] - [common/separator st/details-separator st/details-separator-wrapper] - [details transaction]] - (when (and confirmed? (not offline?)) - [password-form/view 1]) - (when-not offline? - (let [confirm-text (if confirmed? - (i18n/label :t/confirm) - (i18n/label-pluralize 1 :t/confirm-transactions)) - confirm-fn (if confirmed? - #(do (rf/dispatch [:accept-transaction password id]) - (rf/dispatch [:set :confirmed-transactions-count 1])) - #(rf/dispatch [:set-in [:transaction-details-ui-props :confirmed?] true]))] - [sticky-button/sticky-button confirm-text confirm-fn true])) - [offline-view/offline-view {:top (if platform/ios? 21 0)}]])) diff --git a/src/status_im/transactions/screens/unsigned_transactions.cljs b/src/status_im/transactions/screens/unsigned_transactions.cljs deleted file mode 100644 index adc4a449ac..0000000000 --- a/src/status_im/transactions/screens/unsigned_transactions.cljs +++ /dev/null @@ -1,72 +0,0 @@ -(ns status-im.transactions.screens.unsigned-transactions - (:require-macros [status-im.utils.views :refer [defview]]) - (:require [re-frame.core :as rf] - [status-im.components.common.common :as common] - [status-im.components.react :as rn] - [status-im.components.sticky-button :as sticky-button] - [status-im.components.status-bar :as status-bar] - [status-im.components.sync-state.offline :as offline-view] - [status-im.components.toolbar-new.actions :as act] - [status-im.components.toolbar-new.view :as toolbar] - [status-im.transactions.views.list-item :as transactions-list-item] - [status-im.transactions.views.password-form :as password-form] - [status-im.transactions.styles.screens :as st] - [status-im.utils.listview :as lw] - [status-im.utils.platform :as platform] - [status-im.i18n :as i18n])) - -(defn toolbar-view [transactions] - [toolbar/toolbar - {:background-color st/transactions-toolbar-background - :nav-action (act/close-white #(rf/dispatch [:navigate-back])) - :border-style st/toolbar-border - :custom-content [rn/view {:style st/toolbar-title-container} - [rn/text {:style st/toolbar-title-text - :font :toolbar-title} - (i18n/label :t/unsigned-transactions)] - [rn/text {:style st/toolbar-title-count - :font :toolbar-title} - (count transactions)]]}]) - -(defn render-separator-fn [transactions-count] - (fn [_ row-id _] - (when (< row-id (dec transactions-count)) - (rn/list-item - ^{:key row-id} - [common/separator {} st/transactions-list-separator])))) - -(defn render-row-fn [row _ _] - (rn/list-item - [rn/touchable-highlight {:on-press #(rf/dispatch [:navigate-to-modal :transaction-details row])} - [rn/view - [transactions-list-item/view row]]])) - -(defview unsigned-transactions [] - [transactions [:transactions] - {:keys [password]} [:get :confirm-transactions] - confirmed? [:get-in [:transactions-list-ui-props :confirmed?]] - sync-state [:sync-state] - network-status [:get :network-status]] - {:component-did-update #(when-not (seq transactions) (rf/dispatch [:navigate-back])) - :component-will-unmount #(rf/dispatch [:set-in [:transactions-list-ui-props :confirmed?] false])} - (let [offline? (or (= network-status :offline) (= sync-state :offline))] - [rn/keyboard-avoiding-view st/transactions-screen - [status-bar/status-bar {:type :transaction}] - [toolbar-view transactions] - [rn/view {:style st/transactions-screen-content-container} - [rn/list-view {:style st/transactions-list - :dataSource (lw/to-datasource transactions) - :renderSeparator (render-separator-fn (count transactions)) - :renderRow render-row-fn}] - (when (and confirmed? (not offline?)) - [password-form/view (count transactions)])] - (when-not offline? - (let [confirm-text (if confirmed? - (i18n/label :t/confirm) - (i18n/label-pluralize (count transactions) :t/confirm-transactions)) - confirm-fn (if confirmed? - #(do (rf/dispatch [:accept-transactions password]) - (rf/dispatch [:set :confirmed-transactions-count (count transactions)])) - #(rf/dispatch [:set-in [:transactions-list-ui-props :confirmed?] true]))] - [sticky-button/sticky-button confirm-text confirm-fn true])) - [offline-view/offline-view {:top (if platform/ios? 21 0)}]])) diff --git a/src/status_im/transactions/specs.cljs b/src/status_im/transactions/specs.cljs deleted file mode 100644 index aeced89874..0000000000 --- a/src/status_im/transactions/specs.cljs +++ /dev/null @@ -1,12 +0,0 @@ -(ns status-im.transactions.specs - (:require [cljs.spec.alpha :as s])) - -(s/def :transactions/transactions (s/nilable map?)) ;; {id (string) transaction (map)} -(s/def :transactions/transactions-queue (s/nilable map?)) ;; {id (string) transaction (map)} -(s/def :transactions/selected-transaction (s/nilable map?)) -(s/def :transactions/confirm-transactions (s/nilable map?)) -(s/def :transactions/confirmed-transactions-count (s/nilable int?)) -(s/def :transactions/transactions-list-ui-props (s/nilable map?)) -(s/def :transactions/transaction-details-ui-props (s/nilable map?)) -(s/def :transactions/wrong-password-counter (s/nilable int?)) -(s/def :transactions/wrong-password? (s/nilable boolean?)) \ No newline at end of file diff --git a/src/status_im/transactions/styles/list_item.cljs b/src/status_im/transactions/styles/list_item.cljs deleted file mode 100644 index 62de0d6e10..0000000000 --- a/src/status_im/transactions/styles/list_item.cljs +++ /dev/null @@ -1,52 +0,0 @@ -(ns status-im.transactions.styles.list-item - (:require-macros [status-im.utils.styles :refer [defstyle]]) - (:require [status-im.components.styles :as st])) - -(def item - {:padding-vertical 19 - :padding-horizontal 16 - :flex 1 - :flex-direction :row - :align-items :center}) - -(def item-photo - {:width 86 - :height 48 - :border-radius 100 - :background-color st/color-dark-blue-3 - :flex-direction :row - :align-items :center}) - -(def item-info - {:margin-left 16 - :flex 1}) - -(defstyle item-info-recipient - {:color st/color-light-blue - :font-size 15 - :flex-shrink 1 - :android {:margin-bottom 5} - :ios {:margin-bottom 4}}) - -(defstyle item-info-amount - {:color st/color-white - :android {:font-size 19} - :ios {:font-size 20}}) - -(def item-deny-btn - {:margin-left 16}) - -(def item-deny-btn-icon - {:width 24 - :height 24}) - -(def photo-size 48) - -(def photo-placeholder - {:width 48 - :height 48}) - -(def item-photo-icon - {:margin-left 4 - :width 24 - :height 24}) diff --git a/src/status_im/transactions/styles/password_form.cljs b/src/status_im/transactions/styles/password_form.cljs deleted file mode 100644 index a23c78715e..0000000000 --- a/src/status_im/transactions/styles/password_form.cljs +++ /dev/null @@ -1,9 +0,0 @@ -(ns status-im.transactions.styles.password-form - (:require-macros [status-im.utils.styles :refer [defstyle]]) - (:require [status-im.components.styles :as common])) - -(defstyle password-container - {:android {:margin-bottom 27} - :ios {:margin-bottom 20 - :border-top-width 1 - :border-top-color common/color-white-transparent-2}}) diff --git a/src/status_im/transactions/styles/screens.cljs b/src/status_im/transactions/styles/screens.cljs deleted file mode 100644 index c5bb58845e..0000000000 --- a/src/status_im/transactions/styles/screens.cljs +++ /dev/null @@ -1,134 +0,0 @@ -(ns status-im.transactions.styles.screens - (:require-macros [status-im.utils.styles :refer [defstyle]]) - (:require [status-im.components.styles :as common] - [status-im.utils.platform :as platform])) - -;; common - -(def transactions-toolbar-background (if platform/ios? - common/color-dark-blue-2 - common/color-dark-blue-1)) - -(defstyle toolbar-title-container - {:flex 1 - :flex-direction :row - :padding-left 18 - :ios {:align-items :center - :justify-content :center}}) - -(def toolbar-title-text - {:color common/color-white - :font-size 17}) - -(defstyle toolbar-title-count - {:color common/color-white - :font-size 17 - :margin-left 8 - :android {:opacity 0.2} - :ios {:opacity 0.6}}) - -(defstyle toolbar-border - {:ios {:background-color common/color-white - :opacity 0.1}}) - -;; unsigned-transactions - -(def transactions-screen - {:flex 1 - :background-color common/color-dark-blue-2}) - -(def transactions-screen-content-container - {:flex 1 - :justify-content :space-between}) - -(defstyle transactions-list - {:flex 1 - :android {:padding-vertical 8}}) - -(def transactions-list-separator - {:margin-left 16 - :opacity 0.1}) - -;; transaction-details - -(defstyle details-screen-content-container - {:flex 1 - :android {:padding-top 8}}) - -(def details-separator-wrapper - {:background-color common/color-dark-blue-2}) - -(def details-separator - {:margin-left 16 - :background-color common/color-white - :opacity 0.1}) - -(defstyle details-container - {:ios {:margin-top 10} - :android {:margin-top 0}}) - -(def details-item - {:margin-top 10 - :padding-left 16 - :padding-right 16 - :flex-direction :row}) - -(defstyle details-item-title - {:width 80 - :font-size 15 - :color common/color-white - :android {:opacity 0.2 - :margin-right 24} - :ios {:opacity 0.5 - :margin-right 8 - :text-align :right}}) - -(defn details-item-content [name?] - {:font-size 15 - :flex-shrink 1 - :color (if name? common/color-light-blue common/color-white)}) - -(defstyle details-data - {:padding 16 - :margin-top 16 - :background-color common/color-dark-blue-3 - :ios {:margin-horizontal 16}}) - -(defstyle details-data-title - {:font-size 15 - :color common/color-white - :android {:opacity 0.2} - :ios {:opacity 0.5}}) - -(def details-data-content - {:font-size 15 - :color common/color-white - :margin-top 8}) - -;; confirmation-success - -(def success-screen - {:flex 1 - :background-color common/color-dark-blue-2}) - -(def success-screen-content-container - {:flex 1 - :align-items :center - :justify-content :center}) - -(def success-icon-container - {:background-color common/color-light-blue - :border-radius 100 - :height 133 - :width 133 - :justify-content :center - :align-items :center}) - -(def success-icon - {:height 40 - :width 54}) - -(def success-text - {:font-size 17 - :color common/color-light-blue3 - :margin-top 26}) diff --git a/src/status_im/transactions/subs.cljs b/src/status_im/transactions/subs.cljs deleted file mode 100644 index 7cbcf7ed7b..0000000000 --- a/src/status_im/transactions/subs.cljs +++ /dev/null @@ -1,24 +0,0 @@ -(ns status-im.transactions.subs - (:require [re-frame.core :refer [reg-sub subscribe]] - [status-im.utils.hex :as i])) - -(reg-sub :transactions - (fn [db] - (vals (:transactions db)))) - -(reg-sub :contacts-by-address - (fn [db] - (into {} (map (fn [[_ {:keys [address] :as contact}]] - (when address - [address contact])) - (:contacts/contacts db))))) - -(reg-sub :contact-by-address - :<- [:contacts-by-address] - (fn [contacts [_ address]] - (let [address' (when address - (i/normalize-hex address))] - (contacts address')))) - -(reg-sub :wrong-password? - (fn [db] (:wrong-password? db))) diff --git a/src/status_im/transactions/views/list_item.cljs b/src/status_im/transactions/views/list_item.cljs deleted file mode 100644 index ea6438d03c..0000000000 --- a/src/status_im/transactions/views/list_item.cljs +++ /dev/null @@ -1,40 +0,0 @@ -(ns status-im.transactions.views.list-item - (:require-macros [status-im.utils.views :refer [defview]]) - (:require [re-frame.core :as rf] - [status-im.components.chat-icon.screen :as chat-icon] - [status-im.components.react :as rn] - [status-im.i18n :as i18n] - [status-im.transactions.styles.list-item :as st] - [status-im.utils.money :as money])) - -(defview item-image [contact] - [rn/view {:style st/item-photo} - (if-not (empty? contact) - [chat-icon/chat-icon (:photo-path contact) {:size st/photo-size}] - [rn/view {:style st/photo-placeholder}]) - [rn/image {:source {:uri :icon_arrow_left_white} - :style st/item-photo-icon}]]) - -(defn item-info [recipient-name value] - [rn/view {:style st/item-info} - [rn/text {:style st/item-info-recipient - :number-of-lines 1} - recipient-name] - [rn/text {:style st/item-info-amount} value]]) - -(defn deny-btn [transaction-id on-deny] - [rn/touchable-highlight {:on-press #(do (rf/dispatch [:deny-transaction transaction-id]) - (when on-deny (on-deny)))} - [rn/view {:style st/item-deny-btn} - [rn/image {:source {:uri :icon_close_white} - :style st/item-deny-btn-icon}]]]) - -(defview view [{:keys [to value id] :as transaction} on-deny] - [recipient [:contact-by-address to]] - (let [eth-value (str (money/wei->ether value)) - value-str (str (i18n/label-number eth-value) " ETH") - recipient-name (or (:name recipient) to (i18n/label :t/contract-creation))] - [rn/view {:style st/item} - [item-image recipient] - [item-info recipient-name value-str] - [deny-btn id on-deny]])) diff --git a/src/status_im/transactions/views/password_form.cljs b/src/status_im/transactions/views/password_form.cljs deleted file mode 100644 index 3b7573423f..0000000000 --- a/src/status_im/transactions/views/password_form.cljs +++ /dev/null @@ -1,21 +0,0 @@ -(ns status-im.transactions.views.password-form - (:require-macros [status-im.utils.views :refer [defview]]) - (:require [re-frame.core :as rf] - [status-im.components.react :as rn] - [status-im.components.text-input-with-label.view :refer [text-input-with-label]] - [status-im.transactions.styles.password-form :as st] - [status-im.i18n :as i18n])) - -(defview view [transaction-quantity] - [wrong-password? [:wrong-password?]] - (let [error? wrong-password?] - [rn/view st/password-container - [text-input-with-label - {:label (i18n/label :t/password) - :description (i18n/label-pluralize transaction-quantity :t/enter-password-transactions) - :on-change-text #(rf/dispatch [:set-in [:confirm-transactions :password] %]) - :style {:color :white} - :auto-focus true - :secure-text-entry true - :error (when error? (i18n/label :t/wrong-password))}]])) - diff --git a/src/status_im/ui/screens/db.cljs b/src/status_im/ui/screens/db.cljs index e949e2d1f3..5fab6e8ff3 100644 --- a/src/status_im/ui/screens/db.cljs +++ b/src/status_im/ui/screens/db.cljs @@ -10,7 +10,6 @@ status-im.chat.specs status-im.chat.new-public-chat.db status-im.ui.screens.profile.db - status-im.transactions.specs status-im.ui.screens.discover.db status-im.ui.screens.network-settings.db)) @@ -172,15 +171,6 @@ :chat/raw-unviewed-messages :chat/bot-db :chat/geolocation - :transactions/transactions - :transactions/transactions-queue - :transactions/selected-transaction - :transactions/confirm-transactions - :transactions/confirmed-transactions-count - :transactions/transactions-list-ui-props - :transactions/transaction-details-ui-props - :transactions/wrong-password-counter - :transactions/wrong-password? :discoveries/discoveries :discoveries/discover-search-tags :discoveries/tags diff --git a/src/status_im/ui/screens/events.cljs b/src/status_im/ui/screens/events.cljs index af1273ab39..0fac9f6440 100644 --- a/src/status_im/ui/screens/events.cljs +++ b/src/status_im/ui/screens/events.cljs @@ -6,7 +6,6 @@ status-im.debug.handlers status-im.network.handlers status-im.protocol.handlers - status-im.transactions.handlers status-im.ui.screens.accounts.events status-im.ui.screens.contacts.events status-im.ui.screens.discover.events @@ -18,6 +17,8 @@ status-im.ui.screens.qr-scanner.events 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] @@ -348,10 +349,10 @@ (register-handler-fx :app-state-change - (fn [_ [_ state]] + (fn [_ [_ state]])) ;; TODO(rasom): let's not remove this handler, it will be used for ;; pausing node on entering background on android - )) + (register-handler-fx :request-permissions diff --git a/src/status_im/ui/screens/subs.cljs b/src/status_im/ui/screens/subs.cljs index b00caef87f..3be6d18bbf 100644 --- a/src/status_im/ui/screens/subs.cljs +++ b/src/status_im/ui/screens/subs.cljs @@ -13,7 +13,6 @@ status-im.ui.screens.wallet.send.subs status-im.ui.screens.wallet.request.subs status-im.ui.screens.network-settings.subs - status-im.transactions.subs status-im.bots.subs)) (reg-sub :get diff --git a/src/status_im/ui/screens/views.cljs b/src/status_im/ui/screens/views.cljs index c126cc7dd8..e61dc298f0 100644 --- a/src/status_im/ui/screens/views.cljs +++ b/src/status_im/ui/screens/views.cljs @@ -21,11 +21,6 @@ [status-im.ui.screens.qr-scanner.views :refer [qr-scanner]] - [status-im.transactions.screens.confirmation-success :refer [confirmation-success]] - [status-im.transactions.screens.unsigned-transactions :refer [unsigned-transactions]] - [status-im.transactions.screens.transaction-details :refer [transaction-details]] - - [status-im.ui.screens.group.views :refer [new-group edit-contact-group]] [status-im.ui.screens.group.chat-settings.views :refer [chat-group-settings]] [status-im.ui.screens.group.edit-contacts.views :refer [edit-contact-group-contact-list @@ -40,7 +35,7 @@ [status-im.ui.screens.profile.photo-capture.views :refer [profile-photo-capture]] [status-im.ui.screens.profile.qr-code.views :refer [qr-code-view]] - [status-im.ui.screens.wallet.send.views :refer [send-transaction]] + [status-im.ui.screens.wallet.send.views :refer [send-transaction send-transaction-modal]] [status-im.ui.screens.wallet.choose-recipient.views :refer [choose-recipient]] [status-im.ui.screens.wallet.request.views :refer [request-transaction]] [status-im.ui.screens.wallet.wallet-list.views :refer [wallet-list-screen]] @@ -109,8 +104,6 @@ :add-rpc-url add-rpc-url :network-details network-details (throw (str "Unknown view: " current-view)))] - - [(if android? menu-context view) common-styles/flex [view common-styles/flex [component] @@ -122,11 +115,8 @@ (let [component (case modal-view :qr-scanner qr-scanner :qr-code-view qr-code-view - :unsigned-transactions unsigned-transactions - :transaction-details transaction-details - :confirmation-success confirmation-success :contact-list-modal contact-list-modal :wallet-transactions-filter wallet-transactions/filter-history - :wallet-transactions-sign-all wallet-transactions/sign-all + :wallet-send-transaction-modal send-transaction-modal (throw (str "Unknown modal view: " modal-view)))] [component])]])]]))))) diff --git a/src/status_im/ui/screens/wallet/choose_recipient/events.cljs b/src/status_im/ui/screens/wallet/choose_recipient/events.cljs new file mode 100644 index 0000000000..147e810908 --- /dev/null +++ b/src/status_im/ui/screens/wallet/choose_recipient/events.cljs @@ -0,0 +1,26 @@ +(ns status-im.ui.screens.wallet.choose-recipient.events + (:require [status-im.utils.handlers :as handlers])) + +(handlers/register-handler-db + :wallet/toggle-flashlight + (fn [db] + (let [flashlight-state (get-in db [:wallet/send-transaction :camera-flashlight]) + toggled-state (if (= :on flashlight-state) :off :on)] + (assoc-in db [:wallet/send-transaction :camera-flashlight] toggled-state)))) + +(defn choose-address-and-name [db address name] + (update db :wallet/send-transaction assoc :to-address address :to-name name)) + +(handlers/register-handler-fx + :choose-recipient + (fn [{:keys [db]} [_ address name]] + (let [{:keys [view-id]} db] + (cond-> {:db (choose-address-and-name db address name)} + (= :choose-recipient view-id) (assoc :dispatch [:navigate-back]))))) + +(handlers/register-handler-fx + :wallet-open-send-transaction + (fn [{db :db} [_ address name]] + {:db (choose-address-and-name db address name) + :dispatch-n [[:navigate-back] + [:navigate-back]]})) \ No newline at end of file diff --git a/src/status_im/ui/screens/wallet/components/styles.cljs b/src/status_im/ui/screens/wallet/components/styles.cljs index 30b722d9e8..f4821eb027 100644 --- a/src/status_im/ui/screens/wallet/components/styles.cljs +++ b/src/status_im/ui/screens/wallet/components/styles.cljs @@ -21,7 +21,7 @@ :line-height 12}}) (def amount-text-input-container - {:margin-top 8}) + {:margin-top 8}) (def label-transparent (merge label @@ -61,6 +61,14 @@ :ios {:border-radius 8} :android {:border-radius 4}}) +(defstyle container-disabled + {:border-width 1 + :border-color styles/color-white-transparent-4 + :background-color nil + :ios {:border-radius 8} + :android {:border-radius 4}}) + + (defstyle recipient-container {:flex-direction :row :flex 1 diff --git a/src/status_im/ui/screens/wallet/components/views.cljs b/src/status_im/ui/screens/wallet/components/views.cljs index 9ceab4ff6b..50d77396b2 100644 --- a/src/status_im/ui/screens/wallet/components/views.cljs +++ b/src/status_im/ui/screens/wallet/components/views.cljs @@ -21,6 +21,17 @@ [react/text {:style styles/tooltip-text} label]] [vector-icons/icon :icons/tooltip-triangle {:color :white :style styles/tooltip-triangle}]]])) +;;TODO (andrey) temporary, should be removed later +(defn amount-input-disabled [amount] + [react/view components.styles/flex + [react/text {:style styles/label} (i18n/label :t/amount)] + [react/view styles/amount-text-input-container + [react/view (merge (styles/amount-container false) styles/container-disabled) + [react/text-input + {:editable false + :default-value amount + :style styles/text-input}]]]]) + (defn amount-input [] (let [active? (reagent/atom false)] (fn [& [{:keys [input-options style error]}]] @@ -53,6 +64,22 @@ style) [react/text {:style styles/wallet-name} "ETH"]]]) +(defn choose-recipient-disabled [{:keys [address name]}] + [react/view + [react/text {:style styles/label} (i18n/label :t/recipient)] + [react/view (merge styles/recipient-container + styles/container-disabled) + (when name + [react/view styles/recipient-name-container + [react/text {:style (styles/participant true) + :number-of-lines 1} + name]]) + [react/view components.styles/flex + [react/text {:style (styles/participant (not name)) + :number-of-lines 1 + :ellipsizeMode :middle} + address]]]]) + (defn choose-recipient [{:keys [address name on-press style]}] (let [address? (and (not (nil? address)) (not= address ""))] [react/touchable-highlight {:on-press on-press} diff --git a/src/status_im/ui/screens/wallet/events.cljs b/src/status_im/ui/screens/wallet/events.cljs index 7c62130076..57a4332063 100644 --- a/src/status_im/ui/screens/wallet/events.cljs +++ b/src/status_im/ui/screens/wallet/events.cljs @@ -136,3 +136,8 @@ (fn [{:keys [db]} [_ hash]] {:db (assoc-in db [:wallet :current-transaction] hash) :dispatch [:navigate-to :wallet-transaction-details]})) + +(handlers/register-handler-fx + :wallet/discard-unsigned-transaction + (fn [_ [_ transaction-id]] + {:discard-transaction transaction-id})) diff --git a/src/status_im/ui/screens/wallet/navigation.cljs b/src/status_im/ui/screens/wallet/navigation.cljs index 26685e2b51..3d205bdaef 100644 --- a/src/status_im/ui/screens/wallet/navigation.cljs +++ b/src/status_im/ui/screens/wallet/navigation.cljs @@ -20,4 +20,8 @@ [db [event]] (if (= event :navigate-back) db - (dissoc db :wallet/send-transaction))) \ No newline at end of file + (dissoc db :wallet/send-transaction))) + +(defmethod navigation/preload-data! :wallet-send-transaction-modal + [db [_ _ value]] + (assoc db :wallet/send-transaction value)) \ No newline at end of file diff --git a/src/status_im/ui/screens/wallet/send/db.cljs b/src/status_im/ui/screens/wallet/send/db.cljs index 5eb00c9147..97d4b379b1 100644 --- a/src/status_im/ui/screens/wallet/send/db.cljs +++ b/src/status_im/ui/screens/wallet/send/db.cljs @@ -7,6 +7,7 @@ (spec/def ::to-name (spec/nilable string?)) (spec/def ::amount-error (spec/nilable string?)) (spec/def ::password (spec/nilable string?)) +(spec/def ::wrong-password? (spec/nilable boolean?)) (spec/def ::transaction-id (spec/nilable string?)) (spec/def ::waiting-signal? (spec/nilable boolean?)) (spec/def ::signing? (spec/nilable boolean?)) @@ -17,5 +18,5 @@ (spec/def ::camera-flashlight #{:on :off}) (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 ::wrong-password? ::waiting-signal? ::signing? ::transaction-id ::later? ::camera-dimensions ::camera-flashlight])) diff --git a/src/status_im/ui/screens/wallet/send/events.cljs b/src/status_im/ui/screens/wallet/send/events.cljs index 173c6bb447..233b6dedb2 100644 --- a/src/status_im/ui/screens/wallet/send/events.cljs +++ b/src/status_im/ui/screens/wallet/send/events.cljs @@ -30,66 +30,58 @@ (fn [] (utils/show-popup (i18n/label :t/transaction-moved-title) (i18n/label :t/transaction-moved-text)))) -(re-frame/reg-fx - ::discard-transaction - (fn [id] - (status/discard-transaction id))) - ;;;; Handlers -(defn choose-address-and-name [db address name] - (update db :wallet/send-transaction assoc :to-address address :to-name name)) - (handlers/register-handler-fx - :choose-recipient - (fn [{:keys [db]} [_ address name]] - (let [{:keys [view-id]} db] - (cond-> {:db (choose-address-and-name db address name)} - (= :choose-recipient view-id) (assoc :dispatch [:navigate-back]))))) - -(handlers/register-handler-fx - :wallet-open-send-transaction - (fn [{db :db} [_ address name]] - {:db (choose-address-and-name db address name) - :dispatch-n [[:navigate-back] - [:navigate-back]]})) - -(handlers/register-handler-fx - :wallet-validate-amount - (fn [{{:keys [web3] :wallet/keys [send-transaction] :as db} :db} _] - (let [amount (:amount send-transaction) - error (wallet.db/get-amount-validation-error amount web3)] - {:db (assoc-in db [:wallet/send-transaction :amount-error] error)}))) + :wallet/set-and-validate-amount + (fn [{{:keys [web3] :wallet/keys [send-transaction] :as db} :db} [_ amount]] + (let [error (wallet.db/get-amount-validation-error amount web3)] + {:db (-> db + (assoc-in [:wallet/send-transaction :amount] amount) + (assoc-in [:wallet/send-transaction :amount-error] error))}))) (handlers/register-handler-fx ::transaction-completed (fn [{db :db} [_ {:keys [id response]}]] (let [{:keys [hash error]} response] + ;; error is handling in TRANSACTION FAILED signal from status-go (when-not (and error (string? error) (not (string/blank? error))) {:db (-> db + (update-in [:wallet :transactions-unsigned] dissoc id) (assoc-in [:wallet/send-transaction :transaction-id] nil) - (assoc :wrong-password? false)) + (assoc-in [:wallet/send-transaction :wrong-password?] false)) :dispatch [:navigate-to :wallet-transaction-sent]})))) (defn on-transactions-completed [raw-results] (let [results (:results (types/json->clj raw-results))] (doseq [result results] - ;;TODO (andrey) legacy, should be removed with old transactions screens - (re-frame/dispatch [:transaction-completed {:id (name (key result)) :response (second result)}]) (re-frame/dispatch [::transaction-completed {:id (name (key result)) :response (second result)}])))) (handlers/register-handler-fx - :wallet/transaction-queued - (fn [{{:wallet/keys [send-transaction] :as db} :db} [_ transaction-id]] - (let [{:keys [later? password]} send-transaction] + ::transaction-modal-completed + (fn [{db :db} [_ {:keys [id response]}]] + (let [{:keys [hash error]} response] + (when-not (and error (string? error) (not (string/blank? error))) + {:db (-> db + (update-in [:wallet :transactions-unsigned] dissoc id) + (assoc-in [:wallet/send-transaction :transaction-id] nil) + (assoc-in [:wallet/send-transaction :wrong-password?] false)) + :dispatch [:navigate-back]})))) + +(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 [{{:wallet/keys [send-transaction] :as db} :db} _] + (let [{:keys [later? password transaction-id]} send-transaction] (if later? - {:db (-> db - (assoc-in [:wallet/send-transaction :waiting-signal?] false) - (assoc :transactions (:transactions-queue db))) + {:db (assoc-in db [:wallet/send-transaction :waiting-signal?] false) :dispatch [:navigate-back] ::show-transaction-moved nil} - {:db (assoc-in db [:wallet/send-transaction :transaction-id] transaction-id) - ::accept-transaction {:id transaction-id + {::accept-transaction {:id transaction-id :password password :on-completed on-transactions-completed}})))) @@ -112,22 +104,30 @@ :to (:to-address send-transaction) :value amount-in-wei}})))) +(handlers/register-handler-fx + :wallet/sign-transaction-modal + (fn [{{:keys [web3] + :wallet/keys [send-transaction] + :accounts/keys [accounts current-account-id] :as db} :db} [_ later?]] + (let [{:keys [amount transaction-id password]} send-transaction + amount' (money/to-wei (string/replace amount #"," "."))] + {::accept-transaction {:id transaction-id + :password password + :on-completed on-transactions-modal-completed}}))) + (handlers/register-handler-fx :wallet/discard-transaction (fn [{{:wallet/keys [send-transaction] :as db} :db} _] (let [{:keys [transaction-id]} send-transaction] (merge {:db (-> db (update-in [:wallet/send-transaction] - #(assoc % :signing? false :transaction-id nil)) - (assoc :wrong-password? false))} + #(assoc % :signing? false :transaction-id nil :wrong-password? false)))} (when transaction-id - ;;TODO (andrey) use ::discard-transaction fx instead - {:dispatch-n [[:deny-transaction transaction-id] - [:status-im.transactions.handlers/remove-transaction transaction-id]]}))))) + {:discard-transaction transaction-id}))))) -(handlers/register-handler-db - :wallet/toggle-flashlight - (fn [db] - (let [flashlight-state (get-in db [:wallet/send-transaction :camera-flashlight]) - toggled-state (if (= :on flashlight-state) :off :on)] - (assoc-in db [:wallet/send-transaction :camera-flashlight] toggled-state)))) +(handlers/register-handler-fx + :wallet/cancel-signing-modal + (fn [{{:wallet/keys [send-transaction] :as db} :db} _] + (let [{:keys [transaction-id]} send-transaction] + {:db (update-in db [:wallet/send-transaction] + assoc :signing? false :wrong-password? false)}))) diff --git a/src/status_im/ui/screens/wallet/send/views.cljs b/src/status_im/ui/screens/wallet/send/views.cljs index d73b049d5e..65e608ba12 100644 --- a/src/status_im/ui/screens/wallet/send/views.cljs +++ b/src/status_im/ui/screens/wallet/send/views.cljs @@ -36,8 +36,7 @@ (defview sign-panel [] (letsubs [account [:get-current-account] - ;;TODO (andrey) use send-transaction map after we remove old transactions ui - wrong-password? [:get :wrong-password?];[:get-in [:wallet/send-transaction :wrong-password?]] + wrong-password? [:get-in [:wallet/send-transaction :wrong-password?]] signing-phrase (:signing-phrase @account) bottom-value (animation/create-value -250) opacity-value (animation/create-value 0)] @@ -58,14 +57,16 @@ (when wrong-password? [components/tooltip (i18n/label :t/wrong-password)])])) -(defview signing-buttons [] + +;; "Cancel" and "Sign Transaction >" buttons, signing with password +(defview signing-buttons [cancel-handler sign-handler] (letsubs [sign-enabled? [:wallet.send/sign-password-enabled?]] [react/view wallet.styles/buttons-container - [react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet/discard-transaction])} + [react/touchable-highlight {:on-press cancel-handler} [react/view (wallet.styles/button-container true) [components/button-text (i18n/label :t/cancel)]]] [react/view components.styles/flex] - [react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet/sign-transaction])} + [react/touchable-highlight {:on-press sign-handler} [react/view (wallet.styles/button-container sign-enabled?) [components/button-text (i18n/label :t/transactions-sign-transaction)] [vector-icons/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]])) @@ -76,12 +77,13 @@ (not (nil? to-address)) (not= to-address "") (not (nil? amount)) (not= amount ""))) -(defn- sign-buttons [amount-error to-address amount sufficient-funds?] +;; "Sign Later" and "Sign Transaction >" buttons +(defn- sign-buttons [amount-error to-address amount sufficient-funds? sign-later-handler] (let [sign-enabled? (sign-enabled? amount-error to-address amount) immediate-sign-enabled? (and sign-enabled? sufficient-funds?)] [react/view wallet.styles/buttons-container (when sign-enabled? - [react/touchable-highlight {:on-press sign-later} + [react/touchable-highlight {:on-press sign-later-handler} [react/view (wallet.styles/button-container sign-enabled?) [components/button-text (i18n/label :t/transactions-sign-later)]]]) [react/view components.styles/flex] @@ -119,13 +121,50 @@ :input-options {:auto-focus true :default-value amount :on-change-text #(let [value (string/trim %)] - (re-frame/dispatch [:set-in [:wallet/send-transaction :amount] value]) - (re-frame/dispatch [:wallet-validate-amount]))}}] + (re-frame/dispatch [:wallet/set-and-validate-amount value]))}}] [react/view wallet.styles/choose-currency-container [components/choose-currency wallet.styles/choose-currency]]]]] [components/separator] (if signing? - [signing-buttons] - [sign-buttons amount-error to-address amount sufficient-funds?]) + [signing-buttons + #(re-frame/dispatch [:wallet/discard-transaction]) + #(re-frame/dispatch [:wallet/sign-transaction])] + [sign-buttons amount-error to-address amount sufficient-funds? sign-later]) (when signing? - [sign-panel])]]))) \ No newline at end of file + [sign-panel])]]))) + +(defn toolbar-modal [] + [toolbar/toolbar2 {:style wallet.styles/toolbar} + [toolbar/nav-button (act/close-white act/default-handler)] + [toolbar/content-title {:color :white} (i18n/label :t/send-transaction)]]) + +(defview send-transaction-modal [] + (letsubs [amount [:get-in [:wallet/send-transaction :amount]] + amount-error [:get-in [:wallet/send-transaction :amount-error]] + signing? [:get-in [:wallet/send-transaction :signing?]] + to-address [:get-in [:wallet/send-transaction :to-address]] + to-name [:get-in [:wallet/send-transaction :to-name]] + recipient [:contact-by-address @to-name]] + [react/keyboard-avoiding-view wallet.styles/wallet-modal-container + [react/view components.styles/flex + [status-bar/status-bar {:type :wallet}] + [toolbar-modal] + [react/scroll-view {:keyboardShouldPersistTaps :always} + [react/view components.styles/flex + [react/view wallet.styles/choose-participant-container + [components/choose-recipient-disabled {:address to-address + :name (:name recipient)}]] + [react/view wallet.styles/choose-wallet-container + [components/choose-wallet]] + [react/view wallet.styles/amount-container + [components/amount-input-disabled amount] + [react/view wallet.styles/choose-currency-container + [components/choose-currency wallet.styles/choose-currency]]]]] + [components/separator] + (if signing? + [signing-buttons + #(re-frame/dispatch [:wallet/cancel-signing-modal]) + #(re-frame/dispatch [:wallet/sign-transaction-modal])] + [sign-buttons amount-error to-address amount true #(re-frame/dispatch [:navigate-back])]) + (when signing? + [sign-panel])]])) \ No newline at end of file diff --git a/src/status_im/ui/screens/wallet/transactions/events.cljs b/src/status_im/ui/screens/wallet/transactions/events.cljs new file mode 100644 index 0000000000..46a3609190 --- /dev/null +++ b/src/status_im/ui/screens/wallet/transactions/events.cljs @@ -0,0 +1,77 @@ +(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 [{{:wallet/keys [send-transaction] :as db} :db now :now} [_ {:keys [id message_id args] :as transaction}]] + (if (transaction-valid? transaction) + (let [{:keys [from to value data gas gasPrice]} args] + (let [;;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/to-decimal value) + :data data + :gas (money/to-decimal gas) + :gas-price (money/to-decimal gasPrice) + :timestamp now + :message-id message_id}] + (merge + {:db (-> db + (assoc-in [:wallet :transactions-unsigned id] transaction) + (assoc-in [:wallet/send-transaction :transaction-id] id))} + (if (:waiting-signal? send-transaction) + ;;sending from wallet + {:dispatch [:wallet.send-transaction/transaction-queued id]} + ;;sending from chat + {:dispatch [:navigate-to-modal :wallet-send-transaction-modal {:amount (str (money/wei->ether value)) + :transaction-id id + :to-address to + :to-name to}]})))) + {: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}]} + + ;;NO ERROR, TIMEOUT or DEFAULT ERROR + (merge + {:db (update-in db [:wallet :transactions-unsigned] dissoc id)} + (when (and message_id (= current-account-address transaction-initiator-address)) + {:dispatch [:set-chat-ui-props {:validation-messages error_message}]})))))) \ No newline at end of file diff --git a/src/status_im/ui/screens/wallet/transactions/subs.cljs b/src/status_im/ui/screens/wallet/transactions/subs.cljs index e38c0f8d98..2f8a513370 100644 --- a/src/status_im/ui/screens/wallet/transactions/subs.cljs +++ b/src/status_im/ui/screens/wallet/transactions/subs.cljs @@ -3,7 +3,8 @@ [status-im.i18n :as i18n] [status-im.utils.datetime :as datetime] [status-im.utils.money :as money] - [status-im.utils.transactions :as transactions])) + [status-im.utils.transactions :as transactions] + [status-im.utils.hex :as utils.hex])) (reg-sub :wallet.transactions/transactions-loading? :<- [:wallet] @@ -25,18 +26,23 @@ (fn [transactions] (group-by :type (vals transactions)))) -(defn format-unsigned-transaction [{:keys [message-id gas-price] :as transaction}] +(defn format-unsigned-transaction [{:keys [id] :as transaction}] (assoc transaction :type :unsigned :confirmations 0 :symbol "ETH" - :hash message-id)) + ;; TODO (andrey) revisit this, we shouldn't set not hash value to the hash field + :hash id)) + +(reg-sub :wallet/unsigned-transactions + (fn [db] + (vals (get-in db [:wallet :transactions-unsigned])))) (reg-sub :wallet.transactions/unsigned-transactions - :<- [:transactions] + :<- [:wallet/unsigned-transactions] (fn [transactions] - (reduce (fn [acc {:keys [message-id] :as transaction}] - (assoc acc message-id (format-unsigned-transaction transaction))) + (reduce (fn [acc {:keys [id] :as transaction}] + (assoc acc id (format-unsigned-transaction transaction))) {} transactions))) @@ -134,3 +140,19 @@ (if (>= confirmations max-confirmations) 100 (* 100 (/ confirmations max-confirmations)))))) + +(reg-sub + :contacts-by-address + (fn [db] + (into {} (map (fn [[_ {:keys [address] :as contact}]] + (when address + [address contact])) + (:contacts/contacts db))))) + +(reg-sub + :contact-by-address + :<- [:contacts-by-address] + (fn [contacts [_ address]] + (let [address' (when address + (utils.hex/normalize-hex address))] + (contacts address')))) diff --git a/src/status_im/ui/screens/wallet/transactions/views.cljs b/src/status_im/ui/screens/wallet/transactions/views.cljs index c250541c2d..4a65d787d9 100644 --- a/src/status_im/ui/screens/wallet/transactions/views.cljs +++ b/src/status_im/ui/screens/wallet/transactions/views.cljs @@ -26,10 +26,11 @@ (re-frame/dispatch [:accept-transactions password])) (defn on-delete-transaction - [m] - ;; TODO(yenda) implement - (utils/show-popup "TODO" "Delete Transaction")) + [{:keys [id]}] + ;; TODO(andrey) implement alert + (re-frame/dispatch [:wallet/discard-unsigned-transaction id])) +;; TODO (andrey) implement (defn unsigned-action [unsigned-transactions-count] [toolbar/text-action {:disabled? (zero? unsigned-transactions-count) :handler #(re-frame/dispatch [:navigate-to-modal :wallet-transactions-sign-all])} @@ -45,37 +46,24 @@ [toolbar/content-title (i18n/label :t/transactions)] (case @view-id :wallet-transactions-unsigned - [unsigned-action unsigned-transactions-count] + nil ;; TODO (andrey) implement [unsigned-action unsigned-transactions-count] :wallet-transactions-history [toolbar/actions [history-action]])]) -;; Sign all - -(defview sign-all [] - [] - [react/keyboard-avoiding-view {:style transactions.styles/sign-all-view} - [react/view {:style transactions.styles/sign-all-done} - [button/primary-button {:style transactions.styles/sign-all-done-button - :text (i18n/label :t/done) - :on-press #(re-frame/dispatch [:navigate-back])}]] - [react/view {:style transactions.styles/sign-all-popup} - [react/text {:style transactions.styles/sign-all-popup-sign-phrase} "one two three"] ;; TODO hook - [react/text {:style transactions.styles/sign-all-popup-text} (i18n/label :t/transactions-sign-all-text)] - [react/view {:style transactions.styles/sign-all-actions} - [react/text-input {:style transactions.styles/sign-all-input - :secure-text-entry true - :placeholder (i18n/label :t/transactions-sign-input-placeholder)}] - [button/primary-button {:text (i18n/label :t/transactions-sign-all) :on-press #(println %)}]]]]) - - -(defn action-buttons [m] +(defn action-buttons [{:keys [id to value] :as transaction}] [react/view {:style transactions.styles/action-buttons} - [button/primary-button {:text (i18n/label :t/transactions-sign) - :style {:margin-right 12} - :on-press #(re-frame/dispatch [:navigate-to-modal :wallet-transactions-sign-all])}] - [button/secondary-button {:text (i18n/label :t/delete) :on-press #(on-delete-transaction m)}]]) + [button/primary-button {:style {:margin-right 12} + :on-press #(re-frame/dispatch [:navigate-to-modal + :wallet-send-transaction-modal + {:amount (str (money/wei->ether value)) + :transaction-id id + :to-address to + :to-name to}])} + (i18n/label :t/transactions-sign)] + [button/secondary-button {:on-press #(on-delete-transaction transaction)} + (i18n/label :t/delete)]]) (defn- inbound? [type] (= "inbound" type)) (defn- unsigned? [type] (= "unsigned" type)) @@ -93,7 +81,7 @@ (:postponed :pending) (transaction-icon :icons/arrow-right styles/color-gray4-transparent styles/color-gray7) (throw (str "Unknown transaction type: " k)))) -(defn render-transaction [{:keys [hash to from type value symbol] :as m}] +(defn render-transaction [{:keys [hash to from type value symbol] :as transaction}] [list/touchable-item #(re-frame/dispatch [:show-transaction-details hash]) [react/view [list/item @@ -104,7 +92,7 @@ (str (i18n/label :t/from) " " from) (str (i18n/label :t/to) " " to)) (when (unsigned? type) - [action-buttons m])] + [action-buttons transaction])] [list/item-icon {:icon :icons/forward :style {:margin-top 10} :icon-opts transactions.styles/forward}]]]]) @@ -259,14 +247,14 @@ {:text (i18n/label :t/open-on-etherscan) :value #(.openURL react/linking url)}])]) (defview transaction-details [] - (letsubs [{:keys [hash url type] :as transactions} [:wallet.transactions/details] + (letsubs [{:keys [hash url type] :as transactions} [:wallet.transactions/transaction-details] confirmations [:wallet.transactions.details/confirmations] confirmations-progress [:wallet.transactions.details/confirmations-progress]] [react/view {:style styles/flex} [status-bar/status-bar] [toolbar/toolbar2 {} toolbar/default-nav-back - [toolbar/content-title (i18n/label :t/details)] + [toolbar/content-title (i18n/label :t/transaction-details)] [toolbar/actions (details-action hash url)]] [react/scroll-view {:style transactions.styles/main-section} [details-header transactions] diff --git a/src/status_im/utils/money.cljs b/src/status_im/utils/money.cljs index 280c2a3adb..10a3d77857 100644 --- a/src/status_im/utils/money.cljs +++ b/src/status_im/utils/money.cljs @@ -26,6 +26,9 @@ (defn to-wei [str] (dependencies/Web3.prototype.toWei str "ether")) +(defn to-decimal [value] + (dependencies/Web3.prototype.toDecimal value)) + (def eth-units {:wei (bignumber "1") :kwei (bignumber "1000")