From 9258f2a513f3fc97668b4ee08a997106e8c32050 Mon Sep 17 00:00:00 2001 From: Brian Sztamfater Date: Tue, 24 Sep 2024 11:44:35 -0300 Subject: [PATCH] feat: implement proper error handling for swaps (#21261) Signed-off-by: Brian Sztamfater --- .../banners/alert_banner/schema.cljs | 1 + .../banners/alert_banner/style.cljs | 14 ++- .../components/banners/alert_banner/view.cljs | 22 +++-- src/quo/components/buttons/button/view.cljs | 2 +- .../components/settings/data_item/style.cljs | 13 +-- .../components/settings/data_item/view.cljs | 9 +- .../common/controlled_input/utils.cljs | 19 ++-- src/status_im/constants.cljs | 7 ++ .../wallet/sheets/buy_token/view.cljs | 4 +- .../contexts/wallet/swap/events.cljs | 16 +--- .../wallet/swap/setup_swap/style.cljs | 4 +- .../contexts/wallet/swap/setup_swap/view.cljs | 95 ++++++++++++++----- src/status_im/contexts/wallet/swap/utils.cljs | 29 ++++++ src/status_im/subs/wallet/swap.cljs | 10 ++ src/utils/string.cljs | 2 +- translations/en.json | 9 +- 16 files changed, 181 insertions(+), 75 deletions(-) create mode 100644 src/status_im/contexts/wallet/swap/utils.cljs diff --git a/src/quo/components/banners/alert_banner/schema.cljs b/src/quo/components/banners/alert_banner/schema.cljs index 8885cf517e..4e9e3414f4 100644 --- a/src/quo/components/banners/alert_banner/schema.cljs +++ b/src/quo/components/banners/alert_banner/schema.cljs @@ -9,5 +9,6 @@ [:text {:optional true} [:maybe string?]] [:container-style {:optional true} [:maybe :map]] [:button-text {:optional true} [:maybe string?]] + [:text-number-of-lines {:optional true} [:maybe number?]] [:on-button-press {:optional true} [:maybe fn?]]]]] :any]) diff --git a/src/quo/components/banners/alert_banner/style.cljs b/src/quo/components/banners/alert_banner/style.cljs index fe8fcbdcd0..f6037f9408 100644 --- a/src/quo/components/banners/alert_banner/style.cljs +++ b/src/quo/components/banners/alert_banner/style.cljs @@ -11,11 +11,19 @@ :padding-vertical 12} container-style)) +(def content-container + {:flex 1 + :flex-direction :row}) + (defn label [theme] - {:flex 1 - :color (colors/resolve-color :danger theme) - :margin-horizontal 4}) + {:color (colors/resolve-color :danger theme) + :margin-horizontal 4 + :flex 1 + :flex-wrap :wrap}) (def button-text {:color colors/white}) + +(def icon + {:margin-top 2}) diff --git a/src/quo/components/banners/alert_banner/view.cljs b/src/quo/components/banners/alert_banner/view.cljs index bdb0d66ac6..9f8f15da76 100644 --- a/src/quo/components/banners/alert_banner/view.cljs +++ b/src/quo/components/banners/alert_banner/view.cljs @@ -11,7 +11,7 @@ [schema.core :as schema])) (defn- view-internal - [{:keys [action? text button-text container-style on-button-press]}] + [{:keys [action? text button-text text-number-of-lines container-style on-button-press]}] (let [theme (quo.theme/use-theme)] [rn/view {:accessibility-label :alert-banner} @@ -24,15 +24,17 @@ colors/danger-50-opa-10 theme) colors/danger-50-opa-0]} - [icon/icon - :i/alert - {:color (colors/resolve-color :danger theme) - :size 16}] - [text/text - {:style (style/label theme) - :size :paragraph-2 - :number-of-lines 1} - text] + [rn/view {:style style/content-container} + [icon/icon + :i/alert + {:color (colors/resolve-color :danger theme) + :size 16 + :container-style style/icon}] + [text/text + {:style (style/label theme) + :size :paragraph-2 + :number-of-lines (or text-number-of-lines 1)} + text]] (when action? [button/button {:accessibility-label :button diff --git a/src/quo/components/buttons/button/view.cljs b/src/quo/components/buttons/button/view.cljs index 142563f5e6..3d2c83b7ba 100644 --- a/src/quo/components/buttons/button/view.cljs +++ b/src/quo/components/buttons/button/view.cljs @@ -55,7 +55,7 @@ (set-pressed-state nil) (when on-press-out (on-press-out))))] [rn/touchable-without-feedback - {:disabled disabled? + {:disabled (boolean disabled?) :accessibility-label accessibility-label :on-press-in on-press-in-cb :on-press-out on-press-out-cb diff --git a/src/quo/components/settings/data_item/style.cljs b/src/quo/components/settings/data_item/style.cljs index 007f1b785d..dcd3e6d4fe 100644 --- a/src/quo/components/settings/data_item/style.cljs +++ b/src/quo/components/settings/data_item/style.cljs @@ -84,12 +84,13 @@ :height 16}) (defn description - [blur? theme] - {:color (if blur? - colors/white - (colors/theme-colors colors/neutral-100 - colors/white - theme))}) + [subtitle-color blur? theme] + {:color (or subtitle-color + (if blur? + colors/white + (colors/theme-colors colors/neutral-100 + colors/white + theme)))}) (def right-icon {:margin-left 12}) diff --git a/src/quo/components/settings/data_item/view.cljs b/src/quo/components/settings/data_item/view.cljs index 4a7ccf122c..edb5018aba 100644 --- a/src/quo/components/settings/data_item/view.cljs +++ b/src/quo/components/settings/data_item/view.cljs @@ -16,7 +16,8 @@ [rn/view {:style (style/loading-container size blur? theme)}])) (defn- left-subtitle - [{:keys [size subtitle-type icon icon-color blur? subtitle customization-color emoji network-image] + [{:keys [size subtitle-type subtitle-color icon icon-color blur? subtitle customization-color emoji + network-image] :or {subtitle-type :default}}] (let [theme (quo.theme/use-theme)] [rn/view {:style style/subtitle-container} @@ -40,7 +41,7 @@ [text/text {:weight :medium :size :paragraph-2 - :style (style/description blur? theme)} + :style (style/description subtitle-color blur? theme)} subtitle] (when (= subtitle-type :editable) [icons/icon :i/edit @@ -65,7 +66,7 @@ (defn- left-side "The description can either be given as a string `subtitle-type` or a component `custom-subtitle`" - [{:keys [title status size blur? custom-subtitle icon subtitle subtitle-type icon-color + [{:keys [title status size blur? custom-subtitle icon subtitle subtitle-type subtitle-color icon-color customization-color network-image emoji] :as props}] (let [theme (quo.theme/use-theme)] @@ -85,6 +86,7 @@ {:theme theme :size size :subtitle-type subtitle-type + :subtitle-color subtitle-color :icon icon :icon-color icon-color :blur? blur? @@ -124,6 +126,7 @@ [:icon-color {:optional true} [:maybe :schema.common/customization-color]] [:status {:optional true} [:maybe [:enum :default :loading]]] [:subtitle-type {:optional true} [:maybe [:enum :default :icon :network :account :editable]]] + [:subtitle-color {:optional true} [:maybe :schema.common/customization-color]] [:size {:optional true} [:maybe [:enum :default :small :large]]] [:title :string] [:subtitle {:optional true} [:maybe [:or :string :double]]] diff --git a/src/status_im/common/controlled_input/utils.cljs b/src/status_im/common/controlled_input/utils.cljs index fefd37f848..46ceca980f 100644 --- a/src/status_im/common/controlled_input/utils.cljs +++ b/src/status_im/common/controlled_input/utils.cljs @@ -4,6 +4,8 @@ [status-im.contexts.wallet.common.utils :as wallet-utils] [utils.money :as money])) +(def ^:private default-max-limit 12) + (def init-state {:value "" :error? false @@ -101,9 +103,8 @@ (def ^:private dot ".") (defn- can-add-character? - [state character] - (let [max-length 12 - current (input-value state) + [state character max-length] + (let [current (input-value state) length-overflow? (>= (count current) max-length) extra-dot? (and (= character dot) (string/includes? current dot)) extra-leading-zero? (and (= current "0") (= "0" (str character))) @@ -123,11 +124,13 @@ (str value character))) (defn add-character - [state character] - (if (can-add-character? state character) - (set-input-value state - (normalize-value-as-numeric (input-value state) character)) - state)) + ([state character] + (add-character state character default-max-limit)) + ([state character max-length] + (if (can-add-character? state character max-length) + (set-input-value state + (normalize-value-as-numeric (input-value state) character)) + state))) (defn delete-last ([state] diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index 37462b9532..003b604cfd 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -609,3 +609,10 @@ (def ^:const min-token-decimals-to-display 6) (def ^:const swap-proposal-refresh-interval-ms 15000) + +(def router-error-code-generic "0") +(def router-error-code-paraswap-custom-error "WPP-030") +(def router-error-code-price-timeout "WPP-037") +(def router-error-code-not-enough-liquidity "WPP-038") +(def router-error-code-price-impact-too-high "WPP-039") +(def router-error-code-not-enough-native-balance "WR-002") diff --git a/src/status_im/contexts/wallet/sheets/buy_token/view.cljs b/src/status_im/contexts/wallet/sheets/buy_token/view.cljs index b5d00f1694..af17d797d8 100644 --- a/src/status_im/contexts/wallet/sheets/buy_token/view.cljs +++ b/src/status_im/contexts/wallet/sheets/buy_token/view.cljs @@ -35,7 +35,7 @@ (def ^:private initial-tab (:id (first tabs))) (defn view - [] + [{:keys [title]}] (rn/use-mount (fn [] (rf/dispatch [:wallet/get-crypto-on-ramps]))) (let [crypto-on-ramps (rf/sub [:wallet/crypto-on-ramps]) @@ -45,7 +45,7 @@ #(set-min-height (oops/oget % :nativeEvent :layout :height)))] [:<> - [quo/drawer-top {:title (i18n/label :t/buy-assets)}] + [quo/drawer-top {:title (or title (i18n/label :t/buy-assets))}] [quo/segmented-control {:size 32 :container-style style/tabs diff --git a/src/status_im/contexts/wallet/swap/events.cljs b/src/status_im/contexts/wallet/swap/events.cljs index 4ecd1593d3..94f017d0ac 100644 --- a/src/status_im/contexts/wallet/swap/events.cljs +++ b/src/status_im/contexts/wallet/swap/events.cljs @@ -134,15 +134,8 @@ assoc :swap-proposal (when-not (empty? best-routes) (assoc (first best-routes) :uuid request-uuid)) - :error-response (when (empty? best-routes) error-response) + :error-response error-response :loading-swap-proposal? false)} - (empty? best-routes) - (assoc :fx - [[:dispatch - [:toasts/upsert - {:id :swap-proposal-error - :type :negative - :text error-response}]]]) ;; Router is unstable and it can return a swap proposal and after auto-refetching it can ;; return an error. Ideally this shouldn't happen, but adding this behavior so if the ;; user is in swap confirmation screen or in token approval confirmation screen, we @@ -157,12 +150,7 @@ {:db (-> db (update-in [:wallet :ui :swap] dissoc :route :swap-proposal) (assoc-in [:wallet :ui :swap :loading-swap-proposal?] false) - (assoc-in [:wallet :ui :swap :error-response] error-message)) - :fx [[:dispatch - [:toasts/upsert - {:id :swap-proposal-error - :type :negative - :text error-message}]]]})) + (assoc-in [:wallet :ui :swap :error-response] error-message))})) (rf/reg-event-fx :wallet/stop-get-swap-proposal (fn [] diff --git a/src/status_im/contexts/wallet/swap/setup_swap/style.cljs b/src/status_im/contexts/wallet/swap/setup_swap/style.cljs index 84b02717c6..06b8fe3773 100644 --- a/src/status_im/contexts/wallet/swap/setup_swap/style.cljs +++ b/src/status_im/contexts/wallet/swap/setup_swap/style.cljs @@ -37,4 +37,6 @@ :justify-content :flex-end}) (def alert-banner - {:height 40}) + {:height :auto + :min-height 40 + :max-height 62}) diff --git a/src/status_im/contexts/wallet/swap/setup_swap/view.cljs b/src/status_im/contexts/wallet/swap/setup_swap/view.cljs index 2208ad371c..0c5b76d431 100644 --- a/src/status_im/contexts/wallet/swap/setup_swap/view.cljs +++ b/src/status_im/contexts/wallet/swap/setup_swap/view.cljs @@ -1,6 +1,8 @@ (ns status-im.contexts.wallet.swap.setup-swap.view (:require [clojure.string :as string] [quo.core :as quo] + [quo.foundations.colors :as colors] + [quo.theme :as quo.theme] [react-native.core :as rn] [react-native.platform :as platform] [react-native.safe-area :as safe-area] @@ -9,7 +11,9 @@ [status-im.constants :as constants] [status-im.contexts.wallet.common.account-switcher.view :as account-switcher] [status-im.contexts.wallet.common.utils :as utils] + [status-im.contexts.wallet.sheets.buy-token.view :as buy-token] [status-im.contexts.wallet.swap.setup-swap.style :as style] + [status-im.contexts.wallet.swap.utils :as swap-utils] [utils.debounce :as debounce] [utils.i18n :as i18n] [utils.money :as money] @@ -35,7 +39,7 @@ {:clean-approval-transaction? clean-approval-transaction?}]))) (defn- data-item - [{:keys [title subtitle size subtitle-icon loading?]}] + [{:keys [title subtitle size subtitle-icon subtitle-color loading?]}] [quo/data-item {:container-style style/detail-item :blur? false @@ -45,20 +49,27 @@ :title title :subtitle subtitle :size size - :icon subtitle-icon}]) + :icon subtitle-icon + :subtitle-color subtitle-color}]) (defn- transaction-details [] - (let [max-fees (rf/sub [:wallet/wallet-swap-proposal-fee-fiat-formatted + (let [theme (quo.theme/use-theme) + max-fees (rf/sub [:wallet/wallet-swap-proposal-fee-fiat-formatted constants/token-for-fees-symbol]) max-slippage (rf/sub [:wallet/swap-max-slippage]) - loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])] + loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?]) + error-response (rf/sub [:wallet/swap-error-response])] [rn/view {:style style/details-container} [data-item - {:title (i18n/label :t/max-fees) - :subtitle max-fees - :loading? loading-swap-proposal? - :size :small}] + (cond-> {:title (i18n/label :t/max-fees) + :subtitle max-fees + :loading? loading-swap-proposal? + :size :small} + error-response (assoc :subtitle-color + (colors/theme-colors colors/danger-50 + colors/danger-60 + theme)))] [data-item {:title (i18n/label :t/max-slippage) :subtitle max-slippage @@ -79,6 +90,7 @@ 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]) pay-input-num-value (controlled-input/value-numeric input-state) pay-input-amount (controlled-input/input-value input-state) pay-token-symbol (:symbol asset-to-pay) @@ -92,9 +104,10 @@ {:currency currency :balance (or pay-input-num-value 0) :token asset-to-pay})) - available-crypto-limit (number/remove-trailing-zeroes - (.toFixed (money/bignumber - pay-token-balance-selected-chain) + available-crypto-limit (money/bignumber + pay-token-balance-selected-chain) + available-crypto-limit-display (number/remove-trailing-zeroes + (.toFixed available-crypto-limit (min pay-token-decimals constants/min-token-decimals-to-display))) approval-amount-required-num (when approval-amount-required @@ -102,11 +115,10 @@ pay-token-decimals))) pay-input-error? (or (and (not (string/blank? pay-input-amount)) (money/greater-than - (money/bignumber pay-input-num-value) - (money/bignumber - pay-token-balance-selected-chain))) + (money/bignumber pay-input-amount) + available-crypto-limit)) (money/equal-to (money/bignumber - available-crypto-limit) + available-crypto-limit-display) (money/bignumber 0))) valid-pay-input? (and (not (string/blank? @@ -139,12 +151,12 @@ :else :disabled) :currency-symbol currency-symbol :on-token-press on-token-press - :on-max-press #(on-max-press available-crypto-limit) + :on-max-press #(on-max-press (str available-crypto-limit)) :on-input-focus on-input-focus :value pay-input-amount :fiat-value pay-token-fiat-value :network-tag-props {:title (i18n/label :t/max-token - {:number available-crypto-limit + {:number available-crypto-limit-display :token-symbol pay-token-symbol}) :networks [{:source (:source network)}]} :approval-label-props {:status (case approval-transaction-status @@ -153,7 +165,9 @@ :finalised :approved :approve) :token-value (or approval-amount-required-num approved-amount) - :button-props {:on-press on-approve-press} + :button-props (merge {:on-press on-approve-press} + (when error-response + {:disabled? true})) :customization-color account-color :token-symbol pay-token-symbol}}])) @@ -204,10 +218,41 @@ :fiat-value receive-token-fiat-value :container-style (style/receive-token-swap-input-container approval-required?)}])) +(defn- alert-banner + [{:keys [pay-input-error?]}] + (let [error-response (rf/sub [:wallet/swap-error-response]) + error-response-code (rf/sub [:wallet/swap-error-response-code]) + error-response-details (rf/sub [:wallet/swap-error-response-details]) + error-text (if pay-input-error? + (i18n/label :t/insufficient-funds-for-swaps) + (swap-utils/error-message-from-code error-response-code + error-response-details)) + props (cond-> {:container-style style/alert-banner + :text-number-of-lines 0 + :text error-text} + pay-input-error? + (merge {:action? true + :on-button-press #(rf/dispatch [:show-bottom-sheet + {:content buy-token/view}]) + :button-text (i18n/label :t/buy-assets)}) + (= error-response-code + constants/router-error-code-not-enough-native-balance) + (merge {:action? true + :on-button-press #(rf/dispatch + [:show-bottom-sheet + {:content (fn [] + [buy-token/view + {:title (i18n/label + :t/buy-ethereum)}])}]) + :button-text (i18n/label :t/buy-eth)}))] + (when (or pay-input-error? error-response) + [quo/alert-banner props]))) + (defn- action-button [{:keys [on-press]}] (let [account-color (rf/sub [:wallet/current-viewing-account-color]) swap-proposal (rf/sub [:wallet/swap-proposal-without-fees]) + error-response (rf/sub [:wallet/swap-error-response]) loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?]) approval-required? (rf/sub [:wallet/swap-proposal-approval-required]) approval-transaction-status (rf/sub [:wallet/swap-approval-transaction-status])] @@ -215,6 +260,7 @@ {:actions :one-action :button-one-label (i18n/label :t/review-swap) :button-one-props {:disabled? (or (not swap-proposal) + error-response (and approval-required? (not= approval-transaction-status :confirmed)) loading-swap-proposal?) @@ -233,14 +279,13 @@ network (rf/sub [:wallet/swap-network]) pay-input-amount (controlled-input/input-value pay-input-state) pay-token-decimals (:decimals asset-to-pay) - pay-input-num-value (controlled-input/value-numeric pay-input-state) pay-token-balance-selected-chain (get-in asset-to-pay [:balances-per-chain (:chain-id network) :balance] 0) pay-input-error? (and (not (string/blank? pay-input-amount)) (money/greater-than - (money/bignumber pay-input-num-value) + (money/bignumber pay-input-amount) (money/bignumber pay-token-balance-selected-chain))) valid-pay-input? (and @@ -263,7 +308,10 @@ new-text)] (when valid-amount? (set-pay-input-state - #(controlled-input/add-character % c)))))) + #(controlled-input/add-character % + c + ##Inf))))) + [pay-input-amount pay-token-decimals]) on-long-press (rn/use-callback (fn [] (set-pay-input-state controlled-input/delete-all) @@ -371,10 +419,7 @@ :on-token-press #(js/alert "Token Pressed") :on-input-focus #(set-pay-input-focused? false)}]] [rn/view {:style style/footer-container} - (when error-response - [quo/alert-banner - {:container-style style/alert-banner - :text (i18n/label :t/something-went-wrong-please-try-again-later)}]) + [alert-banner {:pay-input-error? pay-input-error?}] (when (or loading-swap-proposal? swap-proposal) [transaction-details]) [action-button {:on-press on-review-swap-press}]] diff --git a/src/status_im/contexts/wallet/swap/utils.cljs b/src/status_im/contexts/wallet/swap/utils.cljs new file mode 100644 index 0000000000..21be39d191 --- /dev/null +++ b/src/status_im/contexts/wallet/swap/utils.cljs @@ -0,0 +1,29 @@ +(ns status-im.contexts.wallet.swap.utils + (:require [status-im.constants :as constants] + [utils.i18n :as i18n])) + +(defn error-message-from-code + [error-code error-details] + (cond + (= error-code + constants/router-error-code-not-enough-liquidity) + (i18n/label :t/not-enough-liquidity) + (= error-code + constants/router-error-code-price-timeout) + (i18n/label :t/fetching-the-price-took-longer-than-expected) + (= error-code + constants/router-error-code-price-impact-too-high) + (i18n/label :t/price-impact-too-high) + (= error-code + constants/router-error-code-paraswap-custom-error) + (i18n/label :t/paraswap-error + {:paraswap-error error-details}) + (= error-code + constants/router-error-code-generic) + (i18n/label :t/generic-error + {:generic-error error-details}) + (= error-code + constants/router-error-code-not-enough-native-balance) + (i18n/label :t/not-enough-assets-to-pay-gas-fees) + :else + (i18n/label :t/something-went-wrong-please-try-again-later))) diff --git a/src/status_im/subs/wallet/swap.cljs b/src/status_im/subs/wallet/swap.cljs index 27a538d08f..5979606428 100644 --- a/src/status_im/subs/wallet/swap.cljs +++ b/src/status_im/subs/wallet/swap.cljs @@ -32,6 +32,16 @@ :<- [:wallet/swap] :-> :error-response) +(rf/reg-sub + :wallet/swap-error-response-code + :<- [:wallet/swap-error-response] + :-> :code) + +(rf/reg-sub + :wallet/swap-error-response-details + :<- [:wallet/swap-error-response] + :-> :details) + (rf/reg-sub :wallet/swap-asset-to-pay-token-symbol :<- [:wallet/swap-asset-to-pay] diff --git a/src/utils/string.cljs b/src/utils/string.cljs index d1836b86ff..ccef67856e 100644 --- a/src/utils/string.cljs +++ b/src/utils/string.cljs @@ -93,4 +93,4 @@ [token-decimals amount-text] (let [regex-pattern (str "^\\d*\\.?\\d{0," token-decimals "}$") regex (re-pattern regex-pattern)] - (re-matches regex amount-text))) + (boolean (re-matches regex amount-text)))) diff --git a/translations/en.json b/translations/en.json index 87c644430e..906eabc4fb 100644 --- a/translations/en.json +++ b/translations/en.json @@ -273,6 +273,7 @@ "buy-crypto-leaving": "You are leaving Status and entering a third party website to complete your purchase", "buy-crypto-title": "Looks like your wallet is empty", "buy-eth": "Buy ETH", + "buy-ethereum": "Buy Ethereum", "by-continuing-you-accept": "By continuing you accept our ", "camera-access-error": "To grant the required camera permission, please go to your system settings and make sure that Status > Camera is selected.", "camera-permission-denied": "Permission denied", @@ -1019,6 +1020,7 @@ "fetch-messages": "Fetch messages", "fetch-timeline": "↓ Fetch", "fetching-community": "Fetching community...", + "fetching-the-price-took-longer-than-expected": "Fetching the price took longer than expected.\nPlease, try again later.", "finalized-on": "Finalized on", "find": "Find", "find-it-in-setting": "Find it in Settings on your other synced device", @@ -1069,6 +1071,7 @@ "generating-keypair": "Generating key pair...", "generating-keys": "Generating keys...", "generating-mnemonic": "Generating seed phrase", + "generic-error": "Error: {{generic-error}}", "get-a-keycard": "Get a Keycard", "get-started": "Get started", "get-status-at": "Get Status at http://status.im", @@ -1183,6 +1186,7 @@ "install": "↓ Install", "instruction-after-qr-generated": "On your other device, navigate to the Syncing screen and select “Scan sync”", "insufficient-balance-to-cover-fee": "not enough balance to cover transaction fee", + "insufficient-funds-for-swaps": "Insufficient funds for swap", "intro-message1": "Welcome to Status!\nTap this message to set your password and get started.", "intro-privacy-policy": "Privacy Policy", "intro-privacy-policy-note1": "Status does not collect or profit from your personal data. By continuing, you agree with the ", @@ -1734,6 +1738,7 @@ "not-connected-to-peers": "Not connected to any peers", "not-enough-assets": "Not enough assets to complete transaction", "not-enough-assets-to-pay-gas-fees": "Not enough assets to pay gas fees", + "not-enough-liquidity": "Not enough liquidity. Lower token amount or try again later.", "not-enough-snt": "Not enough SNT", "not-found": "Not found", "not-keycard-text": "The card you used is not a Keycard. You need to purchase a Keycard to use it", @@ -1848,6 +1853,7 @@ "pairing-new-installation-detected-title": "New device detected", "pairing-no-info": "No info", "pairing-please-set-a-name": "Please set a name for your device.", + "paraswap-error": "Paraswap error: {{paraswap-error}}", "participate-in-the-metaverse": "Participate in the truly free metaverse", "passphrase": "Passphrase", "password": "Password", @@ -1934,6 +1940,7 @@ "previewing-may-share-metadata": "Previewing links from these websites may share your metadata with their owners", "price-impact": "Price impact", "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.", + "price-impact-too-high": "Price impact too high. Lower token amount or try again later.", "principles": "Principles", "priority": "Priority", "privacy": "Privacy", @@ -2320,7 +2327,7 @@ "slow": "Slow", "something-about-you": "Something about you", "something-went-wrong": "Something went wrong", - "something-went-wrong-please-try-again-later": "Something went wrong, please try again later", + "something-went-wrong-please-try-again-later": "Something went wrong. Modify swap parameters or try again later.", "soon": "Soon", "sort-communities": "Sort communities", "special-characters": "Special characters",