@djangocfg/ext-payments 1.0.14 → 1.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/config.cjs +5 -8
  2. package/dist/config.js +5 -8
  3. package/dist/index.cjs +1906 -1043
  4. package/dist/index.d.cts +644 -59
  5. package/dist/index.d.ts +644 -59
  6. package/dist/index.js +1886 -1040
  7. package/package.json +13 -16
  8. package/src/WalletPage.tsx +100 -0
  9. package/src/api/generated/ext_payments/CLAUDE.md +10 -4
  10. package/src/api/generated/ext_payments/_utils/fetchers/ext_payments__payments.ts +268 -5
  11. package/src/api/generated/ext_payments/_utils/hooks/ext_payments__payments.ts +102 -3
  12. package/src/api/generated/ext_payments/_utils/schemas/Balance.schema.ts +1 -1
  13. package/src/api/generated/ext_payments/_utils/schemas/PaginatedWithdrawalListList.schema.ts +24 -0
  14. package/src/api/generated/ext_payments/_utils/schemas/PaymentCreateRequest.schema.ts +21 -0
  15. package/src/api/generated/ext_payments/_utils/schemas/PaymentCreateResponse.schema.ts +22 -0
  16. package/src/api/generated/ext_payments/_utils/schemas/PaymentDetail.schema.ts +3 -3
  17. package/src/api/generated/ext_payments/_utils/schemas/PaymentList.schema.ts +2 -2
  18. package/src/api/generated/ext_payments/_utils/schemas/Transaction.schema.ts +1 -1
  19. package/src/api/generated/ext_payments/_utils/schemas/WithdrawalCancelResponse.schema.ts +22 -0
  20. package/src/api/generated/ext_payments/_utils/schemas/WithdrawalCreateRequest.schema.ts +21 -0
  21. package/src/api/generated/ext_payments/_utils/schemas/WithdrawalCreateResponse.schema.ts +22 -0
  22. package/src/api/generated/ext_payments/_utils/schemas/WithdrawalDetail.schema.ts +42 -0
  23. package/src/api/generated/ext_payments/_utils/schemas/WithdrawalList.schema.ts +29 -0
  24. package/src/api/generated/ext_payments/_utils/schemas/index.ts +8 -0
  25. package/src/api/generated/ext_payments/client.ts +1 -1
  26. package/src/api/generated/ext_payments/enums.ts +36 -0
  27. package/src/api/generated/ext_payments/ext_payments__payments/client.ts +104 -6
  28. package/src/api/generated/ext_payments/ext_payments__payments/models.ts +168 -8
  29. package/src/api/generated/ext_payments/index.ts +1 -1
  30. package/src/api/generated/ext_payments/schema.json +752 -42
  31. package/src/components/ActivityItem.tsx +118 -0
  32. package/src/components/ActivityList.tsx +93 -0
  33. package/src/components/AddFundsSheet.tsx +342 -0
  34. package/src/components/BalanceHero.tsx +102 -0
  35. package/src/components/CurrencyCombobox.tsx +49 -0
  36. package/src/components/PaymentSheet.tsx +352 -0
  37. package/src/components/WithdrawSheet.tsx +355 -0
  38. package/src/components/WithdrawalSheet.tsx +332 -0
  39. package/src/components/index.ts +11 -0
  40. package/src/config.ts +1 -0
  41. package/src/contexts/WalletContext.tsx +356 -0
  42. package/src/contexts/index.ts +13 -42
  43. package/src/contexts/types.ts +43 -37
  44. package/src/hooks/index.ts +3 -20
  45. package/src/hooks/useCurrencyOptions.ts +79 -0
  46. package/src/hooks/useEstimate.ts +113 -0
  47. package/src/hooks/useWithdrawalEstimate.ts +117 -0
  48. package/src/index.ts +9 -18
  49. package/src/types/index.ts +78 -0
  50. package/src/utils/errors.ts +36 -0
  51. package/src/utils/format.ts +65 -0
  52. package/src/utils/index.ts +3 -0
  53. package/src/contexts/BalancesContext.tsx +0 -63
  54. package/src/contexts/CurrenciesContext.tsx +0 -64
  55. package/src/contexts/OverviewContext.tsx +0 -173
  56. package/src/contexts/PaymentsContext.tsx +0 -122
  57. package/src/contexts/PaymentsExtensionProvider.tsx +0 -56
  58. package/src/contexts/README.md +0 -201
  59. package/src/contexts/RootPaymentsContext.tsx +0 -66
  60. package/src/layouts/PaymentsLayout/PaymentsLayout.tsx +0 -90
  61. package/src/layouts/PaymentsLayout/components/CreatePaymentDialog.tsx +0 -274
  62. package/src/layouts/PaymentsLayout/components/PaymentDetailsDialog.tsx +0 -287
  63. package/src/layouts/PaymentsLayout/components/index.ts +0 -2
  64. package/src/layouts/PaymentsLayout/events.ts +0 -47
  65. package/src/layouts/PaymentsLayout/index.ts +0 -16
  66. package/src/layouts/PaymentsLayout/types.ts +0 -6
  67. package/src/layouts/PaymentsLayout/views/overview/components/BalanceCard.tsx +0 -121
  68. package/src/layouts/PaymentsLayout/views/overview/components/RecentPayments.tsx +0 -139
  69. package/src/layouts/PaymentsLayout/views/overview/components/index.ts +0 -2
  70. package/src/layouts/PaymentsLayout/views/overview/index.tsx +0 -21
  71. package/src/layouts/PaymentsLayout/views/payments/components/PaymentsList.tsx +0 -279
  72. package/src/layouts/PaymentsLayout/views/payments/components/index.ts +0 -1
  73. package/src/layouts/PaymentsLayout/views/payments/index.tsx +0 -18
  74. package/src/layouts/PaymentsLayout/views/transactions/components/TransactionsList.tsx +0 -260
  75. package/src/layouts/PaymentsLayout/views/transactions/components/index.ts +0 -1
  76. package/src/layouts/PaymentsLayout/views/transactions/index.tsx +0 -18
package/dist/index.cjs CHANGED
@@ -1,25 +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 api = require('@djangocfg/ext-base/api');
7
- var lucideReact = require('lucide-react');
8
- var uiCore = require('@djangocfg/ui-core');
9
- var react = require('react');
10
8
  var useSWR = require('swr');
11
9
  var jsxRuntime = require('react/jsx-runtime');
10
+ var lucideReact = require('lucide-react');
11
+ var uiCore = require('@djangocfg/ui-core');
12
+ var lib = require('@djangocfg/ui-core/lib');
13
+ var moment3 = require('moment');
12
14
  var reactHookForm = require('react-hook-form');
13
15
  var zod$1 = require('@hookform/resolvers/zod');
14
- var moment = require('moment');
15
- var components = require('@djangocfg/ui-nextjs/components');
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
20
  var pRetry__default = /*#__PURE__*/_interopDefault(pRetry);
21
21
  var useSWR__default = /*#__PURE__*/_interopDefault(useSWR);
22
- var moment__default = /*#__PURE__*/_interopDefault(moment);
22
+ var moment3__default = /*#__PURE__*/_interopDefault(moment3);
23
23
 
24
24
  var __defProp = Object.defineProperty;
25
25
  var __export = (target, all) => {
@@ -45,12 +45,47 @@ var ExtPaymentsPayments = class {
45
45
  /**
46
46
  * Get available currencies
47
47
  *
48
- * Returns list of available currencies with token+network info
48
+ * Returns list of available currencies with token+network info, popular
49
+ * first
49
50
  */
50
51
  async currenciesList() {
51
52
  const response = await this.client.request("GET", "/cfg/payments/currencies/");
52
53
  return response;
53
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
+ }
54
89
  /**
55
90
  * ViewSet for payment operations. Endpoints: - GET /payments/ - List
56
91
  * user's payments - GET /payments/{id}/ - Get payment details - POST
@@ -97,12 +132,12 @@ var ExtPaymentsPayments = class {
97
132
  return response.results || response;
98
133
  }
99
134
  /**
100
- * POST /api/v1/payments/create/ Create new payment. Request body: {
101
- * "amount_usd": "100.00", "currency_code": "USDTTRC20", "description":
102
- * "Optional description" }
135
+ * Create payment
136
+ *
137
+ * Create a new payment with specified amount and currency
103
138
  */
104
- async paymentsCreateCreate() {
105
- const response = await this.client.request("POST", "/cfg/payments/payments/create/");
139
+ async paymentsCreateCreate(data) {
140
+ const response = await this.client.request("POST", "/cfg/payments/payments/create/", { body: data });
106
141
  return response;
107
142
  }
108
143
  /**
@@ -121,6 +156,51 @@ var ExtPaymentsPayments = class {
121
156
  const response = await this.client.request("GET", "/cfg/payments/transactions/", { params });
122
157
  return response;
123
158
  }
159
+ /**
160
+ * ViewSet for withdrawal operations. Endpoints: - GET /withdrawals/ - List
161
+ * user's withdrawal requests - GET /withdrawals/{id}/ - Get withdrawal
162
+ * details - POST /withdrawals/create/ - Create withdrawal request - POST
163
+ * /withdrawals/{id}/cancel/ - Cancel pending withdrawal
164
+ */
165
+ async withdrawalsList(...args) {
166
+ const isParamsObject = args.length === 1 && typeof args[0] === "object" && args[0] !== null && !Array.isArray(args[0]);
167
+ let params;
168
+ if (isParamsObject) {
169
+ params = args[0];
170
+ } else {
171
+ params = { page: args[0], page_size: args[1] };
172
+ }
173
+ const response = await this.client.request("GET", "/cfg/payments/withdrawals/", { params });
174
+ return response;
175
+ }
176
+ /**
177
+ * ViewSet for withdrawal operations. Endpoints: - GET /withdrawals/ - List
178
+ * user's withdrawal requests - GET /withdrawals/{id}/ - Get withdrawal
179
+ * details - POST /withdrawals/create/ - Create withdrawal request - POST
180
+ * /withdrawals/{id}/cancel/ - Cancel pending withdrawal
181
+ */
182
+ async withdrawalsRetrieve(id) {
183
+ const response = await this.client.request("GET", `/cfg/payments/withdrawals/${id}/`);
184
+ return response;
185
+ }
186
+ /**
187
+ * Cancel withdrawal request
188
+ *
189
+ * Cancel a pending withdrawal request
190
+ */
191
+ async withdrawalsCancelCreate(id) {
192
+ const response = await this.client.request("POST", `/cfg/payments/withdrawals/${id}/cancel/`);
193
+ return response;
194
+ }
195
+ /**
196
+ * Create withdrawal request
197
+ *
198
+ * Create a new withdrawal request (requires admin approval)
199
+ */
200
+ async withdrawalsCreateCreate(data) {
201
+ const response = await this.client.request("POST", "/cfg/payments/withdrawals/create/", { body: data });
202
+ return response;
203
+ }
124
204
  };
125
205
 
126
206
  // src/api/generated/ext_payments/ext_payments__payments/models.ts
@@ -799,7 +879,9 @@ var enums_exports = {};
799
879
  __export(enums_exports, {
800
880
  PaymentDetailStatus: () => PaymentDetailStatus,
801
881
  PaymentListStatus: () => PaymentListStatus,
802
- TransactionTransactionType: () => TransactionTransactionType
882
+ TransactionTransactionType: () => TransactionTransactionType,
883
+ WithdrawalDetailStatus: () => WithdrawalDetailStatus,
884
+ WithdrawalListStatus: () => WithdrawalListStatus
803
885
  });
804
886
  var PaymentDetailStatus = /* @__PURE__ */ ((PaymentDetailStatus2) => {
805
887
  PaymentDetailStatus2["PENDING"] = "pending";
@@ -833,6 +915,24 @@ var TransactionTransactionType = /* @__PURE__ */ ((TransactionTransactionType2)
833
915
  TransactionTransactionType2["ADJUSTMENT"] = "adjustment";
834
916
  return TransactionTransactionType2;
835
917
  })(TransactionTransactionType || {});
918
+ var WithdrawalDetailStatus = /* @__PURE__ */ ((WithdrawalDetailStatus2) => {
919
+ WithdrawalDetailStatus2["PENDING"] = "pending";
920
+ WithdrawalDetailStatus2["APPROVED"] = "approved";
921
+ WithdrawalDetailStatus2["PROCESSING"] = "processing";
922
+ WithdrawalDetailStatus2["COMPLETED"] = "completed";
923
+ WithdrawalDetailStatus2["REJECTED"] = "rejected";
924
+ WithdrawalDetailStatus2["CANCELLED"] = "cancelled";
925
+ return WithdrawalDetailStatus2;
926
+ })(WithdrawalDetailStatus || {});
927
+ var WithdrawalListStatus = /* @__PURE__ */ ((WithdrawalListStatus2) => {
928
+ WithdrawalListStatus2["PENDING"] = "pending";
929
+ WithdrawalListStatus2["APPROVED"] = "approved";
930
+ WithdrawalListStatus2["PROCESSING"] = "processing";
931
+ WithdrawalListStatus2["COMPLETED"] = "completed";
932
+ WithdrawalListStatus2["REJECTED"] = "rejected";
933
+ WithdrawalListStatus2["CANCELLED"] = "cancelled";
934
+ return WithdrawalListStatus2;
935
+ })(WithdrawalListStatus || {});
836
936
 
837
937
  // src/api/generated/ext_payments/_utils/schemas/index.ts
838
938
  var schemas_exports = {};
@@ -840,16 +940,24 @@ __export(schemas_exports, {
840
940
  BalanceSchema: () => BalanceSchema,
841
941
  CurrencySchema: () => CurrencySchema,
842
942
  PaginatedPaymentListListSchema: () => PaginatedPaymentListListSchema,
943
+ PaginatedWithdrawalListListSchema: () => PaginatedWithdrawalListListSchema,
944
+ PaymentCreateRequestSchema: () => PaymentCreateRequestSchema,
945
+ PaymentCreateResponseSchema: () => PaymentCreateResponseSchema,
843
946
  PaymentDetailSchema: () => PaymentDetailSchema,
844
947
  PaymentListSchema: () => PaymentListSchema,
845
- TransactionSchema: () => TransactionSchema
948
+ TransactionSchema: () => TransactionSchema,
949
+ WithdrawalCancelResponseSchema: () => WithdrawalCancelResponseSchema,
950
+ WithdrawalCreateRequestSchema: () => WithdrawalCreateRequestSchema,
951
+ WithdrawalCreateResponseSchema: () => WithdrawalCreateResponseSchema,
952
+ WithdrawalDetailSchema: () => WithdrawalDetailSchema,
953
+ WithdrawalListSchema: () => WithdrawalListSchema
846
954
  });
847
955
  var BalanceSchema = zod.z.object({
848
956
  balance_usd: zod.z.string(),
849
957
  balance_display: zod.z.string(),
850
958
  total_deposited: zod.z.string(),
851
959
  total_withdrawn: zod.z.string(),
852
- last_transaction_at: zod.z.iso.datetime().nullable()
960
+ last_transaction_at: zod.z.string().datetime({ offset: true }).nullable()
853
961
  });
854
962
  var CurrencySchema = zod.z.object({
855
963
  code: zod.z.string(),
@@ -871,8 +979,8 @@ var PaymentListSchema = zod.z.object({
871
979
  currency_token: zod.z.string(),
872
980
  status: zod.z.nativeEnum(PaymentListStatus),
873
981
  status_display: zod.z.string(),
874
- created_at: zod.z.iso.datetime(),
875
- completed_at: zod.z.iso.datetime().nullable()
982
+ created_at: zod.z.string().datetime({ offset: true }),
983
+ completed_at: zod.z.string().datetime({ offset: true }).nullable()
876
984
  });
877
985
 
878
986
  // src/api/generated/ext_payments/_utils/schemas/PaginatedPaymentListList.schema.ts
@@ -887,6 +995,36 @@ var PaginatedPaymentListListSchema = zod.z.object({
887
995
  previous_page: zod.z.int().nullable().optional(),
888
996
  results: zod.z.array(PaymentListSchema)
889
997
  });
998
+ var WithdrawalListSchema = zod.z.object({
999
+ 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),
1000
+ internal_withdrawal_id: zod.z.string(),
1001
+ amount_usd: zod.z.string(),
1002
+ final_amount_usd: zod.z.string(),
1003
+ currency_code: zod.z.string(),
1004
+ currency_token: zod.z.string(),
1005
+ status: zod.z.nativeEnum(WithdrawalListStatus),
1006
+ status_display: zod.z.string(),
1007
+ created_at: zod.z.string().datetime({ offset: true }),
1008
+ completed_at: zod.z.string().datetime({ offset: true }).nullable()
1009
+ });
1010
+
1011
+ // src/api/generated/ext_payments/_utils/schemas/PaginatedWithdrawalListList.schema.ts
1012
+ var PaginatedWithdrawalListListSchema = zod.z.object({
1013
+ count: zod.z.int(),
1014
+ page: zod.z.int(),
1015
+ pages: zod.z.int(),
1016
+ page_size: zod.z.int(),
1017
+ has_next: zod.z.boolean(),
1018
+ has_previous: zod.z.boolean(),
1019
+ next_page: zod.z.int().nullable().optional(),
1020
+ previous_page: zod.z.int().nullable().optional(),
1021
+ results: zod.z.array(WithdrawalListSchema)
1022
+ });
1023
+ var PaymentCreateRequestSchema = zod.z.object({
1024
+ amount_usd: zod.z.string(),
1025
+ currency_code: zod.z.string().min(1).max(20),
1026
+ description: zod.z.string().max(500).optional()
1027
+ });
890
1028
  var PaymentDetailSchema = zod.z.object({
891
1029
  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),
892
1030
  internal_payment_id: zod.z.string(),
@@ -906,14 +1044,21 @@ var PaymentDetailSchema = zod.z.object({
906
1044
  transaction_hash: zod.z.string().nullable(),
907
1045
  explorer_link: zod.z.string().nullable(),
908
1046
  confirmations_count: zod.z.int(),
909
- expires_at: zod.z.iso.datetime().nullable(),
910
- completed_at: zod.z.iso.datetime().nullable(),
911
- created_at: zod.z.iso.datetime(),
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 }),
912
1050
  is_completed: zod.z.boolean(),
913
1051
  is_failed: zod.z.boolean(),
914
1052
  is_expired: zod.z.boolean(),
915
1053
  description: zod.z.string()
916
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
+ });
917
1062
  var TransactionSchema = zod.z.object({
918
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),
919
1064
  transaction_type: zod.z.nativeEnum(TransactionTransactionType),
@@ -923,7 +1068,49 @@ var TransactionSchema = zod.z.object({
923
1068
  balance_after: zod.z.string(),
924
1069
  payment_id: zod.z.string().nullable(),
925
1070
  description: zod.z.string(),
926
- created_at: zod.z.iso.datetime()
1071
+ created_at: zod.z.string().datetime({ offset: true })
1072
+ });
1073
+ var WithdrawalDetailSchema = zod.z.object({
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),
1075
+ internal_withdrawal_id: zod.z.string(),
1076
+ amount_usd: zod.z.string(),
1077
+ currency_code: zod.z.string(),
1078
+ currency_name: zod.z.string(),
1079
+ currency_token: zod.z.string(),
1080
+ currency_network: zod.z.string(),
1081
+ wallet_address: zod.z.string(),
1082
+ network_fee_usd: zod.z.string(),
1083
+ service_fee_usd: zod.z.string(),
1084
+ total_fee_usd: zod.z.string(),
1085
+ final_amount_usd: zod.z.string(),
1086
+ crypto_amount: zod.z.string().nullable(),
1087
+ status: zod.z.nativeEnum(WithdrawalDetailStatus),
1088
+ status_display: zod.z.string(),
1089
+ transaction_hash: zod.z.string().nullable(),
1090
+ explorer_link: zod.z.string().nullable(),
1091
+ admin_notes: zod.z.string(),
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()
927
1114
  });
928
1115
 
929
1116
  // src/api/generated/ext_payments/validation-events.ts
@@ -977,12 +1164,18 @@ var fetchers_exports = {};
977
1164
  __export(fetchers_exports, {
978
1165
  createPaymentsPaymentsConfirmCreate: () => createPaymentsPaymentsConfirmCreate,
979
1166
  createPaymentsPaymentsCreateCreate: () => createPaymentsPaymentsCreateCreate,
1167
+ createPaymentsWithdrawalsCancelCreate: () => createPaymentsWithdrawalsCancelCreate,
1168
+ createPaymentsWithdrawalsCreateCreate: () => createPaymentsWithdrawalsCreateCreate,
980
1169
  getPaymentsBalanceRetrieve: () => getPaymentsBalanceRetrieve,
1170
+ getPaymentsCurrenciesEstimateRetrieve: () => getPaymentsCurrenciesEstimateRetrieve,
981
1171
  getPaymentsCurrenciesList: () => getPaymentsCurrenciesList,
1172
+ getPaymentsCurrenciesWithdrawalEstimateRetrieve: () => getPaymentsCurrenciesWithdrawalEstimateRetrieve,
982
1173
  getPaymentsPaymentsList: () => getPaymentsPaymentsList,
983
1174
  getPaymentsPaymentsRetrieve: () => getPaymentsPaymentsRetrieve,
984
1175
  getPaymentsPaymentsStatusRetrieve: () => getPaymentsPaymentsStatusRetrieve,
985
- getPaymentsTransactionsList: () => getPaymentsTransactionsList
1176
+ getPaymentsTransactionsList: () => getPaymentsTransactionsList,
1177
+ getPaymentsWithdrawalsList: () => getPaymentsWithdrawalsList,
1178
+ getPaymentsWithdrawalsRetrieve: () => getPaymentsWithdrawalsRetrieve
986
1179
  });
987
1180
 
988
1181
  // src/api/generated/ext_payments/api-instance.ts
@@ -1087,6 +1280,16 @@ async function getPaymentsCurrenciesList(client) {
1087
1280
  const response = await api.ext_payments_payments.currenciesList();
1088
1281
  return response;
1089
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
+ }
1090
1293
  async function getPaymentsPaymentsList(params, client) {
1091
1294
  const api = client || getAPIInstance();
1092
1295
  const response = await api.ext_payments_payments.paymentsList(params?.page, params?.page_size);
@@ -1255,11 +1458,11 @@ Method: GET`);
1255
1458
  throw error;
1256
1459
  }
1257
1460
  }
1258
- async function createPaymentsPaymentsCreateCreate(client) {
1461
+ async function createPaymentsPaymentsCreateCreate(data, client) {
1259
1462
  const api = client || getAPIInstance();
1260
- const response = await api.ext_payments_payments.paymentsCreateCreate();
1463
+ const response = await api.ext_payments_payments.paymentsCreateCreate(data);
1261
1464
  try {
1262
- return PaymentListSchema.parse(response);
1465
+ return PaymentCreateResponseSchema.parse(response);
1263
1466
  } catch (error) {
1264
1467
  consola.consola.error("\u274C Zod Validation Failed");
1265
1468
  consola.consola.box(`createPaymentsPaymentsCreateCreate
@@ -1302,6 +1505,174 @@ async function getPaymentsTransactionsList(params, client) {
1302
1505
  const response = await api.ext_payments_payments.transactionsList(params?.limit, params?.offset, params?.type);
1303
1506
  return response;
1304
1507
  }
1508
+ async function getPaymentsWithdrawalsList(params, client) {
1509
+ const api = client || getAPIInstance();
1510
+ const response = await api.ext_payments_payments.withdrawalsList(params?.page, params?.page_size);
1511
+ try {
1512
+ return PaginatedWithdrawalListListSchema.parse(response);
1513
+ } catch (error) {
1514
+ consola.consola.error("\u274C Zod Validation Failed");
1515
+ consola.consola.box(`getPaymentsWithdrawalsList
1516
+ Path: /cfg/payments/withdrawals/
1517
+ Method: GET`);
1518
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1519
+ consola.consola.error("Validation Issues:");
1520
+ error.issues.forEach((issue, index) => {
1521
+ consola.consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1522
+ consola.consola.error(` \u251C\u2500 Message: ${issue.message}`);
1523
+ if (issue.expected) consola.consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1524
+ if (issue.received) consola.consola.error(` \u2514\u2500 Received: ${issue.received}`);
1525
+ });
1526
+ }
1527
+ consola.consola.error("Response data:", response);
1528
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1529
+ try {
1530
+ const event = new CustomEvent("zod-validation-error", {
1531
+ detail: {
1532
+ operation: "getPaymentsWithdrawalsList",
1533
+ path: "/cfg/payments/withdrawals/",
1534
+ method: "GET",
1535
+ error,
1536
+ response,
1537
+ timestamp: /* @__PURE__ */ new Date()
1538
+ },
1539
+ bubbles: true,
1540
+ cancelable: false
1541
+ });
1542
+ window.dispatchEvent(event);
1543
+ } catch (eventError) {
1544
+ consola.consola.warn("Failed to dispatch validation error event:", eventError);
1545
+ }
1546
+ }
1547
+ throw error;
1548
+ }
1549
+ }
1550
+ async function getPaymentsWithdrawalsRetrieve(id, client) {
1551
+ const api = client || getAPIInstance();
1552
+ const response = await api.ext_payments_payments.withdrawalsRetrieve(id);
1553
+ try {
1554
+ return WithdrawalDetailSchema.parse(response);
1555
+ } catch (error) {
1556
+ consola.consola.error("\u274C Zod Validation Failed");
1557
+ consola.consola.box(`getPaymentsWithdrawalsRetrieve
1558
+ Path: /cfg/payments/withdrawals/{id}/
1559
+ Method: GET`);
1560
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1561
+ consola.consola.error("Validation Issues:");
1562
+ error.issues.forEach((issue, index) => {
1563
+ consola.consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1564
+ consola.consola.error(` \u251C\u2500 Message: ${issue.message}`);
1565
+ if (issue.expected) consola.consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1566
+ if (issue.received) consola.consola.error(` \u2514\u2500 Received: ${issue.received}`);
1567
+ });
1568
+ }
1569
+ consola.consola.error("Response data:", response);
1570
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1571
+ try {
1572
+ const event = new CustomEvent("zod-validation-error", {
1573
+ detail: {
1574
+ operation: "getPaymentsWithdrawalsRetrieve",
1575
+ path: "/cfg/payments/withdrawals/{id}/",
1576
+ method: "GET",
1577
+ error,
1578
+ response,
1579
+ timestamp: /* @__PURE__ */ new Date()
1580
+ },
1581
+ bubbles: true,
1582
+ cancelable: false
1583
+ });
1584
+ window.dispatchEvent(event);
1585
+ } catch (eventError) {
1586
+ consola.consola.warn("Failed to dispatch validation error event:", eventError);
1587
+ }
1588
+ }
1589
+ throw error;
1590
+ }
1591
+ }
1592
+ async function createPaymentsWithdrawalsCancelCreate(id, client) {
1593
+ const api = client || getAPIInstance();
1594
+ const response = await api.ext_payments_payments.withdrawalsCancelCreate(id);
1595
+ try {
1596
+ return WithdrawalCancelResponseSchema.parse(response);
1597
+ } catch (error) {
1598
+ consola.consola.error("\u274C Zod Validation Failed");
1599
+ consola.consola.box(`createPaymentsWithdrawalsCancelCreate
1600
+ Path: /cfg/payments/withdrawals/{id}/cancel/
1601
+ Method: POST`);
1602
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1603
+ consola.consola.error("Validation Issues:");
1604
+ error.issues.forEach((issue, index) => {
1605
+ consola.consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1606
+ consola.consola.error(` \u251C\u2500 Message: ${issue.message}`);
1607
+ if (issue.expected) consola.consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1608
+ if (issue.received) consola.consola.error(` \u2514\u2500 Received: ${issue.received}`);
1609
+ });
1610
+ }
1611
+ consola.consola.error("Response data:", response);
1612
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1613
+ try {
1614
+ const event = new CustomEvent("zod-validation-error", {
1615
+ detail: {
1616
+ operation: "createPaymentsWithdrawalsCancelCreate",
1617
+ path: "/cfg/payments/withdrawals/{id}/cancel/",
1618
+ method: "POST",
1619
+ error,
1620
+ response,
1621
+ timestamp: /* @__PURE__ */ new Date()
1622
+ },
1623
+ bubbles: true,
1624
+ cancelable: false
1625
+ });
1626
+ window.dispatchEvent(event);
1627
+ } catch (eventError) {
1628
+ consola.consola.warn("Failed to dispatch validation error event:", eventError);
1629
+ }
1630
+ }
1631
+ throw error;
1632
+ }
1633
+ }
1634
+ async function createPaymentsWithdrawalsCreateCreate(data, client) {
1635
+ const api = client || getAPIInstance();
1636
+ const response = await api.ext_payments_payments.withdrawalsCreateCreate(data);
1637
+ try {
1638
+ return WithdrawalCreateResponseSchema.parse(response);
1639
+ } catch (error) {
1640
+ consola.consola.error("\u274C Zod Validation Failed");
1641
+ consola.consola.box(`createPaymentsWithdrawalsCreateCreate
1642
+ Path: /cfg/payments/withdrawals/create/
1643
+ Method: POST`);
1644
+ if (error instanceof Error && "issues" in error && Array.isArray(error.issues)) {
1645
+ consola.consola.error("Validation Issues:");
1646
+ error.issues.forEach((issue, index) => {
1647
+ consola.consola.error(` ${index + 1}. ${issue.path.join(".") || "root"}`);
1648
+ consola.consola.error(` \u251C\u2500 Message: ${issue.message}`);
1649
+ if (issue.expected) consola.consola.error(` \u251C\u2500 Expected: ${issue.expected}`);
1650
+ if (issue.received) consola.consola.error(` \u2514\u2500 Received: ${issue.received}`);
1651
+ });
1652
+ }
1653
+ consola.consola.error("Response data:", response);
1654
+ if (typeof window !== "undefined" && error instanceof Error && "issues" in error) {
1655
+ try {
1656
+ const event = new CustomEvent("zod-validation-error", {
1657
+ detail: {
1658
+ operation: "createPaymentsWithdrawalsCreateCreate",
1659
+ path: "/cfg/payments/withdrawals/create/",
1660
+ method: "POST",
1661
+ error,
1662
+ response,
1663
+ timestamp: /* @__PURE__ */ new Date()
1664
+ },
1665
+ bubbles: true,
1666
+ cancelable: false
1667
+ });
1668
+ window.dispatchEvent(event);
1669
+ } catch (eventError) {
1670
+ consola.consola.warn("Failed to dispatch validation error event:", eventError);
1671
+ }
1672
+ }
1673
+ throw error;
1674
+ }
1675
+ }
1305
1676
 
1306
1677
  // src/api/generated/ext_payments/index.ts
1307
1678
  var TOKEN_KEY = "auth_token";
@@ -1428,6 +1799,8 @@ var API = class {
1428
1799
  return "./schema.json";
1429
1800
  }
1430
1801
  };
1802
+
1803
+ // src/api/index.ts
1431
1804
  api.initializeExtensionAPI(configureAPI);
1432
1805
  var apiPayments = api.createExtensionAPI(API);
1433
1806
  function usePaymentsBalanceRetrieve(client) {
@@ -1448,24 +1821,10 @@ function usePaymentsPaymentsList(params, client) {
1448
1821
  () => getPaymentsPaymentsList(params, client)
1449
1822
  );
1450
1823
  }
1451
- function usePaymentsPaymentsRetrieve(id, client) {
1452
- return useSWR__default.default(
1453
- ["cfg-payments-payment", id],
1454
- () => getPaymentsPaymentsRetrieve(id, client)
1455
- );
1456
- }
1457
- function useCreatePaymentsPaymentsConfirmCreate() {
1458
- const { mutate } = useSWR.useSWRConfig();
1459
- return async (id, client) => {
1460
- const result = await createPaymentsPaymentsConfirmCreate(id, client);
1461
- mutate("cfg-payments-payments-confirm");
1462
- return result;
1463
- };
1464
- }
1465
1824
  function useCreatePaymentsPaymentsCreateCreate() {
1466
1825
  const { mutate } = useSWR.useSWRConfig();
1467
- return async (client) => {
1468
- const result = await createPaymentsPaymentsCreateCreate(client);
1826
+ return async (data, client) => {
1827
+ const result = await createPaymentsPaymentsCreateCreate(data, client);
1469
1828
  mutate("cfg-payments-payments");
1470
1829
  return result;
1471
1830
  };
@@ -1476,287 +1835,1001 @@ function usePaymentsTransactionsList(params, client) {
1476
1835
  () => getPaymentsTransactionsList(params, client)
1477
1836
  );
1478
1837
  }
1479
- var PaymentsContext = react.createContext(void 0);
1480
- function PaymentsProvider({ children }) {
1481
- const {
1482
- data: payments,
1483
- error: paymentsError,
1484
- isLoading: isLoadingPayments,
1485
- mutate: mutatePayments
1486
- } = usePaymentsPaymentsList({ page: 1, page_size: 1 }, apiPayments);
1487
- const refreshPayments = async () => {
1488
- await mutatePayments();
1489
- };
1490
- const createPaymentMutation = useCreatePaymentsPaymentsCreateCreate();
1491
- const confirmPaymentMutation = useCreatePaymentsPaymentsConfirmCreate();
1492
- const getPayment = async (id) => {
1493
- return getPaymentsPaymentsRetrieve(id, apiPayments);
1494
- };
1495
- const createPayment = async () => {
1496
- const result = await createPaymentMutation(apiPayments);
1497
- await refreshPayments();
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");
1498
1849
  return result;
1499
1850
  };
1500
- const confirmPayment = async (id) => {
1501
- const result = await confirmPaymentMutation(id, apiPayments);
1502
- await refreshPayments();
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");
1503
1857
  return result;
1504
1858
  };
1505
- const checkPaymentStatus = async (id) => {
1506
- return getPaymentsPaymentsStatusRetrieve(id, apiPayments);
1507
- };
1508
- const value = {
1509
- payments,
1510
- isLoadingPayments,
1511
- paymentsError,
1512
- refreshPayments,
1513
- getPayment,
1514
- createPayment,
1515
- confirmPayment,
1516
- checkPaymentStatus
1517
- };
1518
- return /* @__PURE__ */ jsxRuntime.jsx(PaymentsContext.Provider, { value, children });
1519
- }
1520
- function usePaymentsContext() {
1521
- const context = react.useContext(PaymentsContext);
1522
- if (!context) {
1523
- throw new Error("usePaymentsContext must be used within PaymentsProvider");
1524
- }
1525
- return context;
1526
1859
  }
1527
- react.createContext(void 0);
1528
- react.createContext(void 0);
1529
- var OverviewContext = react.createContext(void 0);
1530
- function OverviewProvider({ children }) {
1531
- const swrConfig = {
1532
- revalidateOnFocus: false,
1533
- revalidateOnReconnect: false,
1534
- revalidateIfStale: false
1535
- };
1860
+ var WalletContext = react.createContext(void 0);
1861
+ function WalletProvider({ children }) {
1536
1862
  const {
1537
1863
  data: balance,
1538
- error: balanceError,
1539
1864
  isLoading: isLoadingBalance,
1540
1865
  mutate: mutateBalance
1541
1866
  } = usePaymentsBalanceRetrieve(apiPayments);
1542
1867
  const {
1543
- data: payments,
1544
- error: paymentsError,
1868
+ data: paymentsData,
1545
1869
  isLoading: isLoadingPayments,
1546
1870
  mutate: mutatePayments
1547
- } = usePaymentsPaymentsList({}, apiPayments);
1871
+ } = usePaymentsPaymentsList({ page: 1, page_size: 20 }, apiPayments);
1548
1872
  const {
1549
- data: transactions,
1550
- error: transactionsError,
1873
+ data: transactionsData,
1551
1874
  isLoading: isLoadingTransactions,
1552
1875
  mutate: mutateTransactions
1553
- } = usePaymentsTransactionsList({}, apiPayments);
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);
1554
1887
  const createPaymentMutation = useCreatePaymentsPaymentsCreateCreate();
1555
- const isLoadingOverview = isLoadingBalance || isLoadingPayments || isLoadingTransactions;
1556
- const overviewError = balanceError || paymentsError || transactionsError;
1557
- const refreshBalance = async () => {
1558
- await mutateBalance();
1559
- };
1560
- const refreshPayments = async () => {
1561
- await mutatePayments();
1562
- };
1563
- const refreshTransactions = async () => {
1564
- await mutateTransactions();
1565
- };
1566
- const refreshOverview = async () => {
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 () => {
1567
1982
  await Promise.all([
1568
1983
  mutateBalance(),
1569
1984
  mutatePayments(),
1570
- mutateTransactions()
1985
+ mutateWithdrawals(),
1986
+ mutateTransactions(),
1987
+ mutateCurrencies()
1571
1988
  ]);
1572
- };
1573
- const createPayment = async () => {
1574
- const result = await createPaymentMutation(apiPayments);
1575
- await refreshOverview();
1576
- return result;
1577
- };
1989
+ }, [mutateBalance, mutatePayments, mutateWithdrawals, mutateTransactions, mutateCurrencies]);
1990
+ const isLoading = isLoadingBalance || isLoadingPayments || isLoadingWithdrawals || isLoadingTransactions;
1991
+ const isLoadingActivity = isLoadingPayments || isLoadingWithdrawals || isLoadingTransactions;
1578
1992
  const value = {
1579
1993
  balance,
1994
+ balanceAmount,
1580
1995
  isLoadingBalance,
1581
- balanceError,
1582
- refreshBalance,
1583
- payments,
1584
- isLoadingPayments,
1585
- paymentsError,
1586
- refreshPayments,
1587
- transactions,
1588
- isLoadingTransactions,
1589
- transactionsError,
1590
- refreshTransactions,
1591
- createPayment,
1592
- isLoadingOverview,
1593
- overviewError,
1594
- refreshOverview
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
1595
2008
  };
1596
- return /* @__PURE__ */ jsxRuntime.jsx(useSWR.SWRConfig, { value: swrConfig, children: /* @__PURE__ */ jsxRuntime.jsx(OverviewContext.Provider, { value, children }) });
2009
+ return /* @__PURE__ */ jsxRuntime.jsx(WalletContext.Provider, { value, children });
1597
2010
  }
1598
- function useOverviewContext() {
1599
- const context = react.useContext(OverviewContext);
2011
+ function useWallet() {
2012
+ const context = react.useContext(WalletContext);
1600
2013
  if (!context) {
1601
- throw new Error("useOverviewContext must be used within OverviewProvider");
2014
+ throw new Error("useWallet must be used within WalletProvider");
1602
2015
  }
1603
2016
  return context;
1604
2017
  }
1605
- var RootPaymentsContext = react.createContext(void 0);
1606
- function RootPaymentsProvider({ children }) {
1607
- const {
1608
- data: currencies,
1609
- error: currenciesError,
1610
- isLoading: isLoadingCurrencies,
1611
- mutate: mutateCurrencies
1612
- } = usePaymentsCurrenciesList(apiPayments);
1613
- const refreshCurrencies = async () => {
1614
- await mutateCurrencies();
1615
- };
1616
- const value = {
1617
- currencies,
1618
- isLoadingCurrencies,
1619
- currenciesError,
1620
- refreshCurrencies
1621
- };
1622
- return /* @__PURE__ */ jsxRuntime.jsx(RootPaymentsContext.Provider, { value, children });
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
+ }
1623
2039
  }
1624
- function useRootPaymentsContext() {
1625
- const context = react.useContext(RootPaymentsContext);
1626
- if (!context) {
1627
- throw new Error("useRootPaymentsContext must be used within RootPaymentsProvider");
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";
1628
2054
  }
1629
- return context;
2055
+ }
2056
+ function BalanceHero({ onAddFunds, onWithdraw, className }) {
2057
+ const { balance, balanceAmount, isLoadingBalance, refreshWallet } = useWallet();
2058
+ const formattedBalance = new Intl.NumberFormat("en-US", {
2059
+ style: "currency",
2060
+ currency: "USD",
2061
+ minimumFractionDigits: 2,
2062
+ maximumFractionDigits: 2
2063
+ }).format(balanceAmount);
2064
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("flex flex-col items-center py-16 px-4", className), children: [
2065
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center mb-6", children: isLoadingBalance ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2066
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-12 w-48 mx-auto mb-2" }),
2067
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-4 w-24 mx-auto" })
2068
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2069
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-5xl font-bold tracking-tight tabular-nums", children: formattedBalance }),
2070
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mt-1", children: "Available Balance" })
2071
+ ] }) }),
2072
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
2073
+ /* @__PURE__ */ jsxRuntime.jsxs(
2074
+ uiCore.Button,
2075
+ {
2076
+ size: "lg",
2077
+ onClick: onAddFunds,
2078
+ className: "rounded-full px-6",
2079
+ children: [
2080
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-5 w-5 mr-2" }),
2081
+ "Add Funds"
2082
+ ]
2083
+ }
2084
+ ),
2085
+ /* @__PURE__ */ jsxRuntime.jsxs(
2086
+ uiCore.Button,
2087
+ {
2088
+ size: "lg",
2089
+ variant: "outline",
2090
+ onClick: onWithdraw,
2091
+ className: "rounded-full px-6",
2092
+ children: [
2093
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { className: "h-5 w-5 mr-2" }),
2094
+ "Withdraw"
2095
+ ]
2096
+ }
2097
+ ),
2098
+ /* @__PURE__ */ jsxRuntime.jsx(
2099
+ uiCore.Button,
2100
+ {
2101
+ size: "icon",
2102
+ variant: "ghost",
2103
+ onClick: () => refreshWallet(),
2104
+ className: "rounded-full",
2105
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-4 w-4" })
2106
+ }
2107
+ )
2108
+ ] }),
2109
+ balance && !isLoadingBalance && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-6 mt-6 text-sm text-muted-foreground", children: [
2110
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
2111
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "block font-medium text-foreground", children: [
2112
+ "$",
2113
+ parseFloat(balance.total_deposited || "0").toFixed(2)
2114
+ ] }),
2115
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Total Deposited" })
2116
+ ] }),
2117
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 w-px bg-border" }),
2118
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
2119
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "block font-medium text-foreground", children: [
2120
+ "$",
2121
+ parseFloat(balance.total_withdrawn || "0").toFixed(2)
2122
+ ] }),
2123
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Total Withdrawn" })
2124
+ ] })
2125
+ ] })
2126
+ ] });
2127
+ }
2128
+ var statusConfig = {
2129
+ pending: {
2130
+ icon: lucideReact.Clock,
2131
+ color: "text-yellow-500",
2132
+ bg: "bg-yellow-500/10"
2133
+ },
2134
+ confirming: {
2135
+ icon: lucideReact.Loader2,
2136
+ color: "text-blue-500",
2137
+ bg: "bg-blue-500/10",
2138
+ animate: true
2139
+ },
2140
+ completed: {
2141
+ icon: lucideReact.CheckCircle2,
2142
+ color: "text-green-500",
2143
+ bg: "bg-green-500/10"
2144
+ },
2145
+ failed: {
2146
+ icon: lucideReact.XCircle,
2147
+ color: "text-red-500",
2148
+ bg: "bg-red-500/10"
2149
+ },
2150
+ expired: {
2151
+ icon: lucideReact.AlertCircle,
2152
+ color: "text-muted-foreground",
2153
+ bg: "bg-muted"
2154
+ }
2155
+ };
2156
+ function ActivityItem({ item, onClick }) {
2157
+ const config = statusConfig[item.status];
2158
+ const StatusIcon = config.icon;
2159
+ const isPositive = item.type === "payment" || item.type === "deposit";
2160
+ const DirectionIcon = isPositive ? lucideReact.ArrowDownLeft : lucideReact.ArrowUpRight;
2161
+ const relativeTime = moment3__default.default(item.createdAt).fromNow();
2162
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2163
+ "button",
2164
+ {
2165
+ onClick,
2166
+ className: lib.cn(
2167
+ "w-full flex items-center gap-4 p-4 rounded-xl",
2168
+ "cursor-pointer",
2169
+ "hover:bg-accent active:bg-accent/80 transition-colors",
2170
+ "text-left"
2171
+ ),
2172
+ children: [
2173
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: lib.cn(
2174
+ "flex items-center justify-center w-10 h-10 rounded-full",
2175
+ isPositive ? "bg-green-500/10" : "bg-red-500/10"
2176
+ ), children: item.currency ? /* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: item.currency, size: 24 }) : /* @__PURE__ */ jsxRuntime.jsx(DirectionIcon, { className: lib.cn(
2177
+ "h-5 w-5",
2178
+ isPositive ? "text-green-500" : "text-red-500"
2179
+ ) }) }),
2180
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
2181
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium truncate", children: item.description }) }),
2182
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
2183
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: relativeTime }),
2184
+ item.status !== "completed" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2185
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\xB7" }),
2186
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: lib.cn("flex items-center gap-1", config.color), children: [
2187
+ /* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { className: lib.cn("h-3 w-3", config.animate && "animate-spin") }),
2188
+ item.statusDisplay
2189
+ ] })
2190
+ ] })
2191
+ ] })
2192
+ ] }),
2193
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
2194
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: lib.cn(
2195
+ "font-semibold tabular-nums",
2196
+ isPositive ? "text-green-600 dark:text-green-400" : "text-foreground"
2197
+ ), children: item.amountDisplay }),
2198
+ item.status === "completed" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-4 w-4 text-green-500 ml-2 inline-block" })
2199
+ ] })
2200
+ ]
2201
+ }
2202
+ );
2203
+ }
2204
+ function ActivityList({
2205
+ onItemClick,
2206
+ onViewAll,
2207
+ limit = 10,
2208
+ className
2209
+ }) {
2210
+ const { activity, isLoadingActivity, hasMoreActivity } = useWallet();
2211
+ const displayedActivity = limit ? activity.slice(0, limit) : activity;
2212
+ if (isLoadingActivity) {
2213
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("space-y-2", className), children: [
2214
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-5 w-32" }) }),
2215
+ [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 p-4", children: [
2216
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-10 w-10 rounded-full" }),
2217
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-2", children: [
2218
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-4 w-32" }),
2219
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-3 w-24" })
2220
+ ] }),
2221
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-5 w-16" })
2222
+ ] }, i))
2223
+ ] });
2224
+ }
2225
+ if (activity.length === 0) {
2226
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("text-center py-12", className), children: [
2227
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center justify-center w-16 h-16 rounded-full bg-muted mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-8 w-8 text-muted-foreground" }) }),
2228
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-semibold mb-1", children: "No Activity Yet" }),
2229
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Your transactions will appear here" })
2230
+ ] });
2231
+ }
2232
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("pt-6", className), children: [
2233
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-2", children: [
2234
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "font-semibold text-lg", children: "Recent Activity" }),
2235
+ hasMoreActivity && onViewAll && /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Button, { variant: "ghost", size: "sm", onClick: onViewAll, className: "text-primary", children: [
2236
+ "View All",
2237
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4 ml-1" })
2238
+ ] })
2239
+ ] }),
2240
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border/50", children: displayedActivity.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
2241
+ ActivityItem,
2242
+ {
2243
+ item,
2244
+ onClick: () => onItemClick?.(item)
2245
+ },
2246
+ item.id
2247
+ )) })
2248
+ ] });
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;
1630
2452
  }
1631
2453
  var isDevelopment = process.env.NODE_ENV === "development";
1632
- var logger = consola.createConsola({
2454
+ consola.createConsola({
1633
2455
  level: isDevelopment ? 4 : 1
1634
2456
  }).withTag("ext-payments");
1635
- var paymentsLogger = logger;
1636
-
1637
- // src/layouts/PaymentsLayout/events.ts
1638
- var PAYMENT_EVENTS = {
1639
- OPEN_CREATE_PAYMENT_DIALOG: "payments:open-create-payment",
1640
- OPEN_PAYMENT_DETAILS_DIALOG: "payments:open-payment-details",
1641
- CLOSE_DIALOG: "payments:close-dialog"
1642
- };
1643
- var openCreatePaymentDialog = () => {
1644
- window.dispatchEvent(new Event(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG));
1645
- };
1646
- var openPaymentDetailsDialog = (id) => {
1647
- window.dispatchEvent(
1648
- new CustomEvent(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, {
1649
- detail: { id }
1650
- })
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
+ }
1651
2483
  );
1652
- };
1653
- var closePaymentsDialog = () => {
1654
- window.dispatchEvent(new Event(PAYMENT_EVENTS.CLOSE_DIALOG));
1655
- };
1656
- var PaymentCreateSchema = zod.z.object({
1657
- amount_usd: zod.z.number().min(0.01, "Amount must be at least $0.01"),
1658
- currency_code: zod.z.string().min(1, "Please select a currency")
2484
+ }
2485
+ var AddFundsSchema = zod.z.object({
2486
+ amount: zod.z.number().min(1, "Minimum $1"),
2487
+ currency: zod.z.string().min(1, "Select a currency")
1659
2488
  });
1660
- var CreatePaymentDialog = () => {
1661
- const [open, setOpen] = react.useState(false);
2489
+ var STORAGE_KEY = "payments:addFunds";
2490
+ function AddFundsSheet({ open, onOpenChange, onSuccess }) {
2491
+ const { currencies, isLoadingCurrencies, addFunds } = useWallet();
1662
2492
  const [isSubmitting, setIsSubmitting] = react.useState(false);
1663
- const { createPayment } = usePaymentsContext();
1664
- const { currencies, isLoadingCurrencies } = useRootPaymentsContext();
2493
+ const [error, setError] = react.useState(null);
2494
+ const [saved, setSaved] = uiCore.useLocalStorage(STORAGE_KEY, {
2495
+ currency: "",
2496
+ amount: 100
2497
+ });
1665
2498
  const form = reactHookForm.useForm({
1666
- resolver: zod$1.zodResolver(PaymentCreateSchema),
2499
+ resolver: zod$1.zodResolver(AddFundsSchema),
1667
2500
  defaultValues: {
1668
- amount_usd: 10,
1669
- currency_code: "USDT"
2501
+ amount: saved.amount,
2502
+ currency: saved.currency
1670
2503
  }
1671
2504
  });
1672
- const currenciesList = react.useMemo(() => {
1673
- const data = currencies?.currencies || currencies?.results || currencies || [];
1674
- return Array.isArray(data) ? data : [];
1675
- }, [currencies]);
1676
- const currencyOptions = react.useMemo(() => {
1677
- return currenciesList.filter((curr) => curr.is_enabled !== false).map((curr) => ({
1678
- code: curr.code || curr.currency_code || curr.symbol,
1679
- name: curr.name || curr.code || curr.currency_code,
1680
- usd_rate: curr.usd_rate || curr.rate || 1,
1681
- network: curr.network || null
1682
- }));
1683
- }, [currenciesList]);
1684
- const calculateCryptoAmount = react.useMemo(() => {
1685
- const amountUsd = form.watch("amount_usd");
1686
- const currencyCode = form.watch("currency_code");
1687
- const currency = currencyOptions.find((c) => c.code === currencyCode);
1688
- if (!currency || !currency.usd_rate || !amountUsd) {
1689
- return null;
1690
- }
1691
- const cryptoAmount = amountUsd / currency.usd_rate;
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;
1692
2529
  return {
1693
- amount: cryptoAmount,
1694
- currency: currency.code,
1695
- rate: currency.usd_rate,
1696
- network: currency.network
1697
- };
1698
- }, [form.watch("amount_usd"), form.watch("currency_code"), currencyOptions]);
1699
- react.useEffect(() => {
1700
- const handleOpen = () => setOpen(true);
1701
- const handleClose2 = () => setOpen(false);
1702
- window.addEventListener(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG, handleOpen);
1703
- window.addEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
1704
- return () => {
1705
- window.removeEventListener(PAYMENT_EVENTS.OPEN_CREATE_PAYMENT_DIALOG, handleOpen);
1706
- window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
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
1707
2541
  };
1708
- }, []);
1709
- const handleClose = () => {
1710
- setOpen(false);
1711
- form.reset();
1712
- };
1713
- react.useEffect(() => {
1714
- if (currencyOptions.length > 0 && !form.getValues("currency_code")) {
1715
- form.setValue("currency_code", currencyOptions[0].code);
2542
+ }, [selectedCurrency, estimate, watchedAmount]);
2543
+ const handleSubmit = react.useCallback(async (data) => {
2544
+ try {
2545
+ setIsSubmitting(true);
2546
+ setError(null);
2547
+ const result = await addFunds({
2548
+ amount_usd: String(data.amount),
2549
+ currency_code: data.currency
2550
+ });
2551
+ form.reset();
2552
+ onOpenChange(false);
2553
+ onSuccess?.(result);
2554
+ } catch (err) {
2555
+ setError(extractErrorMessage(err, "Failed to create payment"));
2556
+ } finally {
2557
+ setIsSubmitting(false);
2558
+ }
2559
+ }, [addFunds, form, onOpenChange, onSuccess]);
2560
+ const handleOpenChange = react.useCallback((open2) => {
2561
+ if (open2) {
2562
+ form.reset({
2563
+ amount: saved.amount,
2564
+ currency: saved.currency
2565
+ });
2566
+ } else {
2567
+ setError(null);
1716
2568
  }
1717
- }, [currencyOptions, form]);
1718
- const handleSubmit = async (data) => {
2569
+ onOpenChange(open2);
2570
+ }, [form, onOpenChange, saved]);
2571
+ return /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheet, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetContent, { className: "sm:max-w-md", children: [
2572
+ /* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetHeader, { children: [
2573
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetTitle, { children: "Add Funds" }),
2574
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetDescription, { children: "Add funds to your wallet using cryptocurrency" })
2575
+ ] }),
2576
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.Form, { ...form, children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-6 p-4 sm:p-0 sm:mt-4", children: [
2577
+ /* @__PURE__ */ jsxRuntime.jsx(
2578
+ uiCore.FormField,
2579
+ {
2580
+ control: form.control,
2581
+ name: "amount",
2582
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(uiCore.FormItem, { children: [
2583
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormLabel, { children: "Amount (USD)" }),
2584
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
2585
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-muted-foreground text-lg", children: "$" }),
2586
+ /* @__PURE__ */ jsxRuntime.jsx(
2587
+ uiCore.Input,
2588
+ {
2589
+ type: "number",
2590
+ step: "0.01",
2591
+ min: "1",
2592
+ placeholder: "100",
2593
+ className: "pl-8 text-2xl h-14 font-semibold",
2594
+ ...field,
2595
+ onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
2596
+ }
2597
+ )
2598
+ ] }) }),
2599
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormMessage, {})
2600
+ ] })
2601
+ }
2602
+ ),
2603
+ /* @__PURE__ */ jsxRuntime.jsx(
2604
+ uiCore.FormField,
2605
+ {
2606
+ control: form.control,
2607
+ name: "currency",
2608
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(uiCore.FormItem, { children: [
2609
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormLabel, { children: "Pay with" }),
2610
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
2611
+ CurrencyCombobox,
2612
+ {
2613
+ options: currencyOptions,
2614
+ value: field.value,
2615
+ onChange: field.onChange,
2616
+ disabled: isLoadingCurrencies
2617
+ }
2618
+ ) }),
2619
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormMessage, {})
2620
+ ] })
2621
+ }
2622
+ ),
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)
2632
+ ] })
2633
+ ] }),
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: [
2646
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Rate" }),
2647
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2648
+ "1 ",
2649
+ displayData.token,
2650
+ " = $",
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
+ ] })
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
2681
+ ] })
2682
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center text-sm text-muted-foreground py-2", children: "Enter amount to see conversion" }) }),
2683
+ error && /* @__PURE__ */ jsxRuntime.jsx(uiCore.Alert, { variant: "destructive", children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.AlertDescription, { children: error }) }),
2684
+ /* @__PURE__ */ jsxRuntime.jsx(
2685
+ uiCore.Button,
2686
+ {
2687
+ type: "submit",
2688
+ size: "lg",
2689
+ className: "w-full h-14 text-lg rounded-xl",
2690
+ disabled: isSubmitting || currencyOptions.length === 0 || isLoadingEstimate || displayData?.belowMinimum,
2691
+ children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2692
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-5 w-5 mr-2 animate-spin" }),
2693
+ "Creating..."
2694
+ ] }) : "Continue"
2695
+ }
2696
+ )
2697
+ ] }) })
2698
+ ] }) });
2699
+ }
2700
+ var WithdrawSchema = zod.z.object({
2701
+ amount: zod.z.number().min(10, "Minimum $10"),
2702
+ currency: zod.z.string().min(1, "Select a currency"),
2703
+ wallet_address: zod.z.string().min(26, "Invalid wallet address")
2704
+ });
2705
+ var STORAGE_KEY2 = "payments:withdraw";
2706
+ function WithdrawSheet({ open, onOpenChange, onSuccess }) {
2707
+ const { currencies, isLoadingCurrencies, withdraw, balanceAmount } = useWallet();
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
+ });
2714
+ const form = reactHookForm.useForm({
2715
+ resolver: zod$1.zodResolver(WithdrawSchema),
2716
+ defaultValues: {
2717
+ amount: 10,
2718
+ currency: saved.currency,
2719
+ wallet_address: saved.wallet
2720
+ }
2721
+ });
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;
2744
+ return {
2745
+ token: selectedCurrency.token,
2746
+ cryptoAmount: formatCryptoAmount(estimate.estimatedAmount, estimate.isStablecoin)
2747
+ };
2748
+ }, [selectedCurrency, estimate]);
2749
+ const insufficientBalance = amount > balanceAmount;
2750
+ const handleSubmit = react.useCallback(async (data) => {
1719
2751
  try {
1720
2752
  setIsSubmitting(true);
1721
- const result = await createPayment();
1722
- handleClose();
1723
- closePaymentsDialog();
1724
- const paymentData = result;
1725
- const paymentId = paymentData?.payment?.id || paymentData?.id;
1726
- if (paymentId) {
1727
- openPaymentDetailsDialog(String(paymentId));
1728
- }
1729
- } catch (error) {
1730
- paymentsLogger.error("Failed to create payment:", error);
2753
+ setError(null);
2754
+ const result = await withdraw({
2755
+ amount_usd: String(data.amount),
2756
+ currency_code: data.currency,
2757
+ wallet_address: data.wallet_address
2758
+ });
2759
+ form.reset();
2760
+ onOpenChange(false);
2761
+ onSuccess?.(result);
2762
+ } catch (err) {
2763
+ setError(extractErrorMessage(err, "Failed to create withdrawal request"));
1731
2764
  } finally {
1732
2765
  setIsSubmitting(false);
1733
2766
  }
1734
- };
1735
- return /* @__PURE__ */ jsxRuntime.jsx(uiCore.Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.DialogContent, { className: "sm:max-w-md", children: [
1736
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.DialogHeader, { children: [
1737
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.DialogTitle, { children: "Create Payment" }),
1738
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.DialogDescription, { children: "Create a new payment to add funds to your account." })
2767
+ }, [withdraw, form, onOpenChange, onSuccess]);
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 {
2776
+ setError(null);
2777
+ }
2778
+ onOpenChange(open2);
2779
+ }, [form, onOpenChange, saved]);
2780
+ return /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheet, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetContent, { className: "sm:max-w-md", children: [
2781
+ /* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetHeader, { children: [
2782
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetTitle, { children: "Withdraw" }),
2783
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetDescription, { children: "Withdraw funds to your cryptocurrency wallet" })
1739
2784
  ] }),
1740
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Form, { ...form, children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-4", children: [
2785
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.Form, { ...form, children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: form.handleSubmit(handleSubmit), className: "space-y-6 p-4 sm:p-0 sm:mt-4", children: [
1741
2786
  /* @__PURE__ */ jsxRuntime.jsx(
1742
2787
  uiCore.FormField,
1743
2788
  {
1744
2789
  control: form.control,
1745
- name: "amount_usd",
2790
+ name: "amount",
1746
2791
  render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(uiCore.FormItem, { children: [
1747
2792
  /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormLabel, { children: "Amount (USD)" }),
2793
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
2794
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-muted-foreground text-lg", children: "$" }),
2795
+ /* @__PURE__ */ jsxRuntime.jsx(
2796
+ uiCore.Input,
2797
+ {
2798
+ type: "number",
2799
+ step: "0.01",
2800
+ min: "10",
2801
+ placeholder: "10",
2802
+ className: "pl-8 text-2xl h-14 font-semibold",
2803
+ ...field,
2804
+ onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
2805
+ }
2806
+ )
2807
+ ] }) }),
2808
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormMessage, {}),
2809
+ insufficientBalance && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-destructive mt-1", children: [
2810
+ "Insufficient balance (Available: $",
2811
+ formatUsdAmount(balanceAmount),
2812
+ ")"
2813
+ ] })
2814
+ ] })
2815
+ }
2816
+ ),
2817
+ /* @__PURE__ */ jsxRuntime.jsx(
2818
+ uiCore.FormField,
2819
+ {
2820
+ control: form.control,
2821
+ name: "currency",
2822
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(uiCore.FormItem, { children: [
2823
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormLabel, { children: "Withdraw as" }),
1748
2824
  /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
1749
- uiCore.Input,
2825
+ CurrencyCombobox,
1750
2826
  {
1751
- type: "number",
1752
- step: "0.01",
1753
- min: "0.01",
1754
- placeholder: "10.00",
1755
- ...field,
1756
- onChange: (e) => field.onChange(parseFloat(e.target.value) || 0)
2827
+ options: currencyOptions,
2828
+ value: field.value,
2829
+ onChange: field.onChange,
2830
+ disabled: isLoadingCurrencies
1757
2831
  }
1758
2832
  ) }),
1759
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormDescription, { children: "The amount you want to pay in USD." }),
1760
2833
  /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormMessage, {})
1761
2834
  ] })
1762
2835
  }
@@ -1765,122 +2838,366 @@ var CreatePaymentDialog = () => {
1765
2838
  uiCore.FormField,
1766
2839
  {
1767
2840
  control: form.control,
1768
- name: "currency_code",
2841
+ name: "wallet_address",
1769
2842
  render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs(uiCore.FormItem, { children: [
1770
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormLabel, { children: "Currency" }),
1771
- /* @__PURE__ */ jsxRuntime.jsxs(
1772
- uiCore.Select,
2843
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormLabel, { children: "Wallet Address" }),
2844
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
2845
+ uiCore.Input,
1773
2846
  {
1774
- onValueChange: field.onChange,
1775
- defaultValue: field.value,
1776
- disabled: isLoadingCurrencies,
1777
- children: [
1778
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectValue, { placeholder: "Select currency..." }) }) }),
1779
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectContent, { children: currencyOptions.map((curr) => /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectItem, { value: curr.code, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1780
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: curr.code, size: 16 }),
1781
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: curr.code }),
1782
- curr.network && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
1783
- "(",
1784
- curr.network,
1785
- ")"
1786
- ] })
1787
- ] }) }, curr.code)) })
1788
- ]
2847
+ placeholder: "Enter your wallet address",
2848
+ className: "font-mono text-sm",
2849
+ ...field
1789
2850
  }
1790
- ),
1791
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormDescription, { children: "The cryptocurrency to use for payment." }),
2851
+ ) }),
1792
2852
  /* @__PURE__ */ jsxRuntime.jsx(uiCore.FormMessage, {})
1793
2853
  ] })
1794
2854
  }
1795
2855
  ),
1796
- calculateCryptoAmount && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm bg-muted p-4 space-y-3", children: [
1797
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
1798
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "You will send" }),
1799
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1800
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: calculateCryptoAmount.currency, size: 16 }),
1801
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono font-semibold", children: [
1802
- calculateCryptoAmount.amount.toFixed(8),
2856
+ amount >= 10 && selectedCurrency && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted rounded-xl p-4 space-y-2", children: [
2857
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
2858
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Amount" }),
2859
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2860
+ "$",
2861
+ formatUsdAmount(amount)
2862
+ ] })
2863
+ ] }),
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
+ "%)"
2873
+ ] }),
2874
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-destructive", children: [
2875
+ "-$",
2876
+ formatUsdAmount(estimate.serviceFeeUsd)
2877
+ ] })
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
2904
+ ] }),
2905
+ /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Alert, { children: [
2906
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-4 w-4" }),
2907
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.AlertDescription, { children: "Withdrawal requests require admin approval. Processing may take 24-48 hours." })
2908
+ ] }),
2909
+ error && /* @__PURE__ */ jsxRuntime.jsx(uiCore.Alert, { variant: "destructive", children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.AlertDescription, { children: error }) }),
2910
+ /* @__PURE__ */ jsxRuntime.jsx(
2911
+ uiCore.Button,
2912
+ {
2913
+ type: "submit",
2914
+ size: "lg",
2915
+ className: "w-full h-14 text-lg rounded-xl",
2916
+ disabled: isSubmitting || currencyOptions.length === 0 || insufficientBalance || !estimate || estimate.amountToReceive <= 0 || isLoadingEstimate,
2917
+ children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2918
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-5 w-5 mr-2 animate-spin" }),
2919
+ "Submitting..."
2920
+ ] }) : "Request Withdrawal"
2921
+ }
2922
+ )
2923
+ ] }) })
2924
+ ] }) });
2925
+ }
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,
1803
3068
  " ",
1804
- calculateCryptoAmount.currency
3069
+ withdrawal.currency_token
1805
3070
  ] })
1806
3071
  ] })
1807
3072
  ] }),
1808
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
1809
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "You will receive" }),
1810
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-lg font-bold", children: [
1811
- "$",
1812
- form.watch("amount_usd")?.toFixed(2),
1813
- " USD"
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" })
1814
3078
  ] })
1815
3079
  ] }),
1816
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-xs", children: [
1817
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Rate" }),
1818
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
1819
- "1 ",
1820
- calculateCryptoAmount.currency,
1821
- " = $",
1822
- calculateCryptoAmount.rate?.toFixed(2)
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" })
1823
3085
  ] })
1824
3086
  ] }),
1825
- calculateCryptoAmount.network && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t pt-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
1826
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Network" }),
1827
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: calculateCryptoAmount.network })
1828
- ] }) })
1829
- ] }),
1830
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.DialogFooter, { children: [
1831
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Button, { type: "button", variant: "outline", onClick: handleClose, disabled: isSubmitting, children: "Cancel" }),
1832
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Button, { type: "submit", disabled: isSubmitting || currencyOptions.length === 0, children: isSubmitting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1833
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-4 w-4 mr-2 animate-spin" }),
1834
- "Creating..."
1835
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1836
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4 mr-2" }),
1837
- "Create Payment"
1838
- ] }) })
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
+ )
1839
3145
  ] })
1840
- ] }) })
3146
+ ] })
1841
3147
  ] }) });
3148
+ }
3149
+ var statusConfig3 = {
3150
+ pending: {
3151
+ icon: lucideReact.Clock,
3152
+ color: "text-yellow-500",
3153
+ bg: "bg-yellow-500/10",
3154
+ label: "Waiting for payment"
3155
+ },
3156
+ confirming: {
3157
+ icon: lucideReact.RefreshCw,
3158
+ color: "text-blue-500",
3159
+ bg: "bg-blue-500/10",
3160
+ label: "Confirming",
3161
+ animate: true
3162
+ },
3163
+ completed: {
3164
+ icon: lucideReact.CheckCircle2,
3165
+ color: "text-green-500",
3166
+ bg: "bg-green-500/10",
3167
+ label: "Completed"
3168
+ },
3169
+ failed: {
3170
+ icon: lucideReact.XCircle,
3171
+ color: "text-red-500",
3172
+ bg: "bg-red-500/10",
3173
+ label: "Failed"
3174
+ },
3175
+ expired: {
3176
+ icon: lucideReact.AlertCircle,
3177
+ color: "text-muted-foreground",
3178
+ bg: "bg-muted",
3179
+ label: "Expired"
3180
+ }
1842
3181
  };
1843
- var PaymentDetailsDialog = () => {
1844
- const [open, setOpen] = react.useState(false);
1845
- const [paymentId, setPaymentId] = react.useState(null);
3182
+ function PaymentSheet({ paymentId, open, onOpenChange, onCreateNew }) {
3183
+ const { getPaymentDetails } = useWallet();
1846
3184
  const [timeLeft, setTimeLeft] = react.useState("");
1847
- const shouldFetch = open && !!paymentId;
1848
- const { data: payment, isLoading, error, mutate } = usePaymentsPaymentsRetrieve(
1849
- shouldFetch ? paymentId : "",
1850
- apiPayments
3185
+ const { data: payment, isLoading, error, mutate } = useSWR__default.default(
3186
+ open && paymentId ? ["payment-details", paymentId] : null,
3187
+ () => getPaymentDetails(paymentId),
3188
+ { refreshInterval: 1e4 }
1851
3189
  );
1852
- react.useEffect(() => {
1853
- const handleOpen = (event) => {
1854
- const customEvent = event;
1855
- setPaymentId(customEvent.detail.id);
1856
- setOpen(true);
1857
- };
1858
- const handleClose2 = () => {
1859
- setOpen(false);
1860
- setPaymentId(null);
1861
- };
1862
- window.addEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
1863
- window.addEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
1864
- return () => {
1865
- window.removeEventListener(PAYMENT_EVENTS.OPEN_PAYMENT_DETAILS_DIALOG, handleOpen);
1866
- window.removeEventListener(PAYMENT_EVENTS.CLOSE_DIALOG, handleClose2);
1867
- };
1868
- }, []);
1869
- const handleClose = () => {
1870
- setOpen(false);
1871
- setPaymentId(null);
1872
- };
1873
3190
  react.useEffect(() => {
1874
3191
  if (!payment?.expires_at) return;
1875
3192
  const updateTimeLeft = () => {
1876
- const now = moment__default.default();
1877
- const expires = moment__default.default.utc(payment.expires_at);
3193
+ const now = moment3__default.default();
3194
+ const expires = moment3__default.default.utc(payment.expires_at);
1878
3195
  const diff = expires.diff(now);
1879
3196
  if (diff <= 0) {
1880
3197
  setTimeLeft("Expired");
1881
3198
  return;
1882
3199
  }
1883
- const duration = moment__default.default.duration(diff);
3200
+ const duration = moment3__default.default.duration(diff);
1884
3201
  const hours = Math.floor(duration.asHours());
1885
3202
  const minutes = duration.minutes();
1886
3203
  const seconds = duration.seconds();
@@ -1890,713 +3207,245 @@ var PaymentDetailsDialog = () => {
1890
3207
  const interval = setInterval(updateTimeLeft, 1e3);
1891
3208
  return () => clearInterval(interval);
1892
3209
  }, [payment?.expires_at]);
1893
- const getStatusInfo = () => {
1894
- switch (payment?.status?.toLowerCase()) {
1895
- case "pending":
1896
- return { icon: lucideReact.Clock, color: "text-yellow-500", bg: "bg-yellow-500/10" };
1897
- case "completed":
1898
- case "success":
1899
- return { icon: lucideReact.CheckCircle2, color: "text-green-500", bg: "bg-green-500/10" };
1900
- case "failed":
1901
- case "error":
1902
- return { icon: lucideReact.XCircle, color: "text-red-500", bg: "bg-red-500/10" };
1903
- case "expired":
1904
- return { icon: lucideReact.AlertCircle, color: "text-gray-500", bg: "bg-gray-500/10" };
1905
- case "confirming":
1906
- return { icon: lucideReact.RefreshCw, color: "text-blue-500", bg: "bg-blue-500/10" };
1907
- default:
1908
- return { icon: lucideReact.Clock, color: "text-gray-500", bg: "bg-gray-500/10" };
1909
- }
1910
- };
1911
- if (!open) return null;
1912
- if (isLoading) {
1913
- return /* @__PURE__ */ jsxRuntime.jsx(uiCore.Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.DialogContent, { className: "sm:max-w-lg", children: [
1914
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.DialogHeader, { children: [
1915
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.DialogTitle, { children: "Payment Details" }),
1916
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.DialogDescription, { children: "Loading payment information..." })
1917
- ] }),
1918
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-8 w-8 animate-spin text-muted-foreground" }) })
1919
- ] }) });
1920
- }
1921
- if (shouldFetch && !isLoading && (error || !payment)) {
1922
- return /* @__PURE__ */ jsxRuntime.jsx(uiCore.Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.DialogContent, { className: "sm:max-w-lg", children: [
1923
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.DialogHeader, { children: [
1924
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.DialogTitle, { children: "Payment Details" }),
1925
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.DialogDescription, { children: "Failed to load payment information" })
3210
+ const displayData = react.useMemo(() => {
3211
+ const s = payment?.status?.toLowerCase();
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;
3258
+ const StatusIcon = config.icon;
3259
+ return /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheet, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetContent, { className: "sm:max-w-lg", children: [
3260
+ /* @__PURE__ */ jsxRuntime.jsxs(uiCore.ResponsiveSheetHeader, { children: [
3261
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetTitle, { children: "Payment Details" }),
3262
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.ResponsiveSheetDescription, { children: description })
3263
+ ] }),
3264
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 sm:p-0 sm:mt-4 overflow-y-auto max-h-[70vh]", children: [
3265
+ isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
3266
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-48 w-48 rounded-xl" }) }),
3267
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-12 w-full" }),
3268
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-24 w-full" })
1926
3269
  ] }),
1927
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-12 space-y-4", children: [
1928
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "h-12 w-12 text-destructive" }),
1929
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: error ? `Error: ${error}` : "Payment not found" }),
3270
+ error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-12", children: [
3271
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "h-12 w-12 text-destructive mb-4" }),
3272
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-4", children: "Failed to load payment" }),
1930
3273
  /* @__PURE__ */ jsxRuntime.jsx(uiCore.Button, { onClick: () => mutate(), children: "Try Again" })
1931
- ] })
1932
- ] }) });
1933
- }
1934
- const statusInfo = getStatusInfo();
1935
- const StatusIcon = statusInfo.icon;
1936
- const qrCodeUrl = payment.pay_address ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(payment.pay_address)}` : null;
1937
- return /* @__PURE__ */ jsxRuntime.jsx(uiCore.Dialog, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.DialogContent, { className: "sm:max-w-lg", children: [
1938
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.DialogHeader, { children: [
1939
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.DialogTitle, { children: "Payment Details" }),
1940
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.DialogDescription, { children: "Send cryptocurrency to complete your payment" })
1941
- ] }),
1942
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
1943
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-3 p-4 rounded-sm ${statusInfo.bg}`, children: [
1944
- /* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { className: `h-5 w-5 ${statusInfo.color}` }),
1945
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
1946
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold capitalize", children: payment.status }),
1947
- payment.status === "pending" && timeLeft && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-muted-foreground", children: [
1948
- "Expires in ",
1949
- timeLeft
1950
- ] })
1951
- ] })
1952
3274
  ] }),
1953
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
1954
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 bg-muted rounded-sm", children: [
1955
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Amount to send" }),
1956
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1957
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: String(payment.currency_code || "BTC"), size: 20 }),
1958
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono font-bold text-lg", children: [
1959
- payment.pay_amount || "0.00000000",
1960
- " ",
1961
- payment.currency_code
1962
- ] })
1963
- ] })
1964
- ] }),
1965
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4", children: [
1966
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Equivalent to" }),
1967
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-semibold text-lg", children: [
1968
- "$",
1969
- parseFloat(payment.amount_usd || "0").toFixed(2),
1970
- " USD"
3275
+ payment && !isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
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") }),
3278
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
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 })
1971
3281
  ] })
1972
3282
  ] }),
1973
- payment.internal_payment_id && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4", children: [
1974
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Payment Order #" }),
1975
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium", children: payment.internal_payment_id })
1976
- ] }),
1977
- payment.currency_network && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4", children: [
1978
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Network" }),
1979
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: payment.currency_network })
1980
- ] })
1981
- ] }),
1982
- qrCodeUrl && payment.status === "pending" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center p-6 bg-white rounded-sm", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: qrCodeUrl, alt: "Payment QR Code", className: "w-48 h-48" }) }),
1983
- payment.pay_address && payment.status === "pending" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1984
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Payment Address" }),
1985
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1986
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.pay_address }),
1987
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.CopyButton, { value: payment.pay_address, variant: "outline" })
1988
- ] })
1989
- ] }),
1990
- payment.transaction_hash && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1991
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
1992
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3 bg-muted rounded-sm font-mono text-sm break-all", children: payment.transaction_hash })
1993
- ] }),
1994
- payment.payment_url && payment.status === "pending" && /* @__PURE__ */ jsxRuntime.jsxs(
1995
- uiCore.Button,
1996
- {
1997
- variant: "outline",
1998
- className: "w-full",
1999
- onClick: () => window.open(payment.payment_url, "_blank"),
2000
- children: [
2001
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4 mr-2" }),
2002
- "Open in Payment Provider"
2003
- ]
2004
- }
2005
- ),
2006
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-4 border-t space-y-2 text-xs text-muted-foreground", children: [
2007
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
2008
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Payment ID" }),
2009
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: payment.id })
2010
- ] }),
2011
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
2012
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Created" }),
2013
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: moment__default.default.utc(payment.created_at).local().format("MMM D, YYYY HH:mm") })
2014
- ] }),
2015
- payment.confirmations_count !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
2016
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Confirmations" }),
2017
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: payment.confirmations_count })
2018
- ] })
2019
- ] })
2020
- ] }),
2021
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.DialogFooter, { children: [
2022
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Button, { variant: "outline", onClick: handleClose, children: "Close" }),
2023
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Button, { onClick: () => mutate(), variant: "ghost", size: "sm", children: [
2024
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-4 w-4 mr-2" }),
2025
- "Refresh"
2026
- ] })
2027
- ] })
2028
- ] }) });
2029
- };
2030
- var BalanceCard = () => {
2031
- const {
2032
- balance,
2033
- isLoadingBalance,
2034
- refreshBalance
2035
- } = useOverviewContext();
2036
- const formatCurrency = (amount) => {
2037
- if (amount === null || amount === void 0) return "$0.00";
2038
- return new Intl.NumberFormat("en-US", {
2039
- style: "currency",
2040
- currency: "USD",
2041
- minimumFractionDigits: 2
2042
- }).format(amount);
2043
- };
2044
- const formatDate = (dateStr) => {
2045
- if (!dateStr) return "No transactions yet";
2046
- try {
2047
- return moment__default.default.utc(dateStr).local().format("MMM D, YYYY");
2048
- } catch {
2049
- return "Invalid date";
2050
- }
2051
- };
2052
- if (isLoadingBalance) {
2053
- return /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Card, { children: [
2054
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.CardTitle, { className: "flex items-center justify-between", children: [
2055
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2056
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "h-5 w-5" }),
2057
- "Account Balance"
2058
- ] }),
2059
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-8 w-20" })
2060
- ] }) }),
2061
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.CardContent, { className: "space-y-4", children: [
2062
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-10 w-32" }),
2063
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-4 w-48" })
2064
- ] })
2065
- ] });
2066
- }
2067
- const balanceData = balance?.balance || balance;
2068
- const amountUsd = balanceData?.amount_usd ?? 0;
2069
- const totalDeposited = balanceData?.total_deposited ?? 0;
2070
- const totalWithdrawn = balanceData?.total_withdrawn ?? 0;
2071
- const lastTransactionAt = balanceData?.last_transaction_at;
2072
- const isEmpty = amountUsd === 0 && totalDeposited === 0;
2073
- return /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Card, { children: [
2074
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.CardTitle, { className: "flex items-center justify-between", children: [
2075
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2076
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "h-5 w-5" }),
2077
- "Account Balance"
2078
- ] }),
2079
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2080
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Button, { variant: "ghost", size: "sm", onClick: refreshBalance, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-4 w-4" }) }),
2081
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Button, { size: "sm", onClick: () => openCreatePaymentDialog(), children: [
2082
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4 mr-2" }),
2083
- "Add Funds"
2084
- ] })
2085
- ] })
2086
- ] }) }),
2087
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.CardContent, { className: "space-y-4", children: [
2088
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2089
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-4xl font-bold", children: formatCurrency(amountUsd) }),
2090
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground mt-1", children: [
2091
- "Available balance \u2022 Last updated ",
2092
- formatDate(lastTransactionAt)
2093
- ] })
2094
- ] }),
2095
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-4 pt-4 border-t", children: [
2096
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2097
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Total Deposited" }),
2098
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-semibold text-green-600", children: formatCurrency(totalDeposited) })
2099
- ] }),
2100
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2101
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Total Withdrawn" }),
2102
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-semibold text-red-600", children: formatCurrency(totalWithdrawn) })
2103
- ] })
2104
- ] }),
2105
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2106
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Badge, { variant: !isEmpty ? "default" : "secondary", children: !isEmpty ? "Active" : "New Account" }),
2107
- isEmpty && /* @__PURE__ */ jsxRuntime.jsx(uiCore.Badge, { variant: "outline", children: "Empty Balance" })
2108
- ] })
2109
- ] })
2110
- ] });
2111
- };
2112
- var RecentPayments = () => {
2113
- const { payments, isLoadingPayments } = useOverviewContext();
2114
- const formatCurrency = (amount) => {
2115
- if (amount === null || amount === void 0) return "$0.00";
2116
- const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
2117
- return new Intl.NumberFormat("en-US", {
2118
- style: "currency",
2119
- currency: "USD",
2120
- minimumFractionDigits: 2
2121
- }).format(numAmount);
2122
- };
2123
- const getRelativeTime = (date) => {
2124
- if (!date) return "N/A";
2125
- const m = moment__default.default.utc(date).local();
2126
- const now = moment__default.default();
2127
- const diffInSeconds = now.diff(m, "seconds");
2128
- if (diffInSeconds < 60) return "Just now";
2129
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
2130
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
2131
- return `${Math.floor(diffInSeconds / 86400)}d ago`;
2132
- };
2133
- const getStatusVariant = (status) => {
2134
- switch (status?.toLowerCase()) {
2135
- case "completed":
2136
- case "success":
2137
- return "default";
2138
- case "pending":
2139
- case "confirming":
2140
- return "secondary";
2141
- case "failed":
2142
- case "error":
2143
- case "expired":
2144
- return "destructive";
2145
- default:
2146
- return "outline";
2147
- }
2148
- };
2149
- if (isLoadingPayments) {
2150
- return /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Card, { children: [
2151
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.CardTitle, { className: "flex items-center gap-2", children: [
2152
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-5 w-5" }),
2153
- "Recent Payments"
2154
- ] }) }),
2155
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.CardContent, { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-3 border rounded-sm", children: [
2156
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2157
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-4 w-32" }),
2158
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-3 w-24" })
2159
- ] }),
2160
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-6 w-16" })
2161
- ] }, i)) })
2162
- ] });
2163
- }
2164
- const recentPaymentsList = payments?.results?.slice(0, 5) || [];
2165
- return /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Card, { children: [
2166
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.CardTitle, { className: "flex items-center justify-between", children: [
2167
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2168
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-5 w-5" }),
2169
- "Recent Payments"
2170
- ] }),
2171
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Button, { variant: "ghost", size: "sm", children: [
2172
- "View All",
2173
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4 ml-2" })
2174
- ] })
2175
- ] }) }),
2176
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.CardContent, { children: recentPaymentsList.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-8 text-muted-foreground", children: [
2177
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-12 w-12 mx-auto mb-4 opacity-50" }),
2178
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "No recent payments" }),
2179
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm mt-2", children: "Create your first payment to get started" })
2180
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: recentPaymentsList.map((payment) => /* @__PURE__ */ jsxRuntime.jsxs(
2181
- "div",
2182
- {
2183
- className: "flex items-center justify-between p-3 border rounded-sm hover:bg-accent cursor-pointer transition-colors",
2184
- onClick: () => openPaymentDetailsDialog(String(payment.id)),
2185
- children: [
2186
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
3283
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted rounded-xl p-4 space-y-3", children: [
3284
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
3285
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Amount to send" }),
2187
3286
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2188
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: formatCurrency(payment.amount_usd) }),
2189
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Badge, { variant: getStatusVariant(payment.status), className: "text-xs", children: payment.status })
2190
- ] }),
2191
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
2192
- getRelativeTime(payment.created_at),
2193
- " \u2022 ",
2194
- payment.currency_code || "USD"
3287
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.TokenIcon, { symbol: payment.currency_code, size: 24 }),
3288
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono font-bold text-lg", children: [
3289
+ payment.pay_amount,
3290
+ " ",
3291
+ payment.currency_code
3292
+ ] })
2195
3293
  ] })
2196
3294
  ] }),
2197
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4 text-muted-foreground" })
2198
- ]
2199
- },
2200
- payment.id
2201
- )) }) })
2202
- ] });
2203
- };
2204
- var OverviewView = () => {
2205
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6 lg:grid-cols-2", children: [
2206
- /* @__PURE__ */ jsxRuntime.jsx(BalanceCard, {}),
2207
- /* @__PURE__ */ jsxRuntime.jsx(RecentPayments, {})
2208
- ] }) });
2209
- };
2210
- var PaymentsList = () => {
2211
- const pagination = components.useDRFPagination(1, 20);
2212
- const {
2213
- data: payments,
2214
- error,
2215
- isLoading: isLoadingPayments,
2216
- mutate: refreshPayments
2217
- } = usePaymentsPaymentsList(pagination.params, apiPayments);
2218
- const paymentsList = payments?.results || [];
2219
- payments?.count || 0;
2220
- const [searchTerm, setSearchTerm] = react.useState("");
2221
- const [statusFilter, setStatusFilter] = react.useState("all");
2222
- const formatCurrency = (amount) => {
2223
- if (amount === null || amount === void 0) return "$0.00";
2224
- const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
2225
- return new Intl.NumberFormat("en-US", {
2226
- style: "currency",
2227
- currency: "USD",
2228
- minimumFractionDigits: 2
2229
- }).format(numAmount);
2230
- };
2231
- const getRelativeTime = (date) => {
2232
- if (!date) return "N/A";
2233
- const m = moment__default.default.utc(date).local();
2234
- const now = moment__default.default();
2235
- const diffInSeconds = now.diff(m, "seconds");
2236
- if (diffInSeconds < 60) return "Just now";
2237
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
2238
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
2239
- return `${Math.floor(diffInSeconds / 86400)}d ago`;
2240
- };
2241
- const formatDate = (date) => {
2242
- if (!date) return "N/A";
2243
- return moment__default.default.utc(date).local().format("MMM D, YYYY");
2244
- };
2245
- const getStatusVariant = (status) => {
2246
- switch (status?.toLowerCase()) {
2247
- case "completed":
2248
- case "success":
2249
- return "default";
2250
- case "pending":
2251
- case "confirming":
2252
- return "secondary";
2253
- case "failed":
2254
- case "error":
2255
- case "expired":
2256
- return "destructive";
2257
- default:
2258
- return "outline";
2259
- }
2260
- };
2261
- const handleSearch = (value) => {
2262
- setSearchTerm(value);
2263
- };
2264
- const handleStatusFilter = (status) => {
2265
- setStatusFilter(status);
2266
- };
2267
- const truncateId = (id) => {
2268
- if (!id) return "N/A";
2269
- const str = id.toString();
2270
- return str.length > 8 ? `${str.slice(0, 8)}...` : str;
2271
- };
2272
- const filteredPayments = paymentsList.filter((payment) => {
2273
- const matchesSearch = searchTerm ? payment.id?.toLowerCase().includes(searchTerm.toLowerCase()) || payment.status?.toLowerCase().includes(searchTerm.toLowerCase()) || payment.currency_code?.toLowerCase().includes(searchTerm.toLowerCase()) : true;
2274
- const matchesStatus = statusFilter !== "all" ? payment.status?.toLowerCase() === statusFilter.toLowerCase() : true;
2275
- return matchesSearch && matchesStatus;
2276
- }).map((payment) => ({
2277
- ...payment,
2278
- formattedDate: formatDate(payment.created_at),
2279
- relativeTime: getRelativeTime(payment.created_at),
2280
- truncatedId: truncateId(payment.id)
2281
- }));
2282
- return /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Card, { children: [
2283
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.CardTitle, { className: "flex items-center justify-between", children: [
2284
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Payment History" }),
2285
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2286
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Button, { variant: "outline", size: "sm", onClick: () => refreshPayments(), disabled: isLoadingPayments, children: [
2287
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: `h-4 w-4 mr-2 ${isLoadingPayments ? "animate-spin" : ""}` }),
2288
- "Refresh"
3295
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
3296
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Equivalent" }),
3297
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: amountUsd })
3298
+ ] }),
3299
+ payment.currency_network && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm pt-2 border-t", children: [
3300
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Network" }),
3301
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: payment.currency_network })
3302
+ ] })
2289
3303
  ] }),
2290
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Button, { size: "sm", onClick: () => openCreatePaymentDialog(), children: [
2291
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4 mr-2" }),
2292
- "New Payment"
2293
- ] })
2294
- ] })
2295
- ] }) }),
2296
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.CardContent, { className: "space-y-4", children: [
2297
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row gap-4", children: [
2298
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1", children: [
2299
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
2300
- /* @__PURE__ */ jsxRuntime.jsx(
2301
- uiCore.Input,
2302
- {
2303
- placeholder: "Search by ID, status, or currency...",
2304
- value: searchTerm,
2305
- onChange: (e) => handleSearch(e.target.value),
2306
- className: "pl-10"
2307
- }
2308
- )
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: [
3306
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Payment Address" }),
3307
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3308
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 p-3 bg-muted rounded-xl font-mono text-sm break-all", children: payment.pay_address }),
3309
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.CopyButton, { value: payment.pay_address, variant: "outline", className: "shrink-0" })
3310
+ ] })
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
+ ),
3324
+ payment.transaction_hash && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
3325
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: "Transaction Hash" }),
3326
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3 bg-muted rounded-xl font-mono text-sm break-all", children: payment.transaction_hash })
2309
3327
  ] }),
2310
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Select, { value: statusFilter, onValueChange: handleStatusFilter, children: [
2311
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.SelectTrigger, { className: "w-full sm:w-48", children: [
2312
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Filter, { className: "h-4 w-4 mr-2" }),
2313
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectValue, { placeholder: "Filter by status" })
3328
+ payment.payment_url && canPay && /* @__PURE__ */ jsxRuntime.jsxs(
3329
+ uiCore.Button,
3330
+ {
3331
+ variant: "outline",
3332
+ className: "w-full",
3333
+ onClick: () => window.open(payment.payment_url, "_blank"),
3334
+ children: [
3335
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4 mr-2" }),
3336
+ "Open in Payment Provider"
3337
+ ]
3338
+ }
3339
+ ),
3340
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 text-xs text-muted-foreground pt-4 border-t", children: [
3341
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
3342
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Payment ID" }),
3343
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: payment.id })
2314
3344
  ] }),
2315
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.SelectContent, { children: [
2316
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectItem, { value: "all", children: "All Statuses" }),
2317
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectItem, { value: "completed", children: "Completed" }),
2318
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectItem, { value: "pending", children: "Pending" }),
2319
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectItem, { value: "confirming", children: "Confirming" }),
2320
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectItem, { value: "failed", children: "Failed" }),
2321
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectItem, { value: "expired", children: "Expired" })
3345
+ payment.internal_payment_id && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
3346
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Order #" }),
3347
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: payment.internal_payment_id })
3348
+ ] }),
3349
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between", children: [
3350
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Created" }),
3351
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: createdAt })
2322
3352
  ] })
2323
- ] })
2324
- ] }),
2325
- isLoadingPayments ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border rounded-sm", children: [
2326
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2327
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-4 w-32" }),
2328
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-3 w-24" })
2329
3353
  ] }),
2330
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-6 w-16" })
2331
- ] }, i)) }) : filteredPayments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-12", children: [
2332
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-16 mx-auto mb-4 bg-muted rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "w-8 h-8 text-muted-foreground" }) }),
2333
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mb-2", children: "No Payments Found" }),
2334
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mb-4", children: searchTerm || statusFilter !== "all" ? "No payments match your current filters" : "You haven't made any payments yet" }),
2335
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Button, { onClick: () => openCreatePaymentDialog(), children: [
2336
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4 mr-2" }),
2337
- "Create Payment"
2338
- ] })
2339
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2340
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Table, { children: [
2341
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.TableRow, { children: [
2342
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Date" }),
2343
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Amount" }),
2344
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Currency" }),
2345
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Status" }),
2346
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Provider" }),
2347
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Payment ID" }),
2348
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { className: "text-right", children: "Actions" })
2349
- ] }) }),
2350
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableBody, { children: filteredPayments.map((payment) => /* @__PURE__ */ jsxRuntime.jsxs(
2351
- uiCore.TableRow,
2352
- {
2353
- className: "cursor-pointer hover:bg-accent",
2354
- onClick: () => openPaymentDetailsDialog(String(payment.id)),
2355
- children: [
2356
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2357
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: payment.formattedDate }),
2358
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground", children: payment.relativeTime })
2359
- ] }) }),
2360
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { className: "font-mono font-semibold", children: formatCurrency(payment.amount_usd) }),
2361
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.Badge, { variant: "outline", children: payment.currency_code || "USD" }) }),
2362
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.Badge, { variant: getStatusVariant(payment.status), children: payment.status }) }),
2363
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { className: "text-sm text-muted-foreground", children: "NowPayments" }),
2364
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { className: "font-mono text-sm text-muted-foreground", children: payment.truncatedId }),
2365
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(
2366
- uiCore.Button,
2367
- {
2368
- variant: "ghost",
2369
- size: "sm",
2370
- onClick: (e) => {
2371
- e.stopPropagation();
2372
- openPaymentDetailsDialog(String(payment.id));
2373
- },
2374
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4" })
2375
- }
2376
- ) })
2377
- ]
2378
- },
2379
- payment.id
2380
- )) })
2381
- ] }) }),
2382
- /* @__PURE__ */ jsxRuntime.jsx(
2383
- components.StaticPagination,
3354
+ /* @__PURE__ */ jsxRuntime.jsxs(
3355
+ uiCore.Button,
2384
3356
  {
2385
- data: payments,
2386
- onPageChange: pagination.setPage,
2387
- className: "mt-4"
3357
+ variant: "ghost",
3358
+ className: "w-full",
3359
+ onClick: () => mutate(),
3360
+ children: [
3361
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-4 w-4 mr-2" }),
3362
+ "Refresh Status"
3363
+ ]
2388
3364
  }
2389
3365
  )
2390
3366
  ] })
2391
3367
  ] })
2392
- ] });
2393
- };
2394
- var PaymentsView = () => {
2395
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsx(PaymentsList, {}) });
2396
- };
2397
- var TransactionsList = () => {
2398
- const {
2399
- transactions,
2400
- isLoadingTransactions,
2401
- refreshTransactions
2402
- } = useOverviewContext();
2403
- const [searchTerm, setSearchTerm] = react.useState("");
2404
- const [typeFilter, setTypeFilter] = react.useState("all");
2405
- const transactionsList = transactions?.results || transactions?.transactions || [];
2406
- const formatCurrency = (amount) => {
2407
- if (amount === null || amount === void 0) return "$0.00";
2408
- return new Intl.NumberFormat("en-US", {
2409
- style: "currency",
2410
- currency: "USD",
2411
- minimumFractionDigits: 2
2412
- }).format(amount);
2413
- };
2414
- const formatDate = (date) => {
2415
- if (!date) return "N/A";
2416
- try {
2417
- return moment__default.default.utc(date).local().format("MMM D, YYYY hh:mm A");
2418
- } catch {
2419
- return "Invalid date";
2420
- }
2421
- };
2422
- const getRelativeTime = (date) => {
2423
- if (!date) return "N/A";
2424
- const m = moment__default.default.utc(date).local();
2425
- const now = moment__default.default();
2426
- const diffInSeconds = now.diff(m, "seconds");
2427
- if (diffInSeconds < 60) return "Just now";
2428
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
2429
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
2430
- return `${Math.floor(diffInSeconds / 86400)}d ago`;
2431
- };
2432
- const getTypeVariant = (type) => {
2433
- switch (type?.toLowerCase()) {
2434
- case "deposit":
2435
- case "credit":
2436
- return "default";
2437
- case "withdrawal":
2438
- case "debit":
2439
- return "destructive";
2440
- default:
2441
- return "outline";
3368
+ ] }) });
3369
+ }
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);
2442
3384
  }
2443
- };
2444
- const getTypeIcon = (type) => {
2445
- const isDeposit = type?.toLowerCase() === "deposit" || type?.toLowerCase() === "credit";
2446
- return isDeposit ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownLeft, { className: "h-4 w-4 text-green-600" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { className: "h-4 w-4 text-red-600" });
2447
- };
2448
- const handleSearch = async (value) => {
2449
- setSearchTerm(value);
2450
- await refreshTransactions();
2451
- };
2452
- const handleTypeFilter = async (type) => {
2453
- setTypeFilter(type);
2454
- await refreshTransactions();
2455
- };
2456
- const truncateId = (id) => {
2457
- if (!id) return "N/A";
2458
- const str = id.toString();
2459
- return str.length > 8 ? `${str.slice(0, 8)}...` : str;
2460
- };
2461
- const filteredTransactions = transactionsList.filter((transaction) => {
2462
- const matchesSearch = searchTerm ? transaction.id?.toString().toLowerCase().includes(searchTerm.toLowerCase()) || transaction.description?.toLowerCase().includes(searchTerm.toLowerCase()) || transaction.type?.toLowerCase().includes(searchTerm.toLowerCase()) : true;
2463
- const matchesType = typeFilter !== "all" ? transaction.type?.toLowerCase() === typeFilter.toLowerCase() : true;
2464
- return matchesSearch && matchesType;
2465
- }).map((transaction) => ({
2466
- ...transaction,
2467
- isDeposit: transaction.type?.toLowerCase() === "deposit" || transaction.type?.toLowerCase() === "credit",
2468
- formattedDate: formatDate(transaction.created_at || transaction.timestamp),
2469
- relativeTime: getRelativeTime(transaction.created_at || transaction.timestamp),
2470
- truncatedRef: truncateId(transaction.reference || transaction.payment_id)
2471
- }));
2472
- if (isLoadingTransactions) {
2473
- return /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Card, { children: [
2474
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.CardTitle, { className: "flex items-center gap-2", children: [
2475
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-5 w-5" }),
2476
- "Transaction History"
2477
- ] }) }),
2478
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.CardContent, { className: "space-y-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border rounded-sm", children: [
2479
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2480
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-4 w-32" }),
2481
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-3 w-24" })
2482
- ] }),
2483
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Skeleton, { className: "h-6 w-16" })
2484
- ] }, i)) })
2485
- ] });
2486
- }
2487
- return /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Card, { children: [
2488
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.CardTitle, { className: "flex items-center justify-between", children: [
2489
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2490
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-5 w-5" }),
2491
- "Transaction History"
2492
- ] }),
2493
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Button, { variant: "outline", size: "sm", onClick: refreshTransactions, disabled: isLoadingTransactions, children: [
2494
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: `h-4 w-4 mr-2 ${isLoadingTransactions ? "animate-spin" : ""}` }),
2495
- "Refresh"
2496
- ] })
2497
- ] }) }),
2498
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.CardContent, { className: "space-y-4", children: [
2499
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row gap-4", children: [
2500
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1", children: [
2501
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
2502
- /* @__PURE__ */ jsxRuntime.jsx(
2503
- uiCore.Input,
2504
- {
2505
- placeholder: "Search by ID, description, or type...",
2506
- value: searchTerm,
2507
- onChange: (e) => handleSearch(e.target.value),
2508
- className: "pl-10"
2509
- }
2510
- )
2511
- ] }),
2512
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Select, { value: typeFilter, onValueChange: handleTypeFilter, children: [
2513
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.SelectTrigger, { className: "w-full sm:w-48", children: [
2514
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Filter, { className: "h-4 w-4 mr-2" }),
2515
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectValue, { placeholder: "Filter by type" })
2516
- ] }),
2517
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.SelectContent, { children: [
2518
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectItem, { value: "all", children: "All Types" }),
2519
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectItem, { value: "deposit", children: "Deposits" }),
2520
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.SelectItem, { value: "withdrawal", children: "Withdrawals" })
2521
- ] })
2522
- ] })
2523
- ] }),
2524
- filteredTransactions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-12", children: [
2525
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-16 mx-auto mb-4 bg-muted rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "w-8 h-8 text-muted-foreground" }) }),
2526
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mb-2", children: "No Transactions Found" }),
2527
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: searchTerm || typeFilter !== "all" ? "No transactions match your current filters" : "You don't have any transactions yet" })
2528
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Table, { children: [
2529
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(uiCore.TableRow, { children: [
2530
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Date & Time" }),
2531
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Type" }),
2532
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Amount" }),
2533
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Balance After" }),
2534
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Description" }),
2535
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableHead, { children: "Reference" })
2536
- ] }) }),
2537
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableBody, { children: filteredTransactions.map((transaction, index) => /* @__PURE__ */ jsxRuntime.jsxs(uiCore.TableRow, { children: [
2538
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2539
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: transaction.formattedDate }),
2540
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground", children: transaction.relativeTime })
2541
- ] }) }),
2542
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2543
- getTypeIcon(transaction.type),
2544
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.Badge, { variant: getTypeVariant(transaction.type), children: transaction.type || "Unknown" })
2545
- ] }) }),
2546
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { className: "font-mono font-semibold", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: transaction.isDeposit ? "text-green-600" : "text-red-600", children: [
2547
- transaction.isDeposit ? "+" : "-",
2548
- formatCurrency(Math.abs(transaction.amount || transaction.amount_usd || 0))
2549
- ] }) }),
2550
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { className: "font-mono", children: formatCurrency(transaction.balance_after || 0) }),
2551
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { className: "text-sm", children: transaction.description || transaction.note || "No description" }),
2552
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TableCell, { className: "font-mono text-sm text-muted-foreground", children: transaction.truncatedRef })
2553
- ] }, transaction.id || index)) })
2554
- ] }) })
2555
- ] })
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
+ )
2556
3439
  ] });
2557
3440
  };
2558
- var TransactionsView = () => {
2559
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsx(TransactionsList, {}) });
2560
- };
2561
- var PaymentsLayout = () => {
2562
- return /* @__PURE__ */ jsxRuntime.jsx(RootPaymentsProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full p-6 space-y-6", children: [
2563
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2564
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-3xl font-bold tracking-tight", children: "Payments" }),
2565
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "Manage your payments, balance, and transaction history" })
2566
- ] }),
2567
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.Tabs, { defaultValue: "overview", className: "space-y-6", children: [
2568
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.TabsList, { className: "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", children: [
2569
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.TabsTrigger, { value: "overview", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
2570
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "h-4 w-4" }),
2571
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Overview" })
2572
- ] }),
2573
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.TabsTrigger, { value: "payments", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
2574
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "h-4 w-4" }),
2575
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Payments" })
2576
- ] }),
2577
- /* @__PURE__ */ jsxRuntime.jsxs(uiCore.TabsTrigger, { value: "transactions", className: "inline-flex items-center gap-2 px-3 py-1.5", children: [
2578
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, { className: "h-4 w-4" }),
2579
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Transactions" })
2580
- ] })
2581
- ] }),
2582
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TabsContent, { value: "overview", className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsx(OverviewProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(PaymentsProvider, { children: [
2583
- /* @__PURE__ */ jsxRuntime.jsx(OverviewView, {}),
2584
- /* @__PURE__ */ jsxRuntime.jsx(CreatePaymentDialog, {})
2585
- ] }) }) }),
2586
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TabsContent, { value: "payments", className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsxs(PaymentsProvider, { children: [
2587
- /* @__PURE__ */ jsxRuntime.jsx(PaymentsView, {}),
2588
- /* @__PURE__ */ jsxRuntime.jsx(CreatePaymentDialog, {})
2589
- ] }) }),
2590
- /* @__PURE__ */ jsxRuntime.jsx(uiCore.TabsContent, { value: "transactions", className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsx(OverviewProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(TransactionsView, {}) }) })
2591
- ] }),
2592
- /* @__PURE__ */ jsxRuntime.jsx(PaymentDetailsDialog, {})
2593
- ] }) });
2594
- };
3441
+ function WalletPage() {
3442
+ return /* @__PURE__ */ jsxRuntime.jsx(WalletProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(WalletContent, {}) });
3443
+ }
2595
3444
 
2596
3445
  // package.json
2597
3446
  var package_default = {
2598
3447
  name: "@djangocfg/ext-payments",
2599
- version: "1.0.14",
3448
+ version: "1.0.19",
2600
3449
  description: "Payments system extension for DjangoCFG",
2601
3450
  keywords: [
2602
3451
  "django",
@@ -2633,11 +3482,6 @@ var package_default = {
2633
3482
  import: "./dist/index.js",
2634
3483
  require: "./dist/index.cjs"
2635
3484
  },
2636
- "./hooks": {
2637
- types: "./dist/hooks.d.ts",
2638
- import: "./dist/hooks.js",
2639
- require: "./dist/hooks.cjs"
2640
- },
2641
3485
  "./config": {
2642
3486
  types: "./dist/config.d.ts",
2643
3487
  import: "./dist/config.js",
@@ -2665,8 +3509,10 @@ var package_default = {
2665
3509
  "p-retry": "^7.0.0",
2666
3510
  react: "^19",
2667
3511
  swr: "^2.3.7",
2668
- zod: "^4.1.13",
2669
- moment: "^2.30.1"
3512
+ zod: "^4.3.4",
3513
+ moment: "^2.30.1",
3514
+ "react-hook-form": "^7.69.0",
3515
+ "@hookform/resolvers": "^5.2.2"
2670
3516
  },
2671
3517
  devDependencies: {
2672
3518
  "@djangocfg/api": "workspace:*",
@@ -2743,6 +3589,10 @@ exports.API = API;
2743
3589
  exports.APIClient = APIClient;
2744
3590
  exports.APIError = APIError;
2745
3591
  exports.APILogger = APILogger;
3592
+ exports.ActivityItem = ActivityItem;
3593
+ exports.ActivityList = ActivityList;
3594
+ exports.AddFundsSheet = AddFundsSheet;
3595
+ exports.BalanceHero = BalanceHero;
2746
3596
  exports.BalanceSchema = BalanceSchema;
2747
3597
  exports.CookieStorageAdapter = CookieStorageAdapter;
2748
3598
  exports.CurrencySchema = CurrencySchema;
@@ -2754,35 +3604,48 @@ exports.Fetchers = fetchers_exports;
2754
3604
  exports.LocalStorageAdapter = LocalStorageAdapter;
2755
3605
  exports.MemoryStorageAdapter = MemoryStorageAdapter;
2756
3606
  exports.NetworkError = NetworkError;
2757
- exports.PAYMENT_EVENTS = PAYMENT_EVENTS;
2758
3607
  exports.PaginatedPaymentListListSchema = PaginatedPaymentListListSchema;
3608
+ exports.PaginatedWithdrawalListListSchema = PaginatedWithdrawalListListSchema;
3609
+ exports.PaymentCreateRequestSchema = PaymentCreateRequestSchema;
3610
+ exports.PaymentCreateResponseSchema = PaymentCreateResponseSchema;
2759
3611
  exports.PaymentDetailSchema = PaymentDetailSchema;
2760
3612
  exports.PaymentListSchema = PaymentListSchema;
2761
- exports.PaymentsLayout = PaymentsLayout;
3613
+ exports.PaymentSheet = PaymentSheet;
2762
3614
  exports.REFRESH_TOKEN_KEY = REFRESH_TOKEN_KEY;
2763
3615
  exports.Schemas = schemas_exports;
2764
3616
  exports.TOKEN_KEY = TOKEN_KEY;
2765
3617
  exports.TransactionSchema = TransactionSchema;
3618
+ exports.WalletPage = WalletPage;
3619
+ exports.WithdrawSheet = WithdrawSheet;
3620
+ exports.WithdrawalCancelResponseSchema = WithdrawalCancelResponseSchema;
3621
+ exports.WithdrawalCreateRequestSchema = WithdrawalCreateRequestSchema;
3622
+ exports.WithdrawalCreateResponseSchema = WithdrawalCreateResponseSchema;
3623
+ exports.WithdrawalDetailSchema = WithdrawalDetailSchema;
3624
+ exports.WithdrawalListSchema = WithdrawalListSchema;
3625
+ exports.WithdrawalSheet = WithdrawalSheet;
2766
3626
  exports.apiPayments = apiPayments;
2767
3627
  exports.clearAPITokens = clearAPITokens;
2768
- exports.closePaymentsDialog = closePaymentsDialog;
2769
3628
  exports.configureAPI = configureAPI;
2770
3629
  exports.createPaymentsPaymentsConfirmCreate = createPaymentsPaymentsConfirmCreate;
2771
3630
  exports.createPaymentsPaymentsCreateCreate = createPaymentsPaymentsCreateCreate;
3631
+ exports.createPaymentsWithdrawalsCancelCreate = createPaymentsWithdrawalsCancelCreate;
3632
+ exports.createPaymentsWithdrawalsCreateCreate = createPaymentsWithdrawalsCreateCreate;
2772
3633
  exports.dispatchValidationError = dispatchValidationError;
2773
3634
  exports.extensionConfig = extensionConfig;
2774
3635
  exports.formatZodError = formatZodError;
2775
3636
  exports.getAPIInstance = getAPIInstance;
2776
3637
  exports.getPaymentsBalanceRetrieve = getPaymentsBalanceRetrieve;
3638
+ exports.getPaymentsCurrenciesEstimateRetrieve = getPaymentsCurrenciesEstimateRetrieve;
2777
3639
  exports.getPaymentsCurrenciesList = getPaymentsCurrenciesList;
3640
+ exports.getPaymentsCurrenciesWithdrawalEstimateRetrieve = getPaymentsCurrenciesWithdrawalEstimateRetrieve;
2778
3641
  exports.getPaymentsPaymentsList = getPaymentsPaymentsList;
2779
3642
  exports.getPaymentsPaymentsRetrieve = getPaymentsPaymentsRetrieve;
2780
3643
  exports.getPaymentsPaymentsStatusRetrieve = getPaymentsPaymentsStatusRetrieve;
2781
3644
  exports.getPaymentsTransactionsList = getPaymentsTransactionsList;
3645
+ exports.getPaymentsWithdrawalsList = getPaymentsWithdrawalsList;
3646
+ exports.getPaymentsWithdrawalsRetrieve = getPaymentsWithdrawalsRetrieve;
2782
3647
  exports.isAPIConfigured = isAPIConfigured;
2783
3648
  exports.onValidationError = onValidationError;
2784
- exports.openCreatePaymentDialog = openCreatePaymentDialog;
2785
- exports.openPaymentDetailsDialog = openPaymentDetailsDialog;
2786
3649
  exports.reconfigureAPI = reconfigureAPI;
2787
3650
  exports.resetAPI = resetAPI;
2788
3651
  exports.shouldRetry = shouldRetry;