Swap: Edit slippage drawer (#20554)

This commit is contained in:
Ajay Sivan 2024-07-05 15:14:38 +05:30 committed by GitHub
parent eaa5016094
commit b4866ff728
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 213 additions and 9 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -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)

View File

@ -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)})

View File

@ -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}])]))

View File

@ -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))}))

View File

@ -0,0 +1,4 @@
(ns status-im.contexts.wallet.swap.swap-proposal.style)
(def container
{:flex 1})

View File

@ -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 "%")]]))

View File

@ -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

View File

@ -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)

View File

@ -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."

View File

@ -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)))))

View File

@ -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",