feat: implement proper error handling for swaps (#21261)
Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
parent
604ee33c52
commit
9258f2a513
|
@ -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])
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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})
|
||||
|
||||
|
|
|
@ -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]]]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 []
|
||||
|
|
|
@ -37,4 +37,6 @@
|
|||
:justify-content :flex-end})
|
||||
|
||||
(def alert-banner
|
||||
{:height 40})
|
||||
{:height :auto
|
||||
:min-height 40
|
||||
:max-height 62})
|
||||
|
|
|
@ -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}]]
|
||||
|
|
|
@ -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)))
|
|
@ -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]
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue