@djangocfg/ext-payments 1.0.14 → 1.0.19
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.
- package/dist/config.cjs +5 -8
- package/dist/config.js +5 -8
- package/dist/index.cjs +1906 -1043
- package/dist/index.d.cts +644 -59
- package/dist/index.d.ts +644 -59
- package/dist/index.js +1886 -1040
- package/package.json +13 -16
- package/src/WalletPage.tsx +100 -0
- package/src/api/generated/ext_payments/CLAUDE.md +10 -4
- package/src/api/generated/ext_payments/_utils/fetchers/ext_payments__payments.ts +268 -5
- package/src/api/generated/ext_payments/_utils/hooks/ext_payments__payments.ts +102 -3
- package/src/api/generated/ext_payments/_utils/schemas/Balance.schema.ts +1 -1
- package/src/api/generated/ext_payments/_utils/schemas/PaginatedWithdrawalListList.schema.ts +24 -0
- package/src/api/generated/ext_payments/_utils/schemas/PaymentCreateRequest.schema.ts +21 -0
- package/src/api/generated/ext_payments/_utils/schemas/PaymentCreateResponse.schema.ts +22 -0
- package/src/api/generated/ext_payments/_utils/schemas/PaymentDetail.schema.ts +3 -3
- package/src/api/generated/ext_payments/_utils/schemas/PaymentList.schema.ts +2 -2
- package/src/api/generated/ext_payments/_utils/schemas/Transaction.schema.ts +1 -1
- package/src/api/generated/ext_payments/_utils/schemas/WithdrawalCancelResponse.schema.ts +22 -0
- package/src/api/generated/ext_payments/_utils/schemas/WithdrawalCreateRequest.schema.ts +21 -0
- package/src/api/generated/ext_payments/_utils/schemas/WithdrawalCreateResponse.schema.ts +22 -0
- package/src/api/generated/ext_payments/_utils/schemas/WithdrawalDetail.schema.ts +42 -0
- package/src/api/generated/ext_payments/_utils/schemas/WithdrawalList.schema.ts +29 -0
- package/src/api/generated/ext_payments/_utils/schemas/index.ts +8 -0
- package/src/api/generated/ext_payments/client.ts +1 -1
- package/src/api/generated/ext_payments/enums.ts +36 -0
- package/src/api/generated/ext_payments/ext_payments__payments/client.ts +104 -6
- package/src/api/generated/ext_payments/ext_payments__payments/models.ts +168 -8
- package/src/api/generated/ext_payments/index.ts +1 -1
- package/src/api/generated/ext_payments/schema.json +752 -42
- package/src/components/ActivityItem.tsx +118 -0
- package/src/components/ActivityList.tsx +93 -0
- package/src/components/AddFundsSheet.tsx +342 -0
- package/src/components/BalanceHero.tsx +102 -0
- package/src/components/CurrencyCombobox.tsx +49 -0
- package/src/components/PaymentSheet.tsx +352 -0
- package/src/components/WithdrawSheet.tsx +355 -0
- package/src/components/WithdrawalSheet.tsx +332 -0
- package/src/components/index.ts +11 -0
- package/src/config.ts +1 -0
- package/src/contexts/WalletContext.tsx +356 -0
- package/src/contexts/index.ts +13 -42
- package/src/contexts/types.ts +43 -37
- package/src/hooks/index.ts +3 -20
- package/src/hooks/useCurrencyOptions.ts +79 -0
- package/src/hooks/useEstimate.ts +113 -0
- package/src/hooks/useWithdrawalEstimate.ts +117 -0
- package/src/index.ts +9 -18
- package/src/types/index.ts +78 -0
- package/src/utils/errors.ts +36 -0
- package/src/utils/format.ts +65 -0
- package/src/utils/index.ts +3 -0
- package/src/contexts/BalancesContext.tsx +0 -63
- package/src/contexts/CurrenciesContext.tsx +0 -64
- package/src/contexts/OverviewContext.tsx +0 -173
- package/src/contexts/PaymentsContext.tsx +0 -122
- package/src/contexts/PaymentsExtensionProvider.tsx +0 -56
- package/src/contexts/README.md +0 -201
- package/src/contexts/RootPaymentsContext.tsx +0 -66
- package/src/layouts/PaymentsLayout/PaymentsLayout.tsx +0 -90
- package/src/layouts/PaymentsLayout/components/CreatePaymentDialog.tsx +0 -274
- package/src/layouts/PaymentsLayout/components/PaymentDetailsDialog.tsx +0 -287
- package/src/layouts/PaymentsLayout/components/index.ts +0 -2
- package/src/layouts/PaymentsLayout/events.ts +0 -47
- package/src/layouts/PaymentsLayout/index.ts +0 -16
- package/src/layouts/PaymentsLayout/types.ts +0 -6
- package/src/layouts/PaymentsLayout/views/overview/components/BalanceCard.tsx +0 -121
- package/src/layouts/PaymentsLayout/views/overview/components/RecentPayments.tsx +0 -139
- package/src/layouts/PaymentsLayout/views/overview/components/index.ts +0 -2
- package/src/layouts/PaymentsLayout/views/overview/index.tsx +0 -21
- package/src/layouts/PaymentsLayout/views/payments/components/PaymentsList.tsx +0 -279
- package/src/layouts/PaymentsLayout/views/payments/components/index.ts +0 -1
- package/src/layouts/PaymentsLayout/views/payments/index.tsx +0 -18
- package/src/layouts/PaymentsLayout/views/transactions/components/TransactionsList.tsx +0 -260
- package/src/layouts/PaymentsLayout/views/transactions/components/index.ts +0 -1
- package/src/layouts/PaymentsLayout/views/transactions/index.tsx +0 -18
package/dist/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
+
import { createContext, useState, useMemo, useCallback, useEffect, useContext, useRef } from 'react';
|
|
2
|
+
import { initializeExtensionAPI, createExtensionAPI } from '@djangocfg/ext-base/api';
|
|
1
3
|
import { createConsola, consola } from 'consola';
|
|
2
4
|
import pRetry, { AbortError } from 'p-retry';
|
|
3
5
|
import { z } from 'zod';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import
|
|
6
|
+
import useSWR, { useSWRConfig } from 'swr';
|
|
7
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
8
|
+
import { Plus, ArrowUpRight, RefreshCw, AlertCircle, XCircle, CheckCircle2, Loader2, Clock, ArrowDownLeft, History, ChevronRight, Ban, ExternalLink } from 'lucide-react';
|
|
9
|
+
import { Skeleton, Button, TokenIcon, useLocalStorage, ResponsiveSheet, ResponsiveSheetContent, ResponsiveSheetHeader, ResponsiveSheetTitle, ResponsiveSheetDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormMessage, Alert, AlertDescription, CopyButton, Combobox } from '@djangocfg/ui-core';
|
|
10
|
+
import { cn } from '@djangocfg/ui-core/lib';
|
|
11
|
+
import moment3 from 'moment';
|
|
10
12
|
import { useForm } from 'react-hook-form';
|
|
11
13
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
12
|
-
import moment from 'moment';
|
|
13
|
-
import { useDRFPagination, StaticPagination } from '@djangocfg/ui-nextjs/components';
|
|
14
14
|
import { createExtensionConfig } from '@djangocfg/ext-base';
|
|
15
15
|
|
|
16
16
|
var __defProp = Object.defineProperty;
|
|
@@ -37,12 +37,47 @@ var ExtPaymentsPayments = class {
|
|
|
37
37
|
/**
|
|
38
38
|
* Get available currencies
|
|
39
39
|
*
|
|
40
|
-
* Returns list of available currencies with token+network info
|
|
40
|
+
* Returns list of available currencies with token+network info, popular
|
|
41
|
+
* first
|
|
41
42
|
*/
|
|
42
43
|
async currenciesList() {
|
|
43
44
|
const response = await this.client.request("GET", "/cfg/payments/currencies/");
|
|
44
45
|
return response;
|
|
45
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Get currency estimate
|
|
49
|
+
*
|
|
50
|
+
* Get estimated crypto amount for a given USD amount, including min amount
|
|
51
|
+
*/
|
|
52
|
+
async currenciesEstimateRetrieve(...args) {
|
|
53
|
+
const code = args[0];
|
|
54
|
+
const isParamsObject = args.length === 2 && typeof args[1] === "object" && args[1] !== null && !Array.isArray(args[1]);
|
|
55
|
+
let params;
|
|
56
|
+
if (isParamsObject) {
|
|
57
|
+
params = args[1];
|
|
58
|
+
} else {
|
|
59
|
+
params = { amount: args[1] };
|
|
60
|
+
}
|
|
61
|
+
const response = await this.client.request("GET", `/cfg/payments/currencies/${code}/estimate/`, { params });
|
|
62
|
+
return response;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get withdrawal estimate
|
|
66
|
+
*
|
|
67
|
+
* Get estimated crypto amount for withdrawal with fee breakdown
|
|
68
|
+
*/
|
|
69
|
+
async currenciesWithdrawalEstimateRetrieve(...args) {
|
|
70
|
+
const code = args[0];
|
|
71
|
+
const isParamsObject = args.length === 2 && typeof args[1] === "object" && args[1] !== null && !Array.isArray(args[1]);
|
|
72
|
+
let params;
|
|
73
|
+
if (isParamsObject) {
|
|
74
|
+
params = args[1];
|
|
75
|
+
} else {
|
|
76
|
+
params = { amount: args[1] };
|
|
77
|
+
}
|
|
78
|
+
const response = await this.client.request("GET", `/cfg/payments/currencies/${code}/withdrawal-estimate/`, { params });
|
|
79
|
+
return response;
|
|
80
|
+
}
|
|
46
81
|
/**
|
|
47
82
|
* ViewSet for payment operations. Endpoints: - GET /payments/ - List
|
|
48
83
|
* user's payments - GET /payments/{id}/ - Get payment details - POST
|
|
@@ -89,12 +124,12 @@ var ExtPaymentsPayments = class {
|
|
|
89
124
|
return response.results || response;
|
|
90
125
|
}
|
|
91
126
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
127
|
+
* Create payment
|
|
128
|
+
*
|
|
129
|
+
* Create a new payment with specified amount and currency
|
|
95
130
|
*/
|
|
96
|
-
async paymentsCreateCreate() {
|
|
97
|
-
const response = await this.client.request("POST", "/cfg/payments/payments/create/");
|
|
131
|
+
async paymentsCreateCreate(data) {
|
|
132
|
+
const response = await this.client.request("POST", "/cfg/payments/payments/create/", { body: data });
|
|
98
133
|
return response;
|
|
99
134
|
}
|
|
100
135
|
/**
|
|
@@ -113,6 +148,51 @@ var ExtPaymentsPayments = class {
|
|
|
113
148
|
const response = await this.client.request("GET", "/cfg/payments/transactions/", { params });
|
|
114
149
|
return response;
|
|
115
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* ViewSet for withdrawal operations. Endpoints: - GET /withdrawals/ - List
|
|
153
|
+
* user's withdrawal requests - GET /withdrawals/{id}/ - Get withdrawal
|
|
154
|
+
* details - POST /withdrawals/create/ - Create withdrawal request - POST
|
|
155
|
+
* /withdrawals/{id}/cancel/ - Cancel pending withdrawal
|
|
156
|
+
*/
|
|
157
|
+
async withdrawalsList(...args) {
|
|
158
|
+
const isParamsObject = args.length === 1 && typeof args[0] === "object" && args[0] !== null && !Array.isArray(args[0]);
|
|
159
|
+
let params;
|
|
160
|
+
if (isParamsObject) {
|
|
161
|
+
params = args[0];
|
|
162
|
+
} else {
|
|
163
|
+
params = { page: args[0], page_size: args[1] };
|
|
164
|
+
}
|
|
165
|
+
const response = await this.client.request("GET", "/cfg/payments/withdrawals/", { params });
|
|
166
|
+
return response;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* ViewSet for withdrawal operations. Endpoints: - GET /withdrawals/ - List
|
|
170
|
+
* user's withdrawal requests - GET /withdrawals/{id}/ - Get withdrawal
|
|
171
|
+
* details - POST /withdrawals/create/ - Create withdrawal request - POST
|
|
172
|
+
* /withdrawals/{id}/cancel/ - Cancel pending withdrawal
|
|
173
|
+
*/
|
|
174
|
+
async withdrawalsRetrieve(id) {
|
|
175
|
+
const response = await this.client.request("GET", `/cfg/payments/withdrawals/${id}/`);
|
|
176
|
+
return response;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Cancel withdrawal request
|
|
180
|
+
*
|
|
181
|
+
* Cancel a pending withdrawal request
|
|
182
|
+
*/
|
|
183
|
+
async withdrawalsCancelCreate(id) {
|
|
184
|
+
const response = await this.client.request("POST", `/cfg/payments/withdrawals/${id}/cancel/`);
|
|
185
|
+
return response;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Create withdrawal request
|
|
189
|
+
*
|
|
190
|
+
* Create a new withdrawal request (requires admin approval)
|
|
191
|
+
*/
|
|
192
|
+
async withdrawalsCreateCreate(data) {
|
|
193
|
+
const response = await this.client.request("POST", "/cfg/payments/withdrawals/create/", { body: data });
|
|
194
|
+
return response;
|
|
195
|
+
}
|
|
116
196
|
};
|
|
117
197
|
|
|
118
198
|
// src/api/generated/ext_payments/ext_payments__payments/models.ts
|
|
@@ -791,7 +871,9 @@ var enums_exports = {};
|
|
|
791
871
|
__export(enums_exports, {
|
|
792
872
|
PaymentDetailStatus: () => PaymentDetailStatus,
|
|
793
873
|
PaymentListStatus: () => PaymentListStatus,
|
|
794
|
-
TransactionTransactionType: () => TransactionTransactionType
|
|
874
|
+
TransactionTransactionType: () => TransactionTransactionType,
|
|
875
|
+
WithdrawalDetailStatus: () => WithdrawalDetailStatus,
|
|
876
|
+
WithdrawalListStatus: () => WithdrawalListStatus
|
|
795
877
|
});
|
|
796
878
|
var PaymentDetailStatus = /* @__PURE__ */ ((PaymentDetailStatus2) => {
|
|
797
879
|
PaymentDetailStatus2["PENDING"] = "pending";
|
|
@@ -825,6 +907,24 @@ var TransactionTransactionType = /* @__PURE__ */ ((TransactionTransactionType2)
|
|
|
825
907
|
TransactionTransactionType2["ADJUSTMENT"] = "adjustment";
|
|
826
908
|
return TransactionTransactionType2;
|
|
827
909
|
})(TransactionTransactionType || {});
|
|
910
|
+
var WithdrawalDetailStatus = /* @__PURE__ */ ((WithdrawalDetailStatus2) => {
|
|
911
|
+
WithdrawalDetailStatus2["PENDING"] = "pending";
|
|
912
|
+
WithdrawalDetailStatus2["APPROVED"] = "approved";
|
|
913
|
+
WithdrawalDetailStatus2["PROCESSING"] = "processing";
|
|
914
|
+
WithdrawalDetailStatus2["COMPLETED"] = "completed";
|
|
915
|
+
WithdrawalDetailStatus2["REJECTED"] = "rejected";
|
|
916
|
+
WithdrawalDetailStatus2["CANCELLED"] = "cancelled";
|
|
917
|
+
return WithdrawalDetailStatus2;
|
|
918
|
+
})(WithdrawalDetailStatus || {});
|
|
919
|
+
var WithdrawalListStatus = /* @__PURE__ */ ((WithdrawalListStatus2) => {
|
|
920
|
+
WithdrawalListStatus2["PENDING"] = "pending";
|
|
921
|
+
WithdrawalListStatus2["APPROVED"] = "approved";
|
|
922
|
+
WithdrawalListStatus2["PROCESSING"] = "processing";
|
|
923
|
+
WithdrawalListStatus2["COMPLETED"] = "completed";
|
|
924
|
+
WithdrawalListStatus2["REJECTED"] = "rejected";
|
|
925
|
+
WithdrawalListStatus2["CANCELLED"] = "cancelled";
|
|
926
|
+
return WithdrawalListStatus2;
|
|
927
|
+
})(WithdrawalListStatus || {});
|
|
828
928
|
|
|
829
929
|
// src/api/generated/ext_payments/_utils/schemas/index.ts
|
|
830
930
|
var schemas_exports = {};
|
|
@@ -832,16 +932,24 @@ __export(schemas_exports, {
|
|
|
832
932
|
BalanceSchema: () => BalanceSchema,
|
|
833
933
|
CurrencySchema: () => CurrencySchema,
|
|
834
934
|
PaginatedPaymentListListSchema: () => PaginatedPaymentListListSchema,
|
|
935
|
+
PaginatedWithdrawalListListSchema: () => PaginatedWithdrawalListListSchema,
|
|
936
|
+
PaymentCreateRequestSchema: () => PaymentCreateRequestSchema,
|
|
937
|
+
PaymentCreateResponseSchema: () => PaymentCreateResponseSchema,
|
|
835
938
|
PaymentDetailSchema: () => PaymentDetailSchema,
|
|
836
939
|
PaymentListSchema: () => PaymentListSchema,
|
|
837
|
-
TransactionSchema: () => TransactionSchema
|
|
940
|
+
TransactionSchema: () => TransactionSchema,
|
|
941
|
+
WithdrawalCancelResponseSchema: () => WithdrawalCancelResponseSchema,
|
|
942
|
+
WithdrawalCreateRequestSchema: () => WithdrawalCreateRequestSchema,
|
|
943
|
+
WithdrawalCreateResponseSchema: () => WithdrawalCreateResponseSchema,
|
|
944
|
+
WithdrawalDetailSchema: () => WithdrawalDetailSchema,
|
|
945
|
+
WithdrawalListSchema: () => WithdrawalListSchema
|
|
838
946
|
});
|
|
839
947
|
var BalanceSchema = z.object({
|
|
840
948
|
balance_usd: z.string(),
|
|
841
949
|
balance_display: z.string(),
|
|
842
950
|
total_deposited: z.string(),
|
|
843
951
|
total_withdrawn: z.string(),
|
|
844
|
-
last_transaction_at: z.
|
|
952
|
+
last_transaction_at: z.string().datetime({ offset: true }).nullable()
|
|
845
953
|
});
|
|
846
954
|
var CurrencySchema = z.object({
|
|
847
955
|
code: z.string(),
|
|
@@ -863,8 +971,8 @@ var PaymentListSchema = z.object({
|
|
|
863
971
|
currency_token: z.string(),
|
|
864
972
|
status: z.nativeEnum(PaymentListStatus),
|
|
865
973
|
status_display: z.string(),
|
|
866
|
-
created_at: z.
|
|
867
|
-
completed_at: z.
|
|
974
|
+
created_at: z.string().datetime({ offset: true }),
|
|
975
|
+
completed_at: z.string().datetime({ offset: true }).nullable()
|
|
868
976
|
});
|
|
869
977
|
|
|
870
978
|
// src/api/generated/ext_payments/_utils/schemas/PaginatedPaymentListList.schema.ts
|
|
@@ -879,6 +987,36 @@ var PaginatedPaymentListListSchema = z.object({
|
|
|
879
987
|
previous_page: z.int().nullable().optional(),
|
|
880
988
|
results: z.array(PaymentListSchema)
|
|
881
989
|
});
|
|
990
|
+
var WithdrawalListSchema = z.object({
|
|
991
|
+
id: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
|
|
992
|
+
internal_withdrawal_id: z.string(),
|
|
993
|
+
amount_usd: z.string(),
|
|
994
|
+
final_amount_usd: z.string(),
|
|
995
|
+
currency_code: z.string(),
|
|
996
|
+
currency_token: z.string(),
|
|
997
|
+
status: z.nativeEnum(WithdrawalListStatus),
|
|
998
|
+
status_display: z.string(),
|
|
999
|
+
created_at: z.string().datetime({ offset: true }),
|
|
1000
|
+
completed_at: z.string().datetime({ offset: true }).nullable()
|
|
1001
|
+
});
|
|
1002
|
+
|
|
1003
|
+
// src/api/generated/ext_payments/_utils/schemas/PaginatedWithdrawalListList.schema.ts
|
|
1004
|
+
var PaginatedWithdrawalListListSchema = z.object({
|
|
1005
|
+
count: z.int(),
|
|
1006
|
+
page: z.int(),
|
|
1007
|
+
pages: z.int(),
|
|
1008
|
+
page_size: z.int(),
|
|
1009
|
+
has_next: z.boolean(),
|
|
1010
|
+
has_previous: z.boolean(),
|
|
1011
|
+
next_page: z.int().nullable().optional(),
|
|
1012
|
+
previous_page: z.int().nullable().optional(),
|
|
1013
|
+
results: z.array(WithdrawalListSchema)
|
|
1014
|
+
});
|
|
1015
|
+
var PaymentCreateRequestSchema = z.object({
|
|
1016
|
+
amount_usd: z.string(),
|
|
1017
|
+
currency_code: z.string().min(1).max(20),
|
|
1018
|
+
description: z.string().max(500).optional()
|
|
1019
|
+
});
|
|
882
1020
|
var PaymentDetailSchema = z.object({
|
|
883
1021
|
id: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
|
|
884
1022
|
internal_payment_id: z.string(),
|
|
@@ -898,14 +1036,21 @@ var PaymentDetailSchema = z.object({
|
|
|
898
1036
|
transaction_hash: z.string().nullable(),
|
|
899
1037
|
explorer_link: z.string().nullable(),
|
|
900
1038
|
confirmations_count: z.int(),
|
|
901
|
-
expires_at: z.
|
|
902
|
-
completed_at: z.
|
|
903
|
-
created_at: z.
|
|
1039
|
+
expires_at: z.string().datetime({ offset: true }).nullable(),
|
|
1040
|
+
completed_at: z.string().datetime({ offset: true }).nullable(),
|
|
1041
|
+
created_at: z.string().datetime({ offset: true }),
|
|
904
1042
|
is_completed: z.boolean(),
|
|
905
1043
|
is_failed: z.boolean(),
|
|
906
1044
|
is_expired: z.boolean(),
|
|
907
1045
|
description: z.string()
|
|
908
1046
|
});
|
|
1047
|
+
|
|
1048
|
+
// src/api/generated/ext_payments/_utils/schemas/PaymentCreateResponse.schema.ts
|
|
1049
|
+
var PaymentCreateResponseSchema = z.object({
|
|
1050
|
+
success: z.boolean(),
|
|
1051
|
+
payment: PaymentDetailSchema,
|
|
1052
|
+
qr_code_url: z.union([z.url(), z.literal("")]).nullable()
|
|
1053
|
+
});
|
|
909
1054
|
var TransactionSchema = z.object({
|
|
910
1055
|
id: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
|
|
911
1056
|
transaction_type: z.nativeEnum(TransactionTransactionType),
|
|
@@ -915,7 +1060,49 @@ var TransactionSchema = z.object({
|
|
|
915
1060
|
balance_after: z.string(),
|
|
916
1061
|
payment_id: z.string().nullable(),
|
|
917
1062
|
description: z.string(),
|
|
918
|
-
created_at: z.
|
|
1063
|
+
created_at: z.string().datetime({ offset: true })
|
|
1064
|
+
});
|
|
1065
|
+
var WithdrawalDetailSchema = z.object({
|
|
1066
|
+
id: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
|
|
1067
|
+
internal_withdrawal_id: z.string(),
|
|
1068
|
+
amount_usd: z.string(),
|
|
1069
|
+
currency_code: z.string(),
|
|
1070
|
+
currency_name: z.string(),
|
|
1071
|
+
currency_token: z.string(),
|
|
1072
|
+
currency_network: z.string(),
|
|
1073
|
+
wallet_address: z.string(),
|
|
1074
|
+
network_fee_usd: z.string(),
|
|
1075
|
+
service_fee_usd: z.string(),
|
|
1076
|
+
total_fee_usd: z.string(),
|
|
1077
|
+
final_amount_usd: z.string(),
|
|
1078
|
+
crypto_amount: z.string().nullable(),
|
|
1079
|
+
status: z.nativeEnum(WithdrawalDetailStatus),
|
|
1080
|
+
status_display: z.string(),
|
|
1081
|
+
transaction_hash: z.string().nullable(),
|
|
1082
|
+
explorer_link: z.string().nullable(),
|
|
1083
|
+
admin_notes: z.string(),
|
|
1084
|
+
created_at: z.string().datetime({ offset: true }),
|
|
1085
|
+
approved_at: z.string().datetime({ offset: true }).nullable(),
|
|
1086
|
+
completed_at: z.string().datetime({ offset: true }).nullable(),
|
|
1087
|
+
rejected_at: z.string().datetime({ offset: true }).nullable(),
|
|
1088
|
+
cancelled_at: z.string().datetime({ offset: true }).nullable()
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
// src/api/generated/ext_payments/_utils/schemas/WithdrawalCancelResponse.schema.ts
|
|
1092
|
+
var WithdrawalCancelResponseSchema = z.object({
|
|
1093
|
+
success: z.boolean(),
|
|
1094
|
+
withdrawal: WithdrawalDetailSchema,
|
|
1095
|
+
message: z.string()
|
|
1096
|
+
});
|
|
1097
|
+
var WithdrawalCreateRequestSchema = z.object({
|
|
1098
|
+
amount_usd: z.string(),
|
|
1099
|
+
currency_code: z.string().min(1).max(20),
|
|
1100
|
+
wallet_address: z.string().min(1).max(255)
|
|
1101
|
+
});
|
|
1102
|
+
var WithdrawalCreateResponseSchema = z.object({
|
|
1103
|
+
success: z.boolean(),
|
|
1104
|
+
withdrawal: WithdrawalDetailSchema,
|
|
1105
|
+
message: z.string()
|
|
919
1106
|
});
|
|
920
1107
|
|
|
921
1108
|
// src/api/generated/ext_payments/validation-events.ts
|
|
@@ -969,12 +1156,18 @@ var fetchers_exports = {};
|
|
|
969
1156
|
__export(fetchers_exports, {
|
|
970
1157
|
createPaymentsPaymentsConfirmCreate: () => createPaymentsPaymentsConfirmCreate,
|
|
971
1158
|
createPaymentsPaymentsCreateCreate: () => createPaymentsPaymentsCreateCreate,
|
|
1159
|
+
createPaymentsWithdrawalsCancelCreate: () => createPaymentsWithdrawalsCancelCreate,
|
|
1160
|
+
createPaymentsWithdrawalsCreateCreate: () => createPaymentsWithdrawalsCreateCreate,
|
|
972
1161
|
getPaymentsBalanceRetrieve: () => getPaymentsBalanceRetrieve,
|
|
1162
|
+
getPaymentsCurrenciesEstimateRetrieve: () => getPaymentsCurrenciesEstimateRetrieve,
|
|
973
1163
|
getPaymentsCurrenciesList: () => getPaymentsCurrenciesList,
|
|
1164
|
+
getPaymentsCurrenciesWithdrawalEstimateRetrieve: () => getPaymentsCurrenciesWithdrawalEstimateRetrieve,
|
|
974
1165
|
getPaymentsPaymentsList: () => getPaymentsPaymentsList,
|
|
975
1166
|
getPaymentsPaymentsRetrieve: () => getPaymentsPaymentsRetrieve,
|
|
976
1167
|
getPaymentsPaymentsStatusRetrieve: () => getPaymentsPaymentsStatusRetrieve,
|
|
977
|
-
getPaymentsTransactionsList: () => getPaymentsTransactionsList
|
|
1168
|
+
getPaymentsTransactionsList: () => getPaymentsTransactionsList,
|
|
1169
|
+
getPaymentsWithdrawalsList: () => getPaymentsWithdrawalsList,
|
|
1170
|
+
getPaymentsWithdrawalsRetrieve: () => getPaymentsWithdrawalsRetrieve
|
|
978
1171
|
});
|
|
979
1172
|
|
|
980
1173
|
// src/api/generated/ext_payments/api-instance.ts
|
|
@@ -1079,6 +1272,16 @@ async function getPaymentsCurrenciesList(client) {
|
|
|
1079
1272
|
const response = await api.ext_payments_payments.currenciesList();
|
|
1080
1273
|
return response;
|
|
1081
1274
|
}
|
|
1275
|
+
async function getPaymentsCurrenciesEstimateRetrieve(code, params, client) {
|
|
1276
|
+
const api = client || getAPIInstance();
|
|
1277
|
+
const response = await api.ext_payments_payments.currenciesEstimateRetrieve(code, params?.amount);
|
|
1278
|
+
return response;
|
|
1279
|
+
}
|
|
1280
|
+
async function getPaymentsCurrenciesWithdrawalEstimateRetrieve(code, params, client) {
|
|
1281
|
+
const api = client || getAPIInstance();
|
|
1282
|
+
const response = await api.ext_payments_payments.currenciesWithdrawalEstimateRetrieve(code, params?.amount);
|
|
1283
|
+
return response;
|
|
1284
|
+
}
|
|
1082
1285
|
async function getPaymentsPaymentsList(params, client) {
|
|
1083
1286
|
const api = client || getAPIInstance();
|
|
1084
1287
|
const response = await api.ext_payments_payments.paymentsList(params?.page, params?.page_size);
|
|
@@ -1247,11 +1450,11 @@ Method: GET`);
|
|
|
1247
1450
|
throw error;
|
|
1248
1451
|
}
|
|
1249
1452
|
}
|
|
1250
|
-
async function createPaymentsPaymentsCreateCreate(client) {
|
|
1453
|
+
async function createPaymentsPaymentsCreateCreate(data, client) {
|
|
1251
1454
|
const api = client || getAPIInstance();
|
|
1252
|
-
const response = await api.ext_payments_payments.paymentsCreateCreate();
|
|
1455
|
+
const response = await api.ext_payments_payments.paymentsCreateCreate(data);
|
|
1253
1456
|
try {
|
|
1254
|
-
return
|
|
1457
|
+
return PaymentCreateResponseSchema.parse(response);
|
|
1255
1458
|
} catch (error) {
|
|
1256
1459
|
consola.error("\u274C Zod Validation Failed");
|
|
1257
1460
|
consola.box(`createPaymentsPaymentsCreateCreate
|
|
@@ -1294,6 +1497,174 @@ async function getPaymentsTransactionsList(params, client) {
|
|
|
1294
1497
|
const response = await api.ext_payments_payments.transactionsList(params?.limit, params?.offset, params?.type);
|
|
1295
1498
|
return response;
|
|
1296
1499
|
}
|
|
1500
|
+
async function getPaymentsWithdrawalsList(params, client) {
|
|
1501
|
+
const api = client || getAPIInstance();
|
|
1502
|
+
const response = await api.ext_payments_payments.withdrawalsList(params?.page, params?.page_size);
|
|
1503
|
+
try {
|
|
1504
|
+
return PaginatedWithdrawalListListSchema.parse(response);
|
|
1505
|
+
} catch (error) {
|
|
1506
|
+
consola.error("\u274C Zod Validation Failed");
|
|
1507
|
+
consola.box(`getPaymentsWithdrawalsList
|
|
1508
|
+
Path: /cfg/payments/withdrawals/
|
|
1509
|
+
Method: GET`);
|
|
1510
|
+
if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
|
|
1511
|
+
consola.error("Validation Issues:");
|
|
1512
|
+
error.issues.forEach((issue, index) => {
|
|
1513
|
+
consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
|
|
1514
|
+
consola.error(` \u251C\u2500 Message: ${issue.message}`);
|
|
1515
|
+
if (issue.expected) consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
|
|
1516
|
+
if (issue.received) consola.error(` \u2514\u2500 Received: ${issue.received}`);
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
consola.error("Response data:", response);
|
|
1520
|
+
if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
|
|
1521
|
+
try {
|
|
1522
|
+
const event = new CustomEvent("zod-validation-error", {
|
|
1523
|
+
detail: {
|
|
1524
|
+
operation: "getPaymentsWithdrawalsList",
|
|
1525
|
+
path: "/cfg/payments/withdrawals/",
|
|
1526
|
+
method: "GET",
|
|
1527
|
+
error,
|
|
1528
|
+
response,
|
|
1529
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
1530
|
+
},
|
|
1531
|
+
bubbles: true,
|
|
1532
|
+
cancelable: false
|
|
1533
|
+
});
|
|
1534
|
+
window.dispatchEvent(event);
|
|
1535
|
+
} catch (eventError) {
|
|
1536
|
+
consola.warn("Failed to dispatch validation error event:", eventError);
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
throw error;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
async function getPaymentsWithdrawalsRetrieve(id, client) {
|
|
1543
|
+
const api = client || getAPIInstance();
|
|
1544
|
+
const response = await api.ext_payments_payments.withdrawalsRetrieve(id);
|
|
1545
|
+
try {
|
|
1546
|
+
return WithdrawalDetailSchema.parse(response);
|
|
1547
|
+
} catch (error) {
|
|
1548
|
+
consola.error("\u274C Zod Validation Failed");
|
|
1549
|
+
consola.box(`getPaymentsWithdrawalsRetrieve
|
|
1550
|
+
Path: /cfg/payments/withdrawals/{id}/
|
|
1551
|
+
Method: GET`);
|
|
1552
|
+
if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
|
|
1553
|
+
consola.error("Validation Issues:");
|
|
1554
|
+
error.issues.forEach((issue, index) => {
|
|
1555
|
+
consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
|
|
1556
|
+
consola.error(` \u251C\u2500 Message: ${issue.message}`);
|
|
1557
|
+
if (issue.expected) consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
|
|
1558
|
+
if (issue.received) consola.error(` \u2514\u2500 Received: ${issue.received}`);
|
|
1559
|
+
});
|
|
1560
|
+
}
|
|
1561
|
+
consola.error("Response data:", response);
|
|
1562
|
+
if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
|
|
1563
|
+
try {
|
|
1564
|
+
const event = new CustomEvent("zod-validation-error", {
|
|
1565
|
+
detail: {
|
|
1566
|
+
operation: "getPaymentsWithdrawalsRetrieve",
|
|
1567
|
+
path: "/cfg/payments/withdrawals/{id}/",
|
|
1568
|
+
method: "GET",
|
|
1569
|
+
error,
|
|
1570
|
+
response,
|
|
1571
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
1572
|
+
},
|
|
1573
|
+
bubbles: true,
|
|
1574
|
+
cancelable: false
|
|
1575
|
+
});
|
|
1576
|
+
window.dispatchEvent(event);
|
|
1577
|
+
} catch (eventError) {
|
|
1578
|
+
consola.warn("Failed to dispatch validation error event:", eventError);
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
throw error;
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
async function createPaymentsWithdrawalsCancelCreate(id, client) {
|
|
1585
|
+
const api = client || getAPIInstance();
|
|
1586
|
+
const response = await api.ext_payments_payments.withdrawalsCancelCreate(id);
|
|
1587
|
+
try {
|
|
1588
|
+
return WithdrawalCancelResponseSchema.parse(response);
|
|
1589
|
+
} catch (error) {
|
|
1590
|
+
consola.error("\u274C Zod Validation Failed");
|
|
1591
|
+
consola.box(`createPaymentsWithdrawalsCancelCreate
|
|
1592
|
+
Path: /cfg/payments/withdrawals/{id}/cancel/
|
|
1593
|
+
Method: POST`);
|
|
1594
|
+
if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
|
|
1595
|
+
consola.error("Validation Issues:");
|
|
1596
|
+
error.issues.forEach((issue, index) => {
|
|
1597
|
+
consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
|
|
1598
|
+
consola.error(` \u251C\u2500 Message: ${issue.message}`);
|
|
1599
|
+
if (issue.expected) consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
|
|
1600
|
+
if (issue.received) consola.error(` \u2514\u2500 Received: ${issue.received}`);
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
consola.error("Response data:", response);
|
|
1604
|
+
if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
|
|
1605
|
+
try {
|
|
1606
|
+
const event = new CustomEvent("zod-validation-error", {
|
|
1607
|
+
detail: {
|
|
1608
|
+
operation: "createPaymentsWithdrawalsCancelCreate",
|
|
1609
|
+
path: "/cfg/payments/withdrawals/{id}/cancel/",
|
|
1610
|
+
method: "POST",
|
|
1611
|
+
error,
|
|
1612
|
+
response,
|
|
1613
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
1614
|
+
},
|
|
1615
|
+
bubbles: true,
|
|
1616
|
+
cancelable: false
|
|
1617
|
+
});
|
|
1618
|
+
window.dispatchEvent(event);
|
|
1619
|
+
} catch (eventError) {
|
|
1620
|
+
consola.warn("Failed to dispatch validation error event:", eventError);
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
throw error;
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
async function createPaymentsWithdrawalsCreateCreate(data, client) {
|
|
1627
|
+
const api = client || getAPIInstance();
|
|
1628
|
+
const response = await api.ext_payments_payments.withdrawalsCreateCreate(data);
|
|
1629
|
+
try {
|
|
1630
|
+
return WithdrawalCreateResponseSchema.parse(response);
|
|
1631
|
+
} catch (error) {
|
|
1632
|
+
consola.error("\u274C Zod Validation Failed");
|
|
1633
|
+
consola.box(`createPaymentsWithdrawalsCreateCreate
|
|
1634
|
+
Path: /cfg/payments/withdrawals/create/
|
|
1635
|
+
Method: POST`);
|
|
1636
|
+
if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
|
|
1637
|
+
consola.error("Validation Issues:");
|
|
1638
|
+
error.issues.forEach((issue, index) => {
|
|
1639
|
+
consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
|
|
1640
|
+
consola.error(` \u251C\u2500 Message: ${issue.message}`);
|
|
1641
|
+
if (issue.expected) consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
|
|
1642
|
+
if (issue.received) consola.error(` \u2514\u2500 Received: ${issue.received}`);
|
|
1643
|
+
});
|
|
1644
|
+
}
|
|
1645
|
+
consola.error("Response data:", response);
|
|
1646
|
+
if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
|
|
1647
|
+
try {
|
|
1648
|
+
const event = new CustomEvent("zod-validation-error", {
|
|
1649
|
+
detail: {
|
|
1650
|
+
operation: "createPaymentsWithdrawalsCreateCreate",
|
|
1651
|
+
path: "/cfg/payments/withdrawals/create/",
|
|
1652
|
+
method: "POST",
|
|
1653
|
+
error,
|
|
1654
|
+
response,
|
|
1655
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
1656
|
+
},
|
|
1657
|
+
bubbles: true,
|
|
1658
|
+
cancelable: false
|
|
1659
|
+
});
|
|
1660
|
+
window.dispatchEvent(event);
|
|
1661
|
+
} catch (eventError) {
|
|
1662
|
+
consola.warn("Failed to dispatch validation error event:", eventError);
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
throw error;
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1297
1668
|
|
|
1298
1669
|
// src/api/generated/ext_payments/index.ts
|
|
1299
1670
|
var TOKEN_KEY = "auth_token";
|
|
@@ -1420,6 +1791,8 @@ var API = class {
|
|
|
1420
1791
|
return "./schema.json";
|
|
1421
1792
|
}
|
|
1422
1793
|
};
|
|
1794
|
+
|
|
1795
|
+
// src/api/index.ts
|
|
1423
1796
|
initializeExtensionAPI(configureAPI);
|
|
1424
1797
|
var apiPayments = createExtensionAPI(API);
|
|
1425
1798
|
function usePaymentsBalanceRetrieve(client) {
|
|
@@ -1440,24 +1813,10 @@ function usePaymentsPaymentsList(params, client) {
|
|
|
1440
1813
|
() => getPaymentsPaymentsList(params, client)
|
|
1441
1814
|
);
|
|
1442
1815
|
}
|
|
1443
|
-
function usePaymentsPaymentsRetrieve(id, client) {
|
|
1444
|
-
return useSWR(
|
|
1445
|
-
["cfg-payments-payment", id],
|
|
1446
|
-
() => getPaymentsPaymentsRetrieve(id, client)
|
|
1447
|
-
);
|
|
1448
|
-
}
|
|
1449
|
-
function useCreatePaymentsPaymentsConfirmCreate() {
|
|
1450
|
-
const { mutate } = useSWRConfig();
|
|
1451
|
-
return async (id, client) => {
|
|
1452
|
-
const result = await createPaymentsPaymentsConfirmCreate(id, client);
|
|
1453
|
-
mutate("cfg-payments-payments-confirm");
|
|
1454
|
-
return result;
|
|
1455
|
-
};
|
|
1456
|
-
}
|
|
1457
1816
|
function useCreatePaymentsPaymentsCreateCreate() {
|
|
1458
1817
|
const { mutate } = useSWRConfig();
|
|
1459
|
-
return async (client) => {
|
|
1460
|
-
const result = await createPaymentsPaymentsCreateCreate(client);
|
|
1818
|
+
return async (data, client) => {
|
|
1819
|
+
const result = await createPaymentsPaymentsCreateCreate(data, client);
|
|
1461
1820
|
mutate("cfg-payments-payments");
|
|
1462
1821
|
return result;
|
|
1463
1822
|
};
|
|
@@ -1468,287 +1827,1001 @@ function usePaymentsTransactionsList(params, client) {
|
|
|
1468
1827
|
() => getPaymentsTransactionsList(params, client)
|
|
1469
1828
|
);
|
|
1470
1829
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
await
|
|
1481
|
-
|
|
1482
|
-
const createPaymentMutation = useCreatePaymentsPaymentsCreateCreate();
|
|
1483
|
-
const confirmPaymentMutation = useCreatePaymentsPaymentsConfirmCreate();
|
|
1484
|
-
const getPayment = async (id) => {
|
|
1485
|
-
return getPaymentsPaymentsRetrieve(id, apiPayments);
|
|
1486
|
-
};
|
|
1487
|
-
const createPayment = async () => {
|
|
1488
|
-
const result = await createPaymentMutation(apiPayments);
|
|
1489
|
-
await refreshPayments();
|
|
1830
|
+
function usePaymentsWithdrawalsList(params, client) {
|
|
1831
|
+
return useSWR(
|
|
1832
|
+
params ? ["cfg-payments-withdrawals", params] : "cfg-payments-withdrawals",
|
|
1833
|
+
() => getPaymentsWithdrawalsList(params, client)
|
|
1834
|
+
);
|
|
1835
|
+
}
|
|
1836
|
+
function useCreatePaymentsWithdrawalsCancelCreate() {
|
|
1837
|
+
const { mutate } = useSWRConfig();
|
|
1838
|
+
return async (id, client) => {
|
|
1839
|
+
const result = await createPaymentsWithdrawalsCancelCreate(id, client);
|
|
1840
|
+
mutate("cfg-payments-withdrawals-cancel");
|
|
1490
1841
|
return result;
|
|
1491
1842
|
};
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1843
|
+
}
|
|
1844
|
+
function useCreatePaymentsWithdrawalsCreateCreate() {
|
|
1845
|
+
const { mutate } = useSWRConfig();
|
|
1846
|
+
return async (data, client) => {
|
|
1847
|
+
const result = await createPaymentsWithdrawalsCreateCreate(data, client);
|
|
1848
|
+
mutate("cfg-payments-withdrawals");
|
|
1495
1849
|
return result;
|
|
1496
1850
|
};
|
|
1497
|
-
const checkPaymentStatus = async (id) => {
|
|
1498
|
-
return getPaymentsPaymentsStatusRetrieve(id, apiPayments);
|
|
1499
|
-
};
|
|
1500
|
-
const value = {
|
|
1501
|
-
payments,
|
|
1502
|
-
isLoadingPayments,
|
|
1503
|
-
paymentsError,
|
|
1504
|
-
refreshPayments,
|
|
1505
|
-
getPayment,
|
|
1506
|
-
createPayment,
|
|
1507
|
-
confirmPayment,
|
|
1508
|
-
checkPaymentStatus
|
|
1509
|
-
};
|
|
1510
|
-
return /* @__PURE__ */ jsx(PaymentsContext.Provider, { value, children });
|
|
1511
1851
|
}
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
if (!context) {
|
|
1515
|
-
throw new Error("usePaymentsContext must be used within PaymentsProvider");
|
|
1516
|
-
}
|
|
1517
|
-
return context;
|
|
1518
|
-
}
|
|
1519
|
-
createContext(void 0);
|
|
1520
|
-
createContext(void 0);
|
|
1521
|
-
var OverviewContext = createContext(void 0);
|
|
1522
|
-
function OverviewProvider({ children }) {
|
|
1523
|
-
const swrConfig = {
|
|
1524
|
-
revalidateOnFocus: false,
|
|
1525
|
-
revalidateOnReconnect: false,
|
|
1526
|
-
revalidateIfStale: false
|
|
1527
|
-
};
|
|
1852
|
+
var WalletContext = createContext(void 0);
|
|
1853
|
+
function WalletProvider({ children }) {
|
|
1528
1854
|
const {
|
|
1529
1855
|
data: balance,
|
|
1530
|
-
error: balanceError,
|
|
1531
1856
|
isLoading: isLoadingBalance,
|
|
1532
1857
|
mutate: mutateBalance
|
|
1533
1858
|
} = usePaymentsBalanceRetrieve(apiPayments);
|
|
1534
1859
|
const {
|
|
1535
|
-
data:
|
|
1536
|
-
error: paymentsError,
|
|
1860
|
+
data: paymentsData,
|
|
1537
1861
|
isLoading: isLoadingPayments,
|
|
1538
1862
|
mutate: mutatePayments
|
|
1539
|
-
} = usePaymentsPaymentsList({}, apiPayments);
|
|
1863
|
+
} = usePaymentsPaymentsList({ page: 1, page_size: 20 }, apiPayments);
|
|
1540
1864
|
const {
|
|
1541
|
-
data:
|
|
1542
|
-
error: transactionsError,
|
|
1865
|
+
data: transactionsData,
|
|
1543
1866
|
isLoading: isLoadingTransactions,
|
|
1544
1867
|
mutate: mutateTransactions
|
|
1545
|
-
} = usePaymentsTransactionsList({}, apiPayments);
|
|
1868
|
+
} = usePaymentsTransactionsList({ limit: 20 }, apiPayments);
|
|
1869
|
+
const {
|
|
1870
|
+
data: currenciesData,
|
|
1871
|
+
isLoading: isLoadingCurrencies,
|
|
1872
|
+
mutate: mutateCurrencies
|
|
1873
|
+
} = usePaymentsCurrenciesList(apiPayments);
|
|
1874
|
+
const {
|
|
1875
|
+
data: withdrawalsData,
|
|
1876
|
+
isLoading: isLoadingWithdrawals,
|
|
1877
|
+
mutate: mutateWithdrawals
|
|
1878
|
+
} = usePaymentsWithdrawalsList({ page: 1, page_size: 20 }, apiPayments);
|
|
1546
1879
|
const createPaymentMutation = useCreatePaymentsPaymentsCreateCreate();
|
|
1547
|
-
const
|
|
1548
|
-
const
|
|
1549
|
-
const
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1880
|
+
const createWithdrawalMutation = useCreatePaymentsWithdrawalsCreateCreate();
|
|
1881
|
+
const cancelWithdrawalMutation = useCreatePaymentsWithdrawalsCancelCreate();
|
|
1882
|
+
const balanceAmount = useMemo(() => {
|
|
1883
|
+
if (!balance?.balance_usd) return 0;
|
|
1884
|
+
return parseFloat(balance.balance_usd) || 0;
|
|
1885
|
+
}, [balance]);
|
|
1886
|
+
const activity = useMemo(() => {
|
|
1887
|
+
const items = [];
|
|
1888
|
+
const payments = paymentsData?.results || [];
|
|
1889
|
+
for (const payment of payments) {
|
|
1890
|
+
items.push({
|
|
1891
|
+
id: `payment-${payment.id}`,
|
|
1892
|
+
type: "payment",
|
|
1893
|
+
amount: payment.amount_usd,
|
|
1894
|
+
amountDisplay: `+$${parseFloat(payment.amount_usd).toFixed(2)}`,
|
|
1895
|
+
currency: payment.currency_code,
|
|
1896
|
+
status: mapPaymentStatus(payment.status),
|
|
1897
|
+
statusDisplay: payment.status_display,
|
|
1898
|
+
description: `${payment.currency_code} payment`,
|
|
1899
|
+
createdAt: payment.created_at,
|
|
1900
|
+
payment
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1903
|
+
const withdrawals = withdrawalsData?.results || [];
|
|
1904
|
+
for (const withdrawal of withdrawals) {
|
|
1905
|
+
items.push({
|
|
1906
|
+
id: `withdrawal-${withdrawal.id}`,
|
|
1907
|
+
type: "withdrawal",
|
|
1908
|
+
amount: withdrawal.amount_usd,
|
|
1909
|
+
amountDisplay: `-$${parseFloat(withdrawal.amount_usd).toFixed(2)}`,
|
|
1910
|
+
currency: withdrawal.currency_code,
|
|
1911
|
+
status: mapWithdrawalStatus(withdrawal.status),
|
|
1912
|
+
statusDisplay: withdrawal.status_display,
|
|
1913
|
+
description: `${withdrawal.currency_code} withdrawal`,
|
|
1914
|
+
createdAt: withdrawal.created_at,
|
|
1915
|
+
withdrawal
|
|
1916
|
+
});
|
|
1917
|
+
}
|
|
1918
|
+
const transactions = transactionsData?.results || transactionsData || [];
|
|
1919
|
+
if (Array.isArray(transactions)) {
|
|
1920
|
+
for (const tx of transactions) {
|
|
1921
|
+
if (tx.payment_id && payments.some((p) => p.id === tx.payment_id)) {
|
|
1922
|
+
continue;
|
|
1923
|
+
}
|
|
1924
|
+
const isDeposit = tx.transaction_type === "deposit";
|
|
1925
|
+
items.push({
|
|
1926
|
+
id: `tx-${tx.id}`,
|
|
1927
|
+
type: isDeposit ? "deposit" : "withdrawal",
|
|
1928
|
+
amount: tx.amount_usd,
|
|
1929
|
+
amountDisplay: `${isDeposit ? "+" : "-"}$${Math.abs(parseFloat(tx.amount_usd)).toFixed(2)}`,
|
|
1930
|
+
status: "completed",
|
|
1931
|
+
statusDisplay: "Completed",
|
|
1932
|
+
description: tx.description || tx.type_display,
|
|
1933
|
+
createdAt: tx.created_at,
|
|
1934
|
+
transaction: tx
|
|
1935
|
+
});
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
items.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
1939
|
+
return items;
|
|
1940
|
+
}, [paymentsData, withdrawalsData, transactionsData]);
|
|
1941
|
+
const currencies = useMemo(() => {
|
|
1942
|
+
const data = currenciesData?.currencies || currenciesData?.results || currenciesData || [];
|
|
1943
|
+
if (!Array.isArray(data)) return [];
|
|
1944
|
+
return data.filter((c) => c.is_enabled !== false).map((c) => ({
|
|
1945
|
+
code: c.code || c.currency_code || c.symbol,
|
|
1946
|
+
name: c.name || c.code,
|
|
1947
|
+
token: c.token || c.code,
|
|
1948
|
+
// Token symbol (e.g., USDT, WBTC) with fallback to code
|
|
1949
|
+
network: c.network || void 0,
|
|
1950
|
+
enabled: c.is_enabled !== false
|
|
1951
|
+
}));
|
|
1952
|
+
}, [currenciesData]);
|
|
1953
|
+
const addFunds = useCallback(async (data) => {
|
|
1954
|
+
const response = await createPaymentMutation(data, apiPayments);
|
|
1955
|
+
await Promise.all([mutateBalance(), mutatePayments(), mutateTransactions()]);
|
|
1956
|
+
return response.payment;
|
|
1957
|
+
}, [createPaymentMutation, mutateBalance, mutatePayments, mutateTransactions]);
|
|
1958
|
+
const withdraw = useCallback(async (data) => {
|
|
1959
|
+
const response = await createWithdrawalMutation(data, apiPayments);
|
|
1960
|
+
await Promise.all([mutateBalance(), mutateWithdrawals(), mutateTransactions()]);
|
|
1961
|
+
return response.withdrawal;
|
|
1962
|
+
}, [createWithdrawalMutation, mutateBalance, mutateWithdrawals, mutateTransactions]);
|
|
1963
|
+
const cancelWithdrawal = useCallback(async (id) => {
|
|
1964
|
+
await cancelWithdrawalMutation(id, apiPayments);
|
|
1965
|
+
await Promise.all([mutateBalance(), mutateWithdrawals(), mutateTransactions()]);
|
|
1966
|
+
}, [cancelWithdrawalMutation, mutateBalance, mutateWithdrawals, mutateTransactions]);
|
|
1967
|
+
const getPaymentDetails = useCallback(async (id) => {
|
|
1968
|
+
return apiPayments.ext_payments_payments.paymentsRetrieve(id);
|
|
1969
|
+
}, []);
|
|
1970
|
+
const getWithdrawalDetails = useCallback(async (id) => {
|
|
1971
|
+
return apiPayments.ext_payments_payments.withdrawalsRetrieve(id);
|
|
1972
|
+
}, []);
|
|
1973
|
+
const refreshWallet = useCallback(async () => {
|
|
1559
1974
|
await Promise.all([
|
|
1560
1975
|
mutateBalance(),
|
|
1561
1976
|
mutatePayments(),
|
|
1562
|
-
|
|
1977
|
+
mutateWithdrawals(),
|
|
1978
|
+
mutateTransactions(),
|
|
1979
|
+
mutateCurrencies()
|
|
1563
1980
|
]);
|
|
1564
|
-
};
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1567
|
-
await refreshOverview();
|
|
1568
|
-
return result;
|
|
1569
|
-
};
|
|
1981
|
+
}, [mutateBalance, mutatePayments, mutateWithdrawals, mutateTransactions, mutateCurrencies]);
|
|
1982
|
+
const isLoading = isLoadingBalance || isLoadingPayments || isLoadingWithdrawals || isLoadingTransactions;
|
|
1983
|
+
const isLoadingActivity = isLoadingPayments || isLoadingWithdrawals || isLoadingTransactions;
|
|
1570
1984
|
const value = {
|
|
1571
1985
|
balance,
|
|
1986
|
+
balanceAmount,
|
|
1572
1987
|
isLoadingBalance,
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
overviewError,
|
|
1586
|
-
refreshOverview
|
|
1988
|
+
activity,
|
|
1989
|
+
isLoadingActivity,
|
|
1990
|
+
hasMoreActivity: (paymentsData?.count || 0) > 20 || (withdrawalsData?.count || 0) > 20,
|
|
1991
|
+
currencies,
|
|
1992
|
+
isLoadingCurrencies,
|
|
1993
|
+
addFunds,
|
|
1994
|
+
withdraw,
|
|
1995
|
+
cancelWithdrawal,
|
|
1996
|
+
getPaymentDetails,
|
|
1997
|
+
getWithdrawalDetails,
|
|
1998
|
+
refreshWallet,
|
|
1999
|
+
isLoading
|
|
1587
2000
|
};
|
|
1588
|
-
return /* @__PURE__ */ jsx(
|
|
2001
|
+
return /* @__PURE__ */ jsx(WalletContext.Provider, { value, children });
|
|
1589
2002
|
}
|
|
1590
|
-
function
|
|
1591
|
-
const context = useContext(
|
|
2003
|
+
function useWallet() {
|
|
2004
|
+
const context = useContext(WalletContext);
|
|
1592
2005
|
if (!context) {
|
|
1593
|
-
throw new Error("
|
|
2006
|
+
throw new Error("useWallet must be used within WalletProvider");
|
|
1594
2007
|
}
|
|
1595
2008
|
return context;
|
|
1596
2009
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
2010
|
+
function mapPaymentStatus(status) {
|
|
2011
|
+
switch (status?.toLowerCase()) {
|
|
2012
|
+
case "completed":
|
|
2013
|
+
case "success":
|
|
2014
|
+
case "finished":
|
|
2015
|
+
return "completed";
|
|
2016
|
+
case "pending":
|
|
2017
|
+
case "waiting":
|
|
2018
|
+
return "pending";
|
|
2019
|
+
case "confirming":
|
|
2020
|
+
case "partially_paid":
|
|
2021
|
+
return "confirming";
|
|
2022
|
+
case "expired":
|
|
2023
|
+
return "expired";
|
|
2024
|
+
case "failed":
|
|
2025
|
+
case "error":
|
|
2026
|
+
case "cancelled":
|
|
2027
|
+
return "failed";
|
|
2028
|
+
default:
|
|
2029
|
+
return "pending";
|
|
2030
|
+
}
|
|
1615
2031
|
}
|
|
1616
|
-
function
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
2032
|
+
function mapWithdrawalStatus(status) {
|
|
2033
|
+
switch (status?.toLowerCase()) {
|
|
2034
|
+
case "completed":
|
|
2035
|
+
return "completed";
|
|
2036
|
+
case "pending":
|
|
2037
|
+
case "approved":
|
|
2038
|
+
return "pending";
|
|
2039
|
+
case "processing":
|
|
2040
|
+
return "confirming";
|
|
2041
|
+
case "rejected":
|
|
2042
|
+
case "cancelled":
|
|
2043
|
+
return "failed";
|
|
2044
|
+
default:
|
|
2045
|
+
return "pending";
|
|
1620
2046
|
}
|
|
1621
|
-
|
|
2047
|
+
}
|
|
2048
|
+
function BalanceHero({ onAddFunds, onWithdraw, className }) {
|
|
2049
|
+
const { balance, balanceAmount, isLoadingBalance, refreshWallet } = useWallet();
|
|
2050
|
+
const formattedBalance = new Intl.NumberFormat("en-US", {
|
|
2051
|
+
style: "currency",
|
|
2052
|
+
currency: "USD",
|
|
2053
|
+
minimumFractionDigits: 2,
|
|
2054
|
+
maximumFractionDigits: 2
|
|
2055
|
+
}).format(balanceAmount);
|
|
2056
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-center py-16 px-4", className), children: [
|
|
2057
|
+
/* @__PURE__ */ jsx("div", { className: "text-center mb-6", children: isLoadingBalance ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2058
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-12 w-48 mx-auto mb-2" }),
|
|
2059
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-24 mx-auto" })
|
|
2060
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2061
|
+
/* @__PURE__ */ jsx("h1", { className: "text-5xl font-bold tracking-tight tabular-nums", children: formattedBalance }),
|
|
2062
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1", children: "Available Balance" })
|
|
2063
|
+
] }) }),
|
|
2064
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
2065
|
+
/* @__PURE__ */ jsxs(
|
|
2066
|
+
Button,
|
|
2067
|
+
{
|
|
2068
|
+
size: "lg",
|
|
2069
|
+
onClick: onAddFunds,
|
|
2070
|
+
className: "rounded-full px-6",
|
|
2071
|
+
children: [
|
|
2072
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-5 w-5 mr-2" }),
|
|
2073
|
+
"Add Funds"
|
|
2074
|
+
]
|
|
2075
|
+
}
|
|
2076
|
+
),
|
|
2077
|
+
/* @__PURE__ */ jsxs(
|
|
2078
|
+
Button,
|
|
2079
|
+
{
|
|
2080
|
+
size: "lg",
|
|
2081
|
+
variant: "outline",
|
|
2082
|
+
onClick: onWithdraw,
|
|
2083
|
+
className: "rounded-full px-6",
|
|
2084
|
+
children: [
|
|
2085
|
+
/* @__PURE__ */ jsx(ArrowUpRight, { className: "h-5 w-5 mr-2" }),
|
|
2086
|
+
"Withdraw"
|
|
2087
|
+
]
|
|
2088
|
+
}
|
|
2089
|
+
),
|
|
2090
|
+
/* @__PURE__ */ jsx(
|
|
2091
|
+
Button,
|
|
2092
|
+
{
|
|
2093
|
+
size: "icon",
|
|
2094
|
+
variant: "ghost",
|
|
2095
|
+
onClick: () => refreshWallet(),
|
|
2096
|
+
className: "rounded-full",
|
|
2097
|
+
children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" })
|
|
2098
|
+
}
|
|
2099
|
+
)
|
|
2100
|
+
] }),
|
|
2101
|
+
balance && !isLoadingBalance && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-6 mt-6 text-sm text-muted-foreground", children: [
|
|
2102
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
2103
|
+
/* @__PURE__ */ jsxs("span", { className: "block font-medium text-foreground", children: [
|
|
2104
|
+
"$",
|
|
2105
|
+
parseFloat(balance.total_deposited || "0").toFixed(2)
|
|
2106
|
+
] }),
|
|
2107
|
+
/* @__PURE__ */ jsx("span", { children: "Total Deposited" })
|
|
2108
|
+
] }),
|
|
2109
|
+
/* @__PURE__ */ jsx("div", { className: "h-8 w-px bg-border" }),
|
|
2110
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
2111
|
+
/* @__PURE__ */ jsxs("span", { className: "block font-medium text-foreground", children: [
|
|
2112
|
+
"$",
|
|
2113
|
+
parseFloat(balance.total_withdrawn || "0").toFixed(2)
|
|
2114
|
+
] }),
|
|
2115
|
+
/* @__PURE__ */ jsx("span", { children: "Total Withdrawn" })
|
|
2116
|
+
] })
|
|
2117
|
+
] })
|
|
2118
|
+
] });
|
|
2119
|
+
}
|
|
2120
|
+
var statusConfig = {
|
|
2121
|
+
pending: {
|
|
2122
|
+
icon: Clock,
|
|
2123
|
+
color: "text-yellow-500",
|
|
2124
|
+
bg: "bg-yellow-500/10"
|
|
2125
|
+
},
|
|
2126
|
+
confirming: {
|
|
2127
|
+
icon: Loader2,
|
|
2128
|
+
color: "text-blue-500",
|
|
2129
|
+
bg: "bg-blue-500/10",
|
|
2130
|
+
animate: true
|
|
2131
|
+
},
|
|
2132
|
+
completed: {
|
|
2133
|
+
icon: CheckCircle2,
|
|
2134
|
+
color: "text-green-500",
|
|
2135
|
+
bg: "bg-green-500/10"
|
|
2136
|
+
},
|
|
2137
|
+
failed: {
|
|
2138
|
+
icon: XCircle,
|
|
2139
|
+
color: "text-red-500",
|
|
2140
|
+
bg: "bg-red-500/10"
|
|
2141
|
+
},
|
|
2142
|
+
expired: {
|
|
2143
|
+
icon: AlertCircle,
|
|
2144
|
+
color: "text-muted-foreground",
|
|
2145
|
+
bg: "bg-muted"
|
|
2146
|
+
}
|
|
2147
|
+
};
|
|
2148
|
+
function ActivityItem({ item, onClick }) {
|
|
2149
|
+
const config = statusConfig[item.status];
|
|
2150
|
+
const StatusIcon = config.icon;
|
|
2151
|
+
const isPositive = item.type === "payment" || item.type === "deposit";
|
|
2152
|
+
const DirectionIcon = isPositive ? ArrowDownLeft : ArrowUpRight;
|
|
2153
|
+
const relativeTime = moment3(item.createdAt).fromNow();
|
|
2154
|
+
return /* @__PURE__ */ jsxs(
|
|
2155
|
+
"button",
|
|
2156
|
+
{
|
|
2157
|
+
onClick,
|
|
2158
|
+
className: cn(
|
|
2159
|
+
"w-full flex items-center gap-4 p-4 rounded-xl",
|
|
2160
|
+
"cursor-pointer",
|
|
2161
|
+
"hover:bg-accent active:bg-accent/80 transition-colors",
|
|
2162
|
+
"text-left"
|
|
2163
|
+
),
|
|
2164
|
+
children: [
|
|
2165
|
+
/* @__PURE__ */ jsx("div", { className: cn(
|
|
2166
|
+
"flex items-center justify-center w-10 h-10 rounded-full",
|
|
2167
|
+
isPositive ? "bg-green-500/10" : "bg-red-500/10"
|
|
2168
|
+
), children: item.currency ? /* @__PURE__ */ jsx(TokenIcon, { symbol: item.currency, size: 24 }) : /* @__PURE__ */ jsx(DirectionIcon, { className: cn(
|
|
2169
|
+
"h-5 w-5",
|
|
2170
|
+
isPositive ? "text-green-500" : "text-red-500"
|
|
2171
|
+
) }) }),
|
|
2172
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2173
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx("span", { className: "font-medium truncate", children: item.description }) }),
|
|
2174
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
2175
|
+
/* @__PURE__ */ jsx("span", { children: relativeTime }),
|
|
2176
|
+
item.status !== "completed" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2177
|
+
/* @__PURE__ */ jsx("span", { children: "\xB7" }),
|
|
2178
|
+
/* @__PURE__ */ jsxs("span", { className: cn("flex items-center gap-1", config.color), children: [
|
|
2179
|
+
/* @__PURE__ */ jsx(StatusIcon, { className: cn("h-3 w-3", config.animate && "animate-spin") }),
|
|
2180
|
+
item.statusDisplay
|
|
2181
|
+
] })
|
|
2182
|
+
] })
|
|
2183
|
+
] })
|
|
2184
|
+
] }),
|
|
2185
|
+
/* @__PURE__ */ jsxs("div", { className: "text-right", children: [
|
|
2186
|
+
/* @__PURE__ */ jsx("span", { className: cn(
|
|
2187
|
+
"font-semibold tabular-nums",
|
|
2188
|
+
isPositive ? "text-green-600 dark:text-green-400" : "text-foreground"
|
|
2189
|
+
), children: item.amountDisplay }),
|
|
2190
|
+
item.status === "completed" && /* @__PURE__ */ jsx(CheckCircle2, { className: "h-4 w-4 text-green-500 ml-2 inline-block" })
|
|
2191
|
+
] })
|
|
2192
|
+
]
|
|
2193
|
+
}
|
|
2194
|
+
);
|
|
2195
|
+
}
|
|
2196
|
+
function ActivityList({
|
|
2197
|
+
onItemClick,
|
|
2198
|
+
onViewAll,
|
|
2199
|
+
limit = 10,
|
|
2200
|
+
className
|
|
2201
|
+
}) {
|
|
2202
|
+
const { activity, isLoadingActivity, hasMoreActivity } = useWallet();
|
|
2203
|
+
const displayedActivity = limit ? activity.slice(0, limit) : activity;
|
|
2204
|
+
if (isLoadingActivity) {
|
|
2205
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
|
|
2206
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between px-4 py-2", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-32" }) }),
|
|
2207
|
+
[1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 p-4", children: [
|
|
2208
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-10 rounded-full" }),
|
|
2209
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2", children: [
|
|
2210
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" }),
|
|
2211
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
|
|
2212
|
+
] }),
|
|
2213
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-16" })
|
|
2214
|
+
] }, i))
|
|
2215
|
+
] });
|
|
2216
|
+
}
|
|
2217
|
+
if (activity.length === 0) {
|
|
2218
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("text-center py-12", className), children: [
|
|
2219
|
+
/* @__PURE__ */ jsx("div", { className: "inline-flex items-center justify-center w-16 h-16 rounded-full bg-muted mb-4", children: /* @__PURE__ */ jsx(History, { className: "h-8 w-8 text-muted-foreground" }) }),
|
|
2220
|
+
/* @__PURE__ */ jsx("h3", { className: "font-semibold mb-1", children: "No Activity Yet" }),
|
|
2221
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Your transactions will appear here" })
|
|
2222
|
+
] });
|
|
2223
|
+
}
|
|
2224
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("pt-6", className), children: [
|
|
2225
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2", children: [
|
|
2226
|
+
/* @__PURE__ */ jsx("h2", { className: "font-semibold text-lg", children: "Recent Activity" }),
|
|
2227
|
+
hasMoreActivity && onViewAll && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: onViewAll, className: "text-primary", children: [
|
|
2228
|
+
"View All",
|
|
2229
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 ml-1" })
|
|
2230
|
+
] })
|
|
2231
|
+
] }),
|
|
2232
|
+
/* @__PURE__ */ jsx("div", { className: "divide-y divide-border/50", children: displayedActivity.map((item) => /* @__PURE__ */ jsx(
|
|
2233
|
+
ActivityItem,
|
|
2234
|
+
{
|
|
2235
|
+
item,
|
|
2236
|
+
onClick: () => onItemClick?.(item)
|
|
2237
|
+
},
|
|
2238
|
+
item.id
|
|
2239
|
+
)) })
|
|
2240
|
+
] });
|
|
2241
|
+
}
|
|
2242
|
+
function useEstimate({
|
|
2243
|
+
currencyCode,
|
|
2244
|
+
amountUsd,
|
|
2245
|
+
minAmount = 0,
|
|
2246
|
+
debounceMs = 300,
|
|
2247
|
+
skip = false
|
|
2248
|
+
}) {
|
|
2249
|
+
const [estimate, setEstimate] = useState(null);
|
|
2250
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
2251
|
+
const [error, setError] = useState(null);
|
|
2252
|
+
useEffect(() => {
|
|
2253
|
+
if (skip || !currencyCode || amountUsd < minAmount) {
|
|
2254
|
+
setEstimate(null);
|
|
2255
|
+
setError(null);
|
|
2256
|
+
return;
|
|
2257
|
+
}
|
|
2258
|
+
const fetchEstimate = async () => {
|
|
2259
|
+
setIsLoading(true);
|
|
2260
|
+
setError(null);
|
|
2261
|
+
try {
|
|
2262
|
+
const response = await apiPayments.ext_payments_payments.currenciesEstimateRetrieve(
|
|
2263
|
+
currencyCode,
|
|
2264
|
+
{ amount: amountUsd }
|
|
2265
|
+
);
|
|
2266
|
+
if (response?.success && response?.estimated_amount) {
|
|
2267
|
+
setEstimate({
|
|
2268
|
+
estimatedAmount: parseFloat(response.estimated_amount),
|
|
2269
|
+
usdRate: parseFloat(response.usd_rate) || 0,
|
|
2270
|
+
minAmountUsd: response.min_amount_usd ? parseFloat(response.min_amount_usd) : null,
|
|
2271
|
+
isStablecoin: response.is_stablecoin || false,
|
|
2272
|
+
// New fee fields
|
|
2273
|
+
amountToReceive: parseFloat(response.amount_to_receive) || amountUsd,
|
|
2274
|
+
serviceFeeUsd: parseFloat(response.service_fee_usd) || 0,
|
|
2275
|
+
serviceFeePercent: parseFloat(response.service_fee_percent) || 0,
|
|
2276
|
+
totalToPayUsd: parseFloat(response.total_to_pay_usd) || amountUsd
|
|
2277
|
+
});
|
|
2278
|
+
} else {
|
|
2279
|
+
setEstimate(null);
|
|
2280
|
+
}
|
|
2281
|
+
} catch (err) {
|
|
2282
|
+
console.error("Failed to fetch estimate:", err);
|
|
2283
|
+
setEstimate(null);
|
|
2284
|
+
setError(err instanceof Error ? err : new Error("Failed to fetch estimate"));
|
|
2285
|
+
} finally {
|
|
2286
|
+
setIsLoading(false);
|
|
2287
|
+
}
|
|
2288
|
+
};
|
|
2289
|
+
const timeoutId = setTimeout(fetchEstimate, debounceMs);
|
|
2290
|
+
return () => clearTimeout(timeoutId);
|
|
2291
|
+
}, [currencyCode, amountUsd, minAmount, debounceMs, skip]);
|
|
2292
|
+
return { estimate, isLoading, error };
|
|
2293
|
+
}
|
|
2294
|
+
function useWithdrawalEstimate({
|
|
2295
|
+
currencyCode,
|
|
2296
|
+
amountUsd,
|
|
2297
|
+
minAmount = 10,
|
|
2298
|
+
debounceMs = 300,
|
|
2299
|
+
skip = false
|
|
2300
|
+
}) {
|
|
2301
|
+
const [estimate, setEstimate] = useState(null);
|
|
2302
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
2303
|
+
const [error, setError] = useState(null);
|
|
2304
|
+
useEffect(() => {
|
|
2305
|
+
if (skip || !currencyCode || amountUsd < minAmount) {
|
|
2306
|
+
setEstimate(null);
|
|
2307
|
+
setError(null);
|
|
2308
|
+
return;
|
|
2309
|
+
}
|
|
2310
|
+
const fetchEstimate = async () => {
|
|
2311
|
+
setIsLoading(true);
|
|
2312
|
+
setError(null);
|
|
2313
|
+
try {
|
|
2314
|
+
const response = await apiPayments.ext_payments_payments.currenciesWithdrawalEstimateRetrieve(
|
|
2315
|
+
currencyCode,
|
|
2316
|
+
{ amount: amountUsd }
|
|
2317
|
+
);
|
|
2318
|
+
if (response?.success && response?.estimated_amount) {
|
|
2319
|
+
setEstimate({
|
|
2320
|
+
estimatedAmount: parseFloat(response.estimated_amount),
|
|
2321
|
+
usdRate: parseFloat(response.usd_rate) || 0,
|
|
2322
|
+
minAmountUsd: response.min_amount_usd ? parseFloat(response.min_amount_usd) : null,
|
|
2323
|
+
isStablecoin: response.is_stablecoin || false,
|
|
2324
|
+
// Withdrawal-specific fields
|
|
2325
|
+
amountRequested: parseFloat(response.amount_requested) || amountUsd,
|
|
2326
|
+
serviceFeeUsd: parseFloat(response.service_fee_usd) || 0,
|
|
2327
|
+
serviceFeePercent: parseFloat(response.service_fee_percent) || 0,
|
|
2328
|
+
networkFeeUsd: parseFloat(response.network_fee_usd) || 0,
|
|
2329
|
+
totalFeesUsd: parseFloat(response.total_fees_usd) || 0,
|
|
2330
|
+
amountToReceive: parseFloat(response.amount_to_receive) || 0
|
|
2331
|
+
});
|
|
2332
|
+
} else {
|
|
2333
|
+
setEstimate(null);
|
|
2334
|
+
}
|
|
2335
|
+
} catch (err) {
|
|
2336
|
+
console.error("Failed to fetch withdrawal estimate:", err);
|
|
2337
|
+
setEstimate(null);
|
|
2338
|
+
setError(err instanceof Error ? err : new Error("Failed to fetch withdrawal estimate"));
|
|
2339
|
+
} finally {
|
|
2340
|
+
setIsLoading(false);
|
|
2341
|
+
}
|
|
2342
|
+
};
|
|
2343
|
+
const timeoutId = setTimeout(fetchEstimate, debounceMs);
|
|
2344
|
+
return () => clearTimeout(timeoutId);
|
|
2345
|
+
}, [currencyCode, amountUsd, minAmount, debounceMs, skip]);
|
|
2346
|
+
return { estimate, isLoading, error };
|
|
2347
|
+
}
|
|
2348
|
+
function useCurrencyOptions(currencies) {
|
|
2349
|
+
return useMemo(() => {
|
|
2350
|
+
return currencies.map((c) => ({
|
|
2351
|
+
value: c.code,
|
|
2352
|
+
label: c.name,
|
|
2353
|
+
token: c.token,
|
|
2354
|
+
network: c.network
|
|
2355
|
+
}));
|
|
2356
|
+
}, [currencies]);
|
|
2357
|
+
}
|
|
2358
|
+
function useDefaultCurrency({
|
|
2359
|
+
currencyOptions,
|
|
2360
|
+
savedCurrency,
|
|
2361
|
+
currentValue,
|
|
2362
|
+
setValue
|
|
2363
|
+
}) {
|
|
2364
|
+
useEffect(() => {
|
|
2365
|
+
if (currencyOptions.length > 0 && !currentValue) {
|
|
2366
|
+
const savedOption = savedCurrency && currencyOptions.find((c) => c.value === savedCurrency);
|
|
2367
|
+
if (savedOption) {
|
|
2368
|
+
setValue(savedOption.value);
|
|
2369
|
+
} else {
|
|
2370
|
+
const usdt = currencyOptions.find((c) => c.value.includes("USDT"));
|
|
2371
|
+
setValue(usdt?.value || currencyOptions[0].value);
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
}, [currencyOptions, savedCurrency, currentValue, setValue]);
|
|
2375
|
+
}
|
|
2376
|
+
function useAutoSave(value, save, validate) {
|
|
2377
|
+
const saveRef = useRef(save);
|
|
2378
|
+
const validateRef = useRef(validate);
|
|
2379
|
+
useEffect(() => {
|
|
2380
|
+
saveRef.current = save;
|
|
2381
|
+
validateRef.current = validate;
|
|
2382
|
+
});
|
|
2383
|
+
useEffect(() => {
|
|
2384
|
+
const isValid = validateRef.current ? validateRef.current(value) : Boolean(value);
|
|
2385
|
+
if (isValid) {
|
|
2386
|
+
saveRef.current(value);
|
|
2387
|
+
}
|
|
2388
|
+
}, [value]);
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
// src/utils/format.ts
|
|
2392
|
+
function formatUsdRate(rate) {
|
|
2393
|
+
if (rate >= 1) {
|
|
2394
|
+
return rate.toLocaleString(void 0, {
|
|
2395
|
+
minimumFractionDigits: 2,
|
|
2396
|
+
maximumFractionDigits: 2
|
|
2397
|
+
});
|
|
2398
|
+
} else if (rate >= 0.01) {
|
|
2399
|
+
return rate.toLocaleString(void 0, {
|
|
2400
|
+
minimumFractionDigits: 2,
|
|
2401
|
+
maximumFractionDigits: 4
|
|
2402
|
+
});
|
|
2403
|
+
} else if (rate >= 1e-4) {
|
|
2404
|
+
return rate.toLocaleString(void 0, {
|
|
2405
|
+
minimumFractionDigits: 4,
|
|
2406
|
+
maximumFractionDigits: 6
|
|
2407
|
+
});
|
|
2408
|
+
} else {
|
|
2409
|
+
return rate.toLocaleString(void 0, {
|
|
2410
|
+
minimumFractionDigits: 6,
|
|
2411
|
+
maximumFractionDigits: 8
|
|
2412
|
+
});
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
function formatCryptoAmount(amount, isStablecoin) {
|
|
2416
|
+
const decimals = isStablecoin ? 2 : 8;
|
|
2417
|
+
return amount.toFixed(decimals);
|
|
2418
|
+
}
|
|
2419
|
+
function formatUsdAmount(amount, alwaysShowCents = false) {
|
|
2420
|
+
if (alwaysShowCents) {
|
|
2421
|
+
return amount.toFixed(2);
|
|
2422
|
+
}
|
|
2423
|
+
const hasCents = amount % 1 !== 0;
|
|
2424
|
+
if (hasCents) {
|
|
2425
|
+
return amount.toFixed(2);
|
|
2426
|
+
}
|
|
2427
|
+
return amount.toFixed(0);
|
|
2428
|
+
}
|
|
2429
|
+
|
|
2430
|
+
// src/utils/errors.ts
|
|
2431
|
+
function extractErrorMessage(err, fallback = "An error occurred") {
|
|
2432
|
+
if (!err) return fallback;
|
|
2433
|
+
const error = err;
|
|
2434
|
+
const responseData = error.response?.data;
|
|
2435
|
+
const response = responseData || error.response;
|
|
2436
|
+
if (response) {
|
|
2437
|
+
if (typeof response.error === "string") return response.error;
|
|
2438
|
+
if (typeof response.message === "string") return response.message;
|
|
2439
|
+
if (typeof response.detail === "string") return response.detail;
|
|
2440
|
+
}
|
|
2441
|
+
if (typeof error.errorMessage === "string") return error.errorMessage;
|
|
2442
|
+
if (typeof error.message === "string") return error.message;
|
|
2443
|
+
return fallback;
|
|
1622
2444
|
}
|
|
1623
2445
|
var isDevelopment = process.env.NODE_ENV === "development";
|
|
1624
|
-
|
|
2446
|
+
createConsola({
|
|
1625
2447
|
level: isDevelopment ? 4 : 1
|
|
1626
2448
|
}).withTag("ext-payments");
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
2449
|
+
function CurrencyCombobox({
|
|
2450
|
+
options,
|
|
2451
|
+
value,
|
|
2452
|
+
onChange,
|
|
2453
|
+
disabled,
|
|
2454
|
+
placeholder = "Select currency..."
|
|
2455
|
+
}) {
|
|
2456
|
+
return /* @__PURE__ */ jsx(
|
|
2457
|
+
Combobox,
|
|
2458
|
+
{
|
|
2459
|
+
options,
|
|
2460
|
+
value,
|
|
2461
|
+
onValueChange: onChange,
|
|
2462
|
+
placeholder,
|
|
2463
|
+
searchPlaceholder: "Search...",
|
|
2464
|
+
disabled,
|
|
2465
|
+
className: "h-14",
|
|
2466
|
+
renderOption: (option) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 flex-1", children: [
|
|
2467
|
+
/* @__PURE__ */ jsx(TokenIcon, { symbol: option.value, size: 24 }),
|
|
2468
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: option.label })
|
|
2469
|
+
] }),
|
|
2470
|
+
renderValue: (option) => option && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
2471
|
+
/* @__PURE__ */ jsx(TokenIcon, { symbol: option.value, size: 24 }),
|
|
2472
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: option.label })
|
|
2473
|
+
] })
|
|
2474
|
+
}
|
|
1643
2475
|
);
|
|
1644
|
-
}
|
|
1645
|
-
var
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
var PaymentCreateSchema = z.object({
|
|
1649
|
-
amount_usd: z.number().min(0.01, "Amount must be at least $0.01"),
|
|
1650
|
-
currency_code: z.string().min(1, "Please select a currency")
|
|
2476
|
+
}
|
|
2477
|
+
var AddFundsSchema = z.object({
|
|
2478
|
+
amount: z.number().min(1, "Minimum $1"),
|
|
2479
|
+
currency: z.string().min(1, "Select a currency")
|
|
1651
2480
|
});
|
|
1652
|
-
var
|
|
1653
|
-
|
|
2481
|
+
var STORAGE_KEY = "payments:addFunds";
|
|
2482
|
+
function AddFundsSheet({ open, onOpenChange, onSuccess }) {
|
|
2483
|
+
const { currencies, isLoadingCurrencies, addFunds } = useWallet();
|
|
1654
2484
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
1655
|
-
const
|
|
1656
|
-
const
|
|
2485
|
+
const [error, setError] = useState(null);
|
|
2486
|
+
const [saved, setSaved] = useLocalStorage(STORAGE_KEY, {
|
|
2487
|
+
currency: "",
|
|
2488
|
+
amount: 100
|
|
2489
|
+
});
|
|
1657
2490
|
const form = useForm({
|
|
1658
|
-
resolver: zodResolver(
|
|
2491
|
+
resolver: zodResolver(AddFundsSchema),
|
|
1659
2492
|
defaultValues: {
|
|
1660
|
-
|
|
1661
|
-
|
|
2493
|
+
amount: saved.amount,
|
|
2494
|
+
currency: saved.currency
|
|
1662
2495
|
}
|
|
1663
2496
|
});
|
|
1664
|
-
const
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
const currencyOptions =
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
const
|
|
2497
|
+
const watchedAmount = form.watch("amount");
|
|
2498
|
+
const watchedCurrency = form.watch("currency");
|
|
2499
|
+
useAutoSave(watchedAmount, (v) => setSaved((prev) => ({ ...prev, amount: v })), (v) => v > 0);
|
|
2500
|
+
useAutoSave(watchedCurrency, (v) => setSaved((prev) => ({ ...prev, currency: v })));
|
|
2501
|
+
const currencyOptions = useCurrencyOptions(currencies);
|
|
2502
|
+
useDefaultCurrency({
|
|
2503
|
+
currencyOptions,
|
|
2504
|
+
savedCurrency: saved.currency,
|
|
2505
|
+
currentValue: watchedCurrency,
|
|
2506
|
+
setValue: (v) => form.setValue("currency", v)
|
|
2507
|
+
});
|
|
2508
|
+
const { estimate, isLoading: isLoadingEstimate } = useEstimate({
|
|
2509
|
+
currencyCode: watchedCurrency,
|
|
2510
|
+
amountUsd: watchedAmount,
|
|
2511
|
+
minAmount: 1
|
|
2512
|
+
});
|
|
2513
|
+
const selectedCurrency = currencyOptions.find((c) => c.value === watchedCurrency);
|
|
2514
|
+
const displayData = useMemo(() => {
|
|
2515
|
+
if (!selectedCurrency || !estimate) return null;
|
|
2516
|
+
const token = selectedCurrency.token;
|
|
2517
|
+
const cryptoAmount = formatCryptoAmount(estimate.estimatedAmount, estimate.isStablecoin);
|
|
2518
|
+
const rate = formatUsdRate(estimate.usdRate);
|
|
2519
|
+
const belowMinimum = estimate.minAmountUsd ? watchedAmount < estimate.minAmountUsd : false;
|
|
2520
|
+
const minAmount = estimate.minAmountUsd ? formatUsdAmount(estimate.minAmountUsd) : void 0;
|
|
1684
2521
|
return {
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
rate
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
return () => {
|
|
1697
|
-
window.removeEventListener(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG, handleOpen);
|
|
1698
|
-
window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
|
|
2522
|
+
token,
|
|
2523
|
+
cryptoAmount,
|
|
2524
|
+
rate,
|
|
2525
|
+
showRate: !estimate.isStablecoin && estimate.usdRate > 0,
|
|
2526
|
+
belowMinimum,
|
|
2527
|
+
minAmount,
|
|
2528
|
+
// Fee breakdown from API
|
|
2529
|
+
amountToReceive: estimate.amountToReceive,
|
|
2530
|
+
serviceFeeUsd: estimate.serviceFeeUsd,
|
|
2531
|
+
serviceFeePercent: estimate.serviceFeePercent,
|
|
2532
|
+
totalToPayUsd: estimate.totalToPayUsd
|
|
1699
2533
|
};
|
|
1700
|
-
}, []);
|
|
1701
|
-
const
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
2534
|
+
}, [selectedCurrency, estimate, watchedAmount]);
|
|
2535
|
+
const handleSubmit = useCallback(async (data) => {
|
|
2536
|
+
try {
|
|
2537
|
+
setIsSubmitting(true);
|
|
2538
|
+
setError(null);
|
|
2539
|
+
const result = await addFunds({
|
|
2540
|
+
amount_usd: String(data.amount),
|
|
2541
|
+
currency_code: data.currency
|
|
2542
|
+
});
|
|
2543
|
+
form.reset();
|
|
2544
|
+
onOpenChange(false);
|
|
2545
|
+
onSuccess?.(result);
|
|
2546
|
+
} catch (err) {
|
|
2547
|
+
setError(extractErrorMessage(err, "Failed to create payment"));
|
|
2548
|
+
} finally {
|
|
2549
|
+
setIsSubmitting(false);
|
|
2550
|
+
}
|
|
2551
|
+
}, [addFunds, form, onOpenChange, onSuccess]);
|
|
2552
|
+
const handleOpenChange = useCallback((open2) => {
|
|
2553
|
+
if (open2) {
|
|
2554
|
+
form.reset({
|
|
2555
|
+
amount: saved.amount,
|
|
2556
|
+
currency: saved.currency
|
|
2557
|
+
});
|
|
2558
|
+
} else {
|
|
2559
|
+
setError(null);
|
|
2560
|
+
}
|
|
2561
|
+
onOpenChange(open2);
|
|
2562
|
+
}, [form, onOpenChange, saved]);
|
|
2563
|
+
return /* @__PURE__ */ jsx(ResponsiveSheet, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs(ResponsiveSheetContent, { className: "sm:max-w-md", children: [
|
|
2564
|
+
/* @__PURE__ */ jsxs(ResponsiveSheetHeader, { children: [
|
|
2565
|
+
/* @__PURE__ */ jsx(ResponsiveSheetTitle, { children: "Add Funds" }),
|
|
2566
|
+
/* @__PURE__ */ jsx(ResponsiveSheetDescription, { children: "Add funds to your wallet using cryptocurrency" })
|
|
2567
|
+
] }),
|
|
2568
|
+
/* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-6 p-4 sm:p-0 sm:mt-4", children: [
|
|
2569
|
+
/* @__PURE__ */ jsx(
|
|
2570
|
+
FormField,
|
|
2571
|
+
{
|
|
2572
|
+
control: form.control,
|
|
2573
|
+
name: "amount",
|
|
2574
|
+
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
2575
|
+
/* @__PURE__ */ jsx(FormLabel, { children: "Amount (USD)" }),
|
|
2576
|
+
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
2577
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-muted-foreground text-lg", children: "$" }),
|
|
2578
|
+
/* @__PURE__ */ jsx(
|
|
2579
|
+
Input,
|
|
2580
|
+
{
|
|
2581
|
+
type: "number",
|
|
2582
|
+
step: "0.01",
|
|
2583
|
+
min: "1",
|
|
2584
|
+
placeholder: "100",
|
|
2585
|
+
className: "pl-8 text-2xl h-14 font-semibold",
|
|
2586
|
+
...field,
|
|
2587
|
+
onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
|
|
2588
|
+
}
|
|
2589
|
+
)
|
|
2590
|
+
] }) }),
|
|
2591
|
+
/* @__PURE__ */ jsx(FormMessage, {})
|
|
2592
|
+
] })
|
|
2593
|
+
}
|
|
2594
|
+
),
|
|
2595
|
+
/* @__PURE__ */ jsx(
|
|
2596
|
+
FormField,
|
|
2597
|
+
{
|
|
2598
|
+
control: form.control,
|
|
2599
|
+
name: "currency",
|
|
2600
|
+
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
2601
|
+
/* @__PURE__ */ jsx(FormLabel, { children: "Pay with" }),
|
|
2602
|
+
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
|
|
2603
|
+
CurrencyCombobox,
|
|
2604
|
+
{
|
|
2605
|
+
options: currencyOptions,
|
|
2606
|
+
value: field.value,
|
|
2607
|
+
onChange: field.onChange,
|
|
2608
|
+
disabled: isLoadingCurrencies
|
|
2609
|
+
}
|
|
2610
|
+
) }),
|
|
2611
|
+
/* @__PURE__ */ jsx(FormMessage, {})
|
|
2612
|
+
] })
|
|
2613
|
+
}
|
|
2614
|
+
),
|
|
2615
|
+
selectedCurrency && watchedAmount >= 1 && /* @__PURE__ */ jsx("div", { className: "bg-muted rounded-xl p-4 space-y-2", children: isLoadingEstimate ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center py-2", children: [
|
|
2616
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-5 w-5 animate-spin text-muted-foreground" }),
|
|
2617
|
+
/* @__PURE__ */ jsx("span", { className: "ml-2 text-sm text-muted-foreground", children: "Getting rate..." })
|
|
2618
|
+
] }) : displayData ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2619
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
2620
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Amount" }),
|
|
2621
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2622
|
+
"$",
|
|
2623
|
+
formatUsdAmount(displayData.amountToReceive)
|
|
2624
|
+
] })
|
|
2625
|
+
] }),
|
|
2626
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
2627
|
+
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
2628
|
+
"Service fee (",
|
|
2629
|
+
displayData.serviceFeePercent,
|
|
2630
|
+
"%)"
|
|
2631
|
+
] }),
|
|
2632
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2633
|
+
"+$",
|
|
2634
|
+
formatUsdAmount(displayData.serviceFeeUsd)
|
|
2635
|
+
] })
|
|
2636
|
+
] }),
|
|
2637
|
+
displayData.showRate && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm text-muted-foreground", children: [
|
|
2638
|
+
/* @__PURE__ */ jsx("span", { children: "Rate" }),
|
|
2639
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2640
|
+
"1 ",
|
|
2641
|
+
displayData.token,
|
|
2642
|
+
" = $",
|
|
2643
|
+
displayData.rate
|
|
2644
|
+
] })
|
|
2645
|
+
] }),
|
|
2646
|
+
/* @__PURE__ */ jsx("div", { className: "border-t pt-2 mt-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2647
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "You will send" }),
|
|
2648
|
+
/* @__PURE__ */ jsxs("div", { className: "text-right", children: [
|
|
2649
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 justify-end", children: [
|
|
2650
|
+
/* @__PURE__ */ jsx(TokenIcon, { symbol: displayData.token, size: 20 }),
|
|
2651
|
+
/* @__PURE__ */ jsxs("span", { className: "font-mono font-semibold text-lg", children: [
|
|
2652
|
+
displayData.cryptoAmount,
|
|
2653
|
+
" ",
|
|
2654
|
+
displayData.token
|
|
2655
|
+
] })
|
|
2656
|
+
] }),
|
|
2657
|
+
/* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
|
|
2658
|
+
"~$",
|
|
2659
|
+
formatUsdAmount(displayData.totalToPayUsd)
|
|
2660
|
+
] })
|
|
2661
|
+
] })
|
|
2662
|
+
] }) }),
|
|
2663
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm pt-2", children: [
|
|
2664
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "You will receive" }),
|
|
2665
|
+
/* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
2666
|
+
"$",
|
|
2667
|
+
formatUsdAmount(displayData.amountToReceive)
|
|
2668
|
+
] })
|
|
2669
|
+
] }),
|
|
2670
|
+
displayData.belowMinimum && displayData.minAmount && /* @__PURE__ */ jsxs("div", { className: "text-sm text-destructive mt-2 pt-2 border-t border-destructive/20", children: [
|
|
2671
|
+
"Minimum amount: $",
|
|
2672
|
+
displayData.minAmount
|
|
2673
|
+
] })
|
|
2674
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "text-center text-sm text-muted-foreground py-2", children: "Enter amount to see conversion" }) }),
|
|
2675
|
+
error && /* @__PURE__ */ jsx(Alert, { variant: "destructive", children: /* @__PURE__ */ jsx(AlertDescription, { children: error }) }),
|
|
2676
|
+
/* @__PURE__ */ jsx(
|
|
2677
|
+
Button,
|
|
2678
|
+
{
|
|
2679
|
+
type: "submit",
|
|
2680
|
+
size: "lg",
|
|
2681
|
+
className: "w-full h-14 text-lg rounded-xl",
|
|
2682
|
+
disabled: isSubmitting || currencyOptions.length === 0 || isLoadingEstimate || displayData?.belowMinimum,
|
|
2683
|
+
children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2684
|
+
/* @__PURE__ */ jsx(RefreshCw, { className: "h-5 w-5 mr-2 animate-spin" }),
|
|
2685
|
+
"Creating..."
|
|
2686
|
+
] }) : "Continue"
|
|
2687
|
+
}
|
|
2688
|
+
)
|
|
2689
|
+
] }) })
|
|
2690
|
+
] }) });
|
|
2691
|
+
}
|
|
2692
|
+
var WithdrawSchema = z.object({
|
|
2693
|
+
amount: z.number().min(10, "Minimum $10"),
|
|
2694
|
+
currency: z.string().min(1, "Select a currency"),
|
|
2695
|
+
wallet_address: z.string().min(26, "Invalid wallet address")
|
|
2696
|
+
});
|
|
2697
|
+
var STORAGE_KEY2 = "payments:withdraw";
|
|
2698
|
+
function WithdrawSheet({ open, onOpenChange, onSuccess }) {
|
|
2699
|
+
const { currencies, isLoadingCurrencies, withdraw, balanceAmount } = useWallet();
|
|
2700
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
2701
|
+
const [error, setError] = useState(null);
|
|
2702
|
+
const [saved, setSaved] = useLocalStorage(STORAGE_KEY2, {
|
|
2703
|
+
currency: "",
|
|
2704
|
+
wallet: ""
|
|
2705
|
+
});
|
|
2706
|
+
const form = useForm({
|
|
2707
|
+
resolver: zodResolver(WithdrawSchema),
|
|
2708
|
+
defaultValues: {
|
|
2709
|
+
amount: 10,
|
|
2710
|
+
currency: saved.currency,
|
|
2711
|
+
wallet_address: saved.wallet
|
|
1708
2712
|
}
|
|
1709
|
-
}
|
|
1710
|
-
const
|
|
2713
|
+
});
|
|
2714
|
+
const watchedAmount = form.watch("amount");
|
|
2715
|
+
const watchedCurrency = form.watch("currency");
|
|
2716
|
+
const watchedWallet = form.watch("wallet_address");
|
|
2717
|
+
useAutoSave(watchedCurrency, (v) => setSaved((prev) => ({ ...prev, currency: v })));
|
|
2718
|
+
useAutoSave(watchedWallet, (v) => setSaved((prev) => ({ ...prev, wallet: v })), (v) => v.length >= 26);
|
|
2719
|
+
const currencyOptions = useCurrencyOptions(currencies);
|
|
2720
|
+
useDefaultCurrency({
|
|
2721
|
+
currencyOptions,
|
|
2722
|
+
savedCurrency: saved.currency,
|
|
2723
|
+
currentValue: watchedCurrency,
|
|
2724
|
+
setValue: (v) => form.setValue("currency", v)
|
|
2725
|
+
});
|
|
2726
|
+
const selectedCurrency = currencyOptions.find((c) => c.value === watchedCurrency);
|
|
2727
|
+
const amount = watchedAmount || 0;
|
|
2728
|
+
const { estimate, isLoading: isLoadingEstimate } = useWithdrawalEstimate({
|
|
2729
|
+
currencyCode: watchedCurrency,
|
|
2730
|
+
amountUsd: amount,
|
|
2731
|
+
minAmount: 10,
|
|
2732
|
+
skip: amount < 10
|
|
2733
|
+
});
|
|
2734
|
+
const cryptoDisplay = useMemo(() => {
|
|
2735
|
+
if (!selectedCurrency || !estimate) return null;
|
|
2736
|
+
return {
|
|
2737
|
+
token: selectedCurrency.token,
|
|
2738
|
+
cryptoAmount: formatCryptoAmount(estimate.estimatedAmount, estimate.isStablecoin)
|
|
2739
|
+
};
|
|
2740
|
+
}, [selectedCurrency, estimate]);
|
|
2741
|
+
const insufficientBalance = amount > balanceAmount;
|
|
2742
|
+
const handleSubmit = useCallback(async (data) => {
|
|
1711
2743
|
try {
|
|
1712
2744
|
setIsSubmitting(true);
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
2745
|
+
setError(null);
|
|
2746
|
+
const result = await withdraw({
|
|
2747
|
+
amount_usd: String(data.amount),
|
|
2748
|
+
currency_code: data.currency,
|
|
2749
|
+
wallet_address: data.wallet_address
|
|
2750
|
+
});
|
|
2751
|
+
form.reset();
|
|
2752
|
+
onOpenChange(false);
|
|
2753
|
+
onSuccess?.(result);
|
|
2754
|
+
} catch (err) {
|
|
2755
|
+
setError(extractErrorMessage(err, "Failed to create withdrawal request"));
|
|
1723
2756
|
} finally {
|
|
1724
2757
|
setIsSubmitting(false);
|
|
1725
2758
|
}
|
|
1726
|
-
};
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
2759
|
+
}, [withdraw, form, onOpenChange, onSuccess]);
|
|
2760
|
+
const handleOpenChange = useCallback((open2) => {
|
|
2761
|
+
if (open2) {
|
|
2762
|
+
form.reset({
|
|
2763
|
+
amount: 10,
|
|
2764
|
+
currency: saved.currency,
|
|
2765
|
+
wallet_address: saved.wallet
|
|
2766
|
+
});
|
|
2767
|
+
} else {
|
|
2768
|
+
setError(null);
|
|
2769
|
+
}
|
|
2770
|
+
onOpenChange(open2);
|
|
2771
|
+
}, [form, onOpenChange, saved]);
|
|
2772
|
+
return /* @__PURE__ */ jsx(ResponsiveSheet, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs(ResponsiveSheetContent, { className: "sm:max-w-md", children: [
|
|
2773
|
+
/* @__PURE__ */ jsxs(ResponsiveSheetHeader, { children: [
|
|
2774
|
+
/* @__PURE__ */ jsx(ResponsiveSheetTitle, { children: "Withdraw" }),
|
|
2775
|
+
/* @__PURE__ */ jsx(ResponsiveSheetDescription, { children: "Withdraw funds to your cryptocurrency wallet" })
|
|
1731
2776
|
] }),
|
|
1732
|
-
/* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-4", children: [
|
|
2777
|
+
/* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-6 p-4 sm:p-0 sm:mt-4", children: [
|
|
1733
2778
|
/* @__PURE__ */ jsx(
|
|
1734
2779
|
FormField,
|
|
1735
2780
|
{
|
|
1736
2781
|
control: form.control,
|
|
1737
|
-
name: "
|
|
2782
|
+
name: "amount",
|
|
1738
2783
|
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
1739
2784
|
/* @__PURE__ */ jsx(FormLabel, { children: "Amount (USD)" }),
|
|
2785
|
+
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
2786
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-muted-foreground text-lg", children: "$" }),
|
|
2787
|
+
/* @__PURE__ */ jsx(
|
|
2788
|
+
Input,
|
|
2789
|
+
{
|
|
2790
|
+
type: "number",
|
|
2791
|
+
step: "0.01",
|
|
2792
|
+
min: "10",
|
|
2793
|
+
placeholder: "10",
|
|
2794
|
+
className: "pl-8 text-2xl h-14 font-semibold",
|
|
2795
|
+
...field,
|
|
2796
|
+
onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
|
|
2797
|
+
}
|
|
2798
|
+
)
|
|
2799
|
+
] }) }),
|
|
2800
|
+
/* @__PURE__ */ jsx(FormMessage, {}),
|
|
2801
|
+
insufficientBalance && /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive mt-1", children: [
|
|
2802
|
+
"Insufficient balance (Available: $",
|
|
2803
|
+
formatUsdAmount(balanceAmount),
|
|
2804
|
+
")"
|
|
2805
|
+
] })
|
|
2806
|
+
] })
|
|
2807
|
+
}
|
|
2808
|
+
),
|
|
2809
|
+
/* @__PURE__ */ jsx(
|
|
2810
|
+
FormField,
|
|
2811
|
+
{
|
|
2812
|
+
control: form.control,
|
|
2813
|
+
name: "currency",
|
|
2814
|
+
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
2815
|
+
/* @__PURE__ */ jsx(FormLabel, { children: "Withdraw as" }),
|
|
1740
2816
|
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
|
|
1741
|
-
|
|
2817
|
+
CurrencyCombobox,
|
|
1742
2818
|
{
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
...field,
|
|
1748
|
-
onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
|
|
2819
|
+
options: currencyOptions,
|
|
2820
|
+
value: field.value,
|
|
2821
|
+
onChange: field.onChange,
|
|
2822
|
+
disabled: isLoadingCurrencies
|
|
1749
2823
|
}
|
|
1750
2824
|
) }),
|
|
1751
|
-
/* @__PURE__ */ jsx(FormDescription, { children: "The amount you want to pay in USD." }),
|
|
1752
2825
|
/* @__PURE__ */ jsx(FormMessage, {})
|
|
1753
2826
|
] })
|
|
1754
2827
|
}
|
|
@@ -1757,122 +2830,366 @@ var CreatePaymentDialog = () => {
|
|
|
1757
2830
|
FormField,
|
|
1758
2831
|
{
|
|
1759
2832
|
control: form.control,
|
|
1760
|
-
name: "
|
|
2833
|
+
name: "wallet_address",
|
|
1761
2834
|
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
1762
|
-
/* @__PURE__ */ jsx(FormLabel, { children: "
|
|
1763
|
-
/* @__PURE__ */
|
|
1764
|
-
|
|
2835
|
+
/* @__PURE__ */ jsx(FormLabel, { children: "Wallet Address" }),
|
|
2836
|
+
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
|
|
2837
|
+
Input,
|
|
1765
2838
|
{
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
children: [
|
|
1770
|
-
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select currency..." }) }) }),
|
|
1771
|
-
/* @__PURE__ */ jsx(SelectContent, { children: currencyOptions.map((curr) => /* @__PURE__ */ jsx(SelectItem, { value: curr.code, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1772
|
-
/* @__PURE__ */ jsx(TokenIcon, { symbol: curr.code, size: 16 }),
|
|
1773
|
-
/* @__PURE__ */ jsx("span", { children: curr.code }),
|
|
1774
|
-
curr.network && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
1775
|
-
"(",
|
|
1776
|
-
curr.network,
|
|
1777
|
-
")"
|
|
1778
|
-
] })
|
|
1779
|
-
] }) }, curr.code)) })
|
|
1780
|
-
]
|
|
2839
|
+
placeholder: "Enter your wallet address",
|
|
2840
|
+
className: "font-mono text-sm",
|
|
2841
|
+
...field
|
|
1781
2842
|
}
|
|
1782
|
-
),
|
|
1783
|
-
/* @__PURE__ */ jsx(FormDescription, { children: "The cryptocurrency to use for payment." }),
|
|
2843
|
+
) }),
|
|
1784
2844
|
/* @__PURE__ */ jsx(FormMessage, {})
|
|
1785
2845
|
] })
|
|
1786
2846
|
}
|
|
1787
2847
|
),
|
|
1788
|
-
|
|
1789
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1790
|
-
/* @__PURE__ */ jsx("span", { className: "text-
|
|
1791
|
-
/* @__PURE__ */ jsxs("
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
2848
|
+
amount >= 10 && selectedCurrency && /* @__PURE__ */ jsxs("div", { className: "bg-muted rounded-xl p-4 space-y-2", children: [
|
|
2849
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
2850
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Amount" }),
|
|
2851
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2852
|
+
"$",
|
|
2853
|
+
formatUsdAmount(amount)
|
|
2854
|
+
] })
|
|
2855
|
+
] }),
|
|
2856
|
+
isLoadingEstimate ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground py-2", children: [
|
|
2857
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
2858
|
+
/* @__PURE__ */ jsx("span", { children: "Calculating fees..." })
|
|
2859
|
+
] }) : estimate ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2860
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
2861
|
+
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
2862
|
+
"Service fee (",
|
|
2863
|
+
estimate.serviceFeePercent,
|
|
2864
|
+
"%)"
|
|
2865
|
+
] }),
|
|
2866
|
+
/* @__PURE__ */ jsxs("span", { className: "text-destructive", children: [
|
|
2867
|
+
"-$",
|
|
2868
|
+
formatUsdAmount(estimate.serviceFeeUsd)
|
|
2869
|
+
] })
|
|
2870
|
+
] }),
|
|
2871
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
2872
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Network fee" }),
|
|
2873
|
+
/* @__PURE__ */ jsxs("span", { className: "text-destructive", children: [
|
|
2874
|
+
"-$",
|
|
2875
|
+
formatUsdAmount(estimate.networkFeeUsd)
|
|
2876
|
+
] })
|
|
2877
|
+
] }),
|
|
2878
|
+
/* @__PURE__ */ jsx("div", { className: "border-t pt-2 mt-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2879
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: "You will receive" }),
|
|
2880
|
+
/* @__PURE__ */ jsxs("div", { className: "text-right", children: [
|
|
2881
|
+
/* @__PURE__ */ jsxs("div", { className: "font-semibold", children: [
|
|
2882
|
+
"$",
|
|
2883
|
+
formatUsdAmount(estimate.amountToReceive)
|
|
2884
|
+
] }),
|
|
2885
|
+
cryptoDisplay && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
|
|
2886
|
+
/* @__PURE__ */ jsx(TokenIcon, { symbol: cryptoDisplay.token, size: 16 }),
|
|
2887
|
+
/* @__PURE__ */ jsxs("span", { className: "font-mono", children: [
|
|
2888
|
+
cryptoDisplay.cryptoAmount,
|
|
2889
|
+
" ",
|
|
2890
|
+
cryptoDisplay.token
|
|
2891
|
+
] })
|
|
2892
|
+
] })
|
|
2893
|
+
] })
|
|
2894
|
+
] }) })
|
|
2895
|
+
] }) : null
|
|
2896
|
+
] }),
|
|
2897
|
+
/* @__PURE__ */ jsxs(Alert, { children: [
|
|
2898
|
+
/* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4" }),
|
|
2899
|
+
/* @__PURE__ */ jsx(AlertDescription, { children: "Withdrawal requests require admin approval. Processing may take 24-48 hours." })
|
|
2900
|
+
] }),
|
|
2901
|
+
error && /* @__PURE__ */ jsx(Alert, { variant: "destructive", children: /* @__PURE__ */ jsx(AlertDescription, { children: error }) }),
|
|
2902
|
+
/* @__PURE__ */ jsx(
|
|
2903
|
+
Button,
|
|
2904
|
+
{
|
|
2905
|
+
type: "submit",
|
|
2906
|
+
size: "lg",
|
|
2907
|
+
className: "w-full h-14 text-lg rounded-xl",
|
|
2908
|
+
disabled: isSubmitting || currencyOptions.length === 0 || insufficientBalance || !estimate || estimate.amountToReceive <= 0 || isLoadingEstimate,
|
|
2909
|
+
children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2910
|
+
/* @__PURE__ */ jsx(RefreshCw, { className: "h-5 w-5 mr-2 animate-spin" }),
|
|
2911
|
+
"Submitting..."
|
|
2912
|
+
] }) : "Request Withdrawal"
|
|
2913
|
+
}
|
|
2914
|
+
)
|
|
2915
|
+
] }) })
|
|
2916
|
+
] }) });
|
|
2917
|
+
}
|
|
2918
|
+
var statusConfig2 = {
|
|
2919
|
+
pending: {
|
|
2920
|
+
icon: Clock,
|
|
2921
|
+
color: "text-yellow-500",
|
|
2922
|
+
bg: "bg-yellow-500/10",
|
|
2923
|
+
label: "Pending Approval"
|
|
2924
|
+
},
|
|
2925
|
+
approved: {
|
|
2926
|
+
icon: CheckCircle2,
|
|
2927
|
+
color: "text-blue-500",
|
|
2928
|
+
bg: "bg-blue-500/10",
|
|
2929
|
+
label: "Approved"
|
|
2930
|
+
},
|
|
2931
|
+
processing: {
|
|
2932
|
+
icon: RefreshCw,
|
|
2933
|
+
color: "text-blue-500",
|
|
2934
|
+
bg: "bg-blue-500/10",
|
|
2935
|
+
label: "Processing",
|
|
2936
|
+
animate: true
|
|
2937
|
+
},
|
|
2938
|
+
completed: {
|
|
2939
|
+
icon: CheckCircle2,
|
|
2940
|
+
color: "text-green-500",
|
|
2941
|
+
bg: "bg-green-500/10",
|
|
2942
|
+
label: "Completed"
|
|
2943
|
+
},
|
|
2944
|
+
rejected: {
|
|
2945
|
+
icon: XCircle,
|
|
2946
|
+
color: "text-red-500",
|
|
2947
|
+
bg: "bg-red-500/10",
|
|
2948
|
+
label: "Rejected"
|
|
2949
|
+
},
|
|
2950
|
+
cancelled: {
|
|
2951
|
+
icon: Ban,
|
|
2952
|
+
color: "text-muted-foreground",
|
|
2953
|
+
bg: "bg-muted",
|
|
2954
|
+
label: "Cancelled"
|
|
2955
|
+
}
|
|
2956
|
+
};
|
|
2957
|
+
function WithdrawalSheet({ withdrawalId, open, onOpenChange }) {
|
|
2958
|
+
const { getWithdrawalDetails, cancelWithdrawal, refreshWallet } = useWallet();
|
|
2959
|
+
const { data: withdrawal, isLoading, error, mutate } = useSWR(
|
|
2960
|
+
open && withdrawalId ? ["withdrawal-details", withdrawalId] : null,
|
|
2961
|
+
() => getWithdrawalDetails(withdrawalId),
|
|
2962
|
+
{ refreshInterval: 3e4 }
|
|
2963
|
+
);
|
|
2964
|
+
const displayData = useMemo(() => {
|
|
2965
|
+
const s = withdrawal?.status?.toLowerCase() || "pending";
|
|
2966
|
+
const config2 = statusConfig2[s] || statusConfig2.pending;
|
|
2967
|
+
const isPending = s === "pending";
|
|
2968
|
+
const isCompleted = s === "completed";
|
|
2969
|
+
const isRejected = s === "rejected";
|
|
2970
|
+
const isCancelled = s === "cancelled";
|
|
2971
|
+
const isProcessing = s === "processing" || s === "approved";
|
|
2972
|
+
const canCancel2 = isPending;
|
|
2973
|
+
let description2 = "";
|
|
2974
|
+
if (isPending) description2 = "Waiting for admin approval";
|
|
2975
|
+
else if (isProcessing) description2 = "Your withdrawal is being processed";
|
|
2976
|
+
else if (isCompleted) description2 = "Withdrawal completed successfully";
|
|
2977
|
+
else if (isRejected) description2 = "Withdrawal was rejected";
|
|
2978
|
+
else if (isCancelled) description2 = "Withdrawal was cancelled";
|
|
2979
|
+
const amountUsd2 = withdrawal?.amount_usd ? `$${parseFloat(withdrawal.amount_usd).toFixed(2)}` : "";
|
|
2980
|
+
const finalAmountUsd2 = withdrawal?.final_amount_usd ? `$${parseFloat(withdrawal.final_amount_usd).toFixed(2)}` : "";
|
|
2981
|
+
const totalFeeUsd2 = withdrawal?.total_fee_usd ? `$${parseFloat(withdrawal.total_fee_usd).toFixed(2)}` : "";
|
|
2982
|
+
const createdAt2 = withdrawal?.created_at ? moment3.utc(withdrawal.created_at).local().format("MMM D, YYYY HH:mm") : "";
|
|
2983
|
+
const completedAt2 = withdrawal?.completed_at ? moment3.utc(withdrawal.completed_at).local().format("MMM D, YYYY HH:mm") : null;
|
|
2984
|
+
return {
|
|
2985
|
+
status: s,
|
|
2986
|
+
config: config2,
|
|
2987
|
+
isPending,
|
|
2988
|
+
isCompleted,
|
|
2989
|
+
isRejected,
|
|
2990
|
+
isCancelled,
|
|
2991
|
+
isProcessing,
|
|
2992
|
+
canCancel: canCancel2,
|
|
2993
|
+
description: description2,
|
|
2994
|
+
amountUsd: amountUsd2,
|
|
2995
|
+
finalAmountUsd: finalAmountUsd2,
|
|
2996
|
+
totalFeeUsd: totalFeeUsd2,
|
|
2997
|
+
createdAt: createdAt2,
|
|
2998
|
+
completedAt: completedAt2
|
|
2999
|
+
};
|
|
3000
|
+
}, [withdrawal]);
|
|
3001
|
+
const { config, canCancel, description, amountUsd, finalAmountUsd, totalFeeUsd, createdAt, completedAt } = displayData;
|
|
3002
|
+
const StatusIcon = config.icon;
|
|
3003
|
+
const handleCancel = async () => {
|
|
3004
|
+
if (!withdrawalId) return;
|
|
3005
|
+
try {
|
|
3006
|
+
await cancelWithdrawal(withdrawalId);
|
|
3007
|
+
await mutate();
|
|
3008
|
+
await refreshWallet();
|
|
3009
|
+
} catch (err) {
|
|
3010
|
+
console.error("Failed to cancel withdrawal:", err);
|
|
3011
|
+
}
|
|
3012
|
+
};
|
|
3013
|
+
return /* @__PURE__ */ jsx(ResponsiveSheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs(ResponsiveSheetContent, { className: "sm:max-w-lg", children: [
|
|
3014
|
+
/* @__PURE__ */ jsxs(ResponsiveSheetHeader, { children: [
|
|
3015
|
+
/* @__PURE__ */ jsx(ResponsiveSheetTitle, { children: "Withdrawal Details" }),
|
|
3016
|
+
/* @__PURE__ */ jsx(ResponsiveSheetDescription, { children: description })
|
|
3017
|
+
] }),
|
|
3018
|
+
/* @__PURE__ */ jsxs("div", { className: "p-4 sm:p-0 sm:mt-4 overflow-y-auto max-h-[70vh]", children: [
|
|
3019
|
+
isLoading && /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
3020
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-16 w-full rounded-xl" }),
|
|
3021
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-24 w-full rounded-xl" }),
|
|
3022
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-20 w-full rounded-xl" })
|
|
3023
|
+
] }),
|
|
3024
|
+
error && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-12", children: [
|
|
3025
|
+
/* @__PURE__ */ jsx(XCircle, { className: "h-12 w-12 text-destructive mb-4" }),
|
|
3026
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-4", children: "Failed to load withdrawal" }),
|
|
3027
|
+
/* @__PURE__ */ jsx(Button, { onClick: () => mutate(), children: "Try Again" })
|
|
3028
|
+
] }),
|
|
3029
|
+
withdrawal && !isLoading && /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
3030
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-3 p-4 rounded-xl", config.bg), children: [
|
|
3031
|
+
/* @__PURE__ */ jsx(StatusIcon, { className: cn("h-6 w-6", config.color, config.animate && "animate-spin") }),
|
|
3032
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
3033
|
+
/* @__PURE__ */ jsx("div", { className: "font-semibold", children: config.label }),
|
|
3034
|
+
withdrawal.admin_notes && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: withdrawal.admin_notes })
|
|
3035
|
+
] })
|
|
3036
|
+
] }),
|
|
3037
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-muted rounded-xl p-4 space-y-3", children: [
|
|
3038
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
3039
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Amount" }),
|
|
3040
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: amountUsd })
|
|
3041
|
+
] }),
|
|
3042
|
+
totalFeeUsd && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
3043
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Total fees" }),
|
|
3044
|
+
/* @__PURE__ */ jsxs("span", { className: "text-destructive", children: [
|
|
3045
|
+
"-",
|
|
3046
|
+
totalFeeUsd
|
|
3047
|
+
] })
|
|
3048
|
+
] }),
|
|
3049
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pt-2 border-t", children: [
|
|
3050
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "You receive" }),
|
|
3051
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3052
|
+
/* @__PURE__ */ jsx(TokenIcon, { symbol: withdrawal.currency_code, size: 24 }),
|
|
3053
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono font-bold text-lg", children: finalAmountUsd })
|
|
3054
|
+
] })
|
|
3055
|
+
] }),
|
|
3056
|
+
withdrawal.crypto_amount && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
3057
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Crypto amount" }),
|
|
3058
|
+
/* @__PURE__ */ jsxs("span", { className: "font-mono", children: [
|
|
3059
|
+
withdrawal.crypto_amount,
|
|
1795
3060
|
" ",
|
|
1796
|
-
|
|
3061
|
+
withdrawal.currency_token
|
|
1797
3062
|
] })
|
|
1798
3063
|
] })
|
|
1799
3064
|
] }),
|
|
1800
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
1801
|
-
/* @__PURE__ */ jsx("
|
|
1802
|
-
/* @__PURE__ */ jsxs("
|
|
1803
|
-
"
|
|
1804
|
-
|
|
1805
|
-
" USD"
|
|
3065
|
+
withdrawal.wallet_address && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
3066
|
+
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Destination Wallet" }),
|
|
3067
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3068
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all", children: withdrawal.wallet_address }),
|
|
3069
|
+
/* @__PURE__ */ jsx(CopyButton, { value: withdrawal.wallet_address, variant: "outline", className: "shrink-0" })
|
|
1806
3070
|
] })
|
|
1807
3071
|
] }),
|
|
1808
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
1809
|
-
/* @__PURE__ */ jsx("
|
|
1810
|
-
/* @__PURE__ */ jsxs("
|
|
1811
|
-
"1 ",
|
|
1812
|
-
|
|
1813
|
-
" = $",
|
|
1814
|
-
calculateCryptoAmount.rate?.toFixed(2)
|
|
3072
|
+
withdrawal.transaction_hash && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
3073
|
+
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
|
|
3074
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3075
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all", children: withdrawal.transaction_hash }),
|
|
3076
|
+
/* @__PURE__ */ jsx(CopyButton, { value: withdrawal.transaction_hash, variant: "outline", className: "shrink-0" })
|
|
1815
3077
|
] })
|
|
1816
3078
|
] }),
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
3079
|
+
withdrawal.explorer_link && /* @__PURE__ */ jsxs(
|
|
3080
|
+
Button,
|
|
3081
|
+
{
|
|
3082
|
+
variant: "outline",
|
|
3083
|
+
className: "w-full",
|
|
3084
|
+
onClick: () => window.open(withdrawal.explorer_link, "_blank"),
|
|
3085
|
+
children: [
|
|
3086
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 mr-2" }),
|
|
3087
|
+
"View on Explorer"
|
|
3088
|
+
]
|
|
3089
|
+
}
|
|
3090
|
+
),
|
|
3091
|
+
canCancel && /* @__PURE__ */ jsxs(
|
|
3092
|
+
Button,
|
|
3093
|
+
{
|
|
3094
|
+
variant: "destructive",
|
|
3095
|
+
className: "w-full",
|
|
3096
|
+
onClick: handleCancel,
|
|
3097
|
+
children: [
|
|
3098
|
+
/* @__PURE__ */ jsx(Ban, { className: "h-4 w-4 mr-2" }),
|
|
3099
|
+
"Cancel Withdrawal"
|
|
3100
|
+
]
|
|
3101
|
+
}
|
|
3102
|
+
),
|
|
3103
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 text-xs text-muted-foreground pt-4 border-t", children: [
|
|
3104
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
3105
|
+
/* @__PURE__ */ jsx("span", { children: "Withdrawal ID" }),
|
|
3106
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono", children: withdrawal.id })
|
|
3107
|
+
] }),
|
|
3108
|
+
withdrawal.internal_withdrawal_id && /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
3109
|
+
/* @__PURE__ */ jsx("span", { children: "Reference #" }),
|
|
3110
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono", children: withdrawal.internal_withdrawal_id })
|
|
3111
|
+
] }),
|
|
3112
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
3113
|
+
/* @__PURE__ */ jsx("span", { children: "Created" }),
|
|
3114
|
+
/* @__PURE__ */ jsx("span", { children: createdAt })
|
|
3115
|
+
] }),
|
|
3116
|
+
completedAt && /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
3117
|
+
/* @__PURE__ */ jsx("span", { children: "Completed" }),
|
|
3118
|
+
/* @__PURE__ */ jsx("span", { children: completedAt })
|
|
3119
|
+
] }),
|
|
3120
|
+
withdrawal.currency_network && /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
3121
|
+
/* @__PURE__ */ jsx("span", { children: "Network" }),
|
|
3122
|
+
/* @__PURE__ */ jsx("span", { children: withdrawal.currency_network })
|
|
3123
|
+
] })
|
|
3124
|
+
] }),
|
|
3125
|
+
/* @__PURE__ */ jsxs(
|
|
3126
|
+
Button,
|
|
3127
|
+
{
|
|
3128
|
+
variant: "ghost",
|
|
3129
|
+
className: "w-full",
|
|
3130
|
+
onClick: () => mutate(),
|
|
3131
|
+
children: [
|
|
3132
|
+
/* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4 mr-2" }),
|
|
3133
|
+
"Refresh Status"
|
|
3134
|
+
]
|
|
3135
|
+
}
|
|
3136
|
+
)
|
|
1831
3137
|
] })
|
|
1832
|
-
] })
|
|
3138
|
+
] })
|
|
1833
3139
|
] }) });
|
|
3140
|
+
}
|
|
3141
|
+
var statusConfig3 = {
|
|
3142
|
+
pending: {
|
|
3143
|
+
icon: Clock,
|
|
3144
|
+
color: "text-yellow-500",
|
|
3145
|
+
bg: "bg-yellow-500/10",
|
|
3146
|
+
label: "Waiting for payment"
|
|
3147
|
+
},
|
|
3148
|
+
confirming: {
|
|
3149
|
+
icon: RefreshCw,
|
|
3150
|
+
color: "text-blue-500",
|
|
3151
|
+
bg: "bg-blue-500/10",
|
|
3152
|
+
label: "Confirming",
|
|
3153
|
+
animate: true
|
|
3154
|
+
},
|
|
3155
|
+
completed: {
|
|
3156
|
+
icon: CheckCircle2,
|
|
3157
|
+
color: "text-green-500",
|
|
3158
|
+
bg: "bg-green-500/10",
|
|
3159
|
+
label: "Completed"
|
|
3160
|
+
},
|
|
3161
|
+
failed: {
|
|
3162
|
+
icon: XCircle,
|
|
3163
|
+
color: "text-red-500",
|
|
3164
|
+
bg: "bg-red-500/10",
|
|
3165
|
+
label: "Failed"
|
|
3166
|
+
},
|
|
3167
|
+
expired: {
|
|
3168
|
+
icon: AlertCircle,
|
|
3169
|
+
color: "text-muted-foreground",
|
|
3170
|
+
bg: "bg-muted",
|
|
3171
|
+
label: "Expired"
|
|
3172
|
+
}
|
|
1834
3173
|
};
|
|
1835
|
-
|
|
1836
|
-
const
|
|
1837
|
-
const [paymentId, setPaymentId] = useState(null);
|
|
3174
|
+
function PaymentSheet({ paymentId, open, onOpenChange, onCreateNew }) {
|
|
3175
|
+
const { getPaymentDetails } = useWallet();
|
|
1838
3176
|
const [timeLeft, setTimeLeft] = useState("");
|
|
1839
|
-
const
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
3177
|
+
const { data: payment, isLoading, error, mutate } = useSWR(
|
|
3178
|
+
open && paymentId ? ["payment-details", paymentId] : null,
|
|
3179
|
+
() => getPaymentDetails(paymentId),
|
|
3180
|
+
{ refreshInterval: 1e4 }
|
|
1843
3181
|
);
|
|
1844
|
-
useEffect(() => {
|
|
1845
|
-
const handleOpen = (event) => {
|
|
1846
|
-
const customEvent = event;
|
|
1847
|
-
setPaymentId(customEvent.detail.id);
|
|
1848
|
-
setOpen(true);
|
|
1849
|
-
};
|
|
1850
|
-
const handleClose2 = () => {
|
|
1851
|
-
setOpen(false);
|
|
1852
|
-
setPaymentId(null);
|
|
1853
|
-
};
|
|
1854
|
-
window.addEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
|
|
1855
|
-
window.addEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
|
|
1856
|
-
return () => {
|
|
1857
|
-
window.removeEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
|
|
1858
|
-
window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
|
|
1859
|
-
};
|
|
1860
|
-
}, []);
|
|
1861
|
-
const handleClose = () => {
|
|
1862
|
-
setOpen(false);
|
|
1863
|
-
setPaymentId(null);
|
|
1864
|
-
};
|
|
1865
3182
|
useEffect(() => {
|
|
1866
3183
|
if (!payment?.expires_at) return;
|
|
1867
3184
|
const updateTimeLeft = () => {
|
|
1868
|
-
const now =
|
|
1869
|
-
const expires =
|
|
3185
|
+
const now = moment3();
|
|
3186
|
+
const expires = moment3.utc(payment.expires_at);
|
|
1870
3187
|
const diff = expires.diff(now);
|
|
1871
3188
|
if (diff <= 0) {
|
|
1872
3189
|
setTimeLeft("Expired");
|
|
1873
3190
|
return;
|
|
1874
3191
|
}
|
|
1875
|
-
const duration =
|
|
3192
|
+
const duration = moment3.duration(diff);
|
|
1876
3193
|
const hours = Math.floor(duration.asHours());
|
|
1877
3194
|
const minutes = duration.minutes();
|
|
1878
3195
|
const seconds = duration.seconds();
|
|
@@ -1882,713 +3199,245 @@ var PaymentDetailsDialog = () => {
|
|
|
1882
3199
|
const interval = setInterval(updateTimeLeft, 1e3);
|
|
1883
3200
|
return () => clearInterval(interval);
|
|
1884
3201
|
}, [payment?.expires_at]);
|
|
1885
|
-
const
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
3202
|
+
const displayData = useMemo(() => {
|
|
3203
|
+
const s = payment?.status?.toLowerCase();
|
|
3204
|
+
let status;
|
|
3205
|
+
if (s === "completed" || s === "success" || s === "finished") status = "completed";
|
|
3206
|
+
else if (s === "confirming" || s === "partially_paid") status = "confirming";
|
|
3207
|
+
else if (s === "expired") status = "expired";
|
|
3208
|
+
else if (s === "failed" || s === "error" || s === "cancelled") status = "failed";
|
|
3209
|
+
else status = "pending";
|
|
3210
|
+
const config2 = statusConfig3[status];
|
|
3211
|
+
const isPending = status === "pending";
|
|
3212
|
+
const isExpired2 = status === "expired" || timeLeft === "Expired";
|
|
3213
|
+
const isCompleted = status === "completed";
|
|
3214
|
+
const isFailed = status === "failed";
|
|
3215
|
+
const isConfirming = status === "confirming";
|
|
3216
|
+
const canPay2 = isPending && !isExpired2;
|
|
3217
|
+
let description2 = "";
|
|
3218
|
+
if (canPay2) description2 = "Send cryptocurrency to complete payment";
|
|
3219
|
+
else if (isExpired2) description2 = "This payment has expired";
|
|
3220
|
+
else if (isCompleted) description2 = "Payment completed successfully";
|
|
3221
|
+
else if (isFailed) description2 = "Payment failed";
|
|
3222
|
+
else if (isConfirming) description2 = "Confirming your payment";
|
|
3223
|
+
const statusBadge2 = {
|
|
3224
|
+
bg: isExpired2 ? "bg-muted" : config2.bg,
|
|
3225
|
+
iconColor: isExpired2 ? "text-muted-foreground" : config2.color,
|
|
3226
|
+
iconAnimate: config2.animate,
|
|
3227
|
+
label: isExpired2 ? "Payment Expired" : config2.label,
|
|
3228
|
+
subtitle: canPay2 && timeLeft ? `Expires in ${timeLeft}` : isExpired2 ? "Please create a new payment to continue" : null
|
|
3229
|
+
};
|
|
3230
|
+
const qrCodeUrl2 = payment?.pay_address && canPay2 ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(payment.pay_address)}` : null;
|
|
3231
|
+
const amountUsd2 = payment?.amount_usd ? `$${parseFloat(payment.amount_usd).toFixed(2)} USD` : "";
|
|
3232
|
+
const createdAt2 = payment?.created_at ? moment3.utc(payment.created_at).local().format("MMM D, YYYY HH:mm") : "";
|
|
3233
|
+
return {
|
|
3234
|
+
status,
|
|
3235
|
+
config: config2,
|
|
3236
|
+
isPending,
|
|
3237
|
+
isExpired: isExpired2,
|
|
3238
|
+
isCompleted,
|
|
3239
|
+
isFailed,
|
|
3240
|
+
isConfirming,
|
|
3241
|
+
canPay: canPay2,
|
|
3242
|
+
description: description2,
|
|
3243
|
+
statusBadge: statusBadge2,
|
|
3244
|
+
qrCodeUrl: qrCodeUrl2,
|
|
3245
|
+
amountUsd: amountUsd2,
|
|
3246
|
+
createdAt: createdAt2
|
|
3247
|
+
};
|
|
3248
|
+
}, [payment, timeLeft]);
|
|
3249
|
+
const { config, canPay, isExpired, description, statusBadge, qrCodeUrl, amountUsd, createdAt } = displayData;
|
|
3250
|
+
const StatusIcon = config.icon;
|
|
3251
|
+
return /* @__PURE__ */ jsx(ResponsiveSheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs(ResponsiveSheetContent, { className: "sm:max-w-lg", children: [
|
|
3252
|
+
/* @__PURE__ */ jsxs(ResponsiveSheetHeader, { children: [
|
|
3253
|
+
/* @__PURE__ */ jsx(ResponsiveSheetTitle, { children: "Payment Details" }),
|
|
3254
|
+
/* @__PURE__ */ jsx(ResponsiveSheetDescription, { children: description })
|
|
3255
|
+
] }),
|
|
3256
|
+
/* @__PURE__ */ jsxs("div", { className: "p-4 sm:p-0 sm:mt-4 overflow-y-auto max-h-[70vh]", children: [
|
|
3257
|
+
isLoading && /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
3258
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-48 w-48 rounded-xl" }) }),
|
|
3259
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-12 w-full" }),
|
|
3260
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-24 w-full" })
|
|
1918
3261
|
] }),
|
|
1919
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-12
|
|
1920
|
-
/* @__PURE__ */ jsx(XCircle, { className: "h-12 w-12 text-destructive" }),
|
|
1921
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children:
|
|
3262
|
+
error && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-12", children: [
|
|
3263
|
+
/* @__PURE__ */ jsx(XCircle, { className: "h-12 w-12 text-destructive mb-4" }),
|
|
3264
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-4", children: "Failed to load payment" }),
|
|
1922
3265
|
/* @__PURE__ */ jsx(Button, { onClick: () => mutate(), children: "Try Again" })
|
|
1923
|
-
] })
|
|
1924
|
-
] }) });
|
|
1925
|
-
}
|
|
1926
|
-
const statusInfo = getStatusInfo();
|
|
1927
|
-
const StatusIcon = statusInfo.icon;
|
|
1928
|
-
const qrCodeUrl = payment.pay_address ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(payment.pay_address)}` : null;
|
|
1929
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
|
|
1930
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
1931
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: "Payment Details" }),
|
|
1932
|
-
/* @__PURE__ */ jsx(DialogDescription, { children: "Send cryptocurrency to complete your payment" })
|
|
1933
|
-
] }),
|
|
1934
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
1935
|
-
/* @__PURE__ */ jsxs("div", { className: `flex items-center gap-3 p-4 rounded-sm ${statusInfo.bg}`, children: [
|
|
1936
|
-
/* @__PURE__ */ jsx(StatusIcon, { className: `h-5 w-5 ${statusInfo.color}` }),
|
|
1937
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
1938
|
-
/* @__PURE__ */ jsx("div", { className: "font-semibold capitalize", children: payment.status }),
|
|
1939
|
-
payment.status === "pending" && timeLeft && /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
|
|
1940
|
-
"Expires in ",
|
|
1941
|
-
timeLeft
|
|
1942
|
-
] })
|
|
1943
|
-
] })
|
|
1944
3266
|
] }),
|
|
1945
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-
|
|
1946
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center
|
|
1947
|
-
/* @__PURE__ */ jsx(
|
|
1948
|
-
/* @__PURE__ */ jsxs("div", { className: "flex
|
|
1949
|
-
/* @__PURE__ */ jsx(
|
|
1950
|
-
/* @__PURE__ */
|
|
1951
|
-
payment.pay_amount || "0.00000000",
|
|
1952
|
-
" ",
|
|
1953
|
-
payment.currency_code
|
|
1954
|
-
] })
|
|
1955
|
-
] })
|
|
1956
|
-
] }),
|
|
1957
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4", children: [
|
|
1958
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Equivalent to" }),
|
|
1959
|
-
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-lg", children: [
|
|
1960
|
-
"$",
|
|
1961
|
-
parseFloat(payment.amount_usd || "0").toFixed(2),
|
|
1962
|
-
" USD"
|
|
3267
|
+
payment && !isLoading && /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
3268
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-3 p-4 rounded-xl", statusBadge.bg), children: [
|
|
3269
|
+
/* @__PURE__ */ jsx(StatusIcon, { className: cn("h-6 w-6", statusBadge.iconColor, statusBadge.iconAnimate && "animate-spin") }),
|
|
3270
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
3271
|
+
/* @__PURE__ */ jsx("div", { className: "font-semibold", children: statusBadge.label }),
|
|
3272
|
+
statusBadge.subtitle && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: statusBadge.subtitle })
|
|
1963
3273
|
] })
|
|
1964
3274
|
] }),
|
|
1965
|
-
|
|
1966
|
-
/* @__PURE__ */
|
|
1967
|
-
|
|
1968
|
-
] }),
|
|
1969
|
-
payment.currency_network && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4", children: [
|
|
1970
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Network" }),
|
|
1971
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium", children: payment.currency_network })
|
|
1972
|
-
] })
|
|
1973
|
-
] }),
|
|
1974
|
-
qrCodeUrl && payment.status === "pending" && /* @__PURE__ */ jsx("div", { className: "flex justify-center p-6 bg-white rounded-sm", children: /* @__PURE__ */ jsx("img", { src: qrCodeUrl, alt: "Payment QR Code", className: "w-48 h-48" }) }),
|
|
1975
|
-
payment.pay_address && payment.status === "pending" && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1976
|
-
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Payment Address" }),
|
|
1977
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1978
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.pay_address }),
|
|
1979
|
-
/* @__PURE__ */ jsx(CopyButton, { value: payment.pay_address, variant: "outline" })
|
|
1980
|
-
] })
|
|
1981
|
-
] }),
|
|
1982
|
-
payment.transaction_hash && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1983
|
-
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
|
|
1984
|
-
/* @__PURE__ */ jsx("div", { className: "p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.transaction_hash })
|
|
1985
|
-
] }),
|
|
1986
|
-
payment.payment_url && payment.status === "pending" && /* @__PURE__ */ jsxs(
|
|
1987
|
-
Button,
|
|
1988
|
-
{
|
|
1989
|
-
variant: "outline",
|
|
1990
|
-
className: "w-full",
|
|
1991
|
-
onClick: () => window.open(payment.payment_url, "_blank"),
|
|
1992
|
-
children: [
|
|
1993
|
-
/* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 mr-2" }),
|
|
1994
|
-
"Open in Payment Provider"
|
|
1995
|
-
]
|
|
1996
|
-
}
|
|
1997
|
-
),
|
|
1998
|
-
/* @__PURE__ */ jsxs("div", { className: "pt-4 border-t space-y-2 text-xs text-muted-foreground", children: [
|
|
1999
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
2000
|
-
/* @__PURE__ */ jsx("span", { children: "Payment ID" }),
|
|
2001
|
-
/* @__PURE__ */ jsx("span", { className: "font-mono", children: payment.id })
|
|
2002
|
-
] }),
|
|
2003
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
2004
|
-
/* @__PURE__ */ jsx("span", { children: "Created" }),
|
|
2005
|
-
/* @__PURE__ */ jsx("span", { children: moment.utc(payment.created_at).local().format("MMM D, YYYY HH:mm") })
|
|
2006
|
-
] }),
|
|
2007
|
-
payment.confirmations_count !== void 0 && /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
2008
|
-
/* @__PURE__ */ jsx("span", { children: "Confirmations" }),
|
|
2009
|
-
/* @__PURE__ */ jsx("span", { children: payment.confirmations_count })
|
|
2010
|
-
] })
|
|
2011
|
-
] })
|
|
2012
|
-
] }),
|
|
2013
|
-
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
2014
|
-
/* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleClose, children: "Close" }),
|
|
2015
|
-
/* @__PURE__ */ jsxs(Button, { onClick: () => mutate(), variant: "ghost", size: "sm", children: [
|
|
2016
|
-
/* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4 mr-2" }),
|
|
2017
|
-
"Refresh"
|
|
2018
|
-
] })
|
|
2019
|
-
] })
|
|
2020
|
-
] }) });
|
|
2021
|
-
};
|
|
2022
|
-
var BalanceCard = () => {
|
|
2023
|
-
const {
|
|
2024
|
-
balance,
|
|
2025
|
-
isLoadingBalance,
|
|
2026
|
-
refreshBalance
|
|
2027
|
-
} = useOverviewContext();
|
|
2028
|
-
const formatCurrency = (amount) => {
|
|
2029
|
-
if (amount === null || amount === void 0) return "$0.00";
|
|
2030
|
-
return new Intl.NumberFormat("en-US", {
|
|
2031
|
-
style: "currency",
|
|
2032
|
-
currency: "USD",
|
|
2033
|
-
minimumFractionDigits: 2
|
|
2034
|
-
}).format(amount);
|
|
2035
|
-
};
|
|
2036
|
-
const formatDate = (dateStr) => {
|
|
2037
|
-
if (!dateStr) return "No transactions yet";
|
|
2038
|
-
try {
|
|
2039
|
-
return moment.utc(dateStr).local().format("MMM D, YYYY");
|
|
2040
|
-
} catch {
|
|
2041
|
-
return "Invalid date";
|
|
2042
|
-
}
|
|
2043
|
-
};
|
|
2044
|
-
if (isLoadingBalance) {
|
|
2045
|
-
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
2046
|
-
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
|
|
2047
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2048
|
-
/* @__PURE__ */ jsx(Wallet, { className: "h-5 w-5" }),
|
|
2049
|
-
"Account Balance"
|
|
2050
|
-
] }),
|
|
2051
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-20" })
|
|
2052
|
-
] }) }),
|
|
2053
|
-
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
|
|
2054
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-32" }),
|
|
2055
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" })
|
|
2056
|
-
] })
|
|
2057
|
-
] });
|
|
2058
|
-
}
|
|
2059
|
-
const balanceData = balance?.balance || balance;
|
|
2060
|
-
const amountUsd = balanceData?.amount_usd ?? 0;
|
|
2061
|
-
const totalDeposited = balanceData?.total_deposited ?? 0;
|
|
2062
|
-
const totalWithdrawn = balanceData?.total_withdrawn ?? 0;
|
|
2063
|
-
const lastTransactionAt = balanceData?.last_transaction_at;
|
|
2064
|
-
const isEmpty = amountUsd === 0 && totalDeposited === 0;
|
|
2065
|
-
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
2066
|
-
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
|
|
2067
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2068
|
-
/* @__PURE__ */ jsx(Wallet, { className: "h-5 w-5" }),
|
|
2069
|
-
"Account Balance"
|
|
2070
|
-
] }),
|
|
2071
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2072
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: refreshBalance, children: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }) }),
|
|
2073
|
-
/* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => openCreatePaymentDialog(), children: [
|
|
2074
|
-
/* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
|
|
2075
|
-
"Add Funds"
|
|
2076
|
-
] })
|
|
2077
|
-
] })
|
|
2078
|
-
] }) }),
|
|
2079
|
-
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
|
|
2080
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
2081
|
-
/* @__PURE__ */ jsx("div", { className: "text-4xl font-bold", children: formatCurrency(amountUsd) }),
|
|
2082
|
-
/* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground mt-1", children: [
|
|
2083
|
-
"Available balance \u2022 Last updated ",
|
|
2084
|
-
formatDate(lastTransactionAt)
|
|
2085
|
-
] })
|
|
2086
|
-
] }),
|
|
2087
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4 pt-4 border-t", children: [
|
|
2088
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
2089
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Total Deposited" }),
|
|
2090
|
-
/* @__PURE__ */ jsx("p", { className: "text-lg font-semibold text-green-600", children: formatCurrency(totalDeposited) })
|
|
2091
|
-
] }),
|
|
2092
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
2093
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Total Withdrawn" }),
|
|
2094
|
-
/* @__PURE__ */ jsx("p", { className: "text-lg font-semibold text-red-600", children: formatCurrency(totalWithdrawn) })
|
|
2095
|
-
] })
|
|
2096
|
-
] }),
|
|
2097
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2098
|
-
/* @__PURE__ */ jsx(Badge, { variant: !isEmpty ? "default" : "secondary", children: !isEmpty ? "Active" : "New Account" }),
|
|
2099
|
-
isEmpty && /* @__PURE__ */ jsx(Badge, { variant: "outline", children: "Empty Balance" })
|
|
2100
|
-
] })
|
|
2101
|
-
] })
|
|
2102
|
-
] });
|
|
2103
|
-
};
|
|
2104
|
-
var RecentPayments = () => {
|
|
2105
|
-
const { payments, isLoadingPayments } = useOverviewContext();
|
|
2106
|
-
const formatCurrency = (amount) => {
|
|
2107
|
-
if (amount === null || amount === void 0) return "$0.00";
|
|
2108
|
-
const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
|
|
2109
|
-
return new Intl.NumberFormat("en-US", {
|
|
2110
|
-
style: "currency",
|
|
2111
|
-
currency: "USD",
|
|
2112
|
-
minimumFractionDigits: 2
|
|
2113
|
-
}).format(numAmount);
|
|
2114
|
-
};
|
|
2115
|
-
const getRelativeTime = (date) => {
|
|
2116
|
-
if (!date) return "N/A";
|
|
2117
|
-
const m = moment.utc(date).local();
|
|
2118
|
-
const now = moment();
|
|
2119
|
-
const diffInSeconds = now.diff(m, "seconds");
|
|
2120
|
-
if (diffInSeconds < 60) return "Just now";
|
|
2121
|
-
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
|
|
2122
|
-
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
|
|
2123
|
-
return `${Math.floor(diffInSeconds / 86400)}d ago`;
|
|
2124
|
-
};
|
|
2125
|
-
const getStatusVariant = (status) => {
|
|
2126
|
-
switch (status?.toLowerCase()) {
|
|
2127
|
-
case "completed":
|
|
2128
|
-
case "success":
|
|
2129
|
-
return "default";
|
|
2130
|
-
case "pending":
|
|
2131
|
-
case "confirming":
|
|
2132
|
-
return "secondary";
|
|
2133
|
-
case "failed":
|
|
2134
|
-
case "error":
|
|
2135
|
-
case "expired":
|
|
2136
|
-
return "destructive";
|
|
2137
|
-
default:
|
|
2138
|
-
return "outline";
|
|
2139
|
-
}
|
|
2140
|
-
};
|
|
2141
|
-
if (isLoadingPayments) {
|
|
2142
|
-
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
2143
|
-
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2", children: [
|
|
2144
|
-
/* @__PURE__ */ jsx(History, { className: "h-5 w-5" }),
|
|
2145
|
-
"Recent Payments"
|
|
2146
|
-
] }) }),
|
|
2147
|
-
/* @__PURE__ */ jsx(CardContent, { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-3 border rounded-sm", children: [
|
|
2148
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2149
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" }),
|
|
2150
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
|
|
2151
|
-
] }),
|
|
2152
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-16" })
|
|
2153
|
-
] }, i)) })
|
|
2154
|
-
] });
|
|
2155
|
-
}
|
|
2156
|
-
const recentPaymentsList = payments?.results?.slice(0, 5) || [];
|
|
2157
|
-
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
2158
|
-
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
|
|
2159
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2160
|
-
/* @__PURE__ */ jsx(History, { className: "h-5 w-5" }),
|
|
2161
|
-
"Recent Payments"
|
|
2162
|
-
] }),
|
|
2163
|
-
/* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", children: [
|
|
2164
|
-
"View All",
|
|
2165
|
-
/* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 ml-2" })
|
|
2166
|
-
] })
|
|
2167
|
-
] }) }),
|
|
2168
|
-
/* @__PURE__ */ jsx(CardContent, { children: recentPaymentsList.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8 text-muted-foreground", children: [
|
|
2169
|
-
/* @__PURE__ */ jsx(History, { className: "h-12 w-12 mx-auto mb-4 opacity-50" }),
|
|
2170
|
-
/* @__PURE__ */ jsx("p", { children: "No recent payments" }),
|
|
2171
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm mt-2", children: "Create your first payment to get started" })
|
|
2172
|
-
] }) : /* @__PURE__ */ jsx("div", { className: "space-y-3", children: recentPaymentsList.map((payment) => /* @__PURE__ */ jsxs(
|
|
2173
|
-
"div",
|
|
2174
|
-
{
|
|
2175
|
-
className: "flex items-center justify-between p-3 border rounded-sm hover:bg-accent cursor-pointer transition-colors",
|
|
2176
|
-
onClick: () => openPaymentDetailsDialog(String(payment.id)),
|
|
2177
|
-
children: [
|
|
2178
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
3275
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-muted rounded-xl p-4 space-y-3", children: [
|
|
3276
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
3277
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Amount to send" }),
|
|
2179
3278
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2180
|
-
/* @__PURE__ */ jsx(
|
|
2181
|
-
/* @__PURE__ */
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
payment.currency_code || "USD"
|
|
3279
|
+
/* @__PURE__ */ jsx(TokenIcon, { symbol: payment.currency_code, size: 24 }),
|
|
3280
|
+
/* @__PURE__ */ jsxs("span", { className: "font-mono font-bold text-lg", children: [
|
|
3281
|
+
payment.pay_amount,
|
|
3282
|
+
" ",
|
|
3283
|
+
payment.currency_code
|
|
3284
|
+
] })
|
|
2187
3285
|
] })
|
|
2188
3286
|
] }),
|
|
2189
|
-
/* @__PURE__ */
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
}
|
|
2196
|
-
|
|
2197
|
-
return /* @__PURE__ */ jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxs("div", { className: "grid gap-6 lg:grid-cols-2", children: [
|
|
2198
|
-
/* @__PURE__ */ jsx(BalanceCard, {}),
|
|
2199
|
-
/* @__PURE__ */ jsx(RecentPayments, {})
|
|
2200
|
-
] }) });
|
|
2201
|
-
};
|
|
2202
|
-
var PaymentsList = () => {
|
|
2203
|
-
const pagination = useDRFPagination(1, 20);
|
|
2204
|
-
const {
|
|
2205
|
-
data: payments,
|
|
2206
|
-
error,
|
|
2207
|
-
isLoading: isLoadingPayments,
|
|
2208
|
-
mutate: refreshPayments
|
|
2209
|
-
} = usePaymentsPaymentsList(pagination.params, apiPayments);
|
|
2210
|
-
const paymentsList = payments?.results || [];
|
|
2211
|
-
payments?.count || 0;
|
|
2212
|
-
const [searchTerm, setSearchTerm] = useState("");
|
|
2213
|
-
const [statusFilter, setStatusFilter] = useState("all");
|
|
2214
|
-
const formatCurrency = (amount) => {
|
|
2215
|
-
if (amount === null || amount === void 0) return "$0.00";
|
|
2216
|
-
const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
|
|
2217
|
-
return new Intl.NumberFormat("en-US", {
|
|
2218
|
-
style: "currency",
|
|
2219
|
-
currency: "USD",
|
|
2220
|
-
minimumFractionDigits: 2
|
|
2221
|
-
}).format(numAmount);
|
|
2222
|
-
};
|
|
2223
|
-
const getRelativeTime = (date) => {
|
|
2224
|
-
if (!date) return "N/A";
|
|
2225
|
-
const m = moment.utc(date).local();
|
|
2226
|
-
const now = moment();
|
|
2227
|
-
const diffInSeconds = now.diff(m, "seconds");
|
|
2228
|
-
if (diffInSeconds < 60) return "Just now";
|
|
2229
|
-
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
|
|
2230
|
-
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
|
|
2231
|
-
return `${Math.floor(diffInSeconds / 86400)}d ago`;
|
|
2232
|
-
};
|
|
2233
|
-
const formatDate = (date) => {
|
|
2234
|
-
if (!date) return "N/A";
|
|
2235
|
-
return moment.utc(date).local().format("MMM D, YYYY");
|
|
2236
|
-
};
|
|
2237
|
-
const getStatusVariant = (status) => {
|
|
2238
|
-
switch (status?.toLowerCase()) {
|
|
2239
|
-
case "completed":
|
|
2240
|
-
case "success":
|
|
2241
|
-
return "default";
|
|
2242
|
-
case "pending":
|
|
2243
|
-
case "confirming":
|
|
2244
|
-
return "secondary";
|
|
2245
|
-
case "failed":
|
|
2246
|
-
case "error":
|
|
2247
|
-
case "expired":
|
|
2248
|
-
return "destructive";
|
|
2249
|
-
default:
|
|
2250
|
-
return "outline";
|
|
2251
|
-
}
|
|
2252
|
-
};
|
|
2253
|
-
const handleSearch = (value) => {
|
|
2254
|
-
setSearchTerm(value);
|
|
2255
|
-
};
|
|
2256
|
-
const handleStatusFilter = (status) => {
|
|
2257
|
-
setStatusFilter(status);
|
|
2258
|
-
};
|
|
2259
|
-
const truncateId = (id) => {
|
|
2260
|
-
if (!id) return "N/A";
|
|
2261
|
-
const str = id.toString();
|
|
2262
|
-
return str.length > 8 ? `${str.slice(0, 8)}...` : str;
|
|
2263
|
-
};
|
|
2264
|
-
const filteredPayments = paymentsList.filter((payment) => {
|
|
2265
|
-
const matchesSearch = searchTerm ? payment.id?.toLowerCase().includes(searchTerm.toLowerCase()) || payment.status?.toLowerCase().includes(searchTerm.toLowerCase()) || payment.currency_code?.toLowerCase().includes(searchTerm.toLowerCase()) : true;
|
|
2266
|
-
const matchesStatus = statusFilter !== "all" ? payment.status?.toLowerCase() === statusFilter.toLowerCase() : true;
|
|
2267
|
-
return matchesSearch && matchesStatus;
|
|
2268
|
-
}).map((payment) => ({
|
|
2269
|
-
...payment,
|
|
2270
|
-
formattedDate: formatDate(payment.created_at),
|
|
2271
|
-
relativeTime: getRelativeTime(payment.created_at),
|
|
2272
|
-
truncatedId: truncateId(payment.id)
|
|
2273
|
-
}));
|
|
2274
|
-
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
2275
|
-
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between", children: [
|
|
2276
|
-
/* @__PURE__ */ jsx("span", { children: "Payment History" }),
|
|
2277
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2278
|
-
/* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: () => refreshPayments(), disabled: isLoadingPayments, children: [
|
|
2279
|
-
/* @__PURE__ */ jsx(RefreshCw, { className: `h-4 w-4 mr-2 ${isLoadingPayments ? "animate-spin" : ""}` }),
|
|
2280
|
-
"Refresh"
|
|
3287
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
3288
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Equivalent" }),
|
|
3289
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: amountUsd })
|
|
3290
|
+
] }),
|
|
3291
|
+
payment.currency_network && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm pt-2 border-t", children: [
|
|
3292
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Network" }),
|
|
3293
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: payment.currency_network })
|
|
3294
|
+
] })
|
|
2281
3295
|
] }),
|
|
2282
|
-
/* @__PURE__ */
|
|
2283
|
-
|
|
2284
|
-
"
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row gap-4", children: [
|
|
2290
|
-
/* @__PURE__ */ jsxs("div", { className: "relative flex-1", children: [
|
|
2291
|
-
/* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
|
|
2292
|
-
/* @__PURE__ */ jsx(
|
|
2293
|
-
Input,
|
|
2294
|
-
{
|
|
2295
|
-
placeholder: "Search by ID, status, or currency...",
|
|
2296
|
-
value: searchTerm,
|
|
2297
|
-
onChange: (e) => handleSearch(e.target.value),
|
|
2298
|
-
className: "pl-10"
|
|
2299
|
-
}
|
|
2300
|
-
)
|
|
3296
|
+
qrCodeUrl && /* @__PURE__ */ jsx("div", { className: "flex justify-center p-6 bg-white rounded-xl", children: /* @__PURE__ */ jsx("img", { src: qrCodeUrl, alt: "Payment QR Code", className: "w-48 h-48" }) }),
|
|
3297
|
+
payment.pay_address && canPay && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
3298
|
+
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Payment Address" }),
|
|
3299
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3300
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all", children: payment.pay_address }),
|
|
3301
|
+
/* @__PURE__ */ jsx(CopyButton, { value: payment.pay_address, variant: "outline", className: "shrink-0" })
|
|
3302
|
+
] })
|
|
2301
3303
|
] }),
|
|
2302
|
-
/* @__PURE__ */
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
3304
|
+
isExpired && onCreateNew && /* @__PURE__ */ jsx(
|
|
3305
|
+
Button,
|
|
3306
|
+
{
|
|
3307
|
+
size: "lg",
|
|
3308
|
+
className: "w-full",
|
|
3309
|
+
onClick: () => {
|
|
3310
|
+
onOpenChange(false);
|
|
3311
|
+
onCreateNew();
|
|
3312
|
+
},
|
|
3313
|
+
children: "Create New Payment"
|
|
3314
|
+
}
|
|
3315
|
+
),
|
|
3316
|
+
payment.transaction_hash && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
3317
|
+
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
|
|
3318
|
+
/* @__PURE__ */ jsx("div", { className: "p-3 bg-muted rounded-xl font-mono text-sm break-all", children: payment.transaction_hash })
|
|
3319
|
+
] }),
|
|
3320
|
+
payment.payment_url && canPay && /* @__PURE__ */ jsxs(
|
|
3321
|
+
Button,
|
|
3322
|
+
{
|
|
3323
|
+
variant: "outline",
|
|
3324
|
+
className: "w-full",
|
|
3325
|
+
onClick: () => window.open(payment.payment_url, "_blank"),
|
|
3326
|
+
children: [
|
|
3327
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4 mr-2" }),
|
|
3328
|
+
"Open in Payment Provider"
|
|
3329
|
+
]
|
|
3330
|
+
}
|
|
3331
|
+
),
|
|
3332
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 text-xs text-muted-foreground pt-4 border-t", children: [
|
|
3333
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
3334
|
+
/* @__PURE__ */ jsx("span", { children: "Payment ID" }),
|
|
3335
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono", children: payment.id })
|
|
3336
|
+
] }),
|
|
3337
|
+
payment.internal_payment_id && /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
3338
|
+
/* @__PURE__ */ jsx("span", { children: "Order #" }),
|
|
3339
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono", children: payment.internal_payment_id })
|
|
2306
3340
|
] }),
|
|
2307
|
-
/* @__PURE__ */ jsxs(
|
|
2308
|
-
/* @__PURE__ */ jsx(
|
|
2309
|
-
/* @__PURE__ */ jsx(
|
|
2310
|
-
/* @__PURE__ */ jsx(SelectItem, { value: "pending", children: "Pending" }),
|
|
2311
|
-
/* @__PURE__ */ jsx(SelectItem, { value: "confirming", children: "Confirming" }),
|
|
2312
|
-
/* @__PURE__ */ jsx(SelectItem, { value: "failed", children: "Failed" }),
|
|
2313
|
-
/* @__PURE__ */ jsx(SelectItem, { value: "expired", children: "Expired" })
|
|
3341
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
3342
|
+
/* @__PURE__ */ jsx("span", { children: "Created" }),
|
|
3343
|
+
/* @__PURE__ */ jsx("span", { children: createdAt })
|
|
2314
3344
|
] })
|
|
2315
|
-
] })
|
|
2316
|
-
] }),
|
|
2317
|
-
isLoadingPayments ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 border rounded-sm", children: [
|
|
2318
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2319
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" }),
|
|
2320
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
|
|
2321
3345
|
] }),
|
|
2322
|
-
/* @__PURE__ */
|
|
2323
|
-
|
|
2324
|
-
/* @__PURE__ */ jsx("div", { className: "w-16 h-16 mx-auto mb-4 bg-muted rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx(Search, { className: "w-8 h-8 text-muted-foreground" }) }),
|
|
2325
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "No Payments Found" }),
|
|
2326
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-4", children: searchTerm || statusFilter !== "all" ? "No payments match your current filters" : "You haven't made any payments yet" }),
|
|
2327
|
-
/* @__PURE__ */ jsxs(Button, { onClick: () => openCreatePaymentDialog(), children: [
|
|
2328
|
-
/* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
|
|
2329
|
-
"Create Payment"
|
|
2330
|
-
] })
|
|
2331
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2332
|
-
/* @__PURE__ */ jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs(Table, { children: [
|
|
2333
|
-
/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
2334
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Date" }),
|
|
2335
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Amount" }),
|
|
2336
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Currency" }),
|
|
2337
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Status" }),
|
|
2338
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Provider" }),
|
|
2339
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Payment ID" }),
|
|
2340
|
-
/* @__PURE__ */ jsx(TableHead, { className: "text-right", children: "Actions" })
|
|
2341
|
-
] }) }),
|
|
2342
|
-
/* @__PURE__ */ jsx(TableBody, { children: filteredPayments.map((payment) => /* @__PURE__ */ jsxs(
|
|
2343
|
-
TableRow,
|
|
2344
|
-
{
|
|
2345
|
-
className: "cursor-pointer hover:bg-accent",
|
|
2346
|
-
onClick: () => openPaymentDetailsDialog(String(payment.id)),
|
|
2347
|
-
children: [
|
|
2348
|
-
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { children: [
|
|
2349
|
-
/* @__PURE__ */ jsx("div", { className: "font-medium", children: payment.formattedDate }),
|
|
2350
|
-
/* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: payment.relativeTime })
|
|
2351
|
-
] }) }),
|
|
2352
|
-
/* @__PURE__ */ jsx(TableCell, { className: "font-mono font-semibold", children: formatCurrency(payment.amount_usd) }),
|
|
2353
|
-
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Badge, { variant: "outline", children: payment.currency_code || "USD" }) }),
|
|
2354
|
-
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Badge, { variant: getStatusVariant(payment.status), children: payment.status }) }),
|
|
2355
|
-
/* @__PURE__ */ jsx(TableCell, { className: "text-sm text-muted-foreground", children: "NowPayments" }),
|
|
2356
|
-
/* @__PURE__ */ jsx(TableCell, { className: "font-mono text-sm text-muted-foreground", children: payment.truncatedId }),
|
|
2357
|
-
/* @__PURE__ */ jsx(TableCell, { className: "text-right", children: /* @__PURE__ */ jsx(
|
|
2358
|
-
Button,
|
|
2359
|
-
{
|
|
2360
|
-
variant: "ghost",
|
|
2361
|
-
size: "sm",
|
|
2362
|
-
onClick: (e) => {
|
|
2363
|
-
e.stopPropagation();
|
|
2364
|
-
openPaymentDetailsDialog(String(payment.id));
|
|
2365
|
-
},
|
|
2366
|
-
children: /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4" })
|
|
2367
|
-
}
|
|
2368
|
-
) })
|
|
2369
|
-
]
|
|
2370
|
-
},
|
|
2371
|
-
payment.id
|
|
2372
|
-
)) })
|
|
2373
|
-
] }) }),
|
|
2374
|
-
/* @__PURE__ */ jsx(
|
|
2375
|
-
StaticPagination,
|
|
3346
|
+
/* @__PURE__ */ jsxs(
|
|
3347
|
+
Button,
|
|
2376
3348
|
{
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
3349
|
+
variant: "ghost",
|
|
3350
|
+
className: "w-full",
|
|
3351
|
+
onClick: () => mutate(),
|
|
3352
|
+
children: [
|
|
3353
|
+
/* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4 mr-2" }),
|
|
3354
|
+
"Refresh Status"
|
|
3355
|
+
]
|
|
2380
3356
|
}
|
|
2381
3357
|
)
|
|
2382
3358
|
] })
|
|
2383
3359
|
] })
|
|
2384
|
-
] });
|
|
2385
|
-
}
|
|
2386
|
-
var
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
const
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
return new Intl.NumberFormat("en-US", {
|
|
2401
|
-
style: "currency",
|
|
2402
|
-
currency: "USD",
|
|
2403
|
-
minimumFractionDigits: 2
|
|
2404
|
-
}).format(amount);
|
|
2405
|
-
};
|
|
2406
|
-
const formatDate = (date) => {
|
|
2407
|
-
if (!date) return "N/A";
|
|
2408
|
-
try {
|
|
2409
|
-
return moment.utc(date).local().format("MMM D, YYYY hh:mm A");
|
|
2410
|
-
} catch {
|
|
2411
|
-
return "Invalid date";
|
|
2412
|
-
}
|
|
2413
|
-
};
|
|
2414
|
-
const getRelativeTime = (date) => {
|
|
2415
|
-
if (!date) return "N/A";
|
|
2416
|
-
const m = moment.utc(date).local();
|
|
2417
|
-
const now = moment();
|
|
2418
|
-
const diffInSeconds = now.diff(m, "seconds");
|
|
2419
|
-
if (diffInSeconds < 60) return "Just now";
|
|
2420
|
-
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
|
|
2421
|
-
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
|
|
2422
|
-
return `${Math.floor(diffInSeconds / 86400)}d ago`;
|
|
2423
|
-
};
|
|
2424
|
-
const getTypeVariant = (type) => {
|
|
2425
|
-
switch (type?.toLowerCase()) {
|
|
2426
|
-
case "deposit":
|
|
2427
|
-
case "credit":
|
|
2428
|
-
return "default";
|
|
2429
|
-
case "withdrawal":
|
|
2430
|
-
case "debit":
|
|
2431
|
-
return "destructive";
|
|
2432
|
-
default:
|
|
2433
|
-
return "outline";
|
|
3360
|
+
] }) });
|
|
3361
|
+
}
|
|
3362
|
+
var WalletContent = () => {
|
|
3363
|
+
const [addFundsOpen, setAddFundsOpen] = useState(false);
|
|
3364
|
+
const [withdrawOpen, setWithdrawOpen] = useState(false);
|
|
3365
|
+
const [selectedPaymentId, setSelectedPaymentId] = useState(null);
|
|
3366
|
+
const [paymentSheetOpen, setPaymentSheetOpen] = useState(false);
|
|
3367
|
+
const [selectedWithdrawalId, setSelectedWithdrawalId] = useState(null);
|
|
3368
|
+
const [withdrawalSheetOpen, setWithdrawalSheetOpen] = useState(false);
|
|
3369
|
+
const handleActivityClick = useCallback((item) => {
|
|
3370
|
+
if (item.payment) {
|
|
3371
|
+
setSelectedPaymentId(item.payment.id);
|
|
3372
|
+
setPaymentSheetOpen(true);
|
|
3373
|
+
} else if (item.withdrawal) {
|
|
3374
|
+
setSelectedWithdrawalId(item.withdrawal.id);
|
|
3375
|
+
setWithdrawalSheetOpen(true);
|
|
2434
3376
|
}
|
|
2435
|
-
};
|
|
2436
|
-
const
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
};
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
] }) }),
|
|
2490
|
-
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
|
|
2491
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row gap-4", children: [
|
|
2492
|
-
/* @__PURE__ */ jsxs("div", { className: "relative flex-1", children: [
|
|
2493
|
-
/* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
|
|
2494
|
-
/* @__PURE__ */ jsx(
|
|
2495
|
-
Input,
|
|
2496
|
-
{
|
|
2497
|
-
placeholder: "Search by ID, description, or type...",
|
|
2498
|
-
value: searchTerm,
|
|
2499
|
-
onChange: (e) => handleSearch(e.target.value),
|
|
2500
|
-
className: "pl-10"
|
|
2501
|
-
}
|
|
2502
|
-
)
|
|
2503
|
-
] }),
|
|
2504
|
-
/* @__PURE__ */ jsxs(Select, { value: typeFilter, onValueChange: handleTypeFilter, children: [
|
|
2505
|
-
/* @__PURE__ */ jsxs(SelectTrigger, { className: "w-full sm:w-48", children: [
|
|
2506
|
-
/* @__PURE__ */ jsx(Filter, { className: "h-4 w-4 mr-2" }),
|
|
2507
|
-
/* @__PURE__ */ jsx(SelectValue, { placeholder: "Filter by type" })
|
|
2508
|
-
] }),
|
|
2509
|
-
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
2510
|
-
/* @__PURE__ */ jsx(SelectItem, { value: "all", children: "All Types" }),
|
|
2511
|
-
/* @__PURE__ */ jsx(SelectItem, { value: "deposit", children: "Deposits" }),
|
|
2512
|
-
/* @__PURE__ */ jsx(SelectItem, { value: "withdrawal", children: "Withdrawals" })
|
|
2513
|
-
] })
|
|
2514
|
-
] })
|
|
2515
|
-
] }),
|
|
2516
|
-
filteredTransactions.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
|
|
2517
|
-
/* @__PURE__ */ jsx("div", { className: "w-16 h-16 mx-auto mb-4 bg-muted rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx(History, { className: "w-8 h-8 text-muted-foreground" }) }),
|
|
2518
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "No Transactions Found" }),
|
|
2519
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: searchTerm || typeFilter !== "all" ? "No transactions match your current filters" : "You don't have any transactions yet" })
|
|
2520
|
-
] }) : /* @__PURE__ */ jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs(Table, { children: [
|
|
2521
|
-
/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
2522
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Date & Time" }),
|
|
2523
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Type" }),
|
|
2524
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Amount" }),
|
|
2525
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Balance After" }),
|
|
2526
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Description" }),
|
|
2527
|
-
/* @__PURE__ */ jsx(TableHead, { children: "Reference" })
|
|
2528
|
-
] }) }),
|
|
2529
|
-
/* @__PURE__ */ jsx(TableBody, { children: filteredTransactions.map((transaction, index) => /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
2530
|
-
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { children: [
|
|
2531
|
-
/* @__PURE__ */ jsx("div", { className: "font-medium", children: transaction.formattedDate }),
|
|
2532
|
-
/* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: transaction.relativeTime })
|
|
2533
|
-
] }) }),
|
|
2534
|
-
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2535
|
-
getTypeIcon(transaction.type),
|
|
2536
|
-
/* @__PURE__ */ jsx(Badge, { variant: getTypeVariant(transaction.type), children: transaction.type || "Unknown" })
|
|
2537
|
-
] }) }),
|
|
2538
|
-
/* @__PURE__ */ jsx(TableCell, { className: "font-mono font-semibold", children: /* @__PURE__ */ jsxs("span", { className: transaction.isDeposit ? "text-green-600" : "text-red-600", children: [
|
|
2539
|
-
transaction.isDeposit ? "+" : "-",
|
|
2540
|
-
formatCurrency(Math.abs(transaction.amount || transaction.amount_usd || 0))
|
|
2541
|
-
] }) }),
|
|
2542
|
-
/* @__PURE__ */ jsx(TableCell, { className: "font-mono", children: formatCurrency(transaction.balance_after || 0) }),
|
|
2543
|
-
/* @__PURE__ */ jsx(TableCell, { className: "text-sm", children: transaction.description || transaction.note || "No description" }),
|
|
2544
|
-
/* @__PURE__ */ jsx(TableCell, { className: "font-mono text-sm text-muted-foreground", children: transaction.truncatedRef })
|
|
2545
|
-
] }, transaction.id || index)) })
|
|
2546
|
-
] }) })
|
|
2547
|
-
] })
|
|
3377
|
+
}, []);
|
|
3378
|
+
const handlePaymentCreated = useCallback((payment) => {
|
|
3379
|
+
setSelectedPaymentId(payment.id);
|
|
3380
|
+
setPaymentSheetOpen(true);
|
|
3381
|
+
}, []);
|
|
3382
|
+
return /* @__PURE__ */ jsxs("div", { className: "min-h-screen", children: [
|
|
3383
|
+
/* @__PURE__ */ jsx(
|
|
3384
|
+
BalanceHero,
|
|
3385
|
+
{
|
|
3386
|
+
onAddFunds: () => setAddFundsOpen(true),
|
|
3387
|
+
onWithdraw: () => setWithdrawOpen(true),
|
|
3388
|
+
className: "bg-muted/30 border-b"
|
|
3389
|
+
}
|
|
3390
|
+
),
|
|
3391
|
+
/* @__PURE__ */ jsx(
|
|
3392
|
+
ActivityList,
|
|
3393
|
+
{
|
|
3394
|
+
onItemClick: handleActivityClick,
|
|
3395
|
+
limit: 20,
|
|
3396
|
+
className: "max-w-2xl mx-auto pb-12"
|
|
3397
|
+
}
|
|
3398
|
+
),
|
|
3399
|
+
/* @__PURE__ */ jsx(
|
|
3400
|
+
AddFundsSheet,
|
|
3401
|
+
{
|
|
3402
|
+
open: addFundsOpen,
|
|
3403
|
+
onOpenChange: setAddFundsOpen,
|
|
3404
|
+
onSuccess: handlePaymentCreated
|
|
3405
|
+
}
|
|
3406
|
+
),
|
|
3407
|
+
/* @__PURE__ */ jsx(
|
|
3408
|
+
WithdrawSheet,
|
|
3409
|
+
{
|
|
3410
|
+
open: withdrawOpen,
|
|
3411
|
+
onOpenChange: setWithdrawOpen
|
|
3412
|
+
}
|
|
3413
|
+
),
|
|
3414
|
+
/* @__PURE__ */ jsx(
|
|
3415
|
+
PaymentSheet,
|
|
3416
|
+
{
|
|
3417
|
+
paymentId: selectedPaymentId,
|
|
3418
|
+
open: paymentSheetOpen,
|
|
3419
|
+
onOpenChange: setPaymentSheetOpen,
|
|
3420
|
+
onCreateNew: () => setAddFundsOpen(true)
|
|
3421
|
+
}
|
|
3422
|
+
),
|
|
3423
|
+
/* @__PURE__ */ jsx(
|
|
3424
|
+
WithdrawalSheet,
|
|
3425
|
+
{
|
|
3426
|
+
withdrawalId: selectedWithdrawalId,
|
|
3427
|
+
open: withdrawalSheetOpen,
|
|
3428
|
+
onOpenChange: setWithdrawalSheetOpen
|
|
3429
|
+
}
|
|
3430
|
+
)
|
|
2548
3431
|
] });
|
|
2549
3432
|
};
|
|
2550
|
-
|
|
2551
|
-
return /* @__PURE__ */ jsx(
|
|
2552
|
-
}
|
|
2553
|
-
var PaymentsLayout = () => {
|
|
2554
|
-
return /* @__PURE__ */ jsx(RootPaymentsProvider, { children: /* @__PURE__ */ jsxs("div", { className: "h-full p-6 space-y-6", children: [
|
|
2555
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
2556
|
-
/* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold tracking-tight", children: "Payments" }),
|
|
2557
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "Manage your payments, balance, and transaction history" })
|
|
2558
|
-
] }),
|
|
2559
|
-
/* @__PURE__ */ jsxs(Tabs, { defaultValue: "overview", className: "space-y-6", children: [
|
|
2560
|
-
/* @__PURE__ */ jsxs(TabsList, { className: "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", children: [
|
|
2561
|
-
/* @__PURE__ */ jsxs(TabsTrigger, { value: "overview", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
|
|
2562
|
-
/* @__PURE__ */ jsx(Wallet, { className: "h-4 w-4" }),
|
|
2563
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Overview" })
|
|
2564
|
-
] }),
|
|
2565
|
-
/* @__PURE__ */ jsxs(TabsTrigger, { value: "payments", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
|
|
2566
|
-
/* @__PURE__ */ jsx(CreditCard, { className: "h-4 w-4" }),
|
|
2567
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Payments" })
|
|
2568
|
-
] }),
|
|
2569
|
-
/* @__PURE__ */ jsxs(TabsTrigger, { value: "transactions", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
|
|
2570
|
-
/* @__PURE__ */ jsx(History, { className: "h-4 w-4" }),
|
|
2571
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Transactions" })
|
|
2572
|
-
] })
|
|
2573
|
-
] }),
|
|
2574
|
-
/* @__PURE__ */ jsx(TabsContent, { value: "overview", className: "space-y-6", children: /* @__PURE__ */ jsx(OverviewProvider, { children: /* @__PURE__ */ jsxs(PaymentsProvider, { children: [
|
|
2575
|
-
/* @__PURE__ */ jsx(OverviewView, {}),
|
|
2576
|
-
/* @__PURE__ */ jsx(CreatePaymentDialog, {})
|
|
2577
|
-
] }) }) }),
|
|
2578
|
-
/* @__PURE__ */ jsx(TabsContent, { value: "payments", className: "space-y-6", children: /* @__PURE__ */ jsxs(PaymentsProvider, { children: [
|
|
2579
|
-
/* @__PURE__ */ jsx(PaymentsView, {}),
|
|
2580
|
-
/* @__PURE__ */ jsx(CreatePaymentDialog, {})
|
|
2581
|
-
] }) }),
|
|
2582
|
-
/* @__PURE__ */ jsx(TabsContent, { value: "transactions", className: "space-y-6", children: /* @__PURE__ */ jsx(OverviewProvider, { children: /* @__PURE__ */ jsx(TransactionsView, {}) }) })
|
|
2583
|
-
] }),
|
|
2584
|
-
/* @__PURE__ */ jsx(PaymentDetailsDialog, {})
|
|
2585
|
-
] }) });
|
|
2586
|
-
};
|
|
3433
|
+
function WalletPage() {
|
|
3434
|
+
return /* @__PURE__ */ jsx(WalletProvider, { children: /* @__PURE__ */ jsx(WalletContent, {}) });
|
|
3435
|
+
}
|
|
2587
3436
|
|
|
2588
3437
|
// package.json
|
|
2589
3438
|
var package_default = {
|
|
2590
3439
|
name: "@djangocfg/ext-payments",
|
|
2591
|
-
version: "1.0.
|
|
3440
|
+
version: "1.0.19",
|
|
2592
3441
|
description: "Payments system extension for DjangoCFG",
|
|
2593
3442
|
keywords: [
|
|
2594
3443
|
"django",
|
|
@@ -2625,11 +3474,6 @@ var package_default = {
|
|
|
2625
3474
|
import: "./dist/index.js",
|
|
2626
3475
|
require: "./dist/index.cjs"
|
|
2627
3476
|
},
|
|
2628
|
-
"./hooks": {
|
|
2629
|
-
types: "./dist/hooks.d.ts",
|
|
2630
|
-
import: "./dist/hooks.js",
|
|
2631
|
-
require: "./dist/hooks.cjs"
|
|
2632
|
-
},
|
|
2633
3477
|
"./config": {
|
|
2634
3478
|
types: "./dist/config.d.ts",
|
|
2635
3479
|
import: "./dist/config.js",
|
|
@@ -2657,8 +3501,10 @@ var package_default = {
|
|
|
2657
3501
|
"p-retry": "^7.0.0",
|
|
2658
3502
|
react: "^19",
|
|
2659
3503
|
swr: "^2.3.7",
|
|
2660
|
-
zod: "^4.
|
|
2661
|
-
moment: "^2.30.1"
|
|
3504
|
+
zod: "^4.3.4",
|
|
3505
|
+
moment: "^2.30.1",
|
|
3506
|
+
"react-hook-form": "^7.69.0",
|
|
3507
|
+
"@hookform/resolvers": "^5.2.2"
|
|
2662
3508
|
},
|
|
2663
3509
|
devDependencies: {
|
|
2664
3510
|
"@djangocfg/api": "workspace:*",
|
|
@@ -2731,4 +3577,4 @@ export default function CryptoCheckout() {
|
|
|
2731
3577
|
]
|
|
2732
3578
|
});
|
|
2733
3579
|
|
|
2734
|
-
export { API, APIClient, APIError, APILogger, BalanceSchema, CookieStorageAdapter, CurrencySchema, DEFAULT_RETRY_CONFIG, enums_exports as Enums, models_exports as ExtPaymentsPaymentsTypes, FetchAdapter, fetchers_exports as Fetchers, LocalStorageAdapter, MemoryStorageAdapter, NetworkError,
|
|
3580
|
+
export { API, APIClient, APIError, APILogger, ActivityItem, ActivityList, AddFundsSheet, BalanceHero, BalanceSchema, CookieStorageAdapter, CurrencySchema, DEFAULT_RETRY_CONFIG, enums_exports as Enums, models_exports as ExtPaymentsPaymentsTypes, FetchAdapter, fetchers_exports as Fetchers, LocalStorageAdapter, MemoryStorageAdapter, NetworkError, PaginatedPaymentListListSchema, PaginatedWithdrawalListListSchema, PaymentCreateRequestSchema, PaymentCreateResponseSchema, PaymentDetailSchema, PaymentListSchema, PaymentSheet, REFRESH_TOKEN_KEY, schemas_exports as Schemas, TOKEN_KEY, TransactionSchema, WalletPage, WithdrawSheet, WithdrawalCancelResponseSchema, WithdrawalCreateRequestSchema, WithdrawalCreateResponseSchema, WithdrawalDetailSchema, WithdrawalListSchema, WithdrawalSheet, apiPayments, clearAPITokens, configureAPI, createPaymentsPaymentsConfirmCreate, createPaymentsPaymentsCreateCreate, createPaymentsWithdrawalsCancelCreate, createPaymentsWithdrawalsCreateCreate, dispatchValidationError, extensionConfig, formatZodError, getAPIInstance, getPaymentsBalanceRetrieve, getPaymentsCurrenciesEstimateRetrieve, getPaymentsCurrenciesList, getPaymentsCurrenciesWithdrawalEstimateRetrieve, getPaymentsPaymentsList, getPaymentsPaymentsRetrieve, getPaymentsPaymentsStatusRetrieve, getPaymentsTransactionsList, getPaymentsWithdrawalsList, getPaymentsWithdrawalsRetrieve, isAPIConfigured, onValidationError, reconfigureAPI, resetAPI, shouldRetry, withRetry };
|