feat: calculate and show max fees on transaction confirmation page (#20133)

Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
Brian Sztamfater 2024-05-28 18:16:47 -03:00 committed by GitHub
parent 47f6bda563
commit a63ea3290e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 114 additions and 99 deletions

View File

@ -96,7 +96,8 @@
:layer 1}] :layer 1}]
:wallet/wallet-send-enabled-from-chain-ids [1] :wallet/wallet-send-enabled-from-chain-ids [1]
:wallet/wallet-send-amount nil :wallet/wallet-send-amount nil
:wallet/wallet-send-tx-type :tx/send}) :wallet/wallet-send-tx-type :tx/send
:wallet/wallet-send-fee-fiat-formatted "$5,00"})
(h/describe "Send > input amount screen" (h/describe "Send > input amount screen"
(h/setup-restorable-re-frame) (h/setup-restorable-re-frame)

View File

@ -12,7 +12,6 @@
[status-im.contexts.wallet.common.utils :as utils] [status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.input-amount.style :as style] [status-im.contexts.wallet.send.input-amount.style :as style]
[status-im.contexts.wallet.send.routes.view :as routes] [status-im.contexts.wallet.send.routes.view :as routes]
[status-im.contexts.wallet.send.utils :as send-utils]
[status-im.contexts.wallet.sheets.unpreferred-networks-alert.view :as unpreferred-networks-alert] [status-im.contexts.wallet.sheets.unpreferred-networks-alert.view :as unpreferred-networks-alert]
[utils.debounce :as debounce] [utils.debounce :as debounce]
[utils.i18n :as i18n] [utils.i18n :as i18n]
@ -227,22 +226,8 @@
native-token (when native-currency-symbol native-token (when native-currency-symbol
(rf/sub [:wallet/token-by-symbol (rf/sub [:wallet/token-by-symbol
native-currency-symbol])) native-currency-symbol]))
fee-in-native-token (when-not confirm-disabled? fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted
(send-utils/calculate-full-route-gas-fee route)) native-token])
fee-in-crypto-formatted (when fee-in-native-token
(utils/get-standard-crypto-format
native-token
fee-in-native-token))
fee-in-fiat (when-not confirm-disabled?
(utils/calculate-token-fiat-value
{:currency fiat-currency
:balance fee-in-native-token
:token native-token}))
fee-formatted (when fee-in-fiat
(utils/get-standard-fiat-format
fee-in-crypto-formatted
currency-symbol
fee-in-fiat))
show-select-asset-sheet #(rf/dispatch show-select-asset-sheet #(rf/dispatch
[:show-bottom-sheet [:show-bottom-sheet
{:content (fn [] {:content (fn []
@ -349,7 +334,7 @@
sender-network-values sender-network-values
token-not-supported-in-receiver-networks?) token-not-supported-in-receiver-networks?)
[token-not-available token-symbol receiver-networks token-networks]) [token-not-available token-symbol receiver-networks token-networks])
(when (or loading-routes? fee-formatted) (when (or loading-routes? route)
[estimated-fees [estimated-fees
{:loading-routes? loading-routes? {:loading-routes? loading-routes?
:fees fee-formatted :fees fee-formatted

View File

@ -2,8 +2,9 @@
(:require [quo.foundations.colors :as colors])) (:require [quo.foundations.colors :as colors]))
(def detail-item (def detail-item
{:flex 1 {:flex 1
:height 36}) :height 36
:background-color :transparent})
(def content-container (def content-container
{:padding-top 12 {:padding-top 12
@ -14,22 +15,14 @@
{:margin-right 4}) {:margin-right 4})
(defn details-container (defn details-container
[{:keys [loading-suggested-routes? route-loaded? theme]}] [{:keys [loading-suggested-routes? route-loaded?]}]
{:flex-direction :row {:flex-direction :row
:justify-content (if route-loaded? :space-between :center) :width "100%"
:height (when (or loading-suggested-routes? route-loaded?) 52) :justify-content (if route-loaded? :space-between :center)
:padding-horizontal 12 :height (when (or loading-suggested-routes? route-loaded?) 52)
:padding-top 7 :margin-horizontal 5
:padding-bottom 8 :padding-top 7
:border-radius 16 :margin-bottom 8})
:border-width 1
:border-color (if (or loading-suggested-routes? route-loaded?)
(colors/theme-colors colors/neutral-10 colors/neutral-90 theme)
:transparent)})
(def details-title-container
{:padding-horizontal 20
:padding-bottom 16})
(defn section-label (defn section-label
[theme] [theme]

View File

@ -166,46 +166,33 @@
(defn- transaction-details (defn- transaction-details
[{:keys [estimated-time-min max-fees token-display-name amount to-network route [{:keys [estimated-time-min max-fees token-display-name amount to-network route
transaction-type transaction-type]}]
theme]}] (let [route-loaded? (and route (seq route))
(let [currency-symbol (rf/sub [:profile/currency-symbol])
route-loaded? (and route (seq route))
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])] loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])]
[rn/view [rn/view
{:style style/details-title-container} {:style (style/details-container
[quo/text {:loading-suggested-routes? loading-suggested-routes?
{:size :paragraph-2 :route-loaded? route-loaded?})}
:weight :medium (cond
:style (style/section-label theme) loading-suggested-routes?
:accessibility-label :summary-from-label} [rn/activity-indicator {:style {:flex 1}}]
(i18n/label :t/details)] route-loaded?
[rn/view [:<>
{:style (style/details-container [data-item
{:loading-suggested-routes? loading-suggested-routes? {:title (i18n/label :t/est-time)
:route-loaded? route-loaded? :subtitle (i18n/label :t/time-in-mins {:minutes (str estimated-time-min)})}]
:theme theme})} [data-item
(cond {:title (i18n/label :t/max-fees)
loading-suggested-routes? :subtitle max-fees}]
[rn/activity-indicator {:style {:align-self :center}}] [data-item
route-loaded? {:title (if (= transaction-type :tx/bridge)
[:<> (i18n/label :t/bridged-to
[data-item {:network (:abbreviated-name to-network)})
{:title (i18n/label :t/est-time) (i18n/label :t/recipient-gets))
:subtitle (i18n/label :t/time-in-mins {:minutes (str estimated-time-min)})}] :subtitle (str amount " " token-display-name)}]]
[data-item :else
{:title (i18n/label :t/max-fees) [quo/text {:style {:align-self :center}}
:subtitle (i18n/label :t/amount-with-currency-symbol (i18n/label :t/no-routes-found-confirmation)])]))
{:amount (str max-fees)
:symbol currency-symbol})}]
[data-item
{:title (if (= transaction-type :tx/bridge)
(i18n/label :t/bridged-to
{:network (:abbreviated-name to-network)})
(i18n/label :t/recipient-gets))
:subtitle (str amount " " token-display-name)}]]
:else
[quo/text {:style {:align-self :center}}
(i18n/label :t/no-routes-found-confirmation)])]]))
(defn view (defn view
[_] [_]
@ -222,12 +209,17 @@
(get-in collectible [:preview-url :uri])) (get-in collectible [:preview-url :uri]))
transaction-type (:tx-type send-transaction-data) transaction-type (:tx-type send-transaction-data)
estimated-time-min (reduce + (map :estimated-time route)) estimated-time-min (reduce + (map :estimated-time route))
max-fees "-" 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])
account (rf/sub [:wallet/current-viewing-account]) account (rf/sub [:wallet/current-viewing-account])
account-color (:color account) account-color (:color account)
bridge-to-network (when bridge-to-chain-id bridge-to-network (when bridge-to-chain-id
(rf/sub [:wallet/network-details-by-chain-id (rf/sub [:wallet/network-details-by-chain-id
bridge-to-chain-id])) bridge-to-chain-id]))
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
from-account-props {:customization-color account-color from-account-props {:customization-color account-color
:size 32 :size 32
:emoji (:emoji account) :emoji (:emoji account)
@ -246,19 +238,29 @@
:margin-top (safe-area/get-top) :margin-top (safe-area/get-top)
:background :blur :background :blur
:accessibility-label :top-bar}] :accessibility-label :top-bar}]
:footer (when (and route (seq route)) :footer [:<>
[standard-auth/slide-button [transaction-details
{:size :size-48 {:estimated-time-min estimated-time-min
:track-text (if (= transaction-type :tx/bridge) :max-fees fee-formatted
(i18n/label :t/slide-to-bridge) :token-display-name token-display-name
(i18n/label :t/slide-to-send)) :amount amount
:container-style {:z-index 2} :to-network bridge-to-network
:customization-color account-color :theme theme
:on-auth-success #(rf/dispatch :route route
[:wallet/send-transaction :transaction-type transaction-type}]
(security/safe-unmask-data (when (and (not loading-suggested-routes?) route (seq route))
%)]) [standard-auth/slide-button
:auth-button-label (i18n/label :t/confirm)}]) {:size :size-48
:track-text (if (= transaction-type :tx/bridge)
(i18n/label :t/slide-to-bridge)
(i18n/label :t/slide-to-send))
:container-style {:z-index 2}
:customization-color account-color
:on-auth-success #(rf/dispatch
[:wallet/send-transaction
(security/safe-unmask-data
%)])
:auth-button-label (i18n/label :t/confirm)}])]
:gradient-cover? true :gradient-cover? true
:customization-color (:color account)} :customization-color (:color account)}
[rn/view [rn/view
@ -291,13 +293,4 @@
from-account-props from-account-props
user-props) user-props)
:network-values to-values-by-chain :network-values to-values-by-chain
:theme theme}] :theme theme}]]]]))))
[transaction-details
{:estimated-time-min estimated-time-min
:max-fees max-fees
:token-display-name token-display-name
:amount amount
:to-network bridge-to-network
:theme theme
:route route
:transaction-type transaction-type}]]]]))))

View File

@ -4,6 +4,7 @@
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.wallet.common.utils :as utils] [status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.common.utils.networks :as network-utils] [status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.contexts.wallet.send.utils :as send-utils]
[status-im.subs.wallet.add-account.address-to-watch] [status-im.subs.wallet.add-account.address-to-watch]
[utils.number] [utils.number]
[utils.security.core :as security])) [utils.security.core :as security]))
@ -574,3 +575,23 @@
:<- [:wallet/wallet-send-enabled-networks] :<- [:wallet/wallet-send-enabled-networks]
(fn [send-enabled-networks] (fn [send-enabled-networks]
(map :chain-id send-enabled-networks))) (map :chain-id send-enabled-networks)))
(rf/reg-sub
:wallet/wallet-send-fee-fiat-formatted
:<- [: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)))

View File

@ -187,6 +187,12 @@
:chain-id 10 :chain-id 10
:layer 2}]}) :layer 2}]})
(def route-data
[{:gas-amount "25000"
:gas-fees {:max-fee-per-gas-medium "4"
:eip-1559-enabled true
:l-1-gas-fee "0"}}])
(h/deftest-sub :wallet/balances-in-selected-networks (h/deftest-sub :wallet/balances-in-selected-networks
[sub-name] [sub-name]
(testing "a map: address->balance" (testing "a map: address->balance"
@ -890,3 +896,19 @@
(is (match? (get result constants/ethereum-mainnet-chain-id) "$1500.00")) (is (match? (get result constants/ethereum-mainnet-chain-id) "$1500.00"))
(is (match? (get result constants/optimism-mainnet-chain-id) "$600.00")) (is (match? (get result constants/optimism-mainnet-chain-id) "$600.00"))
(is (match? (get result constants/arbitrum-mainnet-chain-id) "$0.00"))))) (is (match? (get result constants/arbitrum-mainnet-chain-id) "$0.00")))))
(h/deftest-sub :wallet/wallet-send-fee-fiat-formatted
[sub-name]
(testing "wallet send fee calculated and formatted in fiat"
(swap! rf-db/app-db
#(-> %
(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])]
(is (match? result "$1.00")))))