bug #5171 - fixed incorrect amount validation in wallet request

Signed-off-by: Goran Jovic <goranjovic@gmail.com>
This commit is contained in:
Goran Jovic 2018-07-20 15:12:07 +02:00
parent 14be2c0d5e
commit a5d5ed3596
No known key found for this signature in database
GPG Key ID: 52B109CE27986F7F
5 changed files with 66 additions and 8 deletions

View File

@ -1,6 +1,5 @@
(ns status-im.ui.screens.wallet.db
(:require [clojure.string :as string]
[cljs.spec.alpha :as spec]
(:require [cljs.spec.alpha :as spec]
[status-im.i18n :as i18n]
status-im.ui.screens.wallet.request.db
status-im.ui.screens.wallet.send.db
@ -16,9 +15,14 @@
;; Placeholder namespace for wallet specs, which are a WIP depending on data
;; model we decide on for balances, prices, etc.
(defn- too-precise-amount? [amount decimals]
(let [amount-splited (string/split amount #"[.]")]
(and (= (count amount-splited) 2) (> (count (last amount-splited)) decimals))))
(defn- too-precise-amount?
"Checks if number has any extra digit beyond the allowed number of decimals.
It does so by checking the number against its rounded value."
[amount decimals]
(let [bn (money/bignumber amount)]
(not (.eq bn
(.round bn decimals)))))
(defn parse-amount [amount decimals]
(when-not (empty? amount)

View File

@ -35,7 +35,7 @@
(handlers/register-handler-fx
:wallet.request/set-and-validate-amount
(fn [{:keys [db]} [_ amount symbol decimals]]
(let [{:keys [value error]} (wallet-db/parse-amount amount symbol)]
(let [{:keys [value error]} (wallet-db/parse-amount amount decimals)]
{:db (-> db
(assoc-in [:wallet :request-transaction :amount] (money/formatted->internal value symbol decimals))
(assoc-in [:wallet :request-transaction :amount-text] amount)

View File

@ -53,7 +53,7 @@
token]]]
[bottom-buttons/bottom-buttons styles/bottom-buttons
nil ;; Force a phantom button to ensure consistency with other transaction screens which define 2 buttons
[button/button {:disabled? (not (and to amount))
[button/button {:disabled? (or amount-error (not (and to amount)))
:on-press #(re-frame/dispatch [:wallet-send-request whisper-identity amount symbol decimals])
:text-style {:padding-horizontal 0}
:accessibility-label :sent-request-button}

View File

@ -46,7 +46,8 @@
[status-im.test.utils.universal-links.core]
[status-im.test.utils.http]
[status-im.test.ui.screens.events]
[status-im.test.ui.screens.accounts.login.events]))
[status-im.test.ui.screens.accounts.login.events]
[status-im.test.ui.screens.wallet.db]))
(enable-console-print!)
@ -103,4 +104,5 @@
'status-im.test.utils.http
'status-im.test.ui.screens.events
'status-im.test.ui.screens.accounts.login.events
'status-im.test.ui.screens.wallet.db
'status-im.test.browser.events)

View File

@ -0,0 +1,52 @@
(ns status-im.test.ui.screens.wallet.db
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.ui.screens.wallet.db :as wallet.db]
[status-im.utils.money :as money]
[status-im.i18n :as i18n]))
(deftest test-too-precise-amount?
(testing "try both decimal and scientific or hex format"
(is (= false (wallet.db/too-precise-amount? "100" 2)))
(is (= false (wallet.db/too-precise-amount? "100" 0)))
(is (= true (wallet.db/too-precise-amount? "100.1" 0)))
(is (= false (wallet.db/too-precise-amount? "100.23" 2)))
(is (= true (wallet.db/too-precise-amount? "100.233" 2)))
(is (= true (wallet.db/too-precise-amount? "100.0000000000000000001" 18)))
(is (= false (wallet.db/too-precise-amount? "100.000000000000000001" 18)))
(is (= false (wallet.db/too-precise-amount? "1e-18" 18)))
(is (= true (wallet.db/too-precise-amount? "1e-19" 18)))
(is (= true (wallet.db/too-precise-amount? "0xa.a" 2))) ;; 0xa.a is 10.625
(is (= false (wallet.db/too-precise-amount? "0xa.a" 3)))
(is (= false (wallet.db/too-precise-amount? "1000" 3)))))
(defn- equal-results? [a b]
(and (= (:error a) (:error b))
(or (and (nil? (:amount a))
(nil? (:amount b)))
(.eq (:amount a) (:amount b)))))
(deftest test-parse-amount
(testing "test amount parsing"
(is (equal-results? {:value (money/bignumber "100")} (wallet.db/parse-amount "100" 2)))
(is (equal-results? {:value (money/bignumber "100")} (wallet.db/parse-amount "100" 0)))
(is (equal-results? {:error (i18n/label :t/validation-amount-is-too-precise {:decimals 0})
:value (money/bignumber "100.1")} (wallet.db/parse-amount "100.1" 0)))
(is (equal-results? {:value (money/bignumber "100.23")} (wallet.db/parse-amount "100.23" 2)))
(is (equal-results? {:error (i18n/label :t/validation-amount-is-too-precise {:decimals 2})
:value (money/bignumber "100.233")} (wallet.db/parse-amount "100.233" 2)))
(is (equal-results? {:error (i18n/label :t/validation-amount-is-too-precise {:decimals 18})
:value (money/bignumber "100.0000000000000000001")}
(wallet.db/parse-amount "100.0000000000000000001" 18)))
(is (equal-results? {:value (money/bignumber "100.000000000000000001")}
(wallet.db/parse-amount "100.000000000000000001" 18)))
(is (equal-results? {:value (money/bignumber "1e-18")} (wallet.db/parse-amount "1e-18" 18)))
(is (equal-results? {:error (i18n/label :t/validation-amount-is-too-precise {:decimals 18})
:value (money/bignumber "1e-19")} (wallet.db/parse-amount "1e-19" 18)))
(is (equal-results? {:error (i18n/label :t/validation-amount-is-too-precise {:decimals 2})
:value (money/bignumber "10.625")} (wallet.db/parse-amount "0xa.a" 2)))
(is (equal-results? {:value (money/bignumber "10.625")} (wallet.db/parse-amount "0xa.a" 3)))
(is (equal-results? {:error (i18n/label :t/validation-amount-invalid-number)
:value nil} (wallet.db/parse-amount "SOMETHING" 5)))
(is (nil? (wallet.db/parse-amount nil 5)))
(is (nil? (wallet.db/parse-amount "" 5)))
(is (equal-results? {:value (money/bignumber "1000")} (wallet.db/parse-amount "1000" 3)))))