From 521f39b6fbdc0099dac8585e3453aea4197ca7e8 Mon Sep 17 00:00:00 2001 From: mmilad75 <55688834+mmilad75@users.noreply.github.com> Date: Wed, 24 Jan 2024 16:37:47 +0330 Subject: [PATCH] No ability to enter/paste assets exceeds the users's balance #18526 (#18599) * change functionality * fix handle-swap * fix lint issues * update tests * change error to error? * change reset-input-error * update tests * fix lint issues --- .../components/wallet/token_input/style.cljs | 8 ++- .../components/wallet/token_input/view.cljs | 11 ++-- .../preview/quo/wallet/token_input.cljs | 4 +- .../send/input_amount/component_spec.cljs | 54 +++++-------------- .../wallet/send/input_amount/view.cljs | 37 ++++++++----- 5 files changed, 54 insertions(+), 60 deletions(-) diff --git a/src/quo/components/wallet/token_input/style.cljs b/src/quo/components/wallet/token_input/style.cljs index bef187a3a9..772692c2c2 100644 --- a/src/quo/components/wallet/token_input/style.cljs +++ b/src/quo/components/wallet/token_input/style.cljs @@ -49,8 +49,12 @@ :height "100%"))) (defn text-input - [theme] - (assoc text-input-dimensions :color (colors/theme-colors colors/neutral-100 colors/white theme))) + [theme error?] + (assoc text-input-dimensions + :color + (if error? + (colors/resolve-color :danger theme) + (colors/theme-colors colors/neutral-100 colors/white theme)))) (defn placeholder-text [theme] diff --git a/src/quo/components/wallet/token_input/view.cljs b/src/quo/components/wallet/token_input/view.cljs index e992d1cb42..7ee37a9168 100644 --- a/src/quo/components/wallet/token_input/view.cljs +++ b/src/quo/components/wallet/token_input/view.cljs @@ -32,9 +32,12 @@ (crypto-format num-value conversion crypto-decimals token)))) (defn- data-info - [{:keys [theme token crypto-decimals conversion networks title crypto? currency amount]}] + [{:keys [theme token crypto-decimals conversion networks title crypto? currency amount error?]}] [rn/view {:style style/data-container} - [network-tag/view {:networks networks :title title}] + [network-tag/view + {:networks networks + :title title + :status (when error? :error)}] [text/text {:size :paragraph-2 :weight :medium @@ -80,7 +83,7 @@ (reset! value-atom v)) (when on-change-text (on-change-text v)))] - (fn [{:keys [theme token customization-color show-keyboard? crypto? currency value] + (fn [{:keys [theme token customization-color show-keyboard? crypto? currency value error?] :or {show-keyboard? true}}] [rn/pressable {:on-press focus-input @@ -90,7 +93,7 @@ :size :size-32}] [rn/view {:style style/text-input-container} [rn/text-input - (cond-> {:style (style/text-input theme) + (cond-> {:style (style/text-input theme error?) :placeholder-text-color (style/placeholder-text theme) :auto-focus true :ref set-ref diff --git a/src/status_im/contexts/preview/quo/wallet/token_input.cljs b/src/status_im/contexts/preview/quo/wallet/token_input.cljs index cfdb3c1728..b4b2f75f39 100644 --- a/src/status_im/contexts/preview/quo/wallet/token_input.cljs +++ b/src/status_im/contexts/preview/quo/wallet/token_input.cljs @@ -21,7 +21,9 @@ {:key :currency :type :select :options [{:key :usd} - {:key :eur}]}]) + {:key :eur}]} + {:key :error? + :type :boolean}]) (defn view [] diff --git a/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs b/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs index 54eb8902d3..288f4e398c 100644 --- a/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs +++ b/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs @@ -57,6 +57,7 @@ (h/is-truthy (h/get-by-text "0")) (h/is-truthy (h/get-by-text "ETH")) (h/is-truthy (h/get-by-text "$0.00")) + (h/is-truthy (h/get-by-label-text :container)) (h/is-disabled (h/get-by-label-text :button-one))) (h/test "Fill token input and confirm" @@ -77,6 +78,7 @@ (-> (h/wait-for #(h/get-by-text "$1234.50")) (.then (fn [] (h/is-truthy (h/get-by-label-text :button-one)) + (h/is-truthy (h/get-by-label-text :container)) (h/fire-event :press (h/get-by-label-text :button-one)) (h/was-called on-confirm)))))) @@ -99,61 +101,33 @@ (-> (h/wait-for #(h/get-by-text "$1234.50")) (.then (fn [] (h/is-truthy (h/get-by-label-text :button-one)) + (h/is-truthy (h/get-by-label-text :container)) (h/fire-event :press (h/get-by-label-text :button-one)) (h/was-called on-confirm)))))) (h/test "Try to fill more than limit" (h/setup-subs sub-mocks) (h/render [input-amount/view - {:crypto-decimals 10 - :limit-crypto 286}]) + {:crypto-decimals 1 + :limit-crypto 1}]) (h/fire-event :press (h/query-by-label-text :keyboard-key-2)) (h/fire-event :press (h/query-by-label-text :keyboard-key-9)) (h/fire-event :press (h/query-by-label-text :keyboard-key-5)) - (-> (h/wait-for #(h/is-truthy (h/get-by-text "$290.00"))) - (.then (fn [] - (h/fire-event :press (h/query-by-label-text :keyboard-key-backspace)) - (h/fire-event :press (h/query-by-label-text :keyboard-key-8)) - (h/fire-event :press (h/query-by-label-text :keyboard-key-5)) - (h/wait-for #(h/get-by-text "$2850.00")))))) - - (h/test "Try to fill more than limit" - (h/setup-subs sub-mocks) - (h/render [input-amount/view - {:crypto-decimals 10 - :limit-crypto 286 - :on-confirm #()}]) - - (h/fire-event :press (h/query-by-label-text :keyboard-key-2)) - (h/fire-event :press (h/query-by-label-text :keyboard-key-9)) - (h/fire-event :press (h/query-by-label-text :keyboard-key-5)) - - (-> (h/wait-for #(h/get-by-text "$290.00")) - (.then (fn [] - (h/fire-event :press (h/query-by-label-text :keyboard-key-backspace)) - (h/fire-event :press (h/query-by-label-text :keyboard-key-8)) - (h/fire-event :press (h/query-by-label-text :keyboard-key-5)) - (h/wait-for #(h/get-by-text "$2850.00")))))) + (h/is-truthy (h/get-by-label-text :container-error))) (h/test "Switch from crypto to fiat and check limit" (h/setup-subs sub-mocks) (h/render [input-amount/view - {:crypto-decimals 2 - :limit-crypto 250 + {:crypto-decimals 1 + :limit-crypto 1 :on-confirm #()}]) - (h/fire-event :press (h/query-by-label-text :keyboard-key-2)) - (h/fire-event :press (h/query-by-label-text :keyboard-key-0)) - (-> (h/wait-for #(h/get-by-text "$200.00")) + (h/fire-event :press (h/query-by-label-text :keyboard-key-9)) + (h/is-truthy (h/get-by-label-text :container-error)) + (h/fire-event :press (h/query-by-label-text :reorder)) + + (-> (h/wait-for #(h/get-by-text "Max: 1000.00 USD")) (.then (fn [] - (h/fire-event :press (h/query-by-label-text :reorder)) - (h/wait-for #(h/get-by-text "2.00 ETH")))) - (.then (fn [] - (h/fire-event :press (h/query-by-label-text :keyboard-key-5)) - (h/fire-event :press (h/query-by-label-text :keyboard-key-5)) - (h/wait-for #(h/get-by-text "20.50 ETH")))) - (.then (fn [] - (h/fire-event :press (h/query-by-label-text :keyboard-key-5)) - (h/wait-for #(h/get-by-text "20.50 ETH"))))))) + (h/wait-for #(h/is-truthy (h/get-by-label-text :container)))))))) diff --git a/src/status_im/contexts/wallet/send/input_amount/view.cljs b/src/status_im/contexts/wallet/send/input_amount/view.cljs index 3032bcb77c..c5cf2c7186 100644 --- a/src/status_im/contexts/wallet/send/input_amount/view.cljs +++ b/src/status_im/contexts/wallet/send/input_amount/view.cljs @@ -61,6 +61,11 @@ (>= (js/parseFloat balance) input-value))) (map first))) +(defn- reset-input-error + [new-value prev-value input-error] + (reset! input-error + (> new-value prev-value))) + (defn- f-view-internal ;; crypto-decimals and limit-crypto args are needed for component tests only [{:keys [crypto-decimals limit-crypto]}] @@ -75,6 +80,7 @@ limit-fiat (.toFixed (* (:total-balance token) conversion-rate) 2) crypto-decimals (or crypto-decimals (utils/get-crypto-decimals-count token)) input-value (reagent/atom "") + input-error (reagent/atom false) current-limit (reagent/atom {:amount limit-crypto :currency token-symbol}) handle-swap (fn [crypto?] @@ -84,27 +90,30 @@ :currency token-symbol} {:amount limit-fiat :currency currency})) - (when (> num-value (:amount @current-limit)) - (reset! input-value "")))) + (reset-input-error num-value + (:amount @current-limit) + input-error))) handle-keyboard-press (fn [v] - (let [current-value @input-value - new-value (make-new-input current-value v) - num-value (or (parse-double new-value) 0)] - (when (and (not loading-suggested-routes?) - (<= num-value (:amount @current-limit))) + (let [current-value @input-value + new-value (make-new-input current-value v) + num-value (or (parse-double new-value) 0) + current-limit-amount (:amount @current-limit)] + (when (not loading-suggested-routes?) (reset! input-value new-value) + (reset-input-error num-value current-limit-amount input-error) (reagent/flush)))) handle-delete (fn [_] (when-not loading-suggested-routes? - (swap! input-value #(subs % 0 (dec (count %)))) - (reagent/flush))) + (let [current-limit-amount (:amount @current-limit)] + (swap! input-value #(subs % 0 (dec (count %)))) + (reset-input-error @input-value current-limit-amount input-error) + (reagent/flush)))) handle-on-change (fn [v] (when (valid-input? @input-value v) (let [num-value (or (parse-double v) 0) current-limit-amount (:amount @current-limit)] - (if (> num-value current-limit-amount) - (reset! input-value (str current-limit-amount)) - (reset! input-value v)) + (reset! input-value v) + (reset-input-error num-value current-limit-amount input-error) (reagent/flush))))] (fn [{:keys [on-confirm] :or {on-confirm #(rf/dispatch [:wallet/send-select-amount @@ -135,7 +144,8 @@ 100))) [@input-value]) [rn/view - {:style style/screen} + {:style style/screen + :accessibility-label (str "container" (when @input-error "-error"))} [account-switcher/view {:icon-name :i/arrow-left :on-press #(rf/dispatch [:navigate-back-within-stack :wallet-send-input-amount]) @@ -145,6 +155,7 @@ :token token-symbol :currency currency :crypto-decimals crypto-decimals + :error? @input-error :networks (:networks token) :title (i18n/label :t/send-limit {:limit limit-label}) :conversion conversion-rate