[BUG #1990] Improved amount validation in wallet/send screen
This commit is contained in:
parent
10752aeb5e
commit
23eeadf95a
1
.env
1
.env
|
@ -1,5 +1,4 @@
|
|||
TESTFAIRY_ENABLED=0
|
||||
WALLET_WIP_ENABLED=1
|
||||
NOTIFICATIONS_WIP_ENABLED=1
|
||||
DEBUG_LOGS_ENABLED=1
|
||||
STUB_STATUS_GO=0
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
TESTFAIRY_ENABLED=1
|
||||
WALLET_WIP_ENABLED=1
|
||||
NOTIFICATIONS_WIP_ENABLED=1
|
||||
DEBUG_LOGS_ENABLED=1
|
||||
STUB_STATUS_GO=0
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
TESTFAIRY_ENABLED=0
|
||||
WALLET_WIP_ENABLED=0
|
||||
NOTIFICATIONS_WIP_ENABLED=0
|
||||
DEBUG_LOGS_ENABLED=0
|
|
@ -3,46 +3,34 @@
|
|||
[status-im.components.react :as react]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
(defn- button [{:keys [on-press style text text-style disabled? fit-to-text?]}]
|
||||
(defn button-text [{:keys [disabled? text-style]} label]
|
||||
[react/text {:style (merge (button.styles/button-text disabled?)
|
||||
text-style)
|
||||
:font (if platform/android? :medium :default)
|
||||
:uppercase? (get-in platform/platform-specific [:uppercase?])}
|
||||
label])
|
||||
|
||||
(defn button [{:keys [on-press style disabled? fit-to-text?] :as props} label]
|
||||
[react/touchable-highlight (merge {:underlay-color button.styles/border-color-high}
|
||||
(when-not fit-to-text?
|
||||
{:style button.styles/button-container})
|
||||
(when (and on-press
|
||||
(not disabled?))
|
||||
(when (and on-press (not disabled?))
|
||||
{:on-press on-press}))
|
||||
[react/view {:style (merge (button.styles/button disabled?)
|
||||
style)}
|
||||
[react/text {:style (merge (button.styles/button-text disabled?)
|
||||
text-style)
|
||||
:font :medium
|
||||
:uppercase? platform/android?}
|
||||
text]]])
|
||||
[button-text props
|
||||
label]]])
|
||||
|
||||
(defn primary-button [{:keys [style text-style] :as m}]
|
||||
(button (assoc m
|
||||
(defn primary-button [{:keys [style text-style] :as m} label]
|
||||
[button (assoc m
|
||||
:fit-to-text? true
|
||||
:style (merge button.styles/primary-button style)
|
||||
:text-style (merge button.styles/primary-button-text text-style))))
|
||||
:text-style (merge button.styles/primary-button-text text-style))
|
||||
label])
|
||||
|
||||
(defn secondary-button [{:keys [style text-style] :as m}]
|
||||
(button (assoc m
|
||||
(defn secondary-button [{:keys [style text-style] :as m} label]
|
||||
[button (assoc m
|
||||
:fit-to-text? true
|
||||
:style (merge button.styles/secondary-button style)
|
||||
:text-style (merge button.styles/secondary-button-text text-style))))
|
||||
|
||||
(defn- position [i v]
|
||||
(cond
|
||||
(zero? i) :first
|
||||
(= i (dec (count v))) :last
|
||||
:else :other))
|
||||
|
||||
(defn buttons
|
||||
([v] (buttons nil v))
|
||||
([{:keys [style button-text-style]} v]
|
||||
[react/view {:style (merge button.styles/buttons-container style)}
|
||||
(doall
|
||||
(map-indexed
|
||||
(fn [i m] ^{:key i} [button (merge m
|
||||
{:style (button.styles/button-bar (position i v))
|
||||
:text-style button-text-style})])
|
||||
v))]))
|
||||
:text-style (merge button.styles/secondary-button-text text-style))
|
||||
label])
|
||||
|
|
|
@ -362,6 +362,7 @@
|
|||
:wallet-total-value "Total value"
|
||||
:wallet-settings "Wallet Settings"
|
||||
:signing-phrase-description "Sign the transaction by entering your password. Make sure that the words above match your secret signing phrase"
|
||||
:wallet-insufficient-funds "Insufficient funds"
|
||||
:request-transaction "Request Transaction"
|
||||
:send-request "Send request"
|
||||
:share "Share"
|
||||
|
@ -385,7 +386,7 @@
|
|||
:view-transaction-details "View Transaction Details"
|
||||
:transaction-description "If you want to be sure you transaction will not be compromised wait until it gets at least 10 block confirmations"
|
||||
:transaction-sent "Transaction Sent"
|
||||
:transaction-moved-text "The transaction has ben successfully moved to “Unsigned”"
|
||||
:transaction-moved-text "The transaction has been successfully moved to “Unsigned”"
|
||||
:transaction-moved-title "Transaction Moved"
|
||||
:sign-later-title "Sign Transaction Later?"
|
||||
:sign-later-text "You will be able to sign in in the transaction history"
|
||||
|
@ -398,7 +399,8 @@
|
|||
:wallet-choose-from-contacts "Choose From Contacts"
|
||||
:wallet-address-from-clipboard "Use Address From Clipboard"
|
||||
:wallet-browse-photos "Browse Photos"
|
||||
:validation-amount-invalid-number "Amount is not valid number"
|
||||
:validation-amount-invalid "Amount is not valid"
|
||||
:validation-amount-invalid-number "Amount is not a valid number"
|
||||
:validation-amount-is-too-precise "Amount is too precise. The smallest unit you can send is 1 Wei (1x10^-18 ETH)"
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[reagent.core :as reagent]
|
||||
[status-im.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.components.animation :as animation]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.screens.wallet.components.animations :as animations]))
|
||||
|
||||
|
@ -73,16 +74,18 @@
|
|||
|
||||
;;TODO (andrey) this should be choose component with the list of wallets
|
||||
(views/defview choose-wallet [& [style]]
|
||||
(views/letsubs [eth-balance [:eth-balance]]
|
||||
(views/letsubs [balance [:balance]]
|
||||
[react/view
|
||||
[react/text {:style styles/label} (i18n/label :t/wallet)]
|
||||
[react/view (merge styles/wallet-container
|
||||
style)
|
||||
[react/text {:style styles/wallet-name} "Main wallet"]
|
||||
[react/text {:style styles/wallet-name} (i18n/label :t/main-wallet)]
|
||||
[react/text {:style styles/wallet-value
|
||||
:number-of-lines 1
|
||||
:ellipsizeMode :middle}
|
||||
(str eth-balance " ETH")]]]))
|
||||
(if balance
|
||||
(money/wei->str :eth balance)
|
||||
"...")]]]))
|
||||
|
||||
(defn network-label
|
||||
([n] (network-label [{} n]))
|
||||
|
|
|
@ -24,9 +24,12 @@
|
|||
(let [amount' (string/replace amount #"," ".")
|
||||
amount-splited (string/split amount' #"[.]")]
|
||||
(cond
|
||||
(or (nil? amount) (= amount "") (= amount "0") (re-matches #"0[,.]0*$" amount))
|
||||
(or (nil? amount) (= amount "") (re-matches #"0[,.]0*$" amount))
|
||||
nil
|
||||
|
||||
(= amount "0")
|
||||
(i18n/label :t/validation-amount-invalid)
|
||||
|
||||
(or (js/isNaN (js/parseFloat amount'))
|
||||
(try (when (<= (.toWei web3 amount' "ether") 0) true)
|
||||
(catch :default err true)))
|
||||
|
|
|
@ -12,11 +12,13 @@
|
|||
[status-im.i18n :as i18n]
|
||||
[status-im.react-native.resources :as resources]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.ui.screens.wallet.main.styles :as styles]
|
||||
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||
[status-im.components.styles :as components.styles]
|
||||
[status-im.components.button.styles :as button.styles]
|
||||
[status-im.ui.screens.wallet.views :as wallet.views]))
|
||||
|
||||
(defn- show-not-implemented! []
|
||||
|
@ -59,6 +61,11 @@
|
|||
(str (when pos-change? "+") change "%")
|
||||
"-%")]]))
|
||||
|
||||
(defn- wallet-send []
|
||||
(rf/dispatch [:navigate-to :wallet-send-transaction])
|
||||
(when platform/android?
|
||||
(rf/dispatch [:request-permissions [:camera]])))
|
||||
|
||||
(defn main-section [usd-value change error-message]
|
||||
[react/view {:style styles/main-section}
|
||||
(when error-message
|
||||
|
@ -71,17 +78,13 @@
|
|||
[react/text {:style styles/value-variation-title}
|
||||
(i18n/label :t/wallet-total-value)]
|
||||
[change-display change]]
|
||||
[btn/buttons {:style styles/buttons :button-text-style styles/main-button-text}
|
||||
[{:text (i18n/label :t/wallet-send)
|
||||
:on-press #(do (rf/dispatch [:navigate-to :wallet-send-transaction])
|
||||
(when platform/android?
|
||||
(rf/dispatch [:request-permissions [:camera]])))
|
||||
:disabled? (not config/wallet-wip-enabled?)}
|
||||
{:text (i18n/label :t/wallet-request)
|
||||
:on-press #(rf/dispatch [:navigate-to :wallet-request-transaction])
|
||||
:disabled? (not config/wallet-wip-enabled?)}
|
||||
{:text (i18n/label :t/wallet-exchange)
|
||||
:disabled? true}]]]])
|
||||
[react/view {:style (merge button.styles/buttons-container styles/buttons) :button-text-style styles/main-button-text}
|
||||
[btn/button {:on-press wallet-send :style (button.styles/button-bar :first)}
|
||||
(i18n/label :t/wallet-send)]
|
||||
[btn/button {:on-press #(rf/dispatch [:navigate-to :wallet-request-transaction]) :style (button.styles/button-bar :other)}
|
||||
(i18n/label :t/wallet-request)]
|
||||
[btn/button {:disabled? true :style (button.styles/button-bar :last)}
|
||||
(i18n/label :t/wallet-exchange)]]]])
|
||||
|
||||
(defn- token->image [id]
|
||||
(case id
|
||||
|
@ -115,14 +118,14 @@
|
|||
(let [{:keys [source style]} (token->image id)]
|
||||
[list/item-image source style])
|
||||
[react/view {:style styles/asset-item-value-container}
|
||||
[react/text {:style styles/asset-item-value} (str amount)]
|
||||
[react/text {:style styles/asset-item-value} (str (money/wei->ether amount))]
|
||||
[react/text {:style styles/asset-item-currency
|
||||
:uppercase? true}
|
||||
id]]]]
|
||||
[add-asset]))
|
||||
|
||||
(defn asset-section [eth prices-loading? balance-loading?]
|
||||
(let [assets [{:id "eth" :currency :eth :amount eth}]]
|
||||
(defn asset-section [balance prices-loading? balance-loading?]
|
||||
(let [assets [{:id "eth" :currency :eth :amount balance}]]
|
||||
[react/view {:style styles/asset-section}
|
||||
[react/text {:style styles/asset-section-title} (i18n/label :t/wallet-assets)]
|
||||
[list/flat-list
|
||||
|
@ -132,7 +135,7 @@
|
|||
:refreshing (boolean (or prices-loading? balance-loading?))}]]))
|
||||
|
||||
(defview wallet []
|
||||
(letsubs [eth-balance [:eth-balance]
|
||||
(letsubs [balance [:balance]
|
||||
portfolio-value [:portfolio-value]
|
||||
portfolio-change [:portfolio-change]
|
||||
prices-loading? [:prices-loading?]
|
||||
|
@ -142,4 +145,4 @@
|
|||
[toolbar-view]
|
||||
[react/view components.styles/flex
|
||||
[main-section portfolio-value portfolio-change error-message]
|
||||
[asset-section eth-balance prices-loading? balance-loading?]]]))
|
||||
[asset-section balance prices-loading? balance-loading?]]]))
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
: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 #"," "."))]
|
||||
amount-in-wei (money/to-wei (string/replace amount #"," "."))]
|
||||
(if transaction-id
|
||||
{::accept-transaction {:id transaction-id
|
||||
:password password
|
||||
|
@ -110,7 +110,7 @@
|
|||
::send-transaction {:web3 web3
|
||||
:from (get-in accounts [current-account-id :address])
|
||||
:to (:to-address send-transaction)
|
||||
:value amount'}}))))
|
||||
:value amount-in-wei}}))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet/discard-transaction
|
||||
|
|
|
@ -1,27 +1,24 @@
|
|||
(ns status-im.ui.screens.wallet.send.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [clojure.string :as str]
|
||||
[status-im.components.react :as react]
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.components.button.view :as button]
|
||||
[status-im.components.animation :as animation]
|
||||
[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.utils.utils :as utils]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.screens.wallet.send.styles :as send.styles]
|
||||
[status-im.components.icons.vector-icons :as vector-icons]
|
||||
[reagent.core :as r]
|
||||
[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.send.styles :as styles]
|
||||
[status-im.ui.screens.wallet.components.views :as components]
|
||||
[status-im.components.styles :as components.styles]
|
||||
[status-im.components.icons.vector-icons :as vi]
|
||||
[status-im.components.animation :as animation]
|
||||
[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.animations :as send.animations]
|
||||
[status-im.ui.screens.wallet.send.styles :as send.styles]))
|
||||
|
||||
(defn toolbar-view [signing?]
|
||||
[toolbar/toolbar2 {:style wallet.styles/toolbar}
|
||||
|
@ -45,24 +42,22 @@
|
|||
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 (styles/animated-sign-panel bottom-value)}
|
||||
[react/animated-view {:style (styles/sign-panel opacity-value)}
|
||||
[react/view styles/signing-phrase-container
|
||||
[react/text {:style styles/signing-phrase} signing-phrase]]
|
||||
[react/text {:style styles/signing-phrase-description} (i18n/label :t/signing-phrase-description)]
|
||||
[react/view styles/password-container
|
||||
[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 #(do
|
||||
(re-frame/dispatch [:set-in [:wallet/send-transaction :password] %]))
|
||||
:style styles/password}]]]
|
||||
:on-change-text #(re-frame/dispatch [:set-in [:wallet/send-transaction :password] %])
|
||||
:style send.styles/password}]]]
|
||||
(when wrong-password?
|
||||
[components/tooltip (i18n/label :t/wrong-password)])]))
|
||||
|
||||
|
||||
(defview signing-buttons []
|
||||
(letsubs [sign-enabled? [:wallet.send/sign-password-enabled?]]
|
||||
[react/view wallet.styles/buttons-container
|
||||
|
@ -73,52 +68,64 @@
|
|||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet/sign-transaction])}
|
||||
[react/view (wallet.styles/button-container sign-enabled?)
|
||||
[components/button-text (i18n/label :t/transactions-sign-transaction)]
|
||||
[vi/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]]))
|
||||
[vector-icons/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]]))
|
||||
|
||||
(defview sign-buttons []
|
||||
(letsubs [sign-enabled? [:wallet.send/sign-enabled?]]
|
||||
(defn sign-enabled? [amount-error to-address amount]
|
||||
(and
|
||||
(nil? amount-error)
|
||||
(not (nil? to-address)) (not= to-address "")
|
||||
(not (nil? amount)) (not= amount "")))
|
||||
|
||||
(defn- sign-buttons [amount-error to-address amount sufficient-funds?]
|
||||
(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/view (wallet.styles/button-container sign-enabled?)
|
||||
[components/button-text (i18n/label :t/transactions-sign-later)]]])
|
||||
[react/view components.styles/flex]
|
||||
[react/touchable-highlight {:on-press (when sign-enabled? #(re-frame/dispatch [:set-in [:wallet/send-transaction :signing?] true]))}
|
||||
[react/view (wallet.styles/button-container sign-enabled?)
|
||||
[react/touchable-highlight {:on-press (when immediate-sign-enabled? #(re-frame/dispatch [:set-in [:wallet/send-transaction :signing?] true]))}
|
||||
[react/view (wallet.styles/button-container immediate-sign-enabled?)
|
||||
[components/button-text (i18n/label :t/transactions-sign-transaction)]
|
||||
[vi/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]]))
|
||||
[vector-icons/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]]))
|
||||
|
||||
(defn- sufficient-funds? [amount balance]
|
||||
(<= amount (money/wei->ether balance)))
|
||||
|
||||
(defview send-transaction []
|
||||
(letsubs [amount [:get-in [:wallet/send-transaction :amount]]
|
||||
(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]]]
|
||||
[react/keyboard-avoiding-view wallet.styles/wallet-modal-container
|
||||
[react/view components.styles/flex
|
||||
[status-bar/status-bar {:type :wallet}]
|
||||
[toolbar-view signing?]
|
||||
[react/scroll-view {:keyboardShouldPersistTaps :always}
|
||||
(let [sufficient-funds? (sufficient-funds? amount balance)]
|
||||
[react/keyboard-avoiding-view wallet.styles/wallet-modal-container
|
||||
[react/view components.styles/flex
|
||||
[react/view wallet.styles/choose-participant-container
|
||||
[components/choose-recipient {:address to-address
|
||||
:name to-name
|
||||
:on-press #(re-frame/dispatch [:navigate-to :choose-recipient])}]]
|
||||
[react/view wallet.styles/choose-wallet-container
|
||||
[components/choose-wallet]]
|
||||
[react/view wallet.styles/amount-container
|
||||
[components/amount-input
|
||||
{:error amount-error
|
||||
:input-options {:auto-focus true
|
||||
:default-value amount
|
||||
:on-change-text #(do
|
||||
(re-frame/dispatch [:set-in [:wallet/send-transaction :amount] %])
|
||||
(re-frame/dispatch [:wallet-validate-amount]))}}]
|
||||
[react/view wallet.styles/choose-currency-container
|
||||
[components/choose-currency wallet.styles/choose-currency]]]]]
|
||||
[components/separator]
|
||||
(if signing?
|
||||
[signing-buttons]
|
||||
[sign-buttons])
|
||||
(when signing?
|
||||
[sign-panel])]]))
|
||||
[status-bar/status-bar {:type :wallet}]
|
||||
[toolbar-view signing?]
|
||||
[react/scroll-view {:keyboardShouldPersistTaps :always}
|
||||
[react/view components.styles/flex
|
||||
[react/view wallet.styles/choose-participant-container
|
||||
[components/choose-recipient {:address to-address
|
||||
:name to-name
|
||||
:on-press #(re-frame/dispatch [:navigate-to :choose-recipient])}]]
|
||||
[react/view wallet.styles/choose-wallet-container
|
||||
[components/choose-wallet]]
|
||||
[react/view wallet.styles/amount-container
|
||||
[components/amount-input
|
||||
{:error (or amount-error (when-not sufficient-funds? (i18n/label :t/wallet-insufficient-funds)))
|
||||
: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]))}}]
|
||||
[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?])
|
||||
(when signing?
|
||||
[sign-panel])]])))
|
|
@ -25,13 +25,6 @@
|
|||
(or (get-in wallet [:errors :balance-update])
|
||||
(get-in wallet [:errors :prices-update]))))
|
||||
|
||||
(reg-sub :eth-balance
|
||||
:<- [:balance]
|
||||
(fn [balance]
|
||||
(if balance
|
||||
(money/wei->ether balance)
|
||||
"...")))
|
||||
|
||||
(reg-sub :portfolio-value
|
||||
:<- [:balance]
|
||||
:<- [:price]
|
||||
|
|
|
@ -92,50 +92,50 @@
|
|||
|
||||
;; transaction details
|
||||
|
||||
(def transaction-details-row
|
||||
(def details-row
|
||||
{:flex-direction :row
|
||||
:margin-vertical 5})
|
||||
|
||||
(def transaction-details-item-label
|
||||
(def details-item-label
|
||||
{:flex 1
|
||||
:margin-right 10
|
||||
:color styles/color-gray4
|
||||
:font-size 14})
|
||||
|
||||
(def transaction-details-item-value-wrapper
|
||||
(def details-item-value-wrapper
|
||||
{:flex 5})
|
||||
|
||||
(def transaction-details-item-value
|
||||
(def details-item-value
|
||||
{:font-size 14
|
||||
:color styles/color-black})
|
||||
|
||||
(def transaction-details-item-extra-value
|
||||
(def details-item-extra-value
|
||||
{:font-size 14
|
||||
:color styles/color-gray4})
|
||||
|
||||
(def transaction-details-header
|
||||
(def details-header
|
||||
{:margin-horizontal 16
|
||||
:margin-top 10
|
||||
:flex-direction :row})
|
||||
|
||||
(def transaction-details-header-icon
|
||||
(def details-header-icon
|
||||
{:margin-vertical 7})
|
||||
|
||||
(def transaction-details-header-infos
|
||||
(def details-header-infos
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:margin-left 12
|
||||
:margin-vertical 7})
|
||||
|
||||
(def transaction-details-header-value
|
||||
(def details-header-value
|
||||
{:font-size 16
|
||||
:color styles/color-black})
|
||||
|
||||
(def transaction-details-header-date
|
||||
(def details-header-date
|
||||
{:font-size 14
|
||||
:color styles/color-gray4})
|
||||
|
||||
(def transaction-details-block
|
||||
(def details-block
|
||||
{:margin-horizontal 16})
|
||||
|
||||
(def progress-bar
|
||||
|
@ -152,17 +152,17 @@
|
|||
:background-color styles/color-blue2
|
||||
:opacity 0.30})
|
||||
|
||||
(def transaction-details-confirmations-count
|
||||
(def details-confirmations-count
|
||||
{:color styles/color-black
|
||||
:font-size 15
|
||||
:margin-vertical 2})
|
||||
|
||||
(def transaction-details-confirmations-helper-text
|
||||
(def details-confirmations-helper-text
|
||||
{:color styles/color-gray4
|
||||
:font-size 14
|
||||
:margin-vertical 2})
|
||||
|
||||
(def transaction-details-separator
|
||||
(def details-separator
|
||||
{:background-color styles/color-light-gray3
|
||||
:height 1
|
||||
:margin-vertical 10})
|
||||
|
|
|
@ -26,12 +26,11 @@
|
|||
(group-by :type (vals transactions))))
|
||||
|
||||
(defn format-unsigned-transaction [{:keys [message-id gas-price] :as transaction}]
|
||||
(-> transaction
|
||||
(update :value money/wei->ether)
|
||||
(assoc :type :unsigned
|
||||
:confirmations 0
|
||||
:symbol "ETH"
|
||||
:hash message-id)))
|
||||
(assoc transaction
|
||||
:type :unsigned
|
||||
:confirmations 0
|
||||
:symbol "ETH"
|
||||
:hash message-id))
|
||||
|
||||
(reg-sub :wallet.transactions/unsigned-transactions
|
||||
:<- [:transactions]
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.screens.wallet.transactions.styles :as transactions.styles]
|
||||
[status-im.ui.screens.wallet.views :as wallet.views]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.utils :as utils])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
|
@ -98,7 +99,7 @@
|
|||
[list/item
|
||||
[list/item-icon (transaction-type->icon (keyword type))]
|
||||
[list/item-content
|
||||
(str value " " symbol)
|
||||
(money/wei->str :eth value)
|
||||
(if (inbound? type)
|
||||
(str (i18n/label :t/from) " " from)
|
||||
(str (i18n/label :t/to) " " to))
|
||||
|
@ -205,66 +206,70 @@
|
|||
[toolbar-view view-id unsigned-transactions-count]
|
||||
[main-section view-id tabs]])))
|
||||
|
||||
(defn transaction-details-header [{:keys [value date type]}]
|
||||
[react/view {:style transactions.styles/transaction-details-header}
|
||||
[react/view {:style transactions.styles/transaction-details-header-icon}
|
||||
(defn- pretty-print-asset [symbol amount]
|
||||
(case symbol
|
||||
"ETH" (if amount (money/wei->str :eth amount) "...")))
|
||||
|
||||
(defn details-header [{:keys [value date type symbol]}]
|
||||
[react/view {:style transactions.styles/details-header}
|
||||
[react/view {:style transactions.styles/details-header-icon}
|
||||
[list/item-icon (transaction-type->icon type)]]
|
||||
[react/view {:style transactions.styles/transaction-details-header-infos}
|
||||
[react/text {:style transactions.styles/transaction-details-header-value} (str value " ETH")]
|
||||
[react/text {:style transactions.styles/transaction-details-header-date} date]]])
|
||||
[react/view {:style transactions.styles/details-header-infos}
|
||||
[react/text {:style transactions.styles/details-header-value} (pretty-print-asset symbol value)]
|
||||
[react/text {:style transactions.styles/details-header-date} date]]])
|
||||
|
||||
(defn progress-bar [progress]
|
||||
[react/view {:style transactions.styles/progress-bar}
|
||||
[react/view {:style (transactions.styles/progress-bar-done progress)}]
|
||||
[react/view {:style (transactions.styles/progress-bar-todo (- 100 progress))}]])
|
||||
|
||||
(defn transaction-details-confirmations [confirmations confirmations-progress]
|
||||
[react/view {:style transactions.styles/transaction-details-block}
|
||||
(defn details-confirmations [confirmations confirmations-progress]
|
||||
[react/view {:style transactions.styles/details-block}
|
||||
[progress-bar confirmations-progress]
|
||||
[react/text {:style transactions.styles/transaction-details-confirmations-count}
|
||||
[react/text {:style transactions.styles/details-confirmations-count}
|
||||
(str confirmations " " (i18n/label :t/confirmations))]
|
||||
[react/text {:style transactions.styles/transaction-details-confirmations-helper-text}
|
||||
[react/text {:style transactions.styles/details-confirmations-helper-text}
|
||||
(i18n/label :t/confirmations-helper-text)]])
|
||||
|
||||
(defn transaction-details-list-row
|
||||
(defn details-list-row
|
||||
([label value]
|
||||
(transaction-details-list-row label value nil))
|
||||
(details-list-row label value nil))
|
||||
([label value extra-value]
|
||||
[react/view {:style transactions.styles/transaction-details-row}
|
||||
[react/text {:style transactions.styles/transaction-details-item-label} (i18n/label label)]
|
||||
[react/view {:style transactions.styles/transaction-details-item-value-wrapper}
|
||||
[react/text {:style transactions.styles/transaction-details-item-value} (str value)]
|
||||
[react/text {:style transactions.styles/transaction-details-item-extra-value} (str extra-value)]]]))
|
||||
[react/view {:style transactions.styles/details-row}
|
||||
[react/text {:style transactions.styles/details-item-label} (i18n/label label)]
|
||||
[react/view {:style transactions.styles/details-item-value-wrapper}
|
||||
[react/text {:style transactions.styles/details-item-value} (str value)]
|
||||
[react/text {:style transactions.styles/details-item-extra-value} (str extra-value)]]]))
|
||||
|
||||
(defn transaction-details-list [{:keys [block hash from from-wallet to to-wallet gas-limit gas-price-gwei gas-price-eth gas-used cost nonce data]}]
|
||||
[react/view {:style transactions.styles/transaction-details-block}
|
||||
[transaction-details-list-row :t/block block]
|
||||
[transaction-details-list-row :t/hash hash]
|
||||
[transaction-details-list-row :t/from (or from-wallet from) (when from-wallet from)]
|
||||
[transaction-details-list-row :t/to (or to-wallet to) (when to-wallet to)]
|
||||
[transaction-details-list-row :t/gas-limit gas-limit]
|
||||
[transaction-details-list-row :t/gas-price gas-price-gwei gas-price-eth]
|
||||
[transaction-details-list-row :t/gas-used gas-used]
|
||||
[transaction-details-list-row :t/cost-fee cost]
|
||||
[transaction-details-list-row :t/nonce nonce]
|
||||
[transaction-details-list-row :t/data data]])
|
||||
(defn details-list [{:keys [block hash from from-wallet to to-wallet gas-limit gas-price-gwei gas-price-eth gas-used cost nonce data]}]
|
||||
[react/view {:style transactions.styles/details-block}
|
||||
[details-list-row :t/block block]
|
||||
[details-list-row :t/hash hash]
|
||||
[details-list-row :t/from (or from-wallet from) (when from-wallet from)]
|
||||
[details-list-row :t/to (or to-wallet to) (when to-wallet to)]
|
||||
[details-list-row :t/gas-limit gas-limit]
|
||||
[details-list-row :t/gas-price gas-price-gwei gas-price-eth]
|
||||
[details-list-row :t/gas-used gas-used]
|
||||
[details-list-row :t/cost-fee cost]
|
||||
[details-list-row :t/nonce nonce]
|
||||
[details-list-row :t/data data]])
|
||||
|
||||
(defn details-action [hash url]
|
||||
[(actions/opts [{:text (i18n/label :t/copy-transaction-hash) :value #(react/copy-to-clipboard hash)}
|
||||
{:text (i18n/label :t/open-on-etherscan) :value #(.openURL react/linking url)}])])
|
||||
|
||||
(defview transaction-details []
|
||||
(letsubs [{:keys [hash url type] :as transaction-details} [:wallet.transactions/transaction-details]
|
||||
confirmations [:wallet.transactions.details/confirmations]
|
||||
confirmations-progress [:wallet.transactions.details/confirmations-progress]]
|
||||
(letsubs [{:keys [hash url type] :as transactions} [:wallet.transactions/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/transaction-details)]
|
||||
[toolbar/content-title (i18n/label :t/details)]
|
||||
[toolbar/actions (details-action hash url)]]
|
||||
[react/scroll-view {:style transactions.styles/main-section}
|
||||
[transaction-details-header transaction-details]
|
||||
[transaction-details-confirmations confirmations confirmations-progress]
|
||||
[react/view {:style transactions.styles/transaction-details-separator}]
|
||||
[transaction-details-list transaction-details]]]))
|
||||
[details-header transactions]
|
||||
[details-confirmations confirmations confirmations-progress]
|
||||
[react/view {:style transactions.styles/details-separator}]
|
||||
[details-list transactions]]]))
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
(defn enabled? [v] (= "1" v))
|
||||
|
||||
(def testfairy-enabled? (enabled? (get-config :TESTFAIRY_ENABLED)))
|
||||
(def wallet-wip-enabled? (enabled? (get-config :WALLET_WIP_ENABLED 0)))
|
||||
(def notifications-wip-enabled? (enabled? (get-config :NOTIFICATIONS_WIP_ENABLED 0)))
|
||||
(def stub-status-go? (enabled? (get-config :STUB_STATUS_GO 0)))
|
||||
(def network-switching-enabled? (enabled? (get-config :NETWORK_SWITCHING 0)))
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
(str "https://" network-subdomain ".etherscan.io/api?module=account&action=txlist&address=0x"
|
||||
account "&startblock=0&endblock=99999999&sort=desc&apikey=YourApiKeyToken?q=json")))
|
||||
|
||||
(defn format-transaction [account {:keys [value timeStamp blockNumber hash from to gas gasPrice gasUsed nonce confirmations input]}]
|
||||
(defn- format-transaction [account {:keys [value timeStamp blockNumber hash from to gas gasPrice gasUsed nonce confirmations input]}]
|
||||
(let [inbound? (= (str "0x" account) to)]
|
||||
{:value (money/wei->ether value)
|
||||
{:value value
|
||||
;; timestamp is in seconds, we convert it in ms
|
||||
:timestamp (str timeStamp "000")
|
||||
:symbol "ETH"
|
||||
|
@ -36,7 +36,7 @@
|
|||
:confirmations confirmations
|
||||
:data input}))
|
||||
|
||||
(defn format-transactions-response [response account]
|
||||
(defn- format-transactions-response [response account]
|
||||
(->> response
|
||||
types/json->clj
|
||||
:result
|
||||
|
|
Loading…
Reference in New Issue