feat(swap): swap confirmation screen (#20669)
Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
parent
12b8dcf1e7
commit
5f085e9cea
|
@ -5,8 +5,9 @@
|
|||
[:catn
|
||||
[:props
|
||||
[:map
|
||||
[:type [:enum :status-account :saved-account :account :user]]
|
||||
[:type [:enum :status-account :saved-account :account :user :token]]
|
||||
[:account-props {:optional true} [:maybe :map]]
|
||||
[:token-props {:optional true} [:maybe :map]]
|
||||
[:networks? {:optional true} [:maybe :boolean]]
|
||||
[:values {:optional true} [:maybe :map]]]]]
|
||||
:any])
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
[quo.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo.components.avatars.wallet-user-avatar.view :as wallet-user-avatar]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.utilities.token.view :as token]
|
||||
[quo.components.wallet.summary-info.schema :as summary-info-schema]
|
||||
[quo.components.wallet.summary-info.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
|
@ -58,13 +59,14 @@
|
|||
:theme theme}])]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [type account-props networks? values]}]
|
||||
[{:keys [type account-props token-props networks? values]}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view
|
||||
{:style (style/container networks? theme)}
|
||||
[rn/view
|
||||
{:style style/info-container}
|
||||
(case type
|
||||
:token [token/view (select-keys token-props #{:token :size})]
|
||||
:status-account [account-avatar/view account-props]
|
||||
:saved-account [wallet-user-avatar/wallet-user-avatar (assoc account-props :size :size-32)]
|
||||
:account [wallet-user-avatar/wallet-user-avatar
|
||||
|
@ -73,7 +75,8 @@
|
|||
:neutral? true)]
|
||||
[user-avatar/user-avatar account-props])
|
||||
[rn/view {:style {:margin-left 8}}
|
||||
(when (not= type :account) [text/text {:weight :semi-bold} (:name account-props)])
|
||||
(when (not= type :account)
|
||||
[text/text {:weight :semi-bold} (or (:name account-props) (:label token-props))])
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:align-items :center}}
|
||||
|
@ -91,7 +94,7 @@
|
|||
:weight (when (= type :account) :semi-bold)
|
||||
:style {:color (when (not= type :account)
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}}
|
||||
(:address account-props)]]]]
|
||||
(or (:address account-props) (:address token-props))]]]]
|
||||
(when networks?
|
||||
[:<>
|
||||
[rn/view
|
||||
|
|
|
@ -566,3 +566,6 @@
|
|||
(def ^:const default-slippage 0.5)
|
||||
(def ^:const max-recommended-slippage 5)
|
||||
(def ^:const max-slippage-decimal-places 2)
|
||||
(def ^:const swap-default-provider
|
||||
{:name "Paraswap"
|
||||
:terms-and-conditions-url "https://files.paraswap.io/tos_v4.pdf"})
|
||||
|
|
|
@ -42,3 +42,23 @@
|
|||
(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))}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/select-asset-to-receive
|
||||
(fn [{:keys [db]} [{:keys [token]}]]
|
||||
{:db (assoc-in db [:wallet :ui :swap :asset-to-receive] token)}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/set-pay-amount
|
||||
(fn [{:keys [db]} [amount]]
|
||||
{:db (assoc-in db [:wallet :ui :swap :pay-amount] amount)}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/set-swap-proposal
|
||||
(fn [{:keys [db]} [swap-proposal]]
|
||||
{:db (assoc-in db [:wallet :ui :swap :swap-proposal] swap-proposal)}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/set-provider
|
||||
(fn [{:keys [db]}]
|
||||
{:db (assoc-in db [:wallet :ui :swap :providers] [constants/swap-default-provider])}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/recalculate-fees
|
||||
(fn [{:keys [db]} [loading-fees?]]
|
||||
{:db (assoc-in db [:wallet :ui :swap :loading-fees?] loading-fees?)}))
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
|
||||
[status-im.contexts.wallet.common.asset-list.view :as asset-list]
|
||||
[status-im.contexts.wallet.swap.select-asset-to-pay.style :as style]
|
||||
[status-im.setup.hot-reload :as hot-reload]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
@ -19,6 +18,20 @@
|
|||
:value search-text
|
||||
:on-change-text on-change-text}]])
|
||||
|
||||
(def dummy-swap-proposal
|
||||
{:from {:chain-id 1
|
||||
:native-currency-symbol "ETH"}
|
||||
:to {:chain-id 1
|
||||
:native-currency-symbol "ETH"}
|
||||
:gas-amount "23487"
|
||||
:gas-fees {:base-fee "32.325296406"
|
||||
:max-priority-fee-per-gas "0.011000001"
|
||||
:eip1559-enabled true}
|
||||
:estimated-time 3
|
||||
:receive-amount 99.98
|
||||
:receive-token {:symbol "SNT"
|
||||
:address "0x432492384728934239789"}})
|
||||
|
||||
(defn- assets-view
|
||||
[search-text on-change-text]
|
||||
(let [on-token-press (fn [token]
|
||||
|
@ -27,7 +40,11 @@
|
|||
{:token token
|
||||
:network (when (= (count token-networks) 1)
|
||||
(first token-networks))
|
||||
:stack-id :screen/wallet.swap-select-asset-to-pay}])))]
|
||||
:stack-id :screen/wallet.swap-select-asset-to-pay}])
|
||||
(rf/dispatch [:wallet.swap/select-asset-to-receive {:token token}])
|
||||
(rf/dispatch [:wallet.swap/set-pay-amount 100])
|
||||
(rf/dispatch [:wallet.swap/set-swap-proposal dummy-swap-proposal])
|
||||
(rf/dispatch [:wallet.swap/set-provider])))]
|
||||
[:<>
|
||||
[search-input search-text on-change-text]
|
||||
[asset-list/view
|
||||
|
@ -41,8 +58,6 @@
|
|||
on-close (fn []
|
||||
(rf/dispatch [:wallet.swap/clean-asset-to-pay])
|
||||
(rf/dispatch [:navigate-back]))]
|
||||
(hot-reload/use-safe-unmount (fn []
|
||||
(rf/dispatch [:wallet.swap/clean-asset-to-pay])))
|
||||
[rn/safe-area-view {:style style/container}
|
||||
[account-switcher/view
|
||||
{:on-press on-close
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
(ns status-im.contexts.wallet.swap.swap-confirmation.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def detail-item
|
||||
{:flex 1
|
||||
:height 36
|
||||
:background-color :transparent})
|
||||
|
||||
(def content-container
|
||||
{:padding-top 12
|
||||
:padding-horizontal 20
|
||||
:padding-bottom 32})
|
||||
|
||||
(def title-container
|
||||
{:margin-right 4})
|
||||
|
||||
(def title-line-with-margin-top
|
||||
{:flex-direction :row
|
||||
:margin-top 4})
|
||||
|
||||
(def details-container
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:height 52
|
||||
:padding-top 7
|
||||
:margin-bottom 8})
|
||||
|
||||
(def summary-section-container
|
||||
{:padding-horizontal 20
|
||||
:padding-bottom 16})
|
||||
|
||||
(defn section-label
|
||||
[theme]
|
||||
{:margin-bottom 8
|
||||
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
|
||||
|
||||
(def providers-container
|
||||
{:align-items :center
|
||||
:margin-top 12})
|
|
@ -0,0 +1,192 @@
|
|||
(ns status-im.contexts.wallet.swap.swap-confirmation.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.common.standard-authentication.core :as standard-auth]
|
||||
[status-im.contexts.wallet.swap.swap-confirmation.style :as style]
|
||||
[utils.address :as address-utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- on-close-action
|
||||
[]
|
||||
(rf/dispatch [:navigate-back]))
|
||||
|
||||
(defn- swap-title
|
||||
[{:keys [pay-token-symbol pay-amount receive-token-symbol receive-amount account]}]
|
||||
[rn/view {:style style/content-container}
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/title-container
|
||||
:accessibility-label :title-label}
|
||||
(i18n/label :t/swap)]
|
||||
[quo/summary-tag
|
||||
{:token pay-token-symbol
|
||||
:label (str pay-amount " " pay-token-symbol)
|
||||
:type :token}]]
|
||||
[rn/view {:style style/title-line-with-margin-top}
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/title-container
|
||||
:accessibility-label :title-label}
|
||||
(i18n/label :t/to)]
|
||||
[quo/summary-tag
|
||||
{:token receive-token-symbol
|
||||
:label (str receive-amount " " receive-token-symbol)
|
||||
:type :token}]]
|
||||
[rn/view {:style style/title-line-with-margin-top}
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/title-container
|
||||
:accessibility-label :send-label}
|
||||
(i18n/label :t/in)]
|
||||
[quo/summary-tag
|
||||
{:label (:name account)
|
||||
:type :account
|
||||
:emoji (:emoji account)
|
||||
:customization-color (:color account)}]]])
|
||||
|
||||
(defn- summary-section
|
||||
[{:keys [theme label title-accessibility-label amount token-symbol token-address network]}]
|
||||
(let [network-values {(if (= network :mainnet) :ethereum network)
|
||||
{:amount amount :token-symbol token-symbol}}]
|
||||
[rn/view {:style style/summary-section-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/section-label theme)
|
||||
:accessibility-label title-accessibility-label}
|
||||
label]
|
||||
[quo/summary-info
|
||||
{:type :token
|
||||
:networks? true
|
||||
:values network-values
|
||||
:token-props {:token token-symbol
|
||||
:label (str amount " " token-symbol)
|
||||
:address (address-utils/get-shortened-compressed-key token-address)
|
||||
:size 32}}]]))
|
||||
|
||||
(defn- data-item
|
||||
[{:keys [title subtitle loading?]}]
|
||||
[quo/data-item
|
||||
{:container-style style/detail-item
|
||||
:blur? false
|
||||
:card? false
|
||||
:status (if loading? :loading :default)
|
||||
:size :small
|
||||
:title title
|
||||
:subtitle subtitle}])
|
||||
|
||||
(defn- transaction-details
|
||||
[{:keys [estimated-time-min max-fees max-slippage loading-fees?]}]
|
||||
[rn/view {:style style/details-container}
|
||||
[:<>
|
||||
[data-item
|
||||
{:title (i18n/label :t/est-time)
|
||||
:subtitle (i18n/label :t/time-in-mins {:minutes (str estimated-time-min)})}]
|
||||
[data-item
|
||||
{:title (i18n/label :t/max-fees)
|
||||
:subtitle max-fees
|
||||
:loading? loading-fees?}]
|
||||
[data-item
|
||||
{:title (i18n/label :t/max-slippage)
|
||||
:subtitle (str max-slippage "%")}]]])
|
||||
|
||||
(defn footer
|
||||
[{:keys [estimated-time-min native-currency-symbol max-slippage theme account-color provider
|
||||
loading-fees?]}]
|
||||
(let [native-token (when native-currency-symbol
|
||||
(rf/sub [:wallet/token-by-symbol
|
||||
native-currency-symbol]))
|
||||
fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted
|
||||
native-token])]
|
||||
[:<>
|
||||
[transaction-details
|
||||
{:estimated-time-min estimated-time-min
|
||||
:max-fees fee-formatted
|
||||
:max-slippage max-slippage
|
||||
:loading-fees? loading-fees?
|
||||
:theme theme}]
|
||||
[standard-auth/slide-button
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-swap)
|
||||
:container-style {:z-index 2}
|
||||
:customization-color account-color
|
||||
:disabled? loading-fees?
|
||||
:auth-button-label (i18n/label :t/confirm)}]
|
||||
[rn/view {:style style/providers-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (colors/theme-colors colors/neutral-80-opa-40
|
||||
colors/white-opa-70
|
||||
theme)}}
|
||||
(i18n/label :t/swaps-powered-by {:provider (:name provider)})]]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
swap-transaction-data (rf/sub [:wallet/swap])
|
||||
{:keys [asset-to-pay max-slippage network
|
||||
pay-amount providers swap-proposal
|
||||
loading-fees?]} swap-transaction-data
|
||||
receive-amount (:receive-amount swap-proposal)
|
||||
receive-token (:receive-token swap-proposal)
|
||||
receive-token-symbol (:symbol receive-token)
|
||||
receive-token-address (:address receive-token)
|
||||
estimated-time-min (:estimated-time swap-proposal)
|
||||
pay-token-symbol (:symbol asset-to-pay)
|
||||
pay-token-address (:address asset-to-pay)
|
||||
native-currency-symbol (get-in swap-proposal [:from :native-currency-symbol])
|
||||
account (rf/sub [:wallet/current-viewing-account])
|
||||
account-color (:color account)
|
||||
provider (first providers)]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
:header [quo/page-nav
|
||||
{:icon-name :i/arrow-left
|
||||
:on-press on-close-action
|
||||
:margin-top (safe-area/get-top)
|
||||
:background :blur
|
||||
:accessibility-label :top-bar}]
|
||||
:footer [footer
|
||||
{:estimated-time-min estimated-time-min
|
||||
:native-currency-symbol native-currency-symbol
|
||||
:max-slippage max-slippage
|
||||
:account-color account-color
|
||||
:provider provider
|
||||
:loading-fees? loading-fees?
|
||||
:theme theme}]
|
||||
:gradient-cover? true
|
||||
:customization-color account-color}
|
||||
[rn/view
|
||||
[swap-title
|
||||
{:pay-token-symbol pay-token-symbol
|
||||
:pay-amount pay-amount
|
||||
:receive-token-symbol receive-token-symbol
|
||||
:receive-amount receive-amount
|
||||
:account account}]
|
||||
[summary-section
|
||||
{:title-accessibility-label :summary-section-pay
|
||||
:label (i18n/label :t/pay)
|
||||
:token-symbol pay-token-symbol
|
||||
:amount pay-amount
|
||||
:token-address pay-token-address
|
||||
:network (:network-name network)
|
||||
:theme theme}]
|
||||
[summary-section
|
||||
{:title-accessibility-label :summary-section-receive
|
||||
:label (i18n/label :t/receive)
|
||||
:token-symbol receive-token-symbol
|
||||
:amount receive-amount
|
||||
:token-address receive-token-address
|
||||
:network (:network-name network)
|
||||
:theme theme}]]]]))
|
|
@ -12,4 +12,8 @@
|
|||
[quo/button
|
||||
{:on-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content slippage-settings/view}])}
|
||||
(str "Edit Slippage: " max-slippage "%")]]))
|
||||
(str "Edit Slippage: " max-slippage "%")]
|
||||
[quo/button
|
||||
{:on-press #(rf/dispatch [:navigate-to-within-stack
|
||||
[:screen/wallet.swap-confirmation :screen/wallet.swap-propasal]])}
|
||||
"Swap confirmation"]]))
|
||||
|
|
|
@ -118,6 +118,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-confirmation.view :as wallet-swap-confirmation]
|
||||
[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]
|
||||
|
@ -521,6 +522,10 @@
|
|||
:options {:insets {:top? true}}
|
||||
:component wallet-swap-propasal/view}
|
||||
|
||||
{:name :screen/wallet.swap-confirmation
|
||||
:options {:modalPresentationStyle :overCurrentContext}
|
||||
:component wallet-swap-confirmation/view}
|
||||
|
||||
{:name :scan-profile-qr-code
|
||||
:options (merge
|
||||
options/dark-screen
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
fiat-value)]
|
||||
{:crypto (str crypto-formatted " " token-symbol)
|
||||
:fiat fiat-formatted})))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/swap-max-slippage
|
||||
:<- [:wallet/swap]
|
||||
|
|
|
@ -182,7 +182,7 @@
|
|||
"chat-with-friends": "Chat privately with friends",
|
||||
"chats": "Chats",
|
||||
"check-before-syncing": "Check before syncing",
|
||||
"check-before-syncing-doc-description" :"To sync your devices successfully, make sure to check and complete these steps:",
|
||||
"check-before-syncing-doc-description": "To sync your devices successfully, make sure to check and complete these steps:",
|
||||
"check-before-syncing-doc-checkbox-1": "Connect both devices to the same network",
|
||||
"check-before-syncing-doc-checkbox-2": "Make sure you are logged in on the other device",
|
||||
"check-before-syncing-doc-checkbox-3": "Disable the firewall and VPN on your devices",
|
||||
|
@ -2007,7 +2007,7 @@
|
|||
"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",
|
||||
"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",
|
||||
|
@ -2651,6 +2651,7 @@
|
|||
"testnet-not-available": "Testnet not available",
|
||||
"bridged-to": "Bridged to {{network}}",
|
||||
"slide-to-bridge": "Slide to bridge",
|
||||
"slide-to-swap": "Slide to swap",
|
||||
"provider-is-down": "The provider for the following chain(s) is down: {{chains}}",
|
||||
"unknown": "Unknown",
|
||||
"unsupported-file": "Unsupported file",
|
||||
|
@ -2746,12 +2747,15 @@
|
|||
"add-preferences": "Add preferences",
|
||||
"buy-eth": "Buy ETH",
|
||||
"not-enough-assets": "Not enough assets to pay gas fees",
|
||||
"send-from-network" : "Send from {{network}}",
|
||||
"define-amount-sent-from-network" : "Define amount sent from {{network}} network",
|
||||
"send-from-network": "Send from {{network}}",
|
||||
"define-amount-sent-from-network": "Define amount sent from {{network}} network",
|
||||
"dont-auto-recalculate-network": "Don't auto recalculate {{network}}",
|
||||
"import-keypair-to-use-account": "Import key pair to use this account",
|
||||
"import-keypair-steps": "{{account-name}} was derived from your {{keypair-name}} key pair, which has not yet been imported to this device. To transact using this account, you will need to import the {{keypair-name}} key pair first.",
|
||||
"not-now": "Not now",
|
||||
"share-usage-data": "Share usage data with Status",
|
||||
"value-higher-than-send-amount": "This value is higher than entered amount to send"
|
||||
"value-higher-than-send-amount": "This value is higher than entered amount to send",
|
||||
"swaps-powered-by": "Swaps powered by {{provider}}",
|
||||
"max-slippage": "Max slippage",
|
||||
"pay": "Pay"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue