@coinlist-co/react 0.12.2-rc.8a0d02a → 0.12.2-rc.8a65e9d
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/README.md +10 -0
- package/dist/{chunk-C6GF7MDF.js → chunk-2FZAXGVH.js} +1011 -1184
- package/dist/chunk-2FZAXGVH.js.map +1 -0
- package/dist/{chunk-IZJ4JSSC.js → chunk-EAPBF7T2.js} +152 -234
- package/dist/chunk-EAPBF7T2.js.map +1 -0
- package/dist/chunk-IWQ6A52U.js +24 -0
- package/dist/chunk-IWQ6A52U.js.map +1 -0
- package/dist/{chunk-3WW5FLT7.js → chunk-OQ2ANYUF.js} +334 -27
- package/dist/chunk-OQ2ANYUF.js.map +1 -0
- package/dist/client/index.d.ts +3277 -5736
- package/dist/client/index.js +10835 -10729
- package/dist/client/index.js.map +1 -1
- package/dist/client-credentials-BwcmPcn-.d.ts +13 -0
- package/dist/server/index.d.ts +54 -132
- package/dist/server/index.js +211 -171
- package/dist/server/index.js.map +1 -1
- package/dist/{time-CVZpAkGY.d.cts → time-ChSGmKZe.d.ts} +2194 -3422
- package/dist/{token-registry-snapshot-BkwA8KmD.d.ts → token-registry-snapshot-DMubXr2c.d.ts} +22 -58
- package/dist/universal/index.d.ts +94 -1068
- package/dist/universal/index.js +25 -47
- package/package.json +18 -14
- package/dist/chunk-3WW5FLT7.js.map +0 -1
- package/dist/chunk-C6GF7MDF.js.map +0 -1
- package/dist/chunk-IZJ4JSSC.js.map +0 -1
- package/dist/client/index.cjs +0 -20460
- package/dist/client/index.cjs.map +0 -1
- package/dist/client/index.d.cts +0 -8195
- package/dist/server/index.cjs +0 -4525
- package/dist/server/index.cjs.map +0 -1
- package/dist/server/index.d.cts +0 -382
- package/dist/time-CVZpAkGY.d.ts +0 -3987
- package/dist/token-registry-snapshot-bR14QehS.d.cts +0 -245
- package/dist/universal/index.cjs +0 -4562
- package/dist/universal/index.cjs.map +0 -1
- package/dist/universal/index.d.cts +0 -1362
|
@@ -1,18 +1,310 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Attributes,
|
|
3
3
|
EpochMillis,
|
|
4
|
-
HEADER_IDEMPOTENCY_KEY,
|
|
5
|
-
HttpClient,
|
|
6
4
|
HttpError,
|
|
7
|
-
Request,
|
|
8
5
|
TokenTrigger,
|
|
6
|
+
ValidationError,
|
|
9
7
|
getUUIDv4,
|
|
10
8
|
internalLogger,
|
|
11
9
|
viemChain
|
|
12
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-2FZAXGVH.js";
|
|
13
11
|
|
|
14
|
-
// src/universal/api/
|
|
15
|
-
var
|
|
12
|
+
// src/universal/api/frontline/config.ts
|
|
13
|
+
var PUBLIC_API_BASE_URL = "https://api.coinlist.co";
|
|
14
|
+
var HEADER_API_VERSION = "X-API-Version";
|
|
15
|
+
var HEADER_USER_AGENT = "User-Agent";
|
|
16
|
+
var HEADER_IDEMPOTENCY_KEY = "Idempotency-Key";
|
|
17
|
+
var API_VERSION = "2025-10-17";
|
|
18
|
+
var COINLIST_BASE_URL = "https://coinlist.co";
|
|
19
|
+
var OAUTH_PAGE_PATH = "/oauth/authorize";
|
|
20
|
+
var SUPPORT_NEW_TICKET_URL = "https://support.coinlist.co/support/tickets/new";
|
|
21
|
+
var VERIFY_IDENTITY_PATH = "/verify-identity";
|
|
22
|
+
var VERIFY_IDENTITY_ACCREDITATION_PATH = "/verify-identity/accreditation_full";
|
|
23
|
+
var WALLET_PATH = "/wallet";
|
|
24
|
+
|
|
25
|
+
// src/universal/core/auth/session-expired.ts
|
|
26
|
+
function notifySessionExpired(onSessionExpired, log) {
|
|
27
|
+
if (onSessionExpired === void 0) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
Promise.resolve().then(onSessionExpired).catch(
|
|
31
|
+
(error) => log.failure(() => ({ msg: "onSessionExpired threw" }), error)
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/universal/core/shared/effects.ts
|
|
36
|
+
var systemTime = { time: { now: EpochMillis.now } };
|
|
37
|
+
var systemDelay = {
|
|
38
|
+
delay: (duration) => new Promise((resolve) => setTimeout(resolve, duration))
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// src/universal/api/http.ts
|
|
42
|
+
async function makeRequest(request) {
|
|
43
|
+
const headers = {
|
|
44
|
+
Accept: "application/json",
|
|
45
|
+
...request.method === "POST" && request.body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
46
|
+
...request.headers ?? {}
|
|
47
|
+
};
|
|
48
|
+
const init = {
|
|
49
|
+
method: request.method,
|
|
50
|
+
headers,
|
|
51
|
+
...request.redirect !== void 0 ? { redirect: request.redirect } : {}
|
|
52
|
+
};
|
|
53
|
+
if (request.method === "POST" && request.body !== void 0) {
|
|
54
|
+
init.body = JSON.stringify(request.body);
|
|
55
|
+
}
|
|
56
|
+
const response = await fetch(
|
|
57
|
+
buildUrlWithQueryParams(request.url, request.queryParams),
|
|
58
|
+
init
|
|
59
|
+
);
|
|
60
|
+
const responseHeaders = headersToRecord(response.headers);
|
|
61
|
+
if (response.status === 204 || response.status === 205) {
|
|
62
|
+
return {
|
|
63
|
+
status: response.status,
|
|
64
|
+
body: null,
|
|
65
|
+
headers: responseHeaders
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (response.status >= 300 && response.status < 400) {
|
|
69
|
+
await response.text();
|
|
70
|
+
return {
|
|
71
|
+
status: response.status,
|
|
72
|
+
body: null,
|
|
73
|
+
headers: responseHeaders
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
const text = await response.text();
|
|
77
|
+
let body;
|
|
78
|
+
try {
|
|
79
|
+
body = text ? JSON.parse(text) : null;
|
|
80
|
+
} catch (_) {
|
|
81
|
+
throw new HttpError({
|
|
82
|
+
status: response.status,
|
|
83
|
+
headers: responseHeaders,
|
|
84
|
+
body: text
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
status: response.status,
|
|
89
|
+
body,
|
|
90
|
+
headers: responseHeaders
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function buildUrlWithQueryParams(url, queryParams) {
|
|
94
|
+
if (!queryParams) {
|
|
95
|
+
return url;
|
|
96
|
+
}
|
|
97
|
+
const searchParams = new URLSearchParams();
|
|
98
|
+
for (const [key, value] of Object.entries(queryParams)) {
|
|
99
|
+
if (value === void 0 || value === null) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (Array.isArray(value)) {
|
|
103
|
+
for (const item of value) {
|
|
104
|
+
if (item === void 0 || item === null) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
searchParams.append(key, String(item));
|
|
108
|
+
}
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
searchParams.append(key, String(value));
|
|
112
|
+
}
|
|
113
|
+
const queryString = searchParams.toString();
|
|
114
|
+
if (!queryString) {
|
|
115
|
+
return url;
|
|
116
|
+
}
|
|
117
|
+
return url.includes("?") ? `${url}&${queryString}` : `${url}?${queryString}`;
|
|
118
|
+
}
|
|
119
|
+
function headersToRecord(headers) {
|
|
120
|
+
const record = {};
|
|
121
|
+
headers.forEach((value, key) => {
|
|
122
|
+
record[key.toLowerCase()] = value;
|
|
123
|
+
});
|
|
124
|
+
return record;
|
|
125
|
+
}
|
|
126
|
+
function concatAttributes(request, attrs) {
|
|
127
|
+
const nextAttributes = Attributes.concat(
|
|
128
|
+
request.attributes ?? Attributes.empty,
|
|
129
|
+
attrs
|
|
130
|
+
);
|
|
131
|
+
const nextRequest = {
|
|
132
|
+
...request,
|
|
133
|
+
attributes: nextAttributes
|
|
134
|
+
};
|
|
135
|
+
return nextRequest;
|
|
136
|
+
}
|
|
137
|
+
var Request = {
|
|
138
|
+
concatAttributes
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// src/universal/api/http-client.ts
|
|
142
|
+
var HttpClient = class {
|
|
143
|
+
constructor(config, middleware = {}, logger = null, options = {}) {
|
|
144
|
+
this.config = config;
|
|
145
|
+
this.middleware = middleware;
|
|
146
|
+
this.log = internalLogger(logger, "HTTP");
|
|
147
|
+
this.makeRequestId = options.makeRequestId ?? defaultMakeRequestId;
|
|
148
|
+
}
|
|
149
|
+
async send(request) {
|
|
150
|
+
return this.runRequestWithAfterMiddleware(request);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Runs beforeRequest, executeRequest, then the full afterRequest middleware
|
|
154
|
+
* chain. Used by send() and by the retry() callback so that when a
|
|
155
|
+
* middleware calls retry(), the retried response also goes through all
|
|
156
|
+
* afterRequest middleware (e.g. session renewal, retry). Middleware
|
|
157
|
+
* must use request.attributes.retryAttempt (or similar) to avoid infinite
|
|
158
|
+
* recursion when they trigger retries.
|
|
159
|
+
*/
|
|
160
|
+
async runRequestWithAfterMiddleware(request) {
|
|
161
|
+
const preparedRequest = await this.runBeforeRequestMiddleware(
|
|
162
|
+
this.withClientDefaults(request)
|
|
163
|
+
);
|
|
164
|
+
let response = await this.executeRequest(preparedRequest);
|
|
165
|
+
for (const middleware of this.middleware.afterRequest ?? []) {
|
|
166
|
+
let retried = false;
|
|
167
|
+
response = await middleware({
|
|
168
|
+
request: preparedRequest,
|
|
169
|
+
response,
|
|
170
|
+
retry: (nextRequest = preparedRequest) => {
|
|
171
|
+
retried = true;
|
|
172
|
+
return this.runRequestWithAfterMiddleware(nextRequest);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
if (retried) {
|
|
176
|
+
return response;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return response;
|
|
180
|
+
}
|
|
181
|
+
withClientDefaults(request) {
|
|
182
|
+
const url = this.resolveUrl(request.url);
|
|
183
|
+
const headers = {
|
|
184
|
+
...request.headers ?? {},
|
|
185
|
+
...this.config.xApiVersion !== void 0 ? { [HEADER_API_VERSION]: this.config.xApiVersion } : {}
|
|
186
|
+
};
|
|
187
|
+
return {
|
|
188
|
+
...request,
|
|
189
|
+
url,
|
|
190
|
+
headers,
|
|
191
|
+
// Only when absent: a retry or a post-renewal re-send arrives with the
|
|
192
|
+
// first attempt's id already on it, and keeping it is the whole point.
|
|
193
|
+
attributes: Attributes.getRequestId(request.attributes) === null ? Attributes.concat(
|
|
194
|
+
request.attributes ?? Attributes.empty,
|
|
195
|
+
Attributes.requestId(this.makeRequestId())
|
|
196
|
+
) : request.attributes
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Resolves a request URL against the client's baseUrl.
|
|
201
|
+
*
|
|
202
|
+
* @internal Public only for testing. Do not use in application code; use
|
|
203
|
+
* {@link HttpClient.send} with a path and the client will resolve the URL.
|
|
204
|
+
*/
|
|
205
|
+
resolveUrl(url) {
|
|
206
|
+
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
207
|
+
return url;
|
|
208
|
+
}
|
|
209
|
+
const base = this.config.baseUrl.replace(/\/$/, "");
|
|
210
|
+
const path = url.startsWith("/") ? url : `/${url}`;
|
|
211
|
+
return base + path;
|
|
212
|
+
}
|
|
213
|
+
async runBeforeRequestMiddleware(initialRequest) {
|
|
214
|
+
let request = initialRequest;
|
|
215
|
+
for (const middleware of this.middleware.beforeRequest ?? []) {
|
|
216
|
+
request = await middleware(request);
|
|
217
|
+
}
|
|
218
|
+
return request;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* One physical attempt, logged as one line.
|
|
222
|
+
*
|
|
223
|
+
* A non-2xx is a `warn` rather than an `error` because the wire does not
|
|
224
|
+
* know whether it is a failure: the retry middleware may turn a 503 into a
|
|
225
|
+
* success, and the token registry reads a 404 as "not listed". The namespace
|
|
226
|
+
* above decides, and logs the `error` when it does.
|
|
227
|
+
*/
|
|
228
|
+
async executeRequest(request) {
|
|
229
|
+
const requestId = Attributes.getRequestId(request.attributes);
|
|
230
|
+
const log = requestId === null ? this.log : this.log.child({ requestId });
|
|
231
|
+
const attempt = Attributes.getRetryAttempt(request.attributes) + 1;
|
|
232
|
+
const startedAt = Date.now();
|
|
233
|
+
log.debug(() => ({
|
|
234
|
+
msg: "request sent",
|
|
235
|
+
fields: describeRequestUnredacted(request)
|
|
236
|
+
}));
|
|
237
|
+
try {
|
|
238
|
+
const response = await makeRequest(request);
|
|
239
|
+
const elapsed = Date.now() - startedAt;
|
|
240
|
+
const outcome = () => ({
|
|
241
|
+
msg: "request completed",
|
|
242
|
+
fields: {
|
|
243
|
+
...identifyRequest(request),
|
|
244
|
+
"http.response.status_code": response.status,
|
|
245
|
+
duration_ms: elapsed,
|
|
246
|
+
attempt
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
if (response.status >= 200 && response.status < 300) {
|
|
250
|
+
log.info(outcome);
|
|
251
|
+
} else {
|
|
252
|
+
log.warn(outcome);
|
|
253
|
+
}
|
|
254
|
+
log.debug(() => ({
|
|
255
|
+
msg: "response received",
|
|
256
|
+
fields: { body: response.body }
|
|
257
|
+
}));
|
|
258
|
+
return requestId === null ? response : { ...response, requestId };
|
|
259
|
+
} catch (error) {
|
|
260
|
+
const elapsed = Date.now() - startedAt;
|
|
261
|
+
log.warning(
|
|
262
|
+
() => ({
|
|
263
|
+
msg: "request threw",
|
|
264
|
+
fields: {
|
|
265
|
+
...identifyRequest(request),
|
|
266
|
+
duration_ms: elapsed,
|
|
267
|
+
attempt
|
|
268
|
+
}
|
|
269
|
+
}),
|
|
270
|
+
error
|
|
271
|
+
);
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
function identifyRequest(request) {
|
|
277
|
+
const { host, path } = splitUrl(request.url);
|
|
278
|
+
return {
|
|
279
|
+
"http.request.method": request.method,
|
|
280
|
+
"server.address": host,
|
|
281
|
+
"url.path": path
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function splitUrl(url) {
|
|
285
|
+
try {
|
|
286
|
+
const parsed = new URL(url);
|
|
287
|
+
return { host: parsed.host, path: parsed.pathname };
|
|
288
|
+
} catch (_) {
|
|
289
|
+
return { host: null, path: url };
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function defaultMakeRequestId() {
|
|
293
|
+
return Math.random().toString(36).slice(2, 10).padEnd(8, "0");
|
|
294
|
+
}
|
|
295
|
+
function describeRequestUnredacted(request) {
|
|
296
|
+
return {
|
|
297
|
+
"http.request.method": request.method,
|
|
298
|
+
"url.full": buildUrlWithQueryParams(request.url, request.queryParams),
|
|
299
|
+
headers: request.headers,
|
|
300
|
+
...request.method === "POST" ? { body: request.body } : {}
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// src/universal/api/nabu/client.ts
|
|
305
|
+
function createNabuApiClient(baseUrl, logger = null) {
|
|
306
|
+
return new HttpClient({ baseUrl }, {}, logger);
|
|
307
|
+
}
|
|
16
308
|
|
|
17
309
|
// src/universal/api/rpc/public-clients.ts
|
|
18
310
|
import {
|
|
@@ -132,16 +424,32 @@ function publicClients(api, config, logger = null) {
|
|
|
132
424
|
return client;
|
|
133
425
|
};
|
|
134
426
|
}
|
|
135
|
-
function transportFor(api,
|
|
136
|
-
if (
|
|
137
|
-
return typeof
|
|
427
|
+
function transportFor(api, override2, chain, logger) {
|
|
428
|
+
if (override2 === void 0) return frontlineTransport(api, chain, logger);
|
|
429
|
+
return typeof override2 === "string" ? http(override2) : override2;
|
|
138
430
|
}
|
|
139
431
|
|
|
140
|
-
// src/universal/
|
|
141
|
-
var
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
432
|
+
// src/universal/api/nabu/config.ts
|
|
433
|
+
var NABU_BASE_URL = "https://asset.coinlist.co";
|
|
434
|
+
|
|
435
|
+
// src/universal/core/shared/base-urls.ts
|
|
436
|
+
function baseUrls(config) {
|
|
437
|
+
return {
|
|
438
|
+
api: override("baseUrl", config.baseUrl, PUBLIC_API_BASE_URL),
|
|
439
|
+
tokens: override("tokensBaseUrl", config.tokensBaseUrl, NABU_BASE_URL)
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
function override(field, value, fallback) {
|
|
443
|
+
if (value === void 0) {
|
|
444
|
+
return fallback;
|
|
445
|
+
}
|
|
446
|
+
if (value.trim() === "") {
|
|
447
|
+
throw new ValidationError(
|
|
448
|
+
`Config.${field} is empty. Omit it to use the default, or set a URL.`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
return value;
|
|
452
|
+
}
|
|
145
453
|
|
|
146
454
|
// src/universal/core/shared/observability/pino-logger.ts
|
|
147
455
|
function toPinoRecord(event) {
|
|
@@ -414,25 +722,24 @@ var AuthenticatedApiClient = class {
|
|
|
414
722
|
}
|
|
415
723
|
};
|
|
416
724
|
|
|
417
|
-
// src/universal/core/auth/session-expired.ts
|
|
418
|
-
function notifySessionExpired(onSessionExpired, log) {
|
|
419
|
-
if (onSessionExpired === void 0) {
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
Promise.resolve().then(onSessionExpired).catch(
|
|
423
|
-
(error) => log.failure(() => ({ msg: "onSessionExpired threw" }), error)
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
725
|
export {
|
|
726
|
+
HEADER_USER_AGENT,
|
|
727
|
+
API_VERSION,
|
|
728
|
+
COINLIST_BASE_URL,
|
|
729
|
+
OAUTH_PAGE_PATH,
|
|
730
|
+
SUPPORT_NEW_TICKET_URL,
|
|
731
|
+
VERIFY_IDENTITY_PATH,
|
|
732
|
+
VERIFY_IDENTITY_ACCREDITATION_PATH,
|
|
733
|
+
WALLET_PATH,
|
|
428
734
|
AuthenticatedApiClient,
|
|
429
735
|
notifySessionExpired,
|
|
430
|
-
NABU_BASE_URL,
|
|
431
|
-
publicClients,
|
|
432
736
|
systemTime,
|
|
433
737
|
systemDelay,
|
|
738
|
+
createNabuApiClient,
|
|
739
|
+
publicClients,
|
|
740
|
+
baseUrls,
|
|
434
741
|
PINO_LEVEL,
|
|
435
742
|
SDK_LOGGER_NAME,
|
|
436
743
|
loggerOverPino
|
|
437
744
|
};
|
|
438
|
-
//# sourceMappingURL=chunk-
|
|
745
|
+
//# sourceMappingURL=chunk-OQ2ANYUF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/universal/api/frontline/config.ts","../src/universal/core/auth/session-expired.ts","../src/universal/core/shared/effects.ts","../src/universal/api/http.ts","../src/universal/api/http-client.ts","../src/universal/api/nabu/client.ts","../src/universal/api/rpc/public-clients.ts","../src/universal/api/rpc/frontline-transport.ts","../src/universal/api/nabu/config.ts","../src/universal/core/shared/base-urls.ts","../src/universal/core/shared/observability/pino-logger.ts","../src/universal/api/middleware/attach-session-middleware.ts","../src/universal/api/middleware/idempotency-key.ts","../src/universal/api/middleware/request-retry.ts","../src/universal/api/middleware/session-renewal.ts","../src/universal/api/authenticated-api-client.ts"],"sourcesContent":["export const PUBLIC_API_BASE_URL = 'https://api.coinlist.co';\nexport const HEADER_API_VERSION = 'X-API-Version';\nexport const HEADER_USER_AGENT = 'User-Agent';\nexport const HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';\nexport const API_VERSION = '2025-10-17';\n\nexport const COINLIST_BASE_URL = 'https://coinlist.co';\nexport const OAUTH_PAGE_PATH = '/oauth/authorize';\n\nexport const SUPPORT_NEW_TICKET_URL =\n 'https://support.coinlist.co/support/tickets/new';\n\nexport const VERIFY_IDENTITY_PATH = '/verify-identity';\nexport const VERIFY_IDENTITY_ACCREDITATION_PATH =\n '/verify-identity/accreditation_full';\nexport const WALLET_PATH = '/wallet';\n","import type { InternalLogger } from '@/universal/core/shared/observability/internal-logger';\n\n/**\n * Calls the host's `Config.onSessionExpired`, without awaiting it and without\n * letting it fail the request that found out.\n *\n * Total: the handler runs on the next microtask, so a sync throw from untyped\n * JavaScript and an async rejection land on the same `catch`, and both are\n * logged and dropped.\n */\nexport function notifySessionExpired(\n onSessionExpired: (() => Promise<void>) | undefined,\n log: InternalLogger\n): void {\n if (onSessionExpired === undefined) {\n return;\n }\n Promise.resolve()\n .then(onSessionExpired)\n .catch((error: unknown) =>\n log.failure(() => ({ msg: 'onSessionExpired threw' }), error)\n );\n}\n","import { EpochMillis, type Millis } from '@/universal/types/time';\n\n/**\n * Reading the clock, as an effect: code that takes a `TimeEff` can be driven\n * by a fake clock in specs instead of real time.\n */\nexport type TimeEff = {\n readonly time: { readonly now: () => EpochMillis };\n};\n\n/** Waiting, as an effect, for the same reason as {@link TimeEff}. */\nexport type DelayEff = {\n readonly delay: (duration: Millis) => Promise<void>;\n};\n\n/** The real clock, wired in at the construction edges. */\nexport const systemTime: TimeEff = { time: { now: EpochMillis.now } };\n\n/** Real waiting on `setTimeout`, wired in at the construction edges. */\nexport const systemDelay: DelayEff = {\n delay: (duration) => new Promise((resolve) => setTimeout(resolve, duration)),\n};\n","import { Attributes } from '@/universal/api/http-attributes';\nimport type { HttpRequest } from '@/universal/api/sender';\nimport {\n HttpError,\n type HttpResponse,\n type QueryParamValues,\n} from '@/universal/types/http';\n\nexport type HttpClientConfig = {\n baseUrl: string;\n /**\n * The frontline `X-API-Version` header. Omit for clients against other\n * backends (e.g. the token registry): a version header they don't know\n * would also force a CORS preflight the CDN cannot answer.\n */\n xApiVersion?: string;\n};\n\nexport async function makeRequest<TResponse = unknown>(\n request: HttpRequest\n): Promise<HttpResponse<TResponse>> {\n const headers: Record<string, string> = {\n Accept: 'application/json',\n ...(request.method === 'POST' && request.body !== undefined\n ? { 'Content-Type': 'application/json' }\n : {}),\n ...(request.headers ?? {}),\n };\n\n const init: RequestInit = {\n method: request.method,\n headers,\n ...(request.redirect !== undefined ? { redirect: request.redirect } : {}),\n };\n\n if (request.method === 'POST' && request.body !== undefined) {\n init.body = JSON.stringify(request.body);\n }\n\n const response = await fetch(\n buildUrlWithQueryParams(request.url, request.queryParams),\n init\n );\n const responseHeaders = headersToRecord(response.headers);\n\n if (response.status === 204 || response.status === 205) {\n return {\n status: response.status,\n body: null,\n headers: responseHeaders,\n };\n }\n\n if (response.status >= 300 && response.status < 400) {\n await response.text();\n return {\n status: response.status,\n body: null,\n headers: responseHeaders,\n };\n }\n\n const text = await response.text();\n let body: TResponse | null;\n try {\n body = text ? (JSON.parse(text) as TResponse) : null;\n } catch (_) {\n // A non-JSON body (an HTML error page from a CDN, proxy, or load\n // balancer) would otherwise surface as a bare SyntaxError with the status\n // lost. Throw the full response instead, so callers can classify the\n // failure by status and still see what the server actually sent.\n throw new HttpError({\n status: response.status,\n headers: responseHeaders,\n body: text,\n });\n }\n\n return {\n status: response.status,\n body,\n headers: responseHeaders,\n };\n}\n\n/**\n * The URL as `fetch` will see it, query string included.\n *\n * Exported for {@link HttpClient}'s `debug` request line, which renders the\n * request exactly as sent. Every other log line carries {@link HttpRequest.url}\n * alone - the query holds wallet addresses, chains and amounts, and `debug` is\n * the only level allowed to see them.\n */\nexport function buildUrlWithQueryParams(\n url: string,\n queryParams?: Record<string, QueryParamValues>\n): string {\n if (!queryParams) {\n return url;\n }\n\n const searchParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(queryParams)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item === undefined || item === null) {\n continue;\n }\n searchParams.append(key, String(item));\n }\n continue;\n }\n\n searchParams.append(key, String(value));\n }\n\n const queryString = searchParams.toString();\n if (!queryString) {\n return url;\n }\n\n return url.includes('?') ? `${url}&${queryString}` : `${url}?${queryString}`;\n}\n\nfunction headersToRecord(headers: Headers): Record<string, string> {\n const record: Record<string, string> = {};\n headers.forEach((value, key) => {\n record[key.toLowerCase()] = value;\n });\n return record;\n}\n\nfunction concatAttributes(\n request: HttpRequest,\n attrs: Attributes\n): HttpRequest {\n const nextAttributes = Attributes.concat(\n request.attributes ?? Attributes.empty,\n attrs\n );\n const nextRequest: typeof request = {\n ...request,\n attributes: nextAttributes,\n };\n return nextRequest;\n}\n\nexport const Request = {\n concatAttributes,\n};\n","import { HEADER_API_VERSION } from '@/universal/api/frontline/config';\nimport type { HttpClientConfig } from '@/universal/api/http';\nimport { buildUrlWithQueryParams, makeRequest } from '@/universal/api/http';\nimport { Attributes } from '@/universal/api/http-attributes';\nimport type { HttpRequest } from '@/universal/api/sender';\nimport {\n type InternalLogger,\n internalLogger,\n} from '@/universal/core/shared/observability/internal-logger';\nimport type { HttpResponse } from '@/universal/types/http';\nimport type {\n Logger,\n RequestId,\n UnredactedFields,\n} from '@/universal/types/logger';\n\nexport type BeforeRequestMiddleware = (\n request: HttpRequest\n) => Promise<HttpRequest>;\n\nexport type AfterRequestMiddleware = (args: {\n request: HttpRequest;\n response: HttpResponse<unknown>;\n retry: (request?: HttpRequest) => Promise<HttpResponse<unknown>>;\n}) => Promise<HttpResponse<unknown>>;\n\nexport type HttpClientMiddleware = {\n beforeRequest?: BeforeRequestMiddleware[];\n afterRequest?: AfterRequestMiddleware[];\n};\n\nexport type HttpClientOptions = {\n /**\n * Mints the id that correlates one request's log lines. Injected so specs\n * can assert on log output, the same reason\n * {@link createRequestRetryMiddleware} takes a `delayFn`; defaults to a\n * short random string.\n */\n makeRequestId?: () => RequestId;\n};\n\n/**\n * Logging lives here rather than in a middleware pair so that every client\n * built on `HttpClient` reports by construction - the frontline client, the\n * token registry client, and whatever comes next. A middleware would have to\n * be remembered per client, and could not time a request or see one that threw\n * before producing a response.\n */\nexport class HttpClient {\n private readonly log: InternalLogger;\n private readonly makeRequestId: () => RequestId;\n\n constructor(\n readonly config: HttpClientConfig,\n readonly middleware: HttpClientMiddleware = {},\n logger: Logger | null = null,\n options: HttpClientOptions = {}\n ) {\n this.log = internalLogger(logger, 'HTTP');\n this.makeRequestId = options.makeRequestId ?? defaultMakeRequestId;\n }\n\n async send<TResponse = unknown>(\n request: HttpRequest\n ): Promise<HttpResponse<TResponse>> {\n return this.runRequestWithAfterMiddleware<TResponse>(request);\n }\n\n /**\n * Runs beforeRequest, executeRequest, then the full afterRequest middleware\n * chain. Used by send() and by the retry() callback so that when a\n * middleware calls retry(), the retried response also goes through all\n * afterRequest middleware (e.g. session renewal, retry). Middleware\n * must use request.attributes.retryAttempt (or similar) to avoid infinite\n * recursion when they trigger retries.\n */\n private async runRequestWithAfterMiddleware<TResponse = unknown>(\n request: HttpRequest\n ): Promise<HttpResponse<TResponse>> {\n const preparedRequest = await this.runBeforeRequestMiddleware(\n this.withClientDefaults(request)\n );\n let response = await this.executeRequest<TResponse>(preparedRequest);\n\n for (const middleware of this.middleware.afterRequest ?? []) {\n let retried = false;\n response = (await middleware({\n request: preparedRequest,\n response,\n retry: (nextRequest = preparedRequest) => {\n retried = true;\n return this.runRequestWithAfterMiddleware(nextRequest) as Promise<\n HttpResponse<TResponse>\n >;\n },\n })) as HttpResponse<TResponse>;\n // A retried response has already been through the whole chain, the\n // middleware after this one included. Running those again here would\n // hand them the outer request's attributes - a fresh retry budget - so\n // a 401 renewed into a persistent 5xx would be retried twice over.\n if (retried) {\n return response;\n }\n }\n\n return response;\n }\n\n private withClientDefaults(request: HttpRequest): HttpRequest {\n const url = this.resolveUrl(request.url);\n const headers = {\n ...(request.headers ?? {}),\n ...(this.config.xApiVersion !== undefined\n ? { [HEADER_API_VERSION]: this.config.xApiVersion }\n : {}),\n };\n\n return {\n ...request,\n url,\n headers,\n // Only when absent: a retry or a post-renewal re-send arrives with the\n // first attempt's id already on it, and keeping it is the whole point.\n attributes:\n Attributes.getRequestId(request.attributes) === null\n ? Attributes.concat(\n request.attributes ?? Attributes.empty,\n Attributes.requestId(this.makeRequestId())\n )\n : request.attributes,\n };\n }\n\n /**\n * Resolves a request URL against the client's baseUrl.\n *\n * @internal Public only for testing. Do not use in application code; use\n * {@link HttpClient.send} with a path and the client will resolve the URL.\n */\n resolveUrl(url: string): string {\n // If already absolute, use as-is.\n if (url.startsWith('http://') || url.startsWith('https://')) {\n return url;\n }\n // Otherwise append path to baseUrl so base path (e.g. /api) is preserved.\n const base = this.config.baseUrl.replace(/\\/$/, '');\n const path = url.startsWith('/') ? url : `/${url}`;\n return base + path;\n }\n\n private async runBeforeRequestMiddleware(\n initialRequest: HttpRequest\n ): Promise<HttpRequest> {\n let request = initialRequest;\n for (const middleware of this.middleware.beforeRequest ?? []) {\n request = await middleware(request);\n }\n\n return request;\n }\n\n /**\n * One physical attempt, logged as one line.\n *\n * A non-2xx is a `warn` rather than an `error` because the wire does not\n * know whether it is a failure: the retry middleware may turn a 503 into a\n * success, and the token registry reads a 404 as \"not listed\". The namespace\n * above decides, and logs the `error` when it does.\n */\n private async executeRequest<TResponse = unknown>(\n request: HttpRequest\n ): Promise<HttpResponse<TResponse>> {\n const requestId = Attributes.getRequestId(request.attributes);\n const log = requestId === null ? this.log : this.log.child({ requestId });\n const attempt = Attributes.getRetryAttempt(request.attributes) + 1;\n const startedAt = Date.now();\n\n log.debug(() => ({\n msg: 'request sent',\n fields: describeRequestUnredacted(request),\n }));\n\n try {\n const response = await makeRequest<TResponse>(request);\n const elapsed = Date.now() - startedAt;\n const outcome = () => ({\n msg: 'request completed',\n fields: {\n ...identifyRequest(request),\n 'http.response.status_code': response.status,\n duration_ms: elapsed,\n attempt,\n },\n });\n\n if (response.status >= 200 && response.status < 300) {\n log.info(outcome);\n } else {\n log.warn(outcome);\n }\n log.debug(() => ({\n msg: 'response received',\n fields: { body: response.body },\n }));\n\n return requestId === null ? response : { ...response, requestId };\n } catch (error) {\n const elapsed = Date.now() - startedAt;\n // `warning`, not two hand-written lines: it renders the error verbatim\n // at `'debug'` and classified at `'warn'`, which is the pairing this\n // used to spell out by hand.\n log.warning(\n () => ({\n msg: 'request threw',\n fields: {\n ...identifyRequest(request),\n duration_ms: elapsed,\n attempt,\n },\n }),\n error\n );\n throw error;\n }\n }\n}\n\n/**\n * How a request is named on every line above `'debug'`.\n *\n * `server.address` and `url.path` rather than OpenTelemetry's `url.full`, and\n * that is a deliberate deviation from the convention the rest of these keys\n * follow. `url.full` is defined to carry the query string, and frontline reads\n * take `chain`, `wallet_address` and `amount` as query parameters - so the\n * standard key would put host data on the levels this SDK keeps redacted.\n * The full URL appears at `'debug'` and nowhere else.\n *\n * `HttpRequest.url` carries no query to begin with - {@link makeRequest}\n * appends it on the way to `fetch` - so the split is about naming rather than\n * about stripping anything.\n */\nfunction identifyRequest(request: HttpRequest): {\n 'http.request.method': string;\n 'server.address': string | null;\n 'url.path': string;\n} {\n const { host, path } = splitUrl(request.url);\n return {\n 'http.request.method': request.method,\n 'server.address': host,\n 'url.path': path,\n };\n}\n\n/**\n * The host and the path of an absolute URL, separately, because OpenTelemetry\n * names them separately and because only the path is worth grouping on.\n *\n * Never throws: it runs inside an event lambda, and the {@link Logger}\n * contract says nothing the SDK hands over may turn a log line into a second\n * failure. A URL `URL` refuses is reported as it stands, which is safe either\n * way - `HttpRequest.url` never carries a query string.\n */\nfunction splitUrl(url: string): { host: string | null; path: string } {\n try {\n const parsed = new URL(url);\n return { host: parsed.host, path: parsed.pathname };\n } catch (_) {\n return { host: null, path: url };\n }\n}\n\n/**\n * Eight base36 characters. Short enough to read at the head of every line and\n * wide enough that two concurrent requests in one session will not collide.\n * Deliberately not a counter: a module-level counter would be global mutable\n * state shared by every client in the process.\n */\nfunction defaultMakeRequestId(): RequestId {\n return Math.random().toString(36).slice(2, 10).padEnd(8, '0') as RequestId;\n}\n\n/**\n * The request as sent - full URL, headers and body verbatim. `debug` is\n * documented as unredacted: it exists to reproduce a bug, and a redacted\n * `Authorization` is exactly what you need when the bug is that the wrong\n * token went out.\n *\n * The query string appears here and nowhere else, under `url.full`. Every\n * other line names the request through {@link identifyRequest}, whose\n * `url.path` has none - which is why those lines are safe above `debug`.\n * Rendering the sent URL here is what makes a `wallet_address`, a `chain` or\n * an `amount` reproducible at all.\n *\n * The values are handed over as they stand rather than stringified: a\n * {@link DebugEvent} accepts anything, and the logger implementation is what\n * guarantees a `bigint` or a cycle cannot fail to render.\n */\nfunction describeRequestUnredacted(request: HttpRequest): UnredactedFields {\n return {\n 'http.request.method': request.method,\n 'url.full': buildUrlWithQueryParams(request.url, request.queryParams),\n headers: request.headers,\n ...(request.method === 'POST' ? { body: request.body } : {}),\n };\n}\n","import { HttpClient } from '@/universal/api/http-client';\nimport type { Logger } from '@/universal/types/logger';\n\n/**\n * The HTTP client the token registry's api functions take. Its own name,\n * rather than `HttpClient`, so the tokens namespace can hold one without\n * importing the transport: it is wiring the composition roots build once,\n * as `rpc/public-clients` is for chains.\n */\nexport type NabuClient = HttpClient;\n\n/**\n * A client against the token registry rather than frontline: no\n * `X-API-Version` (the registry doesn't know it, and the extra header would\n * force a CORS preflight the static CDN cannot answer) and no session\n * middleware (the registry is public).\n */\nexport function createNabuApiClient(\n baseUrl: string,\n logger: Logger | null = null\n): NabuClient {\n return new HttpClient({ baseUrl }, {}, logger);\n}\n","import {\n createPublicClient,\n http,\n type PublicClient,\n type Transport,\n} from 'viem';\nimport { frontlineTransport } from '@/universal/api/rpc/frontline-transport';\nimport type { Sender } from '@/universal/api/sender';\nimport { viemChain } from '@/universal/core/shared/blockchain/chain';\nimport type { EthereumChain } from '@/universal/types/blockchain/core';\nimport type { RpcConfig } from '@/universal/types/config';\nimport type { Logger } from '@/universal/types/logger';\n\n/**\n * Resolves a chain to the viem `PublicClient` the SDK reads it through.\n *\n * One function rather than a client per read, because the client is where the\n * batching lives: viem's multicall scheduler is keyed on the client's `uid`,\n * so two reads only ever share an `eth_call` if they share a client. Hence the\n * memoisation - it is correctness for batching, not a performance tweak.\n */\nexport type PublicClients = (chain: EthereumChain) => PublicClient;\n\n/**\n * Builds the per-chain `PublicClient` factory, lazily and once per chain.\n *\n * `batch: { multicall: true }` routes concurrent `eth_call`s through\n * Multicall3, whose address comes from viem's own chain definitions (see\n * `viemChain`). A checkout screen mounts several hooks that each read\n * independently - status, authorization, allowance, balance - and they collapse\n * into a single request. Per-call failures survive it: viem calls `aggregate3`\n * with `allowFailure: true` and re-throws each revert on its own call.\n *\n * **A read reached through these clients must take its subject as an\n * argument.** Batching makes `msg.sender` the Multicall3 address rather than\n * the caller, so a view that reads `msg.sender` would answer differently under\n * batching than without. Nothing the SDK reads does - `allowance(owner,\n * spender)`, `balanceOf(account)`, `authorized(user)` all name theirs - and a\n * new read must keep it that way.\n */\nexport function publicClients(\n api: Sender,\n config: RpcConfig | undefined,\n logger: Logger | null = null\n): PublicClients {\n const cache = new Map<EthereumChain, PublicClient>();\n\n return (chain) => {\n const cached = cache.get(chain);\n if (cached) return cached;\n\n const client = createPublicClient({\n chain: viemChain(chain),\n transport: transportFor(api, config?.[chain], chain, logger),\n batch: { multicall: true },\n });\n cache.set(chain, client);\n return client;\n };\n}\n\n/**\n * A host's override, or CoinList's proxy. A string is a URL the SDK wraps in\n * `http()`; a {@link Transport} is used as it stands, so `fallback([...])` and\n * a partner's own transport both pass through untouched.\n *\n * Only the proxy transport is given the logger. A host's own transport reports\n * however they built it, and viem's `http()` has no logging seam, so a host on\n * their own node gets whatever they wired up and nothing from the SDK.\n */\nfunction transportFor(\n api: Sender,\n override: string | Transport | undefined,\n chain: EthereumChain,\n logger: Logger | null\n): Transport {\n if (override === undefined) return frontlineTransport(api, chain, logger);\n return typeof override === 'string' ? http(override) : override;\n}\n","import { custom, RpcRequestError, type Transport } from 'viem';\nimport { Attributes } from '@/universal/api/http-attributes';\nimport type { Sender } from '@/universal/api/sender';\nimport {\n type InternalLogger,\n internalLogger,\n} from '@/universal/core/shared/observability/internal-logger';\nimport type { EthereumChain } from '@/universal/types/blockchain/core';\nimport { HttpError } from '@/universal/types/http';\nimport type { Logger } from '@/universal/types/logger';\n\n/**\n * A viem {@link Transport} that speaks JSON-RPC to CoinList's proxy,\n * `POST /v1/chains/{chain}/rpc`.\n *\n * Built over the SDK's own {@link Sender} rather than viem's `http()`, so an\n * on-chain read is an SDK request like any other: it carries the bearer token,\n * renews a stale session on a 401 and retries, is stamped with a request id,\n * and is reported by `HttpClient` by construction. Pointing `http()` at the\n * same URL would mean a second HTTP path through the SDK with none of that.\n * Retrying is the `Sender`'s job alone: viem's own `retryCount` is set to `0`\n * here, because it would otherwise rerun that whole pipeline on top of itself.\n *\n * **This is where the session requirement lives**, and it is the proxy that\n * enforces it: the endpoint is OAuth-gated, so a logged-out read comes back\n * `401` and reaches the caller as viem's `ContractFunctionExecutionError`\n * wrapping the SDK's own `HttpError`. Deliberately *not* translated to\n * `NotAuthenticatedError` - viem re-wraps whatever a `Transport` throws, so the\n * translation would not survive to the caller anyway and would only buy a\n * promise the SDK cannot keep. `classifyLogCause` walks the chain, so the\n * failure still logs as the HTTP failure it is.\n *\n * A partner who supplies their own node via {@link RpcConfig} never reaches\n * this transport and correctly needs no CoinList session.\n *\n * **What its `RPC` lines add over the `HTTP` ones for the same request.** The\n * JSON-RPC method, which the path `/v1/chains/{chain}/rpc` does not carry; and\n * a JSON-RPC error, which usually arrives with HTTP 200 and is therefore an\n * `info` success as far as `HttpClient` can tell.\n *\n * **They do not name the contract call**, and cannot: `publicClients` batches\n * through Multicall3, so one `eth_call` here may be several reads and its `to`\n * is Multicall3 rather than any contract. What is available is on the `debug`\n * line - the raw params, so the target address and the calldata. Which method\n * asked for the read, and whether it reverted, come from the namespace above.\n */\nexport function frontlineTransport(\n api: Sender,\n chain: EthereumChain,\n logger: Logger | null = null\n): Transport {\n const log = internalLogger(logger, 'RPC');\n let nextId = 0;\n\n return custom(\n {\n async request({ method, params }) {\n const id = ++nextId;\n return sendRpc({ api, log, chain, id, method, params });\n },\n },\n // The `Sender` below already retries: `requestRetryMiddleware` makes three\n // attempts at a 5xx and `renewSessionMiddleware` re-sends once after a 401.\n // viem's own default is `retryCount: 3`, and it applies on top: an\n // `HttpError` carries no numeric `code`, so `buildRequest` wraps it in\n // `UnknownRpcError` (`code === -1`) and `shouldRetry` says yes. That reruns\n // the whole pipeline four times - twelve requests for one `eth_call`, and\n // with multicall batching one `eth_call` is a screen's worth of reads. The\n // SDK's retry policy is the one that applies, so viem's is turned off.\n { retryCount: 0 }\n );\n}\n\nasync function sendRpc({\n api,\n log,\n chain,\n id,\n method,\n params,\n}: {\n api: Sender;\n log: InternalLogger;\n chain: EthereumChain;\n /** The JSON-RPC envelope's `id`, unique per request within one transport. */\n id: number;\n method: string;\n /** The JSON-RPC method's own params, passed through untouched. */\n params: unknown;\n}): Promise<unknown> {\n const url = rpcPath(chain);\n const startedAt = Date.now();\n\n // `params` carries calldata, so the envelope is a `'debug'` disclosure.\n log.debug(() => ({\n msg: 'rpc call sent',\n fields: { id, method, chain, params },\n }));\n\n const response = await sendEnvelope(api, url, {\n jsonrpc: '2.0',\n id,\n method,\n params,\n });\n const elapsed = Date.now() - startedAt;\n\n // A JSON-RPC error usually arrives with HTTP 200, so the `Sender` hands it\n // back as a success. viem's own `http()` transport raises `RpcRequestError`\n // here, and every viem action above - `readContract`'s revert decoding\n // included - is written against that.\n if (response.error) {\n const error = new RpcRequestError({\n body: { method, params },\n error: response.error,\n url,\n });\n // `warn`: the node declined, and only the namespace above knows whether\n // that broke anything. The code is the node's own, not a message anyone\n // wrote about this request.\n //\n // The cause is stated rather than classified. viem's `buildRequest` maps a\n // `RpcRequestError` onto one of its `RpcError` subclasses on the way out,\n // which is what `classifyLogCause` recognises - but that happens *above*\n // this throw, so classifying here would answer `'unknown'` for every\n // rejection. This call site knows: the node answered with an error object.\n log.warning(\n () => ({\n msg: 'rpc call rejected',\n cause: { type: 'rpc', reason: 'node-rejected' },\n fields: {\n method,\n chain,\n duration_ms: elapsed,\n 'rpc.error_code': response.error?.code ?? null,\n },\n }),\n error\n );\n throw error;\n }\n\n log.info(() => ({\n msg: 'rpc call',\n fields: { method, chain, duration_ms: elapsed },\n }));\n return response.result;\n}\n\nfunction rpcPath(chain: EthereumChain): string {\n return `/v1/chains/${encodeURIComponent(chain)}/rpc`;\n}\n\n/**\n * Posts the envelope, and reads a JSON-RPC error out of a non-2xx as well.\n *\n * The proxy forwards the node's status alongside its body, so a node that\n * answers a JSON-RPC error with, say, a `400` reaches the `Sender` as an\n * {@link HttpError}. Left as that, the node's error code and any revert data\n * would be lost behind an opaque HTTP failure. An `HttpError` whose body is not\n * a JSON-RPC error - frontline's own `422` for an unsupported chain or a\n * disallowed method, a `401`, a `5xx` - is the HTTP failure it looks like and\n * propagates untouched.\n */\nasync function sendEnvelope(\n api: Sender,\n url: string,\n body: { jsonrpc: '2.0'; id: number; method: string; params: unknown }\n): Promise<JsonRpcResponse> {\n try {\n return await api.send<JsonRpcResponse>({\n method: 'POST',\n url,\n body,\n attributes: Attributes.protected(),\n });\n } catch (error) {\n if (error instanceof HttpError && isJsonRpcError(error.response.body)) {\n return error.response.body;\n }\n throw error;\n }\n}\n\nfunction isJsonRpcError(\n body: unknown\n): body is Required<Pick<JsonRpcResponse, 'error'>> {\n if (typeof body !== 'object' || body === null || !('error' in body)) {\n return false;\n }\n const { error } = body;\n return (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n typeof error.code === 'number'\n );\n}\n\n/**\n * Only what the transport branches on. The SDK does not model the envelope as\n * a DTO: it is JSON-RPC's shape, not frontline's, and every field but these\n * two is handed straight back to viem.\n */\ntype JsonRpcResponse = {\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n};\n","/**\n * Base URL of CoinList's public token registry (Nabu), a static CDN serving\n * token display metadata keyed by chain + contract address. Override per\n * environment via `Config.tokensBaseUrl`.\n */\nexport const NABU_BASE_URL = 'https://asset.coinlist.co';\n","import { PUBLIC_API_BASE_URL } from '@/universal/api/frontline/config';\nimport { NABU_BASE_URL } from '@/universal/api/nabu/config';\nimport type { Config } from '@/universal/types/config';\nimport { ValidationError } from '@/universal/types/errors';\n\n/** The hosts a client talks to, after the host's overrides are applied. */\nexport type BaseUrls = {\n /** CoinList's API. */\n readonly api: string;\n /** The public token registry behind `coinlist.tokens`. */\n readonly tokens: string;\n};\n\n/**\n * The one defaulting rule both composition roots share: an omitted override\n * means production, and an empty one is a mistake, not a request for the\n * default. Rejected rather than read as \"unset\", because an empty string\n * usually means an environment variable that is set but empty, and a host\n * pointed at production by accident is worse than one that fails to start.\n *\n * @throws {@link ValidationError} naming the field when an override is empty\n * or whitespace.\n */\nexport function baseUrls(\n config: Pick<Config, 'baseUrl' | 'tokensBaseUrl'>\n): BaseUrls {\n return {\n api: override('baseUrl', config.baseUrl, PUBLIC_API_BASE_URL),\n tokens: override('tokensBaseUrl', config.tokensBaseUrl, NABU_BASE_URL),\n };\n}\n\nfunction override(\n field: 'baseUrl' | 'tokensBaseUrl',\n value: string | undefined,\n fallback: string\n): string {\n if (value === undefined) {\n return fallback;\n }\n if (value.trim() === '') {\n throw new ValidationError(\n `Config.${field} is empty. Omit it to use the default, or set a URL.`\n );\n }\n return value;\n}\n","import type {\n DebugEvent,\n Logger,\n LogLevel,\n SafeEvent,\n} from '@/universal/types/logger';\n\n/**\n * The SDK's logging seam expressed over pino, minus the environment.\n *\n * Imports no pino - {@link PinoSink} is a structural type - so `@/universal`\n * stays pino-free and the `./universal` entry point costs a consumer nothing.\n * Both shipped implementations\n * ({@link pinoClientLogger}, {@link pinoServerLogger}) differ only in the pino\n * instance they construct; everything worth testing lives here.\n *\n * ## Nothing here may throw\n *\n * A {@link Logger} implementation is called inline, on the codepath of the\n * work it reports, and the SDK does not catch it - so a log line that fails to\n * render would turn a successful request into an exception. That risk is real\n * rather than theoretical: `'debug'` fields carry whatever the SDK was\n * handling, and this codebase routinely handles `bigint` (every uint256 on\n * every DTO), which `JSON.stringify` throws on. Response bodies may be\n * circular, params may hold functions, and a host's object may have a getter\n * that throws.\n *\n * So {@link toPinoRecord} is total by construction: every value is rendered\n * into something a JSON serialiser cannot refuse, every property read is\n * guarded, and the whole translation has a fallback. Pino is never handed a\n * value it could fail on.\n */\n\n/**\n * Flattens an event into the object pino merges into its output line.\n *\n * Flat rather than nested, because nesting is what a host has to un-nest\n * before they can facet on it: `scope`, the {@link LogBindings} and every\n * field sit at the top level, and only `cause` stays an object because its\n * arms are a closed union a host switches on.\n *\n * `msg` is **not** included: it is pino's own second argument.\n *\n * Never throws. A value it cannot render becomes a `<tag>` string rather than\n * an exception, and a translation that fails entirely degrades to a record\n * naming the failure.\n */\nexport function toPinoRecord(event: SafeEvent | DebugEvent): PinoRecord {\n try {\n const record: Record<string, unknown> = {};\n\n for (const key of ownKeys(event.fields)) {\n record[key] = readProperty(event.fields, key, 0, new WeakSet());\n }\n\n const cause = 'cause' in event ? event.cause : undefined;\n if (cause !== undefined) {\n record.cause = sanitize(cause, 0, new WeakSet());\n }\n\n // Last, so the stamped keys win. `scope` and the bindings are what a host\n // routes and filters on, and they are stamped by `internalLogger` rather\n // than written at a call site - so a field that happened to be named\n // `scope` or `op` must not be able to take their place.\n return { ...record, scope: event.scope, ...event.bindings };\n } catch (_) {\n // The event itself is malformed - a Proxy for `fields`, a frozen exotic\n // object. Report that rather than losing the line, and never rethrow.\n return { 'log.render': '<unrenderable event>' };\n }\n}\n\n/** What pino merges into one output line. */\nexport type PinoRecord = Readonly<Record<string, unknown>>;\n\n/**\n * The SDK's five levels in pino's vocabulary.\n *\n * `'none'` is pino's `'silent'`; the other four are the same word in both, and\n * deliberately so. The SDK does not adopt pino's seven because `'trace'` would\n * sit below `'debug'`, and the guarantee \"`debug` is unredacted and every\n * other level is not\" only closes while `'debug'` is the bottom.\n */\nexport const PINO_LEVEL = {\n none: 'silent',\n error: 'error',\n warn: 'warn',\n info: 'info',\n debug: 'debug',\n} as const satisfies Record<LogLevel, string>;\n\n/**\n * How deep a `'debug'` field is followed before it is summarised.\n *\n * A bound rather than a guess at what is deep enough: a self-referential\n * structure is already caught by the cycle check, but a legitimately deep DTO\n * would otherwise cost real time inside a log line.\n */\nconst MAX_DEPTH = 8;\n\n/**\n * Renders any value into something a JSON serialiser cannot refuse.\n *\n * `bigint` is the one that matters in practice - every uint256 the SDK handles\n * is one - but the rest are all reachable from a `'debug'` field: `undefined`\n * and functions from an operation's params, `NaN` from arithmetic, symbols\n * from a host's object.\n */\nfunction sanitize(\n value: unknown,\n depth: number,\n seen: WeakSet<object>\n): unknown {\n switch (typeof value) {\n case 'string':\n case 'boolean':\n return value;\n case 'number':\n // `NaN` and the infinities serialise to `null`, which reads as \"absent\"\n // rather than \"not a number\". Name them instead.\n return Number.isFinite(value) ? value : String(value);\n case 'bigint':\n return value.toString();\n case 'undefined':\n return '<undefined>';\n case 'function':\n return '<function>';\n case 'symbol':\n return value.toString();\n case 'object':\n return value === null ? null : sanitizeObject(value, depth, seen);\n default:\n return '<unrenderable>';\n }\n}\n\nfunction sanitizeObject(\n value: object,\n depth: number,\n seen: WeakSet<object>\n): unknown {\n if (seen.has(value)) return '<circular>';\n if (depth >= MAX_DEPTH) return '<max depth>';\n\n // `name`, `message` and `stack` are all non-enumerable, so an `Error` handed\n // to a structured sink as an object serialises to `{}`.\n if (value instanceof Error) return describeError(value);\n if (value instanceof Date) return describeDate(value);\n\n seen.add(value);\n try {\n if (Array.isArray(value)) {\n return value.map((_item, index) =>\n readProperty(value, String(index), depth, seen)\n );\n }\n\n const out: Record<string, unknown> = {};\n for (const key of ownKeys(value)) {\n out[key] = readProperty(value, key, depth, seen);\n }\n return out;\n } finally {\n // Removed on the way out, so a value referenced twice in a tree renders\n // twice. Only a genuine cycle is `<circular>`.\n seen.delete(value);\n }\n}\n\n/**\n * One property read, guarded. A getter may throw, and a log line is not\n * allowed to be the reason a request fails.\n */\nfunction readProperty(\n owner: object,\n key: string,\n depth: number,\n seen: WeakSet<object>\n): unknown {\n try {\n return sanitize((owner as Record<string, unknown>)[key], depth + 1, seen);\n } catch (_) {\n return '<unreadable>';\n }\n}\n\n/** Own enumerable keys, guarded: an exotic object may refuse to be enumerated. */\nfunction ownKeys(value: object): readonly string[] {\n try {\n return Object.keys(value);\n } catch (_) {\n return [];\n }\n}\n\nfunction describeError(error: Error): Record<string, unknown> {\n return {\n name: safeRead(() => error.name),\n message: safeRead(() => error.message),\n stack: safeRead(() => error.stack),\n };\n}\n\nfunction describeDate(date: Date): unknown {\n // An invalid `Date` throws from `toISOString`.\n return safeRead(() => date.toISOString());\n}\n\nfunction safeRead(read: () => unknown): unknown {\n try {\n const value = read();\n return typeof value === 'string' ? value : '<unreadable>';\n } catch (_) {\n return '<unreadable>';\n }\n}\n\n/**\n * The part of a pino logger this adapter uses.\n *\n * Structural rather than `import type { Logger } from 'pino'`, so that\n * `@/universal` takes no dependency on pino at all. A real pino instance - node\n * or browser build - satisfies it.\n */\nexport type PinoSink = {\n debug(record: PinoRecord, msg: string): void;\n info(record: PinoRecord, msg: string): void;\n warn(record: PinoRecord, msg: string): void;\n error(record: PinoRecord, msg: string): void;\n};\n\n/**\n * The `name` binding every SDK line carries, so a partner can separate the\n * SDK's output from their own in a shared aggregator without matching on\n * `scope`.\n *\n * Applied through `pino.child({ name })` rather than pino's `name` *option*,\n * which its browser build ignores. The browser lane's spec is what caught\n * that, and is what keeps it caught.\n */\nexport const SDK_LOGGER_NAME = '@coinlist-co/react';\n\n/**\n * Adapts a pino instance into the {@link Logger} the SDK consumes.\n *\n * **Total, and that is the point.** The SDK calls a `Logger` inline and does\n * not catch it, so an exception raised while reporting a successful request\n * would fail that request. Three things could raise one - the event lambda\n * itself, rendering the event, and the sink - and all three are caught here.\n * A render failure is reported through the sink rather than swallowed, since a\n * log line that silently vanishes is a bug nobody finds; if the sink is what\n * broke, there is nowhere left to report it and the error stops here.\n *\n * **The level is fixed here, and that is this adapter's choice rather than the\n * seam's.** {@link InternalLogger} calls {@link Logger.level} before *every*\n * log call and caches nothing, so a host-implemented `Logger` reading a mutable\n * field has a level they can change at runtime. This adapter captures `level`\n * instead, and the pino instance it wraps is built with a fixed one - so\n * `Logger.level` is a constant lookup and two loggers never interfere. A host\n * who wants to turn `'debug'` on without rebuilding implements {@link Logger}\n * directly over their own pino instance; the port is four methods and this\n * function is the worked example.\n */\nexport function loggerOverPino(sink: PinoSink, level: LogLevel): Logger {\n return {\n level: () => level,\n debug: (event) => emit(sink, 'debug', event),\n info: (event) => emit(sink, 'info', event),\n warn: (event) => emit(sink, 'warn', event),\n error: (event) => emit(sink, 'error', event),\n };\n}\n\nfunction emit(\n sink: PinoSink,\n method: keyof PinoSink,\n event: () => SafeEvent | DebugEvent\n): void {\n try {\n const value = event();\n sink[method](toPinoRecord(value), value.msg);\n } catch (error) {\n reportRenderFailure(sink, error);\n }\n}\n\nfunction reportRenderFailure(sink: PinoSink, error: unknown): void {\n try {\n sink.error(\n { 'error.type': error instanceof Error ? error.name : typeof error },\n 'log event failed to render'\n );\n } catch (_) {\n // The sink itself threw. There is nowhere left to report this, and the SDK\n // is on the other side of the call that got us here.\n }\n}\n","import { Attributes } from '@/universal/api/http-attributes';\nimport type { BeforeRequestMiddleware } from '@/universal/api/http-client';\nimport type { HttpRequest } from '@/universal/api/sender';\nimport {\n type InternalAccessTokenSource,\n TokenTrigger,\n} from '@/universal/types/access-token-source';\n\nexport function attachSessionMiddleware(\n fetchAccessToken: InternalAccessTokenSource\n): BeforeRequestMiddleware {\n return async (request: HttpRequest): Promise<HttpRequest> => {\n if (!Attributes.isProtected(request.attributes)) {\n return request;\n }\n\n const userToken = await fetchAccessToken(TokenTrigger.beforeRequest);\n if (userToken !== null) {\n // Recorded so a 401 can name the token it refused: see `TokenTrigger`.\n return withBearer(\n {\n ...request,\n attributes: Attributes.concat(\n request.attributes ?? Attributes.empty,\n Attributes.sentWith(userToken)\n ),\n },\n userToken.value\n );\n }\n\n const clientCreds = Attributes.getClientCredentials(request.attributes);\n if (clientCreds) {\n return withBearer(request, clientCreds.value);\n }\n return request;\n };\n}\n\nfunction withBearer(request: HttpRequest, token: string): HttpRequest {\n return {\n ...request,\n headers: {\n ...(request.headers ?? {}),\n Authorization: `Bearer ${token}`,\n },\n };\n}\n","import { HEADER_IDEMPOTENCY_KEY } from '@/universal/api/frontline/config';\nimport { Attributes } from '@/universal/api/http-attributes';\nimport type { BeforeRequestMiddleware } from '@/universal/api/http-client';\nimport type { HttpRequest } from '@/universal/api/sender';\nimport { getUUIDv4 } from '@/universal/core/shared/utils/crypto';\n\nexport const idempotencyKeyMiddleware: BeforeRequestMiddleware = async (\n request: HttpRequest\n): Promise<HttpRequest> => {\n if (!Attributes.isIdempotent(request.attributes)) {\n return request;\n }\n\n const existingHeaders = request.headers ?? {};\n if (existingHeaders[HEADER_IDEMPOTENCY_KEY]) {\n return request;\n }\n\n return {\n ...request,\n headers: {\n ...existingHeaders,\n [HEADER_IDEMPOTENCY_KEY]: getUUIDv4(),\n },\n };\n};\n","import { Request } from '@/universal/api/http';\nimport { Attributes } from '@/universal/api/http-attributes';\nimport type { AfterRequestMiddleware } from '@/universal/api/http-client';\n\nconst MAX_ATTEMPTS = 3;\nconst INITIAL_DELAY_MS = 300;\nconst MAX_DELAY_MS = 2000;\n\nconst RETRYABLE_4XX = new Set([408, 409, 429]);\n\nexport function isRetryableStatus(status: number): boolean {\n return (status >= 500 && status < 600) || RETRYABLE_4XX.has(status);\n}\n\nfunction getRetryDelayMs(attempt: number): number {\n return Math.min(INITIAL_DELAY_MS * 2 ** (attempt - 1), MAX_DELAY_MS);\n}\n\nexport type RequestRetryMiddlewareOptions = {\n /**\n * Optional delay function. Defaults to real setTimeout-based delay.\n * Use a no-op (e.g. () => Promise.resolve()) in tests to avoid slow tests.\n */\n delayFn?: (ms: number) => Promise<void>;\n};\n\n/**\n * Creates the request retry after-request middleware. Inject a no-op delayFn\n * in tests to avoid real delays (unit testing best practice).\n */\nexport function createRequestRetryMiddleware(\n options: RequestRetryMiddlewareOptions = {}\n): AfterRequestMiddleware {\n const delayFn = options.delayFn ?? defaultDelay;\n\n return async ({ request, response, retry }) => {\n if (\n !isRetryableStatus(response.status) ||\n !Attributes.isRetryable(request.attributes)\n ) {\n return response;\n }\n\n const currentAttempt = Attributes.getRetryAttempt(request.attributes);\n if (currentAttempt >= MAX_ATTEMPTS - 1) {\n return response;\n }\n\n const nextAttempt = currentAttempt + 1;\n await delayFn(getRetryDelayMs(nextAttempt));\n\n const nextRequest = Request.concatAttributes(\n request,\n Attributes.retryAttempt(nextAttempt)\n );\n return retry(nextRequest);\n };\n}\n\nfunction defaultDelay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Retries the request up to 3 times with exponential backoff when the response\n * has a retryable status (5xx server errors). Uses request.attributes.retryAttempt\n * to decide delay and whether to retry, so the middleware does not loop when\n * retry() runs the full HTTP middleware chain again.\n */\nexport const requestRetryMiddleware: AfterRequestMiddleware =\n createRequestRetryMiddleware();\n","import { Request } from '@/universal/api/http';\nimport { Attributes } from '@/universal/api/http-attributes';\nimport type { AfterRequestMiddleware } from '@/universal/api/http-client';\nimport {\n type InternalAccessTokenSource,\n TokenTrigger,\n} from '@/universal/types/access-token-source';\n\n/**\n * On a 401 to a protected request, asks for a better token than the one the\n * request was sent with and replays the request once with it.\n *\n * Deduplication is the token source's job, not this middleware's: a burst of\n * N requests that all 401 calls it N times, and the source answers all of\n * them from one renewal.\n */\nexport function renewSessionMiddleware(\n fetchAccessToken: InternalAccessTokenSource\n): AfterRequestMiddleware {\n return async ({ request, response, retry }) => {\n if (response.status !== 401) {\n return response;\n }\n if (!Attributes.isProtected(request.attributes)) {\n return response;\n }\n if (Attributes.wasRenewAttempted(request.attributes)) {\n return response;\n }\n\n const newToken = await fetchAccessToken(\n TokenTrigger.after401(Attributes.getSentWith(request.attributes))\n );\n if (newToken) {\n const nextRequest = Request.concatAttributes(\n request,\n Attributes.renewAttempted(true)\n );\n return retry(nextRequest);\n } else {\n return response;\n }\n };\n}\n","import type { HttpClientConfig } from '@/universal/api/http';\nimport type { BeforeRequestMiddleware } from '@/universal/api/http-client';\nimport { HttpClient } from '@/universal/api/http-client';\nimport { attachSessionMiddleware } from '@/universal/api/middleware/attach-session-middleware';\nimport { idempotencyKeyMiddleware } from '@/universal/api/middleware/idempotency-key';\nimport { requestRetryMiddleware } from '@/universal/api/middleware/request-retry';\nimport { renewSessionMiddleware } from '@/universal/api/middleware/session-renewal';\nimport type { HttpRequest } from '@/universal/api/sender';\nimport type { InternalAccessTokenSource } from '@/universal/types/access-token-source';\nimport { HttpError } from '@/universal/types/http';\nimport type { Logger } from '@/universal/types/logger';\n\n/**\n * Isomorphic HTTP client with session attachment, session renewal on 401,\n * idempotency key injection, and request retry. Works in both browser and\n * Node/server environments. Pass `additionalBeforeRequest` to inject\n * environment-specific middleware (e.g. `userAgentMiddleware` on the client).\n *\n * Pass `logger` through to have every request reported; the client logs\n * nothing without one.\n */\nexport class AuthenticatedApiClient {\n private readonly httpClient: HttpClient;\n\n constructor(\n config: HttpClientConfig,\n fetchAccessToken: InternalAccessTokenSource,\n additionalBeforeRequest: BeforeRequestMiddleware[] = [],\n logger: Logger | null = null\n ) {\n this.httpClient = new HttpClient(\n config,\n {\n beforeRequest: [\n attachSessionMiddleware(fetchAccessToken),\n ...additionalBeforeRequest,\n idempotencyKeyMiddleware,\n ],\n afterRequest: [\n renewSessionMiddleware(fetchAccessToken),\n requestRetryMiddleware,\n ],\n },\n logger\n );\n }\n\n async send<TResponse>(request: HttpRequest): Promise<TResponse> {\n const response = await this.httpClient.send<TResponse>(request);\n if (response.status >= 200 && response.status < 300) {\n return response.body as TResponse;\n } else {\n throw new HttpError(response);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AAAO,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB;AAC1B,IAAM,yBAAyB;AAC/B,IAAM,cAAc;AAEpB,IAAM,oBAAoB;AAC1B,IAAM,kBAAkB;AAExB,IAAM,yBACX;AAEK,IAAM,uBAAuB;AAC7B,IAAM,qCACX;AACK,IAAM,cAAc;;;ACLpB,SAAS,qBACd,kBACA,KACM;AACN,MAAI,qBAAqB,QAAW;AAClC;AAAA,EACF;AACA,UAAQ,QAAQ,EACb,KAAK,gBAAgB,EACrB;AAAA,IAAM,CAAC,UACN,IAAI,QAAQ,OAAO,EAAE,KAAK,yBAAyB,IAAI,KAAK;AAAA,EAC9D;AACJ;;;ACNO,IAAM,aAAsB,EAAE,MAAM,EAAE,KAAK,YAAY,IAAI,EAAE;AAG7D,IAAM,cAAwB;AAAA,EACnC,OAAO,CAAC,aAAa,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,QAAQ,CAAC;AAC7E;;;ACHA,eAAsB,YACpB,SACkC;AAClC,QAAM,UAAkC;AAAA,IACtC,QAAQ;AAAA,IACR,GAAI,QAAQ,WAAW,UAAU,QAAQ,SAAS,SAC9C,EAAE,gBAAgB,mBAAmB,IACrC,CAAC;AAAA,IACL,GAAI,QAAQ,WAAW,CAAC;AAAA,EAC1B;AAEA,QAAM,OAAoB;AAAA,IACxB,QAAQ,QAAQ;AAAA,IAChB;AAAA,IACA,GAAI,QAAQ,aAAa,SAAY,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,EACzE;AAEA,MAAI,QAAQ,WAAW,UAAU,QAAQ,SAAS,QAAW;AAC3D,SAAK,OAAO,KAAK,UAAU,QAAQ,IAAI;AAAA,EACzC;AAEA,QAAM,WAAW,MAAM;AAAA,IACrB,wBAAwB,QAAQ,KAAK,QAAQ,WAAW;AAAA,IACxD;AAAA,EACF;AACA,QAAM,kBAAkB,gBAAgB,SAAS,OAAO;AAExD,MAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,WAAO;AAAA,MACL,QAAQ,SAAS;AAAA,MACjB,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI,SAAS,UAAU,OAAO,SAAS,SAAS,KAAK;AACnD,UAAM,SAAS,KAAK;AACpB,WAAO;AAAA,MACL,QAAQ,SAAS;AAAA,MACjB,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,MAAI;AACJ,MAAI;AACF,WAAO,OAAQ,KAAK,MAAM,IAAI,IAAkB;AAAA,EAClD,SAAS,GAAG;AAKV,UAAM,IAAI,UAAU;AAAA,MAClB,QAAQ,SAAS;AAAA,MACjB,SAAS;AAAA,MACT,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,QAAQ,SAAS;AAAA,IACjB;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAUO,SAAS,wBACd,KACA,aACQ;AACR,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,IAAI,gBAAgB;AAEzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,WAAW,GAAG;AACtD,QAAI,UAAU,UAAa,UAAU,MAAM;AACzC;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAW,QAAQ,OAAO;AACxB,YAAI,SAAS,UAAa,SAAS,MAAM;AACvC;AAAA,QACF;AACA,qBAAa,OAAO,KAAK,OAAO,IAAI,CAAC;AAAA,MACvC;AACA;AAAA,IACF;AAEA,iBAAa,OAAO,KAAK,OAAO,KAAK,CAAC;AAAA,EACxC;AAEA,QAAM,cAAc,aAAa,SAAS;AAC1C,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AAEA,SAAO,IAAI,SAAS,GAAG,IAAI,GAAG,GAAG,IAAI,WAAW,KAAK,GAAG,GAAG,IAAI,WAAW;AAC5E;AAEA,SAAS,gBAAgB,SAA0C;AACjE,QAAM,SAAiC,CAAC;AACxC,UAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC9B,WAAO,IAAI,YAAY,CAAC,IAAI;AAAA,EAC9B,CAAC;AACD,SAAO;AACT;AAEA,SAAS,iBACP,SACA,OACa;AACb,QAAM,iBAAiB,WAAW;AAAA,IAChC,QAAQ,cAAc,WAAW;AAAA,IACjC;AAAA,EACF;AACA,QAAM,cAA8B;AAAA,IAClC,GAAG;AAAA,IACH,YAAY;AAAA,EACd;AACA,SAAO;AACT;AAEO,IAAM,UAAU;AAAA,EACrB;AACF;;;AC1GO,IAAM,aAAN,MAAiB;AAAA,EAItB,YACW,QACA,aAAmC,CAAC,GAC7C,SAAwB,MACxB,UAA6B,CAAC,GAC9B;AAJS;AACA;AAIT,SAAK,MAAM,eAAe,QAAQ,MAAM;AACxC,SAAK,gBAAgB,QAAQ,iBAAiB;AAAA,EAChD;AAAA,EAEA,MAAM,KACJ,SACkC;AAClC,WAAO,KAAK,8BAAyC,OAAO;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAc,8BACZ,SACkC;AAClC,UAAM,kBAAkB,MAAM,KAAK;AAAA,MACjC,KAAK,mBAAmB,OAAO;AAAA,IACjC;AACA,QAAI,WAAW,MAAM,KAAK,eAA0B,eAAe;AAEnE,eAAW,cAAc,KAAK,WAAW,gBAAgB,CAAC,GAAG;AAC3D,UAAI,UAAU;AACd,iBAAY,MAAM,WAAW;AAAA,QAC3B,SAAS;AAAA,QACT;AAAA,QACA,OAAO,CAAC,cAAc,oBAAoB;AACxC,oBAAU;AACV,iBAAO,KAAK,8BAA8B,WAAW;AAAA,QAGvD;AAAA,MACF,CAAC;AAKD,UAAI,SAAS;AACX,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAmB,SAAmC;AAC5D,UAAM,MAAM,KAAK,WAAW,QAAQ,GAAG;AACvC,UAAM,UAAU;AAAA,MACd,GAAI,QAAQ,WAAW,CAAC;AAAA,MACxB,GAAI,KAAK,OAAO,gBAAgB,SAC5B,EAAE,CAAC,kBAAkB,GAAG,KAAK,OAAO,YAAY,IAChD,CAAC;AAAA,IACP;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA;AAAA;AAAA;AAAA,MAGA,YACE,WAAW,aAAa,QAAQ,UAAU,MAAM,OAC5C,WAAW;AAAA,QACT,QAAQ,cAAc,WAAW;AAAA,QACjC,WAAW,UAAU,KAAK,cAAc,CAAC;AAAA,MAC3C,IACA,QAAQ;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,KAAqB;AAE9B,QAAI,IAAI,WAAW,SAAS,KAAK,IAAI,WAAW,UAAU,GAAG;AAC3D,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,OAAO,EAAE;AAClD,UAAM,OAAO,IAAI,WAAW,GAAG,IAAI,MAAM,IAAI,GAAG;AAChD,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAc,2BACZ,gBACsB;AACtB,QAAI,UAAU;AACd,eAAW,cAAc,KAAK,WAAW,iBAAiB,CAAC,GAAG;AAC5D,gBAAU,MAAM,WAAW,OAAO;AAAA,IACpC;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAc,eACZ,SACkC;AAClC,UAAM,YAAY,WAAW,aAAa,QAAQ,UAAU;AAC5D,UAAM,MAAM,cAAc,OAAO,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,UAAU,CAAC;AACxE,UAAM,UAAU,WAAW,gBAAgB,QAAQ,UAAU,IAAI;AACjE,UAAM,YAAY,KAAK,IAAI;AAE3B,QAAI,MAAM,OAAO;AAAA,MACf,KAAK;AAAA,MACL,QAAQ,0BAA0B,OAAO;AAAA,IAC3C,EAAE;AAEF,QAAI;AACF,YAAM,WAAW,MAAM,YAAuB,OAAO;AACrD,YAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,YAAM,UAAU,OAAO;AAAA,QACrB,KAAK;AAAA,QACL,QAAQ;AAAA,UACN,GAAG,gBAAgB,OAAO;AAAA,UAC1B,6BAA6B,SAAS;AAAA,UACtC,aAAa;AAAA,UACb;AAAA,QACF;AAAA,MACF;AAEA,UAAI,SAAS,UAAU,OAAO,SAAS,SAAS,KAAK;AACnD,YAAI,KAAK,OAAO;AAAA,MAClB,OAAO;AACL,YAAI,KAAK,OAAO;AAAA,MAClB;AACA,UAAI,MAAM,OAAO;AAAA,QACf,KAAK;AAAA,QACL,QAAQ,EAAE,MAAM,SAAS,KAAK;AAAA,MAChC,EAAE;AAEF,aAAO,cAAc,OAAO,WAAW,EAAE,GAAG,UAAU,UAAU;AAAA,IAClE,SAAS,OAAO;AACd,YAAM,UAAU,KAAK,IAAI,IAAI;AAI7B,UAAI;AAAA,QACF,OAAO;AAAA,UACL,KAAK;AAAA,UACL,QAAQ;AAAA,YACN,GAAG,gBAAgB,OAAO;AAAA,YAC1B,aAAa;AAAA,YACb;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAgBA,SAAS,gBAAgB,SAIvB;AACA,QAAM,EAAE,MAAM,KAAK,IAAI,SAAS,QAAQ,GAAG;AAC3C,SAAO;AAAA,IACL,uBAAuB,QAAQ;AAAA,IAC/B,kBAAkB;AAAA,IAClB,YAAY;AAAA,EACd;AACF;AAWA,SAAS,SAAS,KAAoD;AACpE,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,WAAO,EAAE,MAAM,OAAO,MAAM,MAAM,OAAO,SAAS;AAAA,EACpD,SAAS,GAAG;AACV,WAAO,EAAE,MAAM,MAAM,MAAM,IAAI;AAAA,EACjC;AACF;AAQA,SAAS,uBAAkC;AACzC,SAAO,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,EAAE,OAAO,GAAG,GAAG;AAC9D;AAkBA,SAAS,0BAA0B,SAAwC;AACzE,SAAO;AAAA,IACL,uBAAuB,QAAQ;AAAA,IAC/B,YAAY,wBAAwB,QAAQ,KAAK,QAAQ,WAAW;AAAA,IACpE,SAAS,QAAQ;AAAA,IACjB,GAAI,QAAQ,WAAW,SAAS,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,EAC5D;AACF;;;AChSO,SAAS,oBACd,SACA,SAAwB,MACZ;AACZ,SAAO,IAAI,WAAW,EAAE,QAAQ,GAAG,CAAC,GAAG,MAAM;AAC/C;;;ACtBA;AAAA,EACE;AAAA,EACA;AAAA,OAGK;;;ACLP,SAAS,QAAQ,uBAAuC;AA8CjD,SAAS,mBACd,KACA,OACA,SAAwB,MACb;AACX,QAAM,MAAM,eAAe,QAAQ,KAAK;AACxC,MAAI,SAAS;AAEb,SAAO;AAAA,IACL;AAAA,MACE,MAAM,QAAQ,EAAE,QAAQ,OAAO,GAAG;AAChC,cAAM,KAAK,EAAE;AACb,eAAO,QAAQ,EAAE,KAAK,KAAK,OAAO,IAAI,QAAQ,OAAO,CAAC;AAAA,MACxD;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,EAAE,YAAY,EAAE;AAAA,EAClB;AACF;AAEA,eAAe,QAAQ;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASqB;AACnB,QAAM,MAAM,QAAQ,KAAK;AACzB,QAAM,YAAY,KAAK,IAAI;AAG3B,MAAI,MAAM,OAAO;AAAA,IACf,KAAK;AAAA,IACL,QAAQ,EAAE,IAAI,QAAQ,OAAO,OAAO;AAAA,EACtC,EAAE;AAEF,QAAM,WAAW,MAAM,aAAa,KAAK,KAAK;AAAA,IAC5C,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,QAAM,UAAU,KAAK,IAAI,IAAI;AAM7B,MAAI,SAAS,OAAO;AAClB,UAAM,QAAQ,IAAI,gBAAgB;AAAA,MAChC,MAAM,EAAE,QAAQ,OAAO;AAAA,MACvB,OAAO,SAAS;AAAA,MAChB;AAAA,IACF,CAAC;AAUD,QAAI;AAAA,MACF,OAAO;AAAA,QACL,KAAK;AAAA,QACL,OAAO,EAAE,MAAM,OAAO,QAAQ,gBAAgB;AAAA,QAC9C,QAAQ;AAAA,UACN;AAAA,UACA;AAAA,UACA,aAAa;AAAA,UACb,kBAAkB,SAAS,OAAO,QAAQ;AAAA,QAC5C;AAAA,MACF;AAAA,MACA;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAEA,MAAI,KAAK,OAAO;AAAA,IACd,KAAK;AAAA,IACL,QAAQ,EAAE,QAAQ,OAAO,aAAa,QAAQ;AAAA,EAChD,EAAE;AACF,SAAO,SAAS;AAClB;AAEA,SAAS,QAAQ,OAA8B;AAC7C,SAAO,cAAc,mBAAmB,KAAK,CAAC;AAChD;AAaA,eAAe,aACb,KACA,KACA,MAC0B;AAC1B,MAAI;AACF,WAAO,MAAM,IAAI,KAAsB;AAAA,MACrC,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,YAAY,WAAW,UAAU;AAAA,IACnC,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAI,iBAAiB,aAAa,eAAe,MAAM,SAAS,IAAI,GAAG;AACrE,aAAO,MAAM,SAAS;AAAA,IACxB;AACA,UAAM;AAAA,EACR;AACF;AAEA,SAAS,eACP,MACkD;AAClD,MAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,EAAE,WAAW,OAAO;AACnE,WAAO;AAAA,EACT;AACA,QAAM,EAAE,MAAM,IAAI;AAClB,SACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,OAAO,MAAM,SAAS;AAE1B;;;AD7JO,SAAS,cACd,KACA,QACA,SAAwB,MACT;AACf,QAAM,QAAQ,oBAAI,IAAiC;AAEnD,SAAO,CAAC,UAAU;AAChB,UAAM,SAAS,MAAM,IAAI,KAAK;AAC9B,QAAI,OAAQ,QAAO;AAEnB,UAAM,SAAS,mBAAmB;AAAA,MAChC,OAAO,UAAU,KAAK;AAAA,MACtB,WAAW,aAAa,KAAK,SAAS,KAAK,GAAG,OAAO,MAAM;AAAA,MAC3D,OAAO,EAAE,WAAW,KAAK;AAAA,IAC3B,CAAC;AACD,UAAM,IAAI,OAAO,MAAM;AACvB,WAAO;AAAA,EACT;AACF;AAWA,SAAS,aACP,KACAA,WACA,OACA,QACW;AACX,MAAIA,cAAa,OAAW,QAAO,mBAAmB,KAAK,OAAO,MAAM;AACxE,SAAO,OAAOA,cAAa,WAAW,KAAKA,SAAQ,IAAIA;AACzD;;;AEzEO,IAAM,gBAAgB;;;ACkBtB,SAAS,SACd,QACU;AACV,SAAO;AAAA,IACL,KAAK,SAAS,WAAW,OAAO,SAAS,mBAAmB;AAAA,IAC5D,QAAQ,SAAS,iBAAiB,OAAO,eAAe,aAAa;AAAA,EACvE;AACF;AAEA,SAAS,SACP,OACA,OACA,UACQ;AACR,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,KAAK,MAAM,IAAI;AACvB,UAAM,IAAI;AAAA,MACR,UAAU,KAAK;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;;;ACCO,SAAS,aAAa,OAA2C;AACtE,MAAI;AACF,UAAM,SAAkC,CAAC;AAEzC,eAAW,OAAO,QAAQ,MAAM,MAAM,GAAG;AACvC,aAAO,GAAG,IAAI,aAAa,MAAM,QAAQ,KAAK,GAAG,oBAAI,QAAQ,CAAC;AAAA,IAChE;AAEA,UAAM,QAAQ,WAAW,QAAQ,MAAM,QAAQ;AAC/C,QAAI,UAAU,QAAW;AACvB,aAAO,QAAQ,SAAS,OAAO,GAAG,oBAAI,QAAQ,CAAC;AAAA,IACjD;AAMA,WAAO,EAAE,GAAG,QAAQ,OAAO,MAAM,OAAO,GAAG,MAAM,SAAS;AAAA,EAC5D,SAAS,GAAG;AAGV,WAAO,EAAE,cAAc,uBAAuB;AAAA,EAChD;AACF;AAaO,IAAM,aAAa;AAAA,EACxB,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AASA,IAAM,YAAY;AAUlB,SAAS,SACP,OACA,OACA,MACS;AACT,UAAQ,OAAO,OAAO;AAAA,IACpB,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAGH,aAAO,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK;AAAA,IACtD,KAAK;AACH,aAAO,MAAM,SAAS;AAAA,IACxB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,MAAM,SAAS;AAAA,IACxB,KAAK;AACH,aAAO,UAAU,OAAO,OAAO,eAAe,OAAO,OAAO,IAAI;AAAA,IAClE;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,eACP,OACA,OACA,MACS;AACT,MAAI,KAAK,IAAI,KAAK,EAAG,QAAO;AAC5B,MAAI,SAAS,UAAW,QAAO;AAI/B,MAAI,iBAAiB,MAAO,QAAO,cAAc,KAAK;AACtD,MAAI,iBAAiB,KAAM,QAAO,aAAa,KAAK;AAEpD,OAAK,IAAI,KAAK;AACd,MAAI;AACF,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,aAAO,MAAM;AAAA,QAAI,CAAC,OAAO,UACvB,aAAa,OAAO,OAAO,KAAK,GAAG,OAAO,IAAI;AAAA,MAChD;AAAA,IACF;AAEA,UAAM,MAA+B,CAAC;AACtC,eAAW,OAAO,QAAQ,KAAK,GAAG;AAChC,UAAI,GAAG,IAAI,aAAa,OAAO,KAAK,OAAO,IAAI;AAAA,IACjD;AACA,WAAO;AAAA,EACT,UAAE;AAGA,SAAK,OAAO,KAAK;AAAA,EACnB;AACF;AAMA,SAAS,aACP,OACA,KACA,OACA,MACS;AACT,MAAI;AACF,WAAO,SAAU,MAAkC,GAAG,GAAG,QAAQ,GAAG,IAAI;AAAA,EAC1E,SAAS,GAAG;AACV,WAAO;AAAA,EACT;AACF;AAGA,SAAS,QAAQ,OAAkC;AACjD,MAAI;AACF,WAAO,OAAO,KAAK,KAAK;AAAA,EAC1B,SAAS,GAAG;AACV,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,cAAc,OAAuC;AAC5D,SAAO;AAAA,IACL,MAAM,SAAS,MAAM,MAAM,IAAI;AAAA,IAC/B,SAAS,SAAS,MAAM,MAAM,OAAO;AAAA,IACrC,OAAO,SAAS,MAAM,MAAM,KAAK;AAAA,EACnC;AACF;AAEA,SAAS,aAAa,MAAqB;AAEzC,SAAO,SAAS,MAAM,KAAK,YAAY,CAAC;AAC1C;AAEA,SAAS,SAAS,MAA8B;AAC9C,MAAI;AACF,UAAM,QAAQ,KAAK;AACnB,WAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,EAC7C,SAAS,GAAG;AACV,WAAO;AAAA,EACT;AACF;AAyBO,IAAM,kBAAkB;AAuBxB,SAAS,eAAe,MAAgB,OAAyB;AACtE,SAAO;AAAA,IACL,OAAO,MAAM;AAAA,IACb,OAAO,CAAC,UAAU,KAAK,MAAM,SAAS,KAAK;AAAA,IAC3C,MAAM,CAAC,UAAU,KAAK,MAAM,QAAQ,KAAK;AAAA,IACzC,MAAM,CAAC,UAAU,KAAK,MAAM,QAAQ,KAAK;AAAA,IACzC,OAAO,CAAC,UAAU,KAAK,MAAM,SAAS,KAAK;AAAA,EAC7C;AACF;AAEA,SAAS,KACP,MACA,QACA,OACM;AACN,MAAI;AACF,UAAM,QAAQ,MAAM;AACpB,SAAK,MAAM,EAAE,aAAa,KAAK,GAAG,MAAM,GAAG;AAAA,EAC7C,SAAS,OAAO;AACd,wBAAoB,MAAM,KAAK;AAAA,EACjC;AACF;AAEA,SAAS,oBAAoB,MAAgB,OAAsB;AACjE,MAAI;AACF,SAAK;AAAA,MACH,EAAE,cAAc,iBAAiB,QAAQ,MAAM,OAAO,OAAO,MAAM;AAAA,MACnE;AAAA,IACF;AAAA,EACF,SAAS,GAAG;AAAA,EAGZ;AACF;;;AChSO,SAAS,wBACd,kBACyB;AACzB,SAAO,OAAO,YAA+C;AAC3D,QAAI,CAAC,WAAW,YAAY,QAAQ,UAAU,GAAG;AAC/C,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,MAAM,iBAAiB,aAAa,aAAa;AACnE,QAAI,cAAc,MAAM;AAEtB,aAAO;AAAA,QACL;AAAA,UACE,GAAG;AAAA,UACH,YAAY,WAAW;AAAA,YACrB,QAAQ,cAAc,WAAW;AAAA,YACjC,WAAW,SAAS,SAAS;AAAA,UAC/B;AAAA,QACF;AAAA,QACA,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,cAAc,WAAW,qBAAqB,QAAQ,UAAU;AACtE,QAAI,aAAa;AACf,aAAO,WAAW,SAAS,YAAY,KAAK;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,WAAW,SAAsB,OAA4B;AACpE,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS;AAAA,MACP,GAAI,QAAQ,WAAW,CAAC;AAAA,MACxB,eAAe,UAAU,KAAK;AAAA,IAChC;AAAA,EACF;AACF;;;ACzCO,IAAM,2BAAoD,OAC/D,YACyB;AACzB,MAAI,CAAC,WAAW,aAAa,QAAQ,UAAU,GAAG;AAChD,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkB,QAAQ,WAAW,CAAC;AAC5C,MAAI,gBAAgB,sBAAsB,GAAG;AAC3C,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS;AAAA,MACP,GAAG;AAAA,MACH,CAAC,sBAAsB,GAAG,UAAU;AAAA,IACtC;AAAA,EACF;AACF;;;ACrBA,IAAM,eAAe;AACrB,IAAM,mBAAmB;AACzB,IAAM,eAAe;AAErB,IAAM,gBAAgB,oBAAI,IAAI,CAAC,KAAK,KAAK,GAAG,CAAC;AAEtC,SAAS,kBAAkB,QAAyB;AACzD,SAAQ,UAAU,OAAO,SAAS,OAAQ,cAAc,IAAI,MAAM;AACpE;AAEA,SAAS,gBAAgB,SAAyB;AAChD,SAAO,KAAK,IAAI,mBAAmB,MAAM,UAAU,IAAI,YAAY;AACrE;AAcO,SAAS,6BACd,UAAyC,CAAC,GAClB;AACxB,QAAM,UAAU,QAAQ,WAAW;AAEnC,SAAO,OAAO,EAAE,SAAS,UAAU,MAAM,MAAM;AAC7C,QACE,CAAC,kBAAkB,SAAS,MAAM,KAClC,CAAC,WAAW,YAAY,QAAQ,UAAU,GAC1C;AACA,aAAO;AAAA,IACT;AAEA,UAAM,iBAAiB,WAAW,gBAAgB,QAAQ,UAAU;AACpE,QAAI,kBAAkB,eAAe,GAAG;AACtC,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,iBAAiB;AACrC,UAAM,QAAQ,gBAAgB,WAAW,CAAC;AAE1C,UAAM,cAAc,QAAQ;AAAA,MAC1B;AAAA,MACA,WAAW,aAAa,WAAW;AAAA,IACrC;AACA,WAAO,MAAM,WAAW;AAAA,EAC1B;AACF;AAEA,SAAS,aAAa,IAA2B;AAC/C,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAQO,IAAM,yBACX,6BAA6B;;;ACtDxB,SAAS,uBACd,kBACwB;AACxB,SAAO,OAAO,EAAE,SAAS,UAAU,MAAM,MAAM;AAC7C,QAAI,SAAS,WAAW,KAAK;AAC3B,aAAO;AAAA,IACT;AACA,QAAI,CAAC,WAAW,YAAY,QAAQ,UAAU,GAAG;AAC/C,aAAO;AAAA,IACT;AACA,QAAI,WAAW,kBAAkB,QAAQ,UAAU,GAAG;AACpD,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,MAAM;AAAA,MACrB,aAAa,SAAS,WAAW,YAAY,QAAQ,UAAU,CAAC;AAAA,IAClE;AACA,QAAI,UAAU;AACZ,YAAM,cAAc,QAAQ;AAAA,QAC1B;AAAA,QACA,WAAW,eAAe,IAAI;AAAA,MAChC;AACA,aAAO,MAAM,WAAW;AAAA,IAC1B,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACtBO,IAAM,yBAAN,MAA6B;AAAA,EAGlC,YACE,QACA,kBACA,0BAAqD,CAAC,GACtD,SAAwB,MACxB;AACA,SAAK,aAAa,IAAI;AAAA,MACpB;AAAA,MACA;AAAA,QACE,eAAe;AAAA,UACb,wBAAwB,gBAAgB;AAAA,UACxC,GAAG;AAAA,UACH;AAAA,QACF;AAAA,QACA,cAAc;AAAA,UACZ,uBAAuB,gBAAgB;AAAA,UACvC;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,KAAgB,SAA0C;AAC9D,UAAM,WAAW,MAAM,KAAK,WAAW,KAAgB,OAAO;AAC9D,QAAI,SAAS,UAAU,OAAO,SAAS,SAAS,KAAK;AACnD,aAAO,SAAS;AAAA,IAClB,OAAO;AACL,YAAM,IAAI,UAAU,QAAQ;AAAA,IAC9B;AAAA,EACF;AACF;","names":["override"]}
|