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 default-telemetry-server-url "https://telemetry.status.im")
|
||||||
|
|
||||||
(def ^:const contact-item-height 56)
|
(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
|
(ns status-im.contexts.wallet.swap.events
|
||||||
(:require [re-frame.core :as rf]
|
(: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
|
(rf/reg-event-fx :wallet.swap/start
|
||||||
(fn [{:keys [_db]}]
|
(fn [{:keys [_db]}]
|
||||||
|
@ -11,13 +13,10 @@
|
||||||
{:db (-> db
|
{:db (-> db
|
||||||
(assoc-in [:wallet :ui :swap :asset-to-pay] token)
|
(assoc-in [:wallet :ui :swap :asset-to-pay] token)
|
||||||
(assoc-in [:wallet :ui :swap :network] network))
|
(assoc-in [:wallet :ui :swap :network] network))
|
||||||
:fx [(if network
|
:fx (if network
|
||||||
[:dispatch
|
[[:dispatch [:navigate-to :screen/wallet.swap-propasal]]
|
||||||
[:toasts/upsert
|
[:dispatch [:wallet.swap/set-default-slippage]]]
|
||||||
{:id :swap-error
|
[[:dispatch
|
||||||
:type :negative
|
|
||||||
:text "Not implemented yet"}]]
|
|
||||||
[:dispatch
|
|
||||||
[:show-bottom-sheet
|
[:show-bottom-sheet
|
||||||
{:content (fn []
|
{:content (fn []
|
||||||
[network-selection/view
|
[network-selection/view
|
||||||
|
@ -29,8 +28,17 @@
|
||||||
{:token token
|
{:token token
|
||||||
:network network
|
:network network
|
||||||
:stack-id
|
: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
|
(rf/reg-event-fx :wallet.swap/clean-asset-to-pay
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
{:db (update-in db [:wallet :ui :swap] dissoc :asset-to-pay)}))
|
{: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-confirmation.view :as wallet-transaction-confirmation]
|
||||||
[status-im.contexts.wallet.send.transaction-progress.view :as wallet-transaction-progress]
|
[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.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
|
[status-im.contexts.wallet.wallet-connect.modals.send-transaction.view :as
|
||||||
wallet-connect-send-transaction]
|
wallet-connect-send-transaction]
|
||||||
[status-im.contexts.wallet.wallet-connect.modals.sign-message.view :as wallet-connect-sign-message]
|
[status-im.contexts.wallet.wallet-connect.modals.sign-message.view :as wallet-connect-sign-message]
|
||||||
|
@ -519,6 +520,10 @@
|
||||||
:insets {:top? true}}
|
:insets {:top? true}}
|
||||||
:component wallet-swap-select-asset-to-pay/view}
|
: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
|
{:name :scan-profile-qr-code
|
||||||
:options (merge
|
:options (merge
|
||||||
options/dark-screen
|
options/dark-screen
|
||||||
|
|
|
@ -52,3 +52,7 @@
|
||||||
fiat-value)]
|
fiat-value)]
|
||||||
{:crypto (str crypto-formatted " " token-symbol)
|
{:crypto (str crypto-formatted " " token-symbol)
|
||||||
:fiat fiat-formatted})))
|
:fiat fiat-formatted})))
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet/swap-max-slippage
|
||||||
|
:<- [:wallet/swap]
|
||||||
|
:-> :max-slippage)
|
||||||
|
|
|
@ -25,6 +25,16 @@
|
||||||
maybe-int
|
maybe-int
|
||||||
default))))
|
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
|
(defn value-in-range
|
||||||
"Returns `num` if is in the range [`lower-bound` `upper-bound`]
|
"Returns `num` if is in the range [`lower-bound` `upper-bound`]
|
||||||
if `num` exceeds a given bound, then returns the bound exceeded."
|
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" 0)))
|
||||||
(is (= 6 (utils.number/parse-int "6.99" 0)))
|
(is (= 6 (utils.number/parse-int "6.99" 0)))
|
||||||
(is (= -6 (utils.number/parse-int "-6" 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",
|
"reveal-qr-code": "Reveal QR code",
|
||||||
"revoke-access": "Revoke access",
|
"revoke-access": "Revoke access",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
|
"save-changes": "Save changes",
|
||||||
"save-address": "Save address",
|
"save-address": "Save address",
|
||||||
"save-bio": "Save bio",
|
"save-bio": "Save bio",
|
||||||
"save-colour": "Save colour",
|
"save-colour": "Save colour",
|
||||||
|
@ -1998,6 +1999,13 @@
|
||||||
"status-inactive-subtitle": "Hides your online status",
|
"status-inactive-subtitle": "Hides your online status",
|
||||||
"two-minutes": "two minutes",
|
"two-minutes": "two minutes",
|
||||||
"swap": "Swap",
|
"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-swap": "Select token to Swap",
|
||||||
"select-token-to-receive": "Select token to receive",
|
"select-token-to-receive": "Select token to receive",
|
||||||
"slide-to-request-to-join": "Slide to request to join",
|
"slide-to-request-to-join": "Slide to request to join",
|
||||||
|
|
Loading…
Reference in New Issue