@djangocfg/ext-payments 1.0.20 → 1.0.22

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.
@@ -13,6 +13,9 @@ import { useForm } from 'react-hook-form';
13
13
  import { z } from 'zod';
14
14
  import { zodResolver } from '@hookform/resolvers/zod';
15
15
 
16
+ import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
17
+ import { useT } from '@djangocfg/i18n';
18
+ import { PAYMENTS_NAMESPACE, type PaymentsTranslations } from '../i18n';
16
19
  import {
17
20
  Alert,
18
21
  AlertDescription,
@@ -74,10 +77,31 @@ interface WithdrawSaved {
74
77
  // ─────────────────────────────────────────────────────────────────────────────
75
78
 
76
79
  export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetProps) {
80
+ const baseT = useT();
81
+ const pt = createTypedExtensionT<typeof PAYMENTS_NAMESPACE, PaymentsTranslations>(baseT, PAYMENTS_NAMESPACE);
77
82
  const { currencies, isLoadingCurrencies, withdraw, balanceAmount } = useWallet();
78
83
  const [isSubmitting, setIsSubmitting] = useState(false);
79
84
  const [error, setError] = useState<string | null>(null);
80
85
 
86
+ // Prepare labels before render
87
+ const labels = useMemo(() => ({
88
+ title: pt('sheets.withdrawTitle'),
89
+ description: pt('sheets.withdrawDescription'),
90
+ amountUsd: pt('form.amountUsd'),
91
+ withdrawAs: pt('form.withdrawAs'),
92
+ walletAddress: pt('form.walletAddress'),
93
+ enterWalletAddress: pt('form.enterWalletAddress'),
94
+ amount: pt('form.amount'),
95
+ serviceFee: pt('estimate.serviceFee'),
96
+ networkFee: pt('estimate.networkFee'),
97
+ youWillReceive: pt('estimate.youWillReceive'),
98
+ calculating: pt('estimate.calculating'),
99
+ insufficientBalance: pt('withdraw.insufficientBalance'),
100
+ approvalWarning: pt('withdraw.approvalWarning'),
101
+ submitting: pt('withdraw.submitting'),
102
+ requestWithdrawal: pt('actions.requestWithdrawal'),
103
+ }), [pt]);
104
+
81
105
  // Remember last used currency and wallet address
82
106
  const [saved, setSaved] = useLocalStorage<WithdrawSaved>(STORAGE_KEY, {
83
107
  currency: '',
@@ -178,9 +202,9 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
178
202
  <ResponsiveSheet open={open} onOpenChange={handleOpenChange}>
179
203
  <ResponsiveSheetContent className="sm:max-w-md">
180
204
  <ResponsiveSheetHeader>
181
- <ResponsiveSheetTitle>Withdraw</ResponsiveSheetTitle>
205
+ <ResponsiveSheetTitle>{labels.title}</ResponsiveSheetTitle>
182
206
  <ResponsiveSheetDescription>
183
- Withdraw funds to your cryptocurrency wallet
207
+ {labels.description}
184
208
  </ResponsiveSheetDescription>
185
209
  </ResponsiveSheetHeader>
186
210
 
@@ -192,7 +216,7 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
192
216
  name="amount"
193
217
  render={({ field }) => (
194
218
  <FormItem>
195
- <FormLabel>Amount (USD)</FormLabel>
219
+ <FormLabel>{labels.amountUsd}</FormLabel>
196
220
  <FormControl>
197
221
  <div className="relative">
198
222
  <span className="absolute left-4 top-1/2 -translate-y-1/2 text-muted-foreground text-lg">
@@ -212,7 +236,7 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
212
236
  <FormMessage />
213
237
  {insufficientBalance && (
214
238
  <p className="text-sm text-destructive mt-1">
215
- Insufficient balance (Available: ${formatUsdAmount(balanceAmount)})
239
+ {labels.insufficientBalance} (Available: ${formatUsdAmount(balanceAmount)})
216
240
  </p>
217
241
  )}
218
242
  </FormItem>
@@ -225,7 +249,7 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
225
249
  name="currency"
226
250
  render={({ field }) => (
227
251
  <FormItem>
228
- <FormLabel>Withdraw as</FormLabel>
252
+ <FormLabel>{labels.withdrawAs}</FormLabel>
229
253
  <FormControl>
230
254
  <CurrencyCombobox
231
255
  options={currencyOptions}
@@ -245,10 +269,10 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
245
269
  name="wallet_address"
246
270
  render={({ field }) => (
247
271
  <FormItem>
248
- <FormLabel>Wallet Address</FormLabel>
272
+ <FormLabel>{labels.walletAddress}</FormLabel>
249
273
  <FormControl>
250
274
  <Input
251
- placeholder="Enter your wallet address"
275
+ placeholder={labels.enterWalletAddress}
252
276
  className="font-mono text-sm"
253
277
  {...field}
254
278
  />
@@ -262,33 +286,33 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
262
286
  {amount >= 10 && selectedCurrency && (
263
287
  <div className="bg-muted rounded-xl p-4 space-y-2">
264
288
  <div className="flex items-center justify-between text-sm">
265
- <span className="text-muted-foreground">Amount</span>
289
+ <span className="text-muted-foreground">{labels.amount}</span>
266
290
  <span>${formatUsdAmount(amount)}</span>
267
291
  </div>
268
292
  {isLoadingEstimate ? (
269
293
  <div className="flex items-center gap-2 text-sm text-muted-foreground py-2">
270
294
  <Loader2 className="h-4 w-4 animate-spin" />
271
- <span>Calculating fees...</span>
295
+ <span>{labels.calculating}</span>
272
296
  </div>
273
297
  ) : estimate ? (
274
298
  <>
275
299
  <div className="flex items-center justify-between text-sm">
276
300
  <span className="text-muted-foreground">
277
- Service fee ({estimate.serviceFeePercent}%)
301
+ {labels.serviceFee} ({estimate.serviceFeePercent}%)
278
302
  </span>
279
303
  <span className="text-destructive">
280
304
  -${formatUsdAmount(estimate.serviceFeeUsd)}
281
305
  </span>
282
306
  </div>
283
307
  <div className="flex items-center justify-between text-sm">
284
- <span className="text-muted-foreground">Network fee</span>
308
+ <span className="text-muted-foreground">{labels.networkFee}</span>
285
309
  <span className="text-destructive">
286
310
  -${formatUsdAmount(estimate.networkFeeUsd)}
287
311
  </span>
288
312
  </div>
289
313
  <div className="border-t pt-2 mt-2">
290
314
  <div className="flex items-center justify-between">
291
- <span className="font-medium">You will receive</span>
315
+ <span className="font-medium">{labels.youWillReceive}</span>
292
316
  <div className="text-right">
293
317
  <div className="font-semibold">
294
318
  ${formatUsdAmount(estimate.amountToReceive)}
@@ -313,7 +337,7 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
313
337
  <Alert>
314
338
  <AlertCircle className="h-4 w-4" />
315
339
  <AlertDescription>
316
- Withdrawal requests require admin approval. Processing may take 24-48 hours.
340
+ {labels.approvalWarning}
317
341
  </AlertDescription>
318
342
  </Alert>
319
343
 
@@ -341,10 +365,10 @@ export function WithdrawSheet({ open, onOpenChange, onSuccess }: WithdrawSheetPr
341
365
  {isSubmitting ? (
342
366
  <>
343
367
  <RefreshCw className="h-5 w-5 mr-2 animate-spin" />
344
- Submitting...
368
+ {labels.submitting}
345
369
  </>
346
370
  ) : (
347
- 'Request Withdrawal'
371
+ labels.requestWithdrawal
348
372
  )}
349
373
  </Button>
350
374
  </form>
@@ -19,6 +19,9 @@ import {
19
19
  import moment from 'moment';
20
20
  import useSWR from 'swr';
21
21
 
22
+ import { createTypedExtensionT } from '@djangocfg/ext-base/i18n';
23
+ import { useT } from '@djangocfg/i18n';
24
+ import { PAYMENTS_NAMESPACE, type PaymentsTranslations } from '../i18n';
22
25
  import {
23
26
  Button,
24
27
  CopyButton,
@@ -49,43 +52,37 @@ interface WithdrawalSheetProps {
49
52
  // Status Config
50
53
  // ─────────────────────────────────────────────────────────────────────────────
51
54
 
52
- const statusConfig: Record<string, { icon: any; color: string; bg: string; label: string; animate?: boolean }> = {
55
+ const statusConfig: Record<string, { icon: any; color: string; bg: string; animate?: boolean }> = {
53
56
  pending: {
54
57
  icon: Clock,
55
58
  color: 'text-yellow-500',
56
59
  bg: 'bg-yellow-500/10',
57
- label: 'Pending Approval',
58
60
  },
59
61
  approved: {
60
62
  icon: CheckCircle2,
61
63
  color: 'text-blue-500',
62
64
  bg: 'bg-blue-500/10',
63
- label: 'Approved',
64
65
  },
65
66
  processing: {
66
67
  icon: RefreshCw,
67
68
  color: 'text-blue-500',
68
69
  bg: 'bg-blue-500/10',
69
- label: 'Processing',
70
70
  animate: true,
71
71
  },
72
72
  completed: {
73
73
  icon: CheckCircle2,
74
74
  color: 'text-green-500',
75
75
  bg: 'bg-green-500/10',
76
- label: 'Completed',
77
76
  },
78
77
  rejected: {
79
78
  icon: XCircle,
80
79
  color: 'text-red-500',
81
80
  bg: 'bg-red-500/10',
82
- label: 'Rejected',
83
81
  },
84
82
  cancelled: {
85
83
  icon: Ban,
86
84
  color: 'text-muted-foreground',
87
85
  bg: 'bg-muted',
88
- label: 'Cancelled',
89
86
  },
90
87
  };
91
88
 
@@ -94,8 +91,46 @@ const statusConfig: Record<string, { icon: any; color: string; bg: string; label
94
91
  // ─────────────────────────────────────────────────────────────────────────────
95
92
 
96
93
  export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: WithdrawalSheetProps) {
94
+ const baseT = useT();
95
+ const pt = createTypedExtensionT<typeof PAYMENTS_NAMESPACE, PaymentsTranslations>(baseT, PAYMENTS_NAMESPACE);
97
96
  const { getWithdrawalDetails, cancelWithdrawal, refreshWallet } = useWallet();
98
97
 
98
+ // Prepare labels before render
99
+ const labels = useMemo(() => ({
100
+ title: pt('sheets.withdrawalTitle'),
101
+ // Status labels
102
+ pending: pt('withdrawalStatus.pending'),
103
+ approved: pt('withdrawalStatus.approved'),
104
+ processing: pt('withdrawalStatus.processing'),
105
+ completed: pt('withdrawalStatus.completed'),
106
+ rejected: pt('withdrawalStatus.rejected'),
107
+ cancelled: pt('withdrawalStatus.cancelled'),
108
+ // Descriptions
109
+ pendingApproval: pt('withdrawalDescriptions.pendingApproval'),
110
+ processingDesc: pt('withdrawalDescriptions.processing'),
111
+ completedDesc: pt('withdrawalDescriptions.completed'),
112
+ rejectedDesc: pt('withdrawalDescriptions.rejected'),
113
+ cancelledDesc: pt('withdrawalDescriptions.cancelled'),
114
+ // Form
115
+ amount: pt('form.amount'),
116
+ totalFees: pt('estimate.serviceFee'),
117
+ youReceive: pt('estimate.youWillReceive'),
118
+ cryptoAmount: pt('form.amount'),
119
+ destinationWallet: pt('form.walletAddress'),
120
+ transactionHash: pt('form.transactionHash'),
121
+ withdrawalId: pt('form.paymentId'),
122
+ reference: pt('form.orderId'),
123
+ created: pt('form.created'),
124
+ network: pt('form.network'),
125
+ // Actions
126
+ viewOnExplorer: pt('actions.openInPaymentProvider'),
127
+ cancel: pt('actions.cancel'),
128
+ refreshStatus: pt('actions.refreshStatus'),
129
+ tryAgain: pt('actions.tryAgain'),
130
+ // Messages
131
+ failedToLoad: pt('messages.failedToLoadPayment'),
132
+ }), [pt]);
133
+
99
134
  // Fetch withdrawal details when sheet is open
100
135
  const { data: withdrawal, isLoading, error, mutate } = useSWR<WithdrawalDetail>(
101
136
  open && withdrawalId ? ['withdrawal-details', withdrawalId] : null,
@@ -115,13 +150,23 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
115
150
  const isProcessing = s === 'processing' || s === 'approved';
116
151
  const canCancel = isPending;
117
152
 
153
+ // Status label from translations
154
+ const statusLabels: Record<string, string> = {
155
+ pending: labels.pending,
156
+ approved: labels.approved,
157
+ processing: labels.processing,
158
+ completed: labels.completed,
159
+ rejected: labels.rejected,
160
+ cancelled: labels.cancelled,
161
+ };
162
+
118
163
  // Description text
119
164
  let description = '';
120
- if (isPending) description = 'Waiting for admin approval';
121
- else if (isProcessing) description = 'Your withdrawal is being processed';
122
- else if (isCompleted) description = 'Withdrawal completed successfully';
123
- else if (isRejected) description = 'Withdrawal was rejected';
124
- else if (isCancelled) description = 'Withdrawal was cancelled';
165
+ if (isPending) description = labels.pendingApproval;
166
+ else if (isProcessing) description = labels.processingDesc;
167
+ else if (isCompleted) description = labels.completedDesc;
168
+ else if (isRejected) description = labels.rejectedDesc;
169
+ else if (isCancelled) description = labels.cancelledDesc;
125
170
 
126
171
  // Formatted values
127
172
  const amountUsd = withdrawal?.amount_usd ? `$${parseFloat(withdrawal.amount_usd).toFixed(2)}` : '';
@@ -137,6 +182,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
137
182
  return {
138
183
  status: s,
139
184
  config,
185
+ statusLabel: statusLabels[s] || statusLabels.pending,
140
186
  isPending,
141
187
  isCompleted,
142
188
  isRejected,
@@ -150,9 +196,9 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
150
196
  createdAt,
151
197
  completedAt,
152
198
  };
153
- }, [withdrawal]);
199
+ }, [withdrawal, labels]);
154
200
 
155
- const { config, canCancel, description, amountUsd, finalAmountUsd, totalFeeUsd, createdAt, completedAt } = displayData;
201
+ const { config, statusLabel, canCancel, description, amountUsd, finalAmountUsd, totalFeeUsd, createdAt, completedAt } = displayData;
156
202
  const StatusIcon = config.icon;
157
203
 
158
204
  // Handle cancel
@@ -171,7 +217,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
171
217
  <ResponsiveSheet open={open} onOpenChange={onOpenChange}>
172
218
  <ResponsiveSheetContent className="sm:max-w-lg">
173
219
  <ResponsiveSheetHeader>
174
- <ResponsiveSheetTitle>Withdrawal Details</ResponsiveSheetTitle>
220
+ <ResponsiveSheetTitle>{labels.title}</ResponsiveSheetTitle>
175
221
  <ResponsiveSheetDescription>{description}</ResponsiveSheetDescription>
176
222
  </ResponsiveSheetHeader>
177
223
 
@@ -187,8 +233,8 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
187
233
  {error && (
188
234
  <div className="flex flex-col items-center justify-center py-12">
189
235
  <XCircle className="h-12 w-12 text-destructive mb-4" />
190
- <p className="text-sm text-muted-foreground mb-4">Failed to load withdrawal</p>
191
- <Button onClick={() => mutate()}>Try Again</Button>
236
+ <p className="text-sm text-muted-foreground mb-4">{labels.failedToLoad}</p>
237
+ <Button onClick={() => mutate()}>{labels.tryAgain}</Button>
192
238
  </div>
193
239
  )}
194
240
 
@@ -198,7 +244,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
198
244
  <div className={cn('flex items-center gap-3 p-4 rounded-xl', config.bg)}>
199
245
  <StatusIcon className={cn('h-6 w-6', config.color, config.animate && 'animate-spin')} />
200
246
  <div className="flex-1">
201
- <div className="font-semibold">{config.label}</div>
247
+ <div className="font-semibold">{statusLabel}</div>
202
248
  {withdrawal.admin_notes && (
203
249
  <div className="text-sm text-muted-foreground">{withdrawal.admin_notes}</div>
204
250
  )}
@@ -208,17 +254,17 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
208
254
  {/* Amount Breakdown */}
209
255
  <div className="bg-muted rounded-xl p-4 space-y-3">
210
256
  <div className="flex items-center justify-between">
211
- <span className="text-muted-foreground">Amount</span>
257
+ <span className="text-muted-foreground">{labels.amount}</span>
212
258
  <span className="font-semibold">{amountUsd}</span>
213
259
  </div>
214
260
  {totalFeeUsd && (
215
261
  <div className="flex items-center justify-between text-sm">
216
- <span className="text-muted-foreground">Total fees</span>
262
+ <span className="text-muted-foreground">{labels.totalFees}</span>
217
263
  <span className="text-destructive">-{totalFeeUsd}</span>
218
264
  </div>
219
265
  )}
220
266
  <div className="flex items-center justify-between pt-2 border-t">
221
- <span className="text-muted-foreground">You receive</span>
267
+ <span className="text-muted-foreground">{labels.youReceive}</span>
222
268
  <div className="flex items-center gap-2">
223
269
  <TokenIcon symbol={withdrawal.currency_code} size={24} />
224
270
  <span className="font-mono font-bold text-lg">
@@ -228,7 +274,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
228
274
  </div>
229
275
  {withdrawal.crypto_amount && (
230
276
  <div className="flex items-center justify-between text-sm">
231
- <span className="text-muted-foreground">Crypto amount</span>
277
+ <span className="text-muted-foreground">{labels.cryptoAmount}</span>
232
278
  <span className="font-mono">{withdrawal.crypto_amount} {withdrawal.currency_token}</span>
233
279
  </div>
234
280
  )}
@@ -237,7 +283,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
237
283
  {/* Wallet Address */}
238
284
  {withdrawal.wallet_address && (
239
285
  <div className="space-y-2">
240
- <label className="text-sm font-medium">Destination Wallet</label>
286
+ <label className="text-sm font-medium">{labels.destinationWallet}</label>
241
287
  <div className="flex items-center gap-2">
242
288
  <div className="flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all">
243
289
  {withdrawal.wallet_address}
@@ -250,7 +296,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
250
296
  {/* Transaction Hash (if completed) */}
251
297
  {withdrawal.transaction_hash && (
252
298
  <div className="space-y-2">
253
- <label className="text-sm font-medium">Transaction Hash</label>
299
+ <label className="text-sm font-medium">{labels.transactionHash}</label>
254
300
  <div className="flex items-center gap-2">
255
301
  <div className="flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all">
256
302
  {withdrawal.transaction_hash}
@@ -268,7 +314,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
268
314
  onClick={() => window.open(withdrawal.explorer_link!, '_blank')}
269
315
  >
270
316
  <ExternalLink className="h-4 w-4 mr-2" />
271
- View on Explorer
317
+ {labels.viewOnExplorer}
272
318
  </Button>
273
319
  )}
274
320
 
@@ -280,35 +326,35 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
280
326
  onClick={handleCancel}
281
327
  >
282
328
  <Ban className="h-4 w-4 mr-2" />
283
- Cancel Withdrawal
329
+ {labels.cancel}
284
330
  </Button>
285
331
  )}
286
332
 
287
333
  {/* Metadata */}
288
334
  <div className="space-y-2 text-xs text-muted-foreground pt-4 border-t">
289
335
  <div className="flex justify-between">
290
- <span>Withdrawal ID</span>
336
+ <span>{labels.withdrawalId}</span>
291
337
  <span className="font-mono">{withdrawal.id}</span>
292
338
  </div>
293
339
  {withdrawal.internal_withdrawal_id && (
294
340
  <div className="flex justify-between">
295
- <span>Reference #</span>
341
+ <span>{labels.reference}</span>
296
342
  <span className="font-mono">{withdrawal.internal_withdrawal_id}</span>
297
343
  </div>
298
344
  )}
299
345
  <div className="flex justify-between">
300
- <span>Created</span>
346
+ <span>{labels.created}</span>
301
347
  <span>{createdAt}</span>
302
348
  </div>
303
349
  {completedAt && (
304
350
  <div className="flex justify-between">
305
- <span>Completed</span>
351
+ <span>{labels.completed}</span>
306
352
  <span>{completedAt}</span>
307
353
  </div>
308
354
  )}
309
355
  {withdrawal.currency_network && (
310
356
  <div className="flex justify-between">
311
- <span>Network</span>
357
+ <span>{labels.network}</span>
312
358
  <span>{withdrawal.currency_network}</span>
313
359
  </div>
314
360
  )}
@@ -321,7 +367,7 @@ export function WithdrawalSheet({ withdrawalId, open, onOpenChange }: Withdrawal
321
367
  onClick={() => mutate()}
322
368
  >
323
369
  <RefreshCw className="h-4 w-4 mr-2" />
324
- Refresh Status
370
+ {labels.refreshStatus}
325
371
  </Button>
326
372
  </div>
327
373
  )}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Payments Extension I18n
3
+ *
4
+ * Provides translations for the payments extension.
5
+ * Can be merged with app translations using mergeExtensionTranslations from @djangocfg/ext-base/i18n
6
+ */
7
+
8
+ import { createExtensionI18n } from '@djangocfg/ext-base/i18n';
9
+ import type { PaymentsTranslations } from './types';
10
+ import { en } from './locales/en';
11
+ import { ru } from './locales/ru';
12
+ import { ko } from './locales/ko';
13
+
14
+ /** Payments extension namespace */
15
+ export const PAYMENTS_NAMESPACE = 'payments' as const;
16
+
17
+ /**
18
+ * Payments extension i18n instance
19
+ */
20
+ export const paymentsI18n = createExtensionI18n<PaymentsTranslations>({
21
+ namespace: PAYMENTS_NAMESPACE,
22
+ defaultLocale: 'en',
23
+ locales: { en, ru, ko },
24
+ });
25
+
26
+ /**
27
+ * All payments translations ready to merge with app translations
28
+ */
29
+ export const paymentsTranslations = paymentsI18n.getAllTranslations();
30
+
31
+ // Types
32
+ export type { PaymentsTranslations, PaymentsKeys, PaymentsLocalKeys } from './types';
33
+
34
+ // Re-export locales for direct access if needed
35
+ export { en, ru, ko };
@@ -0,0 +1,136 @@
1
+ import type { PaymentsTranslations } from '../types';
2
+
3
+ export const en: PaymentsTranslations = {
4
+ balance: {
5
+ available: 'Available Balance',
6
+ totalDeposited: 'Total Deposited',
7
+ totalWithdrawn: 'Total Withdrawn',
8
+ },
9
+
10
+ actions: {
11
+ addFunds: 'Add Funds',
12
+ withdraw: 'Withdraw',
13
+ continue: 'Continue',
14
+ requestWithdrawal: 'Request Withdrawal',
15
+ cancel: 'Cancel',
16
+ close: 'Close',
17
+ copyAddress: 'Copy Address',
18
+ copied: 'Copied!',
19
+ viewAll: 'View All',
20
+ tryAgain: 'Try Again',
21
+ refreshStatus: 'Refresh Status',
22
+ createNewPayment: 'Create New Payment',
23
+ openInPaymentProvider: 'Open in Payment Provider',
24
+ },
25
+
26
+ paymentStatus: {
27
+ waiting: 'Waiting for payment',
28
+ confirming: 'Confirming',
29
+ completed: 'Completed',
30
+ failed: 'Failed',
31
+ expired: 'Expired',
32
+ paymentExpired: 'Payment Expired',
33
+ },
34
+
35
+ withdrawalStatus: {
36
+ pending: 'Pending Approval',
37
+ approved: 'Approved',
38
+ processing: 'Processing',
39
+ completed: 'Completed',
40
+ rejected: 'Rejected',
41
+ cancelled: 'Cancelled',
42
+ },
43
+
44
+ paymentDescriptions: {
45
+ sendCrypto: 'Send cryptocurrency to complete payment',
46
+ expired: 'This payment has expired',
47
+ completed: 'Payment completed successfully',
48
+ failed: 'Payment failed',
49
+ confirming: 'Confirming your payment',
50
+ createNew: 'Please create a new payment to continue',
51
+ },
52
+
53
+ withdrawalDescriptions: {
54
+ pendingApproval: 'Waiting for admin approval',
55
+ processing: 'Your withdrawal is being processed',
56
+ completed: 'Withdrawal completed successfully',
57
+ rejected: 'Withdrawal was rejected',
58
+ cancelled: 'Withdrawal was cancelled',
59
+ },
60
+
61
+ form: {
62
+ amount: 'Amount',
63
+ amountUsd: 'Amount (USD)',
64
+ currency: 'Currency',
65
+ walletAddress: 'Wallet Address',
66
+ selectCurrency: 'Select currency...',
67
+ enterWalletAddress: 'Enter your wallet address',
68
+ search: 'Search...',
69
+ payWith: 'Pay with',
70
+ withdrawAs: 'Withdraw as',
71
+ amountToSend: 'Amount to send',
72
+ equivalent: 'Equivalent',
73
+ network: 'Network',
74
+ paymentAddress: 'Payment Address',
75
+ transactionHash: 'Transaction Hash',
76
+ paymentId: 'Payment ID',
77
+ orderId: 'Order #',
78
+ created: 'Created',
79
+ },
80
+
81
+ validation: {
82
+ minimumDeposit: 'Minimum $1',
83
+ minimumWithdrawal: 'Minimum $10',
84
+ selectCurrency: 'Select a currency',
85
+ invalidWalletAddress: 'Invalid wallet address',
86
+ },
87
+
88
+ messages: {
89
+ paymentCreated: 'Payment created successfully',
90
+ paymentFailed: 'Failed to create payment',
91
+ withdrawalCreated: 'Withdrawal request created',
92
+ withdrawalFailed: 'Failed to create withdrawal request',
93
+ withdrawalCancelled: 'Withdrawal cancelled',
94
+ addressCopied: 'Address copied to clipboard',
95
+ failedToLoadPayment: 'Failed to load payment',
96
+ failedToCreateWithdrawal: 'Failed to create withdrawal request',
97
+ },
98
+
99
+ sheets: {
100
+ addFundsTitle: 'Add Funds',
101
+ addFundsDescription: 'Add funds to your wallet using cryptocurrency',
102
+ withdrawTitle: 'Withdraw',
103
+ withdrawDescription: 'Withdraw funds to your cryptocurrency wallet',
104
+ paymentTitle: 'Payment Details',
105
+ withdrawalTitle: 'Withdrawal Details',
106
+ },
107
+
108
+ activity: {
109
+ title: 'Recent Activity',
110
+ noActivity: 'No Activity Yet',
111
+ deposit: 'Deposit',
112
+ withdrawal: 'Withdrawal',
113
+ payment: 'Payment',
114
+ transactionsWillAppear: 'Your transactions will appear here',
115
+ },
116
+
117
+ estimate: {
118
+ gettingRate: 'Getting rate...',
119
+ calculating: 'Calculating fees...',
120
+ enterAmountToSee: 'Enter amount to see conversion',
121
+ youWillSend: 'You will send',
122
+ youWillReceive: 'You will receive',
123
+ serviceFee: 'Service fee',
124
+ networkFee: 'Network fee',
125
+ rate: 'Rate',
126
+ minimumAmount: 'Minimum amount',
127
+ },
128
+
129
+ withdraw: {
130
+ insufficientBalance: 'Insufficient balance',
131
+ approvalWarning: 'Withdrawal requests require admin approval. Processing may take 24-48 hours.',
132
+ submitting: 'Submitting...',
133
+ creating: 'Creating...',
134
+ expiresIn: 'Expires in',
135
+ },
136
+ };