Swap: Edit slippage drawer (#20554)
This commit is contained in:
parent
eaa5016094
commit
b4866ff728
Binary file not shown.
After Width: | Height: | Size: 781 B |
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
|
@ -555,3 +555,8 @@
|
|||
(def ^:const default-telemetry-server-url "https://telemetry.status.im")
|
||||
|
||||
(def ^:const contact-item-height 56)
|
||||
|
||||
(def ^:const slippages [0.1 0.5 1])
|
||||
(def ^:const default-slippage 0.5)
|
||||
(def ^:const max-recommended-slippage 5)
|
||||
(def ^:const max-slippage-decimal-places 2)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
(ns status-im.contexts.wallet.sheets.slippage-settings.style)
|
||||
|
||||
(def slippages
|
||||
{:padding-horizontal 8})
|
||||
|
||||
(def info-message
|
||||
{:margin-vertical 8
|
||||
:margin-horizontal 20})
|
||||
|
||||
(defn percentage-icon
|
||||
[variant-colors]
|
||||
{:size 20
|
||||
:color (:icon variant-colors)})
|
|
@ -0,0 +1,118 @@
|
|||
(ns status-im.contexts.wallet.sheets.slippage-settings.view
|
||||
(:require [clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.sheets.slippage-settings.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.number]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- validate-slippage
|
||||
[slippage]
|
||||
(let [slippage-value (utils.number/parse-float slippage)]
|
||||
(cond
|
||||
(<= slippage-value 0)
|
||||
{:message (i18n/label :t/slippage-should-be-more-than-0)
|
||||
:type :error}
|
||||
(> (count (second (string/split slippage ".")))
|
||||
constants/max-slippage-decimal-places)
|
||||
{:message (i18n/label :t/max-2-decimals)
|
||||
:type :error}
|
||||
(> slippage-value constants/max-recommended-slippage)
|
||||
{:message (i18n/label :t/slippage-may-be-higher-than-necessary)
|
||||
:type :warning})))
|
||||
|
||||
(defn- on-cancel
|
||||
[]
|
||||
(rf/dispatch [:hide-bottom-sheet]))
|
||||
|
||||
(defn- update-string-on-keypress
|
||||
[k s]
|
||||
(if (= :i/backspace k)
|
||||
(subs s 0 (dec (count s)))
|
||||
(str s k)))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [current-slippage (rf/sub [:wallet/swap-max-slippage])
|
||||
account-color (rf/sub [:wallet/current-viewing-account-color])
|
||||
[max-slippage set-max-slippage] (rn/use-state (str current-slippage))
|
||||
[error set-error] (rn/use-state nil)
|
||||
[custom? set-custom?] (rn/use-state (not-any? #{current-slippage}
|
||||
constants/slippages))
|
||||
handle-slippage-change (rn/use-callback
|
||||
(fn [value]
|
||||
(let [new-slippage (update-string-on-keypress value
|
||||
max-slippage)]
|
||||
(set-max-slippage new-slippage)
|
||||
(set-error (validate-slippage new-slippage))))
|
||||
[max-slippage set-max-slippage set-error])
|
||||
on-select-slippage (rn/use-callback (fn [slippage]
|
||||
(set-max-slippage (str slippage))
|
||||
(set-custom? (not slippage)))
|
||||
[set-max-slippage set-custom?])
|
||||
save-disabled? (rn/use-memo (fn []
|
||||
(or (= max-slippage (str current-slippage))
|
||||
(= (:type error) :error)
|
||||
(and custom?
|
||||
(empty? max-slippage))))
|
||||
[max-slippage current-slippage error custom?])
|
||||
on-save (rn/use-callback (fn []
|
||||
(rf/dispatch [:wallet.swap/set-max-slippage
|
||||
max-slippage])
|
||||
(rf/dispatch [:hide-bottom-sheet]))
|
||||
[max-slippage])]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:title (i18n/label :t/slippage-settings)
|
||||
:description (i18n/label :t/slippage-settings-description)}]
|
||||
[rn/view {:style style/slippages}
|
||||
(map (fn [slippage]
|
||||
^{:key slippage}
|
||||
[quo/drawer-action
|
||||
(cond-> {:title (str slippage "%")
|
||||
:on-press #(on-select-slippage slippage)}
|
||||
(= (str slippage) max-slippage) (assoc :state :selected))])
|
||||
constants/slippages)
|
||||
[quo/drawer-action
|
||||
(cond-> {:title (i18n/label :t/custom)
|
||||
:action :input
|
||||
:on-press #(on-select-slippage nil)
|
||||
:input-props {:auto-focus true
|
||||
:customization-color account-color
|
||||
:placeholder (i18n/label :t/type-slippage)
|
||||
:right-icon {:icon-name :i/percentage
|
||||
:on-press identity
|
||||
:style-fn style/percentage-icon}
|
||||
:value max-slippage}}
|
||||
custom? (assoc :state :selected))]]
|
||||
(when (and custom? error)
|
||||
[quo/info-message
|
||||
{:status (:type error)
|
||||
:size :default
|
||||
:container-style style/info-message
|
||||
:icon :i/alert}
|
||||
(:message error)])
|
||||
[quo/bottom-actions
|
||||
{:actions :two-actions
|
||||
:button-one-label (i18n/label :t/save-changes)
|
||||
:button-one-props {:disabled? save-disabled?
|
||||
:customization-color account-color
|
||||
:on-press on-save}
|
||||
:button-two-label (i18n/label :t/cancel)
|
||||
:button-two-props {:on-press on-cancel
|
||||
:customization-color account-color
|
||||
:type :grey}
|
||||
:description :top
|
||||
:context-tag-props {:size 24
|
||||
:type :token
|
||||
:token "USDT"
|
||||
:amount "99.97"} ;; will be replaced with real data later
|
||||
:description-top-text (i18n/label :t/receive-at-least)}]
|
||||
(when custom?
|
||||
[quo/numbered-keyboard
|
||||
{:left-action :dot
|
||||
:delete-key? true
|
||||
:on-press handle-slippage-change
|
||||
:on-delete handle-slippage-change}])]))
|
|
@ -1,6 +1,8 @@
|
|||
(ns status-im.contexts.wallet.swap.events
|
||||
(:require [re-frame.core :as rf]
|
||||
[status-im.contexts.wallet.sheets.network-selection.view :as network-selection]))
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.sheets.network-selection.view :as network-selection]
|
||||
[utils.number]))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/start
|
||||
(fn [{:keys [_db]}]
|
||||
|
@ -11,13 +13,10 @@
|
|||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :swap :asset-to-pay] token)
|
||||
(assoc-in [:wallet :ui :swap :network] network))
|
||||
:fx [(if network
|
||||
[:dispatch
|
||||
[:toasts/upsert
|
||||
{:id :swap-error
|
||||
:type :negative
|
||||
:text "Not implemented yet"}]]
|
||||
[:dispatch
|
||||
:fx (if network
|
||||
[[:dispatch [:navigate-to :screen/wallet.swap-propasal]]
|
||||
[:dispatch [:wallet.swap/set-default-slippage]]]
|
||||
[[:dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[network-selection/view
|
||||
|
@ -29,8 +28,17 @@
|
|||
{:token token
|
||||
:network network
|
||||
:stack-id
|
||||
:screen/wallet.swap-select-asset-to-pay}]))}])}]])]}))
|
||||
:screen/wallet.swap-select-asset-to-pay}]))}])}]]])}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/clean-asset-to-pay
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:wallet :ui :swap] dissoc :asset-to-pay)}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/set-default-slippage
|
||||
(fn [{:keys [db]}]
|
||||
{:db
|
||||
(assoc-in db [:wallet :ui :swap :max-slippage] constants/default-slippage)}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/set-max-slippage
|
||||
(fn [{:keys [db]} [max-slippage]]
|
||||
{:db (assoc-in db [:wallet :ui :swap :max-slippage] (utils.number/parse-float max-slippage))}))
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
(ns status-im.contexts.wallet.swap.swap-proposal.style)
|
||||
|
||||
(def container
|
||||
{:flex 1})
|
|
@ -0,0 +1,15 @@
|
|||
(ns status-im.contexts.wallet.swap.swap-proposal.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.sheets.slippage-settings.view :as slippage-settings]
|
||||
[status-im.contexts.wallet.swap.swap-proposal.style :as style]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [max-slippage (rf/sub [:wallet/swap-max-slippage])]
|
||||
[rn/view {:style style/container}
|
||||
[quo/button
|
||||
{:on-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content slippage-settings/view}])}
|
||||
(str "Edit Slippage: " max-slippage "%")]]))
|
|
@ -116,6 +116,7 @@
|
|||
[status-im.contexts.wallet.send.transaction-confirmation.view :as wallet-transaction-confirmation]
|
||||
[status-im.contexts.wallet.send.transaction-progress.view :as wallet-transaction-progress]
|
||||
[status-im.contexts.wallet.swap.select-asset-to-pay.view :as wallet-swap-select-asset-to-pay]
|
||||
[status-im.contexts.wallet.swap.swap-proposal.view :as wallet-swap-propasal]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.send-transaction.view :as
|
||||
wallet-connect-send-transaction]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.sign-message.view :as wallet-connect-sign-message]
|
||||
|
@ -519,6 +520,10 @@
|
|||
:insets {:top? true}}
|
||||
:component wallet-swap-select-asset-to-pay/view}
|
||||
|
||||
{:name :screen/wallet.swap-propasal
|
||||
:options {:insets {:top? true}}
|
||||
:component wallet-swap-propasal/view}
|
||||
|
||||
{:name :scan-profile-qr-code
|
||||
:options (merge
|
||||
options/dark-screen
|
||||
|
|
|
@ -52,3 +52,7 @@
|
|||
fiat-value)]
|
||||
{:crypto (str crypto-formatted " " token-symbol)
|
||||
:fiat fiat-formatted})))
|
||||
(rf/reg-sub
|
||||
:wallet/swap-max-slippage
|
||||
:<- [:wallet/swap]
|
||||
:-> :max-slippage)
|
||||
|
|
|
@ -25,6 +25,16 @@
|
|||
maybe-int
|
||||
default))))
|
||||
|
||||
(defn parse-float
|
||||
"Parses `n` as a float. Defaults to zero or `default` instead of NaN."
|
||||
([n]
|
||||
(parse-float n 0))
|
||||
([n default]
|
||||
(let [maybe-float (js/parseFloat n 10)]
|
||||
(if (js/Number.isNaN maybe-float)
|
||||
default
|
||||
maybe-float))))
|
||||
|
||||
(defn value-in-range
|
||||
"Returns `num` if is in the range [`lower-bound` `upper-bound`]
|
||||
if `num` exceeds a given bound, then returns the bound exceeded."
|
||||
|
|
|
@ -16,3 +16,17 @@
|
|||
(is (= 6 (utils.number/parse-int "6" 0)))
|
||||
(is (= 6 (utils.number/parse-int "6.99" 0)))
|
||||
(is (= -6 (utils.number/parse-int "-6" 0)))))
|
||||
|
||||
(deftest parse-float-test
|
||||
(testing "defaults to zero"
|
||||
(is (= 0 (utils.number/parse-float nil))))
|
||||
|
||||
(testing "accepts any other default value"
|
||||
(is (= 3 (utils.number/parse-float "" 3)))
|
||||
(is (= :invalid-float (utils.number/parse-float "" :invalid-float))))
|
||||
|
||||
(testing "valid numbers"
|
||||
(is (= -6 (utils.number/parse-float "-6a")))
|
||||
(is (= 6 (utils.number/parse-float "6")))
|
||||
(is (= 6.99 (utils.number/parse-float "6.99" 0)))
|
||||
(is (= -6.9 (utils.number/parse-float "-6.9" 0)))))
|
||||
|
|
|
@ -1296,6 +1296,7 @@
|
|||
"reveal-qr-code": "Reveal QR code",
|
||||
"revoke-access": "Revoke access",
|
||||
"save": "Save",
|
||||
"save-changes": "Save changes",
|
||||
"save-address": "Save address",
|
||||
"save-bio": "Save bio",
|
||||
"save-colour": "Save colour",
|
||||
|
@ -1998,6 +1999,13 @@
|
|||
"status-inactive-subtitle": "Hides your online status",
|
||||
"two-minutes": "two minutes",
|
||||
"swap": "Swap",
|
||||
"slippage-settings": "Slippage settings",
|
||||
"slippage-settings-description": "Your transaction will revert if the price changes more than the slippage percentage",
|
||||
"slippage-may-be-higher-than-necessary": "Slippage may be higher than necessary",
|
||||
"slippage-should-be-more-than-0": "Slippage should be more than 0",
|
||||
"max-2-decimals": "Max. 2 decimals",
|
||||
"type-slippage": "Type slippage",
|
||||
"receive-at-least": "Receive at least",
|
||||
"select-token-to-swap": "Select token to Swap",
|
||||
"select-token-to-receive": "Select token to receive",
|
||||
"slide-to-request-to-join": "Slide to request to join",
|
||||
|
|
Loading…
Reference in New Issue