@sdkrouter/payments 0.1.2

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.
@@ -0,0 +1,561 @@
1
+ "use client";
2
+ import { createPaymentsApi } from './chunk-4QQBPIIT.mjs';
3
+ import { ShoppingBag, AlertCircle, Loader2, CircleAlert, CircleX, CircleCheck, Clock, Wallet, ArrowLeft, Check, Copy } from 'lucide-react';
4
+ import { createContext, useState, useRef, useEffect, useCallback, useContext, useMemo } from 'react';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+ import QRCode from 'react-qr-code';
7
+ import moment from 'moment';
8
+
9
+ // src/config.ts
10
+ var PROD_BASE_URL = "https://api.sdkrouter.com";
11
+ var STYLE_ID = "sdkr-pay-styles";
12
+ function resolveBaseUrl(baseUrl) {
13
+ return baseUrl || PROD_BASE_URL;
14
+ }
15
+
16
+ // src/hooks/usePaymentLink.ts
17
+ function usePaymentLink(options) {
18
+ const { linkId, baseUrl, customerId, onSuccess, onError } = options;
19
+ const [link, setLink] = useState(null);
20
+ const [isLoading, setIsLoading] = useState(true);
21
+ const [error, setError] = useState(null);
22
+ const [step, setStep] = useState("form");
23
+ const [paymentResult, setPaymentResult] = useState(null);
24
+ const [isPaying, setIsPaying] = useState(false);
25
+ const apiRef = useRef(null);
26
+ useEffect(() => {
27
+ const resolved = resolveBaseUrl(baseUrl);
28
+ apiRef.current = createPaymentsApi(resolved);
29
+ let cancelled = false;
30
+ setIsLoading(true);
31
+ setError(null);
32
+ apiRef.current.payments_payments.publicLinksRetrieve(linkId).then((raw) => {
33
+ if (!cancelled) {
34
+ setLink({
35
+ id: raw.id,
36
+ title: raw.title,
37
+ description: raw.description,
38
+ amountUsd: raw.amount_usd ? parseFloat(String(raw.amount_usd)) : null,
39
+ network: raw.network ?? null
40
+ });
41
+ setIsLoading(false);
42
+ }
43
+ }).catch((err) => {
44
+ if (!cancelled) {
45
+ const e = err;
46
+ const msg = e?.statusCode === 404 ? "Payment link not found" : String(e?.errorMessage ?? e?.message ?? "Failed to load payment link");
47
+ setError(msg);
48
+ setIsLoading(false);
49
+ onError?.(msg);
50
+ }
51
+ });
52
+ return () => {
53
+ cancelled = true;
54
+ };
55
+ }, [linkId, baseUrl]);
56
+ const pay = useCallback(async (data) => {
57
+ if (!apiRef.current) return;
58
+ setIsPaying(true);
59
+ setStep("processing");
60
+ setError(null);
61
+ try {
62
+ const raw = await apiRef.current.payments_payments.publicLinksPayCreate(linkId, {
63
+ email: data.email || void 0,
64
+ name: data.name || void 0,
65
+ amount_usd: data.amountUsd != null ? data.amountUsd.toFixed(2) : void 0,
66
+ external_id: data.externalId || customerId || void 0
67
+ });
68
+ const result = {
69
+ success: !!raw.invoice_id,
70
+ paymentId: raw.invoice_id ?? null,
71
+ paymentUrl: null,
72
+ payAddress: raw.pay_address ?? null,
73
+ payAmount: raw.pay_amount ? String(raw.pay_amount) : null,
74
+ coin: raw.coin ?? "USDT",
75
+ network: raw.network ?? null,
76
+ expiresAt: raw.expires_at ?? null,
77
+ error: null
78
+ };
79
+ setPaymentResult(result);
80
+ setStep("status");
81
+ onSuccess?.(result);
82
+ } catch (err) {
83
+ const e = err;
84
+ const msg = String(e?.errorMessage ?? e?.message ?? "Payment failed");
85
+ setError(msg);
86
+ setStep("form");
87
+ onError?.(msg);
88
+ } finally {
89
+ setIsPaying(false);
90
+ }
91
+ }, [linkId, onSuccess, onError]);
92
+ const reset = useCallback(() => {
93
+ setStep("form");
94
+ setPaymentResult(null);
95
+ setError(null);
96
+ }, []);
97
+ return { link, isLoading, error, step, pay, paymentResult, isPaying, reset };
98
+ }
99
+ var KEY_PREFIX = "sdkr_pay_id";
100
+ function usePaymentIdentity(opts) {
101
+ const { linkId, customerId, projectSlug } = opts;
102
+ const key = `${KEY_PREFIX}_${linkId}`;
103
+ const [identity, setIdentity] = useState(null);
104
+ useEffect(() => {
105
+ if (customerId && projectSlug) {
106
+ const value = { customerId, projectSlug };
107
+ setIdentity(value);
108
+ try {
109
+ localStorage.setItem(key, JSON.stringify(value));
110
+ } catch {
111
+ }
112
+ return;
113
+ }
114
+ try {
115
+ const raw = localStorage.getItem(key);
116
+ if (raw) setIdentity(JSON.parse(raw));
117
+ } catch {
118
+ }
119
+ }, [key, customerId, projectSlug]);
120
+ return identity;
121
+ }
122
+ var PaymentContext = createContext(null);
123
+ function usePayment() {
124
+ const ctx = useContext(PaymentContext);
125
+ if (!ctx) throw new Error("usePayment must be used within PaymentProvider");
126
+ return ctx;
127
+ }
128
+ function PaymentProvider({ children, ...config }) {
129
+ const identity = usePaymentIdentity({
130
+ linkId: config.linkId,
131
+ customerId: config.customerId,
132
+ projectSlug: config.projectSlug
133
+ });
134
+ const customerId = identity?.customerId ?? config.customerId;
135
+ const projectSlug = identity?.projectSlug ?? config.projectSlug;
136
+ const hook = usePaymentLink({
137
+ linkId: config.linkId,
138
+ baseUrl: config.baseUrl,
139
+ customerId,
140
+ onSuccess: config.onSuccess,
141
+ onError: config.onError
142
+ });
143
+ const resolvedConfig = { ...config, customerId, projectSlug };
144
+ return /* @__PURE__ */ jsx(PaymentContext.Provider, { value: { ...hook, config: resolvedConfig }, children });
145
+ }
146
+ function useCustomerPayments(options) {
147
+ const { projectSlug, customerId, baseUrl } = options;
148
+ const [payments, setPayments] = useState([]);
149
+ const [loading, setLoading] = useState(false);
150
+ const [error, setError] = useState(null);
151
+ const apiRef = useRef(null);
152
+ const enabled = Boolean(projectSlug && customerId);
153
+ useEffect(() => {
154
+ if (!enabled) return;
155
+ const resolved = resolveBaseUrl(baseUrl);
156
+ apiRef.current = createPaymentsApi(resolved);
157
+ let cancelled = false;
158
+ setLoading(true);
159
+ setError(null);
160
+ apiRef.current.payments_payments.customerInvoicesList().then((data) => {
161
+ if (!cancelled) {
162
+ const results = data?.results;
163
+ setPayments(Array.isArray(results) ? results : []);
164
+ setLoading(false);
165
+ }
166
+ }).catch((err) => {
167
+ if (!cancelled) {
168
+ const msg = err?.message ?? "Failed to load payment history";
169
+ console.warn("[useCustomerPayments]", msg);
170
+ setError(msg);
171
+ setLoading(false);
172
+ }
173
+ });
174
+ return () => {
175
+ cancelled = true;
176
+ };
177
+ }, [projectSlug, customerId, baseUrl, enabled]);
178
+ return { payments, loading, error };
179
+ }
180
+ function CustomerPaymentHistory() {
181
+ const { config } = usePayment();
182
+ const { payments, loading } = useCustomerPayments({
183
+ projectSlug: config.projectSlug,
184
+ customerId: config.customerId,
185
+ baseUrl: config.baseUrl
186
+ });
187
+ const enabled = Boolean(config.customerId && config.projectSlug);
188
+ const hasHistory = !loading && payments.length > 0;
189
+ if (!enabled || !hasHistory) return null;
190
+ const items = payments.map((p) => ({
191
+ id: p.id,
192
+ amount: `$${p.amount_usd}`,
193
+ status: p.status,
194
+ statusClass: `sdkr-pay-history-status sdkr-pay-history-status--${p.status}`,
195
+ date: new Date(p.created_at).toLocaleDateString()
196
+ }));
197
+ return /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-history", children: [
198
+ /* @__PURE__ */ jsx("div", { className: "sdkr-pay-history-title", children: "Your payments" }),
199
+ items.map((item) => /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-history-item", children: [
200
+ /* @__PURE__ */ jsx("span", { className: "sdkr-pay-history-amount", children: item.amount }),
201
+ /* @__PURE__ */ jsx("span", { className: item.statusClass, children: item.status }),
202
+ /* @__PURE__ */ jsx("span", { className: "sdkr-pay-history-date", children: item.date })
203
+ ] }, item.id))
204
+ ] });
205
+ }
206
+ function PaymentInfo() {
207
+ const { link, step } = usePayment();
208
+ if (!link || step === "status") return null;
209
+ return /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-info", children: [
210
+ /* @__PURE__ */ jsx("div", { className: "sdkr-pay-info-icon", children: /* @__PURE__ */ jsx(ShoppingBag, { size: 20 }) }),
211
+ /* @__PURE__ */ jsx("h1", { className: "sdkr-pay-title", children: link.title }),
212
+ link.description && /* @__PURE__ */ jsx("p", { className: "sdkr-pay-description", children: link.description }),
213
+ link.amountUsd != null && /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-amount-badge", children: [
214
+ /* @__PURE__ */ jsxs("span", { className: "sdkr-pay-amount-value", children: [
215
+ "$",
216
+ link.amountUsd.toFixed(2)
217
+ ] }),
218
+ /* @__PURE__ */ jsxs("span", { className: "sdkr-pay-amount-currency", children: [
219
+ "USDT",
220
+ link.network ? ` \xB7 ${link.network}` : ""
221
+ ] })
222
+ ] })
223
+ ] });
224
+ }
225
+
226
+ // src/types.ts
227
+ var MIN_AMOUNT_USD = 20;
228
+ var MAX_AMOUNT_USD = 5e4;
229
+ function PaymentForm() {
230
+ const { link, pay, isPaying, error, step, config } = usePayment();
231
+ const [form, setForm] = useState({
232
+ email: "",
233
+ name: "",
234
+ amountUsd: void 0
235
+ });
236
+ const [fieldErrors, setFieldErrors] = useState({});
237
+ if (!link || step === "status") return null;
238
+ const isCustomAmount = link.amountUsd == null;
239
+ const setField = (key, value) => {
240
+ setForm((prev) => ({ ...prev, [key]: value }));
241
+ setFieldErrors((prev) => {
242
+ const next = { ...prev };
243
+ delete next[key];
244
+ return next;
245
+ });
246
+ };
247
+ const handleSubmit = (e) => {
248
+ e.preventDefault();
249
+ const errors = {};
250
+ if (isCustomAmount) {
251
+ if (!form.amountUsd || form.amountUsd < MIN_AMOUNT_USD) {
252
+ errors.amountUsd = `Minimum $${MIN_AMOUNT_USD}`;
253
+ } else if (form.amountUsd > MAX_AMOUNT_USD) {
254
+ errors.amountUsd = `Maximum $${MAX_AMOUNT_USD.toLocaleString()}`;
255
+ }
256
+ }
257
+ if (form.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email)) {
258
+ errors.email = "Invalid email address";
259
+ }
260
+ if (Object.keys(errors).length > 0) {
261
+ setFieldErrors(errors);
262
+ return;
263
+ }
264
+ const data = {};
265
+ if (form.email) data.email = form.email;
266
+ if (form.name) data.name = form.name;
267
+ if (isCustomAmount && form.amountUsd) data.amountUsd = form.amountUsd;
268
+ if (config.customerId) data.externalId = config.customerId;
269
+ pay(data);
270
+ };
271
+ const displayAmount = isCustomAmount ? form.amountUsd ? `$${form.amountUsd.toFixed(2)}` : null : `$${link.amountUsd.toFixed(2)}`;
272
+ const visibleError = step === "form" ? error : null;
273
+ return /* @__PURE__ */ jsxs("form", { className: "sdkr-pay-form", onSubmit: handleSubmit, children: [
274
+ visibleError && /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-error", children: [
275
+ /* @__PURE__ */ jsx(AlertCircle, { size: 14 }),
276
+ /* @__PURE__ */ jsx("span", { children: visibleError })
277
+ ] }),
278
+ isCustomAmount && /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-field", children: [
279
+ /* @__PURE__ */ jsx("label", { className: "sdkr-pay-label", children: "Amount (USD)" }),
280
+ /* @__PURE__ */ jsx("div", { className: "sdkr-pay-amount-prefix", children: /* @__PURE__ */ jsx(
281
+ "input",
282
+ {
283
+ className: `sdkr-pay-input ${fieldErrors.amountUsd ? "sdkr-pay-input-error" : ""}`,
284
+ type: "number",
285
+ step: "0.01",
286
+ min: MIN_AMOUNT_USD,
287
+ inputMode: "decimal",
288
+ placeholder: "0.00",
289
+ value: form.amountUsd ?? "",
290
+ onChange: (e) => setField("amountUsd", e.target.value ? parseFloat(e.target.value) : void 0),
291
+ disabled: isPaying
292
+ }
293
+ ) }),
294
+ fieldErrors.amountUsd && /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-field-error", children: [
295
+ /* @__PURE__ */ jsx(AlertCircle, { size: 12 }),
296
+ fieldErrors.amountUsd
297
+ ] })
298
+ ] }),
299
+ /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-field", children: [
300
+ /* @__PURE__ */ jsxs("label", { className: "sdkr-pay-label", children: [
301
+ "Email ",
302
+ /* @__PURE__ */ jsx("span", { className: "sdkr-pay-label-optional", children: "(optional)" })
303
+ ] }),
304
+ /* @__PURE__ */ jsx(
305
+ "input",
306
+ {
307
+ className: `sdkr-pay-input ${fieldErrors.email ? "sdkr-pay-input-error" : ""}`,
308
+ type: "email",
309
+ inputMode: "email",
310
+ autoComplete: "email",
311
+ placeholder: "buyer@example.com",
312
+ value: form.email ?? "",
313
+ onChange: (e) => setField("email", e.target.value),
314
+ disabled: isPaying
315
+ }
316
+ ),
317
+ fieldErrors.email && /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-field-error", children: [
318
+ /* @__PURE__ */ jsx(AlertCircle, { size: 12 }),
319
+ fieldErrors.email
320
+ ] })
321
+ ] }),
322
+ /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-field", children: [
323
+ /* @__PURE__ */ jsxs("label", { className: "sdkr-pay-label", children: [
324
+ "Name ",
325
+ /* @__PURE__ */ jsx("span", { className: "sdkr-pay-label-optional", children: "(optional)" })
326
+ ] }),
327
+ /* @__PURE__ */ jsx(
328
+ "input",
329
+ {
330
+ className: "sdkr-pay-input",
331
+ type: "text",
332
+ autoComplete: "name",
333
+ placeholder: "John Doe",
334
+ value: form.name ?? "",
335
+ onChange: (e) => setField("name", e.target.value),
336
+ disabled: isPaying,
337
+ maxLength: 200
338
+ }
339
+ )
340
+ ] }),
341
+ /* @__PURE__ */ jsx("button", { className: "sdkr-pay-btn", type: "submit", disabled: isPaying, children: isPaying ? /* @__PURE__ */ jsxs("span", { className: "sdkr-pay-btn-content", children: [
342
+ /* @__PURE__ */ jsx(Loader2, { size: 16, className: "sdkr-pay-btn-spinner" }),
343
+ "Processing..."
344
+ ] }) : displayAmount ? `Pay ${displayAmount}` : "Pay" })
345
+ ] });
346
+ }
347
+ var POLL_INTERVAL = 15e3;
348
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["paid", "expired", "cancelled", "overpaid", "underpaid"]);
349
+ function useInvoicePolling(invoiceId, baseUrl, onPaid) {
350
+ const [invoiceStatus, setInvoiceStatus] = useState(null);
351
+ const [isPolling, setIsPolling] = useState(false);
352
+ const intervalRef = useRef(null);
353
+ const apiRef = useRef(null);
354
+ const stopPolling = useCallback(() => {
355
+ if (intervalRef.current) {
356
+ clearInterval(intervalRef.current);
357
+ intervalRef.current = null;
358
+ }
359
+ setIsPolling(false);
360
+ }, []);
361
+ const poll = useCallback(async () => {
362
+ if (!invoiceId || !apiRef.current) return;
363
+ try {
364
+ const resolved = resolveBaseUrl(baseUrl);
365
+ const resp = await fetch(`${resolved}/api/payments/invoices/${invoiceId}/status/`);
366
+ if (!resp.ok) return;
367
+ const data = await resp.json();
368
+ const status = {
369
+ invoiceId: data.invoice_id,
370
+ status: data.status,
371
+ confirmTimes: data.confirm_times || null,
372
+ txId: data.tx_id || null,
373
+ completedAt: data.completed_at || null
374
+ };
375
+ setInvoiceStatus(status);
376
+ if (TERMINAL_STATUSES.has(status.status)) {
377
+ stopPolling();
378
+ if (status.status === "paid") {
379
+ onPaid?.(status);
380
+ }
381
+ }
382
+ } catch {
383
+ }
384
+ }, [invoiceId, baseUrl, onPaid, stopPolling]);
385
+ useEffect(() => {
386
+ if (!invoiceId) return;
387
+ apiRef.current = createPaymentsApi(resolveBaseUrl(baseUrl));
388
+ setIsPolling(true);
389
+ poll();
390
+ intervalRef.current = setInterval(poll, POLL_INTERVAL);
391
+ return () => {
392
+ stopPolling();
393
+ };
394
+ }, [invoiceId]);
395
+ return { invoiceStatus, isPolling, stopPolling };
396
+ }
397
+ function useCountdown(expiresAt) {
398
+ const expiresAtMoment = useMemo(
399
+ () => expiresAt ? moment.utc(expiresAt) : null,
400
+ [expiresAt]
401
+ );
402
+ const [now, setNow] = useState(() => moment.utc());
403
+ useEffect(() => {
404
+ if (!expiresAtMoment) return;
405
+ const interval = setInterval(() => {
406
+ setNow(moment.utc());
407
+ }, 1e3);
408
+ return () => clearInterval(interval);
409
+ }, [expiresAtMoment]);
410
+ if (!expiresAtMoment) {
411
+ return { display: "--:--", totalSeconds: 0, isExpired: false, isUrgent: false, minutes: 0, seconds: 0 };
412
+ }
413
+ const diff = expiresAtMoment.diff(now, "seconds");
414
+ const totalSeconds = Math.max(0, diff);
415
+ const isExpired = totalSeconds <= 0;
416
+ const isUrgent = totalSeconds > 0 && totalSeconds < 300;
417
+ const hours = Math.floor(totalSeconds / 3600);
418
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
419
+ const seconds = totalSeconds % 60;
420
+ const pad = (n) => n.toString().padStart(2, "0");
421
+ const display = isExpired ? "Expired" : hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;
422
+ return { display, totalSeconds, isExpired, isUrgent, minutes, seconds };
423
+ }
424
+ function CopyButton({ text }) {
425
+ const [copied, setCopied] = useState(false);
426
+ const copy = useCallback(() => {
427
+ navigator.clipboard.writeText(text);
428
+ setCopied(true);
429
+ setTimeout(() => setCopied(false), 2e3);
430
+ }, [text]);
431
+ return /* @__PURE__ */ jsx("button", { onClick: copy, className: "sdkr-pay-copy-btn", title: "Copy to clipboard", children: copied ? /* @__PURE__ */ jsx(Check, { size: 14 }) : /* @__PURE__ */ jsx(Copy, { size: 14 }) });
432
+ }
433
+ var STATUS_CONFIG = {
434
+ waiting: {
435
+ icon: Clock,
436
+ iconClass: "sdkr-pay-status-icon--waiting",
437
+ title: "Awaiting Payment"
438
+ },
439
+ paid: {
440
+ icon: CircleCheck,
441
+ iconClass: "sdkr-pay-status-icon--paid",
442
+ title: "Payment Received"
443
+ },
444
+ expired: {
445
+ icon: CircleX,
446
+ iconClass: "sdkr-pay-status-icon--error",
447
+ title: "Payment Expired"
448
+ },
449
+ error: {
450
+ icon: CircleAlert,
451
+ iconClass: "sdkr-pay-status-icon--error",
452
+ title: "Payment Error"
453
+ }
454
+ };
455
+ function PaymentStatus() {
456
+ const { paymentResult, step, reset, config } = usePayment();
457
+ const invoiceId = paymentResult?.paymentId ?? null;
458
+ const { invoiceStatus, isPolling } = useInvoicePolling(
459
+ step === "status" && !paymentResult?.error ? invoiceId : null,
460
+ config.baseUrl
461
+ );
462
+ const countdown = useCountdown(paymentResult?.expiresAt ?? null);
463
+ if (step !== "status" || !paymentResult) return null;
464
+ const hasError = !!paymentResult.error;
465
+ const coin = paymentResult.coin || "USDT";
466
+ const network = paymentResult.network || "";
467
+ const isPaid = invoiceStatus?.status === "paid";
468
+ const isExpired = invoiceStatus?.status === "expired" || countdown.isExpired;
469
+ const isActive = !hasError && !isPaid && !isExpired;
470
+ const visualStatus = hasError ? "error" : isPaid ? "paid" : isExpired ? "expired" : "waiting";
471
+ const { icon: StatusLucide, iconClass, title } = STATUS_CONFIG[visualStatus];
472
+ const subtitle = hasError ? paymentResult.error || "Something went wrong" : isPaid ? invoiceStatus?.txId ? `Confirmed \xB7 ${invoiceStatus.txId.slice(0, 16)}...` : "Transaction confirmed" : isExpired ? "This invoice has expired" : "Send the exact amount to the address below";
473
+ return /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-status", children: [
474
+ /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-status-header", children: [
475
+ /* @__PURE__ */ jsx("div", { className: `sdkr-pay-status-icon ${iconClass}`, children: /* @__PURE__ */ jsx(StatusLucide, { size: 24 }) }),
476
+ /* @__PURE__ */ jsx("h2", { className: "sdkr-pay-status-title", children: title }),
477
+ /* @__PURE__ */ jsx("p", { className: "sdkr-pay-status-subtitle", children: subtitle })
478
+ ] }),
479
+ isActive && /* @__PURE__ */ jsxs(Fragment, { children: [
480
+ paymentResult.payAmount && /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-hero-amount", children: [
481
+ /* @__PURE__ */ jsx(Wallet, { size: 16, className: "sdkr-pay-hero-amount-icon" }),
482
+ /* @__PURE__ */ jsx("span", { className: "sdkr-pay-hero-amount-value", children: paymentResult.payAmount }),
483
+ /* @__PURE__ */ jsx("span", { className: "sdkr-pay-hero-amount-coin", children: coin }),
484
+ /* @__PURE__ */ jsx(CopyButton, { text: paymentResult.payAmount })
485
+ ] }),
486
+ paymentResult.payAddress && /* @__PURE__ */ jsx("div", { className: "sdkr-pay-qr", children: /* @__PURE__ */ jsx(
487
+ QRCode,
488
+ {
489
+ value: paymentResult.payAddress,
490
+ size: 160,
491
+ level: "M",
492
+ bgColor: "var(--sdkr-pay-qr-bg)",
493
+ fgColor: "var(--sdkr-pay-qr-fg)"
494
+ }
495
+ ) }),
496
+ paymentResult.payAddress && /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-detail", children: [
497
+ /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-detail-label", children: [
498
+ "Deposit Address",
499
+ network && /* @__PURE__ */ jsx("span", { className: "sdkr-pay-network-badge", children: network })
500
+ ] }),
501
+ /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-detail-value sdkr-pay-detail-mono sdkr-pay-detail-copyable", children: [
502
+ /* @__PURE__ */ jsx("span", { children: paymentResult.payAddress }),
503
+ /* @__PURE__ */ jsx(CopyButton, { text: paymentResult.payAddress })
504
+ ] })
505
+ ] }),
506
+ paymentResult.expiresAt && /* @__PURE__ */ jsxs("div", { className: `sdkr-pay-countdown ${countdown.isUrgent ? "sdkr-pay-countdown--urgent" : ""}`, children: [
507
+ /* @__PURE__ */ jsx(Clock, { size: 14, className: "sdkr-pay-countdown-icon" }),
508
+ /* @__PURE__ */ jsx("span", { className: "sdkr-pay-countdown-value", children: countdown.display })
509
+ ] }),
510
+ invoiceStatus?.confirmTimes && /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-confirmations", children: [
511
+ /* @__PURE__ */ jsx(Loader2, { size: 14, className: "sdkr-pay-confirmations-icon" }),
512
+ "Confirmations: ",
513
+ /* @__PURE__ */ jsx("strong", { children: invoiceStatus.confirmTimes })
514
+ ] }),
515
+ isPolling && !invoiceStatus?.confirmTimes && /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-polling", children: [
516
+ /* @__PURE__ */ jsx("span", { className: "sdkr-pay-polling-dot" }),
517
+ " Checking for payment..."
518
+ ] }),
519
+ /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-warning", children: [
520
+ /* @__PURE__ */ jsx(CircleAlert, { size: 12 }),
521
+ /* @__PURE__ */ jsxs("span", { children: [
522
+ "Send exactly ",
523
+ /* @__PURE__ */ jsxs("strong", { children: [
524
+ paymentResult.payAmount,
525
+ " ",
526
+ coin
527
+ ] }),
528
+ " \u2014 different amount won't be matched"
529
+ ] })
530
+ ] })
531
+ ] }),
532
+ /* @__PURE__ */ jsx("div", { className: "sdkr-pay-status-actions", children: /* @__PURE__ */ jsxs("button", { className: "sdkr-pay-btn sdkr-pay-btn--ghost", onClick: reset, children: [
533
+ /* @__PURE__ */ jsx(ArrowLeft, { size: 14 }),
534
+ hasError || isExpired ? "Try again" : isPaid ? "New payment" : "Cancel"
535
+ ] }) })
536
+ ] });
537
+ }
538
+ function PaymentContent() {
539
+ const { isLoading, error, step, link } = usePayment();
540
+ const showErrorOnly = Boolean(error) && step === "form" && !link;
541
+ if (isLoading) {
542
+ return /* @__PURE__ */ jsx("div", { className: "sdkr-pay-loading", children: /* @__PURE__ */ jsx("span", { className: "sdkr-pay-spinner" }) });
543
+ }
544
+ if (showErrorOnly) {
545
+ return /* @__PURE__ */ jsxs("div", { className: "sdkr-pay-error-page", children: [
546
+ /* @__PURE__ */ jsx("div", { className: "sdkr-pay-status-icon sdkr-pay-status-icon--error", children: /* @__PURE__ */ jsx(AlertCircle, { size: 24 }) }),
547
+ /* @__PURE__ */ jsx("p", { className: "sdkr-pay-error-text", children: error })
548
+ ] });
549
+ }
550
+ return /* @__PURE__ */ jsxs("div", { className: `sdkr-pay-content sdkr-pay-step--${step}`, children: [
551
+ /* @__PURE__ */ jsx(PaymentInfo, {}),
552
+ Boolean(link) && step !== "status" && /* @__PURE__ */ jsx("hr", { className: "sdkr-pay-separator" }),
553
+ /* @__PURE__ */ jsx(PaymentForm, {}),
554
+ /* @__PURE__ */ jsx(PaymentStatus, {}),
555
+ /* @__PURE__ */ jsx(CustomerPaymentHistory, {})
556
+ ] });
557
+ }
558
+
559
+ export { CustomerPaymentHistory, MAX_AMOUNT_USD, MIN_AMOUNT_USD, PaymentContent, PaymentForm, PaymentInfo, PaymentProvider, PaymentStatus, STYLE_ID, useCustomerPayments, usePayment, usePaymentIdentity, usePaymentLink };
560
+ //# sourceMappingURL=chunk-N3LT7RRW.mjs.map
561
+ //# sourceMappingURL=chunk-N3LT7RRW.mjs.map