@coinlist-co/react 0.11.0 → 0.11.1-rc.22d81d4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-AQIHCFW4.js +279 -0
- package/dist/chunk-AQIHCFW4.js.map +1 -0
- package/dist/{chunk-B2HCVPCQ.js → chunk-PRG3EDQJ.js} +25 -10
- package/dist/chunk-PRG3EDQJ.js.map +1 -0
- package/dist/{chunk-UIIXXLA7.js → chunk-ZVB6KWZ2.js} +484 -141
- package/dist/chunk-ZVB6KWZ2.js.map +1 -0
- package/dist/client/index.cjs +1307 -461
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +216 -211
- package/dist/client/index.d.ts +216 -211
- package/dist/client/index.js +464 -108
- package/dist/client/index.js.map +1 -1
- package/dist/collections-DrJFEDHl.d.cts +116 -0
- package/dist/collections-pLtrj6fw.d.ts +116 -0
- package/dist/{config-B5mwS_2l.d.cts → config-C6vlghJY.d.cts} +713 -22
- package/dist/{config-B5mwS_2l.d.ts → config-C6vlghJY.d.ts} +713 -22
- package/dist/server/index.cjs +766 -209
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +80 -3
- package/dist/server/index.d.ts +80 -3
- package/dist/server/index.js +120 -51
- package/dist/server/index.js.map +1 -1
- package/dist/shared/index.cjs +486 -123
- package/dist/shared/index.cjs.map +1 -1
- package/dist/shared/index.d.cts +18 -5
- package/dist/shared/index.d.ts +18 -5
- package/dist/shared/index.js +8 -2
- package/package.json +3 -2
- package/dist/chunk-B2HCVPCQ.js.map +0 -1
- package/dist/chunk-KDGNDAHA.js +0 -146
- package/dist/chunk-KDGNDAHA.js.map +0 -1
- package/dist/chunk-UIIXXLA7.js.map +0 -1
- package/dist/collections-BhDkYmzV.d.cts +0 -65
- package/dist/collections-CZhHoQHr.d.ts +0 -65
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Attributes,
|
|
3
|
+
HEADER_IDEMPOTENCY_KEY,
|
|
4
|
+
HttpClient,
|
|
5
|
+
HttpError,
|
|
6
|
+
Request,
|
|
7
|
+
getUUIDv4
|
|
8
|
+
} from "./chunk-ZVB6KWZ2.js";
|
|
9
|
+
|
|
10
|
+
// src/shared/api/nabu/config.ts
|
|
11
|
+
var NABU_BASE_URL = "https://asset.coinlist.co";
|
|
12
|
+
|
|
13
|
+
// src/shared/core/observability/pino-logger.ts
|
|
14
|
+
function toPinoRecord(event) {
|
|
15
|
+
try {
|
|
16
|
+
const record = {};
|
|
17
|
+
for (const key of ownKeys(event.fields)) {
|
|
18
|
+
record[key] = readProperty(event.fields, key, 0, /* @__PURE__ */ new WeakSet());
|
|
19
|
+
}
|
|
20
|
+
const cause = "cause" in event ? event.cause : void 0;
|
|
21
|
+
if (cause !== void 0) {
|
|
22
|
+
record.cause = sanitize(cause, 0, /* @__PURE__ */ new WeakSet());
|
|
23
|
+
}
|
|
24
|
+
return { ...record, scope: event.scope, ...event.bindings };
|
|
25
|
+
} catch (_) {
|
|
26
|
+
return { "log.render": "<unrenderable event>" };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
var PINO_LEVEL = {
|
|
30
|
+
none: "silent",
|
|
31
|
+
error: "error",
|
|
32
|
+
warn: "warn",
|
|
33
|
+
info: "info",
|
|
34
|
+
debug: "debug"
|
|
35
|
+
};
|
|
36
|
+
var MAX_DEPTH = 8;
|
|
37
|
+
function sanitize(value, depth, seen) {
|
|
38
|
+
switch (typeof value) {
|
|
39
|
+
case "string":
|
|
40
|
+
case "boolean":
|
|
41
|
+
return value;
|
|
42
|
+
case "number":
|
|
43
|
+
return Number.isFinite(value) ? value : String(value);
|
|
44
|
+
case "bigint":
|
|
45
|
+
return value.toString();
|
|
46
|
+
case "undefined":
|
|
47
|
+
return "<undefined>";
|
|
48
|
+
case "function":
|
|
49
|
+
return "<function>";
|
|
50
|
+
case "symbol":
|
|
51
|
+
return value.toString();
|
|
52
|
+
case "object":
|
|
53
|
+
return value === null ? null : sanitizeObject(value, depth, seen);
|
|
54
|
+
default:
|
|
55
|
+
return "<unrenderable>";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function sanitizeObject(value, depth, seen) {
|
|
59
|
+
if (seen.has(value)) return "<circular>";
|
|
60
|
+
if (depth >= MAX_DEPTH) return "<max depth>";
|
|
61
|
+
if (value instanceof Error) return describeError(value);
|
|
62
|
+
if (value instanceof Date) return describeDate(value);
|
|
63
|
+
seen.add(value);
|
|
64
|
+
try {
|
|
65
|
+
if (Array.isArray(value)) {
|
|
66
|
+
return value.map(
|
|
67
|
+
(_item, index) => readProperty(value, String(index), depth, seen)
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
const out = {};
|
|
71
|
+
for (const key of ownKeys(value)) {
|
|
72
|
+
out[key] = readProperty(value, key, depth, seen);
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
} finally {
|
|
76
|
+
seen.delete(value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function readProperty(owner, key, depth, seen) {
|
|
80
|
+
try {
|
|
81
|
+
return sanitize(owner[key], depth + 1, seen);
|
|
82
|
+
} catch (_) {
|
|
83
|
+
return "<unreadable>";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function ownKeys(value) {
|
|
87
|
+
try {
|
|
88
|
+
return Object.keys(value);
|
|
89
|
+
} catch (_) {
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function describeError(error) {
|
|
94
|
+
return {
|
|
95
|
+
name: safeRead(() => error.name),
|
|
96
|
+
message: safeRead(() => error.message),
|
|
97
|
+
stack: safeRead(() => error.stack)
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function describeDate(date) {
|
|
101
|
+
return safeRead(() => date.toISOString());
|
|
102
|
+
}
|
|
103
|
+
function safeRead(read) {
|
|
104
|
+
try {
|
|
105
|
+
const value = read();
|
|
106
|
+
return typeof value === "string" ? value : "<unreadable>";
|
|
107
|
+
} catch (_) {
|
|
108
|
+
return "<unreadable>";
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
var SDK_LOGGER_NAME = "@coinlist-co/react";
|
|
112
|
+
function loggerOverPino(sink, level) {
|
|
113
|
+
return {
|
|
114
|
+
level: () => level,
|
|
115
|
+
debug: (event) => emit(sink, "debug", event),
|
|
116
|
+
info: (event) => emit(sink, "info", event),
|
|
117
|
+
warn: (event) => emit(sink, "warn", event),
|
|
118
|
+
error: (event) => emit(sink, "error", event)
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function emit(sink, method, event) {
|
|
122
|
+
try {
|
|
123
|
+
const value = event();
|
|
124
|
+
sink[method](toPinoRecord(value), value.msg);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
reportRenderFailure(sink, error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function reportRenderFailure(sink, error) {
|
|
130
|
+
try {
|
|
131
|
+
sink.error(
|
|
132
|
+
{ "error.type": error instanceof Error ? error.name : typeof error },
|
|
133
|
+
"log event failed to render"
|
|
134
|
+
);
|
|
135
|
+
} catch (_) {
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/shared/api/middleware/attach-session-middleware.ts
|
|
140
|
+
function attachSessionMiddleware(fetchAccessToken) {
|
|
141
|
+
return async (request) => {
|
|
142
|
+
if (!Attributes.isProtected(request.attributes)) {
|
|
143
|
+
return request;
|
|
144
|
+
}
|
|
145
|
+
let accessToken = await fetchAccessToken(false);
|
|
146
|
+
if (!accessToken) {
|
|
147
|
+
const clientCreds = Attributes.getClientCredentials(request.attributes);
|
|
148
|
+
if (clientCreds) {
|
|
149
|
+
accessToken = clientCreds;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (accessToken === null) {
|
|
153
|
+
return request;
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
...request,
|
|
157
|
+
headers: {
|
|
158
|
+
...request.headers ?? {},
|
|
159
|
+
Authorization: `Bearer ${accessToken.value}`
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/shared/api/middleware/idempotency-key.ts
|
|
166
|
+
var idempotencyKeyMiddleware = async (request) => {
|
|
167
|
+
if (!Attributes.isIdempotent(request.attributes)) {
|
|
168
|
+
return request;
|
|
169
|
+
}
|
|
170
|
+
const existingHeaders = request.headers ?? {};
|
|
171
|
+
if (existingHeaders[HEADER_IDEMPOTENCY_KEY]) {
|
|
172
|
+
return request;
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
...request,
|
|
176
|
+
headers: {
|
|
177
|
+
...existingHeaders,
|
|
178
|
+
[HEADER_IDEMPOTENCY_KEY]: getUUIDv4()
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// src/shared/api/middleware/request-retry.ts
|
|
184
|
+
var MAX_ATTEMPTS = 3;
|
|
185
|
+
var INITIAL_DELAY_MS = 300;
|
|
186
|
+
var MAX_DELAY_MS = 2e3;
|
|
187
|
+
var RETRYABLE_4XX = /* @__PURE__ */ new Set([408, 409, 429]);
|
|
188
|
+
function isRetryableStatus(status) {
|
|
189
|
+
return status >= 500 && status < 600 || RETRYABLE_4XX.has(status);
|
|
190
|
+
}
|
|
191
|
+
function getRetryDelayMs(attempt) {
|
|
192
|
+
return Math.min(INITIAL_DELAY_MS * 2 ** (attempt - 1), MAX_DELAY_MS);
|
|
193
|
+
}
|
|
194
|
+
function createRequestRetryMiddleware(options = {}) {
|
|
195
|
+
const delayFn = options.delayFn ?? defaultDelay;
|
|
196
|
+
return async ({ request, response, retry }) => {
|
|
197
|
+
if (!isRetryableStatus(response.status)) {
|
|
198
|
+
return response;
|
|
199
|
+
}
|
|
200
|
+
const currentAttempt = Attributes.getRetryAttempt(request.attributes);
|
|
201
|
+
if (currentAttempt >= MAX_ATTEMPTS - 1) {
|
|
202
|
+
return response;
|
|
203
|
+
}
|
|
204
|
+
const nextAttempt = currentAttempt + 1;
|
|
205
|
+
await delayFn(getRetryDelayMs(nextAttempt));
|
|
206
|
+
const nextRequest = Request.concatAttributes(
|
|
207
|
+
request,
|
|
208
|
+
Attributes.retryAttempt(nextAttempt)
|
|
209
|
+
);
|
|
210
|
+
return retry(nextRequest);
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function defaultDelay(ms) {
|
|
214
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
215
|
+
}
|
|
216
|
+
var requestRetryMiddleware = createRequestRetryMiddleware();
|
|
217
|
+
|
|
218
|
+
// src/shared/api/middleware/session-renewal.ts
|
|
219
|
+
function renewSessionMiddleware(fetchAccessToken) {
|
|
220
|
+
return async ({ request, response, retry }) => {
|
|
221
|
+
if (response.status !== 401) {
|
|
222
|
+
return response;
|
|
223
|
+
}
|
|
224
|
+
if (!Attributes.isProtected(request.attributes)) {
|
|
225
|
+
return response;
|
|
226
|
+
}
|
|
227
|
+
if (Attributes.wasRenewAttempted(request.attributes)) {
|
|
228
|
+
return response;
|
|
229
|
+
}
|
|
230
|
+
const newToken = await fetchAccessToken(true);
|
|
231
|
+
if (newToken) {
|
|
232
|
+
const nextRequest = Request.concatAttributes(
|
|
233
|
+
request,
|
|
234
|
+
Attributes.renewAttempted(true)
|
|
235
|
+
);
|
|
236
|
+
return retry(nextRequest);
|
|
237
|
+
} else {
|
|
238
|
+
return response;
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// src/shared/api/authenticated-api-client.ts
|
|
244
|
+
var AuthenticatedApiClient = class {
|
|
245
|
+
constructor(config, fetchAccessToken, additionalBeforeRequest = [], logger = null) {
|
|
246
|
+
this.httpClient = new HttpClient(
|
|
247
|
+
config,
|
|
248
|
+
{
|
|
249
|
+
beforeRequest: [
|
|
250
|
+
attachSessionMiddleware(fetchAccessToken),
|
|
251
|
+
...additionalBeforeRequest,
|
|
252
|
+
idempotencyKeyMiddleware
|
|
253
|
+
],
|
|
254
|
+
afterRequest: [
|
|
255
|
+
renewSessionMiddleware(fetchAccessToken),
|
|
256
|
+
requestRetryMiddleware
|
|
257
|
+
]
|
|
258
|
+
},
|
|
259
|
+
logger
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
async send(request) {
|
|
263
|
+
const response = await this.httpClient.send(request);
|
|
264
|
+
if (response.status >= 200 && response.status < 300) {
|
|
265
|
+
return response.body;
|
|
266
|
+
} else {
|
|
267
|
+
throw new HttpError(response);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
export {
|
|
273
|
+
AuthenticatedApiClient,
|
|
274
|
+
NABU_BASE_URL,
|
|
275
|
+
PINO_LEVEL,
|
|
276
|
+
SDK_LOGGER_NAME,
|
|
277
|
+
loggerOverPino
|
|
278
|
+
};
|
|
279
|
+
//# sourceMappingURL=chunk-AQIHCFW4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/api/nabu/config.ts","../src/shared/core/observability/pino-logger.ts","../src/shared/api/middleware/attach-session-middleware.ts","../src/shared/api/middleware/idempotency-key.ts","../src/shared/api/middleware/request-retry.ts","../src/shared/api/middleware/session-renewal.ts","../src/shared/api/authenticated-api-client.ts"],"sourcesContent":["/**\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 type {\n DebugEvent,\n Logger,\n LogLevel,\n SafeEvent,\n} from '@/shared/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 `@/shared`\n * stays pino-free and the `./shared` 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 * `@/shared` 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 type { HttpRequest } from '@/shared/api/http';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type { BeforeRequestMiddleware } from '@/shared/api/http-client';\nimport type { OAuthAccessToken } from '@/shared/types/oauth-session';\n\nexport function attachSessionMiddleware(\n fetchAccessToken: (refresh: boolean) => Promise<OAuthAccessToken | null>\n): BeforeRequestMiddleware {\n return async (request: HttpRequest): Promise<HttpRequest> => {\n if (!Attributes.isProtected(request.attributes)) {\n return request;\n }\n\n let accessToken = await fetchAccessToken(false);\n if (!accessToken) {\n const clientCreds = Attributes.getClientCredentials(request.attributes);\n if (clientCreds) {\n accessToken = clientCreds;\n }\n }\n\n if (accessToken === null) {\n return request;\n }\n\n return {\n ...request,\n headers: {\n ...(request.headers ?? {}),\n Authorization: `Bearer ${accessToken.value}`,\n },\n };\n };\n}\n","import { HEADER_IDEMPOTENCY_KEY } from '@/shared/api/frontline/config';\nimport type { HttpRequest } from '@/shared/api/http';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type { BeforeRequestMiddleware } from '@/shared/api/http-client';\nimport { getUUIDv4 } from '@/shared/core/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 '@/shared/api/http';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type { AfterRequestMiddleware } from '@/shared/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 (!isRetryableStatus(response.status)) {\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 '@/shared/api/http';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type { AfterRequestMiddleware } from '@/shared/api/http-client';\nimport type { OAuthAccessToken } from '@/shared/types/oauth-session';\n\nexport function renewSessionMiddleware(\n fetchAccessToken: (refresh: boolean) => Promise<OAuthAccessToken | null>\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(true);\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, HttpRequest } from '@/shared/api/http';\nimport { HttpError } from '@/shared/api/http';\nimport type { BeforeRequestMiddleware } from '@/shared/api/http-client';\nimport { HttpClient } from '@/shared/api/http-client';\nimport { attachSessionMiddleware } from '@/shared/api/middleware/attach-session-middleware';\nimport { idempotencyKeyMiddleware } from '@/shared/api/middleware/idempotency-key';\nimport { requestRetryMiddleware } from '@/shared/api/middleware/request-retry';\nimport { renewSessionMiddleware } from '@/shared/api/middleware/session-renewal';\nimport type { Logger } from '@/shared/types/logger';\nimport type { OAuthAccessToken } from '@/shared/types/oauth-session';\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: (refresh: boolean) => Promise<OAuthAccessToken | null>,\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":"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","names":[]}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
Bps,
|
|
5
5
|
DecimalString,
|
|
6
6
|
EvmContractAddress,
|
|
7
|
+
InvariantError,
|
|
7
8
|
MAX_UINT_256,
|
|
8
9
|
NA_AMOUNT_ASSET_UI,
|
|
9
10
|
StablecoinSymbol,
|
|
@@ -15,8 +16,9 @@ import {
|
|
|
15
16
|
fetchOffersPage,
|
|
16
17
|
formattedUsdPrice,
|
|
17
18
|
generateSecureRandomBase64Url,
|
|
19
|
+
internalLogger,
|
|
18
20
|
sha256
|
|
19
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-ZVB6KWZ2.js";
|
|
20
22
|
|
|
21
23
|
// src/shared/types/oauth.ts
|
|
22
24
|
var AuthorizationCode = (value) => value;
|
|
@@ -187,7 +189,7 @@ var TOKEN_REGISTRY = {
|
|
|
187
189
|
case "USDT":
|
|
188
190
|
return USDT;
|
|
189
191
|
default:
|
|
190
|
-
throw new
|
|
192
|
+
throw new InvariantError(`Unknown asset symbol: ${symbol}`);
|
|
191
193
|
}
|
|
192
194
|
},
|
|
193
195
|
contractAddress: (symbol, chain) => {
|
|
@@ -197,7 +199,7 @@ var TOKEN_REGISTRY = {
|
|
|
197
199
|
case "USDT":
|
|
198
200
|
return USDT_ADDRESSES[chain];
|
|
199
201
|
default:
|
|
200
|
-
throw new
|
|
202
|
+
throw new InvariantError(`Unknown asset symbol: ${symbol}`);
|
|
201
203
|
}
|
|
202
204
|
}
|
|
203
205
|
};
|
|
@@ -551,21 +553,33 @@ function formattedPricePerShare(quote, locale) {
|
|
|
551
553
|
var OffersNamespaceImpl = class {
|
|
552
554
|
constructor(ctx) {
|
|
553
555
|
this.ctx = ctx;
|
|
556
|
+
this.log = internalLogger(ctx.logger, "OFFERS");
|
|
554
557
|
}
|
|
555
558
|
async list() {
|
|
556
|
-
|
|
557
|
-
|
|
559
|
+
return this.log.wrap("list", void 0, async () => {
|
|
560
|
+
await this.ctx.ensureUserAuthenticated();
|
|
561
|
+
return fetchOffers(this.ctx.api, void 0);
|
|
562
|
+
});
|
|
558
563
|
}
|
|
559
564
|
async listPage(params) {
|
|
560
|
-
|
|
561
|
-
|
|
565
|
+
return this.log.wrap("listPage", params, async () => {
|
|
566
|
+
await this.ctx.ensureUserAuthenticated();
|
|
567
|
+
return fetchOffersPage(this.ctx.api, params, void 0);
|
|
568
|
+
});
|
|
562
569
|
}
|
|
563
570
|
async get(id) {
|
|
564
|
-
|
|
565
|
-
|
|
571
|
+
return this.log.wrap("get", id, async () => {
|
|
572
|
+
await this.ctx.ensureUserAuthenticated();
|
|
573
|
+
return fetchOfferDetails(this.ctx.api, id, void 0);
|
|
574
|
+
});
|
|
566
575
|
}
|
|
567
576
|
};
|
|
568
577
|
|
|
578
|
+
// src/shared/types/blockchain/wallet-error.ts
|
|
579
|
+
var RedactedWalletError = {
|
|
580
|
+
fromWalletError: (error) => error.type === "unknown" ? { type: "unknown" } : error
|
|
581
|
+
};
|
|
582
|
+
|
|
569
583
|
// src/shared/types/user.ts
|
|
570
584
|
var UserId = (value) => value;
|
|
571
585
|
var UserEmail = (value) => value;
|
|
@@ -615,8 +629,9 @@ export {
|
|
|
615
629
|
superstateSwapContractAddress,
|
|
616
630
|
formattedPricePerShare,
|
|
617
631
|
OffersNamespaceImpl,
|
|
632
|
+
RedactedWalletError,
|
|
618
633
|
UserId,
|
|
619
634
|
UserEmail,
|
|
620
635
|
User
|
|
621
636
|
};
|
|
622
|
-
//# sourceMappingURL=chunk-
|
|
637
|
+
//# sourceMappingURL=chunk-PRG3EDQJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/types/oauth.ts","../src/shared/core/auth/pkce.ts","../src/shared/core/blockchain/bps.ts","../src/shared/core/blockchain/erc20/abi.ts","../src/shared/core/blockchain/token-registry.ts","../src/shared/core/checkout/ondo/constants.ts","../src/shared/core/checkout/ondo/math.ts","../src/shared/core/checkout/superstate/blockchain/abi.ts","../src/shared/core/checkout/superstate/blockchain/math.ts","../src/shared/core/checkout/superstate/blockchain/quote.ts","../src/shared/core/checkout/superstate/blockchain/status.ts","../src/shared/core/checkout/superstate/blockchain/swapped-event.ts","../src/shared/core/checkout/superstate/constants.ts","../src/shared/core/checkout/superstate/formatters.ts","../src/shared/core/offers/offers-namespace.ts","../src/shared/types/blockchain/wallet-error.ts","../src/shared/types/user.ts"],"sourcesContent":["import type { Newtype } from '@/shared/types/newtype';\n\nexport type AuthorizationCode = Newtype<string, 'AuthorizationCode'>;\nexport const AuthorizationCode = (value: string): AuthorizationCode =>\n value as AuthorizationCode;\n\nexport type CodeVerifier = Newtype<string, 'CodeVerifier'>;\nexport const CodeVerifier = (value: string): CodeVerifier =>\n value as CodeVerifier;\n\nexport type CodeChallenge = Newtype<string, 'CodeChallenge'>;\nexport const CodeChallenge = (value: string): CodeChallenge =>\n value as CodeChallenge;\n\nexport type PKCEState = Newtype<string, 'PKCEState'>;\nexport const PKCEState = (value: string) => value as PKCEState;\n\nexport type RedirectUri = Newtype<string, 'RedirectUri'>;\nexport const RedirectUri = (value: string): RedirectUri => value as RedirectUri;\n\nexport type ClientId = Newtype<string, 'ClientId'>;\nexport const ClientId = (value: string): ClientId => value as ClientId;\n\nexport type ClientSecret = Newtype<string, 'ClientSecret'>;\nexport const ClientSecret = (value: string): ClientSecret =>\n value as ClientSecret;\n","import {\n arrayBufferToBase64Url,\n generateSecureRandomBase64Url,\n sha256,\n} from '@/shared/core/utils/crypto';\nimport type {\n CodeChallenge as CodeChallengeType,\n CodeVerifier as CodeVerifierType,\n PKCEState as PKCEStateType,\n} from '@/shared/types/oauth';\nimport {\n type ClientId,\n CodeChallenge,\n CodeVerifier,\n PKCEState,\n type RedirectUri,\n} from '@/shared/types/oauth';\n\nexport type PKCEParams = {\n clientId: ClientId;\n responseType: 'code';\n redirectUri: RedirectUri;\n codeChallenge: CodeChallengeType;\n codeChallengeMethod: 'S256';\n state: PKCEStateType;\n codeVerifier: CodeVerifierType;\n};\n\nexport type PKCEConfig = {\n clientId: ClientId;\n redirectUri: RedirectUri;\n};\n\n/**\n * Generates PKCE parameters for an OAuth2 authorization code flow.\n * Pure crypto — no React, no DOM beyond Web Crypto API. Safe to use\n * in server-side code and Next.js middleware.\n */\nexport async function generatePKCEParams(\n config: PKCEConfig\n): Promise<PKCEParams> {\n const state = generateSecureRandomBase64Url(32);\n const codeVerifier = generateSecureRandomBase64Url(32);\n const codeChallengeRaw = await sha256(codeVerifier);\n const codeChallenge = arrayBufferToBase64Url(codeChallengeRaw, false);\n\n return {\n clientId: config.clientId,\n responseType: 'code',\n redirectUri: config.redirectUri,\n codeChallenge: CodeChallenge(codeChallenge),\n codeChallengeMethod: 'S256',\n state: PKCEState(state),\n codeVerifier: CodeVerifier(codeVerifier),\n };\n}\n","import {\n assertUint256,\n Bps,\n type Uint256,\n} from '@/shared/types/blockchain/core';\n\n/** Basis-point denominator: 10_000 bps = 100%. */\nexport const BPS_DENOM: Bps = Bps(10_000n);\n\n/**\n * Applies a basis-point fraction to an amount, flooring the result.\n * `floor((amount × bps) / BPS_DENOM)`. The result is bounds-checked, so an\n * overflow (bps far above BPS_DENOM) or a negative product is rejected.\n */\nexport function applyBps(amount: Uint256, bps: Bps): Uint256 {\n return assertUint256((amount * bps) / BPS_DENOM);\n}\n","/**\n * Minimal ERC-20 ABI the SDK writes against (mirrors viem's `erc20Abi`). The\n * swap flow uses `approve`; `allowance`/`balanceOf`/`decimals`/`symbol`/`name`\n * are included so reads share a single SDK-owned ABI.\n */\nexport const ERC20_ABI = [\n {\n type: 'function',\n name: 'allowance',\n inputs: [\n { name: 'owner', type: 'address' },\n { name: 'spender', type: 'address' },\n ],\n outputs: [{ name: '', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'approve',\n inputs: [\n { name: 'spender', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n name: 'balanceOf',\n inputs: [{ name: 'account', type: 'address' }],\n outputs: [{ name: '', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'decimals',\n inputs: [],\n outputs: [{ name: '', type: 'uint8' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'name',\n inputs: [],\n outputs: [{ name: '', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'symbol',\n inputs: [],\n outputs: [{ name: '', type: 'string' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'totalSupply',\n inputs: [],\n outputs: [{ name: '', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'transfer',\n inputs: [\n { name: 'recipient', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n name: 'transferFrom',\n inputs: [\n { name: 'sender', type: 'address' },\n { name: 'recipient', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n name: 'Approval',\n inputs: [\n { name: 'owner', type: 'address', indexed: true },\n { name: 'spender', type: 'address', indexed: true },\n { name: 'value', type: 'uint256', indexed: false },\n ],\n anonymous: false,\n },\n {\n type: 'event',\n name: 'Transfer',\n inputs: [\n { name: 'from', type: 'address', indexed: true },\n { name: 'to', type: 'address', indexed: true },\n { name: 'value', type: 'uint256', indexed: false },\n ],\n anonymous: false,\n },\n] as const;\n","import {\n AssetDecimals,\n type Erc20Asset,\n type EthereumChain,\n EvmContractAddress,\n type KnownAssetSymbol,\n StablecoinSymbol,\n} from '@/shared/types/blockchain/core';\nimport { InvariantError } from '@/shared/types/errors';\n\nexport const USDC_SYMBOL: StablecoinSymbol = StablecoinSymbol('USDC');\nexport const USDC: Erc20Asset = {\n name: 'USD Coin',\n symbol: USDC_SYMBOL,\n decimals: AssetDecimals(6),\n};\n\nexport const USDT_SYMBOL: StablecoinSymbol = StablecoinSymbol('USDT');\nexport const USDT: Erc20Asset = {\n name: 'Tether USD',\n symbol: USDT_SYMBOL,\n decimals: AssetDecimals(6),\n};\n\n/** ERC-20 contract addresses for a supported stablecoin, keyed by chain. */\ntype TokenAddresses = Record<EthereumChain, EvmContractAddress>;\n\nconst USDC_ADDRESSES: TokenAddresses = {\n ethereum_mainnet: EvmContractAddress(\n '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'\n ),\n ethereum_sepolia: EvmContractAddress(\n '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238'\n ),\n};\n\nconst USDT_ADDRESSES: TokenAddresses = {\n ethereum_mainnet: EvmContractAddress(\n '0xdac17f958d2ee523a2206206994597c13d831ec7'\n ),\n ethereum_sepolia: EvmContractAddress(\n '0x7169D38820dfd117C3FA1f22a697dBA58d90BA06'\n ),\n};\n\n/** Lookups for the stablecoins the SDK's swap flows support out of the box. */\nexport const TOKEN_REGISTRY = {\n erc20: (symbol: KnownAssetSymbol): Erc20Asset => {\n switch (symbol) {\n case 'USDC':\n return USDC;\n case 'USDT':\n return USDT;\n default:\n throw new InvariantError(`Unknown asset symbol: ${symbol}`);\n }\n },\n contractAddress: (\n symbol: KnownAssetSymbol,\n chain: EthereumChain\n ): EvmContractAddress => {\n switch (symbol) {\n case 'USDC':\n return USDC_ADDRESSES[chain];\n case 'USDT':\n return USDT_ADDRESSES[chain];\n default:\n throw new InvariantError(`Unknown asset symbol: ${symbol}`);\n }\n },\n};\n","import { USDC_SYMBOL } from '@/shared/core/blockchain/token-registry';\nimport {\n DecimalString,\n type EthereumChain,\n EvmContractAddress,\n type StablecoinSymbol,\n} from '@/shared/types/blockchain/core';\nimport type { NonEmptyArray } from '@/shared/types/collections';\n\n/**\n * The CoinList integration contract an Ondo swap is sent to, and therefore the\n * ERC-20 spender the user approves.\n *\n * It is a constant rather than a value read off the built transaction because\n * the approval has to happen *before* the transaction is built: the calldata\n * is only good for a minute, and an approval takes most of one to mine. The\n * built transaction's `tx.to` is checked against this before broadcasting, so a\n * stale constant fails loudly instead of sending a transaction that reverts on\n * `transferFrom`.\n *\n * Mainnet is absent, not zeroed: Ondo's production integration contract is not\n * deployed yet, and a zero address would be approved happily and revert only\n * later. Flows return `unsupported-chain` for a chain with no entry.\n */\nconst ONDO_SWAP_CONTRACT_ADDRESSES: Partial<\n Record<EthereumChain, EvmContractAddress>\n> = {\n ethereum_sepolia: EvmContractAddress(\n '0xFF9c5Ade32d9B4102469Bd5F3817CB0061b25feC'\n ),\n};\n\n/** The Ondo integration contract on `chain`, or `null` where none is deployed. */\nexport function ondoSwapContractAddress(\n chain: EthereumChain\n): EvmContractAddress | null {\n return ONDO_SWAP_CONTRACT_ADDRESSES[chain] ?? null;\n}\n\n/**\n * How often the Ondo checkout refreshes what it is allowed to poll: the market\n * status and the indicative price. Both are free - neither spends an\n * attestation - so this is paced for a price the user can trust rather than\n * for cost.\n *\n * A built transaction is deliberately not on this timer. Building spends an\n * attestation, so it happens once per order and once per refresh the user\n * asks for.\n */\nexport const ONDO_POLL_INTERVAL_MS = 15_000;\n\n/**\n * How close to its deadline a built transaction stops being offerable.\n *\n * Placing an order is not instant - the wallet has to prompt, the user has to\n * confirm, and the transaction has to reach a node - so calldata with a second\n * left is one the contract will reject. Treating the last few seconds as\n * already expired turns a paid-for revert into a refresh button.\n */\nexport const ONDO_QUOTE_EXPIRY_THRESHOLD_MS = 5_000;\n\n/**\n * The order size the sidebar prices against before the user names one.\n *\n * Ondo prices by size, so some amount has to be sent. $1,000 is a plausible\n * order rather than a token one: a size so small that Ondo's minimum rejects\n * it would leave the panel permanently blank.\n *\n * Named distinctly from `DEFAULT_AMOUNT_TO_COMPUTE_PRICE` in the swap\n * constants, which is a raw `bigint` of USDC base units for a different\n * endpoint. Both barrels are flat, so two constants of the same name could not\n * coexist - and they mean different things anyway.\n */\nexport const DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE = DecimalString('1000');\n\n/**\n * The coins an Ondo buy can be funded with, in display order, with the first\n * preselected.\n *\n * USDC alone today: it is what the Sepolia integration contract accepts. The\n * amount step renders a single entry as a plain card and two or more as a\n * picker, so adding one here is all it takes.\n */\nexport const ONDO_SUPPORTED_INPUT_ASSETS: NonEmptyArray<StablecoinSymbol> = [\n USDC_SYMBOL,\n];\n","import {\n assertUint256,\n BlockchainAmount,\n type Uint256,\n} from '@/shared/types/blockchain/core';\nimport { ValidationError } from '@/shared/types/errors';\nimport type { OndoSwapTransaction } from '@/shared/types/providers/ondo/ondo';\n\n/**\n * The price of one whole asset token in an Ondo swap transaction, in the\n * funding token's units.\n *\n * `POST /v1/ondo/swap/transaction` publishes no price. Frontline drops\n * Ninshubur's deliberately, because `GET /v1/ondo/swap/quote` already serves\n * one under that name at a different scale, and echoing both would leave a\n * caller to guess which was which.\n *\n * Dividing the two amounts the response *does* carry is better than reading\n * the indicative one anyway: it is the price this transaction fills at, rather\n * than a poll that has since moved and was struck against a different size.\n *\n * **Fee-exclusive.** `notionalValue` is the deposit after CoinList's fee comes\n * off, so this is the price Ondo filled at, not the buyer's all-in cost per\n * token - that would be `payInputAmount / receiveOutputAmount`, and it is\n * higher. Fee-exclusive is what the review screen wants, because it renders\n * the fee on its own line: price x quantity, plus fee, comes to the total.\n * Making this all-in would double-count the fee against that breakdown.\n *\n * The two are equal until ENG-1718 turns a fee on, which frontline rejects\n * today. They diverge the moment it does, so the choice is load-bearing rather\n * than academic.\n *\n * Denominated in the *funding* token's decimals, so it pairs with\n * `formattedUsdPrice` and with the fee and total rendered beside it.\n */\nexport function computeOndoPrice(\n transaction: Pick<\n OndoSwapTransaction,\n 'notionalValue' | 'receiveOutputAmount'\n >\n): BlockchainAmount {\n const { notionalValue, receiveOutputAmount } = transaction;\n\n // Unreachable through `OndoSwapTransaction.fromDto`, which rejects a\n // non-positive output at the boundary - frontline refuses to emit one. The\n // guard is here because this runs during render, where a RangeError from a\n // bare BigInt division would take the checkout down instead of a step.\n if (receiveOutputAmount.raw <= 0n) {\n throw new ValidationError(\n 'Ondo price: receiveOutputAmount must be greater than zero'\n );\n }\n\n // Scale the numerator by the asset's exponent so the quotient lands back in\n // the funding token's, which is the scale every other amount on the review\n // screen is in. Floor division: a price is truncated towards zero rather\n // than rounded, so the total it implies never overstates what was paid.\n const scaled =\n notionalValue.raw * 10n ** BigInt(receiveOutputAmount.decimals);\n const raw = scaled / receiveOutputAmount.raw;\n\n return BlockchainAmount({\n raw: assertPriceFits(raw),\n decimals: notionalValue.decimals,\n });\n}\n\n/**\n * A price past uint256 needs an output amount of a few base units against a\n * notional no real balance holds. It cannot come off the wire, so it is a\n * corrupt response rather than an expensive order.\n */\nfunction assertPriceFits(raw: bigint): Uint256 {\n try {\n return assertUint256(raw);\n } catch {\n throw new ValidationError(`Ondo price: out of uint256 bounds (${raw})`);\n }\n}\n","export const SUPERSTATE_SWAP_ABI = [\n {\n type: 'function',\n name: 'authorized',\n inputs: [{ name: 'user', type: 'address', internalType: 'address' }],\n outputs: [{ name: '', type: 'bool', internalType: 'bool' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'stopped',\n inputs: [],\n outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'SWAP_LEVEL',\n inputs: [],\n outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'preview',\n inputs: [\n { name: 'token', type: 'address', internalType: 'address' },\n { name: 'amount', type: 'uint256', internalType: 'uint256' },\n ],\n outputs: [\n {\n name: '',\n type: 'tuple',\n internalType: 'struct Preview',\n components: [\n { name: 'input', type: 'uint256', internalType: 'uint256' },\n { name: 'fee', type: 'uint256', internalType: 'uint256' },\n { name: 'output', type: 'uint256', internalType: 'uint256' },\n ],\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'swap',\n inputs: [\n { name: 'token', type: 'address', internalType: 'address' },\n { name: 'amount', type: 'uint256', internalType: 'uint256' },\n { name: 'slip', type: 'uint256', internalType: 'uint256' },\n ],\n outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n name: 'tokenBalance',\n inputs: [{ name: 'token', type: 'address', internalType: 'address' }],\n outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'outputToken',\n inputs: [],\n outputs: [{ name: '', type: 'address', internalType: 'address' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'outputTokenBalance',\n inputs: [],\n outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'totals',\n inputs: [{ name: 'token', type: 'address', internalType: 'address' }],\n outputs: [\n {\n name: '',\n type: 'tuple',\n internalType: 'struct SwapTotal',\n components: [\n { name: 'inputSum', type: 'uint256', internalType: 'uint256' },\n { name: 'feeSum', type: 'uint256', internalType: 'uint256' },\n { name: 'outputSum', type: 'uint256', internalType: 'uint256' },\n { name: 'count', type: 'uint256', internalType: 'uint256' },\n ],\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'totals',\n inputs: [\n { name: 'user', type: 'address', internalType: 'address' },\n { name: 'token', type: 'address', internalType: 'address' },\n ],\n outputs: [\n {\n name: '',\n type: 'tuple',\n internalType: 'struct SwapTotal',\n components: [\n { name: 'inputSum', type: 'uint256', internalType: 'uint256' },\n { name: 'feeSum', type: 'uint256', internalType: 'uint256' },\n { name: 'outputSum', type: 'uint256', internalType: 'uint256' },\n { name: 'count', type: 'uint256', internalType: 'uint256' },\n ],\n },\n ],\n stateMutability: 'view',\n },\n {\n type: 'function',\n name: 'transfer',\n inputs: [\n { name: 'to', type: 'address', internalType: 'address' },\n { name: 'amount', type: 'uint256', internalType: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool', internalType: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n name: 'transfer',\n inputs: [\n { name: 'to', type: 'address', internalType: 'address' },\n { name: 'token', type: 'address', internalType: 'address' },\n { name: 'amount', type: 'uint256', internalType: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool', internalType: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'function',\n name: 'setBps',\n inputs: [{ name: 'points', type: 'uint256', internalType: 'uint256' }],\n outputs: [{ name: '', type: 'bool', internalType: 'bool' }],\n stateMutability: 'nonpayable',\n },\n {\n type: 'event',\n name: 'Swapped',\n inputs: [\n { name: 'user', type: 'address', indexed: true, internalType: 'address' },\n {\n name: 'inputToken',\n type: 'address',\n indexed: true,\n internalType: 'address',\n },\n {\n name: 'outputToken',\n type: 'address',\n indexed: true,\n internalType: 'address',\n },\n {\n name: 'inputAmount',\n type: 'uint256',\n indexed: false,\n internalType: 'uint256',\n },\n {\n name: 'outputAmount',\n type: 'uint256',\n indexed: false,\n internalType: 'uint256',\n },\n ],\n anonymous: false,\n },\n {\n type: 'event',\n name: 'Transferred',\n inputs: [\n { name: 'to', type: 'address', indexed: true, internalType: 'address' },\n {\n name: 'token',\n type: 'address',\n indexed: true,\n internalType: 'address',\n },\n {\n name: 'amount',\n type: 'uint256',\n indexed: false,\n internalType: 'uint256',\n },\n ],\n anonymous: false,\n },\n {\n type: 'error',\n name: 'InvalidAddress',\n inputs: [],\n },\n {\n type: 'error',\n name: 'InsufficientAmount',\n inputs: [],\n },\n {\n type: 'error',\n name: 'InvalidAmount',\n inputs: [],\n },\n {\n type: 'error',\n name: 'SwapFailed',\n inputs: [\n { name: 'user', type: 'address', internalType: 'address' },\n { name: 'token', type: 'address', internalType: 'address' },\n ],\n },\n] as const;\n","import { applyBps, BPS_DENOM } from '@/shared/core/blockchain/bps';\nimport type { SwapQuote } from '@/shared/core/checkout/superstate/blockchain/quote';\nimport {\n assertUint256,\n BlockchainAmount,\n Bps,\n} from '@/shared/types/blockchain/core';\n\n/**\n * Price of 1 output token in USD, assuming the input token is a $1 stablecoin.\n *\n * `raw_price = inputTokenAmount.raw × 10^outputDecimals ÷ outputTokenAmount.raw`\n *\n * The multiplication happens before the division so we never lose precision to\n * integer truncation early. This mirrors standard fixed-point practice on-chain.\n * Returned decimals match the input token decimals (always the stablecoin's 6).\n */\nexport function computePrice({\n inputTokenAmount,\n outputTokenAmount,\n}: SwapQuote): BlockchainAmount | null {\n if (outputTokenAmount.raw === 0n) return null;\n\n const scale = 10n ** BigInt(outputTokenAmount.decimals);\n const raw = assertUint256(\n (inputTokenAmount.raw * scale) / outputTokenAmount.raw\n );\n\n return BlockchainAmount({ raw, decimals: inputTokenAmount.decimals });\n}\n\n/**\n * Applies slippage to an amount, returning the minimum acceptable amount:\n * `amount × (BPS_DENOM − slippage) / BPS_DENOM`. Throws when `slippage` exceeds\n * `BPS_DENOM` (the retained fraction would be negative).\n */\nexport function computeSlip(\n amount: BlockchainAmount,\n slippage: Bps\n): BlockchainAmount {\n const retained = Bps(assertUint256(BPS_DENOM - slippage));\n const slipRaw = applyBps(amount.raw, retained);\n return BlockchainAmount({ raw: slipRaw, decimals: amount.decimals });\n}\n","import {\n type AssetDecimals,\n BlockchainAmount,\n} from '@/shared/types/blockchain/core';\nimport type { SwapPreview } from '@/shared/types/providers/superstate/swap';\n\n/**\n * A read-only quote for a swap as domain amounts: how much goes in, the\n * protocol fee, and how much would come out. Derived from the raw\n * {@link SwapPreview} the swap contract returns.\n */\nexport type SwapQuote = {\n inputTokenAmount: BlockchainAmount;\n fee: BlockchainAmount;\n outputTokenAmount: BlockchainAmount;\n};\n\nexport const SwapQuote = {\n /**\n * Assembles a {@link SwapQuote} from a raw contract {@link SwapPreview}. The\n * input and fee are denominated in the input token; the output in the output\n * token.\n */\n fromPreview: (\n preview: SwapPreview,\n inputDecimals: AssetDecimals,\n outputDecimals: AssetDecimals\n ): SwapQuote => ({\n inputTokenAmount: BlockchainAmount({\n raw: preview.inputAmount,\n decimals: inputDecimals,\n }),\n fee: BlockchainAmount({ raw: preview.fee, decimals: inputDecimals }),\n outputTokenAmount: BlockchainAmount({\n raw: preview.outputAmount,\n decimals: outputDecimals,\n }),\n }),\n};\n","import type { SwapStatus } from '@/shared/types/providers/superstate/swap';\n\n/**\n * Interprets the on-chain swap availability read from `stopped()` and\n * `SWAP_LEVEL()`.\n *\n * The contract tracks paused operations as a bitmask in `stopped`. The swap is\n * stopped when the SWAP_LEVEL flag is set:\n *\n * (stopped & SWAP_LEVEL) != 0 -> stopped (not active)\n */\nexport function isStopped(status: SwapStatus): boolean {\n return (status.stopped & status.swapLevel) !== 0n;\n}\n","import { parseEventLogs, type TransactionReceipt } from 'viem';\nimport { SUPERSTATE_SWAP_ABI } from '@/shared/core/checkout/superstate/blockchain/abi';\nimport {\n type AssetDecimals,\n BlockchainAmount,\n MAX_UINT_256,\n} from '@/shared/types/blockchain/core';\n\n/**\n * Decodes the confirmed output amount from the `Swapped` event in a swap\n * transaction receipt.\n *\n * Returns `null` when the event is absent or the amount is not a valid uint256\n * so callers can fall back to the quote's expected output — the swap already\n * confirmed on-chain, so a missing/undecodable event should not fail the flow.\n */\nexport function decodeSwappedOutputAmount(\n receipt: TransactionReceipt,\n outputDecimals: AssetDecimals\n): BlockchainAmount | null {\n try {\n const [swapped] = parseEventLogs({\n abi: SUPERSTATE_SWAP_ABI,\n eventName: 'Swapped',\n logs: receipt.logs,\n });\n if (!swapped) return null;\n\n const raw = swapped.args.outputAmount;\n if (raw < 0n || raw > MAX_UINT_256) return null;\n return BlockchainAmount({ raw, decimals: outputDecimals });\n } catch {\n // Undecodable log (ABI mismatch / malformed) — fall back to the\n // quote. The swap already confirmed on-chain, so never fail here.\n return null;\n }\n}\n","import { USDC_SYMBOL } from '@/shared/core/blockchain/token-registry';\nimport {\n Bps,\n type EthereumChain,\n EvmContractAddress,\n type StablecoinSymbol,\n} from '@/shared/types/blockchain/core';\nimport type { NonEmptyArray } from '@/shared/types/collections';\n\n/**\n * Who issues the asset a Superstate swap pays out.\n *\n * A constant rather than a field off the offer: no frontline endpoint carries\n * an issuer, and every offer this checkout serves is Superstate's by\n * definition — `CheckoutContainer` routes here on `superstate::swap` alone.\n */\nexport const SUPERSTATE_ISSUER_NAME = 'Superstate';\n\n/**\n * The coins a Superstate swap can be funded with, in display order, with the\n * first preselected.\n *\n * USDC alone today: it is what the deployed swap contract accepts. The amount\n * step renders a single entry as a plain card and two or more as a picker, so\n * adding one here is all it takes.\n */\nexport const SUPERSTATE_SUPPORTED_INPUT_ASSETS: NonEmptyArray<StablecoinSymbol> =\n [USDC_SYMBOL];\n\n/** Poll interval for refreshing on-chain swap quotes and balances. */\nexport const SWAP_POLL_INTERVAL_MS = 15_000;\n\n/**\n * Notional input used to derive a display price-per-share when the user has\n * not yet entered an amount (1 USDC at 6 decimals).\n */\nexport const DEFAULT_AMOUNT_TO_COMPUTE_PRICE = 1_000_000n;\n\n/** Slippage tolerances offered in the review step, in basis points. */\nexport const SLIPPAGE_OPTIONS_BPS: Bps[] = [25n, 50n, 100n, 200n, 500n].map(\n (n) => Bps(n)\n);\n\n/** Default slippage tolerance (0.5%). */\nexport const DEFAULT_SLIPPAGE_BPS: Bps = Bps(50n);\n\n/**\n * The Superstate swap contract on Ethereum Sepolia, and therefore the ERC-20\n * spender the user approves there.\n *\n * Exported in its own right for a partner driving `coinlist.superstate.execute`\n * at Level 1, where the contract is an explicit parameter.\n */\nexport const SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA: EvmContractAddress =\n EvmContractAddress('0x84f8e9a6C9Cc12fe911259372EfCa5582C4ae557');\n\n/**\n * The Superstate swap contract per chain.\n *\n * Mainnet is absent, not zeroed: the production address is not finalized\n * upstream, and a zero address would be approved happily and revert only later.\n * A chain with no entry has no checkout — `useSuperstateSwapCheckoutViewModel`\n * reports it as the flow-level error rather than quoting against nothing.\n */\nconst SUPERSTATE_SWAP_CONTRACT_ADDRESSES: Partial<\n Record<EthereumChain, EvmContractAddress>\n> = {\n ethereum_sepolia: SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA,\n};\n\n/** The Superstate swap contract on `chain`, or `null` where none is deployed. */\nexport function superstateSwapContractAddress(\n chain: EthereumChain\n): EvmContractAddress | null {\n return SUPERSTATE_SWAP_CONTRACT_ADDRESSES[chain] ?? null;\n}\n","import {\n formattedUsdPrice,\n NA_AMOUNT_ASSET_UI,\n} from '@/shared/core/blockchain/formatters';\nimport { computePrice } from '@/shared/core/checkout/superstate/blockchain/math';\nimport type { SwapQuote } from '@/shared/core/checkout/superstate/blockchain/quote';\nimport type { FormattedAmountAssetUi } from '@/shared/types/blockchain/ui';\n\n/**\n * Formats a quote's implied price per output token as a USD amount.\n *\n * Lives with the provider rather than in `@/shared/core/blockchain/formatters`\n * because {@link SwapQuote} and {@link computePrice} are Superstate's: the\n * shared formatters stay provider-agnostic.\n */\nexport function formattedPricePerShare(\n quote: SwapQuote | null,\n locale: string\n): FormattedAmountAssetUi {\n if (!quote) return NA_AMOUNT_ASSET_UI;\n return formattedUsdPrice(computePrice(quote), locale);\n}\n","import * as offersApi from '@/shared/api/frontline/offers';\nimport type { SharedNamespaceContext } from '@/shared/core/namespace-context';\nimport {\n type InternalLogger,\n internalLogger,\n} from '@/shared/core/observability/internal-logger';\nimport type { Offer, OfferId } from '@/shared/types/offer';\nimport type { OfferDetail } from '@/shared/types/offer-detail';\nimport type {\n PaginatedResponse,\n PaginationParams,\n} from '@/shared/types/pagination';\n\n/**\n * Reads over CoinList's offers: the catalogue a user can browse, and the full\n * detail of a single offer.\n *\n * Every method requires an authenticated user and throws\n * {@link NotAuthenticatedError} otherwise. On the server, the same reads are\n * additionally available with an app-level token — see\n * `ServerOffersNamespace`.\n */\nexport interface OffersNamespace {\n /**\n * Fetches every offer, iterating through all pages. Prefer {@link listPage}\n * when you render a paginated list yourself.\n */\n list(): Promise<Offer[]>;\n\n /**\n * Fetches a single page of offers. Pass the previous response's\n * `startingAfter` as `after` to advance.\n */\n listPage(params: PaginationParams): Promise<PaginatedResponse<Offer>>;\n\n /**\n * Fetches the full detail of one offer, including its options. Note this\n * returns {@link OfferDetail} — a richer model than the {@link Offer}\n * summaries {@link list} returns.\n */\n get(id: OfferId): Promise<OfferDetail>;\n}\n\nexport class OffersNamespaceImpl implements OffersNamespace {\n private readonly log: InternalLogger;\n\n constructor(private readonly ctx: SharedNamespaceContext) {\n this.log = internalLogger(ctx.logger, 'OFFERS');\n }\n\n async list(): Promise<Offer[]> {\n return this.log.wrap('list', undefined, async () => {\n await this.ctx.ensureUserAuthenticated();\n return offersApi.fetchOffers(this.ctx.api, undefined);\n });\n }\n\n async listPage(params: PaginationParams): Promise<PaginatedResponse<Offer>> {\n return this.log.wrap('listPage', params, async () => {\n await this.ctx.ensureUserAuthenticated();\n return offersApi.fetchOffersPage(this.ctx.api, params, undefined);\n });\n }\n\n async get(id: OfferId): Promise<OfferDetail> {\n return this.log.wrap('get', id, async () => {\n await this.ctx.ensureUserAuthenticated();\n return offersApi.fetchOfferDetails(this.ctx.api, id, undefined);\n });\n }\n}\n","import type { Hash } from 'viem';\n\n/**\n * A classified wallet or transaction failure. The SDK derives this from\n * whatever the {@link EvmWallet} throws, so hosts get a stable, typed error\n * shape regardless of the wallet library underneath.\n *\n * Lives here rather than beside its classifier because it is the failure half\n * of the {@link EvmWallet} contract, and because both `@/shared` and\n * `@/client` name it: {@link LogCause} carries one, and classifying a thrown\n * error into one needs viem's error classes, which are browser-side.\n */\nexport type WalletError =\n | { type: 'user_rejected' }\n | { type: 'insufficient_funds' }\n | {\n type: 'contract_reverted';\n /**\n * What the contract said, when it said anything: a `require` string, a\n * panic description, a custom error's name, or the four-byte selector of\n * an error the ABI could not decode.\n *\n * `null` when a revert carried no data, since the string the RPC node\n * offers in its place is not the contract's - see `classifyWalletError`.\n * Nullable rather than optional so that every arm has to answer the\n * question: \"it reverted and said nothing\" is a fact about the revert,\n * and a caller should have to read it rather than miss it.\n *\n * Never the custom error's arguments. A name is a compile-time\n * identifier; its operands are runtime values - an address, a balance -\n * and those are `'debug'` material.\n */\n reason: string | null;\n }\n | { type: 'timeout'; hash: Hash }\n | { type: 'unknown'; cause: unknown };\n\n/**\n * A {@link WalletError} as it may be reported above `'debug'`: the\n * classification, never the throw.\n *\n * Only the `unknown` arm differs, and it differs because it is the one arm\n * carrying a value the SDK did not author - the raw error the wallet library\n * threw, whose message and metadata hold the transaction's `from`, `to`,\n * `value` and calldata. The other four carry compile-time constants or a\n * server-minted identifier already, so they pass through as they stand.\n *\n * This exists as a type rather than as a scrub some function remembers to\n * apply: `LogCause` names it, so an arm that grew a raw field would fail the\n * build instead of quietly reaching {@link Logger.error}.\n */\nexport type RedactedWalletError =\n | Exclude<WalletError, { type: 'unknown' }>\n | { type: 'unknown' };\n\nexport const RedactedWalletError = {\n fromWalletError: (error: WalletError): RedactedWalletError =>\n error.type === 'unknown' ? { type: 'unknown' } : error,\n};\n","import type { UserDto } from '@/shared/types/dto/user';\nimport type { Newtype } from '@/shared/types/newtype';\n\nexport type UserId = Newtype<string, 'UserId'>;\nexport const UserId = (value: string) => value as UserId;\nexport type UserEmail = Newtype<string, 'UserEmail'>;\nexport const UserEmail = (value: string) => value as UserEmail;\n\nexport type User = {\n id: UserId;\n email: UserEmail;\n};\n\nexport const User = {\n fromDto: (dto: UserDto): User => ({\n id: UserId(dto.id),\n email: UserEmail(dto.email),\n }),\n};\n"],"mappings":"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","names":[]}
|