@doujins/payments-ui 0.0.14 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,10 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var React3 = require('react');
3
+ var React17 = require('react');
4
4
  var reactQuery = require('@tanstack/react-query');
5
5
  var walletAdapterReact = require('@solana/wallet-adapter-react');
6
6
  var walletAdapterReactUi = require('@solana/wallet-adapter-react-ui');
7
7
  require('@solana/wallet-adapter-react-ui/styles.css');
8
+ var walletAdapterBase = require('@solana/wallet-adapter-base');
8
9
  var web3_js = require('@solana/web3.js');
9
10
  var walletAdapterPhantom = require('@solana/wallet-adapter-phantom');
10
11
  var walletAdapterSolflare = require('@solana/wallet-adapter-solflare');
@@ -16,17 +17,16 @@ var clsx = require('clsx');
16
17
  var tailwindMerge = require('tailwind-merge');
17
18
  var jsxRuntime = require('react/jsx-runtime');
18
19
  var countryList = require('country-list');
20
+ var reactSlot = require('@radix-ui/react-slot');
19
21
  var classVarianceAuthority = require('class-variance-authority');
20
22
  var LabelPrimitive = require('@radix-ui/react-label');
21
23
  var SelectPrimitive = require('@radix-ui/react-select');
22
24
  var ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
23
25
  var TabsPrimitive = require('@radix-ui/react-tabs');
24
- var buffer = require('buffer');
25
- var splToken = require('@solana/spl-token');
26
26
  var QRCode = require('qrcode');
27
27
  var AlertDialogPrimitive = require('@radix-ui/react-alert-dialog');
28
- var bs58 = require('bs58');
29
28
  var CheckboxPrimitive = require('@radix-ui/react-checkbox');
29
+ var splToken = require('@solana/spl-token');
30
30
 
31
31
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
32
32
 
@@ -48,7 +48,7 @@ function _interopNamespace(e) {
48
48
  return Object.freeze(n);
49
49
  }
50
50
 
51
- var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
51
+ var React17__namespace = /*#__PURE__*/_interopNamespace(React17);
52
52
  var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
53
53
  var countryList__default = /*#__PURE__*/_interopDefault(countryList);
54
54
  var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespace(LabelPrimitive);
@@ -57,7 +57,6 @@ var ScrollAreaPrimitive__namespace = /*#__PURE__*/_interopNamespace(ScrollAreaPr
57
57
  var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
58
58
  var QRCode__default = /*#__PURE__*/_interopDefault(QRCode);
59
59
  var AlertDialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(AlertDialogPrimitive);
60
- var bs58__default = /*#__PURE__*/_interopDefault(bs58);
61
60
  var CheckboxPrimitive__namespace = /*#__PURE__*/_interopNamespace(CheckboxPrimitive);
62
61
 
63
62
  // src/context/PaymentContext.tsx
@@ -90,531 +89,297 @@ var loadCollectJs = (tokenizationKey) => {
90
89
  document.head.appendChild(script);
91
90
  };
92
91
 
93
- // src/services/apiClient.ts
94
- var buildUrl = (baseUrl, path, { params, query }) => {
95
- let resolved = `${baseUrl}${path}`;
96
- if (params) {
97
- Object.entries(params).forEach(([key, value]) => {
98
- resolved = resolved.replace(`:${key}`, encodeURIComponent(String(value)));
99
- });
92
+ // src/lib/client.ts
93
+ var ClientApiError = class extends Error {
94
+ constructor(message, status, body, request) {
95
+ super(message);
96
+ this.name = "ClientApiError";
97
+ this.status = status;
98
+ this.body = body;
99
+ this.request = request;
100
100
  }
101
- if (query) {
102
- const queryString = new URLSearchParams();
103
- Object.entries(query).forEach(([key, value]) => {
104
- if (value === void 0 || value === null) return;
105
- queryString.append(key, String(value));
106
- });
107
- if ([...queryString.keys()].length > 0) {
108
- resolved = `${resolved}?${queryString.toString()}`;
109
- }
101
+ };
102
+ var ensureFetch = (fetchImpl) => {
103
+ if (fetchImpl) return fetchImpl;
104
+ if (typeof globalThis.fetch === "function") {
105
+ return globalThis.fetch.bind(globalThis);
110
106
  }
111
- return resolved;
107
+ throw new Error("payments-ui: global fetch is not available");
112
108
  };
113
- var createApiClient = (paymentConfig, baseUrl, fetcher, resolveAuthToken) => {
109
+ var createClient = (config) => {
110
+ const fetchImpl = ensureFetch(config.fetch);
111
+ const normalizeBase = (value) => value.replace(/\/$/, "");
112
+ const normalizePath = (value, fallback = "/v1") => {
113
+ if (!value) return fallback;
114
+ return value.startsWith("/") ? value : `/${value}`;
115
+ };
116
+ const billingBaseUrl = normalizeBase(config.billingBaseUrl);
117
+ const accountBaseUrl = normalizeBase(
118
+ config.accountBaseUrl ?? config.billingBaseUrl
119
+ );
120
+ const billingBasePath = normalizePath(config.billingBasePath ?? "/v1");
121
+ const accountBasePath = normalizePath(
122
+ config.accountBasePath ?? config.billingBasePath ?? "/v1"
123
+ );
124
+ const defaultHeaders = config.defaultHeaders ?? {};
125
+ const resolveAuthToken = async () => {
126
+ if (!config.getAuthToken) return null;
127
+ try {
128
+ const result = config.getAuthToken();
129
+ return result instanceof Promise ? await result : result;
130
+ } catch (error) {
131
+ console.warn("payments-ui: failed to resolve auth token", error);
132
+ return null;
133
+ }
134
+ };
135
+ const buildUrl = (path, query, target) => {
136
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
137
+ const basePath = target === "account" ? accountBasePath : billingBasePath;
138
+ const baseUrl = target === "account" ? accountBaseUrl : billingBaseUrl;
139
+ const needsBasePrefix = !normalizedPath.startsWith(basePath);
140
+ const finalPath = needsBasePrefix ? `${basePath}${normalizedPath}` : normalizedPath;
141
+ const url = new URL(`${baseUrl}${finalPath}`);
142
+ if (query) {
143
+ Object.entries(query).forEach(([key, value]) => {
144
+ if (value === void 0 || value === null) return;
145
+ url.searchParams.append(key, String(value));
146
+ });
147
+ }
148
+ return url.toString();
149
+ };
114
150
  const request = async (method, path, options) => {
115
- const url = buildUrl(baseUrl, path, options ?? {});
151
+ const target = options?.target ?? "billing";
152
+ const url = buildUrl(path, options?.query, target);
116
153
  const headers = {
117
154
  "Content-Type": "application/json",
118
- ...paymentConfig.defaultHeaders ?? {},
155
+ ...defaultHeaders,
119
156
  ...options?.headers ?? {}
120
157
  };
121
158
  const token = await resolveAuthToken();
122
159
  if (token) {
123
160
  headers.Authorization = `Bearer ${token}`;
124
161
  }
125
- try {
126
- const response = await fetcher(url, {
127
- method,
128
- headers,
129
- body: options?.body ? JSON.stringify(options.body) : void 0
130
- });
131
- if (!response.ok) {
132
- const message = await response.text();
133
- console.error("payments-ui: API request failed", {
134
- url,
135
- method,
136
- status: response.status,
137
- message
138
- });
139
- throw new Error(message || `Request failed with status ${response.status}`);
140
- }
141
- if (response.status === 204) {
142
- return void 0;
143
- }
144
- const data = await response.json();
145
- return data;
146
- } catch (error) {
147
- console.error("payments-ui: API request error", { url, method, error });
148
- throw error;
149
- }
150
- };
151
- return {
152
- request,
153
- get: (path, options) => request("GET", path, options),
154
- post: (path, options) => request("POST", path, options),
155
- put: (path, options) => request("PUT", path, options),
156
- patch: (path, options) => request("PATCH", path, options),
157
- delete: (path, options) => request("DELETE", path, options)
158
- };
159
- };
160
-
161
- // src/services/CardPaymentService.ts
162
- var CardPaymentService = class {
163
- constructor(config) {
164
- this.config = config;
165
- this.collectLoaded = false;
166
- }
167
- async ensureCollectLoaded() {
168
- if (this.collectLoaded) return;
169
- if (!this.config.collectJsKey) {
170
- throw new Error("payments-ui: collect.js key missing");
171
- }
172
- loadCollectJs(this.config.collectJsKey);
173
- this.collectLoaded = true;
174
- }
175
- buildCreatePayload(result) {
176
- return {
177
- payment_token: result.token,
178
- first_name: result.billing.firstName,
179
- last_name: result.billing.lastName,
180
- address1: result.billing.address1,
181
- address2: result.billing.address2,
182
- city: result.billing.city,
183
- state: result.billing.stateRegion,
184
- zip: result.billing.postalCode,
185
- country: result.billing.country,
186
- email: result.billing.email,
187
- provider: result.billing.provider
188
- };
189
- }
190
- };
191
-
192
- // src/services/PaymentMethodService.ts
193
- var PaymentMethodService = class {
194
- constructor(api) {
195
- this.api = api;
196
- }
197
- async list(params) {
198
- return this.api.get("/payment-methods", {
199
- query: {
200
- page: params?.page ?? 1,
201
- page_size: params?.pageSize ?? 50
202
- }
203
- });
204
- }
205
- async create(payload) {
206
- return this.api.post("/payment-methods", {
207
- body: { ...payload }
208
- });
209
- }
210
- async remove(id) {
211
- await this.api.delete(`/payment-methods/${id}`);
212
- }
213
- async activate(id) {
214
- await this.api.put(`/payment-methods/${id}/activate`);
215
- }
216
- };
217
-
218
- // src/services/SolanaPaymentService.ts
219
- var SolanaPaymentService = class {
220
- constructor(api) {
221
- this.api = api;
222
- }
223
- async generatePayment(priceId, token, userWallet) {
224
- return this.api.post("/solana/generate", {
225
- body: { price_id: priceId, token, user_wallet: userWallet }
226
- });
227
- }
228
- async submitPayment(signedTransaction, priceId, intentId, memo) {
229
- return this.api.post("/solana/submit", {
230
- body: {
231
- signed_transaction: signedTransaction,
232
- price_id: priceId,
233
- intent_id: intentId,
234
- ...memo ? { memo } : {}
235
- }
236
- });
237
- }
238
- async fetchSupportedTokens() {
239
- const response = await this.api.get(
240
- "/solana/tokens"
241
- );
242
- return response.tokens;
243
- }
244
- async getSupportedTokens() {
245
- return this.fetchSupportedTokens();
246
- }
247
- async generateQrCode(priceId, token, userWallet) {
248
- return this.api.post("/solana/qr", {
249
- body: {
250
- price_id: priceId,
251
- token,
252
- ...userWallet ? { user_wallet: userWallet } : {}
253
- }
254
- });
255
- }
256
- async generateQRCode(priceId, token, userWallet) {
257
- return this.generateQrCode(priceId, token, userWallet);
258
- }
259
- async checkPaymentStatus(reference, memo) {
260
- return this.api.get("/solana/check", {
261
- query: {
262
- reference,
263
- ...memo ? { memo } : {}
264
- }
162
+ const response = await fetchImpl(url, {
163
+ method,
164
+ headers,
165
+ body: options?.body ? JSON.stringify(options.body) : void 0
265
166
  });
266
- }
267
- };
268
-
269
- // src/services/TokenCatalog.ts
270
- var TokenCatalog = class {
271
- constructor(solanaService, options = {}) {
272
- this.solanaService = solanaService;
273
- this.options = options;
274
- this.cache = [];
275
- this.lastFetched = 0;
276
- }
277
- get ttl() {
278
- return this.options.ttlMs ?? 5 * 60 * 1e3;
279
- }
280
- async getTokens(force = false) {
281
- const isStale = Date.now() - this.lastFetched > this.ttl;
282
- if (!force && this.cache.length > 0 && !isStale) {
283
- return this.cache;
284
- }
285
- const tokens = await this.solanaService.fetchSupportedTokens();
286
- this.cache = tokens;
287
- this.lastFetched = Date.now();
288
- return tokens;
289
- }
290
- getCached() {
291
- return this.cache;
292
- }
293
- };
294
-
295
- // src/services/WalletGateway.ts
296
- var WalletGateway = class {
297
- constructor() {
298
- this.adapter = null;
299
- }
300
- setAdapter(adapter) {
301
- this.adapter = adapter;
302
- }
303
- getPublicKey() {
304
- if (!this.adapter?.publicKey) return null;
305
- try {
306
- return this.adapter.publicKey.toBase58();
307
- } catch {
308
- return null;
309
- }
310
- }
311
- async sign(transaction) {
312
- if (!this.adapter) {
313
- throw new Error("payments-ui: wallet adapter not set");
314
- }
315
- if (typeof this.adapter.signVersionedTransaction === "function") {
316
- return this.adapter.signVersionedTransaction(transaction);
167
+ if (!response.ok) {
168
+ let payload = null;
169
+ try {
170
+ payload = await response.json();
171
+ } catch {
172
+ payload = await response.text();
173
+ }
174
+ throw new ClientApiError(
175
+ payload && typeof payload === "object" && "message" in payload ? String(payload.message) : response.statusText || "Request failed",
176
+ response.status,
177
+ payload,
178
+ { method, url }
179
+ );
317
180
  }
318
- if (typeof this.adapter.signTransaction === "function") {
319
- return this.adapter.signTransaction(transaction);
181
+ if (response.status === 204) {
182
+ return void 0;
320
183
  }
321
- throw new Error("payments-ui: wallet adapter cannot sign transactions");
322
- }
323
- };
324
-
325
- // src/services/SubscriptionService.ts
326
- var SubscriptionService = class {
327
- constructor(api) {
328
- this.api = api;
329
- }
330
- async subscribe(platform, payload) {
331
- const body = this.serializePayload(platform, payload);
332
- return this.api.post(
333
- `/subscriptions/process/${platform}`,
334
- {
335
- body
184
+ return await response.json();
185
+ };
186
+ const normalizeList = (payload) => {
187
+ const data = payload.data ?? [];
188
+ const total = payload.total ?? payload.total_items ?? data.length;
189
+ const limit = payload.limit ?? data.length;
190
+ const offset = payload.offset ?? 0;
191
+ const hasMore = typeof payload.has_more === "boolean" ? payload.has_more : offset + data.length < total;
192
+ return { data, total, limit, offset, hasMore };
193
+ };
194
+ return {
195
+ async listPaymentMethods(params) {
196
+ const result = await request(
197
+ "GET",
198
+ "/me/payment-methods",
199
+ {
200
+ query: {
201
+ limit: params?.limit,
202
+ offset: params?.offset,
203
+ include_inactive: params?.includeInactive
204
+ },
205
+ target: "account"
206
+ }
207
+ );
208
+ return normalizeList(result);
209
+ },
210
+ createPaymentMethod(payload) {
211
+ return request("POST", "/me/payment-methods", {
212
+ body: payload,
213
+ target: "account"
214
+ });
215
+ },
216
+ updatePaymentMethod(id, payload) {
217
+ return request("PUT", `/me/payment-methods/${id}`, {
218
+ body: payload,
219
+ target: "account"
220
+ });
221
+ },
222
+ deletePaymentMethod(id) {
223
+ return request("DELETE", `/me/payment-methods/${id}`, {
224
+ target: "account"
225
+ });
226
+ },
227
+ activatePaymentMethod(id) {
228
+ return request("PUT", `/me/payment-methods/${id}/activate`, {
229
+ target: "account"
230
+ });
231
+ },
232
+ checkout(payload) {
233
+ return request("POST", "/me/checkout", {
234
+ body: payload
235
+ });
236
+ },
237
+ cancelSubscription(feedback) {
238
+ return request("POST", "/me/subscriptions/cancel", {
239
+ body: feedback ? { feedback } : void 0
240
+ });
241
+ },
242
+ async getPaymentHistory(params) {
243
+ const result = await request("GET", "/me/payments", {
244
+ query: {
245
+ limit: params?.limit,
246
+ offset: params?.offset,
247
+ type: params?.type
248
+ }
249
+ });
250
+ return normalizeList(result);
251
+ },
252
+ async getSolanaTokens() {
253
+ const response = await request(
254
+ "GET",
255
+ "/solana/tokens"
256
+ );
257
+ if (Array.isArray(response)) {
258
+ return response;
336
259
  }
337
- );
338
- }
339
- async generateFlexFormUrl(payload) {
340
- return this.api.post("/subscriptions/flexform", {
341
- body: { ...payload }
342
- });
343
- }
344
- async getPaymentHistory(params) {
345
- const limit = params?.limit ?? 10;
346
- const offset = params?.offset ?? 0;
347
- const query = {
348
- limit: String(limit),
349
- offset: String(offset)
350
- };
351
- if (params?.type) {
352
- query.type = params.type;
353
- }
354
- const response = await this.api.get("/subscriptions/purchases", {
355
- query
356
- });
357
- const totalItems = response?.total_items ?? 0;
358
- const pageSize = limit;
359
- const pageNumber = response?.page ?? (pageSize > 0 ? Math.floor(offset / pageSize) + 1 : 1);
360
- const totalPages = response?.total_pages ?? (pageSize > 0 ? Math.ceil(totalItems / pageSize) : void 0);
361
- return {
362
- data: response?.data ?? [],
363
- total_items: totalItems,
364
- limit,
365
- offset,
366
- page: pageNumber,
367
- page_size: pageSize,
368
- total_pages: totalPages
369
- };
370
- }
371
- async cancelSubscription(feedback) {
372
- return this.api.post("/subscriptions/cancel", {
373
- body: feedback ? { feedback } : void 0
374
- });
375
- }
376
- serializePayload(platform, payload) {
377
- if (platform === "nmi") {
378
- const data2 = payload;
379
- if (!data2.priceId) {
380
- throw new Error("payments-ui: priceId is required for NMI subscriptions");
260
+ return response.tokens ?? [];
261
+ },
262
+ async createSolanaPayIntent(payload) {
263
+ const response = await request("POST", "/solana/pay", {
264
+ body: {
265
+ price_id: payload.priceId,
266
+ token: payload.token,
267
+ ...payload.userWallet ? { user_wallet: payload.userWallet } : {}
268
+ }
269
+ });
270
+ return response;
271
+ },
272
+ async getSolanaPayStatus(reference) {
273
+ const response = await request(
274
+ "GET",
275
+ `/solana/pay/${reference}`
276
+ );
277
+ if (response.status === "confirmed") {
278
+ return {
279
+ status: "confirmed",
280
+ payment_id: response.payment_id ?? "",
281
+ transaction: response.signature ?? null,
282
+ intent_id: response.intent_id
283
+ };
381
284
  }
382
- if (!data2.paymentToken && !data2.paymentMethodId) {
383
- throw new Error(
384
- "payments-ui: paymentToken or paymentMethodId is required for NMI subscriptions"
385
- );
285
+ if (response.status === "expired") {
286
+ return {
287
+ status: "failed",
288
+ payment_id: response.payment_id ?? "",
289
+ transaction: response.signature ?? null,
290
+ intent_id: response.intent_id,
291
+ error_message: "Payment intent expired"
292
+ };
386
293
  }
387
- const body = {
388
- price_id: data2.priceId,
389
- processor: data2.processor ?? "nmi",
390
- provider: data2.provider
294
+ return {
295
+ status: "pending",
296
+ payment_id: response.payment_id ?? "",
297
+ transaction: response.signature ?? null,
298
+ intent_id: response.intent_id
391
299
  };
392
- if (data2.email) body.email = data2.email;
393
- if (data2.firstName) body.first_name = data2.firstName;
394
- if (data2.lastName) body.last_name = data2.lastName;
395
- if (data2.address1) body.address1 = data2.address1;
396
- if (data2.city) body.city = data2.city;
397
- if (data2.state) body.state = data2.state;
398
- if (data2.zipCode) body.zip = data2.zipCode;
399
- if (data2.country) body.country = data2.country;
400
- if (data2.paymentToken) body.payment_token = data2.paymentToken;
401
- if (data2.paymentMethodId) body.payment_method_id = data2.paymentMethodId;
402
- return body;
403
- }
404
- const data = payload;
405
- if (!data.priceId) {
406
- throw new Error("payments-ui: priceId is required for CCBill subscriptions");
407
- }
408
- return {
409
- price_id: data.priceId,
410
- processor: data.processor ?? "ccbill",
411
- email: data.email,
412
- first_name: data.firstName,
413
- last_name: data.lastName,
414
- zip: data.zipCode,
415
- country: data.country
416
- };
417
- }
418
- };
419
-
420
- // src/services/SolanaWalletService.ts
421
- var SolanaWalletService = class {
422
- constructor(api) {
423
- this.api = api;
424
- }
425
- async list() {
426
- const response = await this.api.get(
427
- "/wallet/solana"
428
- );
429
- if (Array.isArray(response)) {
430
- return response;
431
- }
432
- if ("wallets" in response && Array.isArray(response.wallets)) {
433
- return response.wallets;
434
- }
435
- if ("wallet" in response) {
436
- return response.wallet ? [response.wallet] : [];
437
- }
438
- if ("address" in response) {
439
- return [response];
440
- }
441
- return [];
442
- }
443
- async requestChallenge(wallet) {
444
- return this.api.post("/wallet/solana/challenge", {
445
- body: { wallet }
446
- });
447
- }
448
- async verify(wallet, signature, nonce) {
449
- const body = { wallet, signature };
450
- if (nonce) {
451
- body.nonce = nonce;
452
- }
453
- return this.api.post("/wallet/solana/verify", { body });
454
- }
455
- async remove(wallet) {
456
- await this.api.delete("/wallet/solana", {
457
- query: { wallet }
458
- });
459
- }
460
- };
461
-
462
- // src/core/PaymentApp.ts
463
- var PaymentApp = class {
464
- constructor(options) {
465
- this.resolveAuthToken = async () => {
466
- if (!this.config.getAuthToken) {
467
- return null;
468
- }
300
+ },
301
+ async getPaymentStatus(id) {
469
302
  try {
470
- const result = this.config.getAuthToken();
471
- if (result instanceof Promise) {
472
- return await result ?? null;
473
- }
474
- return result ?? null;
303
+ return await request("GET", `/payment/status/${id}`);
475
304
  } catch (error) {
476
- console.warn("payments-ui: failed to resolve auth token", error);
477
- return null;
305
+ if (error instanceof ClientApiError && error.status === 404) {
306
+ return null;
307
+ }
308
+ throw error;
478
309
  }
479
- };
480
- this.config = options.config;
481
- this.fetcher = options.fetcher ?? options.config.fetcher ?? globalThis.fetch?.bind(globalThis);
482
- if (!this.fetcher) {
483
- throw new Error("payments-ui: fetch implementation is required");
484
- }
485
- this.services = this.createServices();
486
- }
487
- getConfig() {
488
- return this.config;
489
- }
490
- getFetcher() {
491
- return this.fetcher;
492
- }
493
- getServices() {
494
- return this.services;
495
- }
496
- createServices() {
497
- const billingApi = createApiClient(
498
- this.config,
499
- this.config.endpoints.billingBaseUrl,
500
- this.fetcher,
501
- this.resolveAuthToken
502
- );
503
- const accountBaseUrl = this.config.endpoints.accountBaseUrl ?? this.config.endpoints.billingBaseUrl;
504
- const accountApi = createApiClient(
505
- this.config,
506
- accountBaseUrl,
507
- this.fetcher,
508
- this.resolveAuthToken
509
- );
510
- const solanaPayments = new SolanaPaymentService(billingApi);
511
- const solanaWallets = new SolanaWalletService(billingApi);
512
- const paymentMethods = new PaymentMethodService(accountApi);
513
- const cardPayments = new CardPaymentService(this.config);
514
- const walletGateway = new WalletGateway();
515
- const tokenCatalog = new TokenCatalog(solanaPayments);
516
- const subscriptions = new SubscriptionService(billingApi);
517
- return {
518
- cardPayments,
519
- paymentMethods,
520
- solanaPayments,
521
- solanaWallets,
522
- tokenCatalog,
523
- walletGateway,
524
- subscriptions,
525
- billingApi,
526
- accountApi
527
- };
528
- }
529
- };
530
-
531
- // src/runtime/PaymentsRuntime.ts
532
- var createQueryClient = () => new reactQuery.QueryClient({
533
- defaultOptions: {
534
- queries: {
535
- staleTime: 3e4,
536
- gcTime: 5 * 6e4,
537
- refetchOnWindowFocus: false,
538
- retry: 1
539
- },
540
- mutations: {
541
- retry: 1
542
310
  }
543
- }
544
- });
545
- var PaymentsRuntime = class {
546
- constructor(config) {
547
- this.config = config;
548
- this.app = new PaymentApp({ config });
549
- this.services = this.app.getServices();
550
- this.queryClient = createQueryClient();
551
- }
311
+ };
552
312
  };
553
- var createPaymentsRuntime = (config) => new PaymentsRuntime(config);
554
-
555
- // node_modules/@solana/wallet-adapter-base/lib/esm/types.js
556
- var WalletAdapterNetwork;
557
- (function(WalletAdapterNetwork2) {
558
- WalletAdapterNetwork2["Mainnet"] = "mainnet-beta";
559
- WalletAdapterNetwork2["Testnet"] = "testnet";
560
- WalletAdapterNetwork2["Devnet"] = "devnet";
561
- })(WalletAdapterNetwork || (WalletAdapterNetwork = {}));
562
313
  function cn(...inputs) {
563
314
  return tailwindMerge.twMerge(clsx.clsx(inputs));
564
315
  }
565
316
  var Dialog = DialogPrimitive__namespace.Root;
566
- var DialogPortal = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Portal, { className: cn(className), ...props });
567
- DialogPortal.displayName = DialogPrimitive__namespace.Portal.displayName;
568
- var DialogOverlay = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
317
+ var DialogPortal = DialogPrimitive__namespace.Portal;
318
+ var DialogOverlay = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
569
319
  DialogPrimitive__namespace.Overlay,
570
320
  {
571
321
  ref,
572
322
  className: cn(
573
- "fixed inset-0 z-50 bg-black/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out data-[state=open]:fade-in",
323
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
574
324
  className
575
325
  ),
576
326
  ...props
577
327
  }
578
328
  ));
579
329
  DialogOverlay.displayName = DialogPrimitive__namespace.Overlay.displayName;
580
- var DialogContent = React3__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
330
+ var DialogContent = React17__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(DialogPortal, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payments-ui-portal", children: [
581
331
  /* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
582
332
  /* @__PURE__ */ jsxRuntime.jsxs(
583
333
  DialogPrimitive__namespace.Content,
584
334
  {
585
335
  ref,
586
336
  className: cn(
587
- "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
337
+ "fixed left-[50%] top-[50%] z-50 grid w-[calc(100vw-40px)] sm:w-[calc(100vw-60px)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-white/10 bg-[#161b22] text-white p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] rounded-lg",
588
338
  className
589
339
  ),
590
340
  ...props,
591
341
  children: [
592
342
  children,
593
- /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none", children: [
594
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }),
343
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Close, { className: "absolute right-4 top-5 rounded-full bg-white/10 p-1 opacity-70 transition-opacity hover:opacity-100 hover:bg-white/20 focus:outline-none disabled:pointer-events-none", children: [
344
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3 w-3 text-white" }),
595
345
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
596
346
  ] })
597
347
  ]
598
348
  }
599
349
  )
600
- ] }));
350
+ ] }) }));
601
351
  DialogContent.displayName = DialogPrimitive__namespace.Content.displayName;
602
- var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
352
+ var DialogHeader = ({
353
+ className,
354
+ ...props
355
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
356
+ "div",
357
+ {
358
+ className: cn(
359
+ "flex flex-col space-y-1.5 text-center sm:text-left",
360
+ className
361
+ ),
362
+ ...props
363
+ }
364
+ );
603
365
  DialogHeader.displayName = "DialogHeader";
604
- var DialogTitle = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
366
+ var DialogTitle = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
605
367
  DialogPrimitive__namespace.Title,
606
368
  {
607
369
  ref,
608
- className: cn("text-lg font-semibold leading-none tracking-tight", className),
370
+ className: cn(
371
+ "text-lg font-semibold leading-none tracking-tight",
372
+ className
373
+ ),
609
374
  ...props
610
375
  }
611
376
  ));
612
377
  DialogTitle.displayName = DialogPrimitive__namespace.Title.displayName;
613
- var DialogDescription = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
378
+ var DialogDescription = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
614
379
  DialogPrimitive__namespace.Description,
615
380
  {
616
381
  ref,
617
- className: cn("text-sm text-muted-foreground", className),
382
+ className: cn("text-white/60 text-sm", className),
618
383
  ...props
619
384
  }
620
385
  ));
@@ -634,131 +399,17 @@ var customCountries = [
634
399
  ];
635
400
  countryList__default.default.overwrite(customCountries);
636
401
  var countries = countryList__default.default.getData().sort((a, b) => a.name.localeCompare(b.name));
637
- function setRef(ref, value) {
638
- if (typeof ref === "function") {
639
- return ref(value);
640
- } else if (ref !== null && ref !== void 0) {
641
- ref.current = value;
642
- }
643
- }
644
- function composeRefs(...refs) {
645
- return (node) => {
646
- let hasCleanup = false;
647
- const cleanups = refs.map((ref) => {
648
- const cleanup = setRef(ref, node);
649
- if (!hasCleanup && typeof cleanup == "function") {
650
- hasCleanup = true;
651
- }
652
- return cleanup;
653
- });
654
- if (hasCleanup) {
655
- return () => {
656
- for (let i = 0; i < cleanups.length; i++) {
657
- const cleanup = cleanups[i];
658
- if (typeof cleanup == "function") {
659
- cleanup();
660
- } else {
661
- setRef(refs[i], null);
662
- }
663
- }
664
- };
665
- }
666
- };
667
- }
668
- // @__NO_SIDE_EFFECTS__
669
- function createSlot(ownerName) {
670
- const SlotClone = /* @__PURE__ */ createSlotClone(ownerName);
671
- const Slot2 = React3__namespace.forwardRef((props, forwardedRef) => {
672
- const { children, ...slotProps } = props;
673
- const childrenArray = React3__namespace.Children.toArray(children);
674
- const slottable = childrenArray.find(isSlottable);
675
- if (slottable) {
676
- const newElement = slottable.props.children;
677
- const newChildren = childrenArray.map((child) => {
678
- if (child === slottable) {
679
- if (React3__namespace.Children.count(newElement) > 1) return React3__namespace.Children.only(null);
680
- return React3__namespace.isValidElement(newElement) ? newElement.props.children : null;
681
- } else {
682
- return child;
683
- }
684
- });
685
- return /* @__PURE__ */ jsxRuntime.jsx(SlotClone, { ...slotProps, ref: forwardedRef, children: React3__namespace.isValidElement(newElement) ? React3__namespace.cloneElement(newElement, void 0, newChildren) : null });
686
- }
687
- return /* @__PURE__ */ jsxRuntime.jsx(SlotClone, { ...slotProps, ref: forwardedRef, children });
688
- });
689
- Slot2.displayName = `${ownerName}.Slot`;
690
- return Slot2;
691
- }
692
- var Slot = /* @__PURE__ */ createSlot("Slot");
693
- // @__NO_SIDE_EFFECTS__
694
- function createSlotClone(ownerName) {
695
- const SlotClone = React3__namespace.forwardRef((props, forwardedRef) => {
696
- const { children, ...slotProps } = props;
697
- if (React3__namespace.isValidElement(children)) {
698
- const childrenRef = getElementRef(children);
699
- const props2 = mergeProps(slotProps, children.props);
700
- if (children.type !== React3__namespace.Fragment) {
701
- props2.ref = forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef;
702
- }
703
- return React3__namespace.cloneElement(children, props2);
704
- }
705
- return React3__namespace.Children.count(children) > 1 ? React3__namespace.Children.only(null) : null;
706
- });
707
- SlotClone.displayName = `${ownerName}.SlotClone`;
708
- return SlotClone;
709
- }
710
- var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
711
- function isSlottable(child) {
712
- return React3__namespace.isValidElement(child) && typeof child.type === "function" && "__radixId" in child.type && child.type.__radixId === SLOTTABLE_IDENTIFIER;
713
- }
714
- function mergeProps(slotProps, childProps) {
715
- const overrideProps = { ...childProps };
716
- for (const propName in childProps) {
717
- const slotPropValue = slotProps[propName];
718
- const childPropValue = childProps[propName];
719
- const isHandler = /^on[A-Z]/.test(propName);
720
- if (isHandler) {
721
- if (slotPropValue && childPropValue) {
722
- overrideProps[propName] = (...args) => {
723
- const result = childPropValue(...args);
724
- slotPropValue(...args);
725
- return result;
726
- };
727
- } else if (slotPropValue) {
728
- overrideProps[propName] = slotPropValue;
729
- }
730
- } else if (propName === "style") {
731
- overrideProps[propName] = { ...slotPropValue, ...childPropValue };
732
- } else if (propName === "className") {
733
- overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(" ");
734
- }
735
- }
736
- return { ...slotProps, ...overrideProps };
737
- }
738
- function getElementRef(element) {
739
- let getter = Object.getOwnPropertyDescriptor(element.props, "ref")?.get;
740
- let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
741
- if (mayWarn) {
742
- return element.ref;
743
- }
744
- getter = Object.getOwnPropertyDescriptor(element, "ref")?.get;
745
- mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
746
- if (mayWarn) {
747
- return element.props.ref;
748
- }
749
- return element.props.ref || element.ref;
750
- }
751
402
  var buttonVariants = classVarianceAuthority.cva(
752
- "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
403
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/20 disabled:pointer-events-none disabled:opacity-50",
753
404
  {
754
405
  variants: {
755
406
  variant: {
756
- default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
757
- secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
758
- outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
759
- ghost: "hover:bg-accent hover:text-accent-foreground",
760
- destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
761
- link: "text-primary underline-offset-4 hover:underline"
407
+ default: "bg-[#28a745] text-white shadow hover:bg-[#16a34a]",
408
+ secondary: "bg-white/10 text-white hover:bg-white/20",
409
+ outline: "border border-white/10 bg-transparent text-white hover:bg-white/10",
410
+ ghost: "text-white/80 hover:bg-white/10 hover:text-white",
411
+ destructive: "bg-red-600 text-white hover:bg-red-700",
412
+ link: "text-blue-400 underline-offset-4 hover:underline"
762
413
  },
763
414
  size: {
764
415
  default: "h-10 px-4 py-2",
@@ -773,9 +424,9 @@ var buttonVariants = classVarianceAuthority.cva(
773
424
  }
774
425
  }
775
426
  );
776
- var Button = React3__namespace.forwardRef(
427
+ var Button = React17__namespace.forwardRef(
777
428
  ({ className, variant, size, asChild = false, ...props }, ref) => {
778
- const Comp = asChild ? Slot : "button";
429
+ const Comp = asChild ? reactSlot.Slot : "button";
779
430
  return /* @__PURE__ */ jsxRuntime.jsx(
780
431
  Comp,
781
432
  {
@@ -787,14 +438,14 @@ var Button = React3__namespace.forwardRef(
787
438
  }
788
439
  );
789
440
  Button.displayName = "Button";
790
- var Input = React3__namespace.forwardRef(
441
+ var Input = React17__namespace.forwardRef(
791
442
  ({ className, type, ...props }, ref) => {
792
443
  return /* @__PURE__ */ jsxRuntime.jsx(
793
444
  "input",
794
445
  {
795
446
  type,
796
447
  className: cn(
797
- "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
448
+ "flex h-10 w-full rounded-md border border-white/10 bg-white/5 px-3 py-2 text-sm text-white placeholder:text-white/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/20 focus-visible:border-white/20 disabled:cursor-not-allowed disabled:opacity-50",
798
449
  className
799
450
  ),
800
451
  ref,
@@ -804,12 +455,12 @@ var Input = React3__namespace.forwardRef(
804
455
  }
805
456
  );
806
457
  Input.displayName = "Input";
807
- var Label = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
458
+ var Label = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
808
459
  LabelPrimitive__namespace.Root,
809
460
  {
810
461
  ref,
811
462
  className: cn(
812
- "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
463
+ "text-sm font-medium leading-none text-white peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
813
464
  className
814
465
  ),
815
466
  ...props
@@ -818,12 +469,12 @@ var Label = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @_
818
469
  Label.displayName = LabelPrimitive__namespace.Root.displayName;
819
470
  var Select = SelectPrimitive__namespace.Root;
820
471
  var SelectValue = SelectPrimitive__namespace.Value;
821
- var SelectTrigger = React3__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
472
+ var SelectTrigger = React17__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
822
473
  SelectPrimitive__namespace.Trigger,
823
474
  {
824
475
  ref,
825
476
  className: cn(
826
- "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
477
+ "flex h-10 w-full items-center justify-between rounded-md border border-white/10 bg-white/5 px-3 py-2 text-sm text-white placeholder:text-white/40 focus:outline-none focus:ring-2 focus:ring-white/20 disabled:cursor-not-allowed disabled:opacity-50",
827
478
  className
828
479
  ),
829
480
  ...props,
@@ -834,39 +485,39 @@ var SelectTrigger = React3__namespace.forwardRef(({ className, children, ...prop
834
485
  }
835
486
  ));
836
487
  SelectTrigger.displayName = SelectPrimitive__namespace.Trigger.displayName;
837
- var SelectContent = React3__namespace.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
488
+ var SelectContent = React17__namespace.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payments-ui-portal", children: /* @__PURE__ */ jsxRuntime.jsxs(
838
489
  SelectPrimitive__namespace.Content,
839
490
  {
840
491
  ref,
841
492
  className: cn(
842
- "relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
493
+ "relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-white/10 bg-[#1a1f26] text-white shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
843
494
  className
844
495
  ),
845
496
  position,
846
497
  ...props,
847
498
  children: [
848
- /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ScrollUpButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "h-4 w-4" }) }),
499
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ScrollUpButton, { className: "flex cursor-default items-center justify-center py-1 text-white/60", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "h-4 w-4" }) }),
849
500
  /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Viewport, { className: "p-1", children }),
850
- /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ScrollDownButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-4 w-4" }) })
501
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ScrollDownButton, { className: "flex cursor-default items-center justify-center py-1 text-white/60", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-4 w-4" }) })
851
502
  ]
852
503
  }
853
- ) }));
504
+ ) }) }));
854
505
  SelectContent.displayName = SelectPrimitive__namespace.Content.displayName;
855
- var SelectLabel = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
506
+ var SelectLabel = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
856
507
  SelectPrimitive__namespace.Label,
857
508
  {
858
509
  ref,
859
- className: cn("px-2 py-1.5 text-sm font-semibold text-muted-foreground", className),
510
+ className: cn("px-2 py-1.5 text-sm font-semibold text-white/60", className),
860
511
  ...props
861
512
  }
862
513
  ));
863
514
  SelectLabel.displayName = SelectPrimitive__namespace.Label.displayName;
864
- var SelectItem = React3__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
515
+ var SelectItem = React17__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
865
516
  SelectPrimitive__namespace.Item,
866
517
  {
867
518
  ref,
868
519
  className: cn(
869
- "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
520
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm text-white outline-none focus:bg-white/10 focus:text-white data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
870
521
  className
871
522
  ),
872
523
  ...props,
@@ -877,16 +528,18 @@ var SelectItem = React3__namespace.forwardRef(({ className, children, ...props }
877
528
  }
878
529
  ));
879
530
  SelectItem.displayName = SelectPrimitive__namespace.Item.displayName;
880
- var SelectSeparator = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
531
+ var SelectSeparator = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
881
532
  SelectPrimitive__namespace.Separator,
882
533
  {
883
534
  ref,
884
- className: cn("mx-1 my-1 h-px bg-muted", className),
535
+ className: cn("mx-1 my-1 h-px bg-white/10", className),
885
536
  ...props
886
537
  }
887
538
  ));
888
539
  SelectSeparator.displayName = SelectPrimitive__namespace.Separator.displayName;
889
- var defaultBilling = {
540
+
541
+ // src/constants/billing.ts
542
+ var defaultBillingDetails = {
890
543
  firstName: "",
891
544
  lastName: "",
892
545
  address1: "",
@@ -911,32 +564,32 @@ var CardDetailsForm = ({
911
564
  submitDisabled = false
912
565
  }) => {
913
566
  const { config } = usePaymentContext();
914
- const defaultValuesKey = React3.useMemo(() => JSON.stringify(defaultValues ?? {}), [defaultValues]);
915
- const mergedDefaults = React3.useMemo(
567
+ const defaultValuesKey = React17.useMemo(() => JSON.stringify(defaultValues ?? {}), [defaultValues]);
568
+ const mergedDefaults = React17.useMemo(
916
569
  () => ({
917
- ...defaultBilling,
570
+ ...defaultBillingDetails,
918
571
  ...defaultValues,
919
- email: defaultValues?.email ?? config.defaultUser?.email ?? defaultBilling.email
572
+ email: defaultValues?.email ?? config.defaultUser?.email ?? defaultBillingDetails.email
920
573
  }),
921
574
  [defaultValuesKey, config.defaultUser?.email]
922
575
  );
923
- const [firstName, setFirstName] = React3.useState(mergedDefaults.firstName);
924
- const [lastName, setLastName] = React3.useState(mergedDefaults.lastName);
925
- const [address1, setAddress1] = React3.useState(mergedDefaults.address1);
926
- const [city, setCity] = React3.useState(mergedDefaults.city);
927
- const [stateRegion, setStateRegion] = React3.useState(mergedDefaults.stateRegion ?? "");
928
- const [postalCode, setPostalCode] = React3.useState(mergedDefaults.postalCode);
929
- const [country, setCountry] = React3.useState(mergedDefaults.country);
930
- const [email, setEmail] = React3.useState(mergedDefaults.email ?? "");
931
- const [localError, setLocalError] = React3.useState(null);
932
- const [isTokenizing, setIsTokenizing] = React3.useState(false);
933
- React3.useEffect(() => {
576
+ const [firstName, setFirstName] = React17.useState(mergedDefaults.firstName);
577
+ const [lastName, setLastName] = React17.useState(mergedDefaults.lastName);
578
+ const [address1, setAddress1] = React17.useState(mergedDefaults.address1);
579
+ const [city, setCity] = React17.useState(mergedDefaults.city);
580
+ const [stateRegion, setStateRegion] = React17.useState(mergedDefaults.stateRegion ?? "");
581
+ const [postalCode, setPostalCode] = React17.useState(mergedDefaults.postalCode);
582
+ const [country, setCountry] = React17.useState(mergedDefaults.country);
583
+ const [email, setEmail] = React17.useState(mergedDefaults.email ?? "");
584
+ const [localError, setLocalError] = React17.useState(null);
585
+ const [isTokenizing, setIsTokenizing] = React17.useState(false);
586
+ React17.useEffect(() => {
934
587
  if (!visible) {
935
588
  setLocalError(null);
936
589
  setIsTokenizing(false);
937
590
  }
938
591
  }, [visible]);
939
- React3.useEffect(() => {
592
+ React17.useEffect(() => {
940
593
  if (!visible) return;
941
594
  setFirstName(mergedDefaults.firstName);
942
595
  setLastName(mergedDefaults.lastName);
@@ -947,7 +600,7 @@ var CardDetailsForm = ({
947
600
  setCountry(mergedDefaults.country);
948
601
  setEmail(mergedDefaults.email ?? "");
949
602
  }, [defaultValuesKey, mergedDefaults, visible]);
950
- React3.useEffect(() => {
603
+ React17.useEffect(() => {
951
604
  if (!onBillingChange) return;
952
605
  onBillingChange({
953
606
  firstName,
@@ -972,7 +625,7 @@ var CardDetailsForm = ({
972
625
  mergedDefaults.provider,
973
626
  onBillingChange
974
627
  ]);
975
- React3.useEffect(() => {
628
+ React17.useEffect(() => {
976
629
  if (typeof window === "undefined" || !window.CollectJS || !visible) {
977
630
  return;
978
631
  }
@@ -1045,7 +698,7 @@ var CardDetailsForm = ({
1045
698
  window.CollectJS.startPaymentRequest();
1046
699
  };
1047
700
  const errorMessage = localError ?? externalError;
1048
- const collectFieldClass = "flex h-11 w-full items-center rounded-md border border-border/60 bg-background px-3 text-sm text-muted-foreground";
701
+ const collectFieldClass = "flex h-11 w-full items-center rounded-md border border-white/10 bg-white/5 px-3 text-sm text-white";
1049
702
  return /* @__PURE__ */ jsxRuntime.jsxs(
1050
703
  "form",
1051
704
  {
@@ -1053,10 +706,10 @@ var CardDetailsForm = ({
1053
706
  onSubmit: handleSubmit,
1054
707
  noValidate: true,
1055
708
  children: [
1056
- errorMessage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 px-4 py-2 text-sm text-destructive", children: errorMessage }),
709
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-red-500/40 bg-red-500/10 px-4 py-2 text-sm text-red-400", children: errorMessage }),
1057
710
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-5 md:grid-cols-2", children: [
1058
711
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1059
- /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: "payments-first", className: "flex items-center gap-2 text-muted-foreground", children: [
712
+ /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: "payments-first", className: "flex items-center gap-2 text-white/70", children: [
1060
713
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.User, { className: "h-4 w-4" }),
1061
714
  " First name"
1062
715
  ] }),
@@ -1071,7 +724,7 @@ var CardDetailsForm = ({
1071
724
  )
1072
725
  ] }),
1073
726
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1074
- /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: "payments-last", className: "flex items-center gap-2 text-muted-foreground", children: [
727
+ /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: "payments-last", className: "flex items-center gap-2 text-white/70", children: [
1075
728
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.User, { className: "h-4 w-4" }),
1076
729
  " Last name"
1077
730
  ] }),
@@ -1138,7 +791,7 @@ var CardDetailsForm = ({
1138
791
  ] }),
1139
792
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-5 md:grid-cols-2", children: [
1140
793
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1141
- /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: "payments-postal", className: "flex items-center gap-2 text-muted-foreground", children: [
794
+ /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: "payments-postal", className: "flex items-center gap-2 text-white/70", children: [
1142
795
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MapPin, { className: "h-4 w-4" }),
1143
796
  " Postal code"
1144
797
  ] }),
@@ -1190,7 +843,7 @@ var CardDetailsForm = ({
1190
843
  ] })
1191
844
  }
1192
845
  ),
1193
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
846
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-2 text-xs text-white/50", children: [
1194
847
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "h-4 w-4" }),
1195
848
  " Your payment information is encrypted and processed securely."
1196
849
  ] })
@@ -1198,19 +851,24 @@ var CardDetailsForm = ({
1198
851
  }
1199
852
  );
1200
853
  };
1201
- var usePaymentMethodService = () => {
1202
- const { services } = usePaymentContext();
1203
- return React3.useMemo(() => services.paymentMethods, [services]);
1204
- };
1205
-
1206
- // src/hooks/usePaymentMethods.ts
1207
854
  var PAYMENT_METHODS_KEY = ["payments-ui", "payment-methods"];
1208
855
  var usePaymentMethods = () => {
1209
- const service = usePaymentMethodService();
856
+ const { client } = usePaymentContext();
1210
857
  const queryClient = reactQuery.useQueryClient();
1211
858
  const listQuery = reactQuery.useQuery({
1212
859
  queryKey: PAYMENT_METHODS_KEY,
1213
- queryFn: () => service.list({ pageSize: 50 })
860
+ queryFn: async () => {
861
+ const response = await client.listPaymentMethods({ limit: 50 });
862
+ return {
863
+ data: response.data,
864
+ total_items: response.total,
865
+ limit: response.limit,
866
+ offset: response.offset,
867
+ page: response.limit > 0 ? Math.floor(response.offset / response.limit) + 1 : 1,
868
+ page_size: response.limit,
869
+ total_pages: response.limit > 0 ? Math.ceil(response.total / response.limit) : void 0
870
+ };
871
+ }
1214
872
  });
1215
873
  const createMutation = reactQuery.useMutation({
1216
874
  mutationFn: ({ token, billing }) => {
@@ -1227,14 +885,14 @@ var usePaymentMethods = () => {
1227
885
  email: billing.email,
1228
886
  provider: billing.provider
1229
887
  };
1230
- return service.create(payload);
888
+ return client.createPaymentMethod(payload);
1231
889
  },
1232
890
  onSuccess: () => {
1233
891
  void queryClient.invalidateQueries({ queryKey: PAYMENT_METHODS_KEY });
1234
892
  }
1235
893
  });
1236
894
  const deleteMutation = reactQuery.useMutation({
1237
- mutationFn: ({ id }) => service.remove(id),
895
+ mutationFn: ({ id }) => client.deletePaymentMethod(id),
1238
896
  onSuccess: () => {
1239
897
  void queryClient.invalidateQueries({ queryKey: PAYMENT_METHODS_KEY });
1240
898
  }
@@ -1250,10 +908,10 @@ var badgeVariants = classVarianceAuthority.cva(
1250
908
  {
1251
909
  variants: {
1252
910
  variant: {
1253
- default: "border-transparent bg-primary text-primary-foreground",
1254
- secondary: "border-transparent bg-secondary text-secondary-foreground",
1255
- outline: "text-foreground",
1256
- destructive: "border-transparent bg-destructive text-destructive-foreground"
911
+ default: "border-transparent bg-emerald-500/20 text-emerald-400",
912
+ secondary: "border-transparent bg-white/10 text-white/70",
913
+ outline: "border-white/20 text-white/80",
914
+ destructive: "border-transparent bg-red-500/20 text-red-400"
1257
915
  }
1258
916
  },
1259
917
  defaultVariants: {
@@ -1264,7 +922,7 @@ var badgeVariants = classVarianceAuthority.cva(
1264
922
  function Badge({ className, variant, ...props }) {
1265
923
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(badgeVariants({ variant }), className), ...props });
1266
924
  }
1267
- var ScrollArea = React3__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
925
+ var ScrollArea = React17__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1268
926
  ScrollAreaPrimitive__namespace.Root,
1269
927
  {
1270
928
  ref,
@@ -1278,7 +936,7 @@ var ScrollArea = React3__namespace.forwardRef(({ className, children, ...props }
1278
936
  }
1279
937
  ));
1280
938
  ScrollArea.displayName = ScrollAreaPrimitive__namespace.Root.displayName;
1281
- var ScrollBar = React3__namespace.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
939
+ var ScrollBar = React17__namespace.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1282
940
  ScrollAreaPrimitive__namespace.ScrollAreaScrollbar,
1283
941
  {
1284
942
  ref,
@@ -1307,9 +965,9 @@ var StoredPaymentMethods = ({
1307
965
  description = "Manage your saved cards"
1308
966
  }) => {
1309
967
  const { listQuery, createMutation, deleteMutation } = usePaymentMethods();
1310
- const [isModalOpen, setIsModalOpen] = React3.useState(false);
1311
- const [deletingId, setDeletingId] = React3.useState(null);
1312
- const payments = React3.useMemo(() => listQuery.data?.data ?? [], [listQuery.data]);
968
+ const [isModalOpen, setIsModalOpen] = React17.useState(false);
969
+ const [deletingId, setDeletingId] = React17.useState(null);
970
+ const payments = React17.useMemo(() => listQuery.data?.data ?? [], [listQuery.data]);
1313
971
  const handleCardTokenize = (token, billing) => {
1314
972
  createMutation.mutate({ token, billing });
1315
973
  };
@@ -1416,36 +1074,36 @@ var StoredPaymentMethods = ({
1416
1074
  ] });
1417
1075
  };
1418
1076
  var Tabs = TabsPrimitive__namespace.Root;
1419
- var TabsList = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1077
+ var TabsList = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1420
1078
  TabsPrimitive__namespace.List,
1421
1079
  {
1422
1080
  ref,
1423
1081
  className: cn(
1424
- "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
1082
+ "inline-flex h-10 items-center justify-center rounded-md bg-white/5 border border-white/10 p-1 text-white/60",
1425
1083
  className
1426
1084
  ),
1427
1085
  ...props
1428
1086
  }
1429
1087
  ));
1430
1088
  TabsList.displayName = TabsPrimitive__namespace.List.displayName;
1431
- var TabsTrigger = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1089
+ var TabsTrigger = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1432
1090
  TabsPrimitive__namespace.Trigger,
1433
1091
  {
1434
1092
  ref,
1435
1093
  className: cn(
1436
- "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
1094
+ "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/20 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-white/10 data-[state=active]:text-white data-[state=active]:shadow",
1437
1095
  className
1438
1096
  ),
1439
1097
  ...props
1440
1098
  }
1441
1099
  ));
1442
1100
  TabsTrigger.displayName = TabsPrimitive__namespace.Trigger.displayName;
1443
- var TabsContent = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1101
+ var TabsContent = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1444
1102
  TabsPrimitive__namespace.Content,
1445
1103
  {
1446
1104
  ref,
1447
1105
  className: cn(
1448
- "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
1106
+ "mt-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/20",
1449
1107
  className
1450
1108
  ),
1451
1109
  ...props
@@ -1454,19 +1112,19 @@ var TabsContent = React3__namespace.forwardRef(({ className, ...props }, ref) =>
1454
1112
  TabsContent.displayName = TabsPrimitive__namespace.Content.displayName;
1455
1113
  var usePaymentNotifications = () => {
1456
1114
  const { config } = usePaymentContext();
1457
- const notifyStatus = React3.useCallback(
1115
+ const notifyStatus = React17.useCallback(
1458
1116
  (status, context) => {
1459
1117
  config.callbacks?.onStatusChange?.({ status, context });
1460
1118
  },
1461
1119
  [config.callbacks]
1462
1120
  );
1463
- const notifySuccess = React3.useCallback(
1121
+ const notifySuccess = React17.useCallback(
1464
1122
  (payload) => {
1465
1123
  config.callbacks?.onSuccess?.(payload ?? {});
1466
1124
  },
1467
1125
  [config.callbacks]
1468
1126
  );
1469
- const notifyError = React3.useCallback(
1127
+ const notifyError = React17.useCallback(
1470
1128
  (error) => {
1471
1129
  config.callbacks?.onError?.(
1472
1130
  typeof error === "string" ? new Error(error) : error
@@ -1480,384 +1138,21 @@ var usePaymentNotifications = () => {
1480
1138
  notifyError
1481
1139
  };
1482
1140
  };
1483
- var useSolanaService = () => {
1484
- const { services } = usePaymentContext();
1485
- return React3.useMemo(() => services.solanaPayments, [services]);
1486
- };
1487
- var getSolBalance = async (connection, publicKey) => {
1488
- try {
1489
- const lamports = await connection.getBalance(publicKey);
1490
- return lamports / web3_js.LAMPORTS_PER_SOL;
1491
- } catch (error) {
1492
- console.error("Failed to fetch SOL balance:", error);
1493
- return 0;
1494
- }
1495
- };
1496
- var fetchAllTokenBalances = async (connection, publicKey) => {
1497
- const balances = /* @__PURE__ */ new Map();
1498
- try {
1499
- const tokenAccounts = await connection.getParsedProgramAccounts(
1500
- splToken.TOKEN_PROGRAM_ID,
1501
- {
1502
- filters: [
1503
- {
1504
- dataSize: 165
1505
- // Size of token account
1506
- },
1507
- {
1508
- memcmp: {
1509
- offset: 32,
1510
- // Owner field offset
1511
- bytes: publicKey.toString()
1512
- }
1513
- }
1514
- ]
1515
- }
1516
- );
1517
- for (const account of tokenAccounts) {
1518
- const data = account.account.data;
1519
- const parsed = data.parsed;
1520
- const info = parsed?.info;
1521
- if (info && info.tokenAmount) {
1522
- const mintAddress = info.mint;
1523
- const uiAmount = info.tokenAmount.uiAmount || 0;
1524
- if (uiAmount > 0) {
1525
- balances.set(mintAddress, uiAmount);
1526
- }
1527
- }
1528
- }
1529
- } catch (error) {
1530
- console.error("Failed to fetch token balances:", error);
1531
- }
1532
- return balances;
1533
- };
1534
- var fetchSupportedTokenBalances = async (connection, publicKey, supportedTokens) => {
1535
- const results = [];
1536
- const solBalance = await getSolBalance(connection, publicKey);
1537
- const solTokenMeta = supportedTokens.find((token) => token.is_native || token.symbol === "SOL") || {
1538
- symbol: "SOL",
1539
- name: "Solana",
1540
- mint: "So11111111111111111111111111111111111111112",
1541
- decimals: 9};
1542
- results.push({
1543
- mint: solTokenMeta.mint,
1544
- symbol: solTokenMeta.symbol,
1545
- name: solTokenMeta.name,
1546
- balance: solBalance,
1547
- uiBalance: solBalance.toFixed(solTokenMeta.decimals <= 4 ? solTokenMeta.decimals : 4),
1548
- decimals: solTokenMeta.decimals,
1549
- isNative: true
1550
- });
1551
- const tokenBalances = await fetchAllTokenBalances(connection, publicKey);
1552
- const tokenMetaByMint = new Map(
1553
- supportedTokens.filter((token) => !(token.is_native || token.symbol === "SOL")).map((token) => [token.mint, token])
1554
- );
1555
- for (const [mint, tokenMeta] of tokenMetaByMint.entries()) {
1556
- const balance = tokenBalances.get(mint) || 0;
1557
- results.push({
1558
- mint,
1559
- symbol: tokenMeta.symbol,
1560
- name: tokenMeta.name,
1561
- balance,
1562
- uiBalance: balance.toFixed(tokenMeta.decimals <= 6 ? tokenMeta.decimals : 6),
1563
- decimals: tokenMeta.decimals,
1564
- isNative: false
1565
- });
1566
- }
1567
- return results;
1568
- };
1569
- var hasSufficientBalance = (balance, requiredAmount, buffer = 0.05) => {
1570
- const requiredWithBuffer = requiredAmount * (1 + buffer);
1571
- return balance >= requiredWithBuffer;
1572
- };
1573
-
1574
- // src/hooks/useSolanaDirectPayment.ts
1575
- var useSolanaDirectPayment = (options) => {
1576
- const { priceId, tokenAmount, selectedToken, supportedTokens, onStart, onConfirming, onSuccess, onError } = options;
1577
- const { connected, publicKey, wallet, signTransaction } = walletAdapterReact.useWallet();
1578
- const { config } = usePaymentContext();
1579
- const solanaService = useSolanaService();
1580
- const [tokenBalance, setTokenBalance] = React3.useState(null);
1581
- const [isBalanceLoading, setIsBalanceLoading] = React3.useState(false);
1582
- const [isProcessing, setIsProcessing] = React3.useState(false);
1583
- const connection = React3.useMemo(() => {
1584
- const rpc = config.solanaRpcUrl ?? "https://api.mainnet-beta.solana.com";
1585
- return new web3_js.Connection(rpc);
1586
- }, [config.solanaRpcUrl]);
1587
- const fetchTokenBalance = React3.useCallback(async () => {
1588
- if (!connected || !publicKey || !selectedToken) {
1589
- setTokenBalance({ balance: 0, hasBalance: false });
1590
- return;
1591
- }
1592
- try {
1593
- setIsBalanceLoading(true);
1594
- const balances = await fetchSupportedTokenBalances(
1595
- connection,
1596
- publicKey,
1597
- supportedTokens
1598
- );
1599
- const balanceInfo = balances.find(
1600
- (tb) => tb.symbol === selectedToken.symbol || tb.mint === selectedToken.mint
1601
- );
1602
- const balance = balanceInfo?.balance || 0;
1603
- const hasBalanceFlag = hasSufficientBalance(balance, tokenAmount);
1604
- setTokenBalance({ balance, hasBalance: hasBalanceFlag });
1605
- console.log("payments-ui: Solana wallet balance", {
1606
- token: selectedToken.symbol,
1607
- balance,
1608
- required: tokenAmount
1609
- });
1610
- } catch (error) {
1611
- console.error("Failed to fetch token balance:", {
1612
- token: selectedToken?.symbol,
1613
- error
1614
- });
1615
- setTokenBalance({ balance: 0, hasBalance: false });
1616
- } finally {
1617
- setIsBalanceLoading(false);
1618
- }
1619
- }, [connected, publicKey, connection, selectedToken, tokenAmount, supportedTokens]);
1620
- React3.useEffect(() => {
1621
- if (connected && publicKey && selectedToken) {
1622
- void fetchTokenBalance();
1623
- }
1624
- }, [connected, publicKey, selectedToken, tokenAmount, fetchTokenBalance]);
1625
- const decodeTransaction = React3.useCallback((serialized) => {
1626
- const buffer$1 = buffer.Buffer.from(serialized, "base64");
1627
- try {
1628
- return web3_js.VersionedTransaction.deserialize(buffer$1);
1629
- } catch (err) {
1630
- try {
1631
- return web3_js.Transaction.from(buffer$1);
1632
- } catch (legacyErr) {
1633
- console.error("Failed to deserialize transaction", legacyErr);
1634
- throw new Error("Invalid transaction payload received from server");
1635
- }
1636
- }
1637
- }, []);
1638
- const isVersionedTransaction = (tx) => {
1639
- return !!tx && typeof tx === "object" && "version" in tx;
1640
- };
1641
- const signWithWallet = React3.useCallback(
1642
- async (tx) => {
1643
- if (!wallet) {
1644
- throw new Error("Wallet adapter is not available");
1645
- }
1646
- const adapter = wallet.adapter;
1647
- if (isVersionedTransaction(tx)) {
1648
- if (adapter.supportedTransactionVersions) {
1649
- const supported = adapter.supportedTransactionVersions;
1650
- if (!supported.has(tx.version)) {
1651
- throw new Error("Connected wallet does not support this transaction version");
1652
- }
1653
- }
1654
- if (adapter.signVersionedTransaction) {
1655
- return adapter.signVersionedTransaction(tx);
1656
- }
1657
- }
1658
- if (adapter.signTransaction) {
1659
- return adapter.signTransaction(tx);
1660
- }
1661
- if (signTransaction) {
1662
- return signTransaction(tx);
1663
- }
1664
- throw new Error("Connected wallet cannot sign transactions");
1665
- },
1666
- [wallet, signTransaction]
1667
- );
1668
- const pay = React3.useCallback(async () => {
1669
- if (!connected || !publicKey) {
1670
- onError("Wallet not connected");
1671
- return;
1672
- }
1673
- if (!selectedToken) {
1674
- onError("No payment token selected");
1675
- return;
1676
- }
1677
- if (!tokenBalance?.hasBalance) {
1678
- console.warn("payments-ui: insufficient balance for Solana direct payment", {
1679
- token: selectedToken.symbol
1680
- });
1681
- onError("Insufficient balance for this token");
1682
- return;
1683
- }
1684
- try {
1685
- setIsProcessing(true);
1686
- onStart();
1687
- console.log("payments-ui: initiating Solana direct payment", {
1688
- priceId,
1689
- token: selectedToken.symbol
1690
- });
1691
- const paymentData = await solanaService.generatePayment(
1692
- priceId,
1693
- selectedToken.symbol,
1694
- publicKey.toBase58()
1695
- );
1696
- console.log("payments-ui: Solana payment intent created", {
1697
- intentId: paymentData.intent_id
1698
- });
1699
- const transactionToSign = decodeTransaction(paymentData.transaction);
1700
- console.log("payments-ui: requesting Solana wallet signature");
1701
- const signedTx = await signWithWallet(transactionToSign);
1702
- const signedSerialized = buffer.Buffer.from(signedTx.serialize()).toString("base64");
1703
- onConfirming();
1704
- console.log("payments-ui: submitting signed Solana transaction");
1705
- const result = await solanaService.submitPayment(
1706
- signedSerialized,
1707
- priceId,
1708
- paymentData.intent_id,
1709
- `Payment for subscription - ${selectedToken.symbol}`
1710
- );
1711
- console.log("payments-ui: Solana direct payment confirmed", {
1712
- transactionId: result.transaction_id
1713
- });
1714
- onSuccess(result, result.transaction_id);
1715
- } catch (err) {
1716
- console.error("Solana direct payment failed:", {
1717
- priceId,
1718
- token: selectedToken.symbol,
1719
- error: err
1720
- });
1721
- let errorMessage = "Payment failed. Please try again.";
1722
- const message = err instanceof Error ? err.message : typeof err === "string" ? err : "";
1723
- if (message.includes("User rejected")) {
1724
- errorMessage = "Payment cancelled by user";
1725
- } else if (/insufficient\s+funds/i.test(message)) {
1726
- errorMessage = "Insufficient balance for this token";
1727
- } else if (message) {
1728
- errorMessage = message;
1729
- }
1730
- onError(errorMessage);
1731
- } finally {
1732
- setIsProcessing(false);
1733
- }
1734
- }, [
1735
- connected,
1736
- publicKey,
1737
- selectedToken,
1738
- tokenBalance?.hasBalance,
1739
- onError,
1740
- onStart,
1741
- solanaService,
1742
- priceId,
1743
- decodeTransaction,
1744
- signWithWallet,
1745
- onConfirming,
1746
- onSuccess
1747
- ]);
1748
- const balanceLabel = tokenBalance ? `${tokenBalance.balance.toFixed(4)} ${selectedToken?.symbol ?? ""}` : "--";
1749
- return {
1750
- isBalanceLoading,
1751
- isProcessing,
1752
- balanceLabel,
1753
- canPay: Boolean(
1754
- connected && tokenBalance?.hasBalance && !isProcessing
1755
- ),
1756
- pay
1757
- };
1758
- };
1759
- var Card = React3__namespace.forwardRef(
1760
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1761
- "div",
1762
- {
1763
- ref,
1764
- className: cn("rounded-xl border bg-card text-card-foreground shadow", className),
1765
- ...props
1766
- }
1767
- )
1768
- );
1769
- Card.displayName = "Card";
1770
- var CardHeader = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1771
- "div",
1772
- {
1773
- ref,
1774
- className: cn("flex flex-col space-y-1.5 p-6", className),
1775
- ...props
1776
- }
1777
- ));
1778
- CardHeader.displayName = "CardHeader";
1779
- var CardTitle = React3__namespace.forwardRef(
1780
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: cn("text-2xl font-semibold leading-none tracking-tight", className), ...props })
1781
- );
1782
- CardTitle.displayName = "CardTitle";
1783
- var CardDescription = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
1784
- CardDescription.displayName = "CardDescription";
1785
- var CardContent = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
1786
- CardContent.displayName = "CardContent";
1787
- var CardFooter = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1788
- "div",
1789
- {
1790
- ref,
1791
- className: cn("flex items-center p-6 pt-0", className),
1792
- ...props
1793
- }
1794
- ));
1795
- CardFooter.displayName = "CardFooter";
1796
- var DirectPayment = ({
1797
- priceId,
1798
- tokenAmount,
1799
- selectedToken,
1800
- supportedTokens,
1801
- onPaymentStart,
1802
- onPaymentConfirming,
1803
- onPaymentSuccess,
1804
- onPaymentError
1805
- }) => {
1806
- const { isBalanceLoading, balanceLabel, canPay, isProcessing, pay } = useSolanaDirectPayment({
1807
- priceId,
1808
- tokenAmount,
1809
- selectedToken,
1810
- supportedTokens,
1811
- onStart: onPaymentStart,
1812
- onConfirming: onPaymentConfirming,
1813
- onSuccess: onPaymentSuccess,
1814
- onError: onPaymentError
1815
- });
1816
- return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "space-y-4 rounded-md border border-border/60 bg-background/80 shadow-none p-6", children: [
1817
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
1818
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-2 text-sm font-semibold uppercase tracking-wide text-muted-foreground", children: [
1819
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "h-4 w-4" }),
1820
- " Pay with connected wallet"
1821
- ] }),
1822
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Sign the transaction directly in your Solana wallet." })
1823
- ] }),
1824
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between rounded-lg border border-border/50 bg-muted/10 px-4 py-3 text-sm", children: [
1825
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Available balance" }),
1826
- isBalanceLoading ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) : /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "text-foreground", children: balanceLabel })
1827
- ] }),
1828
- /* @__PURE__ */ jsxRuntime.jsx(
1829
- Button,
1830
- {
1831
- type: "button",
1832
- className: "w-full",
1833
- disabled: !canPay,
1834
- onClick: pay,
1835
- children: isProcessing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1836
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
1837
- " Processing\u2026"
1838
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1839
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "mr-2 h-4 w-4" }),
1840
- " Pay with wallet"
1841
- ] })
1842
- }
1843
- )
1844
- ] });
1845
- };
1846
1141
  var useSolanaQrPayment = (options) => {
1847
1142
  const { priceId, selectedToken, onSuccess, onError } = options;
1848
- const solanaService = useSolanaService();
1143
+ const { client } = usePaymentContext();
1849
1144
  const tokenSymbol = selectedToken?.symbol ?? null;
1850
- const onSuccessRef = React3.useRef(onSuccess);
1851
- const onErrorRef = React3.useRef(onError);
1852
- const [intent, setIntent] = React3.useState(null);
1853
- const [qrDataUri, setQrDataUri] = React3.useState(null);
1854
- const [isLoading, setIsLoading] = React3.useState(false);
1855
- const [error, setError] = React3.useState(null);
1856
- const [timeRemaining, setTimeRemaining] = React3.useState(0);
1857
- const [refreshNonce, setRefreshNonce] = React3.useState(0);
1858
- const pollRef = React3.useRef(null);
1859
- const countdownRef = React3.useRef(null);
1860
- const clearTimers = React3.useCallback(() => {
1145
+ const onSuccessRef = React17.useRef(onSuccess);
1146
+ const onErrorRef = React17.useRef(onError);
1147
+ const [intent, setIntent] = React17.useState(null);
1148
+ const [qrDataUri, setQrDataUri] = React17.useState(null);
1149
+ const [isLoading, setIsLoading] = React17.useState(false);
1150
+ const [error, setError] = React17.useState(null);
1151
+ const [timeRemaining, setTimeRemaining] = React17.useState(0);
1152
+ const [refreshNonce, setRefreshNonce] = React17.useState(0);
1153
+ const pollRef = React17.useRef(null);
1154
+ const countdownRef = React17.useRef(null);
1155
+ const clearTimers = React17.useCallback(() => {
1861
1156
  if (pollRef.current) {
1862
1157
  clearInterval(pollRef.current);
1863
1158
  pollRef.current = null;
@@ -1867,12 +1162,12 @@ var useSolanaQrPayment = (options) => {
1867
1162
  countdownRef.current = null;
1868
1163
  }
1869
1164
  }, []);
1870
- React3.useEffect(() => {
1165
+ React17.useEffect(() => {
1871
1166
  return () => {
1872
1167
  clearTimers();
1873
1168
  };
1874
1169
  }, [clearTimers]);
1875
- const resetState = React3.useCallback(
1170
+ const resetState = React17.useCallback(
1876
1171
  (message) => {
1877
1172
  clearTimers();
1878
1173
  setIntent(null);
@@ -1882,13 +1177,13 @@ var useSolanaQrPayment = (options) => {
1882
1177
  },
1883
1178
  [clearTimers]
1884
1179
  );
1885
- React3.useEffect(() => {
1180
+ React17.useEffect(() => {
1886
1181
  onSuccessRef.current = onSuccess;
1887
1182
  }, [onSuccess]);
1888
- React3.useEffect(() => {
1183
+ React17.useEffect(() => {
1889
1184
  onErrorRef.current = onError;
1890
1185
  }, [onError]);
1891
- const handleError = React3.useCallback(
1186
+ const handleError = React17.useCallback(
1892
1187
  (message, notifyParent = false) => {
1893
1188
  console.error("[payments-ui] Solana Pay QR error:", message);
1894
1189
  clearTimers();
@@ -1899,7 +1194,7 @@ var useSolanaQrPayment = (options) => {
1899
1194
  },
1900
1195
  [clearTimers, resetState]
1901
1196
  );
1902
- const handleSuccess = React3.useCallback(
1197
+ const handleSuccess = React17.useCallback(
1903
1198
  (status) => {
1904
1199
  clearTimers();
1905
1200
  resetState(null);
@@ -1907,14 +1202,16 @@ var useSolanaQrPayment = (options) => {
1907
1202
  paymentId: status.payment_id,
1908
1203
  intentId: status.intent_id
1909
1204
  });
1910
- onSuccessRef.current?.(status.payment_id, status.transaction || "");
1205
+ const paymentId = status.payment_id ?? void 0;
1206
+ const txId = status.transaction ?? void 0;
1207
+ onSuccessRef.current?.(paymentId, txId);
1911
1208
  },
1912
1209
  [clearTimers, resetState]
1913
1210
  );
1914
- const pollStatus = React3.useCallback(
1211
+ const pollStatus = React17.useCallback(
1915
1212
  async (reference) => {
1916
1213
  try {
1917
- const status = await solanaService.checkPaymentStatus(reference);
1214
+ const status = await client.getSolanaPayStatus(reference);
1918
1215
  if (status.status === "confirmed") {
1919
1216
  handleSuccess(status);
1920
1217
  }
@@ -1928,9 +1225,9 @@ var useSolanaQrPayment = (options) => {
1928
1225
  console.error("Failed to poll Solana Pay status:", err);
1929
1226
  }
1930
1227
  },
1931
- [handleError, handleSuccess, solanaService]
1228
+ [handleError, handleSuccess, client]
1932
1229
  );
1933
- const startCountdown = React3.useCallback(
1230
+ const startCountdown = React17.useCallback(
1934
1231
  (expiresAt, reference) => {
1935
1232
  const updateTime = () => {
1936
1233
  const remaining = Math.max(0, Math.floor(expiresAt - Date.now() / 1e3));
@@ -1945,7 +1242,7 @@ var useSolanaQrPayment = (options) => {
1945
1242
  },
1946
1243
  [handleError, pollStatus]
1947
1244
  );
1948
- const renderQr = React3.useCallback(async (qrIntent) => {
1245
+ const renderQr = React17.useCallback(async (qrIntent) => {
1949
1246
  try {
1950
1247
  const dataUri = await QRCode__default.default.toDataURL(qrIntent.url, {
1951
1248
  width: 320,
@@ -1961,7 +1258,7 @@ var useSolanaQrPayment = (options) => {
1961
1258
  handleError("Unable to render QR code");
1962
1259
  }
1963
1260
  }, [handleError]);
1964
- React3.useEffect(() => {
1261
+ React17.useEffect(() => {
1965
1262
  let cancelled = false;
1966
1263
  const generateIntent = async () => {
1967
1264
  clearTimers();
@@ -1977,10 +1274,10 @@ var useSolanaQrPayment = (options) => {
1977
1274
  priceId,
1978
1275
  token: tokenSymbol
1979
1276
  });
1980
- const nextIntent = await solanaService.generateQRCode(
1277
+ const nextIntent = await client.createSolanaPayIntent({
1981
1278
  priceId,
1982
- tokenSymbol
1983
- );
1279
+ token: tokenSymbol
1280
+ });
1984
1281
  if (cancelled) return;
1985
1282
  setIntent(nextIntent);
1986
1283
  setTimeRemaining(
@@ -1990,8 +1287,13 @@ var useSolanaQrPayment = (options) => {
1990
1287
  console.log("[payments-ui] Solana Pay QR ready", {
1991
1288
  reference: nextIntent.reference
1992
1289
  });
1993
- startCountdown(nextIntent.expires_at, nextIntent.reference);
1994
- pollStatus(nextIntent.reference);
1290
+ const reference = nextIntent.reference;
1291
+ if (typeof reference === "string" && reference.length > 0) {
1292
+ startCountdown(nextIntent.expires_at, reference);
1293
+ pollStatus(reference);
1294
+ } else {
1295
+ handleError("Payment reference missing from intent", true);
1296
+ }
1995
1297
  } catch (err) {
1996
1298
  if (cancelled) return;
1997
1299
  console.error("Failed to generate Solana Pay QR intent:", err);
@@ -2015,12 +1317,12 @@ var useSolanaQrPayment = (options) => {
2015
1317
  priceId,
2016
1318
  renderQr,
2017
1319
  resetState,
2018
- solanaService,
1320
+ client,
2019
1321
  startCountdown,
2020
1322
  tokenSymbol,
2021
1323
  refreshNonce
2022
1324
  ]);
2023
- const refresh = React3.useCallback(() => {
1325
+ const refresh = React17.useCallback(() => {
2024
1326
  setRefreshNonce((value) => value + 1);
2025
1327
  }, []);
2026
1328
  return {
@@ -2032,17 +1334,65 @@ var useSolanaQrPayment = (options) => {
2032
1334
  refresh
2033
1335
  };
2034
1336
  };
1337
+ var Card = React17__namespace.forwardRef(
1338
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1339
+ "div",
1340
+ {
1341
+ ref,
1342
+ className: cn("rounded-xl border border-white/10 bg-[#161b22] text-white shadow", className),
1343
+ ...props
1344
+ }
1345
+ )
1346
+ );
1347
+ Card.displayName = "Card";
1348
+ var CardHeader = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1349
+ "div",
1350
+ {
1351
+ ref,
1352
+ className: cn("flex flex-col space-y-1.5 p-6", className),
1353
+ ...props
1354
+ }
1355
+ ));
1356
+ CardHeader.displayName = "CardHeader";
1357
+ var CardTitle = React17__namespace.forwardRef(
1358
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: cn("text-xl font-semibold leading-none tracking-tight text-white", className), ...props })
1359
+ );
1360
+ CardTitle.displayName = "CardTitle";
1361
+ var CardDescription = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("text-sm text-white/60", className), ...props }));
1362
+ CardDescription.displayName = "CardDescription";
1363
+ var CardContent = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
1364
+ CardContent.displayName = "CardContent";
1365
+ var CardFooter = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1366
+ "div",
1367
+ {
1368
+ ref,
1369
+ className: cn("flex items-center p-6 pt-0", className),
1370
+ ...props
1371
+ }
1372
+ ));
1373
+ CardFooter.displayName = "CardFooter";
2035
1374
  var QRCodePayment = ({
2036
1375
  priceId,
2037
1376
  selectedToken,
2038
1377
  onPaymentError,
2039
1378
  onPaymentSuccess
2040
1379
  }) => {
1380
+ const handleQrSuccess = React17__namespace.default.useCallback(
1381
+ (paymentId, txId) => {
1382
+ if (!paymentId && !txId) {
1383
+ onPaymentError("Missing payment confirmation details");
1384
+ return;
1385
+ }
1386
+ const resolvedResult = paymentId ?? txId ?? "";
1387
+ onPaymentSuccess(resolvedResult, txId);
1388
+ },
1389
+ [onPaymentError, onPaymentSuccess]
1390
+ );
2041
1391
  const { intent, qrDataUri, isLoading, error, timeRemaining, refresh } = useSolanaQrPayment({
2042
1392
  priceId,
2043
1393
  selectedToken,
2044
1394
  onError: onPaymentError,
2045
- onSuccess: onPaymentSuccess
1395
+ onSuccess: handleQrSuccess
2046
1396
  });
2047
1397
  if (!selectedToken) {
2048
1398
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border border-dashed border-border/60 bg-muted/10 px-4 py-6 text-center text-sm text-muted-foreground", children: "Select a token to continue." });
@@ -2135,17 +1485,17 @@ var PaymentStatus = ({
2135
1485
  return null;
2136
1486
  };
2137
1487
  var useSupportedTokens = () => {
2138
- const solanaService = useSolanaService();
2139
- const [tokens, setTokens] = React3.useState([]);
2140
- const [isLoading, setIsLoading] = React3.useState(false);
2141
- const [error, setError] = React3.useState(null);
2142
- const [lastFetched, setLastFetched] = React3.useState(null);
1488
+ const { client } = usePaymentContext();
1489
+ const [tokens, setTokens] = React17.useState([]);
1490
+ const [isLoading, setIsLoading] = React17.useState(false);
1491
+ const [error, setError] = React17.useState(null);
1492
+ const [lastFetched, setLastFetched] = React17.useState(null);
2143
1493
  const CACHE_DURATION = 5 * 60 * 1e3;
2144
- const tokensRef = React3.useRef(tokens);
2145
- const lastFetchedRef = React3.useRef(lastFetched);
1494
+ const tokensRef = React17.useRef(tokens);
1495
+ const lastFetchedRef = React17.useRef(lastFetched);
2146
1496
  tokensRef.current = tokens;
2147
1497
  lastFetchedRef.current = lastFetched;
2148
- const fetchSupportedTokens = React3.useCallback(async () => {
1498
+ const fetchSupportedTokens = React17.useCallback(async () => {
2149
1499
  if (tokensRef.current.length > 0 && lastFetchedRef.current && Date.now() - lastFetchedRef.current < CACHE_DURATION) {
2150
1500
  return tokensRef.current;
2151
1501
  }
@@ -2153,7 +1503,7 @@ var useSupportedTokens = () => {
2153
1503
  setError(null);
2154
1504
  try {
2155
1505
  console.log("payments-ui: fetching supported Solana tokens");
2156
- const tokens2 = await solanaService.getSupportedTokens();
1506
+ const tokens2 = await client.getSolanaTokens();
2157
1507
  const sortedTokens = [...tokens2].sort(
2158
1508
  (a, b) => a.symbol.localeCompare(b.symbol)
2159
1509
  );
@@ -2171,51 +1521,51 @@ var useSupportedTokens = () => {
2171
1521
  } finally {
2172
1522
  setIsLoading(false);
2173
1523
  }
2174
- }, [solanaService]);
2175
- React3.useEffect(() => {
1524
+ }, [client]);
1525
+ React17.useEffect(() => {
2176
1526
  if (tokens.length === 0) {
2177
1527
  fetchSupportedTokens();
2178
1528
  }
2179
1529
  }, [tokens.length, fetchSupportedTokens]);
2180
- const getTokenBySymbol = React3.useCallback(
1530
+ const getTokenBySymbol = React17.useCallback(
2181
1531
  (symbol) => {
2182
1532
  return tokens.find((token) => token.symbol === symbol);
2183
1533
  },
2184
1534
  [tokens]
2185
1535
  );
2186
- const getTokenByMint = React3.useCallback(
1536
+ const getTokenByMint = React17.useCallback(
2187
1537
  (mintAddress) => {
2188
1538
  return tokens.find((token) => token.mint === mintAddress);
2189
1539
  },
2190
1540
  [tokens]
2191
1541
  );
2192
- const isTokenSupported = React3.useCallback(
1542
+ const isTokenSupported = React17.useCallback(
2193
1543
  (symbol) => {
2194
1544
  return tokens.some((token) => token.symbol === symbol);
2195
1545
  },
2196
1546
  [tokens]
2197
1547
  );
2198
- const getUSDCToken = React3.useCallback(() => {
1548
+ const getUSDCToken = React17.useCallback(() => {
2199
1549
  return getTokenBySymbol("USDC");
2200
1550
  }, [getTokenBySymbol]);
2201
- const getPYUSDToken = React3.useCallback(() => {
1551
+ const getPYUSDToken = React17.useCallback(() => {
2202
1552
  return getTokenBySymbol("PYUSD");
2203
1553
  }, [getTokenBySymbol]);
2204
- const getSOLToken = React3.useCallback(() => {
1554
+ const getSOLToken = React17.useCallback(() => {
2205
1555
  return getTokenBySymbol("SOL");
2206
1556
  }, [getTokenBySymbol]);
2207
- const getStablecoins = React3.useCallback(() => {
1557
+ const getStablecoins = React17.useCallback(() => {
2208
1558
  return tokens.filter((token) => ["USDC", "PYUSD"].includes(token.symbol));
2209
1559
  }, [tokens]);
2210
- const refreshTokens = React3.useCallback(async () => {
1560
+ const refreshTokens = React17.useCallback(async () => {
2211
1561
  setLastFetched(null);
2212
1562
  return await fetchSupportedTokens();
2213
1563
  }, [fetchSupportedTokens]);
2214
- const isCacheStale = React3.useCallback(() => {
1564
+ const isCacheStale = React17.useCallback(() => {
2215
1565
  if (!lastFetched) return true;
2216
1566
  return Date.now() - lastFetched > CACHE_DURATION;
2217
1567
  }, [lastFetched]);
2218
- const getTokenDisplayInfo = React3.useCallback((token) => {
1568
+ const getTokenDisplayInfo = React17.useCallback((token) => {
2219
1569
  return {
2220
1570
  ...token,
2221
1571
  displayName: `${token.name} (${token.symbol})`,
@@ -2223,7 +1573,7 @@ var useSupportedTokens = () => {
2223
1573
  decimalPlaces: token.decimals
2224
1574
  };
2225
1575
  }, []);
2226
- const getTokenPrice = React3.useCallback(
1576
+ const getTokenPrice = React17.useCallback(
2227
1577
  (symbol) => {
2228
1578
  const token = getTokenBySymbol(symbol);
2229
1579
  if (!token) return 0;
@@ -2232,7 +1582,7 @@ var useSupportedTokens = () => {
2232
1582
  },
2233
1583
  [getTokenBySymbol]
2234
1584
  );
2235
- const calculateTokenAmount = React3.useCallback(
1585
+ const calculateTokenAmount = React17.useCallback(
2236
1586
  (usdAmount, tokenSymbol) => {
2237
1587
  const token = getTokenBySymbol(tokenSymbol);
2238
1588
  const price = getTokenPrice(tokenSymbol);
@@ -2243,7 +1593,7 @@ var useSupportedTokens = () => {
2243
1593
  },
2244
1594
  [getTokenBySymbol, getTokenPrice]
2245
1595
  );
2246
- const formatTokenAmount = React3.useCallback(
1596
+ const formatTokenAmount = React17.useCallback(
2247
1597
  (amount, tokenSymbol) => {
2248
1598
  const token = getTokenBySymbol(tokenSymbol);
2249
1599
  if (!token) return "0";
@@ -2283,39 +1633,29 @@ var SolanaPaymentView = ({
2283
1633
  onError,
2284
1634
  onClose
2285
1635
  }) => {
2286
- const { connected } = walletAdapterReact.useWallet();
2287
1636
  const { notifyStatus, notifyError, notifySuccess } = usePaymentNotifications();
2288
- const [activeTab, setActiveTab] = React3.useState("wallet");
2289
- const [paymentState, setPaymentState] = React3.useState("selecting");
2290
- const [errorMessage, setErrorMessage] = React3.useState(null);
2291
- const [transactionId, setTransactionId] = React3.useState(null);
2292
- const [tokenAmount, setTokenAmount] = React3.useState(0);
2293
- const [selectedTokenSymbol, setSelectedTokenSymbol] = React3.useState(null);
1637
+ const [paymentState, setPaymentState] = React17.useState("selecting");
1638
+ const [errorMessage, setErrorMessage] = React17.useState(null);
1639
+ const [transactionId, setTransactionId] = React17.useState(null);
1640
+ const [tokenAmount, setTokenAmount] = React17.useState(0);
1641
+ const [selectedTokenSymbol, setSelectedTokenSymbol] = React17.useState(null);
2294
1642
  const {
2295
1643
  tokens,
2296
1644
  isLoading: tokensLoading,
2297
1645
  error: tokensError
2298
1646
  } = useSupportedTokens();
2299
- const selectedToken = React3.useMemo(() => {
1647
+ const selectedToken = React17.useMemo(() => {
2300
1648
  if (!tokens.length) return null;
2301
1649
  const explicit = tokens.find((token) => token.symbol === selectedTokenSymbol);
2302
1650
  return explicit || tokens[0];
2303
1651
  }, [tokens, selectedTokenSymbol]);
2304
- React3.useEffect(() => {
1652
+ React17.useEffect(() => {
2305
1653
  if (!selectedTokenSymbol && tokens.length) {
2306
1654
  const defaultToken = tokens.find((token) => token.symbol === "SOL") || tokens[0];
2307
1655
  setSelectedTokenSymbol(defaultToken.symbol);
2308
1656
  }
2309
1657
  }, [tokens, selectedTokenSymbol]);
2310
- const handlePaymentStart = React3.useCallback(() => {
2311
- setPaymentState("processing");
2312
- setErrorMessage(null);
2313
- notifyStatus("processing", { source: "solana" });
2314
- }, [notifyStatus]);
2315
- const handlePaymentConfirming = React3.useCallback(() => {
2316
- setPaymentState("confirming");
2317
- }, []);
2318
- const handlePaymentSuccess = React3.useCallback(
1658
+ const handlePaymentSuccess = React17.useCallback(
2319
1659
  (result, txId) => {
2320
1660
  const resolvedTx = txId || (typeof result === "string" ? result : result.transaction_id);
2321
1661
  setTransactionId(resolvedTx);
@@ -2343,7 +1683,7 @@ var SolanaPaymentView = ({
2343
1683
  },
2344
1684
  [notifyStatus, notifySuccess, onSuccess]
2345
1685
  );
2346
- const handlePaymentError = React3.useCallback(
1686
+ const handlePaymentError = React17.useCallback(
2347
1687
  (error) => {
2348
1688
  setPaymentState("error");
2349
1689
  setErrorMessage(error);
@@ -2353,22 +1693,22 @@ var SolanaPaymentView = ({
2353
1693
  },
2354
1694
  [notifyError, notifyStatus, onError]
2355
1695
  );
2356
- const resetState = React3.useCallback(() => {
1696
+ const resetState = React17.useCallback(() => {
2357
1697
  setPaymentState("selecting");
2358
1698
  setErrorMessage(null);
2359
1699
  setTransactionId(null);
2360
1700
  }, []);
2361
- const handleRetry = React3.useCallback(() => {
1701
+ const handleRetry = React17.useCallback(() => {
2362
1702
  resetState();
2363
1703
  }, [resetState]);
2364
- const handleClose = React3.useCallback(() => {
1704
+ const handleClose = React17.useCallback(() => {
2365
1705
  if (paymentState === "processing" || paymentState === "confirming") {
2366
1706
  return;
2367
1707
  }
2368
1708
  resetState();
2369
1709
  onClose?.();
2370
1710
  }, [paymentState, onClose, resetState]);
2371
- React3.useEffect(() => {
1711
+ React17.useEffect(() => {
2372
1712
  if (!selectedToken || usdAmount === 0) {
2373
1713
  setTokenAmount(0);
2374
1714
  return;
@@ -2380,19 +1720,9 @@ var SolanaPaymentView = ({
2380
1720
  }
2381
1721
  setTokenAmount(usdAmount / price);
2382
1722
  }, [usdAmount, selectedToken]);
2383
- const handleTokenChange = React3.useCallback((value) => {
1723
+ const handleTokenChange = React17.useCallback((value) => {
2384
1724
  setSelectedTokenSymbol(value);
2385
1725
  }, []);
2386
- const wasConnectedRef = React3.useRef(connected);
2387
- React3.useEffect(() => {
2388
- if (connected && !wasConnectedRef.current) {
2389
- setActiveTab("wallet");
2390
- }
2391
- if (!connected && wasConnectedRef.current) {
2392
- setActiveTab("qr");
2393
- }
2394
- wasConnectedRef.current = connected;
2395
- }, [connected]);
2396
1726
  const renderBody = () => {
2397
1727
  if (paymentState !== "selecting") {
2398
1728
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -2447,51 +1777,15 @@ var SolanaPaymentView = ({
2447
1777
  ] }, token.symbol)) })
2448
1778
  ] })
2449
1779
  ] }),
2450
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
2451
- Tabs,
1780
+ /* @__PURE__ */ jsxRuntime.jsx(
1781
+ QRCodePayment,
2452
1782
  {
2453
- value: activeTab,
2454
- onValueChange: (value) => setActiveTab(value),
2455
- className: "w-full space-y-3",
2456
- children: [
2457
- /* @__PURE__ */ jsxRuntime.jsxs(TabsList, { className: "grid w-full grid-cols-2 bg-muted/10", children: [
2458
- /* @__PURE__ */ jsxRuntime.jsxs(TabsTrigger, { value: "wallet", disabled: !connected, children: [
2459
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "mr-2 h-4 w-4" }),
2460
- " Wallet"
2461
- ] }),
2462
- /* @__PURE__ */ jsxRuntime.jsxs(TabsTrigger, { value: "qr", children: [
2463
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "mr-2 h-4 w-4" }),
2464
- " QR Code"
2465
- ] })
2466
- ] }),
2467
- /* @__PURE__ */ jsxRuntime.jsxs(TabsContent, { value: "wallet", className: "space-y-4", children: [
2468
- activeTab === "wallet" && /* @__PURE__ */ jsxRuntime.jsx(
2469
- DirectPayment,
2470
- {
2471
- priceId,
2472
- tokenAmount,
2473
- selectedToken,
2474
- supportedTokens: tokens,
2475
- onPaymentStart: handlePaymentStart,
2476
- onPaymentConfirming: handlePaymentConfirming,
2477
- onPaymentSuccess: handlePaymentSuccess,
2478
- onPaymentError: handlePaymentError
2479
- }
2480
- ),
2481
- !connected && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-amber-100", children: "Connect your Solana wallet to continue or switch to QR mode." })
2482
- ] }),
2483
- /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "qr", children: activeTab === "qr" && /* @__PURE__ */ jsxRuntime.jsx(
2484
- QRCodePayment,
2485
- {
2486
- priceId,
2487
- selectedToken,
2488
- onPaymentError: handlePaymentError,
2489
- onPaymentSuccess: handlePaymentSuccess
2490
- }
2491
- ) })
2492
- ]
1783
+ priceId,
1784
+ selectedToken,
1785
+ onPaymentError: handlePaymentError,
1786
+ onPaymentSuccess: handlePaymentSuccess
2493
1787
  }
2494
- ) })
1788
+ )
2495
1789
  ] });
2496
1790
  };
2497
1791
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
@@ -2499,7 +1793,7 @@ var SolanaPaymentView = ({
2499
1793
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
2500
1794
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs uppercase tracking-wide text-muted-foreground", children: "Solana Pay checkout" }),
2501
1795
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-2xl font-semibold text-foreground", children: "Pay with Solana" }),
2502
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Choose a supported token and send the payment with your wallet or a QR code." })
1796
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Choose a supported token and send the payment via Solana Pay QR code." })
2503
1797
  ] }),
2504
1798
  onClose && /* @__PURE__ */ jsxRuntime.jsxs(
2505
1799
  Button,
@@ -2520,143 +1814,6 @@ var SolanaPaymentView = ({
2520
1814
  renderBody()
2521
1815
  ] });
2522
1816
  };
2523
- var useSubscriptionActions = () => {
2524
- const { services } = usePaymentContext();
2525
- const ensurePrice = (priceId) => {
2526
- if (!priceId) {
2527
- throw new Error("payments-ui: priceId is required for subscription actions");
2528
- }
2529
- return priceId;
2530
- };
2531
- const subscribeWithCard = React3.useCallback(
2532
- async ({
2533
- priceId,
2534
- processor = "nmi",
2535
- provider,
2536
- paymentToken,
2537
- billing
2538
- }) => {
2539
- const payload = {
2540
- priceId: ensurePrice(priceId),
2541
- paymentToken,
2542
- processor,
2543
- provider,
2544
- email: billing.email,
2545
- firstName: billing.firstName,
2546
- lastName: billing.lastName,
2547
- address1: billing.address1,
2548
- city: billing.city,
2549
- state: billing.stateRegion,
2550
- zipCode: billing.postalCode,
2551
- country: billing.country
2552
- };
2553
- return services.subscriptions.subscribe("nmi", payload);
2554
- },
2555
- [services]
2556
- );
2557
- const subscribeWithSavedMethod = React3.useCallback(
2558
- async ({
2559
- priceId,
2560
- processor = "nmi",
2561
- provider,
2562
- paymentMethodId,
2563
- email
2564
- }) => {
2565
- const payload = {
2566
- priceId: ensurePrice(priceId),
2567
- paymentMethodId,
2568
- processor,
2569
- provider,
2570
- email
2571
- };
2572
- return services.subscriptions.subscribe("nmi", payload);
2573
- },
2574
- [services]
2575
- );
2576
- const subscribeWithCCBill = React3.useCallback(
2577
- async ({
2578
- priceId,
2579
- email,
2580
- firstName,
2581
- lastName,
2582
- zipCode,
2583
- country,
2584
- processor = "ccbill"
2585
- }) => {
2586
- const payload = {
2587
- priceId: ensurePrice(priceId),
2588
- email,
2589
- firstName,
2590
- lastName,
2591
- zipCode,
2592
- country,
2593
- processor
2594
- };
2595
- return services.subscriptions.subscribe("ccbill", payload);
2596
- },
2597
- [services]
2598
- );
2599
- const generateFlexFormUrl = React3.useCallback(
2600
- async ({
2601
- priceId,
2602
- firstName,
2603
- lastName,
2604
- address1,
2605
- city,
2606
- state,
2607
- zipCode,
2608
- country
2609
- }) => {
2610
- const payload = {
2611
- price_id: ensurePrice(priceId),
2612
- first_name: firstName,
2613
- last_name: lastName,
2614
- address1,
2615
- city,
2616
- state,
2617
- zip_code: zipCode,
2618
- country
2619
- };
2620
- return services.subscriptions.generateFlexFormUrl(payload);
2621
- },
2622
- [services]
2623
- );
2624
- return {
2625
- subscribeWithCard,
2626
- subscribeWithSavedMethod,
2627
- subscribeWithCCBill,
2628
- generateFlexFormUrl
2629
- };
2630
- };
2631
-
2632
- // src/hooks/useAlternativePaymentProvider.ts
2633
- var useAlternativePaymentProvider = () => {
2634
- const [isLoading, setIsLoading] = React3.useState(false);
2635
- const [error, setError] = React3.useState(null);
2636
- const { generateFlexFormUrl } = useSubscriptionActions();
2637
- const openFlexForm = React3.useCallback(
2638
- async (payload) => {
2639
- setIsLoading(true);
2640
- setError(null);
2641
- try {
2642
- const response = await generateFlexFormUrl(payload);
2643
- if (response?.iframe_url) {
2644
- window.location.href = response.iframe_url;
2645
- } else {
2646
- throw new Error("Unable to launch payment provider.");
2647
- }
2648
- } catch (err) {
2649
- const message = err instanceof Error ? err.message : "Failed to open payment provider.";
2650
- setError(message);
2651
- console.error("[payments-ui] failed to open alternative payment provider", err);
2652
- } finally {
2653
- setIsLoading(false);
2654
- }
2655
- },
2656
- [generateFlexFormUrl]
2657
- );
2658
- return { openFlexForm, isLoading, error };
2659
- };
2660
1817
  var PaymentExperience = ({
2661
1818
  priceId,
2662
1819
  usdAmount,
@@ -2665,7 +1822,6 @@ var PaymentExperience = ({
2665
1822
  enableNewCard = true,
2666
1823
  enableStoredMethods = true,
2667
1824
  enableSolanaPay = true,
2668
- enableAlternativePayments = true,
2669
1825
  onSolanaSuccess,
2670
1826
  onSolanaError,
2671
1827
  initialMode = "cards"
@@ -2673,27 +1829,20 @@ var PaymentExperience = ({
2673
1829
  const showNewCard = enableNewCard && Boolean(onNewCardPayment);
2674
1830
  const showStored = enableStoredMethods && Boolean(onSavedMethodPayment);
2675
1831
  const defaultTab = showStored ? "saved" : "new";
2676
- const [activeTab, setActiveTab] = React3.useState(defaultTab);
2677
- const [mode, setMode] = React3.useState(
1832
+ const [activeTab, setActiveTab] = React17.useState(defaultTab);
1833
+ const [mode, setMode] = React17.useState(
2678
1834
  () => initialMode === "solana" && enableSolanaPay ? "solana" : "cards"
2679
1835
  );
2680
- const [selectedMethodId, setSelectedMethodId] = React3.useState(null);
2681
- const [savedStatus, setSavedStatus] = React3.useState("idle");
2682
- const [savedError, setSavedError] = React3.useState(null);
2683
- const [newCardStatus, setNewCardStatus] = React3.useState("idle");
2684
- const [newCardError, setNewCardError] = React3.useState(null);
2685
- const [billingDetails, setBillingDetails] = React3.useState(null);
2686
- const [alternativePaymentError, setAlternativePaymentError] = React3.useState(null);
1836
+ const [selectedMethodId, setSelectedMethodId] = React17.useState(null);
1837
+ const [savedStatus, setSavedStatus] = React17.useState("idle");
1838
+ const [savedError, setSavedError] = React17.useState(null);
1839
+ const [newCardStatus, setNewCardStatus] = React17.useState("idle");
1840
+ const [newCardError, setNewCardError] = React17.useState(null);
2687
1841
  const { notifyStatus, notifySuccess, notifyError } = usePaymentNotifications();
2688
- const {
2689
- openFlexForm,
2690
- isLoading: flexFormLoading,
2691
- error: flexFormError
2692
- } = useAlternativePaymentProvider();
2693
- React3.useEffect(() => {
1842
+ React17.useEffect(() => {
2694
1843
  setActiveTab(showStored ? "saved" : "new");
2695
1844
  }, [showStored]);
2696
- React3.useEffect(() => {
1845
+ React17.useEffect(() => {
2697
1846
  if (!enableSolanaPay) {
2698
1847
  setMode("cards");
2699
1848
  return;
@@ -2704,12 +1853,12 @@ var PaymentExperience = ({
2704
1853
  setMode("cards");
2705
1854
  }
2706
1855
  }, [enableSolanaPay, initialMode]);
2707
- const handleMethodSelect = React3.useCallback((method) => {
1856
+ const handleMethodSelect = React17.useCallback((method) => {
2708
1857
  setSelectedMethodId(method.id);
2709
1858
  setSavedStatus("idle");
2710
1859
  setSavedError(null);
2711
1860
  }, []);
2712
- const handleSavedPayment = React3.useCallback(async () => {
1861
+ const handleSavedPayment = React17.useCallback(async () => {
2713
1862
  if (!onSavedMethodPayment || !selectedMethodId) return;
2714
1863
  try {
2715
1864
  setSavedStatus("processing");
@@ -2729,7 +1878,7 @@ var PaymentExperience = ({
2729
1878
  notifyError(message);
2730
1879
  }
2731
1880
  }, [notifyError, notifyStatus, onSavedMethodPayment, selectedMethodId, usdAmount]);
2732
- const handleNewCardTokenize = React3.useCallback(
1881
+ const handleNewCardTokenize = React17.useCallback(
2733
1882
  async (token, billing) => {
2734
1883
  if (!onNewCardPayment) return;
2735
1884
  try {
@@ -2749,68 +1898,26 @@ var PaymentExperience = ({
2749
1898
  },
2750
1899
  [notifyError, notifyStatus, onNewCardPayment]
2751
1900
  );
2752
- const showSolanaView = React3.useCallback(() => {
1901
+ const showSolanaView = React17.useCallback(() => {
2753
1902
  if (!enableSolanaPay) return;
2754
1903
  setMode("solana");
2755
1904
  }, [enableSolanaPay]);
2756
- const exitSolanaView = React3.useCallback(() => {
1905
+ const exitSolanaView = React17.useCallback(() => {
2757
1906
  setMode("cards");
2758
1907
  }, []);
2759
- const handleSolanaSuccess = React3.useCallback(
1908
+ const handleSolanaSuccess = React17.useCallback(
2760
1909
  (result) => {
2761
1910
  onSolanaSuccess?.(result);
2762
1911
  exitSolanaView();
2763
1912
  },
2764
1913
  [exitSolanaView, onSolanaSuccess]
2765
1914
  );
2766
- const handleSolanaError = React3.useCallback(
1915
+ const handleSolanaError = React17.useCallback(
2767
1916
  (error) => {
2768
1917
  onSolanaError?.(error);
2769
1918
  },
2770
1919
  [onSolanaError]
2771
1920
  );
2772
- const handleAlternativePayment = React3.useCallback(() => {
2773
- if (!enableAlternativePayments || !priceId) {
2774
- return;
2775
- }
2776
- if (!billingDetails) {
2777
- setAlternativePaymentError("Enter your billing details first.");
2778
- return;
2779
- }
2780
- const requiredFields = [
2781
- "firstName",
2782
- "lastName",
2783
- "address1",
2784
- "city",
2785
- "stateRegion",
2786
- "postalCode",
2787
- "country"
2788
- ];
2789
- const missingField = requiredFields.find((field) => {
2790
- const value = billingDetails[field];
2791
- return typeof value !== "string" || value.trim().length === 0;
2792
- });
2793
- if (missingField) {
2794
- setAlternativePaymentError("Please complete your billing address before continuing.");
2795
- return;
2796
- }
2797
- setAlternativePaymentError(null);
2798
- openFlexForm({
2799
- priceId,
2800
- firstName: billingDetails.firstName,
2801
- lastName: billingDetails.lastName,
2802
- address1: billingDetails.address1,
2803
- city: billingDetails.city,
2804
- state: billingDetails.stateRegion ?? "",
2805
- zipCode: billingDetails.postalCode,
2806
- country: billingDetails.country
2807
- });
2808
- }, [
2809
- billingDetails,
2810
- enableAlternativePayments,
2811
- openFlexForm,
2812
- priceId
2813
- ]);
2814
1921
  const renderSavedTab = () => {
2815
1922
  if (!showStored) {
2816
1923
  return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Saved payment methods are unavailable right now. Add a new card to get started." });
@@ -2849,8 +1956,7 @@ var PaymentExperience = ({
2849
1956
  submitLabel: "Pay now",
2850
1957
  externalError: newCardError,
2851
1958
  onTokenize: handleNewCardTokenize,
2852
- submitting: newCardStatus === "processing",
2853
- onBillingChange: setBillingDetails
1959
+ submitting: newCardStatus === "processing"
2854
1960
  }
2855
1961
  );
2856
1962
  };
@@ -2878,19 +1984,6 @@ var PaymentExperience = ({
2878
1984
  ] });
2879
1985
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6 pt-4", children: [
2880
1986
  mode === "cards" && renderCardExperience(),
2881
- mode === "cards" && enableAlternativePayments && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 text-center text-sm text-muted-foreground", children: [
2882
- /* @__PURE__ */ jsxRuntime.jsx(
2883
- "button",
2884
- {
2885
- type: "button",
2886
- className: "text-primary underline-offset-4 hover:underline disabled:opacity-60",
2887
- onClick: handleAlternativePayment,
2888
- disabled: flexFormLoading || !priceId,
2889
- children: flexFormLoading ? "Preparing alternative checkout\u2026" : "Prefer a different processor? Pay with CCBill"
2890
- }
2891
- ),
2892
- (alternativePaymentError || flexFormError) && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: alternativePaymentError || flexFormError })
2893
- ] }),
2894
1987
  mode === "solana" && enableSolanaPay && /* @__PURE__ */ jsxRuntime.jsx(
2895
1988
  SolanaPaymentView,
2896
1989
  {
@@ -2931,6 +2024,88 @@ var SubscriptionSuccessDialog = ({
2931
2024
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-6", children: /* @__PURE__ */ jsxRuntime.jsx(Button, { className: "w-full", onClick: onClose, children: "Continue exploring" }) })
2932
2025
  ] }) });
2933
2026
  };
2027
+ var useSubscriptionActions = () => {
2028
+ const { client } = usePaymentContext();
2029
+ const ensurePrice = (priceId) => {
2030
+ if (!priceId) {
2031
+ throw new Error("payments-ui: priceId is required for subscription actions");
2032
+ }
2033
+ return priceId;
2034
+ };
2035
+ const subscribeWithCard = React17.useCallback(
2036
+ async ({
2037
+ priceId,
2038
+ processor = "nmi",
2039
+ provider,
2040
+ paymentToken,
2041
+ billing
2042
+ }) => {
2043
+ const payload = {
2044
+ price_id: ensurePrice(priceId),
2045
+ processor,
2046
+ provider,
2047
+ payment_token: paymentToken,
2048
+ email: billing.email,
2049
+ first_name: billing.firstName,
2050
+ last_name: billing.lastName,
2051
+ address1: billing.address1,
2052
+ city: billing.city,
2053
+ state: billing.stateRegion,
2054
+ zip: billing.postalCode,
2055
+ country: billing.country
2056
+ };
2057
+ return client.checkout(payload);
2058
+ },
2059
+ [client]
2060
+ );
2061
+ const subscribeWithSavedMethod = React17.useCallback(
2062
+ async ({
2063
+ priceId,
2064
+ processor = "nmi",
2065
+ provider,
2066
+ paymentMethodId,
2067
+ email
2068
+ }) => {
2069
+ const payload = {
2070
+ price_id: ensurePrice(priceId),
2071
+ processor,
2072
+ provider,
2073
+ payment_method_id: paymentMethodId,
2074
+ email
2075
+ };
2076
+ return client.checkout(payload);
2077
+ },
2078
+ [client]
2079
+ );
2080
+ const subscribeWithCCBill = React17.useCallback(
2081
+ async ({
2082
+ priceId,
2083
+ email,
2084
+ firstName,
2085
+ lastName,
2086
+ zipCode,
2087
+ country,
2088
+ processor = "ccbill"
2089
+ }) => {
2090
+ const payload = {
2091
+ price_id: ensurePrice(priceId),
2092
+ processor,
2093
+ email,
2094
+ first_name: firstName,
2095
+ last_name: lastName,
2096
+ zip: zipCode,
2097
+ country
2098
+ };
2099
+ return client.checkout(payload);
2100
+ },
2101
+ [client]
2102
+ );
2103
+ return {
2104
+ subscribeWithCard,
2105
+ subscribeWithSavedMethod,
2106
+ subscribeWithCCBill
2107
+ };
2108
+ };
2934
2109
  var SubscriptionCheckoutModal = ({
2935
2110
  open,
2936
2111
  onOpenChange,
@@ -2947,9 +2122,9 @@ var SubscriptionCheckoutModal = ({
2947
2122
  onSolanaError,
2948
2123
  initialMode = "cards"
2949
2124
  }) => {
2950
- const [showSuccess, setShowSuccess] = React3.useState(false);
2125
+ const [showSuccess, setShowSuccess] = React17.useState(false);
2951
2126
  const { subscribeWithCard, subscribeWithSavedMethod } = useSubscriptionActions();
2952
- const handleClose = React3.useCallback(
2127
+ const handleClose = React17.useCallback(
2953
2128
  (nextOpen) => {
2954
2129
  onOpenChange(nextOpen);
2955
2130
  if (!nextOpen) setShowSuccess(false);
@@ -2967,22 +2142,32 @@ var SubscriptionCheckoutModal = ({
2967
2142
  console.debug("[payments-ui] subscription success", result);
2968
2143
  }
2969
2144
  };
2145
+ const assertCheckoutSuccess = (status, message) => {
2146
+ if (status === "blocked") {
2147
+ throw new Error(message || "This subscription cannot be completed right now.");
2148
+ }
2149
+ if (status === "redirect_required") {
2150
+ throw new Error(message || "Additional action required in an alternate flow.");
2151
+ }
2152
+ };
2970
2153
  const handleNewCardPayment = async ({ token, billing }) => {
2971
- await subscribeWithCard({
2154
+ const response = await subscribeWithCard({
2972
2155
  priceId: ensurePrice(),
2973
2156
  provider,
2974
2157
  paymentToken: token,
2975
2158
  billing
2976
2159
  });
2160
+ assertCheckoutSuccess(response.status, response.message);
2977
2161
  notifySuccess();
2978
2162
  };
2979
2163
  const handleSavedMethodPayment = async ({ paymentMethodId }) => {
2980
- await subscribeWithSavedMethod({
2164
+ const response = await subscribeWithSavedMethod({
2981
2165
  priceId: ensurePrice(),
2982
2166
  provider,
2983
2167
  paymentMethodId,
2984
2168
  email: userEmail ?? ""
2985
2169
  });
2170
+ assertCheckoutSuccess(response.status, response.message);
2986
2171
  notifySuccess();
2987
2172
  };
2988
2173
  const solanaSuccess = (result) => {
@@ -2994,27 +2179,33 @@ var SubscriptionCheckoutModal = ({
2994
2179
  onSolanaError?.(error);
2995
2180
  };
2996
2181
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2997
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsx(DialogContent, { className: "w-full max-w-3xl max-h-[90vh] overflow-y-auto rounded-md border border-border/60 bg-background p-0 [&::-webkit-scrollbar]:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 space-y-6", children: [
2998
- !priceId && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [
2999
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-4 w-4" }),
3000
- " Select a subscription plan to continue."
3001
- ] }),
3002
- /* @__PURE__ */ jsxRuntime.jsx(
3003
- PaymentExperience,
3004
- {
3005
- usdAmount,
3006
- priceId: priceId ?? "",
3007
- onSolanaSuccess: solanaSuccess,
3008
- onSolanaError: solanaError,
3009
- enableNewCard: Boolean(priceId),
3010
- enableStoredMethods: Boolean(priceId),
3011
- enableSolanaPay: enableSolanaPay && Boolean(priceId),
3012
- onNewCardPayment: priceId ? handleNewCardPayment : void 0,
3013
- onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0,
3014
- initialMode
3015
- }
3016
- )
3017
- ] }) }) }),
2182
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsx(
2183
+ DialogContent,
2184
+ {
2185
+ className: "max-w-3xl max-h-[90vh] overflow-y-auto p-0 [&::-webkit-scrollbar]:hidden",
2186
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 space-y-6", children: [
2187
+ !priceId && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [
2188
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-4 w-4" }),
2189
+ " Select a subscription plan to continue."
2190
+ ] }),
2191
+ /* @__PURE__ */ jsxRuntime.jsx(
2192
+ PaymentExperience,
2193
+ {
2194
+ usdAmount,
2195
+ priceId: priceId ?? "",
2196
+ onSolanaSuccess: solanaSuccess,
2197
+ onSolanaError: solanaError,
2198
+ enableNewCard: Boolean(priceId),
2199
+ enableStoredMethods: Boolean(priceId),
2200
+ enableSolanaPay: enableSolanaPay && Boolean(priceId),
2201
+ onNewCardPayment: priceId ? handleNewCardPayment : void 0,
2202
+ onSavedMethodPayment: priceId ? handleSavedMethodPayment : void 0,
2203
+ initialMode
2204
+ }
2205
+ )
2206
+ ] })
2207
+ }
2208
+ ) }),
3018
2209
  /* @__PURE__ */ jsxRuntime.jsx(
3019
2210
  SubscriptionSuccessDialog,
3020
2211
  {
@@ -3040,7 +2231,7 @@ var wallets = [
3040
2231
  }
3041
2232
  ];
3042
2233
  var WalletModal = ({ open, onOpenChange }) => {
3043
- const [expandedWallet, setExpandedWallet] = React3.useState(null);
2234
+ const [expandedWallet, setExpandedWallet] = React17.useState(null);
3044
2235
  return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "w-full max-w-lg max-h-[90vh] overflow-y-auto rounded-md border border-border/70 bg-background/95 p-0 shadow-2xl [&::-webkit-scrollbar]:hidden", children: [
3045
2236
  /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { className: "border-b border-border/40 bg-gradient-to-r from-primary/10 via-background to-background px-6 py-5 text-left", children: [
3046
2237
  /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: "flex items-center gap-2 text-foreground", children: [
@@ -3096,17 +2287,17 @@ var createDialogState = () => ({
3096
2287
  isOpen: false,
3097
2288
  props: null
3098
2289
  });
3099
- var PaymentsDialogContext = React3.createContext(void 0);
2290
+ var PaymentsDialogContext = React17.createContext(void 0);
3100
2291
  var PaymentsDialogProvider = ({
3101
2292
  children
3102
2293
  }) => {
3103
- const [checkoutState, setCheckoutState] = React3.useState(
2294
+ const [checkoutState, setCheckoutState] = React17.useState(
3104
2295
  () => createDialogState()
3105
2296
  );
3106
- const [walletState, setWalletState] = React3.useState(
2297
+ const [walletState, setWalletState] = React17.useState(
3107
2298
  () => createDialogState()
3108
2299
  );
3109
- const contextValue = React3.useMemo(() => {
2300
+ const contextValue = React17.useMemo(() => {
3110
2301
  const openCheckout = (options) => setCheckoutState({
3111
2302
  isOpen: true,
3112
2303
  props: options
@@ -3160,28 +2351,65 @@ var PaymentsDialogProvider = ({
3160
2351
  ] });
3161
2352
  };
3162
2353
  var usePaymentDialogs = () => {
3163
- const context = React3.useContext(PaymentsDialogContext);
2354
+ const context = React17.useContext(PaymentsDialogContext);
3164
2355
  if (!context) {
3165
2356
  throw new Error("usePaymentDialogs must be used within PaymentProvider");
3166
2357
  }
3167
2358
  return context;
3168
2359
  };
3169
- var PaymentContext = React3.createContext(void 0);
2360
+ var PaymentContext = React17.createContext(void 0);
3170
2361
  var PaymentProvider = ({
3171
2362
  config,
3172
- runtime: runtimeProp,
3173
2363
  children
3174
2364
  }) => {
3175
- const runtime = React3.useMemo(
3176
- () => runtimeProp ?? createPaymentsRuntime(config),
3177
- [runtimeProp, config]
3178
- );
3179
- const solanaEndpoint = React3.useMemo(() => {
2365
+ const queryClient = React17.useMemo(() => {
2366
+ return new reactQuery.QueryClient({
2367
+ defaultOptions: {
2368
+ queries: {
2369
+ staleTime: 3e4,
2370
+ gcTime: 5 * 6e4,
2371
+ refetchOnWindowFocus: false,
2372
+ retry: 1
2373
+ },
2374
+ mutations: {
2375
+ retry: 1
2376
+ }
2377
+ }
2378
+ });
2379
+ }, []);
2380
+ const client = React17.useMemo(() => {
2381
+ const authProvider = config.getAuthToken ? async () => {
2382
+ try {
2383
+ const result = config.getAuthToken?.();
2384
+ if (result instanceof Promise) {
2385
+ return await result ?? null;
2386
+ }
2387
+ return result ?? null;
2388
+ } catch (error) {
2389
+ console.warn("payments-ui: failed to resolve auth token", error);
2390
+ return null;
2391
+ }
2392
+ } : void 0;
2393
+ const wrappedFetch = config.fetcher ? ((input, init) => {
2394
+ const normalizedInput = input instanceof URL ? input.toString() : input;
2395
+ return config.fetcher(normalizedInput, init);
2396
+ }) : void 0;
2397
+ return createClient({
2398
+ billingBaseUrl: config.endpoints.billingBaseUrl,
2399
+ billingBasePath: config.endpoints.billingBasePath,
2400
+ accountBaseUrl: config.endpoints.accountBaseUrl,
2401
+ accountBasePath: config.endpoints.accountBasePath,
2402
+ getAuthToken: authProvider,
2403
+ defaultHeaders: config.defaultHeaders,
2404
+ fetch: wrappedFetch
2405
+ });
2406
+ }, [config]);
2407
+ const solanaEndpoint = React17.useMemo(() => {
3180
2408
  if (config.solana?.endpoint) return config.solana.endpoint;
3181
- const network = config.solana?.network ?? WalletAdapterNetwork.Mainnet;
2409
+ const network = config.solana?.network ?? walletAdapterBase.WalletAdapterNetwork.Mainnet;
3182
2410
  return web3_js.clusterApiUrl(network);
3183
2411
  }, [config.solana?.endpoint, config.solana?.network]);
3184
- const walletAdapters = React3.useMemo(() => {
2412
+ const walletAdapters = React17.useMemo(() => {
3185
2413
  if (config.solana?.wallets?.length) {
3186
2414
  return config.solana.wallets;
3187
2415
  }
@@ -3193,29 +2421,60 @@ var PaymentProvider = ({
3193
2421
  ];
3194
2422
  }, [config.solana?.wallets]);
3195
2423
  const autoConnect = config.solana?.autoConnect ?? true;
3196
- const value = React3.useMemo(() => {
2424
+ const value = React17.useMemo(() => {
3197
2425
  return {
3198
- config: runtime.config,
3199
- fetcher: runtime.app.getFetcher(),
3200
- resolveAuthToken: runtime.app.resolveAuthToken,
3201
- app: runtime.app,
3202
- services: runtime.services,
3203
- queryClient: runtime.queryClient
2426
+ config,
2427
+ client,
2428
+ queryClient
3204
2429
  };
3205
- }, [runtime]);
3206
- React3.useEffect(() => {
2430
+ }, [client, config, queryClient]);
2431
+ React17.useEffect(() => {
3207
2432
  if (!config.collectJsKey) return;
3208
2433
  loadCollectJs(config.collectJsKey);
3209
2434
  }, [config.collectJsKey]);
3210
- return /* @__PURE__ */ jsxRuntime.jsx(PaymentContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: runtime.queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReact.ConnectionProvider, { endpoint: solanaEndpoint, config: { commitment: "confirmed" }, children: /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReact.WalletProvider, { wallets: walletAdapters, autoConnect, children: /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReactUi.WalletModalProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(PaymentsDialogProvider, { children }) }) }) }) }) });
2435
+ return /* @__PURE__ */ jsxRuntime.jsx(PaymentContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReact.ConnectionProvider, { endpoint: solanaEndpoint, config: { commitment: "confirmed" }, children: /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReact.WalletProvider, { wallets: walletAdapters, autoConnect, children: /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReactUi.WalletModalProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(PaymentsDialogProvider, { children }) }) }) }) }) });
3211
2436
  };
3212
2437
  var usePaymentContext = () => {
3213
- const context = React3.useContext(PaymentContext);
2438
+ const context = React17.useContext(PaymentContext);
3214
2439
  if (!context) {
3215
2440
  throw new Error("usePaymentContext must be used within a PaymentProvider");
3216
2441
  }
3217
2442
  return context;
3218
2443
  };
2444
+ var PaymentsUIRoot = ({
2445
+ children,
2446
+ className,
2447
+ dark = false
2448
+ }) => {
2449
+ return /* @__PURE__ */ jsxRuntime.jsx(
2450
+ "div",
2451
+ {
2452
+ className: cn(
2453
+ "payments-ui-root",
2454
+ dark && "dark",
2455
+ className
2456
+ ),
2457
+ children
2458
+ }
2459
+ );
2460
+ };
2461
+ var PaymentsUIPortalRoot = ({
2462
+ children,
2463
+ className,
2464
+ dark = false
2465
+ }) => {
2466
+ return /* @__PURE__ */ jsxRuntime.jsx(
2467
+ "div",
2468
+ {
2469
+ className: cn(
2470
+ "payments-ui-portal",
2471
+ dark && "dark",
2472
+ className
2473
+ ),
2474
+ children
2475
+ }
2476
+ );
2477
+ };
3219
2478
  var SolanaPaymentSelector = ({
3220
2479
  isOpen,
3221
2480
  onClose,
@@ -3223,7 +2482,7 @@ var SolanaPaymentSelector = ({
3223
2482
  }) => {
3224
2483
  return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isOpen, onOpenChange: (value) => value ? void 0 : onClose(), children: /* @__PURE__ */ jsxRuntime.jsx(DialogContent, { className: "w-full max-w-2xl max-h-[90vh] overflow-y-auto rounded-md border border-border/70 bg-background/95 p-0 shadow-2xl [&::-webkit-scrollbar]:hidden", children: /* @__PURE__ */ jsxRuntime.jsx(SolanaPaymentView, { ...props, onClose }) }) });
3225
2484
  };
3226
- var Table = React3__namespace.forwardRef(
2485
+ var Table = React17__namespace.forwardRef(
3227
2486
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3228
2487
  "table",
3229
2488
  {
@@ -3234,15 +2493,15 @@ var Table = React3__namespace.forwardRef(
3234
2493
  )
3235
2494
  );
3236
2495
  Table.displayName = "Table";
3237
- var TableHeader = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
2496
+ var TableHeader = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
3238
2497
  TableHeader.displayName = "TableHeader";
3239
- var TableBody = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props }));
2498
+ var TableBody = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props }));
3240
2499
  TableBody.displayName = "TableBody";
3241
- var TableFooter = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tfoot", { ref, className: cn("bg-muted/50 font-medium text-muted-foreground", className), ...props }));
2500
+ var TableFooter = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tfoot", { ref, className: cn("bg-muted/50 font-medium text-muted-foreground", className), ...props }));
3242
2501
  TableFooter.displayName = "TableFooter";
3243
- var TableRow = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tr", { ref, className: cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className), ...props }));
2502
+ var TableRow = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tr", { ref, className: cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className), ...props }));
3244
2503
  TableRow.displayName = "TableRow";
3245
- var TableHead = React3__namespace.forwardRef(
2504
+ var TableHead = React17__namespace.forwardRef(
3246
2505
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3247
2506
  "th",
3248
2507
  {
@@ -3256,7 +2515,7 @@ var TableHead = React3__namespace.forwardRef(
3256
2515
  )
3257
2516
  );
3258
2517
  TableHead.displayName = "TableHead";
3259
- var TableCell = React3__namespace.forwardRef(
2518
+ var TableCell = React17__namespace.forwardRef(
3260
2519
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3261
2520
  "td",
3262
2521
  {
@@ -3267,37 +2526,37 @@ var TableCell = React3__namespace.forwardRef(
3267
2526
  )
3268
2527
  );
3269
2528
  TableCell.displayName = "TableCell";
3270
- var TableCaption = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("caption", { ref, className: cn("mt-4 text-sm text-muted-foreground", className), ...props }));
2529
+ var TableCaption = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("caption", { ref, className: cn("mt-4 text-sm text-muted-foreground", className), ...props }));
3271
2530
  TableCaption.displayName = "TableCaption";
3272
2531
  var AlertDialog = AlertDialogPrimitive__namespace.Root;
3273
2532
  var AlertDialogTrigger = AlertDialogPrimitive__namespace.Trigger;
3274
2533
  var AlertDialogPortal = AlertDialogPrimitive__namespace.Portal;
3275
- var AlertDialogOverlay = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2534
+ var AlertDialogOverlay = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3276
2535
  AlertDialogPrimitive__namespace.Overlay,
3277
2536
  {
3278
2537
  ref,
3279
2538
  className: cn(
3280
- "fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0",
2539
+ "fixed inset-0 z-50 bg-black/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0",
3281
2540
  className
3282
2541
  ),
3283
2542
  ...props
3284
2543
  }
3285
2544
  ));
3286
2545
  AlertDialogOverlay.displayName = AlertDialogPrimitive__namespace.Overlay.displayName;
3287
- var AlertDialogContent = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogPortal, { children: [
2546
+ var AlertDialogContent = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(AlertDialogPortal, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payments-ui-portal", children: [
3288
2547
  /* @__PURE__ */ jsxRuntime.jsx(AlertDialogOverlay, {}),
3289
2548
  /* @__PURE__ */ jsxRuntime.jsx(
3290
2549
  AlertDialogPrimitive__namespace.Content,
3291
2550
  {
3292
2551
  ref,
3293
2552
  className: cn(
3294
- "fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-border bg-popover p-6 text-popover-foreground shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
2553
+ "fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-white/10 bg-[#161b22] text-white p-6 shadow-lg rounded-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
3295
2554
  className
3296
2555
  ),
3297
2556
  ...props
3298
2557
  }
3299
2558
  )
3300
- ] }));
2559
+ ] }) }));
3301
2560
  AlertDialogContent.displayName = AlertDialogPrimitive__namespace.Content.displayName;
3302
2561
  var AlertDialogHeader = ({
3303
2562
  className,
@@ -3315,13 +2574,13 @@ var AlertDialogFooter = ({
3315
2574
  }
3316
2575
  );
3317
2576
  AlertDialogFooter.displayName = "AlertDialogFooter";
3318
- var AlertDialogTitle = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(AlertDialogPrimitive__namespace.Title, { ref, className: cn("text-lg font-semibold", className), ...props }));
2577
+ var AlertDialogTitle = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(AlertDialogPrimitive__namespace.Title, { ref, className: cn("text-lg font-semibold text-white", className), ...props }));
3319
2578
  AlertDialogTitle.displayName = AlertDialogPrimitive__namespace.Title.displayName;
3320
- var AlertDialogDescription = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(AlertDialogPrimitive__namespace.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
2579
+ var AlertDialogDescription = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(AlertDialogPrimitive__namespace.Description, { ref, className: cn("text-sm text-white/60", className), ...props }));
3321
2580
  AlertDialogDescription.displayName = AlertDialogPrimitive__namespace.Description.displayName;
3322
- var AlertDialogAction = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(AlertDialogPrimitive__namespace.Action, { ref, className: cn(buttonVariants(), className), ...props }));
2581
+ var AlertDialogAction = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(AlertDialogPrimitive__namespace.Action, { ref, className: cn(buttonVariants(), className), ...props }));
3323
2582
  AlertDialogAction.displayName = AlertDialogPrimitive__namespace.Action.displayName;
3324
- var AlertDialogCancel = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
2583
+ var AlertDialogCancel = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3325
2584
  AlertDialogPrimitive__namespace.Cancel,
3326
2585
  {
3327
2586
  ref,
@@ -3330,7 +2589,7 @@ var AlertDialogCancel = React3__namespace.forwardRef(({ className, ...props }, r
3330
2589
  }
3331
2590
  ));
3332
2591
  AlertDialogCancel.displayName = AlertDialogPrimitive__namespace.Cancel.displayName;
3333
- var Textarea = React3__namespace.forwardRef(
2592
+ var Textarea = React17__namespace.forwardRef(
3334
2593
  ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3335
2594
  "textarea",
3336
2595
  {
@@ -3348,19 +2607,39 @@ var notifyDefault = (payload) => {
3348
2607
  const level = payload.status === "destructive" ? "error" : "info";
3349
2608
  console[level === "error" ? "error" : "log"]("[payments-ui] cancellation", payload);
3350
2609
  };
2610
+ var defaultTranslations = {
2611
+ buttonLabel: "Cancel Membership",
2612
+ title: "Confirm Membership Cancellation",
2613
+ description: "You are about to cancel your membership. Please review the consequences:",
2614
+ consequence1: "You will immediately lose access to premium features upon confirmation.",
2615
+ consequence2: "Your benefits remain active until the end of the billing cycle.",
2616
+ consequence3: "Your account will revert to the free plan afterwards.",
2617
+ reasonLabel: "Please provide a reason for cancellation (required):",
2618
+ reasonPlaceholder: "Your feedback helps us improve...",
2619
+ reasonError: "Reason must be at least {min} characters long.",
2620
+ reasonHint: "Minimum {min} characters required.",
2621
+ keepMembership: "Keep Membership",
2622
+ confirmCancellation: "Confirm Cancellation",
2623
+ cancelling: "Cancelling...",
2624
+ membershipCancelled: "Membership cancelled",
2625
+ cancellationSuccess: "Your subscription has been cancelled successfully.",
2626
+ cancellationFailed: "Cancellation failed"
2627
+ };
3351
2628
  var CancelMembershipDialog = ({
3352
2629
  minReasonLength = 15,
3353
2630
  onCancelled,
3354
- onNotify
2631
+ onNotify,
2632
+ translations: customTranslations
3355
2633
  }) => {
3356
- const { services } = usePaymentContext();
2634
+ const { client } = usePaymentContext();
3357
2635
  const notify = onNotify ?? notifyDefault;
3358
- const [cancelReason, setCancelReason] = React3.useState("");
3359
- const [isOpen, setIsOpen] = React3.useState(false);
3360
- const [isReasonValid, setIsReasonValid] = React3.useState(false);
3361
- const [hasInteracted, setHasInteracted] = React3.useState(false);
3362
- const [isSubmitting, setIsSubmitting] = React3.useState(false);
3363
- React3.useEffect(() => {
2636
+ const t = { ...defaultTranslations, ...customTranslations };
2637
+ const [cancelReason, setCancelReason] = React17.useState("");
2638
+ const [isOpen, setIsOpen] = React17.useState(false);
2639
+ const [isReasonValid, setIsReasonValid] = React17.useState(false);
2640
+ const [hasInteracted, setHasInteracted] = React17.useState(false);
2641
+ const [isSubmitting, setIsSubmitting] = React17.useState(false);
2642
+ React17.useEffect(() => {
3364
2643
  const trimmed = cancelReason.trim();
3365
2644
  setIsReasonValid(trimmed.length >= minReasonLength);
3366
2645
  }, [cancelReason, minReasonLength]);
@@ -3386,17 +2665,17 @@ var CancelMembershipDialog = ({
3386
2665
  }
3387
2666
  setIsSubmitting(true);
3388
2667
  try {
3389
- await services.subscriptions.cancelSubscription(cancelReason.trim());
2668
+ await client.cancelSubscription(cancelReason.trim());
3390
2669
  notify({
3391
- title: "Membership cancelled",
3392
- description: "Your subscription has been cancelled successfully.",
2670
+ title: t.membershipCancelled,
2671
+ description: t.cancellationSuccess,
3393
2672
  status: "success"
3394
2673
  });
3395
2674
  onCancelled?.();
3396
2675
  handleOpenChange(false);
3397
2676
  } catch (error) {
3398
2677
  const message = error instanceof Error ? error.message : "Unable to cancel membership";
3399
- notify({ title: "Cancellation failed", description: message, status: "destructive" });
2678
+ notify({ title: t.cancellationFailed, description: message, status: "destructive" });
3400
2679
  } finally {
3401
2680
  setIsSubmitting(false);
3402
2681
  }
@@ -3405,32 +2684,34 @@ var CancelMembershipDialog = ({
3405
2684
  return /* @__PURE__ */ jsxRuntime.jsxs(AlertDialog, { open: isOpen, onOpenChange: handleOpenChange, children: [
3406
2685
  /* @__PURE__ */ jsxRuntime.jsx(AlertDialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", className: "border-destructive/50 text-destructive", children: [
3407
2686
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ban, { className: "mr-2 h-4 w-4" }),
3408
- " Cancel Membership"
2687
+ " ",
2688
+ t.buttonLabel
3409
2689
  ] }) }),
3410
2690
  /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogContent, { className: "max-h-[90vh] overflow-y-auto rounded-md border border-border bg-background", children: [
3411
2691
  /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogHeader, { children: [
3412
2692
  /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogTitle, { className: "flex items-center gap-2 text-lg font-semibold", children: [
3413
2693
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TriangleAlert, { className: "h-5 w-5 text-destructive" }),
3414
- " Confirm Membership Cancellation"
2694
+ " ",
2695
+ t.title
3415
2696
  ] }),
3416
2697
  /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogDescription, { className: "mt-3 space-y-3 text-muted-foreground", children: [
3417
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "You are about to cancel your membership. Please review the consequences:" }),
2698
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: t.description }),
3418
2699
  /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "list-disc space-y-1 pl-5 text-sm", children: [
3419
- /* @__PURE__ */ jsxRuntime.jsx("li", { children: "You will immediately lose access to premium features upon confirmation." }),
3420
- /* @__PURE__ */ jsxRuntime.jsx("li", { children: "Your benefits remain active until the end of the billing cycle." }),
3421
- /* @__PURE__ */ jsxRuntime.jsx("li", { children: "Your account will revert to the free plan afterwards." })
2700
+ /* @__PURE__ */ jsxRuntime.jsx("li", { children: t.consequence1 }),
2701
+ /* @__PURE__ */ jsxRuntime.jsx("li", { children: t.consequence2 }),
2702
+ /* @__PURE__ */ jsxRuntime.jsx("li", { children: t.consequence3 })
3422
2703
  ] })
3423
2704
  ] })
3424
2705
  ] }),
3425
2706
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "my-4 space-y-2 py-2", children: [
3426
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "cancelReason", className: "text-sm font-medium", children: "Please provide a reason for cancellation (required):" }),
2707
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "cancelReason", className: "text-sm font-medium", children: t.reasonLabel }),
3427
2708
  /* @__PURE__ */ jsxRuntime.jsx(
3428
2709
  Textarea,
3429
2710
  {
3430
2711
  id: "cancelReason",
3431
2712
  value: cancelReason,
3432
2713
  onChange: handleReasonChange,
3433
- placeholder: "Your feedback helps us improve...",
2714
+ placeholder: t.reasonPlaceholder,
3434
2715
  className: cn(
3435
2716
  "w-full resize-none border-border bg-background",
3436
2717
  showError && "border-destructive"
@@ -3445,19 +2726,19 @@ var CancelMembershipDialog = ({
3445
2726
  {
3446
2727
  id: "reason-hint",
3447
2728
  className: `text-xs ${showError ? "text-destructive" : "text-muted-foreground"}`,
3448
- children: showError ? `Reason must be at least ${minReasonLength} characters long.` : `Minimum ${minReasonLength} characters required.`
2729
+ children: showError ? t.reasonError.replace("{min}", String(minReasonLength)) : t.reasonHint.replace("{min}", String(minReasonLength))
3449
2730
  }
3450
2731
  )
3451
2732
  ] }),
3452
2733
  /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogFooter, { className: "mt-6 gap-2", children: [
3453
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogCancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", className: "border-border text-muted-foreground", children: "Keep Membership" }) }),
2734
+ /* @__PURE__ */ jsxRuntime.jsx(AlertDialogCancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", className: "border-border text-muted-foreground", children: t.keepMembership }) }),
3454
2735
  /* @__PURE__ */ jsxRuntime.jsx(AlertDialogAction, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
3455
2736
  Button,
3456
2737
  {
3457
2738
  className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
3458
2739
  onClick: handleConfirm,
3459
2740
  disabled: !isReasonValid || isSubmitting,
3460
- children: isSubmitting ? "Cancelling..." : "Confirm Cancellation"
2741
+ children: isSubmitting ? t.cancelling : t.confirmCancellation
3461
2742
  }
3462
2743
  ) })
3463
2744
  ] })
@@ -3468,22 +2749,47 @@ var notifyDefault2 = (payload) => {
3468
2749
  const level = payload.status === "destructive" ? "error" : "info";
3469
2750
  console[level === "error" ? "error" : "log"]("[payments-ui] billing", payload);
3470
2751
  };
2752
+ var defaultTranslations2 = {
2753
+ title: "Transaction History",
2754
+ description: "Record of billing history",
2755
+ reviewActivity: "Review your account activity below",
2756
+ loading: "Loading...",
2757
+ error: "Error loading billing history.",
2758
+ loadingMore: "Loading more...",
2759
+ reference: "Reference",
2760
+ date: "Date",
2761
+ amount: "Amount",
2762
+ processor: "Processor",
2763
+ status: "Status"
2764
+ };
3471
2765
  var BillingHistory = ({
3472
2766
  pageSize = 10,
3473
2767
  initialPage = 1,
3474
2768
  enableCancel = true,
3475
- onNotify
2769
+ onNotify,
2770
+ translations: customTranslations
3476
2771
  }) => {
3477
- const { services } = usePaymentContext();
2772
+ const { client } = usePaymentContext();
3478
2773
  const notify = onNotify ?? notifyDefault2;
3479
- const [isExpanded, setIsExpanded] = React3.useState(false);
3480
- const observerRef = React3.useRef(null);
3481
- const loadMoreRef = React3.useRef(null);
2774
+ const t = { ...defaultTranslations2, ...customTranslations };
2775
+ const [isExpanded, setIsExpanded] = React17.useState(false);
2776
+ const observerRef = React17.useRef(null);
2777
+ const loadMoreRef = React17.useRef(null);
3482
2778
  const historyQuery = reactQuery.useInfiniteQuery({
3483
2779
  queryKey: ["payments-ui", "billing-history", pageSize],
3484
2780
  queryFn: async ({ pageParam = initialPage }) => {
3485
2781
  const offset = (pageParam - 1) * pageSize;
3486
- return services.subscriptions.getPaymentHistory({ limit: pageSize, offset });
2782
+ return client.getPaymentHistory({ limit: pageSize, offset, type: void 0 }).then(
2783
+ (response) => ({
2784
+ data: response.data,
2785
+ total_items: response.total,
2786
+ limit: response.limit,
2787
+ offset: response.offset,
2788
+ page: response.limit > 0 ? Math.floor(response.offset / response.limit) + 1 : 1,
2789
+ page_size: response.limit,
2790
+ total_pages: response.limit > 0 ? Math.ceil(response.total / response.limit) : void 0
2791
+ })
2792
+ );
3487
2793
  },
3488
2794
  initialPageParam: initialPage,
3489
2795
  getNextPageParam: (lastPage) => {
@@ -3495,7 +2801,7 @@ var BillingHistory = ({
3495
2801
  },
3496
2802
  staleTime: 5 * 60 * 1e3
3497
2803
  });
3498
- React3.useEffect(() => {
2804
+ React17.useEffect(() => {
3499
2805
  if (!loadMoreRef.current || !isExpanded) return;
3500
2806
  observerRef.current = new IntersectionObserver((entries) => {
3501
2807
  const [entry] = entries;
@@ -3510,7 +2816,7 @@ var BillingHistory = ({
3510
2816
  observerRef.current?.disconnect();
3511
2817
  };
3512
2818
  }, [historyQuery, isExpanded, notify]);
3513
- const payments = React3.useMemo(() => {
2819
+ const payments = React17.useMemo(() => {
3514
2820
  const data = historyQuery.data;
3515
2821
  return data?.pages ?? [];
3516
2822
  }, [historyQuery.data]);
@@ -3532,8 +2838,8 @@ var BillingHistory = ({
3532
2838
  return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "border-0 bg-background/5 shadow-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 sm:p-6", children: [
3533
2839
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex cursor-pointer items-center justify-between", onClick: () => setIsExpanded((prev) => !prev), children: [
3534
2840
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3535
- /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "text-xl font-semibold", children: "Transaction History" }),
3536
- /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: "Record of billing history" })
2841
+ /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "text-xl font-semibold", children: t.title }),
2842
+ /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: t.description })
3537
2843
  ] }),
3538
2844
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn("h-5 w-5 text-muted-foreground transition-transform", isExpanded && "rotate-180") })
3539
2845
  ] }),
@@ -3546,16 +2852,16 @@ var BillingHistory = ({
3546
2852
  ),
3547
2853
  children: /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: "p-0 pt-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
3548
2854
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between", children: [
3549
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Review your account activity below" }),
2855
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: t.reviewActivity }),
3550
2856
  enableCancel && /* @__PURE__ */ jsxRuntime.jsx(CancelMembershipDialog, { onNotify: notify })
3551
2857
  ] }),
3552
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[300px] overflow-y-auto rounded-lg border border-border/70", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: historyQuery.isLoading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "p-4 text-center text-sm text-muted-foreground", children: "Loading..." }) : historyQuery.isError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "p-4 text-center text-sm text-destructive", children: "Error loading billing history." }) : /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
2858
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[300px] overflow-y-auto rounded-lg border border-border/70", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: historyQuery.isLoading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "p-4 text-center text-sm text-muted-foreground", children: t.loading }) : historyQuery.isError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "p-4 text-center text-sm text-destructive", children: t.error }) : /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
3553
2859
  /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { className: "border-border/60", children: [
3554
- /* @__PURE__ */ jsxRuntime.jsx(TableHead, { children: "Reference" }),
3555
- /* @__PURE__ */ jsxRuntime.jsx(TableHead, { children: "Date" }),
3556
- /* @__PURE__ */ jsxRuntime.jsx(TableHead, { children: "Amount" }),
3557
- /* @__PURE__ */ jsxRuntime.jsx(TableHead, { children: "Processor" }),
3558
- /* @__PURE__ */ jsxRuntime.jsx(TableHead, { children: "Status" })
2860
+ /* @__PURE__ */ jsxRuntime.jsx(TableHead, { children: t.reference }),
2861
+ /* @__PURE__ */ jsxRuntime.jsx(TableHead, { children: t.date }),
2862
+ /* @__PURE__ */ jsxRuntime.jsx(TableHead, { children: t.amount }),
2863
+ /* @__PURE__ */ jsxRuntime.jsx(TableHead, { children: t.processor }),
2864
+ /* @__PURE__ */ jsxRuntime.jsx(TableHead, { children: t.status })
3559
2865
  ] }) }),
3560
2866
  /* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: payments.map(
3561
2867
  (page) => page.data.map((payment) => /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { className: "border-border/40", children: [
@@ -3567,7 +2873,7 @@ var BillingHistory = ({
3567
2873
  ] }, payment.id))
3568
2874
  ) })
3569
2875
  ] }) }) }),
3570
- /* @__PURE__ */ jsxRuntime.jsx("div", { ref: loadMoreRef, className: "h-10 w-full", children: historyQuery.isFetchingNextPage && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-center text-sm text-muted-foreground", children: "Loading more..." }) })
2876
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: loadMoreRef, className: "h-10 w-full", children: historyQuery.isFetchingNextPage && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-center text-sm text-muted-foreground", children: t.loadingMore }) })
3571
2877
  ] }) })
3572
2878
  }
3573
2879
  )
@@ -3582,19 +2888,56 @@ var notifyDefault3 = (payload) => {
3582
2888
  const level = payload.status === "destructive" ? "error" : "info";
3583
2889
  console[level === "error" ? "error" : "log"]("[payments-ui] notification", payload);
3584
2890
  };
2891
+ var defaultTranslations3 = {
2892
+ title: "Payment Methods",
2893
+ description: "Manage your saved billing cards",
2894
+ addCard: "Add card",
2895
+ loadingCards: "Loading cards...",
2896
+ noPaymentMethods: "No saved payment methods yet.",
2897
+ addedOn: "Added on",
2898
+ active: "Active",
2899
+ inactive: "Inactive",
2900
+ replaceCard: "Replace card",
2901
+ makeDefault: "Make default",
2902
+ defaultMethod: "Default method",
2903
+ remove: "Remove",
2904
+ addNewCard: "Add a new card",
2905
+ addNewCardDescription: "Your card details are tokenized securely via our payment provider.",
2906
+ saveCard: "Save card",
2907
+ replaceCardTitle: "Replace card",
2908
+ replaceCardDescription: "Update this card with new billing details.",
2909
+ cardAddedSuccess: "Card added successfully",
2910
+ unableToAddCard: "Unable to add card",
2911
+ cardRemoved: "Card removed",
2912
+ unableToRemoveCard: "Unable to remove card",
2913
+ cardUpdated: "Card updated",
2914
+ unableToReplaceCard: "Unable to replace card",
2915
+ defaultPaymentMethodUpdated: "Default payment method updated",
2916
+ unableToSetDefault: "Unable to set default payment method"
2917
+ };
3585
2918
  var PaymentMethodsSection = ({
3586
2919
  isAuthenticated = true,
3587
2920
  userEmail,
3588
2921
  provider = "mobius",
3589
2922
  defaultCountry = "US",
3590
2923
  collectPrefix = "account-card",
3591
- onNotify
2924
+ onNotify,
2925
+ translations: customTranslations
3592
2926
  }) => {
3593
- const paymentMethods = usePaymentMethodService();
2927
+ const { client } = usePaymentContext();
3594
2928
  const queryClient = reactQuery.useQueryClient();
3595
- const [isModalOpen, setIsModalOpen] = React3.useState(false);
3596
- const [deletingId, setDeletingId] = React3.useState(null);
2929
+ const paymentMethods = {
2930
+ list: (params) => client.listPaymentMethods({ limit: params.pageSize }),
2931
+ create: (payload) => client.createPaymentMethod(payload),
2932
+ update: (id, payload) => client.updatePaymentMethod(id, payload),
2933
+ remove: (id) => client.deletePaymentMethod(id),
2934
+ activate: (id) => client.activatePaymentMethod(id)
2935
+ };
2936
+ const [isModalOpen, setIsModalOpen] = React17.useState(false);
2937
+ const [deletingId, setDeletingId] = React17.useState(null);
2938
+ const [methodBeingReplaced, setMethodBeingReplaced] = React17.useState(null);
3597
2939
  const notify = onNotify ?? notifyDefault3;
2940
+ const t = { ...defaultTranslations3, ...customTranslations };
3598
2941
  const queryKey = ["payments-ui", "payment-methods"];
3599
2942
  const paymentQuery = reactQuery.useQuery({
3600
2943
  queryKey,
@@ -3605,13 +2948,13 @@ var PaymentMethodsSection = ({
3605
2948
  const createMutation = reactQuery.useMutation({
3606
2949
  mutationFn: (payload) => paymentMethods.create(payload),
3607
2950
  onSuccess: () => {
3608
- notify({ title: "Card added successfully", status: "success" });
2951
+ notify({ title: t.cardAddedSuccess, status: "success" });
3609
2952
  setIsModalOpen(false);
3610
2953
  void queryClient.invalidateQueries({ queryKey });
3611
2954
  },
3612
2955
  onError: (error) => {
3613
2956
  notify({
3614
- title: "Unable to add card",
2957
+ title: t.unableToAddCard,
3615
2958
  description: error.message,
3616
2959
  status: "destructive"
3617
2960
  });
@@ -3621,68 +2964,104 @@ var PaymentMethodsSection = ({
3621
2964
  mutationFn: (id) => paymentMethods.remove(id),
3622
2965
  onMutate: (id) => setDeletingId(id),
3623
2966
  onSuccess: () => {
3624
- notify({ title: "Card removed", status: "success" });
2967
+ notify({ title: t.cardRemoved, status: "success" });
3625
2968
  void queryClient.invalidateQueries({ queryKey });
3626
2969
  },
3627
2970
  onError: (error) => {
3628
2971
  notify({
3629
- title: "Unable to remove card",
2972
+ title: t.unableToRemoveCard,
3630
2973
  description: error.message,
3631
2974
  status: "destructive"
3632
2975
  });
3633
2976
  },
3634
2977
  onSettled: () => setDeletingId(null)
3635
2978
  });
3636
- React3.useEffect(() => {
2979
+ const replaceMutation = reactQuery.useMutation({
2980
+ mutationFn: ({ id, payload }) => paymentMethods.update(id, payload),
2981
+ onSuccess: () => {
2982
+ notify({ title: t.cardUpdated, status: "success" });
2983
+ setMethodBeingReplaced(null);
2984
+ void queryClient.invalidateQueries({ queryKey });
2985
+ },
2986
+ onError: (error) => {
2987
+ notify({
2988
+ title: t.unableToReplaceCard,
2989
+ description: error.message,
2990
+ status: "destructive"
2991
+ });
2992
+ }
2993
+ });
2994
+ const activateMutation = reactQuery.useMutation({
2995
+ mutationFn: (id) => paymentMethods.activate(id),
2996
+ onSuccess: () => {
2997
+ notify({ title: t.defaultPaymentMethodUpdated, status: "success" });
2998
+ void queryClient.invalidateQueries({ queryKey });
2999
+ },
3000
+ onError: (error) => {
3001
+ notify({
3002
+ title: t.unableToSetDefault,
3003
+ description: error.message,
3004
+ status: "destructive"
3005
+ });
3006
+ }
3007
+ });
3008
+ React17.useEffect(() => {
3637
3009
  if (!isModalOpen) {
3638
3010
  createMutation.reset();
3639
3011
  }
3640
3012
  }, [createMutation, isModalOpen]);
3641
- const payments = React3.useMemo(() => paymentQuery.data?.data ?? [], [paymentQuery.data]);
3013
+ const payments = React17.useMemo(() => paymentQuery.data?.data ?? [], [paymentQuery.data]);
3642
3014
  const loading = paymentQuery.isLoading || paymentQuery.isFetching;
3015
+ const buildPayload = (token, billing) => ({
3016
+ payment_token: token,
3017
+ first_name: billing.firstName,
3018
+ last_name: billing.lastName,
3019
+ address1: billing.address1,
3020
+ address2: billing.address2,
3021
+ city: billing.city,
3022
+ state: billing.stateRegion,
3023
+ zip: billing.postalCode,
3024
+ country: billing.country,
3025
+ email: billing.email,
3026
+ provider: billing.provider
3027
+ });
3643
3028
  const handleCardTokenize = (token, billing) => {
3644
- const payload = {
3645
- payment_token: token,
3646
- first_name: billing.firstName,
3647
- last_name: billing.lastName,
3648
- address1: billing.address1,
3649
- address2: billing.address2,
3650
- city: billing.city,
3651
- state: billing.stateRegion,
3652
- zip: billing.postalCode,
3653
- country: billing.country,
3654
- email: billing.email,
3655
- provider: billing.provider
3656
- };
3657
- createMutation.mutate(payload);
3029
+ createMutation.mutate(buildPayload(token, billing));
3030
+ };
3031
+ const handleReplaceTokenize = (token, billing) => {
3032
+ if (!methodBeingReplaced) return;
3033
+ replaceMutation.mutate({ id: methodBeingReplaced.id, payload: buildPayload(token, billing) });
3658
3034
  };
3659
- return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "border-0 bg-background/5 shadow-lg", children: [
3035
+ return /* @__PURE__ */ jsxRuntime.jsxs(Card, { children: [
3660
3036
  /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "flex flex-col gap-4 md:flex-row md:items-center md:justify-between", children: [
3661
3037
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3662
- /* @__PURE__ */ jsxRuntime.jsxs(CardTitle, { className: "flex items-center gap-2 text-xl", children: [
3663
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.WalletCards, { className: "h-5 w-5 text-primary" }),
3664
- " Payment Methods"
3038
+ /* @__PURE__ */ jsxRuntime.jsxs(CardTitle, { className: "flex items-center gap-2", children: [
3039
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.WalletCards, { className: "h-5 w-5 text-emerald-400" }),
3040
+ " ",
3041
+ t.title
3665
3042
  ] }),
3666
- /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: "Manage your saved billing cards" })
3043
+ /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: t.description })
3667
3044
  ] }),
3668
3045
  /* @__PURE__ */ jsxRuntime.jsxs(Button, { onClick: () => setIsModalOpen(true), children: [
3669
3046
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "mr-2 h-4 w-4" }),
3670
- " Add card"
3047
+ " ",
3048
+ t.addCard
3671
3049
  ] })
3672
3050
  ] }),
3673
- /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: "space-y-4", children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center py-10 text-muted-foreground", children: [
3051
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: "space-y-4", children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center py-10 text-white/60", children: [
3674
3052
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-5 w-5 animate-spin" }),
3675
- " Loading cards..."
3676
- ] }) : payments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-dashed border-border/60 bg-muted/10 p-6 text-sm text-muted-foreground", children: "No saved payment methods yet." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: payments.map((method) => /* @__PURE__ */ jsxRuntime.jsxs(
3053
+ " ",
3054
+ t.loadingCards
3055
+ ] }) : payments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-dashed border-white/20 bg-white/5 p-6 text-sm text-white/60", children: t.noPaymentMethods }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: payments.map((method) => /* @__PURE__ */ jsxRuntime.jsxs(
3677
3056
  "div",
3678
3057
  {
3679
- className: "rounded-lg border border-border/80 bg-background/40 p-4 shadow-sm",
3058
+ className: "rounded-lg border border-white/10 bg-white/5 p-4 shadow-sm",
3680
3059
  children: [
3681
3060
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 md:flex-row md:items-center md:justify-between", children: [
3682
3061
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3683
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-base font-medium text-foreground", children: formatCardLabel2(method) }),
3684
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
3685
- "Added on",
3062
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-base font-medium text-white", children: formatCardLabel2(method) }),
3063
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-white/60", children: [
3064
+ t.addedOn,
3686
3065
  " ",
3687
3066
  method.created_at ? new Date(method.created_at).toLocaleDateString() : "unknown date"
3688
3067
  ] })
@@ -3692,34 +3071,60 @@ var PaymentMethodsSection = ({
3692
3071
  Badge,
3693
3072
  {
3694
3073
  variant: method.is_active ? "default" : "secondary",
3695
- className: method.is_active ? "bg-emerald-500/20 text-emerald-400" : "",
3696
- children: method.is_active ? "Active" : "Inactive"
3074
+ children: method.is_active ? t.active : t.inactive
3697
3075
  }
3698
3076
  ),
3699
3077
  method.failure_reason && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "destructive", children: method.failure_reason })
3700
3078
  ] })
3701
3079
  ] }),
3702
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
3703
- Button,
3704
- {
3705
- variant: "ghost",
3706
- className: "text-destructive hover:text-destructive",
3707
- disabled: deletingId === method.id && deleteMutation.isPending,
3708
- onClick: () => deleteMutation.mutate(method.id),
3709
- children: [
3710
- deletingId === method.id && deleteMutation.isPending ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "mr-2 h-4 w-4" }),
3711
- "Remove"
3712
- ]
3713
- }
3714
- ) })
3080
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex flex-wrap gap-2", children: [
3081
+ /* @__PURE__ */ jsxRuntime.jsxs(
3082
+ Button,
3083
+ {
3084
+ variant: "ghost",
3085
+ className: "text-blue-400",
3086
+ disabled: replaceMutation.isPending && methodBeingReplaced?.id === method.id,
3087
+ onClick: () => setMethodBeingReplaced(method),
3088
+ children: [
3089
+ replaceMutation.isPending && methodBeingReplaced?.id === method.id ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "mr-2 h-4 w-4" }),
3090
+ t.replaceCard
3091
+ ]
3092
+ }
3093
+ ),
3094
+ /* @__PURE__ */ jsxRuntime.jsxs(
3095
+ Button,
3096
+ {
3097
+ variant: "outline",
3098
+ disabled: method.is_active || activateMutation.isPending,
3099
+ onClick: () => activateMutation.mutate(method.id),
3100
+ children: [
3101
+ activateMutation.isPending ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
3102
+ method.is_active ? t.defaultMethod : t.makeDefault
3103
+ ]
3104
+ }
3105
+ ),
3106
+ /* @__PURE__ */ jsxRuntime.jsxs(
3107
+ Button,
3108
+ {
3109
+ variant: "ghost",
3110
+ className: "text-red-400 hover:text-red-300",
3111
+ disabled: deletingId === method.id && deleteMutation.isPending,
3112
+ onClick: () => deleteMutation.mutate(method.id),
3113
+ children: [
3114
+ deletingId === method.id && deleteMutation.isPending ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "mr-2 h-4 w-4" }),
3115
+ t.remove
3116
+ ]
3117
+ }
3118
+ )
3119
+ ] })
3715
3120
  ]
3716
3121
  },
3717
3122
  method.id
3718
3123
  )) }) }),
3719
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isModalOpen, onOpenChange: setIsModalOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-h-[95vh] overflow-y-auto border border-border bg-background", children: [
3124
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isModalOpen, onOpenChange: setIsModalOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-h-[95vh] overflow-y-auto", children: [
3720
3125
  /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
3721
- /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Add a new card" }),
3722
- /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "Your card details are tokenized securely via our payment provider." })
3126
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: t.addNewCard }),
3127
+ /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: t.addNewCardDescription })
3723
3128
  ] }),
3724
3129
  /* @__PURE__ */ jsxRuntime.jsx(
3725
3130
  CardDetailsForm,
@@ -3727,7 +3132,7 @@ var PaymentMethodsSection = ({
3727
3132
  visible: isModalOpen,
3728
3133
  collectPrefix,
3729
3134
  submitting: createMutation.isPending,
3730
- submitLabel: "Save card",
3135
+ submitLabel: t.saveCard,
3731
3136
  defaultValues: {
3732
3137
  email: userEmail ?? "",
3733
3138
  country: defaultCountry,
@@ -3735,640 +3140,36 @@ var PaymentMethodsSection = ({
3735
3140
  },
3736
3141
  externalError: createMutation.error?.message ?? null,
3737
3142
  onTokenize: handleCardTokenize,
3738
- className: "rounded-2xl border border-border bg-muted/20 p-6"
3143
+ className: "rounded-2xl border border-white/10 bg-white/5 p-6"
3739
3144
  }
3740
3145
  )
3741
- ] }) })
3742
- ] });
3743
- };
3744
- var useWalletList = (options = {}) => {
3745
- const { services } = usePaymentContext();
3746
- const [state, setState] = React3.useState({
3747
- wallets: [],
3748
- isLoading: false,
3749
- error: null
3750
- });
3751
- const fetchWallets = React3.useCallback(async () => {
3752
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
3753
- try {
3754
- const wallets2 = await services.solanaWallets.list();
3755
- setState({ wallets: wallets2, isLoading: false, error: null });
3756
- return wallets2;
3757
- } catch (error) {
3758
- const message = error instanceof Error ? error.message : "Failed to load wallets";
3759
- console.error("payments-ui: wallet list fetch failed", error);
3760
- setState((prev) => ({ ...prev, isLoading: false, error: message }));
3761
- throw error;
3762
- }
3763
- }, [services.solanaWallets]);
3764
- const deleteWallet = React3.useCallback(
3765
- async (walletIdOrAddress) => {
3766
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
3767
- try {
3768
- await services.solanaWallets.remove(walletIdOrAddress);
3769
- setState((prev) => ({
3770
- ...prev,
3771
- wallets: prev.wallets.filter(
3772
- (wallet) => wallet.id !== walletIdOrAddress && wallet.address !== walletIdOrAddress
3773
- ),
3774
- isLoading: false
3775
- }));
3776
- } catch (error) {
3777
- const message = error instanceof Error ? error.message : "Failed to remove wallet";
3778
- console.error("payments-ui: wallet removal failed", error);
3779
- setState((prev) => ({ ...prev, isLoading: false, error: message }));
3780
- throw error;
3781
- }
3782
- },
3783
- [services.solanaWallets]
3784
- );
3785
- const addWallet = React3.useCallback((wallet) => {
3786
- setState((prev) => ({ ...prev, wallets: [...prev.wallets, wallet] }));
3787
- }, []);
3788
- const updateWallet = React3.useCallback((walletId, updates) => {
3789
- setState((prev) => ({
3790
- ...prev,
3791
- wallets: prev.wallets.map(
3792
- (wallet) => wallet.id === walletId ? { ...wallet, ...updates } : wallet
3793
- )
3794
- }));
3795
- }, []);
3796
- const clearError = React3.useCallback(() => {
3797
- setState((prev) => ({ ...prev, error: null }));
3798
- }, []);
3799
- const findWalletByAddress = React3.useCallback(
3800
- (address) => state.wallets.find((wallet) => wallet.address === address),
3801
- [state.wallets]
3802
- );
3803
- const getVerifiedWallets = React3.useCallback(
3804
- () => state.wallets.filter((wallet) => wallet.is_verified),
3805
- [state.wallets]
3806
- );
3807
- React3.useEffect(() => {
3808
- if (options.autoFetch !== false) {
3809
- fetchWallets().catch(() => {
3810
- });
3811
- }
3812
- }, [fetchWallets, options.autoFetch]);
3813
- return {
3814
- wallets: state.wallets,
3815
- isLoading: state.isLoading,
3816
- error: state.error,
3817
- fetchWallets,
3818
- deleteWallet,
3819
- addWallet,
3820
- updateWallet,
3821
- clearError,
3822
- findWalletByAddress,
3823
- getVerifiedWallets,
3824
- hasVerifiedWallets: state.wallets.some((w) => w.is_verified),
3825
- totalWallets: state.wallets.length
3826
- };
3827
- };
3828
- var useWalletVerification = () => {
3829
- const { services } = usePaymentContext();
3830
- const { publicKey, signMessage } = walletAdapterReact.useWallet();
3831
- const [state, setState] = React3.useState({
3832
- isVerifying: false,
3833
- isVerified: false,
3834
- error: null
3835
- });
3836
- const signAndVerifyWallet = React3.useCallback(
3837
- async (walletAddress, message, nonce) => {
3838
- if (!publicKey || !signMessage) {
3839
- throw new Error("Wallet not connected or signing unavailable");
3840
- }
3841
- if (publicKey.toBase58() !== walletAddress) {
3842
- throw new Error("Connected wallet does not match target wallet");
3843
- }
3844
- setState((prev) => ({ ...prev, isVerifying: true, error: null }));
3845
- try {
3846
- const encodedMessage = new TextEncoder().encode(message);
3847
- const signature = await signMessage(encodedMessage);
3848
- const signatureBase58 = bs58__default.default.encode(signature);
3849
- const response = await services.solanaWallets.verify(
3850
- walletAddress,
3851
- signatureBase58,
3852
- nonce
3853
- );
3854
- setState({ isVerifying: false, isVerified: response.verified, error: null });
3855
- return response;
3856
- } catch (error) {
3857
- const message2 = error instanceof Error ? error.message : "Wallet verification failed";
3858
- console.error("payments-ui: wallet verification failed", error);
3859
- setState({ isVerifying: false, isVerified: false, error: message2 });
3860
- throw error;
3861
- }
3862
- },
3863
- [publicKey, signMessage, services.solanaWallets]
3864
- );
3865
- const clearError = React3.useCallback(() => {
3866
- setState((prev) => ({ ...prev, error: null }));
3867
- }, []);
3868
- const resetVerification = React3.useCallback(() => {
3869
- setState({ isVerifying: false, isVerified: false, error: null });
3870
- }, []);
3871
- const autoVerifyWallet = React3.useCallback(
3872
- async (walletAddress, message, nonce) => {
3873
- try {
3874
- return await signAndVerifyWallet(walletAddress, message, nonce);
3875
- } catch (error) {
3876
- console.warn("payments-ui: auto-verification skipped", error);
3877
- return null;
3878
- }
3879
- },
3880
- [signAndVerifyWallet]
3881
- );
3882
- return {
3883
- ...state,
3884
- signAndVerifyWallet,
3885
- autoVerifyWallet,
3886
- clearError,
3887
- resetVerification
3888
- };
3889
- };
3890
- var useWalletConnection = () => {
3891
- const { services } = usePaymentContext();
3892
- const { publicKey, connected, connecting, disconnect, wallet } = walletAdapterReact.useWallet();
3893
- const [state, setState] = React3.useState({
3894
- isConnected: false,
3895
- isConnecting: false,
3896
- publicKey: null,
3897
- wallets: [],
3898
- isLoading: false,
3899
- error: null
3900
- });
3901
- React3.useEffect(() => {
3902
- setState((prev) => ({
3903
- ...prev,
3904
- isConnected: connected,
3905
- isConnecting: connecting,
3906
- publicKey: publicKey?.toBase58() ?? null
3907
- }));
3908
- }, [connected, connecting, publicKey]);
3909
- const connectWalletToBackend = React3.useCallback(
3910
- async (address) => {
3911
- if (!address) {
3912
- throw new Error("Wallet address is required");
3913
- }
3914
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
3915
- try {
3916
- const challenge = await services.solanaWallets.requestChallenge(address);
3917
- setState((prev) => ({ ...prev, isLoading: false }));
3918
- return challenge;
3919
- } catch (error) {
3920
- const message = error instanceof Error ? error.message : "Wallet challenge failed";
3921
- console.error("payments-ui: wallet challenge failed", error);
3922
- setState((prev) => ({ ...prev, isLoading: false, error: message }));
3923
- throw error;
3924
- }
3925
- },
3926
- [services.solanaWallets]
3927
- );
3928
- const connectWallet = React3.useCallback(async () => {
3929
- if (!wallet) {
3930
- throw new Error("No wallet adapter selected");
3931
- }
3932
- setState((prev) => ({ ...prev, isConnecting: true, error: null }));
3933
- try {
3934
- await wallet.adapter.connect();
3935
- if (publicKey) {
3936
- await connectWalletToBackend(publicKey.toBase58());
3937
- }
3938
- } catch (error) {
3939
- const message = error instanceof Error ? error.message : "Failed to connect wallet";
3940
- console.error("payments-ui: wallet connection failed", error);
3941
- setState((prev) => ({ ...prev, isConnecting: false, error: message }));
3942
- throw error;
3943
- } finally {
3944
- setState((prev) => ({ ...prev, isConnecting: false }));
3945
- }
3946
- }, [wallet, publicKey, connectWalletToBackend]);
3947
- const disconnectWallet = React3.useCallback(async () => {
3948
- try {
3949
- await disconnect();
3950
- setState((prev) => ({
3951
- ...prev,
3952
- isConnected: false,
3953
- publicKey: null,
3954
- wallets: [],
3955
- error: null
3956
- }));
3957
- } catch (error) {
3958
- const message = error instanceof Error ? error.message : "Failed to disconnect wallet";
3959
- console.error("payments-ui: wallet disconnect failed", error);
3960
- setState((prev) => ({ ...prev, error: message }));
3961
- throw error;
3962
- }
3963
- }, [disconnect]);
3964
- const clearError = React3.useCallback(() => {
3965
- setState((prev) => ({ ...prev, error: null }));
3966
- }, []);
3967
- return {
3968
- ...state,
3969
- walletName: wallet?.adapter.name,
3970
- walletIcon: wallet?.adapter.icon,
3971
- connectWallet,
3972
- disconnectWallet,
3973
- connectWalletToBackend,
3974
- clearError
3975
- };
3976
- };
3977
- var notifyDefault4 = (payload) => {
3978
- console.log("[payments-ui] wallet-card", payload);
3979
- };
3980
- var WalletCard = ({
3981
- wallet,
3982
- isPrimary = false,
3983
- isConnected = false,
3984
- balance,
3985
- onSetPrimary,
3986
- onVerify,
3987
- onDelete,
3988
- isVerifying = false,
3989
- isDeleting = false,
3990
- notify = notifyDefault4
3991
- }) => {
3992
- const [isCopying, setIsCopying] = React3.useState(false);
3993
- const formatAddress = (address) => address.length <= 12 ? address : `${address.slice(0, 4)}...${address.slice(-4)}`;
3994
- const copyToClipboard = async (text) => {
3995
- setIsCopying(true);
3996
- try {
3997
- await navigator.clipboard.writeText(text);
3998
- notify({ title: "Copied", description: "Wallet address copied to clipboard" });
3999
- } catch (error) {
4000
- notify({ title: "Failed to copy", description: error.message, status: "destructive" });
4001
- } finally {
4002
- setTimeout(() => setIsCopying(false), 500);
4003
- }
4004
- };
4005
- const openExplorer = () => {
4006
- window.open(`https://solscan.io/account/${wallet.address}`, "_blank", "noopener,noreferrer");
4007
- };
4008
- return /* @__PURE__ */ jsxRuntime.jsxs(
4009
- "div",
4010
- {
4011
- className: cn(
4012
- "rounded-lg border bg-background/40 p-4 transition-shadow",
4013
- isPrimary && "border-primary/50 shadow-lg",
4014
- isConnected && "ring-1 ring-primary"
4015
- ),
4016
- children: [
4017
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
4018
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
4019
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-primary/20", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-5 w-5 rounded-full bg-gradient-to-br from-primary to-primary/60" }) }),
4020
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
4021
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
4022
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-sm font-medium", children: formatAddress(wallet.address) }),
4023
- isPrimary && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 rounded-full bg-yellow-500/20 px-2 py-0.5 text-xs text-yellow-500", children: [
4024
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Star, { className: "h-3 w-3 fill-yellow-500 text-yellow-500" }),
4025
- " Primary"
4026
- ] }),
4027
- wallet.is_verified ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-xs text-emerald-400", children: [
4028
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle, { className: "h-3.5 w-3.5" }),
4029
- " Verified"
4030
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-xs text-amber-400", children: [
4031
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-3.5 w-3.5" }),
4032
- " Unverified"
4033
- ] }),
4034
- isConnected && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded bg-blue-500/20 px-2 py-0.5 text-xs text-blue-400", children: "Connected" })
4035
- ] }),
4036
- balance !== null && typeof balance !== "undefined" && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-1 text-sm text-muted-foreground", children: [
4037
- "Balance: ",
4038
- balance.toFixed(4),
4039
- " SOL"
4040
- ] }),
4041
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-0.5 text-xs text-muted-foreground", children: [
4042
- "Added ",
4043
- new Date(wallet.created_at).toLocaleDateString()
4044
- ] })
4045
- ] })
4046
- ] }) }),
4047
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
4048
- /* @__PURE__ */ jsxRuntime.jsx(
4049
- Button,
4050
- {
4051
- variant: "ghost",
4052
- size: "icon",
4053
- className: "h-8 w-8",
4054
- onClick: () => copyToClipboard(wallet.address),
4055
- disabled: isCopying,
4056
- children: isCopying ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-4 w-4" })
4057
- }
4058
- ),
4059
- /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", className: "h-8 w-8", onClick: openExplorer, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-4 w-4" }) })
4060
- ] })
4061
- ] }),
4062
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
4063
- !isPrimary && onSetPrimary && wallet.is_verified && /* @__PURE__ */ jsxRuntime.jsxs(
4064
- Button,
4065
- {
4066
- variant: "outline",
4067
- size: "sm",
4068
- className: "border-primary/40 text-primary",
4069
- onClick: () => onSetPrimary(wallet.id),
4070
- children: [
4071
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Star, { className: "mr-1 h-3 w-3" }),
4072
- " Set Primary"
4073
- ]
4074
- }
4075
- ),
4076
- !wallet.is_verified && onVerify && isConnected && /* @__PURE__ */ jsxRuntime.jsx(
4077
- Button,
4078
- {
4079
- variant: "outline",
4080
- size: "sm",
4081
- className: "border-emerald-500/40 text-emerald-400",
4082
- onClick: () => onVerify(wallet),
4083
- disabled: isVerifying,
4084
- children: isVerifying ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4085
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-1 h-3 w-3 animate-spin" }),
4086
- " Verifying..."
4087
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4088
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Shield, { className: "mr-1 h-3 w-3" }),
4089
- " Verify"
4090
- ] })
4091
- }
4092
- ),
4093
- onDelete && /* @__PURE__ */ jsxRuntime.jsx(
4094
- Button,
4095
- {
4096
- variant: "outline",
4097
- size: "sm",
4098
- className: "ml-auto border-destructive/40 text-destructive",
4099
- onClick: () => onDelete(wallet.id),
4100
- disabled: isDeleting,
4101
- children: isDeleting ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3 w-3" })
4102
- }
4103
- )
4104
- ] })
4105
- ]
4106
- }
4107
- );
4108
- };
4109
- var EmptyWalletState = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
4110
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Wallet, { className: "mb-4 h-12 w-12 text-muted-foreground" }),
4111
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-2 text-lg font-medium", children: "No wallets connected" }),
4112
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-6 text-sm text-muted-foreground", children: "Connect your Solana wallet to get started" }),
4113
- /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReactUi.WalletMultiButton, { className: "!bg-primary text-primary-foreground hover:!bg-primary/90" })
4114
- ] });
4115
- var notifyDefault5 = (payload) => {
4116
- console.log("[payments-ui] solana-wallets", payload);
4117
- };
4118
- var SolanaWalletSection = ({
4119
- onNotify,
4120
- rpcUrl
4121
- }) => {
4122
- const notify = onNotify ?? notifyDefault5;
4123
- const { config } = usePaymentContext();
4124
- const { connected, publicKey, disconnect } = walletAdapterReact.useWallet();
4125
- const { wallets: wallets2, isLoading, deleteWallet, fetchWallets } = useWalletList();
4126
- const { signAndVerifyWallet } = useWalletVerification();
4127
- const walletConnection = useWalletConnection();
4128
- const [primaryWalletId, setPrimaryWalletId] = React3.useState(null);
4129
- const [showOtherWallets, setShowOtherWallets] = React3.useState(false);
4130
- const [balances, setBalances] = React3.useState({});
4131
- const [verifyingWalletId, setVerifyingWalletId] = React3.useState(null);
4132
- const [deletingWalletId, setDeletingWalletId] = React3.useState(null);
4133
- const [walletToDelete, setWalletToDelete] = React3.useState(null);
4134
- const [isRegistering, setIsRegistering] = React3.useState(false);
4135
- const rpcEndpoint = rpcUrl || config.solanaRpcUrl || "https://api.mainnet-beta.solana.com";
4136
- const connection = React3.useMemo(() => new web3_js.Connection(rpcEndpoint), [rpcEndpoint]);
4137
- const primaryWallet = wallets2.find((w) => w.id === primaryWalletId) ?? wallets2.find((w) => w.is_verified) ?? null;
4138
- const otherWallets = wallets2.filter((w) => w.id !== primaryWallet?.id);
4139
- const fetchBalance = React3.useCallback(
4140
- async (address) => {
4141
- try {
4142
- const pubkey = new web3_js.PublicKey(address);
4143
- const balance = await connection.getBalance(pubkey);
4144
- return balance / web3_js.LAMPORTS_PER_SOL;
4145
- } catch (error) {
4146
- console.error("payments-ui: failed to fetch balance", error);
4147
- return null;
4148
- }
4149
- },
4150
- [connection]
4151
- );
4152
- const fetchAllBalances = React3.useCallback(async () => {
4153
- const results = await Promise.all(
4154
- wallets2.map(async (wallet) => ({ address: wallet.address, balance: await fetchBalance(wallet.address) }))
4155
- );
4156
- const next = {};
4157
- results.forEach(({ address, balance }) => {
4158
- if (balance !== null && typeof balance !== "undefined") {
4159
- next[address] = balance;
4160
- }
4161
- });
4162
- setBalances(next);
4163
- }, [wallets2, fetchBalance]);
4164
- React3.useEffect(() => {
4165
- if (wallets2.length > 0) {
4166
- fetchAllBalances().catch(() => void 0);
4167
- }
4168
- }, [wallets2, fetchAllBalances]);
4169
- React3.useEffect(() => {
4170
- const verifiedWallet = wallets2.find((w) => w.is_verified);
4171
- if (verifiedWallet && !primaryWalletId) {
4172
- setPrimaryWalletId(verifiedWallet.id);
4173
- }
4174
- }, [wallets2, primaryWalletId]);
4175
- const registerWallet = React3.useCallback(async () => {
4176
- if (!connected || !publicKey || isRegistering) return;
4177
- setIsRegistering(true);
4178
- try {
4179
- const challenge = await walletConnection.connectWalletToBackend(publicKey.toBase58());
4180
- if (!challenge?.message) {
4181
- throw new Error("Failed to retrieve wallet verification challenge");
4182
- }
4183
- await signAndVerifyWallet(challenge.wallet, challenge.message, challenge.nonce);
4184
- await fetchWallets();
4185
- notify({
4186
- title: "Wallet verified",
4187
- description: "Your wallet has been linked successfully.",
4188
- status: "success"
4189
- });
4190
- } catch (error) {
4191
- notify({
4192
- title: "Wallet verification failed",
4193
- description: error instanceof Error ? error.message : "Failed to verify wallet",
4194
- status: "destructive"
4195
- });
4196
- } finally {
4197
- setIsRegistering(false);
4198
- }
4199
- }, [connected, publicKey, isRegistering, walletConnection, signAndVerifyWallet, fetchWallets, notify]);
4200
- React3.useEffect(() => {
4201
- if (connected && publicKey && !walletConnection.isConnecting && wallets2.length === 0) {
4202
- registerWallet().catch(() => void 0);
4203
- }
4204
- }, [connected, publicKey, walletConnection.isConnecting, wallets2.length, registerWallet]);
4205
- const handleVerifyWallet = React3.useCallback(
4206
- async (wallet) => {
4207
- if (!connected || publicKey?.toBase58() !== wallet.address) {
4208
- notify({
4209
- title: "Connect wallet first",
4210
- description: "Please connect the wallet you want to verify.",
4211
- status: "destructive"
4212
- });
4213
- return;
4214
- }
4215
- setVerifyingWalletId(wallet.id);
4216
- try {
4217
- const challenge = await walletConnection.connectWalletToBackend(wallet.address);
4218
- if (!challenge?.message) {
4219
- throw new Error("Failed to retrieve verification challenge");
4220
- }
4221
- await signAndVerifyWallet(challenge.wallet, challenge.message, challenge.nonce);
4222
- await fetchWallets();
4223
- notify({ title: "Wallet verified", status: "success" });
4224
- } catch (error) {
4225
- notify({
4226
- title: "Verification failed",
4227
- description: error instanceof Error ? error.message : "Failed to verify wallet",
4228
- status: "destructive"
4229
- });
4230
- } finally {
4231
- setVerifyingWalletId(null);
4232
- }
4233
- },
4234
- [connected, publicKey, walletConnection, signAndVerifyWallet, fetchWallets, notify]
4235
- );
4236
- const handleDeleteWallet = React3.useCallback(
4237
- async (walletId) => {
4238
- setDeletingWalletId(walletId);
4239
- try {
4240
- await deleteWallet(walletId);
4241
- if (primaryWalletId === walletId) {
4242
- setPrimaryWalletId(null);
4243
- }
4244
- if (connected && publicKey) {
4245
- const deletedWallet = wallets2.find((w) => w.id === walletId);
4246
- if (deletedWallet?.address === publicKey.toBase58()) {
4247
- await disconnect();
4248
- }
4249
- }
4250
- notify({ title: "Wallet removed", status: "success" });
4251
- } catch (error) {
4252
- notify({
4253
- title: "Failed to remove wallet",
4254
- description: error instanceof Error ? error.message : "Please try again",
4255
- status: "destructive"
4256
- });
4257
- } finally {
4258
- setDeletingWalletId(null);
4259
- setWalletToDelete(null);
4260
- }
4261
- },
4262
- [deleteWallet, primaryWalletId, connected, publicKey, wallets2, disconnect, notify]
4263
- );
4264
- const handleSetPrimary = (walletId) => {
4265
- setPrimaryWalletId(walletId);
4266
- notify({ title: "Primary wallet updated", status: "success" });
4267
- };
4268
- const isWalletRegistered = connected && publicKey && wallets2.some((w) => w.address === publicKey.toBase58());
4269
- if (isLoading && wallets2.length === 0) {
4270
- return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "border-0 bg-background/5", children: [
4271
- /* @__PURE__ */ jsxRuntime.jsx(CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "text-xl", children: "Solana Wallets" }) }),
4272
- /* @__PURE__ */ jsxRuntime.jsx(CardContent, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center py-8", children: [
4273
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-6 w-6 animate-spin text-muted-foreground" }),
4274
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Loading wallets..." })
4275
- ] }) })
4276
- ] });
4277
- }
4278
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4279
- /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "border-0 bg-background/5", children: [
4280
- /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { children: [
4281
- /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "text-xl", children: "Solana Wallets" }),
4282
- /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: "Connect and manage your Solana wallets for payments" })
4283
- ] }),
4284
- /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: "space-y-4", children: wallets2.length === 0 && !connected ? /* @__PURE__ */ jsxRuntime.jsx(EmptyWalletState, {}) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4285
- primaryWallet && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4286
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-3 text-sm font-medium uppercase tracking-wide text-muted-foreground", children: "Primary Wallet" }),
4287
- /* @__PURE__ */ jsxRuntime.jsx(
4288
- WalletCard,
4289
- {
4290
- wallet: primaryWallet,
4291
- isPrimary: true,
4292
- isConnected: connected && publicKey?.toBase58() === primaryWallet.address,
4293
- balance: balances[primaryWallet.address],
4294
- onVerify: handleVerifyWallet,
4295
- onDelete: (id) => {
4296
- const target = wallets2.find((w) => w.id === id);
4297
- if (target) setWalletToDelete(target);
4298
- },
4299
- isVerifying: verifyingWalletId === primaryWallet.id,
4300
- isDeleting: deletingWalletId === primaryWallet.id,
4301
- notify
4302
- }
4303
- )
4304
- ] }),
4305
- otherWallets.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4306
- /* @__PURE__ */ jsxRuntime.jsxs(
4307
- "button",
4308
- {
4309
- className: "mb-3 flex w-full items-center justify-between text-left",
4310
- onClick: () => setShowOtherWallets((prev) => !prev),
4311
- children: [
4312
- /* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "text-sm font-medium uppercase tracking-wide text-muted-foreground", children: [
4313
- "Other Wallets (",
4314
- otherWallets.length,
4315
- ")"
4316
- ] }),
4317
- showOtherWallets ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "h-4 w-4 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-4 w-4 text-muted-foreground" })
4318
- ]
4319
- }
4320
- ),
4321
- showOtherWallets && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: otherWallets.map((wallet) => /* @__PURE__ */ jsxRuntime.jsx(
4322
- WalletCard,
4323
- {
4324
- wallet,
4325
- isConnected: connected && publicKey?.toBase58() === wallet.address,
4326
- balance: balances[wallet.address],
4327
- onSetPrimary: handleSetPrimary,
4328
- onVerify: handleVerifyWallet,
4329
- onDelete: (id) => {
4330
- const target = wallets2.find((w) => w.id === id);
4331
- if (target) setWalletToDelete(target);
4332
- },
4333
- isVerifying: verifyingWalletId === wallet.id,
4334
- isDeleting: deletingWalletId === wallet.id,
4335
- notify
4336
- },
4337
- wallet.id
4338
- )) })
4339
- ] }),
4340
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-4", children: connected && publicKey ? isWalletRegistered ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
4341
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-emerald-500/40 bg-emerald-500/10 p-3 text-sm text-emerald-200", children: [
4342
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle, { className: "h-4 w-4" }),
4343
- " Connected wallet is verified and linked to your account."
4344
- ] }),
4345
- /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReactUi.WalletMultiButton, { className: "w-full !bg-primary text-primary-foreground" })
4346
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
4347
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-amber-500/40 bg-amber-500/10 p-3 text-sm text-amber-200", children: "Your connected wallet is not registered with your account." }),
4348
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
4349
- /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: registerWallet, disabled: isRegistering || walletConnection.isConnecting, className: "flex-1 bg-primary text-primary-foreground", children: isRegistering ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4350
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
4351
- " Registering..."
4352
- ] }) : "Register This Wallet" }),
4353
- /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => disconnect(), variant: "outline", className: "border-border", children: "Disconnect" })
4354
- ] })
4355
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(walletAdapterReactUi.WalletMultiButton, { className: "w-full !bg-primary text-primary-foreground" }) })
4356
- ] }) })
4357
- ] }),
4358
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialog, { open: !!walletToDelete, onOpenChange: () => setWalletToDelete(null), children: /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogContent, { children: [
4359
- /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogHeader, { children: [
4360
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogTitle, { children: "Remove Wallet" }),
4361
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogDescription, { children: "Are you sure you want to remove this wallet from your account? This action cannot be undone." })
3146
+ ] }) }),
3147
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: Boolean(methodBeingReplaced), onOpenChange: (open) => !open && setMethodBeingReplaced(null), children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-h-[95vh] overflow-y-auto", children: [
3148
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
3149
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: t.replaceCardTitle }),
3150
+ /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: t.replaceCardDescription })
4362
3151
  ] }),
4363
- /* @__PURE__ */ jsxRuntime.jsxs(AlertDialogFooter, { children: [
4364
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogCancel, { children: "Cancel" }),
4365
- /* @__PURE__ */ jsxRuntime.jsx(AlertDialogAction, { onClick: () => walletToDelete && handleDeleteWallet(walletToDelete.id), className: "bg-destructive text-destructive-foreground", children: "Remove" })
4366
- ] })
3152
+ methodBeingReplaced && /* @__PURE__ */ jsxRuntime.jsx(
3153
+ CardDetailsForm,
3154
+ {
3155
+ visible: true,
3156
+ collectPrefix: `${collectPrefix}-replace-${methodBeingReplaced.id}`,
3157
+ submitting: replaceMutation.isPending,
3158
+ submitLabel: t.replaceCard,
3159
+ defaultValues: {
3160
+ email: userEmail ?? "",
3161
+ country: defaultCountry,
3162
+ provider
3163
+ },
3164
+ externalError: replaceMutation.error?.message ?? null,
3165
+ onTokenize: handleReplaceTokenize,
3166
+ className: "rounded-2xl border border-white/10 bg-white/5 p-6"
3167
+ }
3168
+ )
4367
3169
  ] }) })
4368
3170
  ] });
4369
3171
  };
4370
- var WalletManagement = (props) => /* @__PURE__ */ jsxRuntime.jsx(SolanaWalletSection, { ...props });
4371
- var Checkbox = React3__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3172
+ var Checkbox = React17__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4372
3173
  CheckboxPrimitive__namespace.Root,
4373
3174
  {
4374
3175
  ref,
@@ -4395,9 +3196,9 @@ var initialState = {
4395
3196
  termsAccepted: false
4396
3197
  };
4397
3198
  var WalletDialog = ({ open, onOpenChange }) => {
4398
- const [form, setForm] = React3.useState(initialState);
4399
- const [errors, setErrors] = React3.useState({});
4400
- const validators = React3.useMemo(
3199
+ const [form, setForm] = React17.useState(initialState);
3200
+ const [errors, setErrors] = React17.useState({});
3201
+ const validators = React17.useMemo(
4401
3202
  () => ({
4402
3203
  nameOnCard: (value) => !value ? "Name is required" : void 0,
4403
3204
  cardNumber: (value) => /^\d{16}$/.test(value) ? void 0 : "Card number must be 16 digits",
@@ -4490,10 +3291,10 @@ var WalletDialog = ({ open, onOpenChange }) => {
4490
3291
  var useTokenBalance = (tokens) => {
4491
3292
  const { publicKey } = walletAdapterReact.useWallet();
4492
3293
  const { connection } = walletAdapterReact.useConnection();
4493
- const [balances, setBalances] = React3.useState([]);
4494
- const [isLoading, setIsLoading] = React3.useState(false);
4495
- const [error, setError] = React3.useState(null);
4496
- const fetchTokenBalance = React3.useCallback(
3294
+ const [balances, setBalances] = React17.useState([]);
3295
+ const [isLoading, setIsLoading] = React17.useState(false);
3296
+ const [error, setError] = React17.useState(null);
3297
+ const fetchTokenBalance = React17.useCallback(
4497
3298
  async (token, walletAddress) => {
4498
3299
  try {
4499
3300
  const mintPublicKey = new web3_js.PublicKey(token.mint);
@@ -4534,8 +3335,8 @@ var useTokenBalance = (tokens) => {
4534
3335
  },
4535
3336
  [connection]
4536
3337
  );
4537
- const tokensKey = React3.useMemo(() => tokens.map((t) => t.mint).join(","), [tokens]);
4538
- React3.useEffect(() => {
3338
+ const tokensKey = React17.useMemo(() => tokens.map((t) => t.mint).join(","), [tokens]);
3339
+ React17.useEffect(() => {
4539
3340
  if (!publicKey || tokens.length === 0) {
4540
3341
  setBalances([]);
4541
3342
  return;
@@ -4559,20 +3360,20 @@ var useTokenBalance = (tokens) => {
4559
3360
  };
4560
3361
  fetchAllBalances();
4561
3362
  }, [publicKey, tokensKey, fetchTokenBalance]);
4562
- const getTokenBalance = React3.useCallback(
3363
+ const getTokenBalance = React17.useCallback(
4563
3364
  (tokenSymbol) => {
4564
3365
  return balances.find((balance) => balance.token.symbol === tokenSymbol);
4565
3366
  },
4566
3367
  [balances]
4567
3368
  );
4568
- const hasSufficientBalance2 = React3.useCallback(
3369
+ const hasSufficientBalance = React17.useCallback(
4569
3370
  (tokenSymbol, requiredAmount) => {
4570
3371
  const balance = getTokenBalance(tokenSymbol);
4571
3372
  return balance ? balance.uiAmount >= requiredAmount : false;
4572
3373
  },
4573
3374
  [getTokenBalance]
4574
3375
  );
4575
- const getFormattedBalance = React3.useCallback(
3376
+ const getFormattedBalance = React17.useCallback(
4576
3377
  (tokenSymbol) => {
4577
3378
  const balance = getTokenBalance(tokenSymbol);
4578
3379
  if (!balance) return "0.00";
@@ -4586,7 +3387,7 @@ var useTokenBalance = (tokens) => {
4586
3387
  },
4587
3388
  [getTokenBalance]
4588
3389
  );
4589
- const refreshBalances = React3.useCallback(async () => {
3390
+ const refreshBalances = React17.useCallback(async () => {
4590
3391
  if (!publicKey || tokens.length === 0) {
4591
3392
  setBalances([]);
4592
3393
  return;
@@ -4607,7 +3408,7 @@ var useTokenBalance = (tokens) => {
4607
3408
  setIsLoading(false);
4608
3409
  }
4609
3410
  }, [publicKey, tokens, fetchTokenBalance]);
4610
- const getTotalValue = React3.useCallback(
3411
+ const getTotalValue = React17.useCallback(
4611
3412
  (priceData) => {
4612
3413
  if (!priceData) return 0;
4613
3414
  return balances.reduce((total, balance) => {
@@ -4626,106 +3427,16 @@ var useTokenBalance = (tokens) => {
4626
3427
  error,
4627
3428
  refreshBalances,
4628
3429
  getTokenBalance,
4629
- hasSufficientBalance: hasSufficientBalance2,
3430
+ hasSufficientBalance,
4630
3431
  getFormattedBalance,
4631
3432
  getTotalValue,
4632
3433
  hasAnyBalance: positiveBalances.length > 0,
4633
3434
  isConnected: !!publicKey
4634
3435
  };
4635
3436
  };
4636
- var useDirectWalletPayment = () => {
4637
- const { publicKey, signTransaction, connected } = walletAdapterReact.useWallet();
4638
- const solanaService = useSolanaService();
4639
- const [paymentState, setPaymentState] = React3.useState({
4640
- loading: false,
4641
- error: null,
4642
- success: false,
4643
- transactionId: null
4644
- });
4645
- const resetPayment = React3.useCallback(() => {
4646
- setPaymentState({
4647
- loading: false,
4648
- error: null,
4649
- success: false,
4650
- transactionId: null
4651
- });
4652
- }, []);
4653
- const payWithWallet = React3.useCallback(
4654
- async (token, priceId) => {
4655
- if (!connected || !publicKey || !signTransaction) {
4656
- setPaymentState((prev) => ({
4657
- ...prev,
4658
- error: "Wallet not connected. Please connect your wallet first."
4659
- }));
4660
- return;
4661
- }
4662
- setPaymentState({
4663
- loading: true,
4664
- error: null,
4665
- success: false,
4666
- transactionId: null
4667
- });
4668
- try {
4669
- console.log("Generating payment transaction...", {
4670
- token: token.symbol,
4671
- priceId
4672
- });
4673
- const paymentData = await solanaService.generatePayment(
4674
- priceId,
4675
- token.symbol,
4676
- publicKey.toBase58()
4677
- );
4678
- const transactionBuffer = buffer.Buffer.from(paymentData.transaction, "base64");
4679
- const transaction = web3_js.Transaction.from(transactionBuffer);
4680
- console.log("Requesting wallet signature...");
4681
- const signedTransaction = await signTransaction(transaction);
4682
- const signedTransactionBase64 = signedTransaction.serialize().toString("base64");
4683
- console.log("Submitting signed transaction...");
4684
- const submitResult = await solanaService.submitPayment(
4685
- signedTransactionBase64,
4686
- priceId,
4687
- paymentData.intent_id
4688
- );
4689
- setPaymentState({
4690
- loading: false,
4691
- error: null,
4692
- success: true,
4693
- transactionId: submitResult.transaction_id
4694
- });
4695
- console.log("Payment successful!", submitResult);
4696
- } catch (err) {
4697
- console.error("Payment failed:", err);
4698
- let errorMessage = "Payment failed. Please try again.";
4699
- const message = err instanceof Error ? err.message : typeof err === "string" ? err : "";
4700
- if (message.includes("User rejected")) {
4701
- errorMessage = "Payment cancelled by user.";
4702
- } else if (/insufficient\s+funds/i.test(message)) {
4703
- errorMessage = `Insufficient ${token.symbol} balance.`;
4704
- } else if (/network/i.test(message)) {
4705
- errorMessage = "Network error. Please check your connection.";
4706
- } else if (message) {
4707
- errorMessage = message;
4708
- }
4709
- setPaymentState({
4710
- loading: false,
4711
- error: errorMessage,
4712
- success: false,
4713
- transactionId: null
4714
- });
4715
- }
4716
- },
4717
- [connected, publicKey, signTransaction, solanaService]
4718
- );
4719
- return {
4720
- paymentState,
4721
- payWithWallet,
4722
- resetPayment
4723
- };
4724
- };
4725
3437
  var usePaymentStatus = (options = {}) => {
4726
3438
  const { connection } = walletAdapterReact.useConnection();
4727
- const { services } = usePaymentContext();
4728
- const billingApi = services.billingApi;
3439
+ const { client } = usePaymentContext();
4729
3440
  const {
4730
3441
  transactionId,
4731
3442
  purchaseId,
@@ -4736,21 +3447,21 @@ var usePaymentStatus = (options = {}) => {
4736
3447
  retryInterval = 1e4
4737
3448
  // 10 seconds
4738
3449
  } = options;
4739
- const [status, setStatus] = React3.useState(null);
4740
- const [paymentStatus, setPaymentStatus] = React3.useState(null);
4741
- const [isLoading, setIsLoading] = React3.useState(false);
4742
- const [error, setError] = React3.useState(null);
4743
- const [retryCount, setRetryCount] = React3.useState(0);
4744
- const intervalRef = React3.useRef(null);
4745
- const isMonitoringRef = React3.useRef(false);
4746
- React3.useEffect(() => {
3450
+ const [status, setStatus] = React17.useState(null);
3451
+ const [paymentStatus, setPaymentStatus] = React17.useState(null);
3452
+ const [isLoading, setIsLoading] = React17.useState(false);
3453
+ const [error, setError] = React17.useState(null);
3454
+ const [retryCount, setRetryCount] = React17.useState(0);
3455
+ const intervalRef = React17.useRef(null);
3456
+ const isMonitoringRef = React17.useRef(false);
3457
+ React17.useEffect(() => {
4747
3458
  return () => {
4748
3459
  if (intervalRef.current) {
4749
3460
  clearInterval(intervalRef.current);
4750
3461
  }
4751
3462
  };
4752
3463
  }, []);
4753
- const checkTransactionStatus = React3.useCallback(
3464
+ const checkTransactionStatus = React17.useCallback(
4754
3465
  async (signature) => {
4755
3466
  try {
4756
3467
  const statusResponse = await connection.getSignatureStatus(signature, {
@@ -4795,17 +3506,11 @@ var usePaymentStatus = (options = {}) => {
4795
3506
  },
4796
3507
  [connection]
4797
3508
  );
4798
- const checkPaymentStatus = React3.useCallback(
3509
+ const checkPaymentStatus = React17.useCallback(
4799
3510
  async (id) => {
4800
3511
  try {
4801
- const data = await billingApi.get(
4802
- `/payment/status/${id}`
4803
- );
4804
- return data;
3512
+ return await client.getPaymentStatus(id);
4805
3513
  } catch (error2) {
4806
- if (error2?.status === 404) {
4807
- return null;
4808
- }
4809
3514
  console.error("Failed to check payment status:", {
4810
3515
  purchaseId: id,
4811
3516
  error: error2
@@ -4813,9 +3518,9 @@ var usePaymentStatus = (options = {}) => {
4813
3518
  return null;
4814
3519
  }
4815
3520
  },
4816
- [billingApi]
3521
+ [client]
4817
3522
  );
4818
- const startMonitoring = React3.useCallback(async () => {
3523
+ const startMonitoring = React17.useCallback(async () => {
4819
3524
  if (isMonitoringRef.current || !transactionId && !purchaseId) {
4820
3525
  return;
4821
3526
  }
@@ -4903,14 +3608,14 @@ var usePaymentStatus = (options = {}) => {
4903
3608
  retryInterval,
4904
3609
  retryCount
4905
3610
  ]);
4906
- const stopMonitoring = React3.useCallback(() => {
3611
+ const stopMonitoring = React17.useCallback(() => {
4907
3612
  if (intervalRef.current) {
4908
3613
  clearInterval(intervalRef.current);
4909
3614
  }
4910
3615
  isMonitoringRef.current = false;
4911
3616
  setIsLoading(false);
4912
3617
  }, []);
4913
- const checkStatus = React3.useCallback(async () => {
3618
+ const checkStatus = React17.useCallback(async () => {
4914
3619
  if (!transactionId && !purchaseId) return;
4915
3620
  setIsLoading(true);
4916
3621
  setError(null);
@@ -4935,7 +3640,7 @@ var usePaymentStatus = (options = {}) => {
4935
3640
  setIsLoading(false);
4936
3641
  }
4937
3642
  }, [transactionId, purchaseId, checkTransactionStatus, checkPaymentStatus]);
4938
- React3.useEffect(() => {
3643
+ React17.useEffect(() => {
4939
3644
  if ((transactionId || purchaseId) && !isMonitoringRef.current) {
4940
3645
  startMonitoring();
4941
3646
  }
@@ -4943,7 +3648,7 @@ var usePaymentStatus = (options = {}) => {
4943
3648
  stopMonitoring();
4944
3649
  };
4945
3650
  }, [transactionId, purchaseId, startMonitoring, stopMonitoring]);
4946
- const getConfirmationStatus = React3.useCallback(() => {
3651
+ const getConfirmationStatus = React17.useCallback(() => {
4947
3652
  if (paymentStatus?.status === "confirmed") return "confirmed";
4948
3653
  if (paymentStatus?.status === "failed") return "failed";
4949
3654
  if (status?.confirmationStatus === "finalized") return "confirmed";
@@ -4952,7 +3657,7 @@ var usePaymentStatus = (options = {}) => {
4952
3657
  return "failed";
4953
3658
  return "pending";
4954
3659
  }, [status, paymentStatus]);
4955
- const getSolscanUrl = React3.useCallback(
3660
+ const getSolscanUrl = React17.useCallback(
4956
3661
  (signature) => {
4957
3662
  const txId = signature || transactionId;
4958
3663
  if (!txId) return null;
@@ -4982,47 +3687,30 @@ var usePaymentStatus = (options = {}) => {
4982
3687
  exports.BillingHistory = BillingHistory;
4983
3688
  exports.CancelMembershipDialog = CancelMembershipDialog;
4984
3689
  exports.CardDetailsForm = CardDetailsForm;
4985
- exports.CardPaymentService = CardPaymentService;
4986
- exports.EmptyWalletState = EmptyWalletState;
4987
- exports.PaymentApp = PaymentApp;
3690
+ exports.ClientApiError = ClientApiError;
3691
+ exports.PaymentContext = PaymentContext;
4988
3692
  exports.PaymentExperience = PaymentExperience;
4989
- exports.PaymentMethodService = PaymentMethodService;
4990
3693
  exports.PaymentMethodsSection = PaymentMethodsSection;
4991
3694
  exports.PaymentProvider = PaymentProvider;
4992
3695
  exports.PaymentsDialogProvider = PaymentsDialogProvider;
4993
- exports.PaymentsRuntime = PaymentsRuntime;
3696
+ exports.PaymentsUIPortalRoot = PaymentsUIPortalRoot;
3697
+ exports.PaymentsUIRoot = PaymentsUIRoot;
4994
3698
  exports.SolanaPaymentSelector = SolanaPaymentSelector;
4995
- exports.SolanaPaymentService = SolanaPaymentService;
4996
3699
  exports.SolanaPaymentView = SolanaPaymentView;
4997
- exports.SolanaWalletSection = SolanaWalletSection;
4998
- exports.SolanaWalletService = SolanaWalletService;
4999
3700
  exports.StoredPaymentMethods = StoredPaymentMethods;
5000
3701
  exports.SubscriptionCheckoutModal = SubscriptionCheckoutModal;
5001
- exports.SubscriptionService = SubscriptionService;
5002
3702
  exports.SubscriptionSuccessDialog = SubscriptionSuccessDialog;
5003
- exports.TokenCatalog = TokenCatalog;
5004
- exports.WalletCard = WalletCard;
5005
3703
  exports.WalletDialog = WalletDialog;
5006
- exports.WalletGateway = WalletGateway;
5007
- exports.WalletManagement = WalletManagement;
5008
3704
  exports.WalletModal = WalletModal;
5009
- exports.createPaymentsRuntime = createPaymentsRuntime;
5010
- exports.useAlternativePaymentProvider = useAlternativePaymentProvider;
5011
- exports.useDirectWalletPayment = useDirectWalletPayment;
3705
+ exports.createClient = createClient;
5012
3706
  exports.usePaymentContext = usePaymentContext;
5013
3707
  exports.usePaymentDialogs = usePaymentDialogs;
5014
- exports.usePaymentMethodService = usePaymentMethodService;
5015
3708
  exports.usePaymentMethods = usePaymentMethods;
5016
3709
  exports.usePaymentNotifications = usePaymentNotifications;
5017
3710
  exports.usePaymentStatus = usePaymentStatus;
5018
- exports.useSolanaDirectPayment = useSolanaDirectPayment;
5019
3711
  exports.useSolanaQrPayment = useSolanaQrPayment;
5020
- exports.useSolanaService = useSolanaService;
5021
3712
  exports.useSubscriptionActions = useSubscriptionActions;
5022
3713
  exports.useSupportedTokens = useSupportedTokens;
5023
3714
  exports.useTokenBalance = useTokenBalance;
5024
- exports.useWalletConnection = useWalletConnection;
5025
- exports.useWalletList = useWalletList;
5026
- exports.useWalletVerification = useWalletVerification;
5027
3715
  //# sourceMappingURL=index.cjs.map
5028
3716
  //# sourceMappingURL=index.cjs.map