Check minimum amount
Use string for inputs validate gas is not 0 Handle signed/unsigned transactions
This commit is contained in:
parent
8848b37433
commit
5a08383bde
|
@ -0,0 +1,53 @@
|
|||
(ns status-im.models.wallet
|
||||
(:require [status-im.utils.money :as money]))
|
||||
|
||||
(def min-gas-price-wei (money/bignumber 1))
|
||||
|
||||
(defmulti invalid-send-parameter? (fn [type _] type))
|
||||
|
||||
(defmethod invalid-send-parameter? :gas-price [_ value]
|
||||
(cond
|
||||
(not value) :invalid-number
|
||||
(< (money/->wei :gwei value) min-gas-price-wei) :not-enough-wei))
|
||||
|
||||
(defmethod invalid-send-parameter? :default [_ value]
|
||||
(when (or (not value)
|
||||
(<= value 0))
|
||||
:invalid-number))
|
||||
|
||||
(defn- calculate-max-fee
|
||||
[gas gas-price]
|
||||
(if (and gas gas-price)
|
||||
(money/to-fixed (money/wei->ether (.times gas gas-price)))
|
||||
"0"))
|
||||
|
||||
(defn- edit-max-fee [edit]
|
||||
(let [gas (get-in edit [:gas-price :value-number])
|
||||
gas-price (get-in edit [:gas :value-number])]
|
||||
(assoc edit :max-fee (calculate-max-fee gas gas-price))))
|
||||
|
||||
(defn add-max-fee [{:keys [gas gas-price] :as transaction}]
|
||||
(assoc transaction :max-fee (calculate-max-fee gas gas-price)))
|
||||
|
||||
(defn build-edit [edit-value key value]
|
||||
"Takes the previous edit, either :gas or :gas-price and a value as string.
|
||||
Wei for gas, and gwei for gas price.
|
||||
Validates them and sets max fee"
|
||||
(let [bn-value (money/bignumber value)
|
||||
invalid? (invalid-send-parameter? key bn-value)
|
||||
data (if invalid?
|
||||
{:value value
|
||||
:max-fee 0
|
||||
:invalid? invalid?}
|
||||
{:value value
|
||||
:value-number (if (= :gas-price key)
|
||||
(money/->wei :gwei bn-value)
|
||||
bn-value)
|
||||
:invalid? false})]
|
||||
(-> edit-value
|
||||
(assoc key data)
|
||||
edit-max-fee)))
|
||||
|
||||
(defn edit-value
|
||||
[key value {:keys [db]}]
|
||||
{:db (update-in db [:wallet :edit] build-edit key value)})
|
|
@ -454,6 +454,7 @@
|
|||
:share "Share"
|
||||
:eth "ETH"
|
||||
:gwei "Gwei"
|
||||
:wallet-send-min-wei "Min 1 wei"
|
||||
:currency "Currency"
|
||||
:usd-currency "USD"
|
||||
:currency-display-name-aed "Emirati Dirham"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.prices :as prices]
|
||||
[status-im.utils.transactions :as transactions]
|
||||
[status-im.models.wallet :as models.wallet]
|
||||
[taoensso.timbre :as log]
|
||||
status-im.ui.screens.wallet.request.events
|
||||
[status-im.utils.money :as money]
|
||||
|
@ -248,7 +249,11 @@
|
|||
:wallet/update-gas-price-success
|
||||
(fn [db [_ price edit?]]
|
||||
(if edit?
|
||||
(assoc-in db [:wallet :edit :gas-price] {:value price :invalid? false})
|
||||
(:db (models.wallet/edit-value
|
||||
:gas-price
|
||||
(money/to-fixed
|
||||
(money/wei-> :gwei price))
|
||||
{:db db}))
|
||||
(assoc-in db [:wallet :send-transaction :gas-price] price))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[status-im.utils.security :as security]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.models.wallet :as models.wallet]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[taoensso.timbre :as log]))
|
||||
|
@ -378,13 +379,8 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.send/edit-value
|
||||
(fn [{:keys [db]} [_ key value]]
|
||||
(let [bn-value (money/bignumber value)
|
||||
data (if bn-value
|
||||
{:value bn-value
|
||||
:invalid? false}
|
||||
{:invalid? true})]
|
||||
{:db (update-in db [:wallet :edit key] merge data)})))
|
||||
(fn [cofx [_ key value]]
|
||||
(models.wallet/edit-value key value cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.send/set-gas-details
|
||||
|
@ -400,11 +396,15 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.send/reset-gas-default
|
||||
(fn [{:keys [db]}]
|
||||
{:dispatch [:wallet/update-gas-price true]
|
||||
:db (assoc-in db [:wallet :edit :gas]
|
||||
{:value (ethereum/estimate-gas (-> db :wallet :send-transaction :symbol))
|
||||
:invalid? false})}))
|
||||
(fn [{:keys [db] :as cofx}]
|
||||
(let [gas-estimate (money/to-fixed
|
||||
(ethereum/estimate-gas
|
||||
(-> db :wallet :send-transaction :symbol)))]
|
||||
(assoc (models.wallet/edit-value
|
||||
:gas
|
||||
gas-estimate
|
||||
cofx)
|
||||
:dispatch [:wallet/update-gas-price true]))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:close-transaction-sent-screen
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.ui.screens.wallet.send.subs
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.models.wallet :as models.wallet]
|
||||
[status-im.utils.hex :as utils.hex]))
|
||||
|
||||
(re-frame/reg-sub ::send-transaction
|
||||
|
@ -54,9 +55,30 @@
|
|||
{:gas (or (:gas send-transaction) (:gas unsigned-transaction))
|
||||
:gas-price (or (:gas-price send-transaction) (:gas-price unsigned-transaction))}))))
|
||||
|
||||
(defn edit-or-transaction-data
|
||||
"Set up edit data structure, defaulting to transaction when not available"
|
||||
[transaction edit]
|
||||
(cond-> edit
|
||||
(not (get-in edit [:gas-price :value]))
|
||||
(models.wallet/build-edit
|
||||
:gas-price
|
||||
(money/to-fixed (money/wei-> :gwei (:gas-price transaction))))
|
||||
|
||||
(not (get-in edit [:gas :value]))
|
||||
(models.wallet/build-edit
|
||||
:gas
|
||||
(money/to-fixed (:gas transaction)))))
|
||||
|
||||
(re-frame/reg-sub :wallet/edit
|
||||
:<- [::send-transaction]
|
||||
:<- [::unsigned-transaction]
|
||||
:<- [:wallet]
|
||||
:edit)
|
||||
(fn [[send-transaction unsigned-transaction {:keys [edit]}]]
|
||||
(edit-or-transaction-data
|
||||
(if (:id send-transaction)
|
||||
unsigned-transaction
|
||||
send-transaction)
|
||||
edit)))
|
||||
|
||||
(defn sign-enabled? [amount-error to amount]
|
||||
(and
|
||||
|
@ -68,8 +90,11 @@
|
|||
:<- [::send-transaction]
|
||||
:<- [:balance]
|
||||
(fn [[{:keys [amount symbol] :as transaction} balance]]
|
||||
(assoc transaction :sufficient-funds? (or (nil? amount)
|
||||
(money/sufficient-funds? amount (get balance symbol))))))
|
||||
(-> transaction
|
||||
(models.wallet/add-max-fee)
|
||||
(assoc :sufficient-funds?
|
||||
(or (nil? amount)
|
||||
(money/sufficient-funds? amount (get balance symbol)))))))
|
||||
|
||||
(re-frame/reg-sub :wallet.send/unsigned-transaction
|
||||
:<- [::unsigned-transaction]
|
||||
|
@ -79,7 +104,7 @@
|
|||
(when transaction
|
||||
(let [contact (contacts (utils.hex/normalize-hex to))
|
||||
sufficient-funds? (money/sufficient-funds? value (get balance symbol))]
|
||||
(cond-> (assoc transaction
|
||||
(cond-> (assoc (models.wallet/add-max-fee transaction)
|
||||
:amount value
|
||||
:sufficient-funds? sufficient-funds?)
|
||||
contact (assoc :to-name (:name contact)))))))
|
||||
|
|
|
@ -92,10 +92,6 @@
|
|||
(i18n/label :t/transactions-sign-transaction)
|
||||
[vector-icons/icon :icons/forward {:color (if immediate-sign-enabled? :white :gray)}]]]))
|
||||
|
||||
(defn- max-fee [gas gas-price]
|
||||
(when (and gas gas-price)
|
||||
(money/wei->ether (.times gas gas-price))))
|
||||
|
||||
(defn return-to-transaction [dapp-transaction?]
|
||||
(if dapp-transaction?
|
||||
(re-frame/dispatch [:navigate-to-modal :wallet-send-transaction-modal])
|
||||
|
@ -116,12 +112,13 @@
|
|||
unsigned-transaction [:wallet.send/unsigned-transaction]
|
||||
network [:get-current-account-network]
|
||||
{gas-edit :gas
|
||||
max-fee :max-fee
|
||||
gas-price-edit :gas-price} [:wallet/edit]]
|
||||
(let [modal? (:id send-transaction)
|
||||
;;TODO(goranjovic) - unify unsigned and regular transaction subs
|
||||
{:keys [amount symbol] :as transaction} (if modal? unsigned-transaction send-transaction)
|
||||
gas (or (:value gas-edit) (:gas transaction))
|
||||
gas-price (or (:value gas-price-edit) (:gas-price transaction))
|
||||
gas (:value gas-edit)
|
||||
gas-price (:value gas-price-edit)
|
||||
{:keys [decimals]} (tokens/asset-for (ethereum/network->chain-keyword network) symbol)]
|
||||
[wallet.components/simple-screen {:status-bar-type :modal-wallet}
|
||||
[toolbar false modal? act/close-white
|
||||
|
@ -135,7 +132,7 @@
|
|||
[react/view styles/gas-input-wrapper
|
||||
[react/text-input (merge styles/transaction-fee-input
|
||||
{:on-change-text #(re-frame/dispatch [:wallet.send/edit-value :gas %])
|
||||
:default-value (str (money/to-fixed gas))
|
||||
:default-value gas
|
||||
:accessibility-label :gas-limit-input})]]]
|
||||
(when (:invalid? gas-edit)
|
||||
[tooltip/tooltip (i18n/label :t/invalid-number)])]
|
||||
|
@ -145,13 +142,15 @@
|
|||
(i18n/label :t/gas-price)
|
||||
[react/view styles/gas-input-wrapper
|
||||
[react/text-input (merge styles/transaction-fee-input
|
||||
{:on-change-text #(re-frame/dispatch [:wallet.send/edit-value :gas-price (money/->wei :gwei %)])
|
||||
:default-value (str (money/to-fixed (money/wei-> :gwei gas-price)))
|
||||
{:on-change-text #(re-frame/dispatch [:wallet.send/edit-value :gas-price %])
|
||||
:default-value gas-price
|
||||
:accessibility-label :gas-price-input})]
|
||||
[wallet.components/cartouche-secondary-text
|
||||
(i18n/label :t/gwei)]]]
|
||||
(when (:invalid? gas-price-edit)
|
||||
[tooltip/tooltip (i18n/label :t/invalid-number)])]]
|
||||
[tooltip/tooltip (i18n/label (if (= :invalid-number (:invalid? gas-price-edit))
|
||||
:t/invalid-number
|
||||
:t/wallet-send-min-wei))])]]
|
||||
|
||||
[react/view styles/transaction-fee-info
|
||||
[react/view styles/transaction-fee-info-icon
|
||||
|
@ -171,21 +170,22 @@
|
|||
(i18n/label :t/wallet-transaction-total-fee)
|
||||
[react/view {:accessibility-label :total-fee-input}
|
||||
[wallet.components/cartouche-text-content
|
||||
(str (money/to-fixed (max-fee gas gas-price)))
|
||||
(i18n/label :t/eth)]]]]
|
||||
(str max-fee " " (i18n/label :t/eth))]]]]
|
||||
|
||||
[bottom-buttons/bottom-buttons styles/fee-buttons
|
||||
[button/button {:on-press #(re-frame/dispatch [:wallet.send/reset-gas-default])
|
||||
:accessibility-label :reset-to-default-button}
|
||||
(i18n/label :t/reset-default)]
|
||||
[button/button {:on-press #(do (re-frame/dispatch [:wallet.send/set-gas-details gas gas-price])
|
||||
[button/button {:on-press #(do (re-frame/dispatch [:wallet.send/set-gas-details
|
||||
(:value-number gas-edit)
|
||||
(:value-number gas-price-edit)])
|
||||
(return-to-transaction modal?))
|
||||
:accessibility-label :done-button
|
||||
:disabled? (or (:invalid? gas-edit)
|
||||
(:invalid? gas-price-edit))}
|
||||
(i18n/label :t/done)]]]])))
|
||||
|
||||
(defn- advanced-cartouche [{:keys [gas gas-price]} modal?]
|
||||
(defn- advanced-cartouche [{:keys [max-fee gas gas-price]} modal?]
|
||||
[react/view
|
||||
[wallet.components/cartouche {:on-press #(do (re-frame/dispatch [:wallet.send/clear-gas])
|
||||
(re-frame/dispatch [:navigate-to-modal :wallet-transaction-fee]))}
|
||||
|
@ -193,7 +193,7 @@
|
|||
[react/view {:style styles/advanced-options-text-wrapper
|
||||
:accessibility-label :transaction-fee-button}
|
||||
[react/text {:style styles/advanced-fees-text}
|
||||
(str (money/to-fixed (max-fee gas gas-price)) " " (i18n/label :t/eth))]
|
||||
(str max-fee " " (i18n/label :t/eth))]
|
||||
[react/text {:style styles/advanced-fees-details-text}
|
||||
(str (money/to-fixed gas) " * " (money/to-fixed (money/wei-> :gwei gas-price)) (i18n/label :t/gwei))]]]])
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
(ns status-im.test.models.wallet
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.models.wallet :as model]))
|
||||
|
||||
(deftest valid-min-gas-price-test
|
||||
(testing "not an number"
|
||||
(is (= :invalid-number (model/invalid-send-parameter? :gas-price nil))))
|
||||
(testing "a number less than the minimum"
|
||||
(is (= :not-enough-wei (model/invalid-send-parameter? :gas-price (money/bignumber "0.0000000001")))))
|
||||
(testing "a number greater than the mininum"
|
||||
(is (not (model/invalid-send-parameter? :gas-price 3))))
|
||||
(testing "the minimum"
|
||||
(is (not (model/invalid-send-parameter? :gas-price (money/bignumber "0.000000001"))))))
|
||||
|
||||
(deftest valid-gas
|
||||
(testing "not an number"
|
||||
(is (= :invalid-number (model/invalid-send-parameter? :gas nil))))
|
||||
(testing "0"
|
||||
(is (= :invalid-number (model/invalid-send-parameter? :gas 0))))
|
||||
(testing "a number"
|
||||
(is (not (model/invalid-send-parameter? :gas 1)))))
|
||||
|
||||
(deftest build-edit-test
|
||||
(testing "an invalid edit"
|
||||
(let [actual (-> {}
|
||||
(model/build-edit :gas "invalid")
|
||||
(model/build-edit :gas-price "0.00000000001"))]
|
||||
(testing "it marks gas-price as invalid"
|
||||
(is (get-in actual [:gas-price :invalid?])))
|
||||
(testing "it does not change value"
|
||||
(is (= "0.00000000001" (get-in actual [:gas-price :value]))))
|
||||
(testing "it marks gas as invalid"
|
||||
(is (get-in actual [:gas :invalid?])))
|
||||
(testing "it does not change gas value"
|
||||
(is (= "invalid" (get-in actual [:gas :value]))))
|
||||
(testing "it sets max-fee to 0"
|
||||
(is (= "0" (:max-fee actual))))))
|
||||
(testing "an valid edit"
|
||||
(let [actual (-> {}
|
||||
(model/build-edit :gas "21000")
|
||||
(model/build-edit :gas-price "10"))]
|
||||
(testing "it does not mark gas-price as invalid"
|
||||
(is (not (get-in actual [:gas-price :invalid?]))))
|
||||
(testing "it sets the value in number for gas-price, in gwei"
|
||||
(is (= "10000000000" (str (get-in actual [:gas-price :value-number])))))
|
||||
(testing "it does not mark gas as invalid"
|
||||
(is (not (get-in actual [:gas :invalid?]))))
|
||||
(testing "it sets the value in number for gasi"
|
||||
(is (= "21000" (str (get-in actual [:gas :value-number])))))
|
||||
(testing "it calculates max-fee"
|
||||
(is (= "0.00021" (:max-fee actual)))))))
|
|
@ -15,6 +15,7 @@
|
|||
[status-im.test.models.account]
|
||||
[status-im.test.models.contact]
|
||||
[status-im.test.models.network]
|
||||
[status-im.test.models.wallet]
|
||||
[status-im.test.transport.core]
|
||||
[status-im.test.transport.inbox]
|
||||
[status-im.test.transport.handlers]
|
||||
|
@ -65,6 +66,7 @@
|
|||
'status-im.test.models.account
|
||||
'status-im.test.models.contact
|
||||
'status-im.test.models.network
|
||||
'status-im.test.models.wallet
|
||||
'status-im.test.bots.events
|
||||
'status-im.test.wallet.subs
|
||||
'status-im.test.wallet.transactions.subs
|
||||
|
|
Loading…
Reference in New Issue