From e1bbefa60bb3a154f7bbacdac658ba3e96105033 Mon Sep 17 00:00:00 2001 From: Brian Sztamfater Date: Fri, 16 Aug 2024 13:45:36 -0300 Subject: [PATCH] feat(swap): setup swap ui (#20853) Signed-off-by: Brian Sztamfater --- .../components/wallet/swap_input/view.cljs | 11 +- .../wallet/send/input_amount/view.cljs | 6 +- .../send/transaction_confirmation/view.cljs | 5 +- .../wallet/swap/select_asset_to_pay/view.cljs | 11 +- .../wallet/swap/set_spending_cap/view.cljs | 6 +- .../wallet/swap/setup_swap/style.cljs | 35 +++++ .../contexts/wallet/swap/setup_swap/view.cljs | 132 ++++++++++++++++++ .../wallet/swap/swap_confirmation/view.cljs | 6 +- .../wallet/swap/swap_proposal/view.cljs | 6 +- src/status_im/navigation/screens.cljs | 5 + src/status_im/subs/wallet/swap.cljs | 5 + src/status_im/subs/wallet/swap_test.cljs | 45 ++++++ src/status_im/subs/wallet/wallet.cljs | 34 +++-- src/status_im/subs/wallet/wallet_test.cljs | 44 +++--- translations/en.json | 2 + 15 files changed, 292 insertions(+), 61 deletions(-) create mode 100644 src/status_im/contexts/wallet/swap/setup_swap/style.cljs create mode 100644 src/status_im/contexts/wallet/swap/setup_swap/view.cljs diff --git a/src/quo/components/wallet/swap_input/view.cljs b/src/quo/components/wallet/swap_input/view.cljs index 4f5b7767b2..9d4444fba0 100644 --- a/src/quo/components/wallet/swap_input/view.cljs +++ b/src/quo/components/wallet/swap_input/view.cljs @@ -107,11 +107,12 @@ (assoc network-tag-props :status (if error? :error :default))]]) - [text/text - {:size :paragraph-2 - :style style/fiat-amount - :weight :medium} - (str currency-symbol fiat-value)]]) + (when fiat-value + [text/text + {:size :paragraph-2 + :style style/fiat-amount + :weight :medium} + (str currency-symbol fiat-value)])]) (when loading? [rn/view {:style (style/row-2-loader theme)}])]] (when (and (not= status :loading) (= type :pay) show-approval-label?) diff --git a/src/status_im/contexts/wallet/send/input_amount/view.cljs b/src/status_im/contexts/wallet/send/input_amount/view.cljs index 1b6b69c225..b90218764d 100644 --- a/src/status_im/contexts/wallet/send/input_amount/view.cljs +++ b/src/status_im/contexts/wallet/send/input_amount/view.cljs @@ -231,11 +231,9 @@ native-currency-symbol (when-not confirm-disabled? (get-in first-route [:from :native-currency-symbol])) - native-token (when native-currency-symbol - (rf/sub [:wallet/token-by-symbol + fee-formatted (when native-currency-symbol + (rf/sub [:wallet/wallet-send-fee-fiat-formatted native-currency-symbol])) - fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted - native-token]) show-select-asset-sheet #(rf/dispatch [:show-bottom-sheet {:content (fn [] diff --git a/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs b/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs index 5e3b2d64d5..d405d1c250 100644 --- a/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs +++ b/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs @@ -213,11 +213,8 @@ first-route (first route) native-currency-symbol (get-in first-route [:from :native-currency-symbol]) - 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]) + native-currency-symbol]) account (rf/sub [:wallet/current-viewing-account]) account-color (:color account) bridge-to-network (when bridge-to-chain-id diff --git a/src/status_im/contexts/wallet/swap/select_asset_to_pay/view.cljs b/src/status_im/contexts/wallet/swap/select_asset_to_pay/view.cljs index 753aca83ce..2f606687ce 100644 --- a/src/status_im/contexts/wallet/swap/select_asset_to_pay/view.cljs +++ b/src/status_im/contexts/wallet/swap/select_asset_to_pay/view.cljs @@ -28,20 +28,23 @@ :max-priority-fee-per-gas "0.011000001" :eip1559-enabled true} :estimated-time 3 - :receive-amount 99.98 - :receive-token {:symbol "SNT" + :receive-amount "99.98" + :pay-token {:symbol "SNT" + :address "0x432492384728934239789"} + :receive-token {:symbol "USDT" :address "0x432492384728934239789"}}) (defn- assets-view [search-text on-change-text] (let [on-token-press (fn [token] - (let [token-networks (:networks token)] + (let [token-networks (:networks token) + asset-to-receive (rf/sub [:wallet/token-by-symbol "SNT"])] (rf/dispatch [:wallet.swap/select-asset-to-pay {:token token :network (when (= (count token-networks) 1) (first token-networks)) :stack-id :screen/wallet.swap-select-asset-to-pay}]) - (rf/dispatch [:wallet.swap/select-asset-to-receive {:token token}]) + (rf/dispatch [:wallet.swap/select-asset-to-receive {:token asset-to-receive}]) (rf/dispatch [:wallet.swap/set-pay-amount 100]) (rf/dispatch [:wallet.swap/set-swap-proposal dummy-swap-proposal]) (rf/dispatch [:wallet.swap/set-provider])))] diff --git a/src/status_im/contexts/wallet/swap/set_spending_cap/view.cljs b/src/status_im/contexts/wallet/swap/set_spending_cap/view.cljs index 05fde4eca4..8cc10826a1 100644 --- a/src/status_im/contexts/wallet/swap/set_spending_cap/view.cljs +++ b/src/status_im/contexts/wallet/swap/set_spending_cap/view.cljs @@ -172,11 +172,7 @@ (defn footer [{:keys [estimated-time-min native-currency-symbol network theme account-color 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]) + (let [fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted native-currency-symbol]) on-auth-success (rn/use-callback #(js/alert "Not implemented yet"))] [rn/view {:style {:margin-bottom -10}} [transaction-details diff --git a/src/status_im/contexts/wallet/swap/setup_swap/style.cljs b/src/status_im/contexts/wallet/swap/setup_swap/style.cljs new file mode 100644 index 0000000000..fd38634d5f --- /dev/null +++ b/src/status_im/contexts/wallet/swap/setup_swap/style.cljs @@ -0,0 +1,35 @@ +(ns status-im.contexts.wallet.swap.setup-swap.style) + +(def container + {:flex 1}) + +(def keyboard-container + {:align-self :flex-end + :width "100%"}) + +(def inputs-container + {:padding-top 12 + :padding-horizontal 20}) + +(def details-container + {:flex-direction :row + :justify-content :space-between + :padding-top 7 + :padding-horizontal 20}) + +(def detail-item + {:flex 1 + :height 36 + :background-color :transparent}) + +(def swap-order-button + {:margin-top -9 + :z-index 2 + :align-self :center}) + +(def receive-token-swap-input-container + {:margin-top -9}) + +(def footer-container + {:flex 1 + :justify-content :flex-end}) diff --git a/src/status_im/contexts/wallet/swap/setup_swap/view.cljs b/src/status_im/contexts/wallet/swap/setup_swap/view.cljs new file mode 100644 index 0000000000..06eadb2834 --- /dev/null +++ b/src/status_im/contexts/wallet/swap/setup_swap/view.cljs @@ -0,0 +1,132 @@ +(ns status-im.contexts.wallet.swap.setup-swap.view + (:require [quo.core :as quo] + [react-native.core :as rn] + [react-native.safe-area :as safe-area] + [status-im.contexts.wallet.common.account-switcher.view :as account-switcher] + [status-im.contexts.wallet.common.utils :as utils] + [status-im.contexts.wallet.swap.setup-swap.style :as style] + [utils.i18n :as i18n] + [utils.navigation :as navigation] + [utils.re-frame :as rf])) + +(defn- data-item + [{:keys [title subtitle size subtitle-icon loading?]}] + [quo/data-item + {:container-style style/detail-item + :blur? false + :card? false + :subtitle-type (if subtitle-icon :editable :default) + :status (if loading? :loading :default) + :title title + :subtitle subtitle + :size size + :icon subtitle-icon}]) + +(defn- transaction-details + [{:keys [max-slippage native-currency-symbol loading-fees?]}] + (let [max-fees (rf/sub [:wallet/wallet-send-fee-fiat-formatted native-currency-symbol])] + [rn/view {:style style/details-container} + [data-item + {:title (i18n/label :t/max-fees) + :subtitle max-fees + :loading? loading-fees? + :size :small}] + [data-item + {:title (i18n/label :t/max-slippage) + :subtitle max-slippage + :subtitle-icon :i/edit + :loading? loading-fees?}]])) + +(defn view + [] + (let [[pay-value set-pay-value] (rn/use-state "") + {:keys [color]} (rf/sub [:wallet/current-viewing-account]) + {:keys [max-slippage swap-proposal loading-fees? + receive-amount network]} (rf/sub [:wallet/swap]) + currency (rf/sub [:profile/currency]) + currency-symbol (rf/sub [:profile/currency-symbol]) + asset-to-pay (rf/sub [:wallet/swap-asset-to-pay]) + asset-to-receive (rf/sub [:wallet/swap-asset-to-receive]) + + pay-token-fiat-value (utils/calculate-token-fiat-value + {:currency currency + :balance (or pay-value 0) + :token asset-to-pay}) + receive-token-fiat-value (utils/calculate-token-fiat-value + {:currency currency + :balance (or receive-amount 0) + :token asset-to-receive}) + native-currency-symbol (get-in swap-proposal + [:from :native-currency-symbol]) + pay-token-symbol (:symbol asset-to-pay) + receive-token-symbol (:symbol asset-to-receive) + on-press (fn [v] (set-pay-value (str pay-value v))) + delete (fn [] + (set-pay-value #(subs % 0 (dec (count %)))))] + [rn/view {:style style/container} + [account-switcher/view + {:on-press navigation/navigate-back + :icon-name :i/arrow-left + :margin-top (safe-area/get-top) + :switcher-type :select-account}] + [rn/view {:style style/inputs-container} + [quo/swap-input + {:type :pay + :error? false + :token pay-token-symbol + :customization-color :blue + :show-approval-label? false + :status :default + :currency-symbol currency-symbol + :on-swap-press #(js/alert "Swap Pressed") + :on-token-press #(js/alert "Token Pressed") + :on-max-press #(js/alert "Max Pressed") + :value pay-value + :fiat-value pay-token-fiat-value + :network-tag-props {:title (i18n/label :t/max-token + {:number 200 + :token-symbol pay-token-symbol}) + :networks [{:source (:source network)}]} + :approval-label-props {:status :approve + :token-value pay-value + :button-props {:on-press + #(js/alert "Approve Pressed")} + :customization-color color + :token-symbol pay-token-symbol}}] + [quo/swap-order-button + {:container-style style/swap-order-button + :on-press #(js/alert "Pressed")}] + [quo/swap-input + {:type :receive + :error? false + :token receive-token-symbol + :customization-color color + :show-approval-label? false + :enable-swap? true + :status :default + :currency-symbol currency-symbol + :on-swap-press #(js/alert "Swap Pressed") + :on-token-press #(js/alert "Token Pressed") + :on-max-press #(js/alert "Max Pressed") + :value receive-amount + :fiat-value receive-token-fiat-value + :container-style style/receive-token-swap-input-container}]] + [rn/view {:style style/footer-container} + (when swap-proposal + [transaction-details + {:native-currency-symbol native-currency-symbol + :max-slippage max-slippage + :loading-fees? loading-fees?}]) + [quo/bottom-actions + {:actions :one-action + :button-one-label (i18n/label :t/review-swap) + :button-one-props {:disabled? (or (not swap-proposal) + loading-fees?) + :customization-color color + :on-press #(js/alert "Review swap pressed")}}]] + [quo/numbered-keyboard + {:container-style style/keyboard-container + :left-action :dot + :delete-key? true + :on-press on-press + :on-delete delete}]])) diff --git a/src/status_im/contexts/wallet/swap/swap_confirmation/view.cljs b/src/status_im/contexts/wallet/swap/swap_confirmation/view.cljs index 7a4acfc5c5..a7509acdee 100644 --- a/src/status_im/contexts/wallet/swap/swap_confirmation/view.cljs +++ b/src/status_im/contexts/wallet/swap/swap_confirmation/view.cljs @@ -103,11 +103,7 @@ (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])] + (let [fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted native-currency-symbol])] [:<> [transaction-details {:estimated-time-min estimated-time-min diff --git a/src/status_im/contexts/wallet/swap/swap_proposal/view.cljs b/src/status_im/contexts/wallet/swap/swap_proposal/view.cljs index c0fab70cac..6314046376 100644 --- a/src/status_im/contexts/wallet/swap/swap_proposal/view.cljs +++ b/src/status_im/contexts/wallet/swap/swap_proposal/view.cljs @@ -19,4 +19,8 @@ "Swap confirmation"] [quo/button {:on-press #(rf/dispatch [:open-modal :screen/wallet.swap-set-spending-cap])} - "Set spending cap"]])) + "Set spending cap"] + [quo/button + {:on-press #(rf/dispatch [:navigate-to-within-stack + [:screen/wallet.setup-swap :screen/wallet.swap-propasal]])} + "Setup swap"]])) diff --git a/src/status_im/navigation/screens.cljs b/src/status_im/navigation/screens.cljs index 4888aec9f6..b5bf76dd88 100644 --- a/src/status_im/navigation/screens.cljs +++ b/src/status_im/navigation/screens.cljs @@ -120,6 +120,7 @@ [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.set-spending-cap.view :as wallet-swap-set-spending-cap] + [status-im.contexts.wallet.swap.setup-swap.view :as wallet-swap-setup-swap] [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 @@ -522,6 +523,10 @@ :insets {:top? true}} :component wallet-swap-select-asset-to-pay/view} + {:name :screen/wallet.setup-swap + :options {:insets {:bottom? true}} + :component wallet-swap-setup-swap/view} + {:name :screen/wallet.swap-propasal :options {:insets {:top? true}} :component wallet-swap-propasal/view} diff --git a/src/status_im/subs/wallet/swap.cljs b/src/status_im/subs/wallet/swap.cljs index 75aa21fed9..b71409493e 100644 --- a/src/status_im/subs/wallet/swap.cljs +++ b/src/status_im/subs/wallet/swap.cljs @@ -14,6 +14,11 @@ :<- [:wallet/swap] :-> :asset-to-pay) +(rf/reg-sub + :wallet/swap-asset-to-receive + :<- [:wallet/swap] + :-> :asset-to-receive) + (rf/reg-sub :wallet/swap-asset-to-pay-token-symbol :<- [:wallet/swap-asset-to-pay] diff --git a/src/status_im/subs/wallet/swap_test.cljs b/src/status_im/subs/wallet/swap_test.cljs index 3e46034ebd..5b0dba310a 100644 --- a/src/status_im/subs/wallet/swap_test.cljs +++ b/src/status_im/subs/wallet/swap_test.cljs @@ -64,6 +64,43 @@ :token-list-id "" :built-on "ETH" :verified true} + :asset-to-receive + {:description "Dai Stablecoin" + :decimals 18 + :symbol "DAI" + :name "Dai Stablecoin" + :total-balance 1 + :balances-per-chain + {1 + {:raw-balance 1000000000000000000 + :balance "1" + :chain-id 1} + 10 + {:raw-balance 0 + :balance "0" + :chain-id 10} + 42161 + {:raw-balance 0 + :balance "0" + :chain-id 42161}} + :networks (concat [(networks :mainnet-network)] (networks :layer-2-networks)) + :chain-id 0 + :market-values-per-currency + {:usd + {:change-24hour -0.00109422754667007 + :change-pct-day -5.57352274163899 + :change-pct-24hour -4.177805426737527 + :high-day 0.0271858672171352 + :market-cap 170783296.1155821 + :has-error false + :change-pct-hour -0.0160462113709363 + :low-day 0.02473516779550377 + :price 0.0251}} + :asset-website-url "https://status.im/" + :available-balance 1 + :token-list-id "" + :built-on "ETH" + :verified true} :network nil}) (h/deftest-sub :wallet/swap @@ -82,6 +119,14 @@ swap-data) (is (match? (swap-data :asset-to-pay) (rf/sub [sub-name]))))) +(h/deftest-sub :wallet/swap-asset-to-receive + [sub-name] + (testing "Return swap asset-to-receive" + (swap! rf-db/app-db assoc-in + [:wallet :ui :swap] + swap-data) + (is (match? (swap-data :asset-to-receive) (rf/sub [sub-name]))))) + (h/deftest-sub :wallet/swap-asset-to-pay-token-symbol [sub-name] (testing "Return asset-to-pay token symbol" diff --git a/src/status_im/subs/wallet/wallet.cljs b/src/status_im/subs/wallet/wallet.cljs index 83e68bed49..cef2e27b23 100644 --- a/src/status_im/subs/wallet/wallet.cljs +++ b/src/status_im/subs/wallet/wallet.cljs @@ -690,23 +690,29 @@ (rf/reg-sub :wallet/wallet-send-fee-fiat-formatted + :<- [:wallet/current-viewing-account] :<- [:wallet/wallet-send-route] :<- [:profile/currency] :<- [:profile/currency-symbol] - (fn [[route currency currency-symbol] [_ token-for-fees]] - (let [fee-in-native-token (send-utils/calculate-full-route-gas-fee route) - fee-in-crypto-formatted (utils/get-standard-crypto-format - token-for-fees - fee-in-native-token) - fee-in-fiat (utils/calculate-token-fiat-value - {:currency currency - :balance fee-in-native-token - :token token-for-fees}) - fee-formatted (utils/get-standard-fiat-format - fee-in-crypto-formatted - currency-symbol - fee-in-fiat)] - fee-formatted))) + (fn [[account route currency currency-symbol] [_ token-symbol-for-fees]] + (when token-symbol-for-fees + (let [tokens (:tokens account) + token-for-fees (first (filter #(= (string/lower-case (:symbol %)) + (string/lower-case token-symbol-for-fees)) + tokens)) + fee-in-native-token (send-utils/calculate-full-route-gas-fee route) + fee-in-crypto-formatted (utils/get-standard-crypto-format + token-for-fees + fee-in-native-token) + fee-in-fiat (utils/calculate-token-fiat-value + {:currency currency + :balance fee-in-native-token + :token token-for-fees}) + fee-formatted (utils/get-standard-fiat-format + fee-in-crypto-formatted + currency-symbol + fee-in-fiat)] + fee-formatted)))) (rf/reg-sub :wallet/has-partially-operable-accounts? diff --git a/src/status_im/subs/wallet/wallet_test.cljs b/src/status_im/subs/wallet/wallet_test.cljs index 571f6981ba..eaff51d605 100644 --- a/src/status_im/subs/wallet/wallet_test.cljs +++ b/src/status_im/subs/wallet/wallet_test.cljs @@ -13,17 +13,20 @@ {:before #(reset! rf-db/app-db {})}) (def ^:private accounts-with-tokens - {:0x1 {:tokens [{:symbol "ETH" - :balances-per-chain {1 {:raw-balance "100"}}} - {:symbol "SNT" - :balances-per-chain {1 {:raw-balance "100"}}}] + {:0x1 {:tokens [{:symbol "ETH" + :balances-per-chain {1 {:raw-balance "100"}} + :market-values-per-currency {:usd {:price 10000}}} + {:symbol "SNT" + :balances-per-chain {1 {:raw-balance "100"}} + :market-values-per-currency {:usd {:price 10000}}}] :network-preferences-names #{} :customization-color nil :operable? true :operable :fully :address "0x1"} - :0x2 {:tokens [{:symbol "SNT" - :balances-per-chain {1 {:raw-balance "200"}}}] + :0x2 {:tokens [{:symbol "SNT" + :balances-per-chain {1 {:raw-balance "200"}} + :market-values-per-currency {:usd {:price 10000}}}] :network-preferences-names #{} :customization-color nil :operable? true @@ -501,10 +504,12 @@ (assoc-in [:wallet :ui :send :token-symbol] "ETH"))) (let [result (rf/sub [sub-name])] (is (match? result - [{:tokens [{:symbol "ETH" - :balances-per-chain {1 {:raw-balance "100"}}} - {:symbol "SNT" - :balances-per-chain {1 {:raw-balance "100"}}}] + [{:tokens [{:symbol "ETH" + :balances-per-chain {1 {:raw-balance "100"}} + :market-values-per-currency {:usd {:price 10000}}} + {:symbol "SNT" + :balances-per-chain {1 {:raw-balance "100"}} + :market-values-per-currency {:usd {:price 10000}}}] :network-preferences-names #{} :customization-color nil :operable? true @@ -518,10 +523,12 @@ (assoc-in [:wallet :ui :send :token] {:symbol "ETH"}))) (let [result (rf/sub [sub-name])] (is (match? result - [{:tokens [{:symbol "ETH" - :balances-per-chain {1 {:raw-balance "100"}}} - {:symbol "SNT" - :balances-per-chain {1 {:raw-balance "100"}}}] + [{:tokens [{:symbol "ETH" + :balances-per-chain {1 {:raw-balance "100"}} + :market-values-per-currency {:usd {:price 10000}}} + {:symbol "SNT" + :balances-per-chain {1 {:raw-balance "100"}} + :market-values-per-currency {:usd {:price 10000}}}] :network-preferences-names #{} :customization-color nil :operable? true @@ -959,15 +966,14 @@ (testing "wallet send fee calculated and formatted in fiat" (swap! rf-db/app-db #(-> % + (assoc-in [:wallet :accounts] accounts-with-tokens) + (assoc-in [:wallet :current-viewing-account-address] "0x1") (assoc-in [:wallet :ui :send :route] route-data) (assoc-in [:profile/profile :currency] :usd) (assoc-in [:profile/profile :currency-symbol] "$"))) - (let [token-for-fees {:decimals 18 - :symbol "ETH" - :name "Ether" - :market-values-per-currency {:usd {:price 10000}}} - result (rf/sub [sub-name token-for-fees])] + (let [token-symbol-for-fees "ETH" + result (rf/sub [sub-name token-symbol-for-fees])] (is (match? result "$1.00"))))) (h/deftest-sub :wallet/has-partially-operable-accounts? diff --git a/translations/en.json b/translations/en.json index feea3b35ab..3dd2b241cb 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1478,6 +1478,7 @@ "max-fees": "Max fees", "max-priority-fee": "Max priority fee", "max-slippage": "Max slippage", + "max-token": "Max: {{number}} {{token-symbol}}", "maximum-fee": "Maximum fee", "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.", "may": "May", @@ -2070,6 +2071,7 @@ "reveal-sync-code": "Reveal sync code", "review-bridge": "Review bridge", "review-send": "Review send", + "review-swap": "Review swap", "revoke-access": "Revoke access", "ropsten-testnet": "Ropsten Testnet", "rpc-usage-copy": "Copy",