@djangocfg/ext-payments 1.0.17 → 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 +1 -1
- package/dist/config.js +1 -1
- package/dist/index.cjs +1175 -290
- package/dist/index.d.cts +226 -80
- package/dist/index.d.ts +226 -80
- package/dist/index.js +1157 -255
- package/package.json +9 -9
- package/src/WalletPage.tsx +100 -0
- package/src/api/generated/ext_payments/CLAUDE.md +6 -4
- package/src/api/generated/ext_payments/_utils/fetchers/ext_payments__payments.ts +37 -6
- package/src/api/generated/ext_payments/_utils/hooks/ext_payments__payments.ts +34 -3
- package/src/api/generated/ext_payments/_utils/schemas/Balance.schema.ts +1 -1
- 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/WithdrawalCreateResponse.schema.ts +22 -0
- package/src/api/generated/ext_payments/_utils/schemas/WithdrawalDetail.schema.ts +5 -5
- package/src/api/generated/ext_payments/_utils/schemas/WithdrawalList.schema.ts +2 -2
- package/src/api/generated/ext_payments/_utils/schemas/index.ts +3 -0
- package/src/api/generated/ext_payments/client.ts +1 -1
- package/src/api/generated/ext_payments/ext_payments__payments/client.ts +49 -4
- package/src/api/generated/ext_payments/ext_payments__payments/models.ts +33 -14
- package/src/api/generated/ext_payments/index.ts +1 -1
- package/src/api/generated/ext_payments/schema.json +167 -33
- package/src/components/AddFundsSheet.tsx +157 -73
- package/src/components/CurrencyCombobox.tsx +49 -0
- package/src/components/PaymentSheet.tsx +94 -32
- package/src/components/WithdrawSheet.tsx +121 -95
- package/src/components/WithdrawalSheet.tsx +332 -0
- package/src/components/index.ts +1 -8
- package/src/config.ts +1 -0
- package/src/contexts/WalletContext.tsx +10 -9
- package/src/contexts/index.ts +5 -1
- package/src/contexts/types.ts +46 -0
- package/src/hooks/index.ts +3 -0
- 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 +3 -0
- 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/components/ResponsiveSheet.tsx +0 -151
package/dist/index.cjs
CHANGED
|
@@ -1,44 +1,25 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var api = require('@djangocfg/ext-base/api');
|
|
3
5
|
var consola = require('consola');
|
|
4
6
|
var pRetry = require('p-retry');
|
|
5
7
|
var zod = require('zod');
|
|
6
|
-
var
|
|
8
|
+
var useSWR = require('swr');
|
|
9
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
10
|
var lucideReact = require('lucide-react');
|
|
8
11
|
var uiCore = require('@djangocfg/ui-core');
|
|
9
12
|
var lib = require('@djangocfg/ui-core/lib');
|
|
10
|
-
var
|
|
11
|
-
var useSWR2 = require('swr');
|
|
12
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
13
|
-
var moment2 = require('moment');
|
|
13
|
+
var moment3 = require('moment');
|
|
14
14
|
var reactHookForm = require('react-hook-form');
|
|
15
15
|
var zod$1 = require('@hookform/resolvers/zod');
|
|
16
16
|
var extBase = require('@djangocfg/ext-base');
|
|
17
17
|
|
|
18
18
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
19
|
|
|
20
|
-
function _interopNamespace(e) {
|
|
21
|
-
if (e && e.__esModule) return e;
|
|
22
|
-
var n = Object.create(null);
|
|
23
|
-
if (e) {
|
|
24
|
-
Object.keys(e).forEach(function (k) {
|
|
25
|
-
if (k !== 'default') {
|
|
26
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
27
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
28
|
-
enumerable: true,
|
|
29
|
-
get: function () { return e[k]; }
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
n.default = e;
|
|
35
|
-
return Object.freeze(n);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
20
|
var pRetry__default = /*#__PURE__*/_interopDefault(pRetry);
|
|
39
|
-
var
|
|
40
|
-
var
|
|
41
|
-
var moment2__default = /*#__PURE__*/_interopDefault(moment2);
|
|
21
|
+
var useSWR__default = /*#__PURE__*/_interopDefault(useSWR);
|
|
22
|
+
var moment3__default = /*#__PURE__*/_interopDefault(moment3);
|
|
42
23
|
|
|
43
24
|
var __defProp = Object.defineProperty;
|
|
44
25
|
var __export = (target, all) => {
|
|
@@ -64,12 +45,47 @@ var ExtPaymentsPayments = class {
|
|
|
64
45
|
/**
|
|
65
46
|
* Get available currencies
|
|
66
47
|
*
|
|
67
|
-
* Returns list of available currencies with token+network info
|
|
48
|
+
* Returns list of available currencies with token+network info, popular
|
|
49
|
+
* first
|
|
68
50
|
*/
|
|
69
51
|
async currenciesList() {
|
|
70
52
|
const response = await this.client.request("GET", "/cfg/payments/currencies/");
|
|
71
53
|
return response;
|
|
72
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Get currency estimate
|
|
57
|
+
*
|
|
58
|
+
* Get estimated crypto amount for a given USD amount, including min amount
|
|
59
|
+
*/
|
|
60
|
+
async currenciesEstimateRetrieve(...args) {
|
|
61
|
+
const code = args[0];
|
|
62
|
+
const isParamsObject = args.length === 2 && typeof args[1] === "object" && args[1] !== null && !Array.isArray(args[1]);
|
|
63
|
+
let params;
|
|
64
|
+
if (isParamsObject) {
|
|
65
|
+
params = args[1];
|
|
66
|
+
} else {
|
|
67
|
+
params = { amount: args[1] };
|
|
68
|
+
}
|
|
69
|
+
const response = await this.client.request("GET", `/cfg/payments/currencies/${code}/estimate/`, { params });
|
|
70
|
+
return response;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get withdrawal estimate
|
|
74
|
+
*
|
|
75
|
+
* Get estimated crypto amount for withdrawal with fee breakdown
|
|
76
|
+
*/
|
|
77
|
+
async currenciesWithdrawalEstimateRetrieve(...args) {
|
|
78
|
+
const code = args[0];
|
|
79
|
+
const isParamsObject = args.length === 2 && typeof args[1] === "object" && args[1] !== null && !Array.isArray(args[1]);
|
|
80
|
+
let params;
|
|
81
|
+
if (isParamsObject) {
|
|
82
|
+
params = args[1];
|
|
83
|
+
} else {
|
|
84
|
+
params = { amount: args[1] };
|
|
85
|
+
}
|
|
86
|
+
const response = await this.client.request("GET", `/cfg/payments/currencies/${code}/withdrawal-estimate/`, { params });
|
|
87
|
+
return response;
|
|
88
|
+
}
|
|
73
89
|
/**
|
|
74
90
|
* ViewSet for payment operations. Endpoints: - GET /payments/ - List
|
|
75
91
|
* user's payments - GET /payments/{id}/ - Get payment details - POST
|
|
@@ -747,8 +763,8 @@ var APIClient = class {
|
|
|
747
763
|
// src/api/generated/ext_payments/storage.ts
|
|
748
764
|
var LocalStorageAdapter = class {
|
|
749
765
|
logger;
|
|
750
|
-
constructor(
|
|
751
|
-
this.logger =
|
|
766
|
+
constructor(logger2) {
|
|
767
|
+
this.logger = logger2;
|
|
752
768
|
}
|
|
753
769
|
getItem(key) {
|
|
754
770
|
try {
|
|
@@ -790,8 +806,8 @@ var LocalStorageAdapter = class {
|
|
|
790
806
|
};
|
|
791
807
|
var CookieStorageAdapter = class {
|
|
792
808
|
logger;
|
|
793
|
-
constructor(
|
|
794
|
-
this.logger =
|
|
809
|
+
constructor(logger2) {
|
|
810
|
+
this.logger = logger2;
|
|
795
811
|
}
|
|
796
812
|
getItem(key) {
|
|
797
813
|
try {
|
|
@@ -840,8 +856,8 @@ var CookieStorageAdapter = class {
|
|
|
840
856
|
var MemoryStorageAdapter = class {
|
|
841
857
|
storage = /* @__PURE__ */ new Map();
|
|
842
858
|
logger;
|
|
843
|
-
constructor(
|
|
844
|
-
this.logger =
|
|
859
|
+
constructor(logger2) {
|
|
860
|
+
this.logger = logger2;
|
|
845
861
|
}
|
|
846
862
|
getItem(key) {
|
|
847
863
|
const value = this.storage.get(key) || null;
|
|
@@ -926,10 +942,13 @@ __export(schemas_exports, {
|
|
|
926
942
|
PaginatedPaymentListListSchema: () => PaginatedPaymentListListSchema,
|
|
927
943
|
PaginatedWithdrawalListListSchema: () => PaginatedWithdrawalListListSchema,
|
|
928
944
|
PaymentCreateRequestSchema: () => PaymentCreateRequestSchema,
|
|
945
|
+
PaymentCreateResponseSchema: () => PaymentCreateResponseSchema,
|
|
929
946
|
PaymentDetailSchema: () => PaymentDetailSchema,
|
|
930
947
|
PaymentListSchema: () => PaymentListSchema,
|
|
931
948
|
TransactionSchema: () => TransactionSchema,
|
|
949
|
+
WithdrawalCancelResponseSchema: () => WithdrawalCancelResponseSchema,
|
|
932
950
|
WithdrawalCreateRequestSchema: () => WithdrawalCreateRequestSchema,
|
|
951
|
+
WithdrawalCreateResponseSchema: () => WithdrawalCreateResponseSchema,
|
|
933
952
|
WithdrawalDetailSchema: () => WithdrawalDetailSchema,
|
|
934
953
|
WithdrawalListSchema: () => WithdrawalListSchema
|
|
935
954
|
});
|
|
@@ -938,7 +957,7 @@ var BalanceSchema = zod.z.object({
|
|
|
938
957
|
balance_display: zod.z.string(),
|
|
939
958
|
total_deposited: zod.z.string(),
|
|
940
959
|
total_withdrawn: zod.z.string(),
|
|
941
|
-
last_transaction_at: zod.z.
|
|
960
|
+
last_transaction_at: zod.z.string().datetime({ offset: true }).nullable()
|
|
942
961
|
});
|
|
943
962
|
var CurrencySchema = zod.z.object({
|
|
944
963
|
code: zod.z.string(),
|
|
@@ -960,8 +979,8 @@ var PaymentListSchema = zod.z.object({
|
|
|
960
979
|
currency_token: zod.z.string(),
|
|
961
980
|
status: zod.z.nativeEnum(PaymentListStatus),
|
|
962
981
|
status_display: zod.z.string(),
|
|
963
|
-
created_at: zod.z.
|
|
964
|
-
completed_at: zod.z.
|
|
982
|
+
created_at: zod.z.string().datetime({ offset: true }),
|
|
983
|
+
completed_at: zod.z.string().datetime({ offset: true }).nullable()
|
|
965
984
|
});
|
|
966
985
|
|
|
967
986
|
// src/api/generated/ext_payments/_utils/schemas/PaginatedPaymentListList.schema.ts
|
|
@@ -985,8 +1004,8 @@ var WithdrawalListSchema = zod.z.object({
|
|
|
985
1004
|
currency_token: zod.z.string(),
|
|
986
1005
|
status: zod.z.nativeEnum(WithdrawalListStatus),
|
|
987
1006
|
status_display: zod.z.string(),
|
|
988
|
-
created_at: zod.z.
|
|
989
|
-
completed_at: zod.z.
|
|
1007
|
+
created_at: zod.z.string().datetime({ offset: true }),
|
|
1008
|
+
completed_at: zod.z.string().datetime({ offset: true }).nullable()
|
|
990
1009
|
});
|
|
991
1010
|
|
|
992
1011
|
// src/api/generated/ext_payments/_utils/schemas/PaginatedWithdrawalListList.schema.ts
|
|
@@ -1025,14 +1044,21 @@ var PaymentDetailSchema = zod.z.object({
|
|
|
1025
1044
|
transaction_hash: zod.z.string().nullable(),
|
|
1026
1045
|
explorer_link: zod.z.string().nullable(),
|
|
1027
1046
|
confirmations_count: zod.z.int(),
|
|
1028
|
-
expires_at: zod.z.
|
|
1029
|
-
completed_at: zod.z.
|
|
1030
|
-
created_at: zod.z.
|
|
1047
|
+
expires_at: zod.z.string().datetime({ offset: true }).nullable(),
|
|
1048
|
+
completed_at: zod.z.string().datetime({ offset: true }).nullable(),
|
|
1049
|
+
created_at: zod.z.string().datetime({ offset: true }),
|
|
1031
1050
|
is_completed: zod.z.boolean(),
|
|
1032
1051
|
is_failed: zod.z.boolean(),
|
|
1033
1052
|
is_expired: zod.z.boolean(),
|
|
1034
1053
|
description: zod.z.string()
|
|
1035
1054
|
});
|
|
1055
|
+
|
|
1056
|
+
// src/api/generated/ext_payments/_utils/schemas/PaymentCreateResponse.schema.ts
|
|
1057
|
+
var PaymentCreateResponseSchema = zod.z.object({
|
|
1058
|
+
success: zod.z.boolean(),
|
|
1059
|
+
payment: PaymentDetailSchema,
|
|
1060
|
+
qr_code_url: zod.z.union([zod.z.url(), zod.z.literal("")]).nullable()
|
|
1061
|
+
});
|
|
1036
1062
|
var TransactionSchema = zod.z.object({
|
|
1037
1063
|
id: zod.z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
|
|
1038
1064
|
transaction_type: zod.z.nativeEnum(TransactionTransactionType),
|
|
@@ -1042,12 +1068,7 @@ var TransactionSchema = zod.z.object({
|
|
|
1042
1068
|
balance_after: zod.z.string(),
|
|
1043
1069
|
payment_id: zod.z.string().nullable(),
|
|
1044
1070
|
description: zod.z.string(),
|
|
1045
|
-
created_at: zod.z.
|
|
1046
|
-
});
|
|
1047
|
-
var WithdrawalCreateRequestSchema = zod.z.object({
|
|
1048
|
-
amount_usd: zod.z.string(),
|
|
1049
|
-
currency_code: zod.z.string().min(1).max(20),
|
|
1050
|
-
wallet_address: zod.z.string().min(1).max(255)
|
|
1071
|
+
created_at: zod.z.string().datetime({ offset: true })
|
|
1051
1072
|
});
|
|
1052
1073
|
var WithdrawalDetailSchema = zod.z.object({
|
|
1053
1074
|
id: zod.z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
|
|
@@ -1068,11 +1089,28 @@ var WithdrawalDetailSchema = zod.z.object({
|
|
|
1068
1089
|
transaction_hash: zod.z.string().nullable(),
|
|
1069
1090
|
explorer_link: zod.z.string().nullable(),
|
|
1070
1091
|
admin_notes: zod.z.string(),
|
|
1071
|
-
created_at: zod.z.
|
|
1072
|
-
approved_at: zod.z.
|
|
1073
|
-
completed_at: zod.z.
|
|
1074
|
-
rejected_at: zod.z.
|
|
1075
|
-
cancelled_at: zod.z.
|
|
1092
|
+
created_at: zod.z.string().datetime({ offset: true }),
|
|
1093
|
+
approved_at: zod.z.string().datetime({ offset: true }).nullable(),
|
|
1094
|
+
completed_at: zod.z.string().datetime({ offset: true }).nullable(),
|
|
1095
|
+
rejected_at: zod.z.string().datetime({ offset: true }).nullable(),
|
|
1096
|
+
cancelled_at: zod.z.string().datetime({ offset: true }).nullable()
|
|
1097
|
+
});
|
|
1098
|
+
|
|
1099
|
+
// src/api/generated/ext_payments/_utils/schemas/WithdrawalCancelResponse.schema.ts
|
|
1100
|
+
var WithdrawalCancelResponseSchema = zod.z.object({
|
|
1101
|
+
success: zod.z.boolean(),
|
|
1102
|
+
withdrawal: WithdrawalDetailSchema,
|
|
1103
|
+
message: zod.z.string()
|
|
1104
|
+
});
|
|
1105
|
+
var WithdrawalCreateRequestSchema = zod.z.object({
|
|
1106
|
+
amount_usd: zod.z.string(),
|
|
1107
|
+
currency_code: zod.z.string().min(1).max(20),
|
|
1108
|
+
wallet_address: zod.z.string().min(1).max(255)
|
|
1109
|
+
});
|
|
1110
|
+
var WithdrawalCreateResponseSchema = zod.z.object({
|
|
1111
|
+
success: zod.z.boolean(),
|
|
1112
|
+
withdrawal: WithdrawalDetailSchema,
|
|
1113
|
+
message: zod.z.string()
|
|
1076
1114
|
});
|
|
1077
1115
|
|
|
1078
1116
|
// src/api/generated/ext_payments/validation-events.ts
|
|
@@ -1129,7 +1167,9 @@ __export(fetchers_exports, {
|
|
|
1129
1167
|
createPaymentsWithdrawalsCancelCreate: () => createPaymentsWithdrawalsCancelCreate,
|
|
1130
1168
|
createPaymentsWithdrawalsCreateCreate: () => createPaymentsWithdrawalsCreateCreate,
|
|
1131
1169
|
getPaymentsBalanceRetrieve: () => getPaymentsBalanceRetrieve,
|
|
1170
|
+
getPaymentsCurrenciesEstimateRetrieve: () => getPaymentsCurrenciesEstimateRetrieve,
|
|
1132
1171
|
getPaymentsCurrenciesList: () => getPaymentsCurrenciesList,
|
|
1172
|
+
getPaymentsCurrenciesWithdrawalEstimateRetrieve: () => getPaymentsCurrenciesWithdrawalEstimateRetrieve,
|
|
1133
1173
|
getPaymentsPaymentsList: () => getPaymentsPaymentsList,
|
|
1134
1174
|
getPaymentsPaymentsRetrieve: () => getPaymentsPaymentsRetrieve,
|
|
1135
1175
|
getPaymentsPaymentsStatusRetrieve: () => getPaymentsPaymentsStatusRetrieve,
|
|
@@ -1240,6 +1280,16 @@ async function getPaymentsCurrenciesList(client) {
|
|
|
1240
1280
|
const response = await api.ext_payments_payments.currenciesList();
|
|
1241
1281
|
return response;
|
|
1242
1282
|
}
|
|
1283
|
+
async function getPaymentsCurrenciesEstimateRetrieve(code, params, client) {
|
|
1284
|
+
const api = client || getAPIInstance();
|
|
1285
|
+
const response = await api.ext_payments_payments.currenciesEstimateRetrieve(code, params?.amount);
|
|
1286
|
+
return response;
|
|
1287
|
+
}
|
|
1288
|
+
async function getPaymentsCurrenciesWithdrawalEstimateRetrieve(code, params, client) {
|
|
1289
|
+
const api = client || getAPIInstance();
|
|
1290
|
+
const response = await api.ext_payments_payments.currenciesWithdrawalEstimateRetrieve(code, params?.amount);
|
|
1291
|
+
return response;
|
|
1292
|
+
}
|
|
1243
1293
|
async function getPaymentsPaymentsList(params, client) {
|
|
1244
1294
|
const api = client || getAPIInstance();
|
|
1245
1295
|
const response = await api.ext_payments_payments.paymentsList(params?.page, params?.page_size);
|
|
@@ -1412,7 +1462,7 @@ async function createPaymentsPaymentsCreateCreate(data, client) {
|
|
|
1412
1462
|
const api = client || getAPIInstance();
|
|
1413
1463
|
const response = await api.ext_payments_payments.paymentsCreateCreate(data);
|
|
1414
1464
|
try {
|
|
1415
|
-
return
|
|
1465
|
+
return PaymentCreateResponseSchema.parse(response);
|
|
1416
1466
|
} catch (error) {
|
|
1417
1467
|
consola.consola.error("\u274C Zod Validation Failed");
|
|
1418
1468
|
consola.consola.box(`createPaymentsPaymentsCreateCreate
|
|
@@ -1543,7 +1593,7 @@ async function createPaymentsWithdrawalsCancelCreate(id, client) {
|
|
|
1543
1593
|
const api = client || getAPIInstance();
|
|
1544
1594
|
const response = await api.ext_payments_payments.withdrawalsCancelCreate(id);
|
|
1545
1595
|
try {
|
|
1546
|
-
return
|
|
1596
|
+
return WithdrawalCancelResponseSchema.parse(response);
|
|
1547
1597
|
} catch (error) {
|
|
1548
1598
|
consola.consola.error("\u274C Zod Validation Failed");
|
|
1549
1599
|
consola.consola.box(`createPaymentsWithdrawalsCancelCreate
|
|
@@ -1585,7 +1635,7 @@ async function createPaymentsWithdrawalsCreateCreate(data, client) {
|
|
|
1585
1635
|
const api = client || getAPIInstance();
|
|
1586
1636
|
const response = await api.ext_payments_payments.withdrawalsCreateCreate(data);
|
|
1587
1637
|
try {
|
|
1588
|
-
return
|
|
1638
|
+
return WithdrawalCreateResponseSchema.parse(response);
|
|
1589
1639
|
} catch (error) {
|
|
1590
1640
|
consola.consola.error("\u274C Zod Validation Failed");
|
|
1591
1641
|
consola.consola.box(`createPaymentsWithdrawalsCreateCreate
|
|
@@ -1639,8 +1689,8 @@ var API = class {
|
|
|
1639
1689
|
constructor(baseUrl, options) {
|
|
1640
1690
|
this.baseUrl = baseUrl;
|
|
1641
1691
|
this.options = options;
|
|
1642
|
-
const
|
|
1643
|
-
this.storage = options?.storage || new LocalStorageAdapter(
|
|
1692
|
+
const logger2 = options?.loggerConfig ? new APILogger(options.loggerConfig) : void 0;
|
|
1693
|
+
this.storage = options?.storage || new LocalStorageAdapter(logger2);
|
|
1644
1694
|
this._loadTokensFromStorage();
|
|
1645
1695
|
this._client = new APIClient(this.baseUrl, {
|
|
1646
1696
|
retryConfig: this.options?.retryConfig,
|
|
@@ -1749,16 +1799,260 @@ var API = class {
|
|
|
1749
1799
|
return "./schema.json";
|
|
1750
1800
|
}
|
|
1751
1801
|
};
|
|
1802
|
+
|
|
1803
|
+
// src/api/index.ts
|
|
1752
1804
|
api.initializeExtensionAPI(configureAPI);
|
|
1753
1805
|
var apiPayments = api.createExtensionAPI(API);
|
|
1754
|
-
|
|
1806
|
+
function usePaymentsBalanceRetrieve(client) {
|
|
1807
|
+
return useSWR__default.default(
|
|
1808
|
+
"cfg-payments-balance",
|
|
1809
|
+
() => getPaymentsBalanceRetrieve(client)
|
|
1810
|
+
);
|
|
1811
|
+
}
|
|
1812
|
+
function usePaymentsCurrenciesList(client) {
|
|
1813
|
+
return useSWR__default.default(
|
|
1814
|
+
"cfg-payments-currencies",
|
|
1815
|
+
() => getPaymentsCurrenciesList(client)
|
|
1816
|
+
);
|
|
1817
|
+
}
|
|
1818
|
+
function usePaymentsPaymentsList(params, client) {
|
|
1819
|
+
return useSWR__default.default(
|
|
1820
|
+
params ? ["cfg-payments-payments", params] : "cfg-payments-payments",
|
|
1821
|
+
() => getPaymentsPaymentsList(params, client)
|
|
1822
|
+
);
|
|
1823
|
+
}
|
|
1824
|
+
function useCreatePaymentsPaymentsCreateCreate() {
|
|
1825
|
+
const { mutate } = useSWR.useSWRConfig();
|
|
1826
|
+
return async (data, client) => {
|
|
1827
|
+
const result = await createPaymentsPaymentsCreateCreate(data, client);
|
|
1828
|
+
mutate("cfg-payments-payments");
|
|
1829
|
+
return result;
|
|
1830
|
+
};
|
|
1831
|
+
}
|
|
1832
|
+
function usePaymentsTransactionsList(params, client) {
|
|
1833
|
+
return useSWR__default.default(
|
|
1834
|
+
params ? ["cfg-payments-transactions", params] : "cfg-payments-transactions",
|
|
1835
|
+
() => getPaymentsTransactionsList(params, client)
|
|
1836
|
+
);
|
|
1837
|
+
}
|
|
1838
|
+
function usePaymentsWithdrawalsList(params, client) {
|
|
1839
|
+
return useSWR__default.default(
|
|
1840
|
+
params ? ["cfg-payments-withdrawals", params] : "cfg-payments-withdrawals",
|
|
1841
|
+
() => getPaymentsWithdrawalsList(params, client)
|
|
1842
|
+
);
|
|
1843
|
+
}
|
|
1844
|
+
function useCreatePaymentsWithdrawalsCancelCreate() {
|
|
1845
|
+
const { mutate } = useSWR.useSWRConfig();
|
|
1846
|
+
return async (id, client) => {
|
|
1847
|
+
const result = await createPaymentsWithdrawalsCancelCreate(id, client);
|
|
1848
|
+
mutate("cfg-payments-withdrawals-cancel");
|
|
1849
|
+
return result;
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1852
|
+
function useCreatePaymentsWithdrawalsCreateCreate() {
|
|
1853
|
+
const { mutate } = useSWR.useSWRConfig();
|
|
1854
|
+
return async (data, client) => {
|
|
1855
|
+
const result = await createPaymentsWithdrawalsCreateCreate(data, client);
|
|
1856
|
+
mutate("cfg-payments-withdrawals");
|
|
1857
|
+
return result;
|
|
1858
|
+
};
|
|
1859
|
+
}
|
|
1860
|
+
var WalletContext = react.createContext(void 0);
|
|
1861
|
+
function WalletProvider({ children }) {
|
|
1862
|
+
const {
|
|
1863
|
+
data: balance,
|
|
1864
|
+
isLoading: isLoadingBalance,
|
|
1865
|
+
mutate: mutateBalance
|
|
1866
|
+
} = usePaymentsBalanceRetrieve(apiPayments);
|
|
1867
|
+
const {
|
|
1868
|
+
data: paymentsData,
|
|
1869
|
+
isLoading: isLoadingPayments,
|
|
1870
|
+
mutate: mutatePayments
|
|
1871
|
+
} = usePaymentsPaymentsList({ page: 1, page_size: 20 }, apiPayments);
|
|
1872
|
+
const {
|
|
1873
|
+
data: transactionsData,
|
|
1874
|
+
isLoading: isLoadingTransactions,
|
|
1875
|
+
mutate: mutateTransactions
|
|
1876
|
+
} = usePaymentsTransactionsList({ limit: 20 }, apiPayments);
|
|
1877
|
+
const {
|
|
1878
|
+
data: currenciesData,
|
|
1879
|
+
isLoading: isLoadingCurrencies,
|
|
1880
|
+
mutate: mutateCurrencies
|
|
1881
|
+
} = usePaymentsCurrenciesList(apiPayments);
|
|
1882
|
+
const {
|
|
1883
|
+
data: withdrawalsData,
|
|
1884
|
+
isLoading: isLoadingWithdrawals,
|
|
1885
|
+
mutate: mutateWithdrawals
|
|
1886
|
+
} = usePaymentsWithdrawalsList({ page: 1, page_size: 20 }, apiPayments);
|
|
1887
|
+
const createPaymentMutation = useCreatePaymentsPaymentsCreateCreate();
|
|
1888
|
+
const createWithdrawalMutation = useCreatePaymentsWithdrawalsCreateCreate();
|
|
1889
|
+
const cancelWithdrawalMutation = useCreatePaymentsWithdrawalsCancelCreate();
|
|
1890
|
+
const balanceAmount = react.useMemo(() => {
|
|
1891
|
+
if (!balance?.balance_usd) return 0;
|
|
1892
|
+
return parseFloat(balance.balance_usd) || 0;
|
|
1893
|
+
}, [balance]);
|
|
1894
|
+
const activity = react.useMemo(() => {
|
|
1895
|
+
const items = [];
|
|
1896
|
+
const payments = paymentsData?.results || [];
|
|
1897
|
+
for (const payment of payments) {
|
|
1898
|
+
items.push({
|
|
1899
|
+
id: `payment-${payment.id}`,
|
|
1900
|
+
type: "payment",
|
|
1901
|
+
amount: payment.amount_usd,
|
|
1902
|
+
amountDisplay: `+$${parseFloat(payment.amount_usd).toFixed(2)}`,
|
|
1903
|
+
currency: payment.currency_code,
|
|
1904
|
+
status: mapPaymentStatus(payment.status),
|
|
1905
|
+
statusDisplay: payment.status_display,
|
|
1906
|
+
description: `${payment.currency_code} payment`,
|
|
1907
|
+
createdAt: payment.created_at,
|
|
1908
|
+
payment
|
|
1909
|
+
});
|
|
1910
|
+
}
|
|
1911
|
+
const withdrawals = withdrawalsData?.results || [];
|
|
1912
|
+
for (const withdrawal of withdrawals) {
|
|
1913
|
+
items.push({
|
|
1914
|
+
id: `withdrawal-${withdrawal.id}`,
|
|
1915
|
+
type: "withdrawal",
|
|
1916
|
+
amount: withdrawal.amount_usd,
|
|
1917
|
+
amountDisplay: `-$${parseFloat(withdrawal.amount_usd).toFixed(2)}`,
|
|
1918
|
+
currency: withdrawal.currency_code,
|
|
1919
|
+
status: mapWithdrawalStatus(withdrawal.status),
|
|
1920
|
+
statusDisplay: withdrawal.status_display,
|
|
1921
|
+
description: `${withdrawal.currency_code} withdrawal`,
|
|
1922
|
+
createdAt: withdrawal.created_at,
|
|
1923
|
+
withdrawal
|
|
1924
|
+
});
|
|
1925
|
+
}
|
|
1926
|
+
const transactions = transactionsData?.results || transactionsData || [];
|
|
1927
|
+
if (Array.isArray(transactions)) {
|
|
1928
|
+
for (const tx of transactions) {
|
|
1929
|
+
if (tx.payment_id && payments.some((p) => p.id === tx.payment_id)) {
|
|
1930
|
+
continue;
|
|
1931
|
+
}
|
|
1932
|
+
const isDeposit = tx.transaction_type === "deposit";
|
|
1933
|
+
items.push({
|
|
1934
|
+
id: `tx-${tx.id}`,
|
|
1935
|
+
type: isDeposit ? "deposit" : "withdrawal",
|
|
1936
|
+
amount: tx.amount_usd,
|
|
1937
|
+
amountDisplay: `${isDeposit ? "+" : "-"}$${Math.abs(parseFloat(tx.amount_usd)).toFixed(2)}`,
|
|
1938
|
+
status: "completed",
|
|
1939
|
+
statusDisplay: "Completed",
|
|
1940
|
+
description: tx.description || tx.type_display,
|
|
1941
|
+
createdAt: tx.created_at,
|
|
1942
|
+
transaction: tx
|
|
1943
|
+
});
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
items.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
1947
|
+
return items;
|
|
1948
|
+
}, [paymentsData, withdrawalsData, transactionsData]);
|
|
1949
|
+
const currencies = react.useMemo(() => {
|
|
1950
|
+
const data = currenciesData?.currencies || currenciesData?.results || currenciesData || [];
|
|
1951
|
+
if (!Array.isArray(data)) return [];
|
|
1952
|
+
return data.filter((c) => c.is_enabled !== false).map((c) => ({
|
|
1953
|
+
code: c.code || c.currency_code || c.symbol,
|
|
1954
|
+
name: c.name || c.code,
|
|
1955
|
+
token: c.token || c.code,
|
|
1956
|
+
// Token symbol (e.g., USDT, WBTC) with fallback to code
|
|
1957
|
+
network: c.network || void 0,
|
|
1958
|
+
enabled: c.is_enabled !== false
|
|
1959
|
+
}));
|
|
1960
|
+
}, [currenciesData]);
|
|
1961
|
+
const addFunds = react.useCallback(async (data) => {
|
|
1962
|
+
const response = await createPaymentMutation(data, apiPayments);
|
|
1963
|
+
await Promise.all([mutateBalance(), mutatePayments(), mutateTransactions()]);
|
|
1964
|
+
return response.payment;
|
|
1965
|
+
}, [createPaymentMutation, mutateBalance, mutatePayments, mutateTransactions]);
|
|
1966
|
+
const withdraw = react.useCallback(async (data) => {
|
|
1967
|
+
const response = await createWithdrawalMutation(data, apiPayments);
|
|
1968
|
+
await Promise.all([mutateBalance(), mutateWithdrawals(), mutateTransactions()]);
|
|
1969
|
+
return response.withdrawal;
|
|
1970
|
+
}, [createWithdrawalMutation, mutateBalance, mutateWithdrawals, mutateTransactions]);
|
|
1971
|
+
const cancelWithdrawal = react.useCallback(async (id) => {
|
|
1972
|
+
await cancelWithdrawalMutation(id, apiPayments);
|
|
1973
|
+
await Promise.all([mutateBalance(), mutateWithdrawals(), mutateTransactions()]);
|
|
1974
|
+
}, [cancelWithdrawalMutation, mutateBalance, mutateWithdrawals, mutateTransactions]);
|
|
1975
|
+
const getPaymentDetails = react.useCallback(async (id) => {
|
|
1976
|
+
return apiPayments.ext_payments_payments.paymentsRetrieve(id);
|
|
1977
|
+
}, []);
|
|
1978
|
+
const getWithdrawalDetails = react.useCallback(async (id) => {
|
|
1979
|
+
return apiPayments.ext_payments_payments.withdrawalsRetrieve(id);
|
|
1980
|
+
}, []);
|
|
1981
|
+
const refreshWallet = react.useCallback(async () => {
|
|
1982
|
+
await Promise.all([
|
|
1983
|
+
mutateBalance(),
|
|
1984
|
+
mutatePayments(),
|
|
1985
|
+
mutateWithdrawals(),
|
|
1986
|
+
mutateTransactions(),
|
|
1987
|
+
mutateCurrencies()
|
|
1988
|
+
]);
|
|
1989
|
+
}, [mutateBalance, mutatePayments, mutateWithdrawals, mutateTransactions, mutateCurrencies]);
|
|
1990
|
+
const isLoading = isLoadingBalance || isLoadingPayments || isLoadingWithdrawals || isLoadingTransactions;
|
|
1991
|
+
const isLoadingActivity = isLoadingPayments || isLoadingWithdrawals || isLoadingTransactions;
|
|
1992
|
+
const value = {
|
|
1993
|
+
balance,
|
|
1994
|
+
balanceAmount,
|
|
1995
|
+
isLoadingBalance,
|
|
1996
|
+
activity,
|
|
1997
|
+
isLoadingActivity,
|
|
1998
|
+
hasMoreActivity: (paymentsData?.count || 0) > 20 || (withdrawalsData?.count || 0) > 20,
|
|
1999
|
+
currencies,
|
|
2000
|
+
isLoadingCurrencies,
|
|
2001
|
+
addFunds,
|
|
2002
|
+
withdraw,
|
|
2003
|
+
cancelWithdrawal,
|
|
2004
|
+
getPaymentDetails,
|
|
2005
|
+
getWithdrawalDetails,
|
|
2006
|
+
refreshWallet,
|
|
2007
|
+
isLoading
|
|
2008
|
+
};
|
|
2009
|
+
return /* @__PURE__ */ jsxRuntime.jsx(WalletContext.Provider, { value, children });
|
|
2010
|
+
}
|
|
1755
2011
|
function useWallet() {
|
|
1756
|
-
const context =
|
|
2012
|
+
const context = react.useContext(WalletContext);
|
|
1757
2013
|
if (!context) {
|
|
1758
2014
|
throw new Error("useWallet must be used within WalletProvider");
|
|
1759
2015
|
}
|
|
1760
2016
|
return context;
|
|
1761
2017
|
}
|
|
2018
|
+
function mapPaymentStatus(status) {
|
|
2019
|
+
switch (status?.toLowerCase()) {
|
|
2020
|
+
case "completed":
|
|
2021
|
+
case "success":
|
|
2022
|
+
case "finished":
|
|
2023
|
+
return "completed";
|
|
2024
|
+
case "pending":
|
|
2025
|
+
case "waiting":
|
|
2026
|
+
return "pending";
|
|
2027
|
+
case "confirming":
|
|
2028
|
+
case "partially_paid":
|
|
2029
|
+
return "confirming";
|
|
2030
|
+
case "expired":
|
|
2031
|
+
return "expired";
|
|
2032
|
+
case "failed":
|
|
2033
|
+
case "error":
|
|
2034
|
+
case "cancelled":
|
|
2035
|
+
return "failed";
|
|
2036
|
+
default:
|
|
2037
|
+
return "pending";
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
function mapWithdrawalStatus(status) {
|
|
2041
|
+
switch (status?.toLowerCase()) {
|
|
2042
|
+
case "completed":
|
|
2043
|
+
return "completed";
|
|
2044
|
+
case "pending":
|
|
2045
|
+
case "approved":
|
|
2046
|
+
return "pending";
|
|
2047
|
+
case "processing":
|
|
2048
|
+
return "confirming";
|
|
2049
|
+
case "rejected":
|
|
2050
|
+
case "cancelled":
|
|
2051
|
+
return "failed";
|
|
2052
|
+
default:
|
|
2053
|
+
return "pending";
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
1762
2056
|
function BalanceHero({ onAddFunds, onWithdraw, className }) {
|
|
1763
2057
|
const { balance, balanceAmount, isLoadingBalance, refreshWallet } = useWallet();
|
|
1764
2058
|
const formattedBalance = new Intl.NumberFormat("en-US", {
|
|
@@ -1864,7 +2158,7 @@ function ActivityItem({ item, onClick }) {
|
|
|
1864
2158
|
const StatusIcon = config.icon;
|
|
1865
2159
|
const isPositive = item.type === "payment" || item.type === "deposit";
|
|
1866
2160
|
const DirectionIcon = isPositive ? lucideReact.ArrowDownLeft : lucideReact.ArrowUpRight;
|
|
1867
|
-
const relativeTime =
|
|
2161
|
+
const relativeTime = moment3__default.default(item.createdAt).fromNow();
|
|
1868
2162
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1869
2163
|
"button",
|
|
1870
2164
|
{
|
|
@@ -1953,42 +2247,300 @@ function ActivityList({
|
|
|
1953
2247
|
)) })
|
|
1954
2248
|
] });
|
|
1955
2249
|
}
|
|
2250
|
+
function useEstimate({
|
|
2251
|
+
currencyCode,
|
|
2252
|
+
amountUsd,
|
|
2253
|
+
minAmount = 0,
|
|
2254
|
+
debounceMs = 300,
|
|
2255
|
+
skip = false
|
|
2256
|
+
}) {
|
|
2257
|
+
const [estimate, setEstimate] = react.useState(null);
|
|
2258
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
2259
|
+
const [error, setError] = react.useState(null);
|
|
2260
|
+
react.useEffect(() => {
|
|
2261
|
+
if (skip || !currencyCode || amountUsd < minAmount) {
|
|
2262
|
+
setEstimate(null);
|
|
2263
|
+
setError(null);
|
|
2264
|
+
return;
|
|
2265
|
+
}
|
|
2266
|
+
const fetchEstimate = async () => {
|
|
2267
|
+
setIsLoading(true);
|
|
2268
|
+
setError(null);
|
|
2269
|
+
try {
|
|
2270
|
+
const response = await apiPayments.ext_payments_payments.currenciesEstimateRetrieve(
|
|
2271
|
+
currencyCode,
|
|
2272
|
+
{ amount: amountUsd }
|
|
2273
|
+
);
|
|
2274
|
+
if (response?.success && response?.estimated_amount) {
|
|
2275
|
+
setEstimate({
|
|
2276
|
+
estimatedAmount: parseFloat(response.estimated_amount),
|
|
2277
|
+
usdRate: parseFloat(response.usd_rate) || 0,
|
|
2278
|
+
minAmountUsd: response.min_amount_usd ? parseFloat(response.min_amount_usd) : null,
|
|
2279
|
+
isStablecoin: response.is_stablecoin || false,
|
|
2280
|
+
// New fee fields
|
|
2281
|
+
amountToReceive: parseFloat(response.amount_to_receive) || amountUsd,
|
|
2282
|
+
serviceFeeUsd: parseFloat(response.service_fee_usd) || 0,
|
|
2283
|
+
serviceFeePercent: parseFloat(response.service_fee_percent) || 0,
|
|
2284
|
+
totalToPayUsd: parseFloat(response.total_to_pay_usd) || amountUsd
|
|
2285
|
+
});
|
|
2286
|
+
} else {
|
|
2287
|
+
setEstimate(null);
|
|
2288
|
+
}
|
|
2289
|
+
} catch (err) {
|
|
2290
|
+
console.error("Failed to fetch estimate:", err);
|
|
2291
|
+
setEstimate(null);
|
|
2292
|
+
setError(err instanceof Error ? err : new Error("Failed to fetch estimate"));
|
|
2293
|
+
} finally {
|
|
2294
|
+
setIsLoading(false);
|
|
2295
|
+
}
|
|
2296
|
+
};
|
|
2297
|
+
const timeoutId = setTimeout(fetchEstimate, debounceMs);
|
|
2298
|
+
return () => clearTimeout(timeoutId);
|
|
2299
|
+
}, [currencyCode, amountUsd, minAmount, debounceMs, skip]);
|
|
2300
|
+
return { estimate, isLoading, error };
|
|
2301
|
+
}
|
|
2302
|
+
function useWithdrawalEstimate({
|
|
2303
|
+
currencyCode,
|
|
2304
|
+
amountUsd,
|
|
2305
|
+
minAmount = 10,
|
|
2306
|
+
debounceMs = 300,
|
|
2307
|
+
skip = false
|
|
2308
|
+
}) {
|
|
2309
|
+
const [estimate, setEstimate] = react.useState(null);
|
|
2310
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
2311
|
+
const [error, setError] = react.useState(null);
|
|
2312
|
+
react.useEffect(() => {
|
|
2313
|
+
if (skip || !currencyCode || amountUsd < minAmount) {
|
|
2314
|
+
setEstimate(null);
|
|
2315
|
+
setError(null);
|
|
2316
|
+
return;
|
|
2317
|
+
}
|
|
2318
|
+
const fetchEstimate = async () => {
|
|
2319
|
+
setIsLoading(true);
|
|
2320
|
+
setError(null);
|
|
2321
|
+
try {
|
|
2322
|
+
const response = await apiPayments.ext_payments_payments.currenciesWithdrawalEstimateRetrieve(
|
|
2323
|
+
currencyCode,
|
|
2324
|
+
{ amount: amountUsd }
|
|
2325
|
+
);
|
|
2326
|
+
if (response?.success && response?.estimated_amount) {
|
|
2327
|
+
setEstimate({
|
|
2328
|
+
estimatedAmount: parseFloat(response.estimated_amount),
|
|
2329
|
+
usdRate: parseFloat(response.usd_rate) || 0,
|
|
2330
|
+
minAmountUsd: response.min_amount_usd ? parseFloat(response.min_amount_usd) : null,
|
|
2331
|
+
isStablecoin: response.is_stablecoin || false,
|
|
2332
|
+
// Withdrawal-specific fields
|
|
2333
|
+
amountRequested: parseFloat(response.amount_requested) || amountUsd,
|
|
2334
|
+
serviceFeeUsd: parseFloat(response.service_fee_usd) || 0,
|
|
2335
|
+
serviceFeePercent: parseFloat(response.service_fee_percent) || 0,
|
|
2336
|
+
networkFeeUsd: parseFloat(response.network_fee_usd) || 0,
|
|
2337
|
+
totalFeesUsd: parseFloat(response.total_fees_usd) || 0,
|
|
2338
|
+
amountToReceive: parseFloat(response.amount_to_receive) || 0
|
|
2339
|
+
});
|
|
2340
|
+
} else {
|
|
2341
|
+
setEstimate(null);
|
|
2342
|
+
}
|
|
2343
|
+
} catch (err) {
|
|
2344
|
+
console.error("Failed to fetch withdrawal estimate:", err);
|
|
2345
|
+
setEstimate(null);
|
|
2346
|
+
setError(err instanceof Error ? err : new Error("Failed to fetch withdrawal estimate"));
|
|
2347
|
+
} finally {
|
|
2348
|
+
setIsLoading(false);
|
|
2349
|
+
}
|
|
2350
|
+
};
|
|
2351
|
+
const timeoutId = setTimeout(fetchEstimate, debounceMs);
|
|
2352
|
+
return () => clearTimeout(timeoutId);
|
|
2353
|
+
}, [currencyCode, amountUsd, minAmount, debounceMs, skip]);
|
|
2354
|
+
return { estimate, isLoading, error };
|
|
2355
|
+
}
|
|
2356
|
+
function useCurrencyOptions(currencies) {
|
|
2357
|
+
return react.useMemo(() => {
|
|
2358
|
+
return currencies.map((c) => ({
|
|
2359
|
+
value: c.code,
|
|
2360
|
+
label: c.name,
|
|
2361
|
+
token: c.token,
|
|
2362
|
+
network: c.network
|
|
2363
|
+
}));
|
|
2364
|
+
}, [currencies]);
|
|
2365
|
+
}
|
|
2366
|
+
function useDefaultCurrency({
|
|
2367
|
+
currencyOptions,
|
|
2368
|
+
savedCurrency,
|
|
2369
|
+
currentValue,
|
|
2370
|
+
setValue
|
|
2371
|
+
}) {
|
|
2372
|
+
react.useEffect(() => {
|
|
2373
|
+
if (currencyOptions.length > 0 && !currentValue) {
|
|
2374
|
+
const savedOption = savedCurrency && currencyOptions.find((c) => c.value === savedCurrency);
|
|
2375
|
+
if (savedOption) {
|
|
2376
|
+
setValue(savedOption.value);
|
|
2377
|
+
} else {
|
|
2378
|
+
const usdt = currencyOptions.find((c) => c.value.includes("USDT"));
|
|
2379
|
+
setValue(usdt?.value || currencyOptions[0].value);
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
}, [currencyOptions, savedCurrency, currentValue, setValue]);
|
|
2383
|
+
}
|
|
2384
|
+
function useAutoSave(value, save, validate) {
|
|
2385
|
+
const saveRef = react.useRef(save);
|
|
2386
|
+
const validateRef = react.useRef(validate);
|
|
2387
|
+
react.useEffect(() => {
|
|
2388
|
+
saveRef.current = save;
|
|
2389
|
+
validateRef.current = validate;
|
|
2390
|
+
});
|
|
2391
|
+
react.useEffect(() => {
|
|
2392
|
+
const isValid = validateRef.current ? validateRef.current(value) : Boolean(value);
|
|
2393
|
+
if (isValid) {
|
|
2394
|
+
saveRef.current(value);
|
|
2395
|
+
}
|
|
2396
|
+
}, [value]);
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
// src/utils/format.ts
|
|
2400
|
+
function formatUsdRate(rate) {
|
|
2401
|
+
if (rate >= 1) {
|
|
2402
|
+
return rate.toLocaleString(void 0, {
|
|
2403
|
+
minimumFractionDigits: 2,
|
|
2404
|
+
maximumFractionDigits: 2
|
|
2405
|
+
});
|
|
2406
|
+
} else if (rate >= 0.01) {
|
|
2407
|
+
return rate.toLocaleString(void 0, {
|
|
2408
|
+
minimumFractionDigits: 2,
|
|
2409
|
+
maximumFractionDigits: 4
|
|
2410
|
+
});
|
|
2411
|
+
} else if (rate >= 1e-4) {
|
|
2412
|
+
return rate.toLocaleString(void 0, {
|
|
2413
|
+
minimumFractionDigits: 4,
|
|
2414
|
+
maximumFractionDigits: 6
|
|
2415
|
+
});
|
|
2416
|
+
} else {
|
|
2417
|
+
return rate.toLocaleString(void 0, {
|
|
2418
|
+
minimumFractionDigits: 6,
|
|
2419
|
+
maximumFractionDigits: 8
|
|
2420
|
+
});
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
function formatCryptoAmount(amount, isStablecoin) {
|
|
2424
|
+
const decimals = isStablecoin ? 2 : 8;
|
|
2425
|
+
return amount.toFixed(decimals);
|
|
2426
|
+
}
|
|
2427
|
+
function formatUsdAmount(amount, alwaysShowCents = false) {
|
|
2428
|
+
if (alwaysShowCents) {
|
|
2429
|
+
return amount.toFixed(2);
|
|
2430
|
+
}
|
|
2431
|
+
const hasCents = amount % 1 !== 0;
|
|
2432
|
+
if (hasCents) {
|
|
2433
|
+
return amount.toFixed(2);
|
|
2434
|
+
}
|
|
2435
|
+
return amount.toFixed(0);
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
// src/utils/errors.ts
|
|
2439
|
+
function extractErrorMessage(err, fallback = "An error occurred") {
|
|
2440
|
+
if (!err) return fallback;
|
|
2441
|
+
const error = err;
|
|
2442
|
+
const responseData = error.response?.data;
|
|
2443
|
+
const response = responseData || error.response;
|
|
2444
|
+
if (response) {
|
|
2445
|
+
if (typeof response.error === "string") return response.error;
|
|
2446
|
+
if (typeof response.message === "string") return response.message;
|
|
2447
|
+
if (typeof response.detail === "string") return response.detail;
|
|
2448
|
+
}
|
|
2449
|
+
if (typeof error.errorMessage === "string") return error.errorMessage;
|
|
2450
|
+
if (typeof error.message === "string") return error.message;
|
|
2451
|
+
return fallback;
|
|
2452
|
+
}
|
|
2453
|
+
var isDevelopment = process.env.NODE_ENV === "development";
|
|
2454
|
+
consola.createConsola({
|
|
2455
|
+
level: isDevelopment ? 4 : 1
|
|
2456
|
+
}).withTag("ext-payments");
|
|
2457
|
+
function CurrencyCombobox({
|
|
2458
|
+
options,
|
|
2459
|
+
value,
|
|
2460
|
+
onChange,
|
|
2461
|
+
disabled,
|
|
2462
|
+
placeholder = "Select currency..."
|
|
2463
|
+
}) {
|
|
2464
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2465
|
+
uiCore.Combobox,
|
|
2466
|
+
{
|
|
2467
|
+
options,
|
|
2468
|
+
value,
|
|
2469
|
+
onValueChange: onChange,
|
|
2470
|
+
placeholder,
|
|
2471
|
+
searchPlaceholder: "Search...",
|
|
2472
|
+
disabled,
|
|
2473
|
+
className: "h-14",
|
|
2474
|
+
renderOption: (option) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-1", children: [
|
|
2475
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: option.value, size: 24 }),
|
|
2476
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: option.label })
|
|
2477
|
+
] }),
|
|
2478
|
+
renderValue: (option) => option && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
2479
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: option.value, size: 24 }),
|
|
2480
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: option.label })
|
|
2481
|
+
] })
|
|
2482
|
+
}
|
|
2483
|
+
);
|
|
2484
|
+
}
|
|
1956
2485
|
var AddFundsSchema = zod.z.object({
|
|
1957
|
-
amount: zod.z.number().min(1, "Minimum $1
|
|
2486
|
+
amount: zod.z.number().min(1, "Minimum $1"),
|
|
1958
2487
|
currency: zod.z.string().min(1, "Select a currency")
|
|
1959
2488
|
});
|
|
2489
|
+
var STORAGE_KEY = "payments:addFunds";
|
|
1960
2490
|
function AddFundsSheet({ open, onOpenChange, onSuccess }) {
|
|
1961
2491
|
const { currencies, isLoadingCurrencies, addFunds } = useWallet();
|
|
1962
|
-
const [isSubmitting, setIsSubmitting] =
|
|
1963
|
-
const [error, setError] =
|
|
2492
|
+
const [isSubmitting, setIsSubmitting] = react.useState(false);
|
|
2493
|
+
const [error, setError] = react.useState(null);
|
|
2494
|
+
const [saved, setSaved] = uiCore.useLocalStorage(STORAGE_KEY, {
|
|
2495
|
+
currency: "",
|
|
2496
|
+
amount: 100
|
|
2497
|
+
});
|
|
1964
2498
|
const form = reactHookForm.useForm({
|
|
1965
2499
|
resolver: zod$1.zodResolver(AddFundsSchema),
|
|
1966
2500
|
defaultValues: {
|
|
1967
|
-
amount:
|
|
1968
|
-
currency:
|
|
2501
|
+
amount: saved.amount,
|
|
2502
|
+
currency: saved.currency
|
|
1969
2503
|
}
|
|
1970
2504
|
});
|
|
1971
|
-
const
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2505
|
+
const watchedAmount = form.watch("amount");
|
|
2506
|
+
const watchedCurrency = form.watch("currency");
|
|
2507
|
+
useAutoSave(watchedAmount, (v) => setSaved((prev) => ({ ...prev, amount: v })), (v) => v > 0);
|
|
2508
|
+
useAutoSave(watchedCurrency, (v) => setSaved((prev) => ({ ...prev, currency: v })));
|
|
2509
|
+
const currencyOptions = useCurrencyOptions(currencies);
|
|
2510
|
+
useDefaultCurrency({
|
|
2511
|
+
currencyOptions,
|
|
2512
|
+
savedCurrency: saved.currency,
|
|
2513
|
+
currentValue: watchedCurrency,
|
|
2514
|
+
setValue: (v) => form.setValue("currency", v)
|
|
2515
|
+
});
|
|
2516
|
+
const { estimate, isLoading: isLoadingEstimate } = useEstimate({
|
|
2517
|
+
currencyCode: watchedCurrency,
|
|
2518
|
+
amountUsd: watchedAmount,
|
|
2519
|
+
minAmount: 1
|
|
2520
|
+
});
|
|
2521
|
+
const selectedCurrency = currencyOptions.find((c) => c.value === watchedCurrency);
|
|
2522
|
+
const displayData = react.useMemo(() => {
|
|
2523
|
+
if (!selectedCurrency || !estimate) return null;
|
|
2524
|
+
const token = selectedCurrency.token;
|
|
2525
|
+
const cryptoAmount = formatCryptoAmount(estimate.estimatedAmount, estimate.isStablecoin);
|
|
2526
|
+
const rate = formatUsdRate(estimate.usdRate);
|
|
2527
|
+
const belowMinimum = estimate.minAmountUsd ? watchedAmount < estimate.minAmountUsd : false;
|
|
2528
|
+
const minAmount = estimate.minAmountUsd ? formatUsdAmount(estimate.minAmountUsd) : void 0;
|
|
2529
|
+
return {
|
|
2530
|
+
token,
|
|
2531
|
+
cryptoAmount,
|
|
2532
|
+
rate,
|
|
2533
|
+
showRate: !estimate.isStablecoin && estimate.usdRate > 0,
|
|
2534
|
+
belowMinimum,
|
|
2535
|
+
minAmount,
|
|
2536
|
+
// Fee breakdown from API
|
|
2537
|
+
amountToReceive: estimate.amountToReceive,
|
|
2538
|
+
serviceFeeUsd: estimate.serviceFeeUsd,
|
|
2539
|
+
serviceFeePercent: estimate.serviceFeePercent,
|
|
2540
|
+
totalToPayUsd: estimate.totalToPayUsd
|
|
2541
|
+
};
|
|
2542
|
+
}, [selectedCurrency, estimate, watchedAmount]);
|
|
2543
|
+
const handleSubmit = react.useCallback(async (data) => {
|
|
1992
2544
|
try {
|
|
1993
2545
|
setIsSubmitting(true);
|
|
1994
2546
|
setError(null);
|
|
@@ -2000,19 +2552,22 @@ function AddFundsSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2000
2552
|
onOpenChange(false);
|
|
2001
2553
|
onSuccess?.(result);
|
|
2002
2554
|
} catch (err) {
|
|
2003
|
-
|
|
2004
|
-
setError(message);
|
|
2555
|
+
setError(extractErrorMessage(err, "Failed to create payment"));
|
|
2005
2556
|
} finally {
|
|
2006
2557
|
setIsSubmitting(false);
|
|
2007
2558
|
}
|
|
2008
2559
|
}, [addFunds, form, onOpenChange, onSuccess]);
|
|
2009
|
-
const handleOpenChange =
|
|
2010
|
-
if (
|
|
2560
|
+
const handleOpenChange = react.useCallback((open2) => {
|
|
2561
|
+
if (open2) {
|
|
2562
|
+
form.reset({
|
|
2563
|
+
amount: saved.amount,
|
|
2564
|
+
currency: saved.currency
|
|
2565
|
+
});
|
|
2566
|
+
} else {
|
|
2011
2567
|
setError(null);
|
|
2012
|
-
form.reset();
|
|
2013
2568
|
}
|
|
2014
2569
|
onOpenChange(open2);
|
|
2015
|
-
}, [form, onOpenChange]);
|
|
2570
|
+
}, [form, onOpenChange, saved]);
|
|
2016
2571
|
return /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheet, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetContent, { className: "sm:max-w-md", children: [
|
|
2017
2572
|
/* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetHeader, { children: [
|
|
2018
2573
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetTitle, { children: "Add Funds" }),
|
|
@@ -2034,7 +2589,7 @@ function AddFundsSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2034
2589
|
type: "number",
|
|
2035
2590
|
step: "0.01",
|
|
2036
2591
|
min: "1",
|
|
2037
|
-
placeholder: "100
|
|
2592
|
+
placeholder: "100",
|
|
2038
2593
|
className: "pl-8 text-2xl h-14 font-semibold",
|
|
2039
2594
|
...field,
|
|
2040
2595
|
onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
|
|
@@ -2053,51 +2608,78 @@ function AddFundsSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2053
2608
|
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(uiCore.FormItem, { children: [
|
|
2054
2609
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.FormLabel, { children: "Pay with" }),
|
|
2055
2610
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2056
|
-
|
|
2611
|
+
CurrencyCombobox,
|
|
2057
2612
|
{
|
|
2058
2613
|
options: currencyOptions,
|
|
2059
2614
|
value: field.value,
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
searchPlaceholder: "Search...",
|
|
2063
|
-
disabled: isLoadingCurrencies,
|
|
2064
|
-
className: "h-14",
|
|
2065
|
-
renderOption: (option) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-1", children: [
|
|
2066
|
-
/* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: option.value, size: 24 }),
|
|
2067
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: option.label })
|
|
2068
|
-
] }),
|
|
2069
|
-
renderValue: (option) => option && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
2070
|
-
/* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: option.value, size: 24 }),
|
|
2071
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: option.label })
|
|
2072
|
-
] })
|
|
2615
|
+
onChange: field.onChange,
|
|
2616
|
+
disabled: isLoadingCurrencies
|
|
2073
2617
|
}
|
|
2074
2618
|
) }),
|
|
2075
2619
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.FormMessage, {})
|
|
2076
2620
|
] })
|
|
2077
2621
|
}
|
|
2078
2622
|
),
|
|
2079
|
-
|
|
2080
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
] })
|
|
2623
|
+
selectedCurrency && watchedAmount >= 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-muted rounded-xl p-4 space-y-2", children: isLoadingEstimate ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center py-2", children: [
|
|
2624
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-5 w-5 animate-spin text-muted-foreground" }),
|
|
2625
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-sm text-muted-foreground", children: "Getting rate..." })
|
|
2626
|
+
] }) : displayData ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2627
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
2628
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Amount" }),
|
|
2629
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
2630
|
+
"$",
|
|
2631
|
+
formatUsdAmount(displayData.amountToReceive)
|
|
2089
2632
|
] })
|
|
2090
2633
|
] }),
|
|
2091
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm
|
|
2634
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
2635
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
|
|
2636
|
+
"Service fee (",
|
|
2637
|
+
displayData.serviceFeePercent,
|
|
2638
|
+
"%)"
|
|
2639
|
+
] }),
|
|
2640
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
2641
|
+
"+$",
|
|
2642
|
+
formatUsdAmount(displayData.serviceFeeUsd)
|
|
2643
|
+
] })
|
|
2644
|
+
] }),
|
|
2645
|
+
displayData.showRate && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm text-muted-foreground", children: [
|
|
2092
2646
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Rate" }),
|
|
2093
2647
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
2094
2648
|
"1 ",
|
|
2095
|
-
|
|
2649
|
+
displayData.token,
|
|
2096
2650
|
" = $",
|
|
2097
|
-
|
|
2651
|
+
displayData.rate
|
|
2652
|
+
] })
|
|
2653
|
+
] }),
|
|
2654
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t pt-2 mt-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2655
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "You will send" }),
|
|
2656
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
|
|
2657
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 justify-end", children: [
|
|
2658
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: displayData.token, size: 20 }),
|
|
2659
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono font-semibold text-lg", children: [
|
|
2660
|
+
displayData.cryptoAmount,
|
|
2661
|
+
" ",
|
|
2662
|
+
displayData.token
|
|
2663
|
+
] })
|
|
2664
|
+
] }),
|
|
2665
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-muted-foreground", children: [
|
|
2666
|
+
"~$",
|
|
2667
|
+
formatUsdAmount(displayData.totalToPayUsd)
|
|
2668
|
+
] })
|
|
2098
2669
|
] })
|
|
2670
|
+
] }) }),
|
|
2671
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm pt-2", children: [
|
|
2672
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "You will receive" }),
|
|
2673
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
|
|
2674
|
+
"$",
|
|
2675
|
+
formatUsdAmount(displayData.amountToReceive)
|
|
2676
|
+
] })
|
|
2677
|
+
] }),
|
|
2678
|
+
displayData.belowMinimum && displayData.minAmount && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-destructive mt-2 pt-2 border-t border-destructive/20", children: [
|
|
2679
|
+
"Minimum amount: $",
|
|
2680
|
+
displayData.minAmount
|
|
2099
2681
|
] })
|
|
2100
|
-
] }),
|
|
2682
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center text-sm text-muted-foreground py-2", children: "Enter amount to see conversion" }) }),
|
|
2101
2683
|
error && /* @__PURE__ */ jsxRuntime.jsx(uiCore.Alert, { variant: "destructive", children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.AlertDescription, { children: error }) }),
|
|
2102
2684
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2103
2685
|
uiCore.Button,
|
|
@@ -2105,7 +2687,7 @@ function AddFundsSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2105
2687
|
type: "submit",
|
|
2106
2688
|
size: "lg",
|
|
2107
2689
|
className: "w-full h-14 text-lg rounded-xl",
|
|
2108
|
-
disabled: isSubmitting || currencyOptions.length === 0,
|
|
2690
|
+
disabled: isSubmitting || currencyOptions.length === 0 || isLoadingEstimate || displayData?.belowMinimum,
|
|
2109
2691
|
children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2110
2692
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-5 w-5 mr-2 animate-spin" }),
|
|
2111
2693
|
"Creating..."
|
|
@@ -2116,56 +2698,56 @@ function AddFundsSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2116
2698
|
] }) });
|
|
2117
2699
|
}
|
|
2118
2700
|
var WithdrawSchema = zod.z.object({
|
|
2119
|
-
amount: zod.z.number().min(10, "Minimum $10
|
|
2701
|
+
amount: zod.z.number().min(10, "Minimum $10"),
|
|
2120
2702
|
currency: zod.z.string().min(1, "Select a currency"),
|
|
2121
2703
|
wallet_address: zod.z.string().min(26, "Invalid wallet address")
|
|
2122
2704
|
});
|
|
2123
|
-
var
|
|
2124
|
-
var NETWORK_FEE_USD = 1;
|
|
2705
|
+
var STORAGE_KEY2 = "payments:withdraw";
|
|
2125
2706
|
function WithdrawSheet({ open, onOpenChange, onSuccess }) {
|
|
2126
2707
|
const { currencies, isLoadingCurrencies, withdraw, balanceAmount } = useWallet();
|
|
2127
|
-
const [isSubmitting, setIsSubmitting] =
|
|
2128
|
-
const [error, setError] =
|
|
2708
|
+
const [isSubmitting, setIsSubmitting] = react.useState(false);
|
|
2709
|
+
const [error, setError] = react.useState(null);
|
|
2710
|
+
const [saved, setSaved] = uiCore.useLocalStorage(STORAGE_KEY2, {
|
|
2711
|
+
currency: "",
|
|
2712
|
+
wallet: ""
|
|
2713
|
+
});
|
|
2129
2714
|
const form = reactHookForm.useForm({
|
|
2130
2715
|
resolver: zod$1.zodResolver(WithdrawSchema),
|
|
2131
2716
|
defaultValues: {
|
|
2132
2717
|
amount: 10,
|
|
2133
|
-
currency:
|
|
2134
|
-
wallet_address:
|
|
2718
|
+
currency: saved.currency,
|
|
2719
|
+
wallet_address: saved.wallet
|
|
2135
2720
|
}
|
|
2136
2721
|
});
|
|
2137
|
-
const
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
const
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2722
|
+
const watchedAmount = form.watch("amount");
|
|
2723
|
+
const watchedCurrency = form.watch("currency");
|
|
2724
|
+
const watchedWallet = form.watch("wallet_address");
|
|
2725
|
+
useAutoSave(watchedCurrency, (v) => setSaved((prev) => ({ ...prev, currency: v })));
|
|
2726
|
+
useAutoSave(watchedWallet, (v) => setSaved((prev) => ({ ...prev, wallet: v })), (v) => v.length >= 26);
|
|
2727
|
+
const currencyOptions = useCurrencyOptions(currencies);
|
|
2728
|
+
useDefaultCurrency({
|
|
2729
|
+
currencyOptions,
|
|
2730
|
+
savedCurrency: saved.currency,
|
|
2731
|
+
currentValue: watchedCurrency,
|
|
2732
|
+
setValue: (v) => form.setValue("currency", v)
|
|
2733
|
+
});
|
|
2734
|
+
const selectedCurrency = currencyOptions.find((c) => c.value === watchedCurrency);
|
|
2735
|
+
const amount = watchedAmount || 0;
|
|
2736
|
+
const { estimate, isLoading: isLoadingEstimate } = useWithdrawalEstimate({
|
|
2737
|
+
currencyCode: watchedCurrency,
|
|
2738
|
+
amountUsd: amount,
|
|
2739
|
+
minAmount: 10,
|
|
2740
|
+
skip: amount < 10
|
|
2741
|
+
});
|
|
2742
|
+
const cryptoDisplay = react.useMemo(() => {
|
|
2743
|
+
if (!selectedCurrency || !estimate) return null;
|
|
2159
2744
|
return {
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
totalFee,
|
|
2163
|
-
finalAmount,
|
|
2164
|
-
cryptoAmount
|
|
2745
|
+
token: selectedCurrency.token,
|
|
2746
|
+
cryptoAmount: formatCryptoAmount(estimate.estimatedAmount, estimate.isStablecoin)
|
|
2165
2747
|
};
|
|
2166
|
-
}, [
|
|
2748
|
+
}, [selectedCurrency, estimate]);
|
|
2167
2749
|
const insufficientBalance = amount > balanceAmount;
|
|
2168
|
-
const handleSubmit =
|
|
2750
|
+
const handleSubmit = react.useCallback(async (data) => {
|
|
2169
2751
|
try {
|
|
2170
2752
|
setIsSubmitting(true);
|
|
2171
2753
|
setError(null);
|
|
@@ -2178,19 +2760,23 @@ function WithdrawSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2178
2760
|
onOpenChange(false);
|
|
2179
2761
|
onSuccess?.(result);
|
|
2180
2762
|
} catch (err) {
|
|
2181
|
-
|
|
2182
|
-
setError(message);
|
|
2763
|
+
setError(extractErrorMessage(err, "Failed to create withdrawal request"));
|
|
2183
2764
|
} finally {
|
|
2184
2765
|
setIsSubmitting(false);
|
|
2185
2766
|
}
|
|
2186
2767
|
}, [withdraw, form, onOpenChange, onSuccess]);
|
|
2187
|
-
const handleOpenChange =
|
|
2188
|
-
if (
|
|
2768
|
+
const handleOpenChange = react.useCallback((open2) => {
|
|
2769
|
+
if (open2) {
|
|
2770
|
+
form.reset({
|
|
2771
|
+
amount: 10,
|
|
2772
|
+
currency: saved.currency,
|
|
2773
|
+
wallet_address: saved.wallet
|
|
2774
|
+
});
|
|
2775
|
+
} else {
|
|
2189
2776
|
setError(null);
|
|
2190
|
-
form.reset();
|
|
2191
2777
|
}
|
|
2192
2778
|
onOpenChange(open2);
|
|
2193
|
-
}, [form, onOpenChange]);
|
|
2779
|
+
}, [form, onOpenChange, saved]);
|
|
2194
2780
|
return /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheet, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetContent, { className: "sm:max-w-md", children: [
|
|
2195
2781
|
/* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetHeader, { children: [
|
|
2196
2782
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetTitle, { children: "Withdraw" }),
|
|
@@ -2212,7 +2798,7 @@ function WithdrawSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2212
2798
|
type: "number",
|
|
2213
2799
|
step: "0.01",
|
|
2214
2800
|
min: "10",
|
|
2215
|
-
placeholder: "10
|
|
2801
|
+
placeholder: "10",
|
|
2216
2802
|
className: "pl-8 text-2xl h-14 font-semibold",
|
|
2217
2803
|
...field,
|
|
2218
2804
|
onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
|
|
@@ -2222,7 +2808,7 @@ function WithdrawSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2222
2808
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.FormMessage, {}),
|
|
2223
2809
|
insufficientBalance && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-destructive mt-1", children: [
|
|
2224
2810
|
"Insufficient balance (Available: $",
|
|
2225
|
-
balanceAmount
|
|
2811
|
+
formatUsdAmount(balanceAmount),
|
|
2226
2812
|
")"
|
|
2227
2813
|
] })
|
|
2228
2814
|
] })
|
|
@@ -2236,23 +2822,12 @@ function WithdrawSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2236
2822
|
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(uiCore.FormItem, { children: [
|
|
2237
2823
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.FormLabel, { children: "Withdraw as" }),
|
|
2238
2824
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2239
|
-
|
|
2825
|
+
CurrencyCombobox,
|
|
2240
2826
|
{
|
|
2241
2827
|
options: currencyOptions,
|
|
2242
2828
|
value: field.value,
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
searchPlaceholder: "Search...",
|
|
2246
|
-
disabled: isLoadingCurrencies,
|
|
2247
|
-
className: "h-14",
|
|
2248
|
-
renderOption: (option) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-1", children: [
|
|
2249
|
-
/* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: option.value, size: 24 }),
|
|
2250
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: option.label })
|
|
2251
|
-
] }),
|
|
2252
|
-
renderValue: (option) => option && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
2253
|
-
/* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: option.value, size: 24 }),
|
|
2254
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: option.label })
|
|
2255
|
-
] })
|
|
2829
|
+
onChange: field.onChange,
|
|
2830
|
+
disabled: isLoadingCurrencies
|
|
2256
2831
|
}
|
|
2257
2832
|
) }),
|
|
2258
2833
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.FormMessage, {})
|
|
@@ -2283,36 +2858,49 @@ function WithdrawSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2283
2858
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Amount" }),
|
|
2284
2859
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
2285
2860
|
"$",
|
|
2286
|
-
amount
|
|
2861
|
+
formatUsdAmount(amount)
|
|
2287
2862
|
] })
|
|
2288
2863
|
] }),
|
|
2289
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center
|
|
2290
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2291
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-destructive", children: [
|
|
2299
|
-
"-$",
|
|
2300
|
-
feeBreakdown.networkFee.toFixed(2)
|
|
2301
|
-
] })
|
|
2302
|
-
] }),
|
|
2303
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t pt-2 mt-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2304
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "You will receive" }),
|
|
2305
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
|
|
2306
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-semibold", children: [
|
|
2307
|
-
"$",
|
|
2308
|
-
feeBreakdown.finalAmount.toFixed(2)
|
|
2864
|
+
isLoadingEstimate ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground py-2", children: [
|
|
2865
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
2866
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Calculating fees..." })
|
|
2867
|
+
] }) : estimate ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2868
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
2869
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
|
|
2870
|
+
"Service fee (",
|
|
2871
|
+
estimate.serviceFeePercent,
|
|
2872
|
+
"%)"
|
|
2309
2873
|
] }),
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2874
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-destructive", children: [
|
|
2875
|
+
"-$",
|
|
2876
|
+
formatUsdAmount(estimate.serviceFeeUsd)
|
|
2313
2877
|
] })
|
|
2314
|
-
] })
|
|
2315
|
-
|
|
2878
|
+
] }),
|
|
2879
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
2880
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Network fee" }),
|
|
2881
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-destructive", children: [
|
|
2882
|
+
"-$",
|
|
2883
|
+
formatUsdAmount(estimate.networkFeeUsd)
|
|
2884
|
+
] })
|
|
2885
|
+
] }),
|
|
2886
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t pt-2 mt-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2887
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "You will receive" }),
|
|
2888
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
|
|
2889
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-semibold", children: [
|
|
2890
|
+
"$",
|
|
2891
|
+
formatUsdAmount(estimate.amountToReceive)
|
|
2892
|
+
] }),
|
|
2893
|
+
cryptoDisplay && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
|
|
2894
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: cryptoDisplay.token, size: 16 }),
|
|
2895
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
|
|
2896
|
+
cryptoDisplay.cryptoAmount,
|
|
2897
|
+
" ",
|
|
2898
|
+
cryptoDisplay.token
|
|
2899
|
+
] })
|
|
2900
|
+
] })
|
|
2901
|
+
] })
|
|
2902
|
+
] }) })
|
|
2903
|
+
] }) : null
|
|
2316
2904
|
] }),
|
|
2317
2905
|
/* @__PURE__ */ jsxRuntime.jsxs(uiCore.Alert, { children: [
|
|
2318
2906
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-4 w-4" }),
|
|
@@ -2325,7 +2913,7 @@ function WithdrawSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2325
2913
|
type: "submit",
|
|
2326
2914
|
size: "lg",
|
|
2327
2915
|
className: "w-full h-14 text-lg rounded-xl",
|
|
2328
|
-
disabled: isSubmitting || currencyOptions.length === 0 || insufficientBalance ||
|
|
2916
|
+
disabled: isSubmitting || currencyOptions.length === 0 || insufficientBalance || !estimate || estimate.amountToReceive <= 0 || isLoadingEstimate,
|
|
2329
2917
|
children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2330
2918
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-5 w-5 mr-2 animate-spin" }),
|
|
2331
2919
|
"Submitting..."
|
|
@@ -2336,6 +2924,229 @@ function WithdrawSheet({ open, onOpenChange, onSuccess }) {
|
|
|
2336
2924
|
] }) });
|
|
2337
2925
|
}
|
|
2338
2926
|
var statusConfig2 = {
|
|
2927
|
+
pending: {
|
|
2928
|
+
icon: lucideReact.Clock,
|
|
2929
|
+
color: "text-yellow-500",
|
|
2930
|
+
bg: "bg-yellow-500/10",
|
|
2931
|
+
label: "Pending Approval"
|
|
2932
|
+
},
|
|
2933
|
+
approved: {
|
|
2934
|
+
icon: lucideReact.CheckCircle2,
|
|
2935
|
+
color: "text-blue-500",
|
|
2936
|
+
bg: "bg-blue-500/10",
|
|
2937
|
+
label: "Approved"
|
|
2938
|
+
},
|
|
2939
|
+
processing: {
|
|
2940
|
+
icon: lucideReact.RefreshCw,
|
|
2941
|
+
color: "text-blue-500",
|
|
2942
|
+
bg: "bg-blue-500/10",
|
|
2943
|
+
label: "Processing",
|
|
2944
|
+
animate: true
|
|
2945
|
+
},
|
|
2946
|
+
completed: {
|
|
2947
|
+
icon: lucideReact.CheckCircle2,
|
|
2948
|
+
color: "text-green-500",
|
|
2949
|
+
bg: "bg-green-500/10",
|
|
2950
|
+
label: "Completed"
|
|
2951
|
+
},
|
|
2952
|
+
rejected: {
|
|
2953
|
+
icon: lucideReact.XCircle,
|
|
2954
|
+
color: "text-red-500",
|
|
2955
|
+
bg: "bg-red-500/10",
|
|
2956
|
+
label: "Rejected"
|
|
2957
|
+
},
|
|
2958
|
+
cancelled: {
|
|
2959
|
+
icon: lucideReact.Ban,
|
|
2960
|
+
color: "text-muted-foreground",
|
|
2961
|
+
bg: "bg-muted",
|
|
2962
|
+
label: "Cancelled"
|
|
2963
|
+
}
|
|
2964
|
+
};
|
|
2965
|
+
function WithdrawalSheet({ withdrawalId, open, onOpenChange }) {
|
|
2966
|
+
const { getWithdrawalDetails, cancelWithdrawal, refreshWallet } = useWallet();
|
|
2967
|
+
const { data: withdrawal, isLoading, error, mutate } = useSWR__default.default(
|
|
2968
|
+
open && withdrawalId ? ["withdrawal-details", withdrawalId] : null,
|
|
2969
|
+
() => getWithdrawalDetails(withdrawalId),
|
|
2970
|
+
{ refreshInterval: 3e4 }
|
|
2971
|
+
);
|
|
2972
|
+
const displayData = react.useMemo(() => {
|
|
2973
|
+
const s = withdrawal?.status?.toLowerCase() || "pending";
|
|
2974
|
+
const config2 = statusConfig2[s] || statusConfig2.pending;
|
|
2975
|
+
const isPending = s === "pending";
|
|
2976
|
+
const isCompleted = s === "completed";
|
|
2977
|
+
const isRejected = s === "rejected";
|
|
2978
|
+
const isCancelled = s === "cancelled";
|
|
2979
|
+
const isProcessing = s === "processing" || s === "approved";
|
|
2980
|
+
const canCancel2 = isPending;
|
|
2981
|
+
let description2 = "";
|
|
2982
|
+
if (isPending) description2 = "Waiting for admin approval";
|
|
2983
|
+
else if (isProcessing) description2 = "Your withdrawal is being processed";
|
|
2984
|
+
else if (isCompleted) description2 = "Withdrawal completed successfully";
|
|
2985
|
+
else if (isRejected) description2 = "Withdrawal was rejected";
|
|
2986
|
+
else if (isCancelled) description2 = "Withdrawal was cancelled";
|
|
2987
|
+
const amountUsd2 = withdrawal?.amount_usd ? `$${parseFloat(withdrawal.amount_usd).toFixed(2)}` : "";
|
|
2988
|
+
const finalAmountUsd2 = withdrawal?.final_amount_usd ? `$${parseFloat(withdrawal.final_amount_usd).toFixed(2)}` : "";
|
|
2989
|
+
const totalFeeUsd2 = withdrawal?.total_fee_usd ? `$${parseFloat(withdrawal.total_fee_usd).toFixed(2)}` : "";
|
|
2990
|
+
const createdAt2 = withdrawal?.created_at ? moment3__default.default.utc(withdrawal.created_at).local().format("MMM D, YYYY HH:mm") : "";
|
|
2991
|
+
const completedAt2 = withdrawal?.completed_at ? moment3__default.default.utc(withdrawal.completed_at).local().format("MMM D, YYYY HH:mm") : null;
|
|
2992
|
+
return {
|
|
2993
|
+
status: s,
|
|
2994
|
+
config: config2,
|
|
2995
|
+
isPending,
|
|
2996
|
+
isCompleted,
|
|
2997
|
+
isRejected,
|
|
2998
|
+
isCancelled,
|
|
2999
|
+
isProcessing,
|
|
3000
|
+
canCancel: canCancel2,
|
|
3001
|
+
description: description2,
|
|
3002
|
+
amountUsd: amountUsd2,
|
|
3003
|
+
finalAmountUsd: finalAmountUsd2,
|
|
3004
|
+
totalFeeUsd: totalFeeUsd2,
|
|
3005
|
+
createdAt: createdAt2,
|
|
3006
|
+
completedAt: completedAt2
|
|
3007
|
+
};
|
|
3008
|
+
}, [withdrawal]);
|
|
3009
|
+
const { config, canCancel, description, amountUsd, finalAmountUsd, totalFeeUsd, createdAt, completedAt } = displayData;
|
|
3010
|
+
const StatusIcon = config.icon;
|
|
3011
|
+
const handleCancel = async () => {
|
|
3012
|
+
if (!withdrawalId) return;
|
|
3013
|
+
try {
|
|
3014
|
+
await cancelWithdrawal(withdrawalId);
|
|
3015
|
+
await mutate();
|
|
3016
|
+
await refreshWallet();
|
|
3017
|
+
} catch (err) {
|
|
3018
|
+
console.error("Failed to cancel withdrawal:", err);
|
|
3019
|
+
}
|
|
3020
|
+
};
|
|
3021
|
+
return /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheet, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetContent, { className: "sm:max-w-lg", children: [
|
|
3022
|
+
/* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetHeader, { children: [
|
|
3023
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetTitle, { children: "Withdrawal Details" }),
|
|
3024
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetDescription, { children: description })
|
|
3025
|
+
] }),
|
|
3026
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 sm:p-0 sm:mt-4 overflow-y-auto max-h-[70vh]", children: [
|
|
3027
|
+
isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
3028
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-16 w-full rounded-xl" }),
|
|
3029
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-24 w-full rounded-xl" }),
|
|
3030
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-20 w-full rounded-xl" })
|
|
3031
|
+
] }),
|
|
3032
|
+
error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-12", children: [
|
|
3033
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "h-12 w-12 text-destructive mb-4" }),
|
|
3034
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-4", children: "Failed to load withdrawal" }),
|
|
3035
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.Button, { onClick: () => mutate(), children: "Try Again" })
|
|
3036
|
+
] }),
|
|
3037
|
+
withdrawal && !isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
3038
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("flex items-center gap-3 p-4 rounded-xl", config.bg), children: [
|
|
3039
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { className: lib.cn("h-6 w-6", config.color, config.animate && "animate-spin") }),
|
|
3040
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
|
|
3041
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold", children: config.label }),
|
|
3042
|
+
withdrawal.admin_notes && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground", children: withdrawal.admin_notes })
|
|
3043
|
+
] })
|
|
3044
|
+
] }),
|
|
3045
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted rounded-xl p-4 space-y-3", children: [
|
|
3046
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
3047
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Amount" }),
|
|
3048
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: amountUsd })
|
|
3049
|
+
] }),
|
|
3050
|
+
totalFeeUsd && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
3051
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Total fees" }),
|
|
3052
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-destructive", children: [
|
|
3053
|
+
"-",
|
|
3054
|
+
totalFeeUsd
|
|
3055
|
+
] })
|
|
3056
|
+
] }),
|
|
3057
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between pt-2 border-t", children: [
|
|
3058
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "You receive" }),
|
|
3059
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3060
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: withdrawal.currency_code, size: 24 }),
|
|
3061
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-bold text-lg", children: finalAmountUsd })
|
|
3062
|
+
] })
|
|
3063
|
+
] }),
|
|
3064
|
+
withdrawal.crypto_amount && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
3065
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Crypto amount" }),
|
|
3066
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
|
|
3067
|
+
withdrawal.crypto_amount,
|
|
3068
|
+
" ",
|
|
3069
|
+
withdrawal.currency_token
|
|
3070
|
+
] })
|
|
3071
|
+
] })
|
|
3072
|
+
] }),
|
|
3073
|
+
withdrawal.wallet_address && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
3074
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Destination Wallet" }),
|
|
3075
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3076
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all", children: withdrawal.wallet_address }),
|
|
3077
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.CopyButton, { value: withdrawal.wallet_address, variant: "outline", className: "shrink-0" })
|
|
3078
|
+
] })
|
|
3079
|
+
] }),
|
|
3080
|
+
withdrawal.transaction_hash && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
3081
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
|
|
3082
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3083
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all", children: withdrawal.transaction_hash }),
|
|
3084
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.CopyButton, { value: withdrawal.transaction_hash, variant: "outline", className: "shrink-0" })
|
|
3085
|
+
] })
|
|
3086
|
+
] }),
|
|
3087
|
+
withdrawal.explorer_link && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3088
|
+
uiCore.Button,
|
|
3089
|
+
{
|
|
3090
|
+
variant: "outline",
|
|
3091
|
+
className: "w-full",
|
|
3092
|
+
onClick: () => window.open(withdrawal.explorer_link, "_blank"),
|
|
3093
|
+
children: [
|
|
3094
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4 mr-2" }),
|
|
3095
|
+
"View on Explorer"
|
|
3096
|
+
]
|
|
3097
|
+
}
|
|
3098
|
+
),
|
|
3099
|
+
canCancel && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3100
|
+
uiCore.Button,
|
|
3101
|
+
{
|
|
3102
|
+
variant: "destructive",
|
|
3103
|
+
className: "w-full",
|
|
3104
|
+
onClick: handleCancel,
|
|
3105
|
+
children: [
|
|
3106
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ban, { className: "h-4 w-4 mr-2" }),
|
|
3107
|
+
"Cancel Withdrawal"
|
|
3108
|
+
]
|
|
3109
|
+
}
|
|
3110
|
+
),
|
|
3111
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 text-xs text-muted-foreground pt-4 border-t", children: [
|
|
3112
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
|
|
3113
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Withdrawal ID" }),
|
|
3114
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: withdrawal.id })
|
|
3115
|
+
] }),
|
|
3116
|
+
withdrawal.internal_withdrawal_id && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
|
|
3117
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Reference #" }),
|
|
3118
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: withdrawal.internal_withdrawal_id })
|
|
3119
|
+
] }),
|
|
3120
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
|
|
3121
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Created" }),
|
|
3122
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: createdAt })
|
|
3123
|
+
] }),
|
|
3124
|
+
completedAt && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
|
|
3125
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Completed" }),
|
|
3126
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: completedAt })
|
|
3127
|
+
] }),
|
|
3128
|
+
withdrawal.currency_network && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
|
|
3129
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Network" }),
|
|
3130
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: withdrawal.currency_network })
|
|
3131
|
+
] })
|
|
3132
|
+
] }),
|
|
3133
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3134
|
+
uiCore.Button,
|
|
3135
|
+
{
|
|
3136
|
+
variant: "ghost",
|
|
3137
|
+
className: "w-full",
|
|
3138
|
+
onClick: () => mutate(),
|
|
3139
|
+
children: [
|
|
3140
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-4 w-4 mr-2" }),
|
|
3141
|
+
"Refresh Status"
|
|
3142
|
+
]
|
|
3143
|
+
}
|
|
3144
|
+
)
|
|
3145
|
+
] })
|
|
3146
|
+
] })
|
|
3147
|
+
] }) });
|
|
3148
|
+
}
|
|
3149
|
+
var statusConfig3 = {
|
|
2339
3150
|
pending: {
|
|
2340
3151
|
icon: lucideReact.Clock,
|
|
2341
3152
|
color: "text-yellow-500",
|
|
@@ -2368,25 +3179,25 @@ var statusConfig2 = {
|
|
|
2368
3179
|
label: "Expired"
|
|
2369
3180
|
}
|
|
2370
3181
|
};
|
|
2371
|
-
function PaymentSheet({ paymentId, open, onOpenChange }) {
|
|
3182
|
+
function PaymentSheet({ paymentId, open, onOpenChange, onCreateNew }) {
|
|
2372
3183
|
const { getPaymentDetails } = useWallet();
|
|
2373
|
-
const [timeLeft, setTimeLeft] =
|
|
2374
|
-
const { data: payment, isLoading, error, mutate } =
|
|
3184
|
+
const [timeLeft, setTimeLeft] = react.useState("");
|
|
3185
|
+
const { data: payment, isLoading, error, mutate } = useSWR__default.default(
|
|
2375
3186
|
open && paymentId ? ["payment-details", paymentId] : null,
|
|
2376
3187
|
() => getPaymentDetails(paymentId),
|
|
2377
3188
|
{ refreshInterval: 1e4 }
|
|
2378
3189
|
);
|
|
2379
|
-
|
|
3190
|
+
react.useEffect(() => {
|
|
2380
3191
|
if (!payment?.expires_at) return;
|
|
2381
3192
|
const updateTimeLeft = () => {
|
|
2382
|
-
const now =
|
|
2383
|
-
const expires =
|
|
3193
|
+
const now = moment3__default.default();
|
|
3194
|
+
const expires = moment3__default.default.utc(payment.expires_at);
|
|
2384
3195
|
const diff = expires.diff(now);
|
|
2385
3196
|
if (diff <= 0) {
|
|
2386
3197
|
setTimeLeft("Expired");
|
|
2387
3198
|
return;
|
|
2388
3199
|
}
|
|
2389
|
-
const duration =
|
|
3200
|
+
const duration = moment3__default.default.duration(diff);
|
|
2390
3201
|
const hours = Math.floor(duration.asHours());
|
|
2391
3202
|
const minutes = duration.minutes();
|
|
2392
3203
|
const seconds = duration.seconds();
|
|
@@ -2396,22 +3207,59 @@ function PaymentSheet({ paymentId, open, onOpenChange }) {
|
|
|
2396
3207
|
const interval = setInterval(updateTimeLeft, 1e3);
|
|
2397
3208
|
return () => clearInterval(interval);
|
|
2398
3209
|
}, [payment?.expires_at]);
|
|
2399
|
-
const
|
|
3210
|
+
const displayData = react.useMemo(() => {
|
|
2400
3211
|
const s = payment?.status?.toLowerCase();
|
|
2401
|
-
|
|
2402
|
-
if (s === "
|
|
2403
|
-
if (s === "
|
|
2404
|
-
if (s === "
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
3212
|
+
let status;
|
|
3213
|
+
if (s === "completed" || s === "success" || s === "finished") status = "completed";
|
|
3214
|
+
else if (s === "confirming" || s === "partially_paid") status = "confirming";
|
|
3215
|
+
else if (s === "expired") status = "expired";
|
|
3216
|
+
else if (s === "failed" || s === "error" || s === "cancelled") status = "failed";
|
|
3217
|
+
else status = "pending";
|
|
3218
|
+
const config2 = statusConfig3[status];
|
|
3219
|
+
const isPending = status === "pending";
|
|
3220
|
+
const isExpired2 = status === "expired" || timeLeft === "Expired";
|
|
3221
|
+
const isCompleted = status === "completed";
|
|
3222
|
+
const isFailed = status === "failed";
|
|
3223
|
+
const isConfirming = status === "confirming";
|
|
3224
|
+
const canPay2 = isPending && !isExpired2;
|
|
3225
|
+
let description2 = "";
|
|
3226
|
+
if (canPay2) description2 = "Send cryptocurrency to complete payment";
|
|
3227
|
+
else if (isExpired2) description2 = "This payment has expired";
|
|
3228
|
+
else if (isCompleted) description2 = "Payment completed successfully";
|
|
3229
|
+
else if (isFailed) description2 = "Payment failed";
|
|
3230
|
+
else if (isConfirming) description2 = "Confirming your payment";
|
|
3231
|
+
const statusBadge2 = {
|
|
3232
|
+
bg: isExpired2 ? "bg-muted" : config2.bg,
|
|
3233
|
+
iconColor: isExpired2 ? "text-muted-foreground" : config2.color,
|
|
3234
|
+
iconAnimate: config2.animate,
|
|
3235
|
+
label: isExpired2 ? "Payment Expired" : config2.label,
|
|
3236
|
+
subtitle: canPay2 && timeLeft ? `Expires in ${timeLeft}` : isExpired2 ? "Please create a new payment to continue" : null
|
|
3237
|
+
};
|
|
3238
|
+
const qrCodeUrl2 = payment?.pay_address && canPay2 ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(payment.pay_address)}` : null;
|
|
3239
|
+
const amountUsd2 = payment?.amount_usd ? `$${parseFloat(payment.amount_usd).toFixed(2)} USD` : "";
|
|
3240
|
+
const createdAt2 = payment?.created_at ? moment3__default.default.utc(payment.created_at).local().format("MMM D, YYYY HH:mm") : "";
|
|
3241
|
+
return {
|
|
3242
|
+
status,
|
|
3243
|
+
config: config2,
|
|
3244
|
+
isPending,
|
|
3245
|
+
isExpired: isExpired2,
|
|
3246
|
+
isCompleted,
|
|
3247
|
+
isFailed,
|
|
3248
|
+
isConfirming,
|
|
3249
|
+
canPay: canPay2,
|
|
3250
|
+
description: description2,
|
|
3251
|
+
statusBadge: statusBadge2,
|
|
3252
|
+
qrCodeUrl: qrCodeUrl2,
|
|
3253
|
+
amountUsd: amountUsd2,
|
|
3254
|
+
createdAt: createdAt2
|
|
3255
|
+
};
|
|
3256
|
+
}, [payment, timeLeft]);
|
|
3257
|
+
const { config, canPay, isExpired, description, statusBadge, qrCodeUrl, amountUsd, createdAt } = displayData;
|
|
2408
3258
|
const StatusIcon = config.icon;
|
|
2409
|
-
const qrCodeUrl = payment?.pay_address ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(payment.pay_address)}` : null;
|
|
2410
|
-
const isPending = status === "pending";
|
|
2411
3259
|
return /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheet, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetContent, { className: "sm:max-w-lg", children: [
|
|
2412
3260
|
/* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetHeader, { children: [
|
|
2413
3261
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetTitle, { children: "Payment Details" }),
|
|
2414
|
-
/* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetDescription, { children:
|
|
3262
|
+
/* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetDescription, { children: description })
|
|
2415
3263
|
] }),
|
|
2416
3264
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 sm:p-0 sm:mt-4 overflow-y-auto max-h-[70vh]", children: [
|
|
2417
3265
|
isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
@@ -2425,14 +3273,11 @@ function PaymentSheet({ paymentId, open, onOpenChange }) {
|
|
|
2425
3273
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.Button, { onClick: () => mutate(), children: "Try Again" })
|
|
2426
3274
|
] }),
|
|
2427
3275
|
payment && !isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
2428
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("flex items-center gap-3 p-4 rounded-xl",
|
|
2429
|
-
/* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { className: lib.cn("h-6 w-6",
|
|
3276
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("flex items-center gap-3 p-4 rounded-xl", statusBadge.bg), children: [
|
|
3277
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { className: lib.cn("h-6 w-6", statusBadge.iconColor, statusBadge.iconAnimate && "animate-spin") }),
|
|
2430
3278
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
|
|
2431
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold", children:
|
|
2432
|
-
|
|
2433
|
-
"Expires in ",
|
|
2434
|
-
timeLeft
|
|
2435
|
-
] })
|
|
3279
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold", children: statusBadge.label }),
|
|
3280
|
+
statusBadge.subtitle && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground", children: statusBadge.subtitle })
|
|
2436
3281
|
] })
|
|
2437
3282
|
] }),
|
|
2438
3283
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted rounded-xl p-4 space-y-3", children: [
|
|
@@ -2449,30 +3294,38 @@ function PaymentSheet({ paymentId, open, onOpenChange }) {
|
|
|
2449
3294
|
] }),
|
|
2450
3295
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
2451
3296
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Equivalent" }),
|
|
2452
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2453
|
-
"$",
|
|
2454
|
-
parseFloat(payment.amount_usd).toFixed(2),
|
|
2455
|
-
" USD"
|
|
2456
|
-
] })
|
|
3297
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: amountUsd })
|
|
2457
3298
|
] }),
|
|
2458
3299
|
payment.currency_network && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm pt-2 border-t", children: [
|
|
2459
3300
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Network" }),
|
|
2460
3301
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: payment.currency_network })
|
|
2461
3302
|
] })
|
|
2462
3303
|
] }),
|
|
2463
|
-
qrCodeUrl &&
|
|
2464
|
-
payment.pay_address &&
|
|
3304
|
+
qrCodeUrl && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center p-6 bg-white rounded-xl", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: qrCodeUrl, alt: "Payment QR Code", className: "w-48 h-48" }) }),
|
|
3305
|
+
payment.pay_address && canPay && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
2465
3306
|
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Payment Address" }),
|
|
2466
3307
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2467
3308
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all", children: payment.pay_address }),
|
|
2468
3309
|
/* @__PURE__ */ jsxRuntime.jsx(uiCore.CopyButton, { value: payment.pay_address, variant: "outline", className: "shrink-0" })
|
|
2469
3310
|
] })
|
|
2470
3311
|
] }),
|
|
3312
|
+
isExpired && onCreateNew && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3313
|
+
uiCore.Button,
|
|
3314
|
+
{
|
|
3315
|
+
size: "lg",
|
|
3316
|
+
className: "w-full",
|
|
3317
|
+
onClick: () => {
|
|
3318
|
+
onOpenChange(false);
|
|
3319
|
+
onCreateNew();
|
|
3320
|
+
},
|
|
3321
|
+
children: "Create New Payment"
|
|
3322
|
+
}
|
|
3323
|
+
),
|
|
2471
3324
|
payment.transaction_hash && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
2472
3325
|
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
|
|
2473
3326
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3 bg-muted rounded-xl font-mono text-sm break-all", children: payment.transaction_hash })
|
|
2474
3327
|
] }),
|
|
2475
|
-
payment.payment_url &&
|
|
3328
|
+
payment.payment_url && canPay && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2476
3329
|
uiCore.Button,
|
|
2477
3330
|
{
|
|
2478
3331
|
variant: "outline",
|
|
@@ -2495,7 +3348,7 @@ function PaymentSheet({ paymentId, open, onOpenChange }) {
|
|
|
2495
3348
|
] }),
|
|
2496
3349
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
|
|
2497
3350
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Created" }),
|
|
2498
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children:
|
|
3351
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: createdAt })
|
|
2499
3352
|
] })
|
|
2500
3353
|
] }),
|
|
2501
3354
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2514,54 +3367,85 @@ function PaymentSheet({ paymentId, open, onOpenChange }) {
|
|
|
2514
3367
|
] })
|
|
2515
3368
|
] }) });
|
|
2516
3369
|
}
|
|
2517
|
-
var
|
|
2518
|
-
|
|
2519
|
-
const
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
}
|
|
2532
|
-
|
|
2533
|
-
const
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
}
|
|
2537
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
}
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
3370
|
+
var WalletContent = () => {
|
|
3371
|
+
const [addFundsOpen, setAddFundsOpen] = react.useState(false);
|
|
3372
|
+
const [withdrawOpen, setWithdrawOpen] = react.useState(false);
|
|
3373
|
+
const [selectedPaymentId, setSelectedPaymentId] = react.useState(null);
|
|
3374
|
+
const [paymentSheetOpen, setPaymentSheetOpen] = react.useState(false);
|
|
3375
|
+
const [selectedWithdrawalId, setSelectedWithdrawalId] = react.useState(null);
|
|
3376
|
+
const [withdrawalSheetOpen, setWithdrawalSheetOpen] = react.useState(false);
|
|
3377
|
+
const handleActivityClick = react.useCallback((item) => {
|
|
3378
|
+
if (item.payment) {
|
|
3379
|
+
setSelectedPaymentId(item.payment.id);
|
|
3380
|
+
setPaymentSheetOpen(true);
|
|
3381
|
+
} else if (item.withdrawal) {
|
|
3382
|
+
setSelectedWithdrawalId(item.withdrawal.id);
|
|
3383
|
+
setWithdrawalSheetOpen(true);
|
|
3384
|
+
}
|
|
3385
|
+
}, []);
|
|
3386
|
+
const handlePaymentCreated = react.useCallback((payment) => {
|
|
3387
|
+
setSelectedPaymentId(payment.id);
|
|
3388
|
+
setPaymentSheetOpen(true);
|
|
3389
|
+
}, []);
|
|
3390
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-h-screen", children: [
|
|
3391
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3392
|
+
BalanceHero,
|
|
3393
|
+
{
|
|
3394
|
+
onAddFunds: () => setAddFundsOpen(true),
|
|
3395
|
+
onWithdraw: () => setWithdrawOpen(true),
|
|
3396
|
+
className: "bg-muted/30 border-b"
|
|
3397
|
+
}
|
|
3398
|
+
),
|
|
3399
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3400
|
+
ActivityList,
|
|
3401
|
+
{
|
|
3402
|
+
onItemClick: handleActivityClick,
|
|
3403
|
+
limit: 20,
|
|
3404
|
+
className: "max-w-2xl mx-auto pb-12"
|
|
3405
|
+
}
|
|
3406
|
+
),
|
|
3407
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3408
|
+
AddFundsSheet,
|
|
3409
|
+
{
|
|
3410
|
+
open: addFundsOpen,
|
|
3411
|
+
onOpenChange: setAddFundsOpen,
|
|
3412
|
+
onSuccess: handlePaymentCreated
|
|
3413
|
+
}
|
|
3414
|
+
),
|
|
3415
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3416
|
+
WithdrawSheet,
|
|
3417
|
+
{
|
|
3418
|
+
open: withdrawOpen,
|
|
3419
|
+
onOpenChange: setWithdrawOpen
|
|
3420
|
+
}
|
|
3421
|
+
),
|
|
3422
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3423
|
+
PaymentSheet,
|
|
3424
|
+
{
|
|
3425
|
+
paymentId: selectedPaymentId,
|
|
3426
|
+
open: paymentSheetOpen,
|
|
3427
|
+
onOpenChange: setPaymentSheetOpen,
|
|
3428
|
+
onCreateNew: () => setAddFundsOpen(true)
|
|
3429
|
+
}
|
|
3430
|
+
),
|
|
3431
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3432
|
+
WithdrawalSheet,
|
|
3433
|
+
{
|
|
3434
|
+
withdrawalId: selectedWithdrawalId,
|
|
3435
|
+
open: withdrawalSheetOpen,
|
|
3436
|
+
onOpenChange: setWithdrawalSheetOpen
|
|
3437
|
+
}
|
|
3438
|
+
)
|
|
3439
|
+
] });
|
|
3440
|
+
};
|
|
3441
|
+
function WalletPage() {
|
|
3442
|
+
return /* @__PURE__ */ jsxRuntime.jsx(WalletProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(WalletContent, {}) });
|
|
2559
3443
|
}
|
|
2560
3444
|
|
|
2561
3445
|
// package.json
|
|
2562
3446
|
var package_default = {
|
|
2563
3447
|
name: "@djangocfg/ext-payments",
|
|
2564
|
-
version: "1.0.
|
|
3448
|
+
version: "1.0.19",
|
|
2565
3449
|
description: "Payments system extension for DjangoCFG",
|
|
2566
3450
|
keywords: [
|
|
2567
3451
|
"django",
|
|
@@ -2723,23 +3607,22 @@ exports.NetworkError = NetworkError;
|
|
|
2723
3607
|
exports.PaginatedPaymentListListSchema = PaginatedPaymentListListSchema;
|
|
2724
3608
|
exports.PaginatedWithdrawalListListSchema = PaginatedWithdrawalListListSchema;
|
|
2725
3609
|
exports.PaymentCreateRequestSchema = PaymentCreateRequestSchema;
|
|
3610
|
+
exports.PaymentCreateResponseSchema = PaymentCreateResponseSchema;
|
|
2726
3611
|
exports.PaymentDetailSchema = PaymentDetailSchema;
|
|
2727
3612
|
exports.PaymentListSchema = PaymentListSchema;
|
|
2728
3613
|
exports.PaymentSheet = PaymentSheet;
|
|
2729
3614
|
exports.REFRESH_TOKEN_KEY = REFRESH_TOKEN_KEY;
|
|
2730
|
-
exports.ResponsiveSheet = ResponsiveSheet4;
|
|
2731
|
-
exports.ResponsiveSheetContent = ResponsiveSheetContent4;
|
|
2732
|
-
exports.ResponsiveSheetDescription = ResponsiveSheetDescription4;
|
|
2733
|
-
exports.ResponsiveSheetFooter = ResponsiveSheetFooter;
|
|
2734
|
-
exports.ResponsiveSheetHeader = ResponsiveSheetHeader4;
|
|
2735
|
-
exports.ResponsiveSheetTitle = ResponsiveSheetTitle4;
|
|
2736
3615
|
exports.Schemas = schemas_exports;
|
|
2737
3616
|
exports.TOKEN_KEY = TOKEN_KEY;
|
|
2738
3617
|
exports.TransactionSchema = TransactionSchema;
|
|
3618
|
+
exports.WalletPage = WalletPage;
|
|
2739
3619
|
exports.WithdrawSheet = WithdrawSheet;
|
|
3620
|
+
exports.WithdrawalCancelResponseSchema = WithdrawalCancelResponseSchema;
|
|
2740
3621
|
exports.WithdrawalCreateRequestSchema = WithdrawalCreateRequestSchema;
|
|
3622
|
+
exports.WithdrawalCreateResponseSchema = WithdrawalCreateResponseSchema;
|
|
2741
3623
|
exports.WithdrawalDetailSchema = WithdrawalDetailSchema;
|
|
2742
3624
|
exports.WithdrawalListSchema = WithdrawalListSchema;
|
|
3625
|
+
exports.WithdrawalSheet = WithdrawalSheet;
|
|
2743
3626
|
exports.apiPayments = apiPayments;
|
|
2744
3627
|
exports.clearAPITokens = clearAPITokens;
|
|
2745
3628
|
exports.configureAPI = configureAPI;
|
|
@@ -2752,7 +3635,9 @@ exports.extensionConfig = extensionConfig;
|
|
|
2752
3635
|
exports.formatZodError = formatZodError;
|
|
2753
3636
|
exports.getAPIInstance = getAPIInstance;
|
|
2754
3637
|
exports.getPaymentsBalanceRetrieve = getPaymentsBalanceRetrieve;
|
|
3638
|
+
exports.getPaymentsCurrenciesEstimateRetrieve = getPaymentsCurrenciesEstimateRetrieve;
|
|
2755
3639
|
exports.getPaymentsCurrenciesList = getPaymentsCurrenciesList;
|
|
3640
|
+
exports.getPaymentsCurrenciesWithdrawalEstimateRetrieve = getPaymentsCurrenciesWithdrawalEstimateRetrieve;
|
|
2756
3641
|
exports.getPaymentsPaymentsList = getPaymentsPaymentsList;
|
|
2757
3642
|
exports.getPaymentsPaymentsRetrieve = getPaymentsPaymentsRetrieve;
|
|
2758
3643
|
exports.getPaymentsPaymentsStatusRetrieve = getPaymentsPaymentsStatusRetrieve;
|