[bug] fix #2128 No feedback on insufficient funds from unsigned

- move current unsigned-transaction to wallet
- move some logic from view to subscriptions and events
This commit is contained in:
Eric Dvorsak 2017-10-13 14:54:50 +02:00 committed by Oskar Thorén
parent f4082951b7
commit 0707af2ad6
14 changed files with 257 additions and 228 deletions

View File

@ -6,12 +6,12 @@
(handlers/register-handler-db
:wallet/toggle-flashlight
(fn [db]
(let [flashlight-state (get-in db [:wallet/send-transaction :camera-flashlight])
(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))))
(assoc-in db [:wallet :send-transaction :camera-flashlight] toggled-state))))
(defn choose-address-and-name [db address name amount]
(update db :wallet/send-transaction assoc :to-address address :to-name name :amount amount))
(update-in db [:wallet :send-transaction] assoc :to-address address :to-name name :amount amount))
(defn- extract-details
"First try to parse as EIP67 URI, if not assume this is an address directly.
@ -28,13 +28,13 @@
;; isAddress works with or without address with leading '0x'
valid-address? (.isAddress web3 address)]
(cond-> {:db db}
(= :choose-recipient view-id) (assoc :dispatch [:navigate-back])
valid-address? (update :db #(choose-address-and-name % address name (:value m)))
(not valid-address?) (assoc :show-error (i18n/label :t/wallet-invalid-address {:data data}))))))
(= :choose-recipient view-id) (assoc :dispatch [:navigate-back])
valid-address? (update :db #(choose-address-and-name % address name (:value m)))
(not valid-address?) (assoc :show-error (i18n/label :t/wallet-invalid-address {:data data}))))))
(handlers/register-handler-fx
:wallet-open-send-transaction
(fn [{db :db} [_ address name]]
{:db (choose-address-and-name db address name nil)
:dispatch-n [[:navigate-back]
[:navigate-back]]}))
[:navigate-back]]}))

View File

@ -71,18 +71,18 @@
:style (styles/corner-right-bottom min-dimension)}]]))
(defview choose-recipient []
(letsubs [camera-dimensions [:camera-dimensions]
camera-flashlight [:camera-flashlight]
camera-permitted? [:get-in [:wallet/send-transaction :camera-permitted?]]]
(letsubs [camera-dimensions [:wallet.send/camera-dimensions]
camera-flashlight [:wallet.send/camera-flashlight]
camera-permitted? [:wallet.send/camera-permitted?]]
[react/view {:style styles/wallet-container}
[status-bar/status-bar {:type :wallet}]
[toolbar-view camera-flashlight]
[react/view {:style styles/qr-container
:pointerEvents :none
:on-layout #(let [layout (.. % -nativeEvent -layout)]
(re-frame/dispatch [:set-in [:wallet/send-transaction :camera-dimensions]
{:width (.-width layout)
:height (.-height layout)}]))}
[react/view {:style styles/qr-container
:pointerEvents :none
:on-layout #(let [layout (.. % -nativeEvent -layout)]
(re-frame/dispatch [:wallet.send/set-camera-dimensions
{:width (.-width layout)
:height (.-height layout)}]))}
(when (or platform/android?
camera-permitted?)[camera/camera {:style styles/preview
:aspect :fill

View File

@ -21,37 +21,29 @@
[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]}]]
(fn [& [{:keys [input-options style error disabled?]}]]
(let [{:keys [on-focus on-blur]} input-options]
[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 @active?) style)
[react/view (merge (styles/amount-container @active?) (if disabled? styles/container-disabled style))
[react/text-input
(merge
{:keyboard-type :numeric
:placeholder "0.000"
:placeholder-text-color "#ffffff66"
:selection-color :white
:style styles/text-input
:on-focus #(do (reset! active? true)
(when on-focus (on-focus)))
:on-blur #(do (reset! active? false)
(when on-blur (on-blur)))}
(dissoc input-options :on-focus :on-blur))]]
{:style styles/text-input}
(if disabled?
{:editable false}
{:keyboard-type :numeric
:placeholder "0.000"
:placeholder-text-color "#ffffff66"
:selection-color :white
:style styles/text-input
:on-focus #(do (reset! active? true)
(when on-focus (on-focus)))
:on-blur #(do (reset! active? false)
(when on-blur (on-blur)))})
(dissoc input-options :on-focus :on-blur))]]
(when-not (nil? error)
[tooltip error])]]))))
@ -124,4 +116,4 @@
(defn button-text [label]
[react/text {:style styles/button-text
:font (if platform/android? :medium :default)
:uppercase? (get-in platform/platform-specific [:uppercase?])} label])
:uppercase? (get-in platform/platform-specific [:uppercase?])} label])

View File

@ -13,7 +13,8 @@
(spec/def :wallet/send (spec/keys :req-un [:wallet.send/recipient]))
(spec/def :wallet/wallet (spec/keys :opt [:wallet/error]))
(spec/def :wallet/wallet (spec/keys :opt [:wallet/error]
:opt-un [ :wallet/send-transaction]))
;; Placeholder namespace for wallet specs, which are a WIP depending on data
;; model we decide on for balances, prices, etc.
@ -36,4 +37,4 @@
(i18n/label :t/validation-amount-invalid-number)
(too-precise-amount? normalized-amount)
(i18n/label :t/validation-amount-is-too-precise)))))
(i18n/label :t/validation-amount-is-too-precise)))))

View File

@ -137,6 +137,13 @@
{:db (assoc-in db [:wallet :current-transaction] hash)
:dispatch [:navigate-to :wallet-transaction-details]}))
(handlers/register-handler-fx
:wallet/show-sign-transaction
(fn [{:keys [db]} [_ id from-chat?]]
{:db (assoc-in db [:wallet :send-transaction] {:id id
:from-chat? from-chat?})
:dispatch [:navigate-to-modal :wallet-send-transaction-modal]}))
(handlers/register-handler-fx
:wallet/discard-unsigned-transaction
(fn [_ [_ transaction-id]]
@ -148,4 +155,4 @@
{:show-confirmation {:title (i18n/label :t/transactions-delete)
:content (i18n/label :t/transactions-delete-content)
:confirm-button-text (i18n/label :t/confirm)
:on-accept #(re-frame/dispatch [:wallet/discard-unsigned-transaction transaction-id])}}))
:on-accept #(re-frame/dispatch [:wallet/discard-unsigned-transaction transaction-id])}}))

View File

@ -20,8 +20,4 @@
[db [event]]
(if (= event :navigate-back)
db
(dissoc db :wallet/send-transaction)))
(defmethod navigation/preload-data! :wallet-send-transaction-modal
[db [_ _ value]]
(assoc db :wallet/send-transaction value))
(update db :wallet dissoc :send-transaction)))

View File

@ -8,7 +8,7 @@
(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 ::id (spec/nilable string?))
(spec/def ::waiting-signal? (spec/nilable boolean?))
(spec/def ::signing? (spec/nilable boolean?))
(spec/def ::later? (spec/nilable boolean?))
@ -18,10 +18,10 @@
(spec/def ::camera-flashlight #{:on :off})
(spec/def ::camera-permitted? boolean?)
(spec/def ::in-progress? boolean?)
(spec/def ::from-chat? boolean?)
(spec/def ::from-chat? (spec/nilable boolean?))
(spec/def :wallet/send-transaction (allowed-keys
:opt-un [::amount ::to-address ::to-name ::amount-error ::password
::waiting-signal? ::signing? ::transaction-id ::later?
::waiting-signal? ::signing? ::id ::later?
::camera-dimensions ::camera-flashlight ::in-progress?
::wrong-password? ::camera-permitted? ::from-chat?]))

View File

@ -34,13 +34,13 @@
(handlers/register-handler-fx
:wallet/set-and-validate-amount
(fn [{{:wallet/keys [send-transaction] :as db} :db} [_ amount]]
(fn [{:keys [db]} [_ amount]]
(let [error (wallet.db/get-amount-validation-error amount)]
{:db (-> db
(assoc-in [:wallet/send-transaction :amount] amount)
(assoc-in [:wallet/send-transaction :amount-error] error))})))
(assoc-in [:wallet :send-transaction :amount] amount)
(assoc-in [:wallet :send-transaction :amount-error] error))})))
(def ^:private clear-send-properties {:transaction-id nil
(def ^:private clear-send-properties {:id nil
:wrong-password? false
:waiting-signal? false
:from-chat? false})
@ -49,11 +49,11 @@
::transaction-completed
(fn [{db :db} [_ {:keys [id response]}]]
(let [{:keys [hash error]} response
db' (assoc-in db [:wallet/send-transaction :in-progress?] false)]
db' (assoc-in db [:wallet :send-transaction :in-progress?] false)]
(if-not (and error (string? error) (not (string/blank? error)))
{:db (-> db'
(update-in [:wallet :transactions-unsigned] dissoc id)
(update :wallet/send-transaction merge clear-send-properties))
(update-in [:wallet :send-transaction] merge clear-send-properties))
:dispatch [:navigate-to :wallet-transaction-sent]}
{:db db'}))))
@ -66,13 +66,13 @@
::transaction-modal-completed
(fn [{db :db} [_ {:keys [id response]}]]
(let [{:keys [hash error]} response
db' (assoc-in db [:wallet/send-transaction :in-progress?] false)
db' (assoc-in db [:wallet :send-transaction :in-progress?] false)
has-error? (and error (string? error) (not (string/blank? error)))]
(if has-error?
{:db db'}
{:db (-> db'
(update-in [:wallet :transactions-unsigned] dissoc id)
(update :wallet/send-transaction merge clear-send-properties))
(update-in [:wallet :send-transaction] merge clear-send-properties))
:dispatch [:navigate-back]}))))
(defn on-transactions-modal-completed [raw-results]
@ -82,56 +82,51 @@
(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]
(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)
{:db (assoc-in db [:wallet :send-transaction :waiting-signal?] false)
:dispatch [:navigate-back]
::show-transaction-moved nil}
{::accept-transaction {:id transaction-id
{::accept-transaction {:id id
:password password
:on-completed on-transactions-completed}}))))
(handlers/register-handler-fx
:wallet/sign-transaction
(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]
(if transaction-id
{::accept-transaction {:id transaction-id
(let [{:keys [amount id password to-address]} (get-in db [:wallet :send-transaction])]
(if id
{::accept-transaction {:id id
:password password
:on-completed on-transactions-completed}
:db (assoc-in db [:wallet/send-transaction :in-progress?] true)}
{:db (update 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 send-transaction)
:to to-address
:value (money/to-wei (money/normalize amount))}}))))
(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 [transaction-id password]} send-transaction]
{:db (assoc-in db [:wallet/send-transaction :in-progress?] true)
::accept-transaction {:id transaction-id
(let [{:keys [id password]} (get-in db [:wallet :send-transaction])]
{:db (assoc-in db [:wallet :send-transaction :in-progress?] true)
::accept-transaction {:id id
:password password
:on-completed on-transactions-modal-completed}})))
(defn discard-transaction
[{{:wallet/keys [send-transaction] :as db} :db}]
(let [{:keys [transaction-id]} send-transaction]
(merge {:db (update db :wallet/send-transaction assoc
:signing? false
:transaction-id nil
:wrong-password? false)}
(when transaction-id
{:discard-transaction transaction-id}))))
[{:keys [db]}]
(let [{:keys [id]} (get-in db [:wallet :send-transaction])]
(merge {:db (update-in db [:wallet :send-transaction] merge clear-send-properties)}
(when id
{:discard-transaction id}))))
(handlers/register-handler-fx
:wallet/discard-transaction
@ -147,7 +142,22 @@
(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)})))
(fn [{:keys [db]} _]
{:db (update-in db [:wallet :send-transaction] assoc
:signing? false
:wrong-password? false)}))
(handlers/register-handler-fx
:wallet.send/set-camera-dimensions
(fn [{:keys [db]} [_ camera-dimensions]]
{:db (assoc-in db [:wallet :send-transaction :camera-dimensions] camera-dimensions)}))
(handlers/register-handler-fx
:wallet.send/set-password
(fn [{:keys [db]} [_ password]]
{:db (assoc-in db [:wallet :send-transaction :password] password)}))
(handlers/register-handler-fx
:wallet.send/set-signing?
(fn [{:keys [db]} [_ signing?]]
{:db (assoc-in db [:wallet :send-transaction :signing?] signing?)}))

View File

@ -1,27 +1,76 @@
(ns status-im.ui.screens.wallet.send.subs
(:require [re-frame.core :as re-frame]))
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.utils.money :as money]
[status-im.utils.hex :as utils.hex]))
(re-frame/reg-sub :camera-dimensions
(fn [db]
(get-in db [:wallet/send-transaction :camera-dimensions])))
(re-frame/reg-sub ::send-transaction
:<- [:wallet]
(fn [wallet]
(:send-transaction wallet)))
(re-frame/reg-sub :camera-flashlight
(fn [db]
(get-in db [:wallet/send-transaction :camera-flashlight])))
(re-frame/reg-sub :wallet.send/camera-dimensions
:<- [::send-transaction]
(fn [send-transaction]
(:camera-dimensions send-transaction)))
(re-frame/reg-sub
:wallet.send/sign-enabled?
:<- [:get-in [:wallet/send-transaction :amount]]
:<- [:get-in [:wallet/send-transaction :to-address]]
:<- [:get-in [:wallet/send-transaction :amount-error]]
(fn [[amount to-address amount-error]]
(and
(nil? amount-error)
(not (nil? to-address)) (not= to-address "")
(not (nil? amount)) (not= amount ""))))
(re-frame/reg-sub :wallet.send/camera-flashlight
:<- [::send-transaction]
(fn [send-transaction]
(:camera-flashlight send-transaction)))
(re-frame/reg-sub
:wallet.send/sign-password-enabled?
:<- [:get-in [:wallet/send-transaction :password]]
(fn [password]
(re-frame/reg-sub :wallet.send/camera-permitted?
:<- [::send-transaction]
(fn [send-transaction]
(:camera-permitted? send-transaction)))
(re-frame/reg-sub :wallet.send/wrong-password?
:<- [::send-transaction]
(fn [send-transaction]
(:wrong-password? send-transaction)))
(re-frame/reg-sub :wallet.send/sign-password-enabled?
:<- [::send-transaction]
(fn [{:keys [password]}]
(and (not (nil? password)) (not= password ""))))
(re-frame/reg-sub ::unsigned-transactions
:<- [:wallet]
(fn [wallet]
(:transactions-unsigned wallet)))
(re-frame/reg-sub ::unsigned-transaction
:<- [::send-transaction]
:<- [::unsigned-transactions]
(fn [[send-transaction unsigned-transactions]]
(when-let [unsigned-transaction (get unsigned-transactions
(:id send-transaction))]
(merge send-transaction
unsigned-transaction))))
(defn sign-enabled? [amount-error to-address amount]
(and
(nil? amount-error)
(not (nil? to-address)) (not= to-address "")
(not (nil? amount)) (not= amount "")))
(re-frame/reg-sub :wallet.send/transaction
:<- [::send-transaction]
:<- [:balance]
(fn [[{:keys [amount to] :as transaction} balance]]
(assoc transaction :sufficient-funds? (or (nil? amount)
(money/sufficient-funds? amount balance)))))
(re-frame/reg-sub :wallet.send/unsigned-transaction
:<- [::unsigned-transaction]
:<- [:contacts/by-address]
:<- [:balance]
(fn [[{:keys [value to] :as transaction} contacts balance]]
(when transaction
(let [contact (contacts (utils.hex/normalize-hex to))
amount (str (.toFixed (money/wei->ether value)))
sufficient-funds? (money/sufficient-funds? amount balance)]
(cond-> (assoc transaction
:amount amount
:sufficient-funds? sufficient-funds?)
contact (assoc :to-name (:name contact)))))))

View File

@ -1,24 +1,23 @@
(ns status-im.ui.screens.wallet.send.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [re-frame.core :as re-frame]
[status-im.components.animation :as animation]
[status-im.components.camera :as camera]
[status-im.components.common.common :as common]
[status-im.components.icons.vector-icons :as vector-icons]
[status-im.components.react :as react]
[status-im.components.status-bar :as status-bar]
[status-im.components.styles :as components.styles]
[status-im.components.toolbar-new.actions :as act]
[status-im.components.toolbar-new.view :as toolbar]
[status-im.components.camera :as camera]
[status-im.components.common.common :as common]
[status-im.utils.utils :as utils]
[status-im.i18n :as i18n]
[status-im.ui.screens.wallet.components.views :as components]
[status-im.ui.screens.wallet.send.animations :as send.animations]
[status-im.ui.screens.wallet.send.styles :as send.styles]
[status-im.ui.screens.wallet.styles :as wallet.styles]
[status-im.utils.money :as money]
[status-im.utils.platform :as platform]
[status-im.ui.screens.wallet.request.styles :as request.styles]
[status-im.ui.screens.wallet.components.views :as components]
[status-im.ui.screens.wallet.styles :as wallet.styles]
[status-im.ui.screens.wallet.send.animations :as send.animations]
[status-im.ui.screens.wallet.send.styles :as send.styles]))
[status-im.utils.utils :as utils])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn toolbar-view [signing?]
[toolbar/toolbar2 {:style wallet.styles/toolbar}
@ -29,30 +28,30 @@
(defn sign-later []
(utils/show-question
(i18n/label :t/sign-later-title)
(i18n/label :t/sign-later-text)
#(re-frame/dispatch [:wallet/sign-transaction true])))
(i18n/label :t/sign-later-title)
(i18n/label :t/sign-later-text)
#(re-frame/dispatch [:wallet/sign-transaction true])))
(defview sign-panel []
(letsubs [account [:get-current-account]
wrong-password? [:get-in [:wallet/send-transaction :wrong-password?]]
wrong-password? [:wallet.send/wrong-password?]
signing-phrase (:signing-phrase @account)
bottom-value (animation/create-value -250)
opacity-value (animation/create-value 0)]
{:component-did-mount #(send.animations/animate-sign-panel opacity-value bottom-value)}
[react/animated-view {:style (send.styles/animated-sign-panel bottom-value)}
[react/animated-view {:style (send.styles/sign-panel opacity-value)}
[react/view send.styles/signing-phrase-container
[react/text {:style send.styles/signing-phrase} signing-phrase]]
[react/text {:style send.styles/signing-phrase-description} (i18n/label :t/signing-phrase-description)]
[react/view send.styles/password-container
[react/text-input
{:auto-focus true
:secure-text-entry true
:placeholder (i18n/label :t/enter-password)
:placeholder-text-color "#939ba1"
:on-change-text #(re-frame/dispatch [:set-in [:wallet/send-transaction :password] %])
:style send.styles/password}]]]
[react/animated-view {:style (send.styles/sign-panel opacity-value)}
[react/view send.styles/signing-phrase-container
[react/text {:style send.styles/signing-phrase} signing-phrase]]
[react/text {:style send.styles/signing-phrase-description} (i18n/label :t/signing-phrase-description)]
[react/view send.styles/password-container
[react/text-input
{:auto-focus true
:secure-text-entry true
:placeholder (i18n/label :t/enter-password)
:placeholder-text-color "#939ba1"
:on-change-text #(re-frame/dispatch [:wallet.send/set-password %])
:style send.styles/password}]]]
(when wrong-password?
[components/tooltip (i18n/label :t/wrong-password)])]))
@ -73,9 +72,9 @@
(defn sign-enabled? [amount-error to-address amount]
(and
(nil? amount-error)
(not (nil? to-address)) (not= to-address "")
(not (nil? amount)) (not= amount "")))
(nil? amount-error)
(not (nil? to-address)) (not= to-address "")
(not (nil? amount)) (not= amount "")))
;; "Sign Later" and "Sign Transaction >" buttons
(defn- sign-buttons [amount-error to-address amount sufficient-funds? sign-later-handler]
@ -88,31 +87,22 @@
[components/button-text (i18n/label :t/transactions-sign-later)]]])
[react/view components.styles/flex]
[react/touchable-highlight {:style wallet.styles/button
:on-press (when immediate-sign-enabled? #(re-frame/dispatch [:set-in [:wallet/send-transaction :signing?] true]))}
:on-press (when immediate-sign-enabled? #(re-frame/dispatch [:wallet.send/set-signing? true]))}
[react/view (wallet.styles/button-container immediate-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}]]]]))
(defn sufficient-funds? [amount-in-eth balance]
(.greaterThanOrEqualTo balance (money/bignumber (money/to-wei amount-in-eth))))
(defn request-camera-permissions []
(when platform/android?
(re-frame/dispatch [:request-permissions [:camera]]))
(camera/request-access
(fn [permitted?]
(re-frame/dispatch [:set-in [:wallet/send-transaction :camera-permitted?] permitted?])
(re-frame/dispatch [:set-in [:wallet :send-transaction :camera-permitted?] permitted?])
(re-frame/dispatch [:navigate-to :choose-recipient]))))
(defview send-transaction []
(letsubs [balance [:balance]
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]]
in-progress? [:get-in [:wallet/send-transaction :in-progress?]]]
(let [sufficient-funds? (or (nil? amount) (sufficient-funds? amount balance))]
(letsubs [transaction [:wallet.send/transaction]]
(let [{:keys [amount amount-error signing? to-address to-name in-progress? sufficient-funds?]} transaction]
[react/keyboard-avoiding-view wallet.styles/wallet-modal-container
[react/view components.styles/flex
[status-bar/status-bar {:type :wallet}]
@ -154,37 +144,34 @@
[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]
in-progress? [:get-in [:wallet/send-transaction :in-progress?]]
from-chat? [:get-in [:wallet/send-transaction :from-chat?]]]
[react/keyboard-avoiding-view wallet.styles/wallet-modal-container
[react/view components.styles/flex
[status-bar/status-bar {:type :modal-wallet}]
[toolbar-modal from-chat?]
[common/network-info {:text-color :white}]
[react/scroll-view {:keyboardShouldPersistTaps :always}
(letsubs [transaction [:wallet.send/unsigned-transaction]]
(let [{:keys [amount amount-error signing? to to-name sufficient-funds? in-progress? from-chat?]} transaction]
[react/keyboard-avoiding-view wallet.styles/wallet-modal-container
[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])
in-progress?]
[sign-buttons amount-error to-address amount true #(re-frame/dispatch [:navigate-back])])
(when signing?
[sign-panel])]
(when in-progress? [react/view send.styles/processing-view])]))
[status-bar/status-bar {:type :modal-wallet}]
[toolbar-modal from-chat?]
[common/network-info {:text-color :white}]
[react/scroll-view {:keyboardShouldPersistTaps :always}
[react/view components.styles/flex
[react/view wallet.styles/choose-participant-container
[components/choose-recipient-disabled {:address to
:name to-name}]]
[react/view wallet.styles/choose-wallet-container
[components/choose-wallet]]
[react/view wallet.styles/amount-container
[components/amount-input
{:error (when-not sufficient-funds? (i18n/label :t/wallet-insufficient-funds))
:disabled? true
:input-options {:default-value 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])
in-progress?]
[sign-buttons amount-error to amount sufficient-funds? #(re-frame/dispatch [:navigate-back])])
(when signing?
[sign-panel])
(when in-progress? [react/view send.styles/processing-view])]])))

View File

@ -21,39 +21,35 @@
;;Handlers
;TRANSACTION QUEUED signal from status-go
;;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}]]
(fn [{:keys [db 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/bignumber 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
:from-chat? true}]}))))
(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}]
(merge
{:db (-> db
(assoc-in [:wallet :transactions-unsigned id] transaction)
(assoc-in [:wallet :send-transaction :id] id))}
(if (get-in db [:wallet :send-transaction :waiting-signal?])
;;sending from wallet
{:dispatch [:wallet.send-transaction/transaction-queued id]}
;;sending from chat
{:dispatch [:navigate-to-modal :wallet-send-transaction-modal id :from-chat]})))
{:discard-transaction id})))
;TRANSACTION FAILED signal from status-go
;;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}]]
@ -63,7 +59,7 @@
;;WRONG PASSWORD
constants/send-transaction-password-error-code
{:db (assoc-in db [:wallet/send-transaction :wrong-password?] true)}
{:db (assoc-in db [:wallet :send-transaction :wrong-password?] true)}
;;TODO (andrey) something weird here below, revisit
;;DISCARDED
@ -73,6 +69,6 @@
;;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}]}))))))
{: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}]}))))))

View File

@ -160,10 +160,3 @@
(if (>= confirmations max-confirmations)
100
(* 100 (/ confirmations max-confirmations))))))
(reg-sub :contact-by-address
:<- [:contacts/by-address]
(fn [contacts [_ address]]
(let [address' (when address
(utils.hex/normalize-hex address))]
(contacts address'))))

View File

@ -50,12 +50,7 @@
(defn action-buttons [{:keys [id to value] :as transaction}]
[react/view {:style transactions.styles/action-buttons}
[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}])}
:on-press #(re-frame/dispatch [:wallet/show-sign-transaction id])}
(i18n/label :t/transactions-sign)]
[button/secondary-button {:on-press #(on-delete-transaction transaction)}
(i18n/label :t/delete)]])

View File

@ -85,3 +85,6 @@
(defn with-precision [n decimals]
(.round (bignumber n) decimals))
(defn sufficient-funds? [amount-in-eth balance]
(.greaterThanOrEqualTo balance (bignumber (to-wei amount-in-eth))))