@ton/appkit-react 1.0.0-alpha.1 → 1.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/esm/components/shared/amount-preview/amount-preview.js +17 -0
  2. package/dist/esm/components/shared/amount-preview/amount-preview.js.map +1 -0
  3. package/dist/esm/components/shared/amount-preview/amount-preview.module.css +40 -0
  4. package/dist/esm/components/shared/amount-preview/index.js +9 -0
  5. package/dist/esm/components/shared/amount-preview/index.js.map +1 -0
  6. package/dist/esm/components/shared/flow-preview/flow-preview.js +24 -0
  7. package/dist/esm/components/shared/flow-preview/flow-preview.js.map +1 -0
  8. package/dist/esm/components/shared/flow-preview/flow-preview.module.css +37 -0
  9. package/dist/esm/components/shared/flow-preview/index.js +9 -0
  10. package/dist/esm/components/shared/flow-preview/index.js.map +1 -0
  11. package/dist/esm/components/ui/logo/logo.module.css +1 -3
  12. package/dist/esm/features/staking/components/staking-confirm-modal/index.js +9 -0
  13. package/dist/esm/features/staking/components/staking-confirm-modal/index.js.map +1 -0
  14. package/dist/esm/features/staking/components/staking-confirm-modal/staking-confirm-modal.js +46 -0
  15. package/dist/esm/features/staking/components/staking-confirm-modal/staking-confirm-modal.js.map +1 -0
  16. package/dist/esm/features/staking/components/staking-confirm-modal/staking-confirm-modal.module.css +11 -0
  17. package/dist/esm/features/staking/components/staking-widget-provider/staking-widget-provider.js +27 -4
  18. package/dist/esm/features/staking/components/staking-widget-provider/staking-widget-provider.js.map +1 -1
  19. package/dist/esm/features/staking/components/staking-widget-provider/use-staking-validation.js +12 -3
  20. package/dist/esm/features/staking/components/staking-widget-provider/use-staking-validation.js.map +1 -1
  21. package/dist/esm/features/staking/components/staking-widget-ui/staking-widget-ui.js +16 -4
  22. package/dist/esm/features/staking/components/staking-widget-ui/staking-widget-ui.js.map +1 -1
  23. package/dist/esm/features/staking/hooks/use-build-stake-transaction.js +2 -2
  24. package/dist/esm/features/staking/hooks/use-build-stake-transaction.js.map +1 -1
  25. package/dist/esm/features/staking/utils/map-staking-error.js +6 -4
  26. package/dist/esm/features/staking/utils/map-staking-error.js.map +1 -1
  27. package/dist/esm/features/swap/components/swap-confirm-modal/index.js +9 -0
  28. package/dist/esm/features/swap/components/swap-confirm-modal/index.js.map +1 -0
  29. package/dist/esm/features/swap/components/swap-confirm-modal/swap-confirm-modal.js +12 -0
  30. package/dist/esm/features/swap/components/swap-confirm-modal/swap-confirm-modal.js.map +1 -0
  31. package/dist/esm/features/swap/components/swap-confirm-modal/swap-confirm-modal.module.css +7 -0
  32. package/dist/esm/features/swap/components/swap-widget-provider/swap-widget-provider.js +28 -6
  33. package/dist/esm/features/swap/components/swap-widget-provider/swap-widget-provider.js.map +1 -1
  34. package/dist/esm/features/swap/components/swap-widget-provider/use-swap-validation.js +12 -3
  35. package/dist/esm/features/swap/components/swap-widget-provider/use-swap-validation.js.map +1 -1
  36. package/dist/esm/features/swap/components/swap-widget-ui/swap-widget-ui.js +16 -4
  37. package/dist/esm/features/swap/components/swap-widget-ui/swap-widget-ui.js.map +1 -1
  38. package/dist/esm/features/swap/utils/map-swap-error.js +5 -3
  39. package/dist/esm/features/swap/utils/map-swap-error.js.map +1 -1
  40. package/dist/esm/locales/en.js +9 -0
  41. package/dist/esm/locales/en.js.map +1 -1
  42. package/dist/esm/styles/index.css +2 -2
  43. package/dist/types/components/shared/amount-preview/amount-preview.d.ts +24 -0
  44. package/dist/types/components/shared/amount-preview/amount-preview.d.ts.map +1 -0
  45. package/dist/types/components/shared/amount-preview/index.d.ts +9 -0
  46. package/dist/types/components/shared/amount-preview/index.d.ts.map +1 -0
  47. package/dist/types/components/shared/flow-preview/flow-preview.d.ts +18 -0
  48. package/dist/types/components/shared/flow-preview/flow-preview.d.ts.map +1 -0
  49. package/dist/types/components/shared/flow-preview/index.d.ts +9 -0
  50. package/dist/types/components/shared/flow-preview/index.d.ts.map +1 -0
  51. package/dist/types/features/staking/components/staking-confirm-modal/index.d.ts +9 -0
  52. package/dist/types/features/staking/components/staking-confirm-modal/index.d.ts.map +1 -0
  53. package/dist/types/features/staking/components/staking-confirm-modal/staking-confirm-modal.d.ts +23 -0
  54. package/dist/types/features/staking/components/staking-confirm-modal/staking-confirm-modal.d.ts.map +1 -0
  55. package/dist/types/features/staking/components/staking-widget-provider/staking-widget-provider.d.ts.map +1 -1
  56. package/dist/types/features/staking/components/staking-widget-provider/use-staking-validation.d.ts +3 -1
  57. package/dist/types/features/staking/components/staking-widget-provider/use-staking-validation.d.ts.map +1 -1
  58. package/dist/types/features/staking/components/staking-widget-ui/staking-widget-ui.d.ts.map +1 -1
  59. package/dist/types/features/staking/hooks/use-build-stake-transaction.d.ts +3 -2
  60. package/dist/types/features/staking/hooks/use-build-stake-transaction.d.ts.map +1 -1
  61. package/dist/types/features/staking/utils/map-staking-error.d.ts +5 -3
  62. package/dist/types/features/staking/utils/map-staking-error.d.ts.map +1 -1
  63. package/dist/types/features/swap/components/swap-confirm-modal/index.d.ts +9 -0
  64. package/dist/types/features/swap/components/swap-confirm-modal/index.d.ts.map +1 -0
  65. package/dist/types/features/swap/components/swap-confirm-modal/swap-confirm-modal.d.ts +26 -0
  66. package/dist/types/features/swap/components/swap-confirm-modal/swap-confirm-modal.d.ts.map +1 -0
  67. package/dist/types/features/swap/components/swap-widget-provider/swap-widget-provider.d.ts.map +1 -1
  68. package/dist/types/features/swap/components/swap-widget-provider/use-swap-validation.d.ts +4 -1
  69. package/dist/types/features/swap/components/swap-widget-provider/use-swap-validation.d.ts.map +1 -1
  70. package/dist/types/features/swap/components/swap-widget-ui/swap-widget-ui.d.ts.map +1 -1
  71. package/dist/types/features/swap/utils/map-swap-error.d.ts +4 -2
  72. package/dist/types/features/swap/utils/map-swap-error.d.ts.map +1 -1
  73. package/dist/types/libs/i18n.d.ts +9 -0
  74. package/dist/types/libs/i18n.d.ts.map +1 -1
  75. package/dist/types/locales/en.d.ts +9 -0
  76. package/dist/types/locales/en.d.ts.map +1 -1
  77. package/package.json +13 -13
  78. package/src/components/shared/amount-preview/amount-preview.tsx +74 -0
  79. package/src/components/shared/amount-preview/index.ts +9 -0
  80. package/src/components/shared/flow-preview/flow-preview.tsx +64 -0
  81. package/src/components/shared/flow-preview/index.ts +9 -0
  82. package/src/features/staking/components/staking-confirm-modal/index.ts +9 -0
  83. package/src/features/staking/components/staking-confirm-modal/staking-confirm-modal.tsx +121 -0
  84. package/src/features/staking/components/staking-widget-provider/staking-widget-provider.tsx +39 -4
  85. package/src/features/staking/components/staking-widget-provider/use-staking-validation.ts +14 -2
  86. package/src/features/staking/components/staking-widget-ui/staking-widget-ui.tsx +28 -3
  87. package/src/features/staking/hooks/use-build-stake-transaction.ts +7 -2
  88. package/src/features/staking/utils/map-staking-error.ts +6 -4
  89. package/src/features/swap/components/swap-confirm-modal/index.ts +9 -0
  90. package/src/features/swap/components/swap-confirm-modal/swap-confirm-modal.tsx +75 -0
  91. package/src/features/swap/components/swap-widget-provider/swap-widget-provider.tsx +40 -6
  92. package/src/features/swap/components/swap-widget-provider/use-swap-validation.ts +17 -2
  93. package/src/features/swap/components/swap-widget-ui/swap-widget-ui.tsx +30 -3
  94. package/src/features/swap/utils/map-swap-error.ts +5 -3
  95. package/src/locales/en.ts +9 -0
  96. package/dist/esm/tsconfig.build.tsbuildinfo +0 -1
@@ -11,10 +11,12 @@ import { StakingError, StakingErrorCode } from '@ton/appkit';
11
11
  import { mapDefiError } from '../../../utils/map-defi-error';
12
12
 
13
13
  /**
14
- * Map a thrown staking error to an i18n key. Tries staking-specific codes first, falls back to the
15
- * shared {@link mapDefiError} for base DeFi codes, and finally to a generic `staking.quoteError`.
14
+ * Map a thrown staking error to an i18n key. Tries staking-specific codes first, falls back to
15
+ * the shared {@link mapDefiError} for base DeFi codes, and finally to the caller-provided
16
+ * {@link fallback} (defaults to `staking.quoteError`, but send-time callers should pass
17
+ * `staking.sendFailed`).
16
18
  */
17
- export const mapStakingError = (error: unknown): string => {
19
+ export const mapStakingError = (error: unknown, fallback: string = 'staking.quoteError'): string => {
18
20
  if (error instanceof StakingError) {
19
21
  switch (error.code) {
20
22
  case StakingErrorCode.InvalidParams:
@@ -24,5 +26,5 @@ export const mapStakingError = (error: unknown): string => {
24
26
  }
25
27
  }
26
28
 
27
- return mapDefiError(error) ?? 'staking.quoteError';
29
+ return mapDefiError(error) ?? fallback;
28
30
  };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) TonTech.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ export * from './swap-confirm-modal';
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Copyright (c) TonTech.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import type { FC } from 'react';
10
+ import type { SwapProvider, SwapQuote } from '@ton/appkit';
11
+
12
+ import { Modal } from '../../../../components/ui/modal/modal';
13
+ import { Button } from '../../../../components/ui/button';
14
+ import { FlowPreview } from '../../../../components/shared/flow-preview';
15
+ import { useI18n } from '../../../settings/hooks/use-i18n';
16
+ import type { AppkitUIToken } from '../../../../types/appkit-ui-token';
17
+ import { SwapInfo } from '../swap-info';
18
+ import styles from './swap-confirm-modal.module.css';
19
+
20
+ export interface SwapConfirmModalProps {
21
+ open: boolean;
22
+ onClose: () => void;
23
+ onConfirm: () => void;
24
+ fromToken: AppkitUIToken | null;
25
+ toToken: AppkitUIToken | null;
26
+ fromAmount: string;
27
+ toAmount: string;
28
+ fiatSymbol: string;
29
+ quote?: SwapQuote;
30
+ swapProvider?: SwapProvider;
31
+ slippage: number;
32
+ isQuoteLoading?: boolean;
33
+ }
34
+
35
+ export const SwapConfirmModal: FC<SwapConfirmModalProps> = ({
36
+ open,
37
+ onClose,
38
+ onConfirm,
39
+ fromToken,
40
+ toToken,
41
+ fromAmount,
42
+ toAmount,
43
+ fiatSymbol,
44
+ quote,
45
+ swapProvider,
46
+ slippage,
47
+ isQuoteLoading,
48
+ }) => {
49
+ const { t } = useI18n();
50
+
51
+ return (
52
+ <Modal open={open} onOpenChange={(isOpen) => !isOpen && onClose()} title={t('swap.confirmTitle')}>
53
+ <FlowPreview
54
+ fromAmount={fromAmount}
55
+ toAmount={toAmount}
56
+ fromToken={fromToken ?? undefined}
57
+ toToken={toToken ?? undefined}
58
+ fiatSymbol={fiatSymbol}
59
+ />
60
+
61
+ <SwapInfo
62
+ className={styles.info}
63
+ quote={quote}
64
+ provider={swapProvider}
65
+ toToken={toToken}
66
+ slippage={slippage}
67
+ isQuoteLoading={isQuoteLoading}
68
+ />
69
+
70
+ <Button className={styles.confirmButton} variant="fill" size="l" fullWidth onClick={onConfirm}>
71
+ {t('swap.confirm')}
72
+ </Button>
73
+ </Modal>
74
+ );
75
+ };
@@ -6,7 +6,7 @@
6
6
  *
7
7
  */
8
8
 
9
- import { createContext, useCallback, useContext, useMemo, useState } from 'react';
9
+ import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
10
10
  import type { FC, PropsWithChildren } from 'react';
11
11
  import { formatUnits } from '@ton/appkit';
12
12
  import type { Network } from '@ton/appkit';
@@ -234,7 +234,7 @@ export const SwapWidgetProvider: FC<SwapProviderProps> = ({
234
234
  network,
235
235
  slippageBps: slippage,
236
236
  providerId: swapProvider?.providerId,
237
- query: { enabled: isNetworkSupported },
237
+ query: { enabled: isNetworkSupported, networkMode: 'always', retry: false, gcTime: 0 },
238
238
  });
239
239
  // Also show "loading" while the user is still typing (debounce in-flight) so the UI doesn't flash
240
240
  // the previous quote as if it were final.
@@ -247,6 +247,29 @@ export const SwapWidgetProvider: FC<SwapProviderProps> = ({
247
247
  });
248
248
  const { data: tonBalance } = useBalance({ network, query: { refetchInterval: 5000 } });
249
249
 
250
+ // 4. Mutations (hoisted above validation: the mutation `error` is one of its inputs)
251
+ const {
252
+ mutateAsync: buildTransaction,
253
+ isPending: isBuildingTransaction,
254
+ error: buildError,
255
+ reset: resetBuild,
256
+ } = useBuildSwapTransaction({ mutation: { networkMode: 'always' } });
257
+ const {
258
+ mutateAsync: sendTransaction,
259
+ isPending: isSendingPending,
260
+ error: sendMutationError,
261
+ reset: resetSend,
262
+ } = useSendTransaction({ mutation: { networkMode: 'always' } });
263
+ const isSendingTransaction = isBuildingTransaction || isSendingPending;
264
+ const sendError = sendMutationError ?? buildError;
265
+
266
+ // Drop the previous send error when the user changes anything that would invalidate it —
267
+ // the next attempt is conceptually a new swap, no need to keep the old message on screen.
268
+ const resetSendError = useCallback(() => {
269
+ resetBuild();
270
+ resetSend();
271
+ }, [resetBuild, resetSend]);
272
+
250
273
  // 3. Derivations
251
274
  const toAmount = quote?.toAmount ?? '';
252
275
  const { error, canSubmit } = useSwapValidation({
@@ -255,7 +278,9 @@ export const SwapWidgetProvider: FC<SwapProviderProps> = ({
255
278
  fromToken,
256
279
  toToken,
257
280
  fromBalance,
281
+ quote,
258
282
  quoteError,
283
+ sendError,
259
284
  isNetworkSupported,
260
285
  });
261
286
  const isLowBalanceWarningOpen = pendingSwap !== undefined;
@@ -265,10 +290,19 @@ export const SwapWidgetProvider: FC<SwapProviderProps> = ({
265
290
  return formatUnits(pendingSwap.requiredNanos, 9);
266
291
  }, [pendingSwap]);
267
292
 
268
- // 4. Mutations
269
- const { mutateAsync: buildTransaction, isPending: isBuildingTransaction } = useBuildSwapTransaction();
270
- const { mutateAsync: sendTransaction, isPending: isSendingPending } = useSendTransaction();
271
- const isSendingTransaction = isBuildingTransaction || isSendingPending;
293
+ // Drop the previous send error when the user changes anything that would invalidate it —
294
+ // the next attempt is conceptually a new swap, no need to keep the old message on screen.
295
+ useEffect(() => {
296
+ resetSendError();
297
+ }, [fromToken?.address, toToken?.address, fromAmount, resetSendError]);
298
+
299
+ // Auto-clear the send error after a short delay so a stale failure doesn't linger in the
300
+ // submit button — the user is expected to act on it within seconds or move on.
301
+ useEffect(() => {
302
+ if (!sendError) return;
303
+ const id = setTimeout(resetSendError, 5000);
304
+ return () => clearTimeout(id);
305
+ }, [sendError, resetSendError]);
272
306
 
273
307
  // 5. Callbacks
274
308
  const handleMaxClick = useCallback(() => {
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  import { useMemo } from 'react';
10
+ import type { SwapQuote } from '@ton/appkit';
10
11
 
11
12
  import type { AppkitUIToken } from '../../../../types/appkit-ui-token';
12
13
  import { hasTooManyDecimals, isAmountExceedingBalance } from '../../../../utils/validate-amount';
@@ -18,7 +19,9 @@ interface UseSwapValidationOptions {
18
19
  fromToken: AppkitUIToken | null;
19
20
  toToken: AppkitUIToken | null;
20
21
  fromBalance: string | undefined;
22
+ quote: SwapQuote | undefined;
21
23
  quoteError: Error | null;
24
+ sendError: Error | null;
22
25
  isNetworkSupported: boolean;
23
26
  }
24
27
 
@@ -28,10 +31,12 @@ export function useSwapValidation({
28
31
  fromToken,
29
32
  toToken,
30
33
  fromBalance,
34
+ quote,
31
35
  quoteError,
36
+ sendError,
32
37
  isNetworkSupported,
33
38
  }: UseSwapValidationOptions) {
34
- const error: string | null = useMemo(() => {
39
+ const blockingError: string | null = useMemo(() => {
35
40
  if (!isNetworkSupported) return 'defi.unsupportedNetwork';
36
41
 
37
42
  if ((parseFloat(fromAmount) || 0) <= 0) return null;
@@ -45,7 +50,17 @@ export function useSwapValidation({
45
50
  return null;
46
51
  }, [isNetworkSupported, fromAmount, fromToken, fromBalance, quoteError, fromAmountDebounced]);
47
52
 
48
- const canSubmit = (parseFloat(fromAmount) || 0) > 0 && fromToken !== null && toToken !== null && error === null;
53
+ const error = useMemo<string | null>(() => {
54
+ if (sendError) return mapSwapError(sendError, 'swap.sendFailed');
55
+ return blockingError;
56
+ }, [sendError, blockingError]);
57
+
58
+ const canSubmit =
59
+ (parseFloat(fromAmount) || 0) > 0 &&
60
+ fromToken !== null &&
61
+ toToken !== null &&
62
+ blockingError === null &&
63
+ quote !== undefined;
49
64
 
50
65
  return { error, canSubmit };
51
66
  }
@@ -12,6 +12,7 @@ import clsx from 'clsx';
12
12
 
13
13
  import { useI18n } from '../../../settings/hooks/use-i18n';
14
14
  import { useSelectedWallet } from '../../../wallets';
15
+ import { SwapConfirmModal } from '../swap-confirm-modal';
15
16
  import { SwapField } from '../swap-field';
16
17
  import { SwapFlipButton } from '../swap-flip-button';
17
18
  import { SwapInfo } from '../swap-info';
@@ -67,6 +68,7 @@ export const SwapWidgetUI: FC<SwapWidgetRenderProps> = ({
67
68
 
68
69
  const [activeField, setActiveField] = useState<'from' | 'to' | null>(null);
69
70
  const [isSettingsOpen, setIsSettingsOpen] = useState(false);
71
+ const [isConfirmOpen, setIsConfirmOpen] = useState(false);
70
72
  const [isFlipped, setIsFlipped] = useState(false);
71
73
 
72
74
  const handleFlip = useCallback(() => {
@@ -74,12 +76,22 @@ export const SwapWidgetUI: FC<SwapWidgetRenderProps> = ({
74
76
  onFlip();
75
77
  }, [onFlip]);
76
78
 
79
+ // Close the modal immediately; the build/send result (including errors) is surfaced
80
+ // back in the widget's main button via the `error` from the provider.
81
+ const handleConfirm = useCallback(() => {
82
+ setIsConfirmOpen(false);
83
+ sendSwapTransaction().catch(() => {
84
+ // Error is captured by the mutation and shown through the validator's `error` output.
85
+ });
86
+ }, [sendSwapTransaction]);
87
+
77
88
  const buttonText = useMemo(() => {
78
- if (error) return t(error);
89
+ if (isSendingTransaction || isQuoteLoading) return t('swap.loading');
79
90
  if (!fromToken || !toToken) return t('swap.selectToken');
91
+ if (error) return t(error);
80
92
  if (canSubmit) return t('swap.continue');
81
93
  return t('swap.enterAmount');
82
- }, [error, fromToken, toToken, canSubmit, t]);
94
+ }, [isSendingTransaction, isQuoteLoading, error, fromToken, toToken, canSubmit, t]);
83
95
 
84
96
  return (
85
97
  <div className={clsx(styles.widget, className)} {...props}>
@@ -135,6 +147,21 @@ export const SwapWidgetUI: FC<SwapWidgetRenderProps> = ({
135
147
  onProviderChange={setSwapProviderId}
136
148
  />
137
149
 
150
+ <SwapConfirmModal
151
+ open={isConfirmOpen}
152
+ onClose={() => setIsConfirmOpen(false)}
153
+ onConfirm={handleConfirm}
154
+ fromToken={fromToken}
155
+ toToken={toToken}
156
+ fromAmount={fromAmount}
157
+ toAmount={toAmount}
158
+ fiatSymbol={fiatSymbol}
159
+ quote={quote}
160
+ swapProvider={swapProvider}
161
+ slippage={slippage}
162
+ isQuoteLoading={isQuoteLoading}
163
+ />
164
+
138
165
  <LowBalanceModal
139
166
  open={isLowBalanceWarningOpen}
140
167
  mode={lowBalanceMode}
@@ -149,7 +176,7 @@ export const SwapWidgetUI: FC<SwapWidgetRenderProps> = ({
149
176
  size="l"
150
177
  fullWidth
151
178
  disabled={!canSubmit || isQuoteLoading || isSendingTransaction}
152
- onClick={sendSwapTransaction}
179
+ onClick={() => setIsConfirmOpen(true)}
153
180
  >
154
181
  {buttonText}
155
182
  </ButtonWithConnect>
@@ -12,9 +12,11 @@ import { mapDefiError } from '../../../utils/map-defi-error';
12
12
 
13
13
  /**
14
14
  * Map a thrown swap error to an i18n key. Tries swap-specific codes first, falls back to the
15
- * shared {@link mapDefiError} for base DeFi codes, and finally to a generic `swap.quoteError`.
15
+ * shared {@link mapDefiError} for base DeFi codes, and finally to the caller-provided
16
+ * {@link fallback} (defaults to `swap.quoteError`, but send-time callers should pass
17
+ * `swap.sendFailed`).
16
18
  */
17
- export const mapSwapError = (error: unknown): string => {
19
+ export const mapSwapError = (error: unknown, fallback: string = 'swap.quoteError'): string => {
18
20
  if (error instanceof SwapError) {
19
21
  switch (error.code) {
20
22
  case SwapErrorCode.InvalidQuote:
@@ -28,5 +30,5 @@ export const mapSwapError = (error: unknown): string => {
28
30
  }
29
31
  }
30
32
 
31
- return mapDefiError(error) ?? 'swap.quoteError';
33
+ return mapDefiError(error) ?? fallback;
32
34
  };
package/src/locales/en.ts CHANGED
@@ -78,6 +78,10 @@ export default {
78
78
  provider: 'Provider',
79
79
  save: 'Save',
80
80
  minReceived: 'Min Received',
81
+ confirmTitle: 'Confirm swap transaction',
82
+ confirm: 'Confirm',
83
+ sendFailed: 'Transaction failed',
84
+ loading: 'Loading...',
81
85
  },
82
86
 
83
87
  // Low balance modal (shared between swap, staking, etc.)
@@ -118,5 +122,10 @@ export default {
118
122
  provider: 'Provider',
119
123
  settings: 'Staking settings',
120
124
  save: 'Save',
125
+ confirmStakingTitle: 'Confirm staking',
126
+ confirmUnstakingTitle: 'Confirm unstaking',
127
+ confirm: 'Confirm',
128
+ sendFailed: 'Transaction failed',
129
+ loading: 'Loading...',
121
130
  },
122
131
  } as const;