fix(swap): refetch swap proposal when switching account (#21518)

Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
Brian Sztamfater 2024-11-10 20:16:11 -03:00 committed by GitHub
parent ca22b67d0e
commit a7d330ecb3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 176 additions and 43 deletions

View File

@ -192,6 +192,18 @@
(number/small-number-threshold display-decimals)
(str amount-fixed-decimals))))
(defn token-balance-display-for-network
"Formats a token balance for a specific chain and rounds it to a specified number of decimals.
If the balance is less than the smallest representable value based on rounding decimals,
a threshold value is displayed instead."
[token chain-id rounding-decimals]
(let [token-decimals (:decimals token)
display-decimals (min token-decimals rounding-decimals)]
(-> (get-in token [:balances-per-chain chain-id :raw-balance] 0)
(number/convert-to-whole-number token-decimals)
money/bignumber
(sanitized-token-amount-to-display display-decimals))))
(defn calculate-balance-from-tokens
[{:keys [currency tokens chain-ids]}]
(->> tokens

View File

@ -195,3 +195,77 @@
(is (= (utils/sanitized-token-amount-to-display 0.00000123 6) "0.000001"))
(is (= (utils/sanitized-token-amount-to-display nil 2) "0"))
(is (= (utils/sanitized-token-amount-to-display "invalid" 2) "0"))))
(deftest token-balance-display-for-network-test
(testing "Standard balance with rounding decimals"
(let [token {:decimals 18
:balances-per-chain {1 {:raw-balance "1000000000000000000"}}}
chain-id 1
rounding-decimals 2
expected "1"]
(is (= (utils/token-balance-display-for-network token chain-id rounding-decimals)
expected))))
(testing "Balance with more decimals than specified rounding"
(let [token {:decimals 18
:balances-per-chain {1 {:raw-balance "123456789000000000"}}}
chain-id 1
rounding-decimals 3
expected "0.123"]
(is (= (utils/token-balance-display-for-network token chain-id rounding-decimals)
expected))))
(testing "Very small balance displayed as threshold (<0.000001)"
(let [token {:decimals 18
:balances-per-chain {1 {:raw-balance "1"}}}
chain-id 1
rounding-decimals 6
expected "<0.000001"]
(is (= (utils/token-balance-display-for-network token chain-id rounding-decimals)
expected))))
(testing
"Very small balance displayed without threshold when token decimals are equal than reounding decimals"
(let [token {:decimals 18
:balances-per-chain {1 {:raw-balance "1"}}}
chain-id 1
rounding-decimals 18
expected "0.000000000000000001"]
(is (= (utils/token-balance-display-for-network token chain-id rounding-decimals)
expected))))
(testing
"Very small balance displayed without threshold when token decimals are lower than reounding decimals"
(let [token {:decimals 18
:balances-per-chain {1 {:raw-balance "1"}}}
chain-id 1
rounding-decimals 21
expected "0.000000000000000001"]
(is (= (utils/token-balance-display-for-network token chain-id rounding-decimals)
expected))))
(testing "Zero balance displayed correctly"
(let [token {:decimals 18
:balances-per-chain {1 {:raw-balance "0"}}}
chain-id 1
rounding-decimals 2
expected "0"]
(is (= (utils/token-balance-display-for-network token chain-id rounding-decimals)
expected))))
(testing "Balance with trailing zeroes removed"
(let [token {:decimals 8
:balances-per-chain {1 {:raw-balance "123400000"}}}
chain-id 1
rounding-decimals 6
expected "1.234"]
(is (= (utils/token-balance-display-for-network token chain-id rounding-decimals)
expected))))
(testing "Balance when chain data is missing"
(let [token {:decimals 18}
chain-id 1
rounding-decimals 2
expected "0"]
(is (= (utils/token-balance-display-for-network token chain-id rounding-decimals)
expected)))))

View File

@ -2,11 +2,13 @@
(:require [quo.core :as quo]
quo.theme
[react-native.gesture :as gesture]
[status-im.contexts.wallet.common.utils :as wallet.utils]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.sheets.select-account.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def ^:private rounding-decimals 4)
(defn list-item
[{:keys [account selected-account-address]}]
(let [{:keys [color address]} account]
@ -25,12 +27,14 @@
token (->> tokens
(filter #(= (:symbol %) asset-symbol))
first)
token-balance (get-in token [:balances-per-chain (:chain-id network) :balance])]
chain-id (:chain-id network)
token-balance-display (utils/token-balance-display-for-network token
chain-id
rounding-decimals)]
[quo/account-item
{:type (if (= address selected-account-address) :default :tag)
:token-props {:symbol asset-symbol
:value (wallet.utils/cut-fiat-balance (or (js/parseFloat token-balance) 0)
4)}
:value token-balance-display}
:account-props (assoc account :customization-color color)
:customization-color color
:state (if (= address selected-account-address) :selected :default)

View File

@ -247,13 +247,12 @@
(rf/reg-event-fx
:wallet/clean-swap-proposal
(fn [{:keys [db]} [{:keys [clean-approval-transaction?]}]]
(let [keys-to-dissoc (cond-> [:amount
:amount-hex
:last-request-uuid
(fn [{:keys [db]} [{:keys [clean-amounts? clean-approval-transaction?]}]]
(let [keys-to-dissoc (cond-> [:last-request-uuid
:swap-proposal
:error-response
:loading-swap-proposal?]
clean-amounts? (conj :amount :amount-hex)
clean-approval-transaction? (conj :approval-transaction-id :approved-amount))]
{:db (apply update-in db [:wallet :ui :swap] dissoc keys-to-dissoc)
:fx [[:dispatch [:wallet/stop-get-swap-proposal]]]})))

View File

@ -26,13 +26,14 @@
[utils.string :as utils.string]))
(def ^:private default-text-for-unfocused-input "0.00")
(def ^:private default-token-symbol "ETH")
(defn- on-close
[start-point]
(when (= start-point :action-menu)
(rf/dispatch [:centralized-metrics/track :metric/swap-closed]))
(rf/dispatch [:wallet/clean-swap-proposal {:clean-approval-transaction? true}])
(rf/dispatch [:wallet/clean-swap-proposal
{:clean-amounts? true
:clean-approval-transaction? true}])
(events-helper/navigate-back))
(defn- fetch-swap-proposal
@ -43,7 +44,8 @@
:clean-approval-transaction? clean-approval-transaction?}]
100)
(rf/dispatch [:wallet/clean-swap-proposal
{:clean-approval-transaction? clean-approval-transaction?}])))
{:clean-amounts? true
:clean-approval-transaction? clean-approval-transaction?}])))
(defn- data-item
[{:keys [title subtitle size subtitle-icon subtitle-color on-press loading?]}]
@ -90,47 +92,31 @@
[{:keys [input-state on-max-press on-input-focus on-token-press on-approve-press input-focused?]}]
(let [account-color (rf/sub [:wallet/current-viewing-account-color])
network (rf/sub [:wallet/swap-network])
pay-token-symbol (:symbol (rf/sub [:wallet/swap-asset-to-pay]))
currency (rf/sub [:profile/currency])
pay-token-symbol (rf/sub [:wallet/swap-asset-to-pay-symbol])
pay-token-decimals (rf/sub [:wallet/swap-asset-to-pay-decimals])
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
approval-required (rf/sub [:wallet/swap-proposal-approval-required])
approval-amount-required (rf/sub [:wallet/swap-proposal-approval-amount-required])
currency-symbol (rf/sub [:profile/currency-symbol])
approval-transaction-status (rf/sub [:wallet/swap-approval-transaction-status])
approval-transaction-id (rf/sub [:wallet/swap-approval-transaction-id])
approved-amount (rf/sub [:wallet/swap-approved-amount])
error-response (rf/sub [:wallet/swap-error-response])
asset-to-pay (rf/sub [:wallet/token-by-symbol
(or pay-token-symbol default-token-symbol)])
overlay-shown? (boolean (:sheets (rf/sub [:bottom-sheet])))
input-ref (rn/use-ref-atom nil)
set-input-ref (rn/use-callback (fn [ref] (reset! input-ref ref)))
pay-input-num-value (controlled-input/value-numeric input-state)
pay-input-amount (controlled-input/input-value input-state)
pay-token-decimals (:decimals asset-to-pay)
pay-token-balance-selected-chain (number/convert-to-whole-number
(get-in asset-to-pay
[:balances-per-chain
(:chain-id network) :raw-balance]
0)
pay-token-decimals)
pay-token-fiat-value (utils/formatted-token-fiat-value
{:currency currency
:currency-symbol currency-symbol
:balance (or pay-input-num-value 0)
:token asset-to-pay})
pay-token-balance-selected-chain (rf/sub [:wallet/swap-asset-to-pay-balance-for-chain
(:chain-id network)])
pay-token-fiat-value (rf/sub [:wallet/swap-asset-to-pay-amount-in-fiat
pay-input-num-value])
available-crypto-limit (money/bignumber
pay-token-balance-selected-chain)
display-decimals (min pay-token-decimals
constants/min-token-decimals-to-display)
available-crypto-limit-display (number/remove-trailing-zeroes
(.toFixed available-crypto-limit display-decimals))
available-crypto-limit-display (if (and (= available-crypto-limit-display "0")
(money/greater-than available-crypto-limit
(money/bignumber 0)))
(number/small-number-threshold display-decimals)
available-crypto-limit-display)
available-crypto-limit-display (rf/sub [:wallet/swap-asset-to-pay-balance-for-chain-ui
(:chain-id network)])
approval-amount-required-num (when approval-amount-required
(number/to-fixed (number/hex->whole
approval-amount-required
@ -345,15 +331,12 @@
asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
asset-to-receive (rf/sub [:wallet/swap-asset-to-receive])
network (rf/sub [:wallet/swap-network])
pay-token-balance-selected-chain (rf/sub [:wallet/swap-asset-to-pay-balance-for-chain
(:chain-id network)])
start-point (rf/sub [:wallet/swap-start-point])
current-account-address (rf/sub [:wallet/current-viewing-account-address])
pay-input-amount (controlled-input/input-value pay-input-state)
pay-token-decimals (:decimals asset-to-pay)
pay-token-balance-selected-chain (number/convert-to-whole-number
(get-in asset-to-pay
[:balances-per-chain
(:chain-id network) :raw-balance]
0)
pay-token-decimals)
pay-input-error? (and (not (string/blank? pay-input-amount))
(money/greater-than
(money/bignumber pay-input-amount)
@ -392,7 +375,8 @@
(set-pay-input-state
controlled-input/delete-last)
(rf/dispatch [:wallet/clean-swap-proposal
{:clean-approval-transaction?
{:clean-amounts? true
:clean-approval-transaction?
true}])))
on-max-press (rn/use-callback
(fn [max-value]
@ -443,8 +427,19 @@
on-refresh-swap-proposal
constants/swap-proposal-refresh-interval-ms))))
[swap-proposal error-response])
(rn/use-effect (fn []
(rf/dispatch [:wallet/clean-swap-proposal
{:clean-amounts? false
:clean-approval-transaction? true}])
(when @refetch-interval
(js/clearInterval @refetch-interval)
(reset! refetch-interval nil))
(refetch-swap-proposal))
[current-account-address])
(rn/use-unmount (fn []
(rf/dispatch [:wallet/clean-swap-proposal {:clean-approval-transaction? true}])
(rf/dispatch [:wallet/clean-swap-proposal
{:clean-amounts? true
:clean-approval-transaction? true}])
(when @refetch-interval
(js/clearInterval @refetch-interval)
(reset! refetch-interval nil))))

View File

@ -17,6 +17,16 @@
:<- [:wallet/swap]
:-> :asset-to-pay)
(rf/reg-sub
:wallet/swap-asset-to-pay-decimals
:<- [:wallet/swap-asset-to-pay]
:-> :decimals)
(rf/reg-sub
:wallet/swap-asset-to-pay-symbol
:<- [:wallet/swap-asset-to-pay]
:-> :symbol)
(rf/reg-sub
:wallet/swap-asset-to-receive
:<- [:wallet/swap]
@ -253,3 +263,42 @@
currency-symbol
fee-in-fiat)]
fee-formatted))))
(rf/reg-sub
:wallet/swap-asset-to-pay-balance-for-chain-data
:<- [:wallet/swap-asset-to-pay]
(fn [asset-to-pay]
(let [token-symbol (or (:symbol asset-to-pay) constants/token-for-fees-symbol)]
@(rf/subscribe [:wallet/token-by-symbol token-symbol]))))
(rf/reg-sub
:wallet/swap-asset-to-pay-balance-for-chain
:<- [:wallet/swap-asset-to-pay-balance-for-chain-data]
(fn [asset-to-pay-with-current-account-balance [_ chain-id]]
(let [pay-token-decimals (:decimals asset-to-pay-with-current-account-balance)
pay-token-balance-selected-chain (-> (get-in asset-to-pay-with-current-account-balance
[:balances-per-chain chain-id :raw-balance]
0)
(number/convert-to-whole-number pay-token-decimals))]
pay-token-balance-selected-chain)))
(rf/reg-sub
:wallet/swap-asset-to-pay-balance-for-chain-ui
:<- [:wallet/swap-asset-to-pay-balance-for-chain-data]
(fn [asset-to-pay-with-current-account-balance [_ chain-id]]
(utils/token-balance-display-for-network
asset-to-pay-with-current-account-balance
chain-id
constants/min-token-decimals-to-display)))
(rf/reg-sub
:wallet/swap-asset-to-pay-amount-in-fiat
:<- [:wallet/swap-asset-to-pay-balance-for-chain-data]
:<- [:profile/currency]
:<- [:profile/currency-symbol]
(fn [[asset-to-pay-with-current-account-balance currency currency-symbol] [_ amount]]
(utils/formatted-token-fiat-value
{:currency currency
:currency-symbol currency-symbol
:balance (or amount 0)
:token asset-to-pay-with-current-account-balance})))