🔁 SWAP UI
CLJ Refactor x Hydra are cool. Add modal Swap UI Swap token input and gas slider in place Asset selector sheets WIP Selector events Tabs are back Hide Swaps behind ff, add cards and modals for advanced settings Fix lint issues Signed-off-by: Shivek Khurana <shivek@status.im>
This commit is contained in:
parent
3499cdc123
commit
eeb8db00f7
1
.env
1
.env
|
@ -33,3 +33,4 @@ DELETE_MESSAGE_ENABLED=1
|
|||
COLLECTIBLES_ENABLED=1
|
||||
COMMANDS_ENABLED=1
|
||||
TWO_MINUTES_SYNCING=1
|
||||
SWAP_ENABLED=1
|
||||
|
|
|
@ -230,7 +230,7 @@ PODS:
|
|||
- React
|
||||
- react-native-status (1.0.0):
|
||||
- React
|
||||
- react-native-status-keycard (2.5.36):
|
||||
- react-native-status-keycard (2.5.37):
|
||||
- Keycard
|
||||
- React
|
||||
- react-native-webview (11.3.0):
|
||||
|
@ -626,7 +626,7 @@ SPEC CHECKSUMS:
|
|||
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
|
||||
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
|
||||
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
|
||||
glog: 5bc68409594b19a3e5c5cbced7b1ecf61053b709
|
||||
glog: 61334f8bdb4deea07543d4fbac3fb5948e78a7a5
|
||||
Keycard: dd96182888da0aacf4de821b641103143bbb26cc
|
||||
libwebp: 98a37e597e40bfdb4c911fc98f2c53d0b12d05fc
|
||||
Permission-Camera: afad27bf90337684d4a86f3825112d648c8c4d3b
|
||||
|
@ -653,7 +653,7 @@ SPEC CHECKSUMS:
|
|||
react-native-slider: 12bd76d3d568c9c5500825db54123d44b48e4ad4
|
||||
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
|
||||
react-native-status: 45dbf1302ce3c258b459dfab137cd1c2c68c295d
|
||||
react-native-status-keycard: eb84554a23315510948613a9467e7e3481be340c
|
||||
react-native-status-keycard: 961d01ca190889ddf220206822fd752f8f4f3f7a
|
||||
react-native-webview: af9990b21a9aeafa8e8347746eb4116c0de086af
|
||||
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
|
||||
React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 527 B |
Binary file not shown.
After Width: | Height: | Size: 899 B |
|
@ -197,11 +197,13 @@
|
|||
left-side-alignment icon-color icon-bg-color
|
||||
title subtitle subtitle-secondary active on-press on-long-press chevron size text-size
|
||||
accessory-text accessibility-label title-accessibility-label accessory-style
|
||||
haptic-feedback haptic-type error animated animated-accessory? title-text-weight container-style]
|
||||
haptic-feedback haptic-type error animated animated-accessory? title-text-weight container-style
|
||||
active-background-enabled]
|
||||
:or {subtitle-max-lines 1
|
||||
theme :main
|
||||
haptic-feedback true
|
||||
animated platform/ios?
|
||||
active-background-enabled true
|
||||
haptic-type :selection}}]
|
||||
(let [theme (if disabled :disabled theme)
|
||||
{:keys [text-color active-background passive-background]}
|
||||
|
@ -223,7 +225,7 @@
|
|||
[component
|
||||
(merge {:type :list-item
|
||||
:disabled disabled
|
||||
:bg-color active-background
|
||||
:bg-color (when active-background-enabled active-background)
|
||||
:accessibility-label accessibility-label}
|
||||
(when on-press
|
||||
{:on-press (fn []
|
||||
|
|
|
@ -180,6 +180,12 @@
|
|||
(reg-root-key-sub :wallet/fetching-collection-assets :wallet/fetching-collection-assets)
|
||||
(reg-root-key-sub :wallet/collectible-assets :wallet/collectible-assets)
|
||||
(reg-root-key-sub :wallet/selected-collectible :wallet/selected-collectible)
|
||||
(reg-root-key-sub :wallet/modal-selecting-source-token? :wallet/modal-selecting-source-token?)
|
||||
(reg-root-key-sub :wallet/swap-from-token :wallet/swap-from-token)
|
||||
(reg-root-key-sub :wallet/swap-to-token :wallet/swap-to-token)
|
||||
(reg-root-key-sub :wallet/swap-from-token-amount :wallet/swap-from-token-amount)
|
||||
(reg-root-key-sub :wallet/swap-to-token-amount :wallet/swap-to-token-amount)
|
||||
(reg-root-key-sub :wallet/swap-advanced-mode? :wallet/swap-advanced-mode?)
|
||||
|
||||
;;commands
|
||||
(reg-root-key-sub :commands/select-account :commands/select-account)
|
||||
|
|
|
@ -44,6 +44,17 @@
|
|||
[status-im.ui.screens.currency-settings.views :as currency-settings]
|
||||
[status-im.ui.screens.dapps-permissions.views :as dapps-permissions]
|
||||
[status-im.ui.screens.default-sync-period-settings.view :as default-sync-period-settings]
|
||||
[status-im.ui.screens.wallet.settings.views :as wallet-settings]
|
||||
[status-im.ui.screens.wallet.transactions.views :as wallet-transactions]
|
||||
[status-im.ui.screens.wallet.custom-tokens.views :as custom-tokens]
|
||||
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
|
||||
[status-im.ui.screens.wallet.collectibles.views :as wallet.collectibles]
|
||||
[status-im.ui.screens.wallet.account.views :as wallet.account]
|
||||
[status-im.ui.screens.wallet.add-new.views :as add-account]
|
||||
[status-im.ui.screens.wallet.account-settings.views :as account-settings]
|
||||
[status-im.ui.screens.wallet.swap.views :as wallet.swap]
|
||||
[status-im.ui.screens.status.views :as status.views]
|
||||
[status-im.ui.screens.profile.user.views :as profile.user]
|
||||
[status-im.ui.screens.ens.views :as ens]
|
||||
[status-im.ui.screens.fleet-settings.views :as fleet-settings]
|
||||
[status-im.ui.screens.glossary.view :as glossary]
|
||||
|
@ -91,7 +102,6 @@
|
|||
[status-im.ui.screens.profile.contact.views :as contact]
|
||||
[status-im.ui.screens.profile.group-chat.views :as profile.group-chat]
|
||||
[status-im.ui.screens.profile.seed.views :as profile.seed]
|
||||
[status-im.ui.screens.profile.user.views :as profile.user]
|
||||
[status-im.ui.screens.progress.views :as progress]
|
||||
[status-im.ui.screens.qr-scanner.views :as qr-scanner]
|
||||
[status-im.ui.screens.referrals.public-chat :as referrals.public-chat]
|
||||
|
@ -99,7 +109,6 @@
|
|||
[status-im.ui.screens.reset-password.views :as reset-password]
|
||||
[status-im.ui.screens.rpc-usage-info :as rpc-usage-info]
|
||||
[status-im.ui.screens.status.new.views :as status.new]
|
||||
[status-im.ui.screens.status.views :as status.views]
|
||||
[status-im.ui.screens.stickers.views :as stickers]
|
||||
[status-im.ui.screens.sync-settings.views :as sync-settings]
|
||||
[status-im.ui.screens.terms-of-service.views :as terms-of-service]
|
||||
|
@ -107,18 +116,10 @@
|
|||
:as
|
||||
edit-wakuv2-node]
|
||||
[status-im.ui.screens.wakuv2-settings.views :as wakuv2-settings]
|
||||
[status-im.ui.screens.wallet.account-settings.views :as account-settings]
|
||||
[status-im.ui.screens.wallet.account.views :as wallet.account]
|
||||
[status-im.ui.screens.wallet.accounts-manage.views :as accounts-manage]
|
||||
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
|
||||
[status-im.ui.screens.wallet.add-new.views :as add-account]
|
||||
[status-im.ui.screens.wallet.buy-crypto.views :as wallet.buy-crypto]
|
||||
[status-im.ui.screens.wallet.collectibles.views :as wallet.collectibles]
|
||||
[status-im.ui.screens.wallet.custom-tokens.views :as custom-tokens]
|
||||
[status-im.ui.screens.wallet.recipient.views :as recipient]
|
||||
[status-im.ui.screens.wallet.send.views :as wallet.send]
|
||||
[status-im.ui.screens.wallet.settings.views :as wallet-settings]
|
||||
[status-im.ui.screens.wallet.transactions.views :as wallet-transactions]))
|
||||
[status-im.ui.screens.wallet.send.views :as wallet.send]))
|
||||
|
||||
(def components
|
||||
[{:name :chat-toolbar
|
||||
|
@ -395,6 +396,32 @@
|
|||
:options {:topBar {:title {:text (i18n/label :t/wallet-manage-accounts)}}}
|
||||
:component accounts-manage/manage}
|
||||
|
||||
{:name :token-swap
|
||||
;;TODO dynamic title
|
||||
:options {:topBar {:visible false}}
|
||||
:component wallet.swap/swap}
|
||||
|
||||
{:name :token-swap-advanced-nonce
|
||||
:options {:topBar {:title {:text (i18n/label :t/nonce)}}}
|
||||
:component wallet.swap/nonce-modal}
|
||||
|
||||
{:name :token-swap-advanced-approve-token
|
||||
:options {:topBar {:title {:text (i18n/label :t/approve-token)}}}
|
||||
:component wallet.swap/approve-token-modal}
|
||||
|
||||
{:name :token-swap-advanced-transaction-fee
|
||||
:options {:topBar {:title {:text (i18n/label :t/transaction-fee)}}}
|
||||
:component wallet.swap/transaction-fee-modal}
|
||||
|
||||
{:name :token-swap-advanced-swap-details
|
||||
:options {:topBar {:title {:text (i18n/label :t/swap-details)}}}
|
||||
:component wallet.swap/swap-details-modal}
|
||||
|
||||
{:name :swap-asset-selector
|
||||
;;TODO dynamic title
|
||||
:options {:topBar {:visible false}}
|
||||
:component wallet.swap/asset-selector}
|
||||
|
||||
;;MY STATUS
|
||||
|
||||
{:name :status
|
||||
|
|
|
@ -42,3 +42,19 @@
|
|||
:duration 200
|
||||
:easing (.-ease ^js animation/easing)
|
||||
:useNativeDriver true}))
|
||||
|
||||
(def round-action-button
|
||||
{:background-color colors/blue
|
||||
:height 44
|
||||
:flex 1
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:width 44
|
||||
:border-radius 44})
|
||||
|
||||
(def top-actions
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:width "60%"
|
||||
:align-self :center})
|
||||
|
|
|
@ -7,16 +7,17 @@
|
|||
[quo.design-system.colors :as colors]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[quo.core :as quo]
|
||||
[quo.design-system.spacing :as spacing]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.topbar :as topbar]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.ui.screens.wallet.account.styles :as styles]
|
||||
[status-im.ui.screens.wallet.accounts.sheets :as sheets]
|
||||
[status-im.ui.screens.wallet.accounts.views :as accounts]
|
||||
[status-im.ui.screens.wallet.buy-crypto.views :as buy-crypto]
|
||||
[status-im.ui.screens.wallet.transactions.views :as history]
|
||||
[status-im.ui.components.tabs :as tabs]
|
||||
[status-im.ui.screens.wallet.collectibles.views :as collectibles.views])
|
||||
[status-im.ui.screens.wallet.collectibles.views :as collectibles.views]
|
||||
[status-im.ui.screens.wallet.buy-crypto.views :as buy-crypto])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(def state (reagent/atom {:tab :assets}))
|
||||
|
@ -102,7 +103,6 @@
|
|||
currency [:wallet/currency]
|
||||
opensea-enabled? [:opensea-enabled?]
|
||||
collectible-collection [:wallet/collectible-collection address]
|
||||
mainnet? [:mainnet?]
|
||||
ethereum-network? [:ethereum-network?]]
|
||||
(let [{:keys [tab]} @state]
|
||||
[react/view {:flex 1}
|
||||
|
@ -111,11 +111,10 @@
|
|||
(when ethereum-network?
|
||||
[tabs/tab-title state :nft (i18n/label :t/wallet-collectibles) (= tab :nft)])
|
||||
[tabs/tab-title state :history (i18n/label :t/history) (= tab :history)]]
|
||||
[quo/separator {:style {:margin-top -8}}]
|
||||
(cond
|
||||
(= tab :assets)
|
||||
[:<>
|
||||
(when mainnet?
|
||||
[buy-crypto/banner])
|
||||
(for [item tokens]
|
||||
^{:key (:name item)}
|
||||
[accounts/render-asset item nil nil (:code currency)])]
|
||||
|
@ -181,6 +180,27 @@
|
|||
(styles/bottom-send-recv-buttons-lower anim-y button-group-height)
|
||||
#(reset! to-show false))))))))
|
||||
|
||||
(defn round-action-button [{:keys [icon title on-press]}]
|
||||
[react/view {:style {:flex 1
|
||||
:align-items :center
|
||||
:margin-vertical (:large spacing/spacing)}}
|
||||
[react/touchable-opacity {:style styles/round-action-button
|
||||
:on-press on-press}
|
||||
(icons/icon icon {:color colors/white})]
|
||||
[quo/text {:color :secondary
|
||||
:size :small
|
||||
:style {:margin-top (:tiny spacing/spacing)}}
|
||||
title]])
|
||||
|
||||
(defn top-actions []
|
||||
[react/view {:style styles/top-actions}
|
||||
[round-action-button {:icon :main-icons/add
|
||||
:title (i18n/label :t/buy-crypto)
|
||||
:on-press #(re-frame/dispatch [:buy-crypto.ui/open-screen])}]
|
||||
[round-action-button {:icon :main-icons/change
|
||||
:title (i18n/label :t/swap)
|
||||
:on-press #(re-frame/dispatch [:open-modal :token-swap])}]])
|
||||
|
||||
(views/defview account []
|
||||
(views/letsubs [{:keys [name address] :as account} [:multiaccount/current-account]
|
||||
fetching-error [:wallet/fetching-error]]
|
||||
|
@ -233,5 +253,8 @@
|
|||
[react/scroll-view {:horizontal true}
|
||||
[react/view {:flex-direction :row :padding-top 8 :padding-bottom 12}
|
||||
[account-card account]]]]
|
||||
(if config/swap-enabled?
|
||||
[top-actions]
|
||||
[buy-crypto/banner])
|
||||
[assets-and-collections address]]
|
||||
[bottom-send-recv-buttons account anim-y]])))
|
||||
|
|
|
@ -0,0 +1,433 @@
|
|||
(ns status-im.ui.screens.wallet.swap.views
|
||||
(:require [quo.core :as quo]
|
||||
[quo.design-system.colors :as colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[status-im.ui.components.keyboard-avoid-presentation
|
||||
:as
|
||||
kb-presentation]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.search-input.view :as search-input]
|
||||
[status-im.ui.components.slider :as slider]
|
||||
[status-im.wallet.swap.core :as wallet.swap]
|
||||
[status-im.ui.components.toolbar :as toolbar]
|
||||
[status-im.ui.components.topbar :as topbar]
|
||||
[status-im.ui.screens.wallet.components.views :as wallet.components]
|
||||
[status-im.utils.handlers :refer [<sub]]
|
||||
[status-im.wallet.utils :as wallet.utils]
|
||||
[clojure.string :as str]))
|
||||
|
||||
(defn render-asset [{{:keys
|
||||
[icon decimals amount color value]
|
||||
:as token} :token
|
||||
currency :currency
|
||||
on-press :on-press}]
|
||||
[quo/list-item
|
||||
{:title [quo/text {:weight :medium}
|
||||
[quo/text {:weight :inherit}
|
||||
(str (if amount
|
||||
(wallet.utils/format-amount amount decimals)
|
||||
"...")
|
||||
" ")]
|
||||
[quo/text {:color :secondary
|
||||
:weight :inherit}
|
||||
(wallet.utils/display-symbol token)]]
|
||||
:on-press on-press
|
||||
:subtitle (str (if value value "...") " " currency)
|
||||
:accessibility-label
|
||||
(str (:symbol token) "-asset-value")
|
||||
:icon (if icon
|
||||
[wallet.components/token-icon icon]
|
||||
[chat-icon/custom-icon-view-list (:name token) color])}])
|
||||
|
||||
(defn asset-selector []
|
||||
(let [{:keys [address]} (<sub [:multiaccount/current-account])
|
||||
{:keys [tokens]} (<sub [:wallet/visible-assets-with-values address])
|
||||
source? (<sub [:wallet/modal-selecting-source-token?])
|
||||
currency (<sub [:wallet/currency])]
|
||||
[:<>
|
||||
[topbar/topbar
|
||||
{:title (if source?
|
||||
(i18n/label :t/select-token-to-swap)
|
||||
(i18n/label :t/select-token-to-receive))
|
||||
:modal? true}]
|
||||
|
||||
[search-input/search-input
|
||||
{:search-active? true}]
|
||||
|
||||
[react/scroll-view
|
||||
(for [token tokens]
|
||||
^{:key (:name token)}
|
||||
[render-asset {:token token
|
||||
:on-press #(re-frame/dispatch
|
||||
[(if source?
|
||||
::wallet.swap/set-from-token
|
||||
::wallet.swap/set-to-token)
|
||||
(:symbol token)])
|
||||
:currency (:code currency)}])]]))
|
||||
|
||||
(defn pill-button [{:keys [on-press label margin-left]}]
|
||||
[react/touchable-opacity {:on-press on-press
|
||||
:style {:background-color colors/blue-light
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 2
|
||||
:border-radius 24
|
||||
:margin-left (or margin-left 8)}}
|
||||
[quo/text {:color :link
|
||||
:weight :medium} label]])
|
||||
|
||||
(defn token-display
|
||||
"Show token and act as an anchor to open selector."
|
||||
[{:keys [token source?]}]
|
||||
(let [token-icon-source (-> token :icon :source)]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [::wallet.swap/open-asset-selector-modal source?])}
|
||||
[react/view {:style {:flex-direction :row
|
||||
:align-items :center
|
||||
:border-width 1
|
||||
:border-color colors/gray-lighter
|
||||
:border-radius 8
|
||||
:margin-left 16
|
||||
:padding-horizontal 8
|
||||
:padding-vertical 2}
|
||||
:accessibility-label
|
||||
:choose-asset-button}
|
||||
[quo/text {:style {:margin-right 8}}
|
||||
(-> token :symbol name)]
|
||||
[react/image {:source (if (fn? token-icon-source)
|
||||
(token-icon-source)
|
||||
token-icon-source)}]]]))
|
||||
|
||||
(defn token-input
|
||||
"Component to get the amount and type of tokens"
|
||||
[{:keys [amount error label token max-from source?]}]
|
||||
(let [window-width (<sub [:dimensions/window-width])]
|
||||
[react/view {:style {:justify-content :space-between
|
||||
:flex-direction :row
|
||||
:align-items :center}}
|
||||
[react/view {:flex 2}
|
||||
[react/view {:flex-direction :row
|
||||
:align-items :center}
|
||||
[quo/text label]
|
||||
(when max-from [pill-button {:on-press #()
|
||||
:label "Max 0.043"}])]
|
||||
[react/text-input
|
||||
{:style {:font-size 38
|
||||
:max-width (- (* (/ window-width 4) 3) 106)
|
||||
:color (if error colors/red colors/black)}
|
||||
:keyboard-type :decimal-pad
|
||||
:auto-capitalize :words
|
||||
:accessibility-label :amount-input
|
||||
:default-value amount
|
||||
:editable true
|
||||
:auto-focus true
|
||||
:on-change-text #(re-frame/dispatch [(when source?
|
||||
::wallet.swap/set-from-token-amount)
|
||||
%])
|
||||
:placeholder "0.0"}]]
|
||||
[token-display {:token token
|
||||
:source? source?}]]))
|
||||
|
||||
(defn separator-with-icon []
|
||||
[react/view
|
||||
{:margin-vertical 8}
|
||||
[quo/separator]
|
||||
[react/touchable-opacity
|
||||
{:on-press #(re-frame/dispatch [::wallet.swap/switch-from-token-with-to])}
|
||||
[react/view {:style {:background-color colors/gray-lighter
|
||||
:width 40
|
||||
:height 40
|
||||
:border-radius 40
|
||||
:border-width 4
|
||||
:border-color colors/white
|
||||
:margin-top -20
|
||||
:margin-bottom -20
|
||||
:align-self :center
|
||||
:align-items :center
|
||||
:justify-content :center}}
|
||||
[react/image {:source (icons/icon-source :main-icons/change)
|
||||
:style {:tint-color colors/gray
|
||||
:transform [{:rotate "90deg"}]}}]]]])
|
||||
|
||||
(defn floating-card [{:keys [icon title body on-press]}]
|
||||
[react/view {:style {:border-width 1
|
||||
:padding 2 ;; need a padding because border breaks otherwise
|
||||
:border-radius 12
|
||||
:margin-top 12
|
||||
:border-color colors/gray-lighter}}
|
||||
[quo/list-item {:title title
|
||||
:subtitle body
|
||||
:active-background-enabled
|
||||
false
|
||||
:on-press on-press
|
||||
:theme :main
|
||||
:chevron true
|
||||
:icon [react/view {:style {:background-color colors/blue-light
|
||||
:padding 8
|
||||
:border-radius 4}}
|
||||
(icons/icon icon {:color :dark})]}]])
|
||||
|
||||
(defn card-body-row [key value primary?]
|
||||
[react/view {:flex-direction :row}
|
||||
[quo/text {:color (when-not primary? :secondary)} key]
|
||||
[quo/text {:style {:margin-right 4}
|
||||
:color (when-not primary? :secondary)} ":"]
|
||||
[quo/text {:ellipsize-mode :middle
|
||||
:number-of-lines 1
|
||||
:style {:width "50%"}
|
||||
:color (when-not primary? :secondary)
|
||||
:weight :semi-bold} value]])
|
||||
|
||||
(defn transaction-fee-card [{:keys [gas-amount price-limit tip-limit gas-in-eth gas-in-usd]}]
|
||||
[floating-card {:title (i18n/label :t/transaction-fee)
|
||||
:icon :main-icons/gas
|
||||
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-transaction-fee])
|
||||
:body [react/view
|
||||
[card-body-row (i18n/label :t/gas-amount-limit) gas-amount]
|
||||
[card-body-row (i18n/label :t/per-gas-price-limit) price-limit]
|
||||
[card-body-row (i18n/label :t/per-gas-tip-limit) tip-limit]
|
||||
[card-body-row (i18n/label :t/total-gas)
|
||||
(str gas-in-eth " • $" gas-in-usd)
|
||||
true]]}])
|
||||
|
||||
(defn swap-details-card [{:keys [slippage price-impact]}]
|
||||
[floating-card {:title (i18n/label :t/swap-details)
|
||||
:icon :main-icons/change
|
||||
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-swap-details])
|
||||
:body [react/view
|
||||
[card-body-row (i18n/label :t/slippage) (str slippage " %")]
|
||||
[card-body-row (i18n/label :t/price-impact) (str price-impact " %")]]}])
|
||||
|
||||
(defn nonce-card [{:keys [nonce]}]
|
||||
[floating-card {:title (i18n/label :t/nonce)
|
||||
:icon :main-icons/channel
|
||||
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-nonce])
|
||||
:body [react/view
|
||||
[card-body-row (i18n/label :t/nonce) nonce]]}])
|
||||
|
||||
(defn approve-token-card [{:keys [token contract-address approve-limit]}]
|
||||
[floating-card {:title (i18n/label :t/approve)
|
||||
:icon :main-icons/check
|
||||
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-approve-token])
|
||||
:body [react/view
|
||||
[card-body-row (i18n/label :t/token) token]
|
||||
[card-body-row (i18n/label :t/contract-address) contract-address]
|
||||
[card-body-row (i18n/label :t/approve-limit) approve-limit]]}])
|
||||
|
||||
(defn advanced-input [{:keys [label label-help value on-change after]}]
|
||||
[react/view {:style {:padding-horizontal 16
|
||||
:margin-bottom 16}}
|
||||
[react/view {:style {:flex-direction :row
|
||||
:justify-content :space-between}}
|
||||
[quo/text {} label]
|
||||
label-help]
|
||||
|
||||
[quo/text-input {:default-value (str value)
|
||||
:show-cancel false
|
||||
:style {:margin-top 12
|
||||
:border-radius 8}
|
||||
:after {:component after}
|
||||
:on-change-text on-change}]])
|
||||
|
||||
(defn help-label-kv [{:keys [key value]}]
|
||||
[react/view {:style {:flex-direction :row}}
|
||||
[quo/text {:color :secondary} key]
|
||||
[quo/text {:color :secondary
|
||||
:style {:margin-right 4}} ":"]
|
||||
[quo/text {:color :secondary} value]])
|
||||
|
||||
(defn nonce-modal []
|
||||
(let [last-txn-nonce 22
|
||||
nonce 23]
|
||||
[kb-presentation/keyboard-avoiding-view {:style {:flex 1
|
||||
:margin-top 16}
|
||||
:ignore-offset true}
|
||||
[advanced-input {:label (i18n/label :t/nonce)
|
||||
:label-help [help-label-kv {:key (i18n/label :t/last-transaction)
|
||||
:value last-txn-nonce}]
|
||||
:value nonce
|
||||
:on-change #()
|
||||
:on-save #()}]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:left [quo/button {:type :secondary}
|
||||
(i18n/label :t/cancel)]
|
||||
:right [quo/button {:theme :accent}
|
||||
(i18n/label :t/save)]}]]))
|
||||
|
||||
(defn approve-token-modal []
|
||||
[quo/text "modal"])
|
||||
|
||||
(defn transaction-fee-modal []
|
||||
(let [gas-amount-limit 21000
|
||||
gas-amount 21000
|
||||
per-gas-price-limit 7.3
|
||||
current-avg-per-gas-price-limit 7.3
|
||||
per-gas-tip-limit 150
|
||||
current-avg-per-gas-tip-limit 150]
|
||||
[kb-presentation/keyboard-avoiding-view {:style {:flex 1
|
||||
:margin-top 16}
|
||||
:ignore-offset true}
|
||||
[react/view {:flex 1}
|
||||
[advanced-input {:label (i18n/label :t/gas-amount-limit)
|
||||
:label-help [help-label-kv {:key (i18n/label :t/limit)
|
||||
:value gas-amount-limit}]
|
||||
:value gas-amount
|
||||
:after [quo/text {:color :secondary} (i18n/label :t/gwei)]
|
||||
:on-change #()
|
||||
:on-save #()}]
|
||||
|
||||
[advanced-input {:label (i18n/label :t/per-gas-price-limit)
|
||||
:label-help [help-label-kv {:key (i18n/label :t/current-average)
|
||||
:value current-avg-per-gas-price-limit}]
|
||||
:value per-gas-price-limit
|
||||
:after [quo/text {:color :secondary} (i18n/label :t/gwei)]
|
||||
:on-change #()
|
||||
:on-save #()}]
|
||||
|
||||
[advanced-input {:label (i18n/label :t/per-gas-price-limit)
|
||||
:label-help [help-label-kv {:key (i18n/label :t/current-average)
|
||||
:value current-avg-per-gas-tip-limit}]
|
||||
:value per-gas-tip-limit
|
||||
:after [quo/text {:color :secondary} (i18n/label :t/gwei)]
|
||||
:on-change #()
|
||||
:on-save #()}]
|
||||
|
||||
[quo/list-item {:title (i18n/label :t/maximum-fee)
|
||||
:text-size :base
|
||||
:title-text-weight :regular
|
||||
:accessory :text
|
||||
:accessory-text [quo/text "0.3 ETH"]
|
||||
:container-style {:margin-top 16}}]
|
||||
[quo/text {:color :secondary
|
||||
:style {:padding-horizontal 16}}
|
||||
(i18n/label :t/maximum-fee-desc)]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:left [quo/button {:type :secondary}
|
||||
(i18n/label :t/cancel)]
|
||||
:right [quo/button {:theme :accent}
|
||||
(i18n/label :t/save)]}]]))
|
||||
|
||||
(defn swap-details-modal []
|
||||
(let [slippage-limit 20
|
||||
slippage 0.5
|
||||
price-impact 4]
|
||||
[kb-presentation/keyboard-avoiding-view {:style {:flex 1
|
||||
:margin-top 16}
|
||||
:ignore-offset true}
|
||||
[react/view {:flex 1}
|
||||
[advanced-input {:label (str (i18n/label :t/slippage) " %")
|
||||
:label-help [help-label-kv {:key (i18n/label :t/limit)
|
||||
:value (str slippage-limit "%")}]
|
||||
:value slippage
|
||||
:on-change #()
|
||||
:on-save #()}]
|
||||
|
||||
[quo/list-item {:title (i18n/label :t/price-impact)
|
||||
:text-size :base
|
||||
:title-text-weight :regular
|
||||
:accessory :text
|
||||
:accessory-text (str price-impact "%")
|
||||
:container-style {:margin-top 16}}]
|
||||
[quo/text {:color :secondary
|
||||
:style {:padding-horizontal 16}}
|
||||
(i18n/label :t/price-impact-desc)]]
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:left [quo/button {:type :secondary}
|
||||
(i18n/label :t/cancel)]
|
||||
:right [quo/button {:theme :accent}
|
||||
(i18n/label :t/save)]}]]))
|
||||
|
||||
(defn advanced-settings []
|
||||
[react/view {:style {:flex 1
|
||||
:padding-horizontal 16}}
|
||||
[react/view {:align-self :flex-start}
|
||||
[pill-button {:label (i18n/label :t/switch-to-simple-interface)
|
||||
:margin-left 0
|
||||
:on-press #(re-frame/dispatch [::wallet.swap/set-advanced-mode false])}]]
|
||||
[transaction-fee-card {:gas-amount 21000
|
||||
:price-limit 74
|
||||
:tip-limit 21
|
||||
:gas-in-eth 0.0031
|
||||
:gas-in-usd 34.28}]
|
||||
[swap-details-card {:slippage 0.5
|
||||
:price-impact 4}]
|
||||
[approve-token-card {:token "USDC"
|
||||
:contract-address "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2"
|
||||
:approve-limit "unlimited"}]
|
||||
[nonce-card {:nonce 22}]])
|
||||
|
||||
(defn swap []
|
||||
(let [{:keys [name]}
|
||||
(<sub [:multiaccount/current-account])
|
||||
all-tokens (<sub [:wallet/all-tokens])
|
||||
from-symbol (<sub [:wallet/swap-from-token])
|
||||
to-symbol (<sub [:wallet/swap-to-token])
|
||||
advanced-mode? (<sub [:wallet/swap-advanced-mode?])
|
||||
amount "0.02"
|
||||
from-token (tokens/symbol->token all-tokens (or from-symbol :DGX))
|
||||
to-token (tokens/symbol->token all-tokens (or to-symbol :SNT))]
|
||||
|
||||
[kb-presentation/keyboard-avoiding-view {:style (merge
|
||||
{:flex 1})
|
||||
:ignore-offset true}
|
||||
[topbar/topbar
|
||||
{:title name
|
||||
:subtitle (str/upper-case (i18n/label :t/powered-by-paraswap))
|
||||
:modal? true}]
|
||||
|
||||
[react/view (merge {:padding-horizontal 16
|
||||
:margin-vertical 32}
|
||||
(when-not advanced-mode?
|
||||
{:flex 1}))
|
||||
[token-input {:amount amount
|
||||
:error nil
|
||||
:label (i18n/label :t/amount)
|
||||
:token from-token
|
||||
:source? true
|
||||
:max-from 67.28}]
|
||||
|
||||
[separator-with-icon]
|
||||
|
||||
[token-input {:amount "0.01"
|
||||
:error nil
|
||||
:label (i18n/label :t/minimum-received)
|
||||
:source? false
|
||||
:token to-token}]]
|
||||
|
||||
(when-not advanced-mode?
|
||||
[react/view {:style {:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:padding-horizontal 16
|
||||
:align-items :center}}
|
||||
[react/view {:style {:flex-direction :row}}
|
||||
[quo/text {} (i18n/label :t/priority)]
|
||||
[pill-button {:label (i18n/label :t/advanced)
|
||||
:on-press #(re-frame/dispatch [::wallet.swap/set-advanced-mode true])}]]
|
||||
|
||||
[quo/text {:color :secondary} "0.0034 ETH/ $ 8.09"]])
|
||||
|
||||
(comment
|
||||
(re-frame/dispatch [::wallet.swap/set-advanced-mode false]))
|
||||
|
||||
(when-not advanced-mode?
|
||||
[react/view {:style {:padding-horizontal 16}}
|
||||
[slider/animated-slider
|
||||
{:minimum-value 0
|
||||
:maximum-value 100
|
||||
:style {:margin-vertical 8}}]])
|
||||
|
||||
(when advanced-mode?
|
||||
[quo/text "here"]
|
||||
[advanced-settings])
|
||||
|
||||
[toolbar/toolbar
|
||||
{:show-border? true
|
||||
:right [quo/button {:theme :accent}
|
||||
(i18n/label :t/swap)]}]]))
|
||||
|
|
@ -53,6 +53,7 @@
|
|||
(def collectibles-enabled? (enabled? (get-config :COLLECTIBLES_ENABLED "1")))
|
||||
(def test-stateofus? (enabled? (get-config :TEST_STATEOFUS "0")))
|
||||
(def two-minutes-syncing? (enabled? (get-config :TWO_MINUTES_SYNCING "0")))
|
||||
(def swap-enabled? (enabled? (get-config :SWAP_ENABLED "0")))
|
||||
|
||||
;; CONFIG VALUES
|
||||
(def log-level
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
(ns status-im.wallet.swap.core
|
||||
(:require [status-im.utils.fx :as fx]
|
||||
[re-frame.db :as re-frame.db]
|
||||
[status-im.navigation :as navigation]))
|
||||
|
||||
(fx/defn open-asset-selector-modal
|
||||
"source? true signinfies we are selecting the source asset. false implies selection of sink asset"
|
||||
{:events [::open-asset-selector-modal]}
|
||||
[{:keys [db]} source?]
|
||||
(fx/merge {:db (assoc db :wallet/modal-selecting-source-token? source?)}
|
||||
(navigation/open-modal :swap-asset-selector {})))
|
||||
|
||||
(fx/defn set-from-token
|
||||
{:events [::set-from-token]}
|
||||
[{:keys [db]} from-symbol]
|
||||
(fx/merge {:db (assoc db :wallet/swap-from-token from-symbol)}
|
||||
(navigation/navigate-back)))
|
||||
|
||||
(fx/defn set-to-token
|
||||
{:events [::set-to-token]}
|
||||
[{:keys [db]} to-symbol]
|
||||
(fx/merge {:db (assoc db :wallet/swap-to-token to-symbol)}
|
||||
(navigation/navigate-back)))
|
||||
|
||||
(fx/defn set-from-token-amount
|
||||
[{:keys [db]} from-amount]
|
||||
{:db (assoc db :wallet/swap-from-token-amount from-amount)})
|
||||
|
||||
(fx/defn set-max-from-token-amount
|
||||
[{:keys [db]} _]
|
||||
{:db (assoc db :wallet/swap-from-token-amount 0)})
|
||||
|
||||
(fx/defn switch-from-token-with-to
|
||||
{:events [::switch-from-token-with-to]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc db
|
||||
:wallet/swap-from-token (:wallet/swap-to-token db)
|
||||
:wallet/swap-to-token (:wallet/swap-from-token db))})
|
||||
|
||||
(fx/defn set-advanced-mode
|
||||
{:events [::set-advanced-mode]}
|
||||
[{:keys [db]} mode]
|
||||
{:db (assoc db :wallet/swap-advanced-mode? mode)})
|
||||
|
||||
(comment
|
||||
(->> re-frame.db/app-db
|
||||
deref
|
||||
:wallet/all-tokens
|
||||
vals
|
||||
(map #(str (:name %) "-" (:symbol %)))))
|
||||
|
|
@ -1704,5 +1704,30 @@
|
|||
"status-always-online": "Always Online",
|
||||
"status-inactive": "Inactive",
|
||||
"status-inactive-subtitle": "Hides your online status",
|
||||
"two-minutes": "two minutes"
|
||||
"two-minutes": "two minutes",
|
||||
"swap": "Swap",
|
||||
"select-token-to-swap": "Select token to Swap",
|
||||
"select-token-to-receive": "Select token to receive",
|
||||
"minimum-received": "Minimum received",
|
||||
"powered-by-paraswap": "Powered by Paraswap",
|
||||
"priority": "Priority",
|
||||
"switch-to-simple-interface":"Switch to simple interface",
|
||||
"transaction-fee": "Transaction fee",
|
||||
"swap-details": "Swap details",
|
||||
"slippage": "Slippage",
|
||||
"price-impact": "Price impact",
|
||||
"total-gas": "Total gas",
|
||||
"token": "Token",
|
||||
"approve-limit": "Approve limit",
|
||||
"approve-token": "Approve token",
|
||||
"approve-token-contract-desc": "Approving a token with a contract allows it to spend your token balance. If you feel that a project is untrustworthy, don’t approve the token with them, or approve only the amount you will use with them.",
|
||||
"unlimited": "Unlimited",
|
||||
"approve": "Approve",
|
||||
"limit": "Limit",
|
||||
"last-transaction": "Last transaction",
|
||||
"price-impact-desc": "Estimated price impact for this transaction. If the current block base fee exceeds this, your transaction will be included in a following block with a lower base fee.",
|
||||
"safe-estimate": "Safe estimate",
|
||||
"current-average": "Current average",
|
||||
"current-base": "Current base",
|
||||
"maximum-fee-desc": "Maximum overall price for the transaction. If the current block base fee exceeds this, your transaction will be included in a following block with a lower base fee."
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue