@happyvertical/payments 0.79.0 → 0.80.1

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.
@@ -1,392 +0,0 @@
1
- import { b as PaymentProviderError, P as PaymentConfigurationError } from "./errors-BgFC46qQ.js";
2
- const TERMINAL_PAYMENT_STATUSES = /* @__PURE__ */ new Set([
3
- "confirmed",
4
- "failed",
5
- "expired",
6
- "refunded"
7
- ]);
8
- const DEFAULT_MAX_STORED_PAYMENT_OPTIONS = 1e3;
9
- const MAX_DECIMAL_PRECISION = 100;
10
- const ZERO_DECIMAL_CURRENCIES = /* @__PURE__ */ new Set([
11
- "BIF",
12
- "CLP",
13
- "DJF",
14
- "GNF",
15
- "JPY",
16
- "KMF",
17
- "KRW",
18
- "MGA",
19
- "PYG",
20
- "RWF",
21
- "VND",
22
- "VUV",
23
- "XAF",
24
- "XOF",
25
- "XPF"
26
- ]);
27
- const THREE_DECIMAL_CURRENCIES = /* @__PURE__ */ new Set([
28
- "BHD",
29
- "IQD",
30
- "JOD",
31
- "KWD",
32
- "LYD",
33
- "OMR",
34
- "TND"
35
- ]);
36
- const TWO_DECIMAL_WHOLE_UNIT_CURRENCIES = /* @__PURE__ */ new Set(["ISK", "UGX"]);
37
- function getFetch(fetchLike) {
38
- const resolved = fetchLike ?? globalThis.fetch;
39
- if (!resolved) {
40
- throw new PaymentProviderError(
41
- "A fetch implementation is required in this runtime."
42
- );
43
- }
44
- if (typeof resolved !== "function") {
45
- throw new PaymentProviderError("Fetch implementation must be a function.");
46
- }
47
- return resolved.bind(globalThis);
48
- }
49
- function normalizeDate(value) {
50
- if (!(value instanceof Date) && typeof value !== "string") {
51
- throw new PaymentProviderError(`Invalid date value: ${String(value)}`);
52
- }
53
- const date = value instanceof Date ? value : new Date(value);
54
- if (Number.isNaN(date.getTime())) {
55
- throw new PaymentProviderError(`Invalid date value: ${String(value)}`);
56
- }
57
- return date;
58
- }
59
- function normalizeFutureDate(value, context) {
60
- const date = normalizeDate(value);
61
- if (date.getTime() <= Date.now()) {
62
- throw new PaymentProviderError(`${context} is in the past.`);
63
- }
64
- return date;
65
- }
66
- function normalizeAmount(value) {
67
- if (typeof value !== "string") {
68
- throw new PaymentProviderError("Monetary amounts must be decimal strings.");
69
- }
70
- const raw = value.trim();
71
- if (!/^\d+(\.\d+)?$/.test(raw)) {
72
- throw new PaymentProviderError(`Invalid amount value: ${String(value)}`);
73
- }
74
- const [whole, fraction] = raw.split(".");
75
- const normalizedWhole = whole.replace(/^0+(?=\d)/, "") || "0";
76
- const normalizedFraction = fraction?.replace(/0+$/, "");
77
- return normalizedFraction ? `${normalizedWhole}.${normalizedFraction}` : normalizedWhole;
78
- }
79
- function normalizeCurrency(value, context) {
80
- if (typeof value !== "string") {
81
- throw new PaymentProviderError(`${context} currency must be a string.`);
82
- }
83
- const normalized = value.trim().toUpperCase();
84
- if (!/^[A-Z0-9]{3,10}$/.test(normalized)) {
85
- throw new PaymentProviderError(
86
- `${context} currency must be a currency code, received ${String(value)}.`
87
- );
88
- }
89
- return normalized;
90
- }
91
- function normalizeMinorUnitAmount(value, context) {
92
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
93
- throw new PaymentProviderError(
94
- `${context} must be a non-negative integer in the smallest currency unit, received ${String(value)}.`
95
- );
96
- }
97
- return value;
98
- }
99
- function normalizePositiveMinorUnitAmount(value, context) {
100
- const amount = normalizeMinorUnitAmount(value, context);
101
- if (amount === 0) {
102
- throw new PaymentProviderError(`${context} must be greater than zero.`);
103
- }
104
- return amount;
105
- }
106
- function normalizePositivePaymentAmount(value, currency, context) {
107
- const amount = normalizePositiveMinorUnitAmount(value, context);
108
- const normalizedCurrency = normalizeCurrency(currency, context);
109
- if (TWO_DECIMAL_WHOLE_UNIT_CURRENCIES.has(normalizedCurrency) && amount % 100 !== 0) {
110
- throw new PaymentProviderError(
111
- `${context} for ${normalizedCurrency} must be evenly divisible by 100.`
112
- );
113
- }
114
- return amount;
115
- }
116
- function normalizeMaxStoredPaymentOptions(value, context) {
117
- if (value === void 0) {
118
- return DEFAULT_MAX_STORED_PAYMENT_OPTIONS;
119
- }
120
- if (!Number.isSafeInteger(value) || value <= 0) {
121
- throw new PaymentConfigurationError(
122
- `${context} must be a positive safe integer.`
123
- );
124
- }
125
- return value;
126
- }
127
- function rememberPaymentOption(optionsByQuote, quoteId, option, maxStoredPaymentOptions) {
128
- optionsByQuote.delete(quoteId);
129
- optionsByQuote.set(quoteId, option);
130
- while (optionsByQuote.size > maxStoredPaymentOptions) {
131
- const oldestQuoteId = optionsByQuote.keys().next().value;
132
- if (oldestQuoteId === void 0) {
133
- return;
134
- }
135
- optionsByQuote.delete(oldestQuoteId);
136
- }
137
- }
138
- function normalizeNonEmptyString(value, context) {
139
- if (typeof value !== "string") {
140
- throw new PaymentProviderError(`${context} must be a string.`);
141
- }
142
- const normalized = value.trim();
143
- if (!normalized) {
144
- throw new PaymentProviderError(`${context} must not be empty.`);
145
- }
146
- return normalized;
147
- }
148
- function normalizeUrlString(value, context) {
149
- const normalized = normalizeNonEmptyString(value, context);
150
- try {
151
- const url = new URL(normalized);
152
- if (!["http:", "https:"].includes(url.protocol)) {
153
- throw new PaymentConfigurationError(`${context} must use http or https.`);
154
- }
155
- } catch (error) {
156
- if (error instanceof PaymentConfigurationError) {
157
- throw error;
158
- }
159
- throw new PaymentConfigurationError(`${context} must be a valid URL.`, {
160
- cause: error
161
- });
162
- }
163
- return normalized;
164
- }
165
- function decimalToAtomicUnits(value, decimals) {
166
- const precision = normalizeDecimalPrecision(decimals);
167
- const normalized = normalizeAmount(value);
168
- const [whole, fraction = ""] = normalized.split(".");
169
- if (fraction.length > precision) {
170
- throw new PaymentProviderError(
171
- `Amount ${String(value)} has more than ${precision} decimal places.`
172
- );
173
- }
174
- const padded = `${fraction}${"0".repeat(precision)}`.slice(0, precision);
175
- const combined = `${whole}${padded}`.replace(/^0+(?=\d)/, "");
176
- return combined || "0";
177
- }
178
- function atomicUnitsToDecimal(value, decimals) {
179
- const precision = normalizeDecimalPrecision(decimals);
180
- if (typeof value !== "string" && typeof value !== "bigint") {
181
- throw new PaymentProviderError(
182
- `Invalid atomic amount value: ${String(value)}`
183
- );
184
- }
185
- const raw = typeof value === "bigint" ? value.toString() : value;
186
- if (!/^\d+$/.test(raw)) {
187
- throw new PaymentProviderError(
188
- `Invalid atomic amount value: ${String(value)}`
189
- );
190
- }
191
- if (precision === 0) {
192
- return raw || "0";
193
- }
194
- const padded = raw.padStart(precision + 1, "0");
195
- const whole = padded.slice(0, -precision);
196
- const fraction = padded.slice(-precision).replace(/0+$/, "");
197
- return fraction ? `${whole}.${fraction}` : whole;
198
- }
199
- function minorUnitsToDecimal(value, decimals) {
200
- return atomicUnitsToDecimal(
201
- BigInt(normalizeMinorUnitAmount(value, "Minor-unit")),
202
- decimals
203
- );
204
- }
205
- function decimalToMinorUnitAmount(value, decimals, context) {
206
- const atomic = typeof value === "bigint" ? value : BigInt(decimalToAtomicUnits(value, decimals));
207
- if (atomic < 0n) {
208
- throw new PaymentProviderError(
209
- `Invalid atomic amount value: ${String(value)}`
210
- );
211
- }
212
- if (atomic > BigInt(Number.MAX_SAFE_INTEGER)) {
213
- throw new PaymentProviderError(
214
- `${context} amount exceeds JavaScript's safe integer range.`
215
- );
216
- }
217
- return Number(atomic);
218
- }
219
- function currencyMinorUnitDecimals(currency) {
220
- const normalized = normalizeCurrency(currency, "Payment");
221
- if (normalized === "BTC") {
222
- return 8;
223
- }
224
- if (normalized === "USDC") {
225
- return 6;
226
- }
227
- if (THREE_DECIMAL_CURRENCIES.has(normalized)) {
228
- return 3;
229
- }
230
- return ZERO_DECIMAL_CURRENCIES.has(normalized) ? 0 : 2;
231
- }
232
- function applyExpiryToPendingStatus(status, expiresAt) {
233
- if (!expiresAt || expiresAt >= /* @__PURE__ */ new Date()) {
234
- return status;
235
- }
236
- return status === "pending" || status === "requires_action" ? "expired" : status;
237
- }
238
- function normalizeDecimalPrecision(decimals) {
239
- if (!Number.isSafeInteger(decimals) || decimals < 0 || decimals > MAX_DECIMAL_PRECISION) {
240
- throw new PaymentProviderError(
241
- `Invalid decimal precision: ${String(decimals)}`
242
- );
243
- }
244
- return decimals;
245
- }
246
- function sleep(ms, signal) {
247
- if (signal?.aborted) {
248
- return Promise.reject(signal.reason);
249
- }
250
- return new Promise((resolve, reject) => {
251
- let timeout;
252
- const handleAbort = () => {
253
- clearTimeout(timeout);
254
- reject(signal?.reason);
255
- };
256
- const handleResolve = () => {
257
- signal?.removeEventListener("abort", handleAbort);
258
- resolve();
259
- };
260
- timeout = setTimeout(handleResolve, ms);
261
- signal?.addEventListener("abort", handleAbort, { once: true });
262
- });
263
- }
264
- async function* pollPaymentStatus(input, getStatus) {
265
- const startedAt = Date.now();
266
- const pollIntervalMs = normalizePollIntervalMs(input.pollIntervalMs ?? 5e3);
267
- const timeoutMs = input.timeoutMs === void 0 ? void 0 : normalizeTimeoutMs(input.timeoutMs);
268
- let lastStatus;
269
- let lastResult;
270
- const remainingTimeoutMs = () => timeoutMs === void 0 ? void 0 : timeoutMs - (Date.now() - startedAt);
271
- const yieldTimeoutEvent = async () => ({
272
- ...lastResult ?? await getStatus(),
273
- event: "timeout",
274
- status: lastResult?.status ?? "pending",
275
- updatedAt: /* @__PURE__ */ new Date()
276
- });
277
- while (!input.signal?.aborted) {
278
- if ((remainingTimeoutMs() ?? 1) <= 0) {
279
- yield await yieldTimeoutEvent();
280
- return;
281
- }
282
- const status = await getStatus();
283
- lastResult = status;
284
- if (status.status !== lastStatus) {
285
- const event = toPaymentEvent(status);
286
- yield event;
287
- lastStatus = status.status;
288
- if (TERMINAL_PAYMENT_STATUSES.has(status.status)) {
289
- return;
290
- }
291
- }
292
- const remaining = remainingTimeoutMs();
293
- if (remaining !== void 0 && remaining <= 0) {
294
- yield await yieldTimeoutEvent();
295
- return;
296
- }
297
- await sleep(
298
- remaining === void 0 ? pollIntervalMs : Math.min(pollIntervalMs, remaining),
299
- input.signal
300
- );
301
- }
302
- }
303
- function normalizePollIntervalMs(value) {
304
- if (!Number.isInteger(value) || value <= 0) {
305
- throw new PaymentProviderError(
306
- `pollIntervalMs must be a positive integer, received ${String(value)}.`
307
- );
308
- }
309
- return value;
310
- }
311
- function normalizeTimeoutMs(value) {
312
- if (!Number.isInteger(value) || value < 0) {
313
- throw new PaymentProviderError(
314
- `timeoutMs must be a non-negative integer, received ${String(value)}.`
315
- );
316
- }
317
- return value;
318
- }
319
- function toPaymentEvent(status) {
320
- if (status.status === "confirmed") {
321
- return { ...status, event: "confirmed" };
322
- }
323
- if (status.status === "failed") {
324
- return { ...status, event: "failed" };
325
- }
326
- if (status.status === "expired") {
327
- return { ...status, event: "expired" };
328
- }
329
- if (status.status === "refunded") {
330
- return { ...status, event: "refunded" };
331
- }
332
- return { ...status, event: "status" };
333
- }
334
- async function readJsonResponse(response, context) {
335
- const text = await response.text();
336
- let body;
337
- if (text) {
338
- try {
339
- body = JSON.parse(text);
340
- } catch (error) {
341
- if (response.ok) {
342
- throw new PaymentProviderError(`${context}: invalid JSON response`, {
343
- cause: error
344
- });
345
- }
346
- body = void 0;
347
- }
348
- }
349
- if (!response.ok) {
350
- const message = body && typeof body === "object" && "message" in body ? String(body.message) : body && typeof body === "object" && typeof body.error === "string" ? String(body.error) : body && typeof body === "object" && "error" in body && typeof body.error?.message === "string" ? body.error.message : text || response.statusText;
351
- throw new PaymentProviderError(`${context}: ${message}`, {
352
- retryable: response.status >= 500
353
- });
354
- }
355
- if (body === void 0) {
356
- throw new PaymentProviderError(`${context}: empty response body`);
357
- }
358
- return body;
359
- }
360
- function formEncode(params) {
361
- const searchParams = new URLSearchParams();
362
- for (const [key, value] of Object.entries(params)) {
363
- if (value === void 0 || value === null) {
364
- continue;
365
- }
366
- searchParams.set(key, String(value));
367
- }
368
- return searchParams.toString();
369
- }
370
- export {
371
- normalizeMaxStoredPaymentOptions as a,
372
- normalizeUrlString as b,
373
- normalizeFutureDate as c,
374
- normalizeCurrency as d,
375
- normalizePositiveMinorUnitAmount as e,
376
- decimalToMinorUnitAmount as f,
377
- getFetch as g,
378
- normalizeDate as h,
379
- normalizeMinorUnitAmount as i,
380
- readJsonResponse as j,
381
- currencyMinorUnitDecimals as k,
382
- decimalToAtomicUnits as l,
383
- minorUnitsToDecimal as m,
384
- normalizeNonEmptyString as n,
385
- normalizePositivePaymentAmount as o,
386
- pollPaymentStatus as p,
387
- normalizeAmount as q,
388
- rememberPaymentOption as r,
389
- applyExpiryToPendingStatus as s,
390
- formEncode as t
391
- };
392
- //# sourceMappingURL=shared-DGHSqDQT.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shared-DGHSqDQT.js","sources":["../../src/shared.ts"],"sourcesContent":["import {\n PaymentConfigurationError,\n PaymentProviderError,\n PaymentUnsupportedError,\n} from './errors.js';\nimport type {\n PaymentEvent,\n PaymentStatus,\n PaymentStatusResult,\n WatchPaymentInput,\n} from './types.js';\n\nexport type FetchLike = (\n input: string | URL | Request,\n init?: RequestInit,\n) => Promise<Response>;\n\nexport const TERMINAL_PAYMENT_STATUSES = new Set<PaymentStatus>([\n 'confirmed',\n 'failed',\n 'expired',\n 'refunded',\n]);\nexport const DEFAULT_MAX_STORED_PAYMENT_OPTIONS = 1_000;\nconst MAX_DECIMAL_PRECISION = 100;\nconst ZERO_DECIMAL_CURRENCIES = new Set([\n 'BIF',\n 'CLP',\n 'DJF',\n 'GNF',\n 'JPY',\n 'KMF',\n 'KRW',\n 'MGA',\n 'PYG',\n 'RWF',\n 'VND',\n 'VUV',\n 'XAF',\n 'XOF',\n 'XPF',\n]);\nconst THREE_DECIMAL_CURRENCIES = new Set([\n 'BHD',\n 'IQD',\n 'JOD',\n 'KWD',\n 'LYD',\n 'OMR',\n 'TND',\n]);\nconst TWO_DECIMAL_WHOLE_UNIT_CURRENCIES = new Set(['ISK', 'UGX']);\n\nexport function getFetch(fetchLike?: FetchLike): FetchLike {\n const resolved = fetchLike ?? globalThis.fetch;\n\n if (!resolved) {\n throw new PaymentProviderError(\n 'A fetch implementation is required in this runtime.',\n );\n }\n\n if (typeof resolved !== 'function') {\n throw new PaymentProviderError('Fetch implementation must be a function.');\n }\n\n return resolved.bind(globalThis) as FetchLike;\n}\n\nexport function normalizeDate(value: Date | string): Date {\n if (!(value instanceof Date) && typeof value !== 'string') {\n throw new PaymentProviderError(`Invalid date value: ${String(value)}`);\n }\n\n const date = value instanceof Date ? value : new Date(value);\n\n if (Number.isNaN(date.getTime())) {\n throw new PaymentProviderError(`Invalid date value: ${String(value)}`);\n }\n\n return date;\n}\n\nexport function normalizeFutureDate(\n value: Date | string,\n context: string,\n): Date {\n const date = normalizeDate(value);\n\n if (date.getTime() <= Date.now()) {\n throw new PaymentProviderError(`${context} is in the past.`);\n }\n\n return date;\n}\n\nexport function normalizeAmount(value: string): string {\n if (typeof value !== 'string') {\n throw new PaymentProviderError('Monetary amounts must be decimal strings.');\n }\n\n const raw = value.trim();\n\n if (!/^\\d+(\\.\\d+)?$/.test(raw)) {\n throw new PaymentProviderError(`Invalid amount value: ${String(value)}`);\n }\n\n const [whole, fraction] = raw.split('.');\n const normalizedWhole = whole.replace(/^0+(?=\\d)/, '') || '0';\n const normalizedFraction = fraction?.replace(/0+$/, '');\n\n return normalizedFraction\n ? `${normalizedWhole}.${normalizedFraction}`\n : normalizedWhole;\n}\n\nexport function normalizePositiveAmount(\n value: string,\n context: string,\n): string {\n const amount = normalizeAmount(value);\n\n if (amount === '0') {\n throw new PaymentProviderError(`${context} must be greater than zero.`);\n }\n\n return amount;\n}\n\nexport function normalizeCurrency(value: string, context: string): string {\n if (typeof value !== 'string') {\n throw new PaymentProviderError(`${context} currency must be a string.`);\n }\n\n const normalized = value.trim().toUpperCase();\n\n if (!/^[A-Z0-9]{3,10}$/.test(normalized)) {\n throw new PaymentProviderError(\n `${context} currency must be a currency code, received ${String(value)}.`,\n );\n }\n\n return normalized;\n}\n\nexport function normalizeMinorUnitAmount(\n value: number,\n context: string,\n): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0) {\n throw new PaymentProviderError(\n `${context} must be a non-negative integer in the smallest currency unit, received ${String(value)}.`,\n );\n }\n\n return value;\n}\n\nexport function normalizePositiveMinorUnitAmount(\n value: number,\n context: string,\n): number {\n const amount = normalizeMinorUnitAmount(value, context);\n\n if (amount === 0) {\n throw new PaymentProviderError(`${context} must be greater than zero.`);\n }\n\n return amount;\n}\n\nexport function normalizePositivePaymentAmount(\n value: number,\n currency: string,\n context: string,\n): number {\n const amount = normalizePositiveMinorUnitAmount(value, context);\n const normalizedCurrency = normalizeCurrency(currency, context);\n\n if (\n TWO_DECIMAL_WHOLE_UNIT_CURRENCIES.has(normalizedCurrency) &&\n amount % 100 !== 0\n ) {\n throw new PaymentProviderError(\n `${context} for ${normalizedCurrency} must be evenly divisible by 100.`,\n );\n }\n\n return amount;\n}\n\nexport function normalizeMaxStoredPaymentOptions(\n value: number | undefined,\n context: string,\n): number {\n if (value === undefined) {\n return DEFAULT_MAX_STORED_PAYMENT_OPTIONS;\n }\n\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new PaymentConfigurationError(\n `${context} must be a positive safe integer.`,\n );\n }\n\n return value;\n}\n\nexport function rememberPaymentOption<TOption>(\n optionsByQuote: Map<string, TOption>,\n quoteId: string,\n option: TOption,\n maxStoredPaymentOptions: number,\n): void {\n optionsByQuote.delete(quoteId);\n optionsByQuote.set(quoteId, option);\n\n while (optionsByQuote.size > maxStoredPaymentOptions) {\n const oldestQuoteId = optionsByQuote.keys().next().value;\n\n if (oldestQuoteId === undefined) {\n return;\n }\n\n optionsByQuote.delete(oldestQuoteId);\n }\n}\n\nexport function normalizeNonEmptyString(\n value: string,\n context: string,\n): string {\n if (typeof value !== 'string') {\n throw new PaymentProviderError(`${context} must be a string.`);\n }\n\n const normalized = value.trim();\n\n if (!normalized) {\n throw new PaymentProviderError(`${context} must not be empty.`);\n }\n\n return normalized;\n}\n\nexport function normalizeUrlString(value: string, context: string): string {\n const normalized = normalizeNonEmptyString(value, context);\n\n try {\n const url = new URL(normalized);\n\n if (!['http:', 'https:'].includes(url.protocol)) {\n throw new PaymentConfigurationError(`${context} must use http or https.`);\n }\n } catch (error) {\n if (error instanceof PaymentConfigurationError) {\n throw error;\n }\n\n throw new PaymentConfigurationError(`${context} must be a valid URL.`, {\n cause: error,\n });\n }\n\n return normalized;\n}\n\nexport function decimalToAtomicUnits(value: string, decimals: number): string {\n const precision = normalizeDecimalPrecision(decimals);\n\n const normalized = normalizeAmount(value);\n const [whole, fraction = ''] = normalized.split('.');\n\n if (fraction.length > precision) {\n throw new PaymentProviderError(\n `Amount ${String(value)} has more than ${precision} decimal places.`,\n );\n }\n\n const padded = `${fraction}${'0'.repeat(precision)}`.slice(0, precision);\n const combined = `${whole}${padded}`.replace(/^0+(?=\\d)/, '');\n\n return combined || '0';\n}\n\nexport function atomicUnitsToDecimal(\n value: string | bigint,\n decimals: number,\n): string {\n const precision = normalizeDecimalPrecision(decimals);\n\n if (typeof value !== 'string' && typeof value !== 'bigint') {\n throw new PaymentProviderError(\n `Invalid atomic amount value: ${String(value)}`,\n );\n }\n\n const raw = typeof value === 'bigint' ? value.toString() : value;\n\n if (!/^\\d+$/.test(raw)) {\n throw new PaymentProviderError(\n `Invalid atomic amount value: ${String(value)}`,\n );\n }\n\n if (precision === 0) {\n return raw || '0';\n }\n\n const padded = raw.padStart(precision + 1, '0');\n const whole = padded.slice(0, -precision);\n const fraction = padded.slice(-precision).replace(/0+$/, '');\n\n return fraction ? `${whole}.${fraction}` : whole;\n}\n\nexport function amountToMinorUnits(value: string, decimals = 2): string {\n return decimalToAtomicUnits(value, decimals);\n}\n\nexport function minorUnitsToDecimal(value: number, decimals: number): string {\n return atomicUnitsToDecimal(\n BigInt(normalizeMinorUnitAmount(value, 'Minor-unit')),\n decimals,\n );\n}\n\nexport function decimalToMinorUnitAmount(\n value: string | bigint,\n decimals: number,\n context: string,\n): number {\n const atomic =\n typeof value === 'bigint'\n ? value\n : BigInt(decimalToAtomicUnits(value, decimals));\n\n if (atomic < 0n) {\n throw new PaymentProviderError(\n `Invalid atomic amount value: ${String(value)}`,\n );\n }\n\n if (atomic > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new PaymentProviderError(\n `${context} amount exceeds JavaScript's safe integer range.`,\n );\n }\n\n return Number(atomic);\n}\n\nexport function currencyMinorUnitDecimals(currency: string): number {\n const normalized = normalizeCurrency(currency, 'Payment');\n\n if (normalized === 'BTC') {\n return 8;\n }\n\n if (normalized === 'USDC') {\n return 6;\n }\n\n if (THREE_DECIMAL_CURRENCIES.has(normalized)) {\n return 3;\n }\n\n return ZERO_DECIMAL_CURRENCIES.has(normalized) ? 0 : 2;\n}\n\nexport function applyExpiryToPendingStatus(\n status: PaymentStatus,\n expiresAt?: Date,\n): PaymentStatus {\n if (!expiresAt || expiresAt >= new Date()) {\n return status;\n }\n\n return status === 'pending' || status === 'requires_action'\n ? 'expired'\n : status;\n}\n\nfunction normalizeDecimalPrecision(decimals: number): number {\n if (\n !Number.isSafeInteger(decimals) ||\n decimals < 0 ||\n decimals > MAX_DECIMAL_PRECISION\n ) {\n throw new PaymentProviderError(\n `Invalid decimal precision: ${String(decimals)}`,\n );\n }\n\n return decimals;\n}\n\nexport function compareDecimalAmounts(left: string, right: string): -1 | 0 | 1 {\n const [leftWhole, leftFraction = ''] = normalizeAmount(left).split('.');\n const [rightWhole, rightFraction = ''] = normalizeAmount(right).split('.');\n const leftWholeValue = BigInt(leftWhole ?? '0');\n const rightWholeValue = BigInt(rightWhole ?? '0');\n\n if (leftWholeValue > rightWholeValue) {\n return 1;\n }\n\n if (leftWholeValue < rightWholeValue) {\n return -1;\n }\n\n const scale = Math.max(leftFraction.length, rightFraction.length);\n const leftFractionValue = BigInt(\n (leftFraction + '0'.repeat(scale)).slice(0, scale) || '0',\n );\n const rightFractionValue = BigInt(\n (rightFraction + '0'.repeat(scale)).slice(0, scale) || '0',\n );\n\n if (leftFractionValue > rightFractionValue) {\n return 1;\n }\n\n if (leftFractionValue < rightFractionValue) {\n return -1;\n }\n\n return 0;\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason);\n }\n\n return new Promise((resolve, reject) => {\n let timeout: ReturnType<typeof setTimeout>;\n const handleAbort = (): void => {\n clearTimeout(timeout);\n reject(signal?.reason);\n };\n const handleResolve = (): void => {\n signal?.removeEventListener('abort', handleAbort);\n resolve();\n };\n\n timeout = setTimeout(handleResolve, ms);\n signal?.addEventListener('abort', handleAbort, { once: true });\n });\n}\n\nexport async function* pollPaymentStatus(\n input: WatchPaymentInput,\n getStatus: () => Promise<PaymentStatusResult>,\n): AsyncIterable<PaymentEvent> {\n const startedAt = Date.now();\n const pollIntervalMs = normalizePollIntervalMs(input.pollIntervalMs ?? 5_000);\n const timeoutMs =\n input.timeoutMs === undefined\n ? undefined\n : normalizeTimeoutMs(input.timeoutMs);\n let lastStatus: PaymentStatus | undefined;\n let lastResult: PaymentStatusResult | undefined;\n\n const remainingTimeoutMs = (): number | undefined =>\n timeoutMs === undefined ? undefined : timeoutMs - (Date.now() - startedAt);\n\n const yieldTimeoutEvent = async (): Promise<PaymentEvent> => ({\n ...(lastResult ?? (await getStatus())),\n event: 'timeout',\n status: lastResult?.status ?? 'pending',\n updatedAt: new Date(),\n });\n\n while (!input.signal?.aborted) {\n if ((remainingTimeoutMs() ?? 1) <= 0) {\n yield await yieldTimeoutEvent();\n return;\n }\n\n const status = await getStatus();\n lastResult = status;\n\n if (status.status !== lastStatus) {\n const event = toPaymentEvent(status);\n yield event;\n lastStatus = status.status;\n\n if (TERMINAL_PAYMENT_STATUSES.has(status.status)) {\n return;\n }\n }\n\n const remaining = remainingTimeoutMs();\n\n if (remaining !== undefined && remaining <= 0) {\n yield await yieldTimeoutEvent();\n return;\n }\n\n await sleep(\n remaining === undefined\n ? pollIntervalMs\n : Math.min(pollIntervalMs, remaining),\n input.signal,\n );\n }\n}\n\nfunction normalizePollIntervalMs(value: number): number {\n if (!Number.isInteger(value) || value <= 0) {\n throw new PaymentProviderError(\n `pollIntervalMs must be a positive integer, received ${String(value)}.`,\n );\n }\n\n return value;\n}\n\nfunction normalizeTimeoutMs(value: number): number {\n if (!Number.isInteger(value) || value < 0) {\n throw new PaymentProviderError(\n `timeoutMs must be a non-negative integer, received ${String(value)}.`,\n );\n }\n\n return value;\n}\n\nexport function toPaymentEvent(status: PaymentStatusResult): PaymentEvent {\n if (status.status === 'confirmed') {\n return { ...status, event: 'confirmed' };\n }\n\n if (status.status === 'failed') {\n return { ...status, event: 'failed' };\n }\n\n if (status.status === 'expired') {\n return { ...status, event: 'expired' };\n }\n\n if (status.status === 'refunded') {\n return { ...status, event: 'refunded' };\n }\n\n return { ...status, event: 'status' };\n}\n\nexport async function readJsonResponse<T>(\n response: Response,\n context: string,\n): Promise<T> {\n const text = await response.text();\n let body: unknown;\n\n if (text) {\n try {\n body = JSON.parse(text);\n } catch (error) {\n if (response.ok) {\n throw new PaymentProviderError(`${context}: invalid JSON response`, {\n cause: error,\n });\n }\n\n body = undefined;\n }\n }\n\n if (!response.ok) {\n const message =\n body && typeof body === 'object' && 'message' in body\n ? String((body as { message: unknown }).message)\n : body &&\n typeof body === 'object' &&\n typeof (body as { error?: unknown }).error === 'string'\n ? String((body as { error: string }).error)\n : body &&\n typeof body === 'object' &&\n 'error' in body &&\n typeof (body as { error?: { message?: unknown } }).error\n ?.message === 'string'\n ? (body as { error: { message: string } }).error.message\n : text || response.statusText;\n\n throw new PaymentProviderError(`${context}: ${message}`, {\n retryable: response.status >= 500,\n });\n }\n\n if (body === undefined) {\n throw new PaymentProviderError(`${context}: empty response body`);\n }\n\n return body as T;\n}\n\nexport function formEncode(params: Record<string, unknown>): string {\n const searchParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n searchParams.set(key, String(value));\n }\n\n return searchParams.toString();\n}\n\nexport function throwUnsupported(message: string): never {\n throw new PaymentUnsupportedError(message);\n}\n"],"names":[],"mappings":";AAiBO,MAAM,gDAAgC,IAAmB;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACM,MAAM,qCAAqC;AAClD,MAAM,wBAAwB;AAC9B,MAAM,8CAA8B,IAAI;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,MAAM,+CAA+B,IAAI;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,MAAM,oCAAoC,oBAAI,IAAI,CAAC,OAAO,KAAK,CAAC;AAEzD,SAAS,SAAS,WAAkC;AACzD,QAAM,WAAW,aAAa,WAAW;AAEzC,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,MAAI,OAAO,aAAa,YAAY;AAClC,UAAM,IAAI,qBAAqB,0CAA0C;AAAA,EAC3E;AAEA,SAAO,SAAS,KAAK,UAAU;AACjC;AAEO,SAAS,cAAc,OAA4B;AACxD,MAAI,EAAE,iBAAiB,SAAS,OAAO,UAAU,UAAU;AACzD,UAAM,IAAI,qBAAqB,uBAAuB,OAAO,KAAK,CAAC,EAAE;AAAA,EACvE;AAEA,QAAM,OAAO,iBAAiB,OAAO,QAAQ,IAAI,KAAK,KAAK;AAE3D,MAAI,OAAO,MAAM,KAAK,QAAA,CAAS,GAAG;AAChC,UAAM,IAAI,qBAAqB,uBAAuB,OAAO,KAAK,CAAC,EAAE;AAAA,EACvE;AAEA,SAAO;AACT;AAEO,SAAS,oBACd,OACA,SACM;AACN,QAAM,OAAO,cAAc,KAAK;AAEhC,MAAI,KAAK,QAAA,KAAa,KAAK,OAAO;AAChC,UAAM,IAAI,qBAAqB,GAAG,OAAO,kBAAkB;AAAA,EAC7D;AAEA,SAAO;AACT;AAEO,SAAS,gBAAgB,OAAuB;AACrD,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI,qBAAqB,2CAA2C;AAAA,EAC5E;AAEA,QAAM,MAAM,MAAM,KAAA;AAElB,MAAI,CAAC,gBAAgB,KAAK,GAAG,GAAG;AAC9B,UAAM,IAAI,qBAAqB,yBAAyB,OAAO,KAAK,CAAC,EAAE;AAAA,EACzE;AAEA,QAAM,CAAC,OAAO,QAAQ,IAAI,IAAI,MAAM,GAAG;AACvC,QAAM,kBAAkB,MAAM,QAAQ,aAAa,EAAE,KAAK;AAC1D,QAAM,qBAAqB,UAAU,QAAQ,OAAO,EAAE;AAEtD,SAAO,qBACH,GAAG,eAAe,IAAI,kBAAkB,KACxC;AACN;AAeO,SAAS,kBAAkB,OAAe,SAAyB;AACxE,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI,qBAAqB,GAAG,OAAO,6BAA6B;AAAA,EACxE;AAEA,QAAM,aAAa,MAAM,KAAA,EAAO,YAAA;AAEhC,MAAI,CAAC,mBAAmB,KAAK,UAAU,GAAG;AACxC,UAAM,IAAI;AAAA,MACR,GAAG,OAAO,+CAA+C,OAAO,KAAK,CAAC;AAAA,IAAA;AAAA,EAE1E;AAEA,SAAO;AACT;AAEO,SAAS,yBACd,OACA,SACQ;AACR,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,GAAG;AAC1E,UAAM,IAAI;AAAA,MACR,GAAG,OAAO,2EAA2E,OAAO,KAAK,CAAC;AAAA,IAAA;AAAA,EAEtG;AAEA,SAAO;AACT;AAEO,SAAS,iCACd,OACA,SACQ;AACR,QAAM,SAAS,yBAAyB,OAAO,OAAO;AAEtD,MAAI,WAAW,GAAG;AAChB,UAAM,IAAI,qBAAqB,GAAG,OAAO,6BAA6B;AAAA,EACxE;AAEA,SAAO;AACT;AAEO,SAAS,+BACd,OACA,UACA,SACQ;AACR,QAAM,SAAS,iCAAiC,OAAO,OAAO;AAC9D,QAAM,qBAAqB,kBAAkB,UAAU,OAAO;AAE9D,MACE,kCAAkC,IAAI,kBAAkB,KACxD,SAAS,QAAQ,GACjB;AACA,UAAM,IAAI;AAAA,MACR,GAAG,OAAO,QAAQ,kBAAkB;AAAA,IAAA;AAAA,EAExC;AAEA,SAAO;AACT;AAEO,SAAS,iCACd,OACA,SACQ;AACR,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,OAAO,cAAc,KAAK,KAAK,SAAS,GAAG;AAC9C,UAAM,IAAI;AAAA,MACR,GAAG,OAAO;AAAA,IAAA;AAAA,EAEd;AAEA,SAAO;AACT;AAEO,SAAS,sBACd,gBACA,SACA,QACA,yBACM;AACN,iBAAe,OAAO,OAAO;AAC7B,iBAAe,IAAI,SAAS,MAAM;AAElC,SAAO,eAAe,OAAO,yBAAyB;AACpD,UAAM,gBAAgB,eAAe,KAAA,EAAO,OAAO;AAEnD,QAAI,kBAAkB,QAAW;AAC/B;AAAA,IACF;AAEA,mBAAe,OAAO,aAAa;AAAA,EACrC;AACF;AAEO,SAAS,wBACd,OACA,SACQ;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI,qBAAqB,GAAG,OAAO,oBAAoB;AAAA,EAC/D;AAEA,QAAM,aAAa,MAAM,KAAA;AAEzB,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,qBAAqB,GAAG,OAAO,qBAAqB;AAAA,EAChE;AAEA,SAAO;AACT;AAEO,SAAS,mBAAmB,OAAe,SAAyB;AACzE,QAAM,aAAa,wBAAwB,OAAO,OAAO;AAEzD,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,UAAU;AAE9B,QAAI,CAAC,CAAC,SAAS,QAAQ,EAAE,SAAS,IAAI,QAAQ,GAAG;AAC/C,YAAM,IAAI,0BAA0B,GAAG,OAAO,0BAA0B;AAAA,IAC1E;AAAA,EACF,SAAS,OAAO;AACd,QAAI,iBAAiB,2BAA2B;AAC9C,YAAM;AAAA,IACR;AAEA,UAAM,IAAI,0BAA0B,GAAG,OAAO,yBAAyB;AAAA,MACrE,OAAO;AAAA,IAAA,CACR;AAAA,EACH;AAEA,SAAO;AACT;AAEO,SAAS,qBAAqB,OAAe,UAA0B;AAC5E,QAAM,YAAY,0BAA0B,QAAQ;AAEpD,QAAM,aAAa,gBAAgB,KAAK;AACxC,QAAM,CAAC,OAAO,WAAW,EAAE,IAAI,WAAW,MAAM,GAAG;AAEnD,MAAI,SAAS,SAAS,WAAW;AAC/B,UAAM,IAAI;AAAA,MACR,UAAU,OAAO,KAAK,CAAC,kBAAkB,SAAS;AAAA,IAAA;AAAA,EAEtD;AAEA,QAAM,SAAS,GAAG,QAAQ,GAAG,IAAI,OAAO,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS;AACvE,QAAM,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,aAAa,EAAE;AAE5D,SAAO,YAAY;AACrB;AAEO,SAAS,qBACd,OACA,UACQ;AACR,QAAM,YAAY,0BAA0B,QAAQ;AAEpD,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;AAC1D,UAAM,IAAI;AAAA,MACR,gCAAgC,OAAO,KAAK,CAAC;AAAA,IAAA;AAAA,EAEjD;AAEA,QAAM,MAAM,OAAO,UAAU,WAAW,MAAM,aAAa;AAE3D,MAAI,CAAC,QAAQ,KAAK,GAAG,GAAG;AACtB,UAAM,IAAI;AAAA,MACR,gCAAgC,OAAO,KAAK,CAAC;AAAA,IAAA;AAAA,EAEjD;AAEA,MAAI,cAAc,GAAG;AACnB,WAAO,OAAO;AAAA,EAChB;AAEA,QAAM,SAAS,IAAI,SAAS,YAAY,GAAG,GAAG;AAC9C,QAAM,QAAQ,OAAO,MAAM,GAAG,CAAC,SAAS;AACxC,QAAM,WAAW,OAAO,MAAM,CAAC,SAAS,EAAE,QAAQ,OAAO,EAAE;AAE3D,SAAO,WAAW,GAAG,KAAK,IAAI,QAAQ,KAAK;AAC7C;AAMO,SAAS,oBAAoB,OAAe,UAA0B;AAC3E,SAAO;AAAA,IACL,OAAO,yBAAyB,OAAO,YAAY,CAAC;AAAA,IACpD;AAAA,EAAA;AAEJ;AAEO,SAAS,yBACd,OACA,UACA,SACQ;AACR,QAAM,SACJ,OAAO,UAAU,WACb,QACA,OAAO,qBAAqB,OAAO,QAAQ,CAAC;AAElD,MAAI,SAAS,IAAI;AACf,UAAM,IAAI;AAAA,MACR,gCAAgC,OAAO,KAAK,CAAC;AAAA,IAAA;AAAA,EAEjD;AAEA,MAAI,SAAS,OAAO,OAAO,gBAAgB,GAAG;AAC5C,UAAM,IAAI;AAAA,MACR,GAAG,OAAO;AAAA,IAAA;AAAA,EAEd;AAEA,SAAO,OAAO,MAAM;AACtB;AAEO,SAAS,0BAA0B,UAA0B;AAClE,QAAM,aAAa,kBAAkB,UAAU,SAAS;AAExD,MAAI,eAAe,OAAO;AACxB,WAAO;AAAA,EACT;AAEA,MAAI,eAAe,QAAQ;AACzB,WAAO;AAAA,EACT;AAEA,MAAI,yBAAyB,IAAI,UAAU,GAAG;AAC5C,WAAO;AAAA,EACT;AAEA,SAAO,wBAAwB,IAAI,UAAU,IAAI,IAAI;AACvD;AAEO,SAAS,2BACd,QACA,WACe;AACf,MAAI,CAAC,aAAa,aAAa,oBAAI,QAAQ;AACzC,WAAO;AAAA,EACT;AAEA,SAAO,WAAW,aAAa,WAAW,oBACtC,YACA;AACN;AAEA,SAAS,0BAA0B,UAA0B;AAC3D,MACE,CAAC,OAAO,cAAc,QAAQ,KAC9B,WAAW,KACX,WAAW,uBACX;AACA,UAAM,IAAI;AAAA,MACR,8BAA8B,OAAO,QAAQ,CAAC;AAAA,IAAA;AAAA,EAElD;AAEA,SAAO;AACT;AAmCO,SAAS,MAAM,IAAY,QAAqC;AACrE,MAAI,QAAQ,SAAS;AACnB,WAAO,QAAQ,OAAO,OAAO,MAAM;AAAA,EACrC;AAEA,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI;AACJ,UAAM,cAAc,MAAY;AAC9B,mBAAa,OAAO;AACpB,aAAO,QAAQ,MAAM;AAAA,IACvB;AACA,UAAM,gBAAgB,MAAY;AAChC,cAAQ,oBAAoB,SAAS,WAAW;AAChD,cAAA;AAAA,IACF;AAEA,cAAU,WAAW,eAAe,EAAE;AACtC,YAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,MAAM;AAAA,EAC/D,CAAC;AACH;AAEA,gBAAuB,kBACrB,OACA,WAC6B;AAC7B,QAAM,YAAY,KAAK,IAAA;AACvB,QAAM,iBAAiB,wBAAwB,MAAM,kBAAkB,GAAK;AAC5E,QAAM,YACJ,MAAM,cAAc,SAChB,SACA,mBAAmB,MAAM,SAAS;AACxC,MAAI;AACJ,MAAI;AAEJ,QAAM,qBAAqB,MACzB,cAAc,SAAY,SAAY,aAAa,KAAK,QAAQ;AAElE,QAAM,oBAAoB,aAAoC;AAAA,IAC5D,GAAI,cAAe,MAAM,UAAA;AAAA,IACzB,OAAO;AAAA,IACP,QAAQ,YAAY,UAAU;AAAA,IAC9B,+BAAe,KAAA;AAAA,EAAK;AAGtB,SAAO,CAAC,MAAM,QAAQ,SAAS;AAC7B,SAAK,mBAAA,KAAwB,MAAM,GAAG;AACpC,YAAM,MAAM,kBAAA;AACZ;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAA;AACrB,iBAAa;AAEb,QAAI,OAAO,WAAW,YAAY;AAChC,YAAM,QAAQ,eAAe,MAAM;AACnC,YAAM;AACN,mBAAa,OAAO;AAEpB,UAAI,0BAA0B,IAAI,OAAO,MAAM,GAAG;AAChD;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAY,mBAAA;AAElB,QAAI,cAAc,UAAa,aAAa,GAAG;AAC7C,YAAM,MAAM,kBAAA;AACZ;AAAA,IACF;AAEA,UAAM;AAAA,MACJ,cAAc,SACV,iBACA,KAAK,IAAI,gBAAgB,SAAS;AAAA,MACtC,MAAM;AAAA,IAAA;AAAA,EAEV;AACF;AAEA,SAAS,wBAAwB,OAAuB;AACtD,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,SAAS,GAAG;AAC1C,UAAM,IAAI;AAAA,MACR,uDAAuD,OAAO,KAAK,CAAC;AAAA,IAAA;AAAA,EAExE;AAEA,SAAO;AACT;AAEA,SAAS,mBAAmB,OAAuB;AACjD,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG;AACzC,UAAM,IAAI;AAAA,MACR,sDAAsD,OAAO,KAAK,CAAC;AAAA,IAAA;AAAA,EAEvE;AAEA,SAAO;AACT;AAEO,SAAS,eAAe,QAA2C;AACxE,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,EAAE,GAAG,QAAQ,OAAO,YAAA;AAAA,EAC7B;AAEA,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,EAAE,GAAG,QAAQ,OAAO,SAAA;AAAA,EAC7B;AAEA,MAAI,OAAO,WAAW,WAAW;AAC/B,WAAO,EAAE,GAAG,QAAQ,OAAO,UAAA;AAAA,EAC7B;AAEA,MAAI,OAAO,WAAW,YAAY;AAChC,WAAO,EAAE,GAAG,QAAQ,OAAO,WAAA;AAAA,EAC7B;AAEA,SAAO,EAAE,GAAG,QAAQ,OAAO,SAAA;AAC7B;AAEA,eAAsB,iBACpB,UACA,SACY;AACZ,QAAM,OAAO,MAAM,SAAS,KAAA;AAC5B,MAAI;AAEJ,MAAI,MAAM;AACR,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,SAAS,OAAO;AACd,UAAI,SAAS,IAAI;AACf,cAAM,IAAI,qBAAqB,GAAG,OAAO,2BAA2B;AAAA,UAClE,OAAO;AAAA,QAAA,CACR;AAAA,MACH;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,UACJ,QAAQ,OAAO,SAAS,YAAY,aAAa,OAC7C,OAAQ,KAA8B,OAAO,IAC7C,QACE,OAAO,SAAS,YAChB,OAAQ,KAA6B,UAAU,WAC/C,OAAQ,KAA2B,KAAK,IACxC,QACE,OAAO,SAAS,YAChB,WAAW,QACX,OAAQ,KAA2C,OAC/C,YAAY,WACf,KAAwC,MAAM,UAC/C,QAAQ,SAAS;AAE3B,UAAM,IAAI,qBAAqB,GAAG,OAAO,KAAK,OAAO,IAAI;AAAA,MACvD,WAAW,SAAS,UAAU;AAAA,IAAA,CAC/B;AAAA,EACH;AAEA,MAAI,SAAS,QAAW;AACtB,UAAM,IAAI,qBAAqB,GAAG,OAAO,uBAAuB;AAAA,EAClE;AAEA,SAAO;AACT;AAEO,SAAS,WAAW,QAAyC;AAClE,QAAM,eAAe,IAAI,gBAAA;AAEzB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,UAAU,UAAa,UAAU,MAAM;AACzC;AAAA,IACF;AAEA,iBAAa,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,EACrC;AAEA,SAAO,aAAa,SAAA;AACtB;"}