@coinlist-co/react 0.12.2-rc.818bed6 → 0.12.2-rc.99b1bd5

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.
Files changed (34) hide show
  1. package/README.md +10 -0
  2. package/dist/{chunk-OUFI3D3Q.js → chunk-IQAJ3L25.js} +173 -259
  3. package/dist/chunk-IQAJ3L25.js.map +1 -0
  4. package/dist/{chunk-2HCSM3FB.js → chunk-J45AY2FX.js} +10 -10
  5. package/dist/chunk-J45AY2FX.js.map +1 -0
  6. package/dist/{chunk-YMDYLYL3.js → chunk-M2TURNJH.js} +821 -801
  7. package/dist/chunk-M2TURNJH.js.map +1 -0
  8. package/dist/chunk-MJ6YXZWH.js +22 -0
  9. package/dist/chunk-MJ6YXZWH.js.map +1 -0
  10. package/dist/client/index.d.ts +2840 -5756
  11. package/dist/client/index.js +8254 -9600
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/server/index.d.ts +4 -37
  14. package/dist/server/index.js +6 -4
  15. package/dist/server/index.js.map +1 -1
  16. package/dist/{time-DJU6E8KK.d.cts → time-DkU7jivQ.d.ts} +1913 -3256
  17. package/dist/{token-registry-snapshot-DGG5N27C.d.ts → token-registry-snapshot-D0OWXMe4.d.ts} +22 -58
  18. package/dist/universal/index.d.ts +80 -1080
  19. package/dist/universal/index.js +22 -50
  20. package/package.json +18 -14
  21. package/dist/chunk-2HCSM3FB.js.map +0 -1
  22. package/dist/chunk-OUFI3D3Q.js.map +0 -1
  23. package/dist/chunk-YMDYLYL3.js.map +0 -1
  24. package/dist/client/index.cjs +0 -20774
  25. package/dist/client/index.cjs.map +0 -1
  26. package/dist/client/index.d.cts +0 -8328
  27. package/dist/server/index.cjs +0 -4580
  28. package/dist/server/index.cjs.map +0 -1
  29. package/dist/server/index.d.cts +0 -385
  30. package/dist/time-DJU6E8KK.d.ts +0 -4052
  31. package/dist/token-registry-snapshot-B0xCp3GD.d.cts +0 -245
  32. package/dist/universal/index.cjs +0 -4625
  33. package/dist/universal/index.cjs.map +0 -1
  34. package/dist/universal/index.d.cts +0 -1376
@@ -1,4052 +0,0 @@
1
- import { Hash, Transport, PublicClient, Hex } from 'viem';
2
-
3
- declare const __brand: unique symbol;
4
- type Newtype<Base, Branding> = Base & {
5
- readonly [__brand]: Branding;
6
- };
7
-
8
- type AuthorizationCode = Newtype<string, 'AuthorizationCode'>;
9
- declare const AuthorizationCode: (value: string) => AuthorizationCode;
10
- type CodeVerifier = Newtype<string, 'CodeVerifier'>;
11
- declare const CodeVerifier: (value: string) => CodeVerifier;
12
- type CodeChallenge = Newtype<string, 'CodeChallenge'>;
13
- declare const CodeChallenge: (value: string) => CodeChallenge;
14
- type PKCEState = Newtype<string, 'PKCEState'>;
15
- declare const PKCEState: (value: string) => PKCEState;
16
- type RedirectUri = Newtype<string, 'RedirectUri'>;
17
- declare const RedirectUri: (value: string) => RedirectUri;
18
- type ClientId = Newtype<string, 'ClientId'>;
19
- declare const ClientId: (value: string) => ClientId;
20
- type ClientSecret = Newtype<string, 'ClientSecret'>;
21
- declare const ClientSecret: (value: string) => ClientSecret;
22
-
23
- /**
24
- * A classified wallet or transaction failure. The SDK derives this from
25
- * whatever the {@link EvmWallet} throws, so hosts get a stable, typed error
26
- * shape regardless of the wallet library underneath.
27
- *
28
- * Lives here rather than beside its classifier because it is the failure half
29
- * of the {@link EvmWallet} contract, and because both `@/universal` and
30
- * `@/client` name it: {@link LogCause} carries one, and classifying a thrown
31
- * error into one needs viem's error classes, which are browser-side.
32
- */
33
- type WalletError = {
34
- type: 'user_rejected';
35
- } | {
36
- type: 'insufficient_funds';
37
- } | {
38
- type: 'contract_reverted';
39
- /**
40
- * What the contract said, when it said anything: a `require` string, a
41
- * panic description, a custom error's name, or the four-byte selector of
42
- * an error the ABI could not decode.
43
- *
44
- * `null` when a revert carried no data, since the string the RPC node
45
- * offers in its place is not the contract's - see `classifyWalletError`.
46
- * Nullable rather than optional so that every arm has to answer the
47
- * question: "it reverted and said nothing" is a fact about the revert,
48
- * and a caller should have to read it rather than miss it.
49
- *
50
- * Never the custom error's arguments. A name is a compile-time
51
- * identifier; its operands are runtime values - an address, a balance -
52
- * and those are `'debug'` material.
53
- */
54
- reason: string | null;
55
- } | {
56
- type: 'timeout';
57
- hash: Hash;
58
- } | {
59
- type: 'unknown';
60
- cause: unknown;
61
- };
62
- /**
63
- * A {@link WalletError} as it may be reported above `'debug'`: the
64
- * classification, never the throw.
65
- *
66
- * Only the `unknown` arm differs, and it differs because it is the one arm
67
- * carrying a value the SDK did not author - the raw error the wallet library
68
- * threw, whose message and metadata hold the transaction's `from`, `to`,
69
- * `value` and calldata. The other four carry compile-time constants or a
70
- * server-minted identifier already, so they pass through as they stand.
71
- *
72
- * This exists as a type rather than as a scrub some function remembers to
73
- * apply: `LogCause` names it, so an arm that grew a raw field would fail the
74
- * build instead of quietly reaching {@link Logger.error}.
75
- */
76
- type RedactedWalletError = Exclude<WalletError, {
77
- type: 'unknown';
78
- }> | {
79
- type: 'unknown';
80
- };
81
- declare const RedactedWalletError: {
82
- fromWalletError: (error: WalletError) => RedactedWalletError;
83
- };
84
-
85
- /**
86
- * The observability seam a host implements to see inside the SDK.
87
- *
88
- * Pass an implementation as {@link Config.logger} and the SDK reports every
89
- * request it makes, every failure it classifies, and every state a hook
90
- * settles into. Leave it out and the SDK logs nothing at all - there is no
91
- * fallback to `console`, at any level, on any codepath.
92
- *
93
- * Four methods over a {@link LogEvent} lambda, plus {@link level}. An event is
94
- * a constant `msg`, the {@link LogScope} it came from, the accumulated
95
- * {@link LogBindings}, and a bag of `fields` - so a host forwards structured
96
- * records rather than parsing strings.
97
- *
98
- * ```ts
99
- * const logger: Logger = {
100
- * level: () => 'info',
101
- * debug: () => {},
102
- * info: (event) => sink.info(toRecord(event())),
103
- * warn: (event) => sink.warn(toRecord(event())),
104
- * error: (event) => sink.error(toRecord(event())),
105
- * };
106
- * ```
107
- *
108
- * {@link pinoClientLogger} and {@link pinoServerLogger} are ready-made
109
- * implementations over pino, and are what most hosts should reach for.
110
- *
111
- * ## Where to run it
112
- *
113
- * **Not in production, as the default answer.** Development, tests, staging,
114
- * and reproducing a reported bug are where this seam earns its keep. Left
115
- * undefined elsewhere it discloses nothing, and that holds no matter what a
116
- * later revision of the SDK puts on a line.
117
- *
118
- * Where you do run one in production, `'info'` and above is the only sane
119
- * choice, and the shipped implementations make the alternative unrepresentable
120
- * rather than merely discouraged: `isDev: false` narrows the level to
121
- * {@link ProductionLogLevel}, so `'debug'` does not compile. That narrowing is
122
- * a guard for the partner who ignored this paragraph, not an endorsement of
123
- * the practice.
124
- *
125
- * The distinction worth holding onto: `'info'` and above are **redacted by
126
- * construction** - see the next section for exactly what that covers, and the
127
- * type that enforces it. Redacted is a mechanism the SDK can hold itself to. A
128
- * blanket "safe in production" is a promise about your environment that the
129
- * SDK is in no position to make, and one that a single future field could
130
- * quietly break.
131
- *
132
- * `'debug'` is for reproducing a bug: a developer's machine, tests, and beta
133
- * or staging environments where the data flowing through the SDK is not real
134
- * customer data.
135
- *
136
- * ## What each level may disclose
137
- *
138
- * **`'debug'` is unredacted. Every other level is not.**
139
- *
140
- * At `'debug'` the SDK reports request and response bodies, request headers,
141
- * the full URL including its query string, and operation parameters
142
- * **verbatim** - bearer tokens, KYC answers, tax-document fields, wallet
143
- * signatures, the lot. There is no denylist and no redaction: see ADR-8 for
144
- * why a partial guarantee was rejected in favour of an honest absence of one.
145
- *
146
- * At `'info'`, `'warn'` and `'error'` the SDK emits only its own
147
- * classification of what happened and identifiers the server minted: a method
148
- * and a bare path, a status, a duration, a {@link RequestId}, a frontline
149
- * error code and event id, a {@link LogCause} arm. No request body, no
150
- * response body, no query string, no host-supplied parameters, and no message
151
- * text read off a thrown error the SDK did not author.
152
- *
153
- * The type carries that boundary rather than merely documenting it:
154
- * {@link SafeEvent} constrains every field value to a {@link LogValue} scalar,
155
- * so spreading a body, a DTO or an operation's params into an `info`, `warn`
156
- * or `error` line does not compile. Only {@link DebugEvent} accepts arbitrary
157
- * values.
158
- *
159
- * The one deliberate exception is an SDK-authored validation message, which
160
- * quotes the single scalar that failed to map - `Unsupported chain:
161
- * "solana_mainnet"`. It is a hand-written template naming one offending value,
162
- * not a payload, and it is the whole reason this seam exists.
163
- *
164
- * ## Your responsibility
165
- *
166
- * The SDK hands you events. What happens next is yours: **you own the final
167
- * filtering, redaction and retention** before anything is written to a file, a
168
- * console, or a third-party sink such as Sentry or Datadog. In particular, if
169
- * you implement {@link debug} and forward it anywhere durable, you have taken
170
- * on storing live credentials and personal data, deliberately. Implement
171
- * `debug` as a no-op - or return a level below it from {@link level} - in any
172
- * environment where that is not acceptable.
173
- *
174
- * **Every event is a lambda, and that is load bearing.** The SDK consults
175
- * {@link level} first and never invokes the lambda when the level forbids it,
176
- * so an expensive debug event - a serialized DTO, a loop over balances - costs
177
- * nothing in production where the level is `'error'` or `'none'`. Build the
178
- * event inside the lambda, never outside it.
179
- *
180
- * ## Every method must be total
181
- *
182
- * **None of the five methods may throw, and that includes {@link level}.** The
183
- * SDK calls them inline, on the codepath of the work it is reporting, and it
184
- * does not catch them: a `logger.error` that throws while reporting a failed
185
- * request turns that request's rejection into your logger's exception, and a
186
- * `level()` that throws breaks the call it was asked about even when nothing
187
- * else went wrong.
188
- *
189
- * That is deliberate. Swallowing would hide a logger that is broken in every
190
- * environment, and the SDK cannot tell a transport blip in your sink from a
191
- * bug in your implementation. So the contract is on this side of the seam:
192
- * catch inside your implementation, and never let an exception out. The
193
- * shipped pino implementations do exactly that.
194
- *
195
- * ```ts
196
- * error: (event) => {
197
- * try {
198
- * const e = event();
199
- * Sentry.captureMessage(e.msg, { extra: e });
200
- * } catch {
201
- * // never rethrow: the SDK is on the other side of this call
202
- * }
203
- * },
204
- * ```
205
- */
206
- interface Logger {
207
- /**
208
- * The most detailed level this logger wants. Consulted before **every** log
209
- * call, so keep it cheap and pure: return a captured constant or read a
210
- * plain field. Do not read an environment variable, hit storage, or call
211
- * out to a feature-flag service here.
212
- *
213
- * Returning `'none'` silences the SDK as completely as omitting the logger.
214
- *
215
- * **Must not throw.** It is consulted inside every SDK operation, so an
216
- * exception here fails the operation itself.
217
- */
218
- level(): LogLevel;
219
- /**
220
- * Fine-grained detail: request and response bodies, full URLs, headers,
221
- * operation parameters, hook transitions.
222
- *
223
- * **Unredacted.** This is the only level that may carry credentials or
224
- * personal data, and it always may. Its event is a {@link DebugEvent}, whose
225
- * fields accept arbitrary values for exactly that reason. Do not forward it
226
- * to a durable or third-party sink outside development and beta.
227
- *
228
- * **Must not throw**, here and on every method below.
229
- */
230
- debug(event: () => DebugEvent): void;
231
- /** Notable, expected events: a request completing, a flow advancing. */
232
- info(event: () => SafeEvent): void;
233
- /**
234
- * Recoverable trouble: a retried request, a renewed session, a poll tick
235
- * that failed while the last value still stands.
236
- *
237
- * Carries a {@link LogCause} when one was classified, the same as
238
- * {@link error} does. What separates the two levels is whether anything
239
- * actually broke, not how much is known about it.
240
- */
241
- warn(event: () => SafeEvent): void;
242
- /**
243
- * A failure. {@link SafeEvent.cause} carries what the SDK knows about it,
244
- * classified into {@link LogCause}, and is absent when the failure is not an
245
- * error the SDK caught - a flow reporting the step it stopped at, for
246
- * instance.
247
- *
248
- * Every part of the event is SDK-authored classification or server-authored
249
- * identifiers, so forwarding it as it stands is safe. `scope` says which
250
- * part of the SDK the line came from, which is what to route or filter on.
251
- */
252
- error(event: () => SafeEvent): void;
253
- }
254
- /**
255
- * A value the SDK is willing to put in a structured field above `'debug'`.
256
- *
257
- * Scalars only, and that is the redaction boundary made structural rather than
258
- * documentary. Every leak ADR-8 found was an *object* spread onto a line that
259
- * a host forwards to a tracker - an operation's params, a thrown wallet error,
260
- * a response body. None of them is assignable to this, so each is now a
261
- * compile error rather than a review catch.
262
- *
263
- * It does not stop a call site writing `{ token: accessToken }`, and it is not
264
- * meant to: a string is a string. What it stops is the mistake that actually
265
- * happened.
266
- */
267
- type LogValue = string | number | boolean | null;
268
- /**
269
- * Fields safe at every level: SDK-authored classification and server-minted
270
- * identifiers, constrained to {@link LogValue}.
271
- */
272
- type SafeFields = Readonly<Record<string, LogValue>>;
273
- /**
274
- * Fields for `'debug'` only: bodies, headers, full URLs, operation params,
275
- * raw thrown values. Arbitrary values, because that is the point of the level.
276
- *
277
- * The SDK's own implementations render these into a form that cannot fail to
278
- * serialize - a `bigint`, a cycle or a getter that throws must never turn a
279
- * log line into a second failure - but they are otherwise passed through.
280
- */
281
- type UnredactedFields = Readonly<Record<string, unknown>>;
282
- /**
283
- * One narrowing applied to a logger by {@link InternalLogger.child}.
284
- *
285
- * A union of single-key objects rather than a positional `string`, because the
286
- * three things the SDK narrows by are not the same kind of thing: a request id
287
- * correlates retries of one wire call, a flow name names an on-chain
288
- * procedure, a hook name names a React binding. Rendered into one `[SCOPE:x]`
289
- * prefix they were indistinguishable; as fields they must not be.
290
- *
291
- * `requestId` keeps its {@link RequestId} newtype rather than widening to
292
- * `string` at the seam.
293
- */
294
- type LogBinding = {
295
- readonly requestId: RequestId;
296
- } | {
297
- readonly flow: string;
298
- } | {
299
- readonly hook: string;
300
- } | {
301
- readonly op: string;
302
- };
303
- /**
304
- * Every {@link LogBinding} applied so far, merged. This is what reaches a
305
- * host, so a line from `prepareOndoSell` carries `flow: 'prepareSell'` as its
306
- * own key and is filterable without parsing anything.
307
- */
308
- type LogBindings = {
309
- readonly [K in LogBinding as keyof K]?: K[keyof K];
310
- };
311
- type BaseEvent = {
312
- /**
313
- * What happened, as a **constant string literal**.
314
- *
315
- * Never interpolated. A log aggregator groups by message, so a `msg` that
316
- * embeds a status, a count or a reason produces one group per distinct
317
- * value and is not groupable at all. Every varying value belongs in
318
- * `fields`, which is what a host filters and facets on.
319
- *
320
- * This is a convention, not a checked rule: deslop reasons about import
321
- * edges and cannot see a template literal, and the type-level approximations
322
- * catch only some interpolations. ADR-8 records why a partial guarantee was
323
- * refused here as elsewhere.
324
- */
325
- readonly msg: string;
326
- /**
327
- * Which part of the SDK reported this. Stamped by
328
- * {@link internalLogger}, never by a call site.
329
- */
330
- readonly scope: LogScope;
331
- /** Every {@link LogBinding} applied by {@link InternalLogger.child}. */
332
- readonly bindings: LogBindings;
333
- };
334
- /**
335
- * An event for `'info'`, `'warn'` and `'error'` - the levels a host may run in
336
- * production.
337
- *
338
- * Its fields are {@link SafeFields}, so nothing but a scalar can reach it.
339
- */
340
- type SafeEvent = BaseEvent & {
341
- readonly fields: SafeFields;
342
- /**
343
- * What the SDK knows about an accompanying failure, classified. Absent when
344
- * there is nothing to classify.
345
- */
346
- readonly cause?: LogCause;
347
- };
348
- /**
349
- * An event for `'debug'`, the unredacted level. Its fields accept anything.
350
- */
351
- type DebugEvent = BaseEvent & {
352
- readonly fields: UnredactedFields;
353
- };
354
- /**
355
- * How much the SDK may report, from silent to everything.
356
- *
357
- * Ordered: each level admits itself and everything before it, so `'info'`
358
- * shows errors, warnings and info but not debug. `'none'` admits nothing.
359
- *
360
- * `'debug'` is the unredacted level, and it is deliberately the bottom of the
361
- * ladder: the guarantee "`debug` is unredacted and every other level is not"
362
- * only closes if there is nothing below it. That is why the SDK keeps its own
363
- * five levels rather than adopting pino's seven, which put `trace` underneath.
364
- */
365
- type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug';
366
- /**
367
- * The redacted levels: the only ones to consider running in production.
368
- *
369
- * Every level except `'debug'`, which is unredacted by design. Used by the
370
- * shipped pino implementations to make a production `'debug'` logger
371
- * unrepresentable rather than merely discouraged - see
372
- * {@link PinoLoggerOptions}.
373
- *
374
- * The name marks which levels are *redacted*, not a verdict that running them
375
- * in production is safe. The SDK's advice is to leave {@link Config.logger}
376
- * undefined there; this type is what stops the partner who does not take it
377
- * from reaching the unredacted level as well.
378
- */
379
- type ProductionLogLevel = Exclude<LogLevel, 'debug'>;
380
- /**
381
- * How to build one of the SDK's pino-backed loggers.
382
- *
383
- * A union rather than `{ level, isDev }`, and that is the whole point:
384
- * `{ isDev: false, level: 'debug' }` does not typecheck, so a production
385
- * build cannot ship a logger that prints bearer tokens to a browser console.
386
- *
387
- * `isDev` does exactly one thing - decide whether `'debug'` is a legal level.
388
- * It changes no formatting: dev output and production output are the same
389
- * shape, so what you debug is what you ship. Pretty-printing is a pipe the
390
- * host owns (`node server.js | npx pino-pretty`), not a dependency the SDK
391
- * takes.
392
- */
393
- type PinoLoggerOptions = {
394
- readonly isDev: true;
395
- readonly level: LogLevel;
396
- } | {
397
- readonly isDev: false;
398
- readonly level: ProductionLogLevel;
399
- };
400
- /**
401
- * Which part of the SDK a line came from, carried as the `scope` field on
402
- * every event.
403
- *
404
- * It names the seam that **reported** the line, not the layer that raised what
405
- * it reports: an error from `OFFERS` surfaced by `useOffers` is reported on a
406
- * `HOOKS` line, because that is the hook telling you what it did with it. The
407
- * `OFFERS` line for the same error is emitted separately, by the namespace.
408
- *
409
- * A closed union rather than a free string so that `ONDO` and `Ondo` cannot
410
- * both appear, so that adding a namespace without giving it a scope fails to
411
- * compile, and so that a host can `switch` on it when routing. Anything finer
412
- * - an operation, a flow, a hook - is a {@link LogBinding} and appears as its
413
- * own field.
414
- */
415
- type LogScope = 'HTTP' | 'RPC' | 'AUTH' | 'OFFERS' | 'REQUIREMENTS' | 'WALLETS' | 'ERC20' | 'TOKEN_SALE' | 'SUPERSTATE' | 'ONDO' | 'CENTRIFUGE' | 'TOKENS' | 'SUPPORT' | 'HOOKS';
416
- /**
417
- * Correlates every line one logical request produces. The first attempt, each
418
- * retry, and the re-send after a session renewal all carry the same id, so a
419
- * failure can be read back to the request that caused it.
420
- */
421
- type RequestId = Newtype<string, 'RequestId'>;
422
- /**
423
- * The id frontline keys its own logs by, minted server-side and returned as
424
- * `event_id` on an error envelope. Quote it when raising a ticket with
425
- * CoinList support: it is what leads from a partner's log line to the request
426
- * as the backend saw it.
427
- *
428
- * A {@link Newtype} rather than a bare `string` because it sits next to
429
- * {@link RequestId} and frontline's `code` on the same cause, and the three
430
- * are not interchangeable: an id swapped for a code reads plausibly and points
431
- * a support engineer at nothing.
432
- */
433
- type FrontlineEventId = Newtype<string, 'FrontlineEventId'>;
434
- /**
435
- * What the SDK knows about a failure, classified.
436
- *
437
- * **Safe to forward as it stands.** Every arm is SDK-authored classification
438
- * or a server-authored identifier: no request or response body, no host-
439
- * supplied parameter, and no value read off a thrown error the SDK did not
440
- * author. There is nothing here to strip before handing it to an error
441
- * tracker, which is deliberate - a `LogCause` reaches {@link Logger.error},
442
- * the level a host actually runs in production, and a guarantee that depends
443
- * on the host remembering to strip a field is not a guarantee.
444
- *
445
- * It is the SDK's **only** structured classification of a thrown error, and it
446
- * reaches {@link Logger.warn} as well as {@link Logger.error}: a recoverable
447
- * failure is no less worth naming than a fatal one, and rendering it into a
448
- * string instead would have meant interpolating into `msg`.
449
- *
450
- * Bodies are a `'debug'`-only disclosure and stay on the `HTTP` lines, which
451
- * {@link RequestId} points at.
452
- *
453
- * The arms are the remedies, not the exception classes: a `validation` cause
454
- * means the backend sent something the SDK does not understand and is worth
455
- * reporting to CoinList, while an `invariant` cause means the SDK itself
456
- * computed something impossible and is worth reporting as an SDK bug. Reading
457
- * `type` should tell you who has to fix it.
458
- *
459
- * It carries no scope of its own. The {@link SafeEvent} it arrives on has one,
460
- * and a cause could only ever have repeated it: the scope is stamped by the
461
- * logger that *emits* the line, not by the layer that raised the error, so a
462
- * `validation` failure from `OFFERS` surfaced by `useOffers` would have been
463
- * tagged `HOOKS` on the hook's line. Forward the event, not the cause alone.
464
- */
465
- /**
466
- * Why an on-chain read failed, named after what a caller would do about it
467
- * rather than after the viem error class that reported it. See the `rpc` arm
468
- * of {@link LogCause}.
469
- */
470
- type RpcFailureReason = 'reverted' | 'node-rejected' | 'transport' | 'malformed-response' | 'unknown';
471
- type LogCause =
472
- /**
473
- * A request reached the backend and came back non-2xx.
474
- *
475
- * Deliberately carries no response body. `requestId` is how you get the
476
- * rest: the `HTTP` lines for the same request carry the method, the path,
477
- * the duration, every retry, and at `'debug'` the body itself. `code` and
478
- * `eventId` are frontline's own - quote `eventId` when raising a ticket with
479
- * CoinList support.
480
- */
481
- {
482
- type: 'http';
483
- requestId: RequestId | null;
484
- status: number;
485
- code: string | null;
486
- eventId: FrontlineEventId | null;
487
- }
488
- /**
489
- * The wire succeeded; the payload was not a shape the SDK can map.
490
- *
491
- * `message` is an SDK-authored template and may quote the single scalar that
492
- * failed - `Unsupported chain: "solana_mainnet"`, `expires_at: not a date
493
- * ("13/40/2026")`. That one value is the point of the arm; it is never a
494
- * body and never a whole field set.
495
- */
496
- | {
497
- type: 'validation';
498
- message: string;
499
- }
500
- /**
501
- * The SDK computed something impossible. An SDK bug - please report it.
502
- * `message` is an SDK-authored template, like `validation`'s.
503
- */
504
- | {
505
- type: 'invariant';
506
- message: string;
507
- }
508
- /**
509
- * Every operand was well-formed and the arithmetic on them still had no
510
- * answer: a division by zero, a result outside the range its type can hold.
511
- * `message` is an SDK-authored template, like `validation`'s.
512
- *
513
- * Separate from `invariant` because the remedy differs. An `invariant` says
514
- * the SDK computed something impossible and is a bug to report against the
515
- * SDK; a `math` says the operation was well-posed and the operands, which
516
- * came off the wire, admit no result - so it points at the response the same
517
- * way `validation` does, one step later.
518
- */
519
- | {
520
- type: 'math';
521
- message: string;
522
- }
523
- /** An API-backed call was made without a logged-in user. */
524
- | {
525
- type: 'not-authenticated';
526
- }
527
- /** A code path the SDK has not shipped yet. */
528
- | {
529
- type: 'not-implemented';
530
- }
531
- /**
532
- * The user's wallet, or the chain, refused.
533
- *
534
- * {@link RedactedWalletError} rather than the full `WalletError`: its
535
- * `unknown` arm arrives with its `cause` dropped, that field holding the raw
536
- * wallet-library error whose message and metadata carry the transaction's
537
- * `from`, `to`, `value` and calldata. It is still on the flow's own returned
538
- * result, and on the `'debug'` line the flow seam emits beside this one.
539
- *
540
- * A type rather than a scrub applied at the call site, so an arm that grew a
541
- * raw field would fail the build.
542
- */
543
- | {
544
- type: 'wallet';
545
- error: RedactedWalletError;
546
- }
547
- /**
548
- * An on-chain read did not answer. `reason` names the remedy, not the viem
549
- * class that carried it:
550
- *
551
- * - `reverted` - the contract refused the call. Check the arguments, or the
552
- * contract's own state (a stopped swap reverts its `preview`).
553
- * - `node-rejected` - the node reached the contract and declined. Usually a
554
- * malformed request, a rate limit, or a method the node does not serve.
555
- * Also where a host-supplied `Transport` throwing something viem cannot
556
- * read a code off lands: `buildRequest` wraps it in `UnknownRpcError`.
557
- * - `transport` - the node was not reached at all. Retry, or fail over.
558
- * A dropped `webSocket()` socket included.
559
- * - `malformed-response` - the call returned something the ABI cannot
560
- * decode, which in practice means the wrong address or a stale ABI.
561
- * - `unknown` - anything else. Rare, since viem wraps most of what a read
562
- * can throw into one of the classes the arms above name.
563
- *
564
- * Decided by `instanceof` alone. Nothing is read off the thrown error - not
565
- * its `name`, not its `message`, not a revert reason - because a viem
566
- * message embeds the calldata, the contract address and the caller, and
567
- * `name` is a writable property a host-supplied transport could set to
568
- * anything. All of that is on the paired `'debug'` line.
569
- */
570
- | {
571
- type: 'rpc';
572
- reason: RpcFailureReason;
573
- }
574
- /**
575
- * Something the SDK does not recognise - usually a host-supplied lambda
576
- * (`getAccessToken`, an {@link EvmWallet} method) throwing, or a
577
- * network-level `fetch` failure.
578
- *
579
- * `name` is the error's class name and nothing else. The message and the
580
- * thrown value itself are host-authored, so they are a `'debug'` disclosure:
581
- * the paired debug line renders them in full.
582
- */
583
- | {
584
- type: 'generic-error';
585
- name: string;
586
- };
587
-
588
- /**
589
- * The exhaustive chain set: a new {@link EthereumChain} is a compile error
590
- * here until it is listed, which is what keeps the constructor total.
591
- */
592
- declare const ETHEREUM_CHAINS: Record<EthereumChain, true>;
593
- type EthereumChain = 'ethereum_mainnet' | 'ethereum_sepolia' | 'base_mainnet' | 'base_sepolia';
594
- /**
595
- * Validates that a raw backend string names a chain the SDK supports.
596
- *
597
- * @throws ValidationError on anything else. Passing an unknown chain through
598
- * would let downstream EIP-155 lookups blow up far from the response that
599
- * caused it.
600
- */
601
- declare const EthereumChain: (value: string) => EthereumChain;
602
- /**
603
- * The exhaustive chain set: a new {@link SolanaChain} is a compile error
604
- * here until it is listed, which is what keeps the constructor total.
605
- */
606
- declare const SOLANA_CHAINS: Record<SolanaChain, true>;
607
- type SolanaChain = 'solana_mainnet' | 'solana_devnet';
608
- /**
609
- * Validates that a raw backend string names a chain the SDK supports.
610
- *
611
- * @throws ValidationError on anything else. Passing an unknown chain through
612
- * would let downstream EIP-155 lookups blow up far from the response that
613
- * caused it.
614
- */
615
- declare const SolanaChain: (value: string) => SolanaChain;
616
- /**
617
- * {@link Chain}'s check without the throw, for a mapper over a list that drops
618
- * the entries it cannot name rather than rejecting the whole list. Frontline's
619
- * chain registry may carry chains this SDK does not model yet.
620
- */
621
- declare const isChain: (value: string) => value is Chain;
622
- type Chain = EthereumChain | SolanaChain;
623
- declare const Chain: (value: string) => Chain;
624
- /**
625
- * Protocol a wallet binding is scoped to. EVM-only for now: an EVM address
626
- * binds once per option regardless of which EVM chain proved ownership.
627
- * Frontline's enum also has `:solana`, but we don't handle Solana bindings yet,
628
- * so this stays `'ethereum'` until Solana support lands.
629
- */
630
- type WalletProtocol = 'ethereum';
631
- /**
632
- * EVM addresses keep a `0x${string}` base so they stay assignable to the
633
- * `0x${string}` shapes that on-chain libraries (viem/wagmi) expect. We only
634
- * drop the runtime `0x` narrowing: values are trusted at the boundary and
635
- * branded via the constructor.
636
- */
637
- type EvmWalletAddress = Newtype<`0x${string}`, 'EvmWalletAddress'>;
638
- declare const EvmWalletAddress: (value: string) => EvmWalletAddress;
639
- type EvmContractAddress = Newtype<`0x${string}`, 'EvmContractAddress'>;
640
- declare const EvmContractAddress: (value: string) => EvmContractAddress;
641
- /**
642
- * What uniquely identifies a token: the chain it is deployed on plus its
643
- * contract address. Never a symbol, which can collide across issuers.
644
- */
645
- type TokenIdentifier = {
646
- /** The chain the token contract is deployed on. */
647
- chain: EthereumChain;
648
- /**
649
- * The token's contract address, in any casing — consumers that need the
650
- * EIP-55 form (e.g. the token registry routes) checksum it themselves.
651
- */
652
- address: EvmContractAddress;
653
- };
654
- type HexEncodedTransactionData = Newtype<`0x${string}`, 'HexEncodedTransactionData'>;
655
- declare const HexEncodedTransactionData: (value: string) => HexEncodedTransactionData;
656
- /**
657
- * A transaction the backend has already encoded for us — the caller only
658
- * broadcasts it. Used by the flows that hand a wallet a ready-made `to`/`data`
659
- * pair (allow-listing a wallet, an Ondo swap) rather than encoding a contract
660
- * call themselves.
661
- */
662
- type Tx = {
663
- to: EvmContractAddress;
664
- data: HexEncodedTransactionData;
665
- };
666
- /**
667
- * The largest exponent whose power of ten still fits a uint256: 10^77 fits,
668
- * 10^78 does not.
669
- *
670
- * The bound is arithmetic rather than a token standard's. ERC-20 reports
671
- * `decimals()` as a `uint8`, so 255 is what a contract *can* say, but every
672
- * {@link AssetDecimals} in this codebase is paired with a {@link Uint256} raw
673
- * by construction, and scaling by anything past this leaves that pairing
674
- * unrepresentable. A value between 78 and 255 would therefore pass a
675
- * standard-faithful check and then break the first multiplication it reached.
676
- */
677
- declare const MAX_ASSET_DECIMALS = 77;
678
- /**
679
- * How many decimal places one whole token divides into.
680
- *
681
- * Validated, unlike its neighbours here — {@link Uint256} is a bare `bigint`
682
- * with a separate {@link assertUint256} guard, and {@link DecimalString} casts
683
- * unchecked. The asymmetry is deliberate and follows the value's provenance:
684
- * an `AssetDecimals` used to come only from literals and the token registry,
685
- * but backends now publish exponents of their own (`asset_decimals` on an Ondo
686
- * quote, both scales on a built swap), and those feed `10n ** BigInt(d)`
687
- * during render. Guarding at construction is what keeps a fractional or
688
- * unbounded exponent from surfacing as a `RangeError` mid-render — or, at
689
- * 10^200, as a hung tab — instead of as the failed state the screen has.
690
- *
691
- * See docs/ADR-7-VALIDATED-NEWTYPES.md.
692
- *
693
- * @throws ValidationError on a non-integer, a negative, or anything above
694
- * {@link MAX_ASSET_DECIMALS}.
695
- */
696
- type AssetDecimals = Newtype<number, 'AssetDecimals'>;
697
- declare const AssetDecimals: (value: number) => AssetDecimals;
698
- declare const STABLE_DECIMALS: AssetDecimals;
699
- /**
700
- * A non-negative decimal number the backend sent as a string, kept unscaled.
701
- *
702
- * Reach for it when a response gives you a number but not the decimals to
703
- * scale it by, or gives you one it has already applied. Inventing an exponent
704
- * for either is how a display ends up orders of magnitude out.
705
- *
706
- * Contrast {@link BlockchainAmount}, which pairs a raw uint256 with the
707
- * decimals it is denominated in and so is only constructible when you know
708
- * both. Arithmetic on a `DecimalString` needs a decimal library we
709
- * deliberately do not ship.
710
- */
711
- type DecimalString = Newtype<string, 'DecimalString'>;
712
- declare const DecimalString: (value: string) => DecimalString;
713
- declare const MAX_UINT_256: bigint;
714
- /**
715
- * A non-negative integer within uint256 bounds. Kept unbranded (a plain
716
- * `bigint`) so raw on-chain amounts flow in without ceremony; bounds are
717
- * enforced where it matters (see {@link combineAmounts}).
718
- */
719
- type Uint256 = bigint;
720
- /**
721
- * Asserts a computed bigint falls within uint256 bounds. Use at on-chain
722
- * arithmetic boundaries (bps math, price computation) where the SDK's own
723
- * arithmetic could underflow below zero or overflow above 2^256-1.
724
- *
725
- * Throws {@link InvariantError}, because reaching it means the SDK computed
726
- * something no chain could represent. **For a value that came off the wire,
727
- * use {@link parseUint256} instead**: the backend sending an unrepresentable
728
- * number is a {@link ValidationError}, and the two have different remedies.
729
- */
730
- declare const assertUint256: (value: bigint) => Uint256;
731
- /**
732
- * {@link assertUint256} at a wire boundary: the same bounds check, reported as
733
- * a {@link ValidationError} against the named field, because a value out of
734
- * range here is the backend's, not the SDK's.
735
- *
736
- * `label` names the field the way a DTO mapper's other failures do, so a log
737
- * line says which one - `SwapPreview.pay_input_amount`, not `a number`.
738
- */
739
- declare const parseUint256: (value: bigint, label: string) => Uint256;
740
- type BlockchainAmount = Newtype<{
741
- raw: Uint256;
742
- decimals: AssetDecimals;
743
- }, 'BlockchainAmount'>;
744
- /**
745
- * Constructs a {@link BlockchainAmount} and exposes arithmetic helpers.
746
- * TypeScript has no operator overloading, so use `BlockchainAmount.add(a, b)`
747
- * instead of `+`/`-`/`*`/`/` on the objects directly.
748
- */
749
- declare const BlockchainAmount: ((value: {
750
- raw: Uint256;
751
- decimals: AssetDecimals;
752
- }) => BlockchainAmount) & {
753
- add: (a: BlockchainAmount, b: BlockchainAmount) => BlockchainAmount;
754
- sub: (a: BlockchainAmount, b: BlockchainAmount) => BlockchainAmount;
755
- mul: typeof multiplyAmounts;
756
- div: typeof divideAmounts;
757
- };
758
- /**
759
- * `a * b`, denominated in `a`'s decimals - a price times a quantity, an amount
760
- * times a rate.
761
- *
762
- * The exact inverse of {@link divideAmounts}, and it reads the same way round:
763
- * the answer stays in `a`'s scale and `b`'s divides back out, so the two
764
- * compose - `mul(div(a, b), b)` is `a` again, short only what truncation took.
765
- * That is what makes `price x quantity` land in the currency the price was
766
- * quoted in rather than at some product of two exponents no token uses.
767
- *
768
- * The multiplication happens *before* the division by `10^b.decimals`, so the
769
- * full precision of both operands survives into the one rounding at the end.
770
- * Like `div` it truncates towards zero on both signs, which is the safe
771
- * direction for money: a total is never inflated past what the parts hold.
772
- *
773
- * Total - unlike `div`, there is nothing here to reject. The scale it divides
774
- * by is a power of ten, never zero, and a product is not bounds-checked for
775
- * the same reason a quotient is not: whether one past uint256 is a corrupt
776
- * response or an expected magnitude belongs to the caller.
777
- */
778
- declare function multiplyAmounts(a: BlockchainAmount, b: BlockchainAmount): BlockchainAmount;
779
- /**
780
- * `a / b`, denominated in `a`'s decimals - a price, a ratio, a rate.
781
- *
782
- * Unlike {@link combineAmounts}, the two operands may be at different scales,
783
- * and usually are: dividing dollars by shares is the point of the operation,
784
- * and the two tokens rarely share an exponent. `b`'s scale divides back out -
785
- * the numerator is scaled by `10^b.decimals` *before* the division, so nothing
786
- * is lost to integer truncation early and the quotient lands in `a`'s scale,
787
- * which is the one the amounts it is rendered beside are in.
788
- *
789
- * Truncates towards zero on both signs, which is what BigInt division already
790
- * does and the safe direction for money: the total a price implies never
791
- * exceeds, in magnitude, the amount that actually moved.
792
- *
793
- * A zero divisor is the only rejection. The quotient is deliberately *not*
794
- * bounds-checked the way {@link combineAmounts} checks a sum: scaling the
795
- * numerator carries even legal pairs past uint256 (a maximal amount over a
796
- * single base unit), and whether that reads as a corrupt response or an
797
- * expected magnitude is the caller's to judge - see `computeOndoBuyPrice` and
798
- * `computeOndoSellPrice`, which bounds-check the price they build out of this.
799
- *
800
- * @throws MathError when `b` is zero. `add` and `sub` throw a bare `Error`
801
- * because a scale mismatch is a programming error caught in review; a zero
802
- * divisor arrives from a server response and is divided by during render, so
803
- * it is a named failure a screen can catch and map to a failed state.
804
- */
805
- declare function divideAmounts(a: BlockchainAmount, b: BlockchainAmount): BlockchainAmount;
806
- type AssetSymbol = Newtype<string, 'AssetSymbol'>;
807
- declare const AssetSymbol: (value: string) => AssetSymbol;
808
- /**
809
- * A stablecoin symbol is an {@link AssetSymbol} narrowed to the coins we
810
- * support. It shares the `AssetSymbol` brand so it stays assignable to it.
811
- */
812
- type StablecoinSymbol = Newtype<'USDC' | 'USDT', 'AssetSymbol'>;
813
- declare const StablecoinSymbol: (value: "USDC" | "USDT") => StablecoinSymbol;
814
- type KnownAssetSymbol = StablecoinSymbol;
815
- declare const KnownAssetSymbol: (value: "USDC" | "USDT") => StablecoinSymbol;
816
- type Erc20Asset = {
817
- name: string;
818
- symbol: AssetSymbol;
819
- decimals: AssetDecimals;
820
- };
821
- type Bps = Newtype<bigint, 'Bps'>;
822
- declare const Bps: (value: bigint) => Bps;
823
-
824
- type GetTokenAllowanceParams = {
825
- tokenAddress: EvmContractAddress;
826
- owner: EvmWalletAddress;
827
- spender: EvmContractAddress;
828
- chain: EthereumChain;
829
- };
830
- type GetTokenBalanceParams = {
831
- tokenAddress: EvmContractAddress;
832
- owner: EvmWalletAddress;
833
- chain: EthereumChain;
834
- };
835
-
836
- /**
837
- * OAuth 2.0 token response (RFC 6749 §5.1).
838
- * Maps to OpenAPI schema OauthToken.
839
- */
840
- type OAuthSessionDto = {
841
- access_token: string;
842
- expires_in: number;
843
- refresh_token?: string;
844
- };
845
-
846
- type ClientCredentialsOAuth = Newtype<OAuthAccessToken, 'ClientCredentialsOAuth'>;
847
- declare const ClientCredentialsOAuth: (value: OAuthAccessToken) => ClientCredentialsOAuth;
848
- type OAuthAccessToken = {
849
- value: string;
850
- expiresAt: Date;
851
- };
852
- type OAuthRefreshToken = Newtype<string, 'OAuthRefreshToken'>;
853
- declare const OAuthRefreshToken: (value: string) => OAuthRefreshToken;
854
- type OAuthSession = {
855
- accessToken: OAuthAccessToken;
856
- refreshToken?: OAuthRefreshToken;
857
- };
858
- declare const OAuthSession: {
859
- fromDto: (dto: OAuthSessionDto) => OAuthSession;
860
- };
861
-
862
- type HttpRequestAttributes = {
863
- /**
864
- * Correlates the log lines of one logical request. Minted by
865
- * {@link HttpClient} on the first attempt and carried onto every retry and
866
- * post-renewal re-send by {@link concat}, which is what lets a reader tell
867
- * three attempts of one request from three separate requests.
868
- */
869
- requestId?: RequestId;
870
- protected?: boolean;
871
- userAgent?: boolean;
872
- idempotencyKey?: boolean;
873
- /** Zero-based attempt index: 0 = first request, 1 = first retry, etc. */
874
- retryAttempt?: number;
875
- renewAttempted?: boolean;
876
- /**
877
- * `false` opts a request out of `requestRetryMiddleware`. For exchanges
878
- * that must never be replayed: a refresh token is single-use, so re-sending
879
- * one whose first attempt reached the server presents a token that has
880
- * already been rotated away.
881
- */
882
- retryable?: boolean;
883
- /**
884
- * The user access token `attachSessionMiddleware` put on this request, so
885
- * that a 401 can say *which* token was refused. Absent when the request
886
- * went out with no user token.
887
- */
888
- sentWith?: OAuthAccessToken;
889
- clientCredentials?: ClientCredentialsOAuth;
890
- };
891
-
892
- /**
893
- * The value types a query-string parameter may take.
894
- *
895
- * Declared here rather than beside the HTTP client because domain models build
896
- * query parameters too: `ParticipationsPaginationParams.toQueryParams` returns
897
- * a `Record<string, QueryParamValue>`, and a domain model must not import
898
- * `@/universal/api/**`.
899
- */
900
- type QueryParamValue = string | number | boolean | null | undefined;
901
- type QueryParamValues = QueryParamValue | QueryParamValue[];
902
-
903
- type HttpRequest<TBody = unknown> = {
904
- method: 'GET';
905
- url: string;
906
- queryParams?: Record<string, QueryParamValues>;
907
- headers?: Record<string, string>;
908
- attributes?: HttpRequestAttributes;
909
- redirect?: RequestRedirect;
910
- } | {
911
- method: 'POST';
912
- url: string;
913
- queryParams?: Record<string, QueryParamValues>;
914
- headers?: Record<string, string>;
915
- body: TBody;
916
- attributes?: HttpRequestAttributes;
917
- redirect?: RequestRedirect;
918
- } | {
919
- method: 'DELETE';
920
- url: string;
921
- queryParams?: Record<string, QueryParamValues>;
922
- headers?: Record<string, string>;
923
- attributes?: HttpRequestAttributes;
924
- redirect?: RequestRedirect;
925
- };
926
- type HttpResponse<TBody = unknown> = {
927
- status: number;
928
- headers?: Record<string, string>;
929
- body: TBody | null;
930
- /**
931
- * The id of the request that produced this response, stamped by
932
- * {@link HttpClient} so that whoever turns a non-2xx into an
933
- * {@link HttpError} can carry it without threading the request alongside.
934
- * Absent when the response did not come from an `HttpClient`.
935
- */
936
- requestId?: RequestId;
937
- };
938
- declare class HttpError<TBody = unknown> extends Error {
939
- readonly response: HttpResponse<TBody>;
940
- constructor(response: HttpResponse<TBody>);
941
- /**
942
- * Correlates this failure with the `[HTTP]` log lines for the same request,
943
- * which carry the method, the URL, the duration and every retry. `null` when
944
- * the response did not come from an {@link HttpClient}.
945
- *
946
- * Worth quoting in a bug report: it is what makes a log excerpt readable.
947
- */
948
- get requestId(): RequestId | null;
949
- }
950
- /**
951
- * The machine-readable `code` frontline attaches to an error, or `null` for
952
- * anything else - a non-HTTP failure, or an error body that carries only a
953
- * message.
954
- *
955
- * Frontline answers a failure with `{ type, message, code?, errors?,
956
- * event_id? }`, and `code` is the only part of it meant to be branched on:
957
- * `message` is prose that may be reworded, and `type` distinguishes
958
- * `invalid_request_error` from `api_error` without saying which one.
959
- *
960
- * Reach for this only where a code has a distinct remedy the user can act on.
961
- * Mapping the whole vocabulary would couple the SDK to strings frontline does
962
- * not version; falling back to a generic failure is the right default.
963
- */
964
- declare function apiErrorCode(error: unknown): string | null;
965
-
966
- /**
967
- * Structural interface satisfied by both {@link AuthenticatedApiClient} and
968
- * {@link ApiClient}. Used by the shared frontline API functions so they can
969
- * be called from either the client or server without any browser dependencies.
970
- */
971
- interface Sender {
972
- send<T>(request: HttpRequest): Promise<T>;
973
- }
974
-
975
- /**
976
- * Where the SDK sends its on-chain reads, per chain.
977
- *
978
- * Leave it undefined and reads go through CoinList's authenticated JSON-RPC
979
- * proxy (`POST /v1/chains/{chain}/rpc`), which needs no setup but does need a
980
- * logged-in user - the proxy is OAuth-gated, so a read on a chain the SDK is
981
- * proxying fails with its `401`, surfaced as the viem error wrapping it. A
982
- * chain you name here is read straight from your own node instead, and needs
983
- * no CoinList session at all.
984
- *
985
- * Each entry is either:
986
- *
987
- * - an RPC URL, which the SDK wraps in viem's `http()` transport, or
988
- * - a viem {@link Transport} used as it stands - `fallback([...])`,
989
- * `webSocket()`, or your app's own.
990
- *
991
- * Chains you leave out fall back to the proxy individually, so overriding
992
- * mainnet does not opt Sepolia out. The SDK always constructs the viem
993
- * `PublicClient` itself, so the chain definition, batching and retry policy
994
- * stay the SDK's regardless of the transport you supply.
995
- *
996
- * @example
997
- * ```ts
998
- * createCoinListClient({
999
- * clientId,
1000
- * redirectUri,
1001
- * rpc: {
1002
- * ethereum_mainnet: 'https://eth-mainnet.g.alchemy.com/v2/KEY',
1003
- * ethereum_sepolia: fallback([http(primary), http(backup)]),
1004
- * // base_* unset -> proxied through CoinList
1005
- * },
1006
- * });
1007
- * ```
1008
- */
1009
- type RpcConfig = Partial<Record<EthereumChain, string | Transport>>;
1010
- interface Config {
1011
- /** OAuth2 public identifier. */
1012
- readonly clientId: ClientId;
1013
- /**
1014
- * OAuth2 redirect URI. Recommended to point to a frontend page where
1015
- * {@link CoinListClient#completeOauth} can be called to complete the PKCE
1016
- * flow on the client side.
1017
- */
1018
- readonly redirectUri: RedirectUri;
1019
- /**
1020
- * Recommended to leave undefined. Used to change the CoinList environment;
1021
- * default is production.
1022
- */
1023
- readonly baseUrl?: string;
1024
- /**
1025
- * Recommended to leave undefined. Overrides the base URL of the public
1026
- * token registry backing `coinlist.tokens`; default is the production
1027
- * registry.
1028
- */
1029
- readonly tokensBaseUrl?: string;
1030
- /**
1031
- * Where the SDK reports what it is doing. **Omit it and the SDK logs nothing
1032
- * at all** - no `console` fallback, at any level, on any codepath. Supply
1033
- * one and every request, every classified failure and every hook state
1034
- * transition is reported at the level your logger asks for.
1035
- *
1036
- * Absent, the SDK says nothing at all - there is no fallback to `console`,
1037
- * at any level, on any codepath.
1038
- *
1039
- * **Running the SDK's logging in production is not advised.** The safest
1040
- * posture is to leave this undefined outside development, staging and
1041
- * incident reproduction: a seam that emits nothing cannot disclose anything,
1042
- * and that property does not depend on the SDK continuing to get redaction
1043
- * right.
1044
- *
1045
- * If you do run one there, run it at `'info'` or above and know what that
1046
- * does and does not buy you. Those levels are **redacted by construction**:
1047
- * they carry only SDK-authored classification and server-authored
1048
- * identifiers, and the type system holds that line rather than a convention -
1049
- * an event at those levels accepts scalar fields only, so a body, a DTO or
1050
- * an operation's parameters cannot be put on one. What the SDK does **not**
1051
- * give you is a warranty that the result is safe for your environment. The
1052
- * mechanism is checkable and stated; the conclusion depends on your sink,
1053
- * your retention and your threat model, and it is yours to draw.
1054
- *
1055
- * **`'debug'` is not.** It reports request and response bodies, full URLs,
1056
- * headers and operation parameters verbatim - bearer tokens, KYC answers,
1057
- * tax-document fields, wallet signatures - and **the SDK does not redact**.
1058
- * Run it on a developer's machine, in tests, and in beta or staging
1059
- * environments where the data flowing through is not real customer data.
1060
- * The shipped implementations make that structural: built with
1061
- * `isDev: false`, `'debug'` does not typecheck. Either way, filtering,
1062
- * redaction and retention at your sink are yours, not the SDK's.
1063
- *
1064
- * Every method you implement here **must be total**: the SDK calls them on
1065
- * the codepath of the work they report and does not catch them, so a logger
1066
- * that throws fails the operation it was describing.
1067
- *
1068
- * See {@link Logger} for the full contract, and {@link pinoClientLogger} or
1069
- * {@link pinoServerLogger} for a ready-made implementation over pino.
1070
- */
1071
- readonly logger?: Logger;
1072
- /**
1073
- * Where on-chain reads go. Omit it and they are proxied through CoinList.
1074
- * See {@link RpcConfig}.
1075
- */
1076
- readonly rpc?: RpcConfig;
1077
- /**
1078
- * Called when the SDK has **confirmed** that the user's CoinList session is
1079
- * gone - its refresh token expired or was revoked - so you can clear your
1080
- * own state and show a sign-in entry point.
1081
- *
1082
- * Confirmed, because the backend answers "rotated a moment ago by a
1083
- * concurrent request" and "dead" identically. A single rejection is only a
1084
- * suspicion: the SDK acts on it only once the same session is rejected again
1085
- * after a settle window, so a lost refresh race never signs a user out.
1086
- *
1087
- * Each environment reports what it confirmed itself, so it fires in the
1088
- * one that drove the confirmation:
1089
- *
1090
- * - **`CoinListClient`**: fires when the SDK moves from `'logged-in'` to
1091
- * `'logged-out'` because your `getAccessToken` answered `null` (or the
1092
- * very token the API just refused) twice, a second apart.
1093
- * - **`CoinListServer`**: fires when the same process sees a refresh token
1094
- * rejected twice, 5 to 60 seconds apart, or an expired session that
1095
- * carries no refresh token. The SDK clears the session from your
1096
- * `SessionStore` just before. The browser's confirmation, through your
1097
- * `getAccessToken` endpoint, comes a second after the first rejection, so
1098
- * it does not reach this verdict: when the browser drives renewal, expect
1099
- * the `CoinListClient` callback, and this one only if a later request
1100
- * presents the dead session 5 to 60 seconds on.
1101
- *
1102
- * It never fires on `auth.logout()`, on a 5xx, a timeout or a network
1103
- * failure - those mean the SDK could not find out, not that the session
1104
- * ended. Per environment it fires at most once per session, within a
1105
- * 60-second memory: the server remembers a verdict for 60 seconds per
1106
- * process (per JavaScript module instance, so Next.js middleware and route
1107
- * handlers count separately). The same dead session presented again after
1108
- * that, or to another instance, can be reported again, so make your handler
1109
- * idempotent.
1110
- *
1111
- * It is called on the next microtask and not awaited. A rejection is
1112
- * logged and dropped, so it cannot fail or delay the request that
1113
- * discovered the expiry. A synchronous handler is written `async () => {}`.
1114
- */
1115
- readonly onSessionExpired?: () => Promise<void>;
1116
- }
1117
-
1118
- /**
1119
- * Resolves a chain to the viem `PublicClient` the SDK reads it through.
1120
- *
1121
- * One function rather than a client per read, because the client is where the
1122
- * batching lives: viem's multicall scheduler is keyed on the client's `uid`,
1123
- * so two reads only ever share an `eth_call` if they share a client. Hence the
1124
- * memoisation - it is correctness for batching, not a performance tweak.
1125
- */
1126
- type PublicClients = (chain: EthereumChain) => PublicClient;
1127
-
1128
- interface UniversalNamespaceContext {
1129
- readonly api: Sender;
1130
- /**
1131
- * The viem `PublicClient` for a chain, over whichever transport that chain
1132
- * resolved to - the host's own node, or CoinList's proxy.
1133
- *
1134
- * A factory rather than a client, because a namespace serves every chain and
1135
- * only the call knows which. Built once per client instance so that
1136
- * concurrent reads share a batch; see `publicClients`.
1137
- */
1138
- readonly rpc: PublicClients;
1139
- /**
1140
- * The host's logger, or `null` when they supplied none.
1141
- *
1142
- * Deliberately the raw port rather than a pre-scoped {@link InternalLogger}:
1143
- * one context serves every namespace, and each namespace owns its own scope.
1144
- * A namespace turns it into something usable in its constructor, with
1145
- * `internalLogger(ctx.logger, 'OFFERS')`.
1146
- */
1147
- readonly logger: Logger | null;
1148
- ensureUserAuthenticated(): Promise<void>;
1149
- }
1150
-
1151
- /**
1152
- * Generic ERC-20 reads shared across on-chain flows (swap, token sale): the
1153
- * allowance an owner has granted a spender, and the raw token balance an owner
1154
- * holds. These are plain token reads, not tied to any single product flow.
1155
- *
1156
- * Read from the chain rather than from a CoinList endpoint. By default that
1157
- * goes through CoinList's authenticated JSON-RPC proxy, so a logged-out caller
1158
- * gets the proxy's `401` - surfaced as a viem error wrapping the SDK's
1159
- * `HttpError`, not as `NotAuthenticatedError`, since viem re-wraps whatever a
1160
- * `Transport` throws. Point `Config.rpc` at your own node for this chain and no
1161
- * CoinList session is involved at all. See {@link RpcConfig}.
1162
- */
1163
- interface Erc20Namespace {
1164
- /**
1165
- * Reads the ERC-20 allowance an `owner` has granted a `spender`, as a raw
1166
- * on-chain integer.
1167
- */
1168
- getAllowance(params: GetTokenAllowanceParams): Promise<Uint256>;
1169
- /**
1170
- * Reads the raw ERC-20 balance an `owner` holds of a token.
1171
- */
1172
- getBalance(params: GetTokenBalanceParams): Promise<Uint256>;
1173
- }
1174
- declare class Erc20NamespaceImpl implements Erc20Namespace {
1175
- private readonly ctx;
1176
- private readonly log;
1177
- constructor(ctx: UniversalNamespaceContext);
1178
- getAllowance(params: GetTokenAllowanceParams): Promise<Uint256>;
1179
- getBalance(params: GetTokenBalanceParams): Promise<Uint256>;
1180
- }
1181
-
1182
- type GetCentrifugeVaultStatusParams = {
1183
- /** Share token symbol of the vault, e.g. `deJTRSY`. */
1184
- symbol: AssetSymbol;
1185
- /**
1186
- * The chain whose proxy answers. Only chains this offer has a proxy on
1187
- * are accepted; the offer's `vault_contracts` lists them.
1188
- */
1189
- chain: EthereumChain;
1190
- };
1191
- type GetCentrifugeVaultQuoteParams = GetCentrifugeVaultStatusParams & {
1192
- /**
1193
- * Amount to price, in the base units of the funding token. Must be greater
1194
- * than zero. No fee is deducted; this product charges none.
1195
- *
1196
- * Sized by `amount` alone: the quote is a free read of one spend, not a
1197
- * dollar figure converted later.
1198
- */
1199
- amount: BlockchainAmount;
1200
- };
1201
- /**
1202
- * One wallet on one vault: what every position read and every claim is keyed
1203
- * by. There is no order id - a wallet has one pooled position per vault per
1204
- * direction.
1205
- */
1206
- type CentrifugeWalletParams = GetCentrifugeVaultStatusParams & {
1207
- /**
1208
- * The wallet whose position is read, or claimed for. A claim must then be
1209
- * broadcast from this same wallet: the proxy credits the sender.
1210
- */
1211
- walletAddress: EvmWalletAddress;
1212
- };
1213
- /**
1214
- * What `POST /v1/centrifuge/vault/invest` is asked for: the wallet that will
1215
- * broadcast the request and fund it, plus the deposit.
1216
- *
1217
- * Built once, when the user confirms an amount. Broadcasting the result places
1218
- * a request; it does not buy shares.
1219
- */
1220
- type BuildCentrifugeVaultBuyParams = CentrifugeWalletParams & {
1221
- /** How much of the funding token to deposit, in its base units. */
1222
- amount: BlockchainAmount;
1223
- };
1224
-
1225
- /**
1226
- * The logging surface SDK code uses. Never exported to hosts: they implement
1227
- * {@link Logger}, which is deliberately smaller.
1228
- */
1229
- type InternalLogger = {
1230
- /**
1231
- * A logger narrowed by one more {@link LogBinding}, which every line it
1232
- * emits carries as its own field.
1233
- */
1234
- child(binding: LogBinding): InternalLogger;
1235
- /**
1236
- * The unredacted level. Request and response bodies, full URLs, headers,
1237
- * operation params and raw thrown errors belong here and **only** here.
1238
- */
1239
- debug(event: () => InternalDebugEvent): void;
1240
- info(event: () => InternalSafeEvent): void;
1241
- warn(event: () => InternalSafeEvent): void;
1242
- /**
1243
- * Reports a failure whose cause is already known, or has none. Prefer
1244
- * {@link failure}, which classifies a thrown error for you.
1245
- */
1246
- error(event: () => InternalSafeEvent): void;
1247
- /**
1248
- * Reports a thrown error, classifying it into a {@link LogCause}. Prefer
1249
- * this over `error` at a `catch`: classification only happens when the level
1250
- * admits it.
1251
- *
1252
- * The `error` line names the error's class but never its message, since an
1253
- * error the SDK did not author may say anything at all. The verbatim
1254
- * rendering goes onto a paired `debug` line instead.
1255
- *
1256
- * For a failure the SDK recovers from, use {@link warning} instead. An
1257
- * `error` line a host cannot act on is worse than no line at all: it trains
1258
- * them to ignore the ones that matter.
1259
- */
1260
- failure(event: () => InternalSafeEvent, error: unknown): void;
1261
- /**
1262
- * {@link failure} for trouble that did not break anything: a poll tick that
1263
- * failed while the last value still stands, a retried request.
1264
- *
1265
- * Carries the classified {@link LogCause} exactly as `failure` does. The two
1266
- * differ in level and in nothing else, because what separates them is
1267
- * whether anything actually broke - not how much is known about it.
1268
- */
1269
- warning(event: () => InternalSafeEvent, error: unknown): void;
1270
- /**
1271
- * Runs one namespace operation with logging around it: the call and its
1272
- * params at `debug`, and any throw at `error` with the cause classified.
1273
- * Every line carries `op` as a binding.
1274
- *
1275
- * **The params never reach the `error` line.** They routinely hold the
1276
- * things this SDK must not put in front of a production error tracker - an
1277
- * app bearer token, a document's signing fields, a wallet signature - and
1278
- * the `debug` line plus the request id is how you get them back. The type
1279
- * says so: `params` is `unknown`, which is not a {@link SafeFields} value.
1280
- *
1281
- * Always rethrows. Logging observes behaviour, it never changes it.
1282
- */
1283
- wrap<T>(op: string, params: unknown, run: () => Promise<T>): Promise<T>;
1284
- };
1285
- /**
1286
- * What a call site hands to `info`, `warn`, `error`, `failure` or `warning` -
1287
- * a {@link SafeEvent} minus the scope and bindings the logger stamps itself.
1288
- */
1289
- type InternalSafeEvent = {
1290
- /** A **constant** string literal. Every varying value belongs in `fields`. */
1291
- readonly msg: string;
1292
- readonly fields?: SafeFields;
1293
- readonly cause?: LogCause;
1294
- };
1295
- /** What a call site hands to `debug`. Its fields accept anything. */
1296
- type InternalDebugEvent = {
1297
- /** A **constant** string literal. Every varying value belongs in `fields`. */
1298
- readonly msg: string;
1299
- readonly fields?: UnredactedFields;
1300
- };
1301
-
1302
- /**
1303
- * Wire shapes for frontline's `/v1/centrifuge/vault/*` endpoints, as published
1304
- * in frontline's OpenAPI schema (ENG-1936). Every uint256 crosses as a decimal
1305
- * string, every price as a decimal string, every timestamp as ISO 8601.
1306
- *
1307
- * **A vault deposit does not settle in the transaction that places it.** The
1308
- * fund fulfils requests on its own epoch, in whole or in part, at a price set
1309
- * then, and the user claims the resulting shares in a second transaction. So
1310
- * every share figure before a fill is an estimate.
1311
- *
1312
- * The three GETs are free to poll. The two POSTs return calldata to broadcast:
1313
- * `invest` is signed for one wallet and called once on confirmation, `claim`
1314
- * collects everything claimable and carries no amount.
1315
- */
1316
- /**
1317
- * Why a deposit cannot be placed right now. A closed set, so a client can
1318
- * branch on every value. `vault_unlinked` is terminal for the offer's proxy on
1319
- * that chain; the rest clear on their own or by hand.
1320
- *
1321
- * `below_minimum` is the one reason that depends on an amount, so only a quote
1322
- * can report it - see {@link CentrifugeVaultReasonDto}.
1323
- */
1324
- type CentrifugeOrderReasonDto = 'vault_unlinked' | 'vault_halted' | 'proxy_not_permissioned' | 'price_unavailable' | 'below_minimum';
1325
- /** What a vault status can report: every reason but the amount-dependent one. */
1326
- type CentrifugeVaultReasonDto = Exclude<CentrifugeOrderReasonDto, 'below_minimum'>;
1327
- /**
1328
- * Where a wallet stands on a vault, derived from its amounts rather than
1329
- * stored. Not a lifecycle: a new request moves any of these back to `pending`
1330
- * while earlier shares stay claimed.
1331
- */
1332
- type CentrifugePositionStatusDto = 'none' | 'pending' | 'partially_filled' | 'filled' | 'claimed';
1333
- /** `GET /v1/centrifuge/vault/quote?symbol&chain&amount`. Indicative only. */
1334
- type CentrifugeVaultQuoteDto = {
1335
- object: 'centrifuge_vault_quote';
1336
- /** The vault's share token symbol, e.g. `deJTRSY`. */
1337
- symbol: string;
1338
- chain: string;
1339
- /** The amount priced, echoed back, in `spend_input_decimals`. No fee. */
1340
- spend_input_amount: string;
1341
- spend_input_decimals: number;
1342
- /** An estimate, not a floor: the fill can price either side of it. */
1343
- estimated_shares: string;
1344
- share_decimals: number;
1345
- /** Funding token per whole share. Null when the vault has no price. */
1346
- indicative_price: string | null;
1347
- /** In `spend_input_decimals`. Null when the offer sets no minimum. */
1348
- minimum_input_amount: string | null;
1349
- can_order: boolean;
1350
- /** Empty exactly when `can_order` is true. */
1351
- reasons: CentrifugeOrderReasonDto[];
1352
- };
1353
- /**
1354
- * `GET /v1/centrifuge/vault/status?symbol&chain`. The vault's own state, read
1355
- * from the chain on every call; the gate to poll, because Centrifuge announces
1356
- * none of these changes.
1357
- */
1358
- type CentrifugeVaultStatusDto = {
1359
- object: 'centrifuge_vault_status';
1360
- symbol: string;
1361
- chain: string;
1362
- /** Centrifuge's vault, read from the proxy. Fixed for the proxy's life. */
1363
- vault_address: string;
1364
- /** False is terminal for this proxy: a replacement has to be deployed. */
1365
- linked: boolean;
1366
- /** Whether the proxy is on the share token's memberlist. */
1367
- permissioned: boolean;
1368
- membership_valid_until: string | null;
1369
- /** Set by the proxy after a force-cancel; cleared only by hand. */
1370
- halted: boolean;
1371
- price_updated_at: string | null;
1372
- can_order: boolean;
1373
- reasons: CentrifugeVaultReasonDto[];
1374
- as_of: string;
1375
- };
1376
- /**
1377
- * What both POSTs return: calldata for the wallet to broadcast verbatim.
1378
- * Unlike Ondo's, `expires_at` is nullable - a claim carries no signature, so
1379
- * it is always null there.
1380
- */
1381
- type CentrifugeBroadcastDto = {
1382
- action: 'broadcast_transaction';
1383
- /** The offer's proxy on the chain. Lower case: compare case-insensitively. */
1384
- to: string;
1385
- data: string;
1386
- expires_at: string | null;
1387
- };
1388
- /**
1389
- * `POST /v1/centrifuge/vault/invest` with `{ symbol, chain, wallet_address,
1390
- * amount }`. Broadcasting it places a request in the vault's queue and buys
1391
- * nothing yet.
1392
- */
1393
- type CentrifugeVaultBuyDto = CentrifugeBroadcastDto & {
1394
- /** Exactly what the approval has to cover: no fee comes off it. */
1395
- spend_input_amount: string;
1396
- spend_input_decimals: number;
1397
- /** Not a quantity purchased: the fill prices later. */
1398
- estimated_shares: string;
1399
- share_decimals: number;
1400
- };
1401
- /**
1402
- * `GET /v1/centrifuge/vault/position?symbol&chain&wallet_address`. The six
1403
- * amounts are independent: a wallet can hold a pending request, a claimable
1404
- * balance and claimed shares at once. There is no per-fulfilment breakdown;
1405
- * settlement pools every fulfilment into one rate.
1406
- */
1407
- type CentrifugeVaultPositionDto = {
1408
- object: 'centrifuge_vault_position';
1409
- symbol: string;
1410
- chain: string;
1411
- wallet_address: string;
1412
- status: CentrifugePositionStatusDto;
1413
- /** Funding token ever requested, in `asset_decimals`. */
1414
- requested: string;
1415
- /** Of that, still queued. */
1416
- pending: string;
1417
- /** Of that, fulfilled. */
1418
- filled_assets: string;
1419
- /** Shares the fulfilments earned, in `share_decimals`. Held by the proxy until claimed. */
1420
- earned_shares: string;
1421
- claimed_shares: string;
1422
- /** Non-zero means the claim endpoint will return calldata. */
1423
- claimable_shares: string;
1424
- /** Read from the share token; can exceed `claimed_shares`. */
1425
- share_balance: string;
1426
- asset_decimals: number;
1427
- share_decimals: number;
1428
- /** Null before the first claim. */
1429
- average_price: string | null;
1430
- /** Centrifuge froze the wallet on the share token; blocks claiming. */
1431
- frozen: boolean;
1432
- as_of: string;
1433
- };
1434
- /**
1435
- * `POST /v1/centrifuge/vault/claim` with `{ symbol, chain, wallet_address }`.
1436
- * The wallet named must be the one that broadcasts: the proxy credits the
1437
- * sender.
1438
- */
1439
- type CentrifugeVaultClaimDto = CentrifugeBroadcastDto & {
1440
- /** A floor: a fill landing before the broadcast raises it. */
1441
- claimable_shares: string;
1442
- share_decimals: number;
1443
- };
1444
- /**
1445
- * `GET /v1/centrifuge/vault/redeem-position?symbol&chain&wallet_address`. The
1446
- * redeem side of {@link CentrifugeVaultPositionDto}, with the units swapped:
1447
- * what is queued is shares, and what a fill makes claimable is the funding
1448
- * token.
1449
- *
1450
- * TODO(frontline, ENG-1909): guessed. Frontline publishes no redeem endpoint
1451
- * yet; this mirrors the invest position field for field so the SDK can be
1452
- * built against it. Replace with the published schema when it lands.
1453
- */
1454
- type CentrifugeVaultRedeemPositionDto = {
1455
- object: 'centrifuge_vault_redeem_position';
1456
- symbol: string;
1457
- chain: string;
1458
- wallet_address: string;
1459
- status: CentrifugePositionStatusDto;
1460
- /** Shares still queued for redemption, in `share_decimals`. */
1461
- pending: string;
1462
- /**
1463
- * Funding token a claim would pay out now, in `asset_decimals`. An
1464
- * estimate: the vault holds the claimable amount in shares and prices it
1465
- * at the claim.
1466
- */
1467
- claimable_assets: string;
1468
- asset_decimals: number;
1469
- share_decimals: number;
1470
- /** Centrifuge froze the wallet on the share token. */
1471
- frozen: boolean;
1472
- as_of: string;
1473
- };
1474
- /**
1475
- * `POST /v1/centrifuge/vault/claim-proceeds` with `{ symbol, chain,
1476
- * wallet_address }`. Collects everything claimable on the redeem side; the
1477
- * proxy pays the sender.
1478
- *
1479
- * TODO(frontline, ENG-1909): guessed, as {@link CentrifugeVaultRedeemPositionDto}.
1480
- */
1481
- type CentrifugeVaultClaimProceedsDto = CentrifugeBroadcastDto & {
1482
- /** An estimate read when the calldata was built, in `asset_decimals`. */
1483
- claimable_assets: string;
1484
- asset_decimals: number;
1485
- };
1486
-
1487
- /**
1488
- * Which leg of a vault trade: `invest` turns the funding token into shares,
1489
- * `redeem` turns shares back into the funding token. Each wallet holds one
1490
- * pooled position per vault per direction, and a claim settles one of them.
1491
- */
1492
- type CentrifugeClaimDirection = 'invest' | 'redeem';
1493
- /**
1494
- * Why a deposit cannot be placed on a vault right now. Kept verbatim from the
1495
- * wire: frontline publishes it as a closed set for clients to branch on.
1496
- */
1497
- type CentrifugeOrderReason = CentrifugeOrderReasonDto;
1498
- /** The reasons a vault status can report - all but `below_minimum`. */
1499
- type CentrifugeVaultReason = CentrifugeVaultReasonDto;
1500
- /**
1501
- * Where a wallet stands on a vault. Not a lifecycle - see
1502
- * {@link CentrifugeVaultPosition.status}.
1503
- */
1504
- type CentrifugePositionStatus = CentrifugePositionStatusDto;
1505
- /**
1506
- * Whether a deposit can be placed, as one union rather than the wire's
1507
- * `can_order` beside `reasons`: a blocked answer always says why, and an
1508
- * orderable one has nothing to say. The wire pair can contradict itself; this
1509
- * cannot, because `fromDto` refuses the payloads that do.
1510
- */
1511
- type CentrifugeOrderability<R extends CentrifugeOrderReason> = {
1512
- type: 'orderable';
1513
- } | {
1514
- type: 'blocked';
1515
- reasons: [R, ...R[]];
1516
- };
1517
- /**
1518
- * What a deposit of a given size would buy, and whether it can be placed.
1519
- *
1520
- * **Indicative only.** The price is read from the vault now and the fund
1521
- * prices the fulfilment on its own epoch, so neither {@link indicativePrice}
1522
- * nor {@link estimatedShares} is a commitment. Free to poll while the user
1523
- * sizes a deposit.
1524
- */
1525
- type CentrifugeVaultQuote = {
1526
- chain: EthereumChain;
1527
- /** The vault's share token symbol, e.g. `deJTRSY`. */
1528
- symbol: AssetSymbol;
1529
- /** The amount priced, in the funding token's decimals. No fee is taken. */
1530
- spendInputAmount: BlockchainAmount;
1531
- /** Shares at the indicative price, in the share token's decimals. */
1532
- estimatedShares: BlockchainAmount;
1533
- /** Funding token per whole share. Null when the vault publishes no price. */
1534
- indicativePrice: DecimalString | null;
1535
- /** Null when the offer sets no minimum. Same decimals as the spend. */
1536
- minimumInputAmount: BlockchainAmount | null;
1537
- orderability: CentrifugeOrderability<CentrifugeOrderReason>;
1538
- };
1539
- declare const CentrifugeVaultQuote: {
1540
- fromDto: (dto: CentrifugeVaultQuoteDto) => CentrifugeVaultQuote;
1541
- };
1542
- /**
1543
- * A vault's own state, independent of any wallet or amount: the gate to poll.
1544
- * Centrifuge announces none of these changes, and an unlinked vault leaves the
1545
- * offer's proxy permanently dead, so a cached answer goes wrong silently.
1546
- */
1547
- type CentrifugeVaultStatus = {
1548
- chain: EthereumChain;
1549
- symbol: AssetSymbol;
1550
- /** Centrifuge's vault behind the proxy. Fixed for the proxy's life. */
1551
- vaultAddress: EvmContractAddress;
1552
- /**
1553
- * Whether Centrifuge still links the vault to its pool. False is terminal
1554
- * for this proxy: no request or claim succeeds until a new one is deployed.
1555
- */
1556
- linked: boolean;
1557
- /**
1558
- * Whether the proxy is on the share token's memberlist. It holds shares for
1559
- * every wallet, so one expired entry stops the whole offer.
1560
- */
1561
- permissioned: boolean;
1562
- /** Watch it: {@link permissioned} goes false the moment it passes. */
1563
- membershipValidUntil: Date | null;
1564
- /** The proxy halted itself after a force-cancel; cleared only by hand. */
1565
- halted: boolean;
1566
- /** A stale value is the signal that a quote's price is old. */
1567
- priceUpdatedAt: Date | null;
1568
- orderability: CentrifugeOrderability<CentrifugeVaultReason>;
1569
- /** When the chain was read: how old everything above is. */
1570
- asOf: Date;
1571
- };
1572
- declare const CentrifugeVaultStatus: {
1573
- fromDto: (dto: CentrifugeVaultStatusDto) => CentrifugeVaultStatus;
1574
- };
1575
- /**
1576
- * What both vault transactions share: calldata to broadcast verbatim, and the
1577
- * deadline on it.
1578
- */
1579
- type CentrifugeVaultTransactionCore = {
1580
- /** The `to` is the offer's proxy: the spender the deposit was approved to. */
1581
- tx: Tx;
1582
- /**
1583
- * When the calldata stops being accepted, or null when it carries no
1584
- * deadline - always the case for a claim, which nobody signs.
1585
- */
1586
- expiresAt: Date | null;
1587
- };
1588
- /**
1589
- * A signed deposit request, ready to broadcast.
1590
- *
1591
- * **Broadcasting it buys nothing yet.** It places a request in the vault's
1592
- * queue; the fund fulfils it later at a price set then, and the user comes
1593
- * back to claim. {@link estimatedShares} is therefore never a quantity
1594
- * purchased. Single-use: built once on confirmation, never on a timer.
1595
- */
1596
- type CentrifugeVaultBuyTransaction = CentrifugeVaultTransactionCore & {
1597
- /** Exactly what the approval has to cover: no fee comes off it. */
1598
- spendInputAmount: BlockchainAmount;
1599
- /** At the price read when the calldata was built. An estimate, not a floor. */
1600
- estimatedShares: BlockchainAmount;
1601
- };
1602
- declare const CentrifugeVaultBuyTransaction: {
1603
- fromDto: (dto: CentrifugeVaultBuyDto) => CentrifugeVaultBuyTransaction;
1604
- };
1605
- /**
1606
- * The claim that moves fulfilled shares from the proxy to the wallet: the
1607
- * second transaction every vault purchase needs. The wallet that broadcasts it
1608
- * is the one credited.
1609
- */
1610
- type CentrifugeVaultClaimTransaction = CentrifugeVaultTransactionCore & {
1611
- /**
1612
- * Read when the calldata was built. A floor: a fill landing before the
1613
- * broadcast raises it, and the claim still collects everything.
1614
- */
1615
- claimableShares: BlockchainAmount;
1616
- };
1617
- declare const CentrifugeVaultClaimTransaction: {
1618
- fromDto: (dto: CentrifugeVaultClaimDto) => CentrifugeVaultClaimTransaction;
1619
- };
1620
- /**
1621
- * One wallet's standing on one vault: what it put in, what has settled, and
1622
- * what it can claim. The endpoint a returning user lands on, and the one that
1623
- * says whether to offer the claim.
1624
- *
1625
- * The amounts are independent of each other: each piece of a request settles
1626
- * and is claimed on its own, so a wallet can be pending, claimable and claimed
1627
- * at once. There is no per-fulfilment breakdown; settlement pools every
1628
- * fulfilment into one {@link averagePrice}.
1629
- */
1630
- type CentrifugeVaultPosition = {
1631
- chain: EthereumChain;
1632
- symbol: AssetSymbol;
1633
- walletAddress: EvmWalletAddress;
1634
- /**
1635
- * Derived by frontline from the amounts. Not a lifecycle: a new request
1636
- * moves it back to `pending` while earlier shares stay claimed.
1637
- */
1638
- status: CentrifugePositionStatus;
1639
- /** Funding token ever requested. */
1640
- requested: BlockchainAmount;
1641
- /** Of {@link requested}, what is still queued. */
1642
- pending: BlockchainAmount;
1643
- /** Of {@link requested}, what has been fulfilled. */
1644
- filledAssets: BlockchainAmount;
1645
- /** Shares the fulfilments earned. Held by the proxy until claimed. */
1646
- earnedShares: BlockchainAmount;
1647
- claimedShares: BlockchainAmount;
1648
- /** Non-zero means a claim will return calldata. */
1649
- claimableShares: BlockchainAmount;
1650
- /**
1651
- * What the wallet holds on the share token. Can exceed
1652
- * {@link claimedShares}: shares acquired any other way count here.
1653
- */
1654
- shareBalance: BlockchainAmount;
1655
- /** Pooled rate over everything claimed. Null before the first claim. */
1656
- averagePrice: DecimalString | null;
1657
- /** Centrifuge froze this wallet on the share token. Blocks claiming. */
1658
- frozen: boolean;
1659
- asOf: Date;
1660
- };
1661
- declare const CentrifugeVaultPosition: {
1662
- fromDto: (dto: CentrifugeVaultPositionDto) => CentrifugeVaultPosition;
1663
- };
1664
- /**
1665
- * One wallet's standing on the redeem side of a vault: shares queued to sell,
1666
- * and the funding token a fill has made claimable. The mirror of
1667
- * {@link CentrifugeVaultPosition}, and as independent of it: a wallet can be
1668
- * investing and redeeming on the same vault at once.
1669
- *
1670
- * TODO(frontline, ENG-1909): built against a guessed wire shape - see
1671
- * `CentrifugeVaultRedeemPositionDto`.
1672
- */
1673
- type CentrifugeVaultRedeemPosition = {
1674
- chain: EthereumChain;
1675
- symbol: AssetSymbol;
1676
- walletAddress: EvmWalletAddress;
1677
- status: CentrifugePositionStatus;
1678
- /** Shares still queued for redemption. */
1679
- pending: BlockchainAmount;
1680
- /**
1681
- * Funding token a claim would pay out now. An estimate: the vault prices the
1682
- * claimable shares at the claim. Non-zero means a claim returns calldata.
1683
- */
1684
- claimableAssets: BlockchainAmount;
1685
- /** Centrifuge froze this wallet on the share token. Blocks claiming. */
1686
- frozen: boolean;
1687
- asOf: Date;
1688
- };
1689
- declare const CentrifugeVaultRedeemPosition: {
1690
- fromDto: (dto: CentrifugeVaultRedeemPositionDto) => CentrifugeVaultRedeemPosition;
1691
- };
1692
- /**
1693
- * One wallet's position on one leg of a vault trade, tagged with the leg. The
1694
- * two legs are read from two endpoints and settle in opposite units - the
1695
- * invest leg queues the funding token and pays out shares, the redeem leg the
1696
- * reverse - so the tag is what says which unit each figure is in.
1697
- */
1698
- type CentrifugeVaultLeg = {
1699
- direction: 'invest';
1700
- position: CentrifugeVaultPosition;
1701
- } | {
1702
- direction: 'redeem';
1703
- position: CentrifugeVaultRedeemPosition;
1704
- };
1705
- declare const CentrifugeVaultLeg: {
1706
- /**
1707
- * What a claim on the leg would collect: shares for `invest`, the funding
1708
- * token for `redeem`.
1709
- */
1710
- claimable: (leg: CentrifugeVaultLeg) => BlockchainAmount;
1711
- /** Whether the leg has anything queued or anything ready to claim. */
1712
- isActive: (leg: CentrifugeVaultLeg) => boolean;
1713
- };
1714
- /**
1715
- * One wallet's position on one leg of one vault: what a claim targets. A
1716
- * wallet holds at most one per direction per chain, so the three together
1717
- * name it.
1718
- */
1719
- type CentrifugeVaultLegId = Newtype<string, 'CentrifugeVaultLegId'>;
1720
- declare const CentrifugeVaultLegId: {
1721
- /** Addresses compare case-insensitively: frontline echoes them lower case. */
1722
- of: (leg: CentrifugeVaultLeg) => CentrifugeVaultLegId;
1723
- };
1724
- /**
1725
- * The claim that pays a filled redemption out in the funding token: the
1726
- * second transaction every vault sale needs. The wallet that broadcasts it is
1727
- * the one paid.
1728
- *
1729
- * TODO(frontline, ENG-1909): built against a guessed wire shape - see
1730
- * `CentrifugeVaultClaimProceedsDto`.
1731
- */
1732
- type CentrifugeVaultClaimProceedsTransaction = CentrifugeVaultTransactionCore & {
1733
- /** An estimate read when the calldata was built; the claim pays it all. */
1734
- claimableAssets: BlockchainAmount;
1735
- };
1736
- declare const CentrifugeVaultClaimProceedsTransaction: {
1737
- fromDto: (dto: CentrifugeVaultClaimProceedsDto) => CentrifugeVaultClaimProceedsTransaction;
1738
- };
1739
-
1740
- /**
1741
- * Centrifuge vault reads and claims: an indicative quote, the vault-wide
1742
- * ordering gate, each wallet's position per direction, and the calldata that
1743
- * claims a filled request.
1744
- *
1745
- * The reads are free to poll - none spends an attestation, so a client may
1746
- * call them while the user sizes a deposit or waits on a fill. The quote has
1747
- * no expiry: it is indicative, the fund prices fulfilment later, and a
1748
- * countdown would imply a commitment the API does not make.
1749
- *
1750
- * A vault trade settles in two legs: a request the fund fills on its own
1751
- * schedule, then a claim. There is no order id - each wallet has one pooled
1752
- * position per vault per direction - so the claims take a wallet, not an
1753
- * order, and collect everything claimable.
1754
- *
1755
- * The calldata builders are the exception: {@link CentrifugeNamespace.buildBuyTransaction}
1756
- * and the claims are each called once, when the user confirms, and never on a
1757
- * timer. Broadcasting the buy calldata places a request. It does not buy
1758
- * shares.
1759
- *
1760
- * Every method requires `AuthState === 'logged-in'` and throws
1761
- * {@link NotAuthenticatedError} otherwise.
1762
- */
1763
- interface CentrifugeNamespace {
1764
- getQuote(params: GetCentrifugeVaultQuoteParams): Promise<CentrifugeVaultQuote>;
1765
- getVaultStatus(params: GetCentrifugeVaultStatusParams): Promise<CentrifugeVaultStatus>;
1766
- /** The wallet's invest position: funding queued, shares claimable. */
1767
- getPosition(params: CentrifugeWalletParams): Promise<CentrifugeVaultPosition>;
1768
- /**
1769
- * The wallet's redeem position: shares queued, funding claimable.
1770
- *
1771
- * TODO(frontline, ENG-1909): built against a guessed endpoint.
1772
- */
1773
- getRedeemPosition(params: CentrifugeWalletParams): Promise<CentrifugeVaultRedeemPosition>;
1774
- /**
1775
- * Calldata claiming every claimable share. Broadcast it from
1776
- * `params.walletAddress`: the proxy credits the sender.
1777
- */
1778
- createClaim(params: CentrifugeWalletParams): Promise<CentrifugeVaultClaimTransaction>;
1779
- /**
1780
- * Calldata paying out every claimable redemption in the funding token.
1781
- * Broadcast it from `params.walletAddress`.
1782
- *
1783
- * TODO(frontline, ENG-1909): built against a guessed endpoint.
1784
- */
1785
- createClaimProceeds(params: CentrifugeWalletParams): Promise<CentrifugeVaultClaimProceedsTransaction>;
1786
- /**
1787
- * Builds the calldata that places a deposit request.
1788
- *
1789
- * Called once on confirmation. The reads above are the ones a checkout polls.
1790
- */
1791
- buildBuyTransaction(params: BuildCentrifugeVaultBuyParams): Promise<CentrifugeVaultBuyTransaction>;
1792
- }
1793
- declare class CentrifugeNamespaceImpl implements CentrifugeNamespace {
1794
- private readonly ctx;
1795
- protected readonly log: InternalLogger;
1796
- constructor(ctx: UniversalNamespaceContext);
1797
- getQuote(params: GetCentrifugeVaultQuoteParams): Promise<CentrifugeVaultQuote>;
1798
- getVaultStatus(params: GetCentrifugeVaultStatusParams): Promise<CentrifugeVaultStatus>;
1799
- getPosition(params: CentrifugeWalletParams): Promise<CentrifugeVaultPosition>;
1800
- getRedeemPosition(params: CentrifugeWalletParams): Promise<CentrifugeVaultRedeemPosition>;
1801
- createClaim(params: CentrifugeWalletParams): Promise<CentrifugeVaultClaimTransaction>;
1802
- createClaimProceeds(params: CentrifugeWalletParams): Promise<CentrifugeVaultClaimProceedsTransaction>;
1803
- buildBuyTransaction(params: BuildCentrifugeVaultBuyParams): Promise<CentrifugeVaultBuyTransaction>;
1804
- }
1805
-
1806
- type AssetDto = {
1807
- code: string;
1808
- fractional_digits: number;
1809
- id: string;
1810
- name: string;
1811
- };
1812
-
1813
- type AssetId = Newtype<string, 'AssetId'>;
1814
- declare const AssetId: (value: string) => AssetId;
1815
- type AssetCode = Newtype<string, 'AssetCode'>;
1816
- declare const AssetCode: (value: string) => AssetCode;
1817
- type Asset = {
1818
- id: AssetId;
1819
- code: AssetCode;
1820
- name: string;
1821
- fractionalDigits: number;
1822
- };
1823
- declare const Asset: {
1824
- fromDto: (dto: AssetDto) => Asset;
1825
- };
1826
-
1827
- /**
1828
- * The product an offer is checked out through. The backend sends one compound
1829
- * `{supplier}::{saleType}` string, verbatim as spelled below: a double colon
1830
- * between the two halves, `snake_case` within each. CoinList's token sale is
1831
- * `coinlist::token_sale`; there is no `coinlist::sale` and no
1832
- * `coinlist_token_sale`.
1833
- *
1834
- * Kept flat rather than split into a supplier and a sale type, because a flat
1835
- * union makes a `switch` over it exhaustive: adding a provider without
1836
- * handling it becomes a compile error.
1837
- */
1838
- type OfferTypeDto = 'coinlist::token_sale' | 'superstate::swap' | 'ondo::swap' | 'centrifuge::vault';
1839
- /**
1840
- * One variant per {@link OfferTypeDto}, mirroring frontline#1365, which keys
1841
- * `GET /v1/offers` on `type`. Read `type` first: it decides which of the
1842
- * fields below mean anything.
1843
- */
1844
- type OfferDto = CoinListTokenSaleOfferDto | SuperstateSwapOfferDto | OndoSwapOfferDto | CentrifugeVaultOfferDto;
1845
- type OfferBaseDto = {
1846
- id: string;
1847
- slug: string;
1848
- ends_at: string | null;
1849
- tokens: OfferTokenDto[];
1850
- };
1851
- /**
1852
- * A curated sale window and the hand-authored copy that goes with it. Required
1853
- * on every variant that runs such a campaign, which is every one but Ondo.
1854
- */
1855
- type OfferEditorialDto = {
1856
- tagline: string;
1857
- banner_url: string;
1858
- starts_at: string;
1859
- };
1860
- /**
1861
- * What an Ondo swap or a Centrifuge vault sends in place of
1862
- * {@link OfferEditorialDto}. Neither runs a campaign, so the keys arrive as
1863
- * `null` and carry nothing, and the backend may stop sending them at all.
1864
- * Declared so a fixture can describe the real payload; no `fromDto` reads
1865
- * them.
1866
- */
1867
- type OfferNoEditorialDto = {
1868
- tagline?: null;
1869
- banner_url?: null;
1870
- starts_at?: null;
1871
- };
1872
- type CoinListTokenSaleOfferDto = OfferBaseDto & OfferEditorialDto & {
1873
- type: 'coinlist::token_sale';
1874
- logo_url: string;
1875
- };
1876
- type SuperstateSwapOfferDto = OfferBaseDto & OfferEditorialDto & {
1877
- type: 'superstate::swap';
1878
- /** Publishing a swap does not require anyone to upload artwork for it. */
1879
- logo_url: string | null;
1880
- };
1881
- type OndoSwapOfferDto = OfferBaseDto & OfferNoEditorialDto & {
1882
- type: 'ondo::swap';
1883
- /** Publishing a swap does not require anyone to upload artwork for it. */
1884
- logo_url: string | null;
1885
- };
1886
- type CentrifugeVaultOfferDto = OfferBaseDto & OfferNoEditorialDto & {
1887
- type: 'centrifuge::vault';
1888
- /** Publishing a vault does not require anyone to upload artwork for it. */
1889
- logo_url: string | null;
1890
- };
1891
- type OfferTokenDto = {
1892
- /**
1893
- * `vault` is the share token a `centrifuge::vault` offer issues for
1894
- * deposits, as `swap` is the token a swap offer trades into.
1895
- */
1896
- role: 'funding' | 'distribution' | 'swap' | 'vault';
1897
- chain: string;
1898
- address: string;
1899
- };
1900
-
1901
- /**
1902
- * One variant per `OfferTypeDto`, the same split as `OfferDto` with what
1903
- * `GET /v1/offers/:id` adds on top. Read `type` first.
1904
- */
1905
- type OfferDetailDto = CoinListTokenSaleOfferDetailDto | SuperstateSwapOfferDetailDto | OndoSwapOfferDetailDto | CentrifugeVaultOfferDetailDto;
1906
- type CoinListTokenSaleOfferDetailDto = OfferDetailBaseDto & OfferEditorialDto & OfferDetailNoSwapContractsDto & OfferDetailNoVaultContractsDto & {
1907
- type: 'coinlist::token_sale';
1908
- logo_url: string;
1909
- };
1910
- type SuperstateSwapOfferDetailDto = OfferDetailBaseDto & OfferEditorialDto & OfferDetailNoSwapContractsDto & OfferDetailNoVaultContractsDto & {
1911
- type: 'superstate::swap';
1912
- logo_url: string | null;
1913
- };
1914
- type OndoSwapOfferDetailDto = OfferDetailBaseDto & OfferNoEditorialDto & OfferDetailNoVaultContractsDto & {
1915
- type: 'ondo::swap';
1916
- logo_url: string | null;
1917
- /**
1918
- * Every chain this offer swaps on, with the contract each settles
1919
- * through. `[]` is an answer - "swaps nowhere" - and a missing key is not.
1920
- */
1921
- swap_contracts: OfferDetailSwapContractDto[];
1922
- };
1923
- type CentrifugeVaultOfferDetailDto = OfferDetailBaseDto & OfferNoEditorialDto & OfferDetailNoSwapContractsDto & {
1924
- type: 'centrifuge::vault';
1925
- logo_url: string | null;
1926
- /**
1927
- * Every chain this vault takes deposits on, with the CoinList proxy each
1928
- * request goes through. `[]` is an answer - "deposits nowhere", which is
1929
- * every vault until a proxy is deployed - and a missing key is not.
1930
- */
1931
- vault_contracts: OfferDetailVaultContractDto[];
1932
- };
1933
- type OfferDetailNoVaultContractsDto = {
1934
- vault_contracts?: OfferDetailVaultContractDto[];
1935
- };
1936
- /**
1937
- * An offer that does not settle through a CoinList swap contract sends `[]`
1938
- * or no key at all, and either way there is nothing to read. Declared so a
1939
- * fixture can describe the real payload.
1940
- */
1941
- type OfferDetailNoSwapContractsDto = {
1942
- swap_contracts?: OfferDetailSwapContractDto[];
1943
- };
1944
- type OfferDetailBaseDto = {
1945
- asset: AssetDto;
1946
- faqs: OfferDetailFaqDto[];
1947
- funding_assets: AssetDto[];
1948
- tokens: OfferTokenDto[];
1949
- id: string;
1950
- links: OfferDetailLinkDto[];
1951
- milestones: OfferDetailMilestoneDto[];
1952
- name: string;
1953
- object: 'offer_details';
1954
- options: OfferDetailOptionDto[];
1955
- slug: string;
1956
- terms: OfferDetailTermDto[];
1957
- about: string | null | undefined;
1958
- category: string;
1959
- ends_at: string | null;
1960
- /** Issuer of the *token*, not of the security it tracks. Ondo offers only. */
1961
- issuer: string | null;
1962
- /** ISO 6166 id of the underlying security. Null when the supplier has none. */
1963
- isin: string | null;
1964
- /** The underlying's symbol on its venue (`QQQ`), never the token's (`QQQon`). */
1965
- ticker: string | null;
1966
- /** Supplier vocabulary (`Stock`, `ETF`). Open set — display, do not branch. */
1967
- instrument_type: string | null;
1968
- /** Venue the underlying lists on. Not served by the supplier; entered by hand. */
1969
- listing_venue: string | null;
1970
- };
1971
- type OfferDetailFaqDto = {
1972
- answer: string | null;
1973
- question: string | null;
1974
- };
1975
- type OfferDetailLinkDto = {
1976
- label: string | null;
1977
- url: string | null;
1978
- };
1979
- type OfferDetailMilestoneDto = {
1980
- name: string | null;
1981
- schedule: string | null;
1982
- status: 'completed' | 'active' | 'upcoming';
1983
- };
1984
- type OfferDetailOptionDto = {
1985
- bid_increment: number | null;
1986
- floor_price_usd: number | null;
1987
- id: string;
1988
- minimum_purchase_usd: number | null;
1989
- price_usd: string | null;
1990
- sale_agreement_url: string | null;
1991
- slug: string;
1992
- total_token_supply: number | null;
1993
- };
1994
- type OfferDetailTermDto = {
1995
- key: string | null;
1996
- value: string | null;
1997
- };
1998
- type OfferDetailSwapContractDto = {
1999
- chain: string;
2000
- address: string;
2001
- };
2002
- type OfferDetailVaultContractDto = {
2003
- chain: string;
2004
- address: string;
2005
- };
2006
-
2007
- type OfferId = Newtype<string, 'OfferId'>;
2008
- declare const OfferId: (value: string) => OfferId;
2009
- type OfferSlug = Newtype<string, 'OfferSlug'>;
2010
- declare const OfferSlug: (value: string) => OfferSlug;
2011
- type OfferType = OfferTypeDto;
2012
- declare const isOfferType: (value: string) => value is OfferType;
2013
- type OfferBase = {
2014
- id: OfferId;
2015
- slug: OfferSlug;
2016
- endsAt: Date | null;
2017
- tokens: OfferToken[];
2018
- };
2019
- type CoinListTokenSaleOffer = OfferBase & OfferEditorial & {
2020
- type: 'coinlist::token_sale';
2021
- logoUrl: string;
2022
- };
2023
- type SuperstateSwapOffer = OfferBase & OfferEditorial & {
2024
- type: 'superstate::swap';
2025
- /** Null when nobody has uploaded artwork: a swap publishes without it. */
2026
- logoUrl: string | null;
2027
- };
2028
- type OndoSwapOffer = OfferBase & {
2029
- type: 'ondo::swap';
2030
- /** Null when nobody has uploaded artwork: a swap publishes without it. */
2031
- logoUrl: string | null;
2032
- };
2033
- type CentrifugeVaultOffer = OfferBase & {
2034
- type: 'centrifuge::vault';
2035
- /** Null when nobody has uploaded artwork: a vault publishes without it. */
2036
- logoUrl: string | null;
2037
- };
2038
- /**
2039
- * A curated sale window and the hand-authored copy that goes with it. Every
2040
- * variant that runs such a campaign carries all three, validated; an Ondo swap
2041
- * trades continuously and a Centrifuge vault takes deposits continuously, so
2042
- * neither runs one and neither carries any.
2043
- */
2044
- type OfferEditorial = {
2045
- tagline: string;
2046
- bannerUrl: string;
2047
- startsAt: Date;
2048
- };
2049
- declare const OfferEditorial: {
2050
- /**
2051
- * `model` prefixes the field in the error (`'Offer'`, `'OfferDetail'`), so
2052
- * the same three checks name the payload that failed them.
2053
- */
2054
- fromDto: (dto: OfferEditorialDto, model: string) => OfferEditorial;
2055
- };
2056
- /**
2057
- * An offer as `GET /v1/offers` lists it: a union on {@link OfferType}, each
2058
- * variant carrying only the fields that mean something for it. Narrow on
2059
- * `type` before reading anything beyond {@link OfferBase} - an Ondo swap has
2060
- * no `startsAt` to read, and the compiler says so.
2061
- */
2062
- type Offer = CoinListTokenSaleOffer | SuperstateSwapOffer | OndoSwapOffer | CentrifugeVaultOffer;
2063
- declare const Offer: {
2064
- fromDto: (dto: OfferDto) => Offer;
2065
- /**
2066
- * Maps a page of offers, dropping every offer whose `type` this SDK does not
2067
- * name. The same reasoning as {@link OfferToken.listFromDto}: a plain `.map`
2068
- * would throw out of `fromDto` and, through `PaginatedResponse.fromDto`,
2069
- * reject the whole page, so one offer of an unknown type would blank the
2070
- * grid for every offer beside it. A single offer fetched by id still
2071
- * throws, because there is nothing beside it to keep.
2072
- */
2073
- listFromDto: (dtos: OfferDto[]) => Offer[];
2074
- };
2075
- /**
2076
- * `vault` is the share token a `centrifuge::vault` offer issues for deposits,
2077
- * as `swap` is the token a swap offer trades into.
2078
- */
2079
- type TokenRole = 'funding' | 'distribution' | 'swap' | 'vault';
2080
- type OfferToken = {
2081
- role: TokenRole;
2082
- chain: Chain;
2083
- address: EvmContractAddress;
2084
- };
2085
- declare const OfferToken: {
2086
- fromDto: (dto: OfferTokenDto) => OfferToken;
2087
- /**
2088
- * Maps an offer's token list, dropping every token on a chain this SDK does
2089
- * not name. Frontline's chain registry runs ahead of {@link Chain}, and a
2090
- * plain `.map` would throw out of `Offer.fromDto` and, through
2091
- * `PaginatedResponse.fromDto`, reject the whole offers page - which is how
2092
- * one Base token blanked production's offers list. Dropping costs that
2093
- * token's metadata alone: `coinlist.tokens.get` takes an `EthereumChain`,
2094
- * so nobody could have looked it up anyway.
2095
- *
2096
- * Same shape as `TokenMetadata.fromRegistryDto`.
2097
- */
2098
- listFromDto: (dtos: OfferTokenDto[]) => OfferToken[];
2099
- };
2100
-
2101
- type Ticker = Newtype<string, 'Ticker'>;
2102
- declare const Ticker: (value: string) => Ticker;
2103
- /**
2104
- * An ISO 6166 International Securities Identification Number, e.g.
2105
- * `US0378331005`. Identifies the security itself, which is what makes it the
2106
- * stable key across venues where a {@link Ticker} is not: the same security
2107
- * trades under different tickers in different places, and the same ticker
2108
- * means different securities in different places.
2109
- *
2110
- * Not validated on construction — the value comes from a supplier that has
2111
- * already checked it, and a client-side check-digit test could only reject
2112
- * data the SDK still has to display.
2113
- */
2114
- type Isin = Newtype<string, 'Isin'>;
2115
- declare const Isin: (value: string) => Isin;
2116
- type OrderBookSide = 'buy' | 'sell';
2117
-
2118
- /** The `type` of every {@link AsyncOfferDetail}. */
2119
- type AsyncOfferType = AsyncOfferDetail['type'];
2120
- /**
2121
- * An offer whose trade settles later: the user places a request, the fund
2122
- * fills it on its own schedule, and the user comes back to claim the result.
2123
- * Only these have a second leg for `ClaimContainer` to show.
2124
- *
2125
- * A subset of {@link OfferDetail} picked by `type`, so it narrows like any
2126
- * other variant and a new async provider is one more member here.
2127
- */
2128
- type AsyncOfferDetail = CentrifugeVaultOfferDetail;
2129
- declare const AsyncOfferDetail: {
2130
- /**
2131
- * Narrows an offer fetched generically, e.g. on an offer page, to one with
2132
- * something to claim.
2133
- *
2134
- * An exhaustive `switch` rather than a list of async types, so a new offer
2135
- * type is a compile error here until someone decides whether it settles
2136
- * later.
2137
- */
2138
- is: (offer: OfferDetail) => offer is AsyncOfferDetail;
2139
- };
2140
- type CoinListTokenSaleOfferDetail = OfferDetailBase & OfferEditorial & {
2141
- type: 'coinlist::token_sale';
2142
- logoUrl: string;
2143
- };
2144
- type SuperstateSwapOfferDetail = OfferDetailBase & OfferEditorial & {
2145
- type: 'superstate::swap';
2146
- /** Null when nobody has uploaded artwork: a swap publishes without it. */
2147
- logoUrl: string | null;
2148
- };
2149
- type OndoSwapOfferDetail = OfferDetailBase & {
2150
- type: 'ondo::swap';
2151
- /** Null when nobody has uploaded artwork: a swap publishes without it. */
2152
- logoUrl: string | null;
2153
- /**
2154
- * Every chain this offer can be swapped on, with the CoinList contract each
2155
- * settles through. Empty means it cannot be swapped anywhere.
2156
- */
2157
- swapContracts: OfferSwapContract[];
2158
- };
2159
- type CentrifugeVaultOfferDetail = OfferDetailBase & {
2160
- type: 'centrifuge::vault';
2161
- /** Null when nobody has uploaded artwork: a vault publishes without it. */
2162
- logoUrl: string | null;
2163
- /**
2164
- * Every chain this vault takes deposits on, with the CoinList proxy each
2165
- * request goes through. Empty means it takes deposits nowhere yet.
2166
- */
2167
- vaultContracts: OfferVaultContract[];
2168
- };
2169
- type OfferDetailBase = {
2170
- id: OfferId;
2171
- slug: OfferSlug;
2172
- name: string;
2173
- asset: Asset;
2174
- fundingAssets: Asset[];
2175
- tokens: OfferToken[];
2176
- about: string | null;
2177
- category: string;
2178
- /**
2179
- * The legal issuer of the *token*, e.g. `'Ondo Global Markets'`. The issuer
2180
- * of the security it tracks is {@link OfferDetail.name} (`'Apple Inc.'`).
2181
- * Null on offers with no single named issuer.
2182
- */
2183
- issuer: string | null;
2184
- /**
2185
- * ISO 6166 identifier of the underlying security, e.g. `'US0378331005'`.
2186
- * Null both on offers that tokenize no security and on the few that do but
2187
- * whose supplier publishes no ISIN, so absence does not imply "not a
2188
- * security".
2189
- */
2190
- isin: Isin | null;
2191
- /**
2192
- * The underlying security's symbol on its listing venue, e.g. `'QQQ'`. This
2193
- * is *not* the token's symbol — that is `asset.code` (`'QQQon'`). Null on
2194
- * offers that tokenize no listed security.
2195
- */
2196
- ticker: Ticker | null;
2197
- /**
2198
- * What kind of instrument the underlying is, as the supplier classifies it:
2199
- * `'Stock'`, `'ETF'`. Distinct from {@link OfferDetail.category}, which is
2200
- * the broader class the offer is grouped under (`'Equities'`) — this field
2201
- * describes the single instrument, `category` describes the shelf it sits
2202
- * on.
2203
- *
2204
- * An open set: the vocabulary belongs to the supplier and may grow without
2205
- * notice, so render an unrecognized value rather than branching on it. Note
2206
- * the supplier's spelling is its own — a common stock arrives as `'Stock'`.
2207
- */
2208
- instrumentType: string | null;
2209
- /**
2210
- * The exchange the underlying security lists on, e.g. `'NASDAQ'`. Not
2211
- * derivable from {@link OfferDetail.isin}, whose country prefix is the
2212
- * country of issuance rather than the venue.
2213
- *
2214
- * Unlike the fields above, this one is recorded by hand rather than served
2215
- * by the supplier, so it is null until someone records it — on a newly
2216
- * listed offer that is the normal state, and it says nothing about whether
2217
- * the offer tokenizes a security.
2218
- */
2219
- listingVenue: string | null;
2220
- endsAt: Date | null;
2221
- faqs: FaqItem[];
2222
- links: Link[];
2223
- milestones: Milestone[];
2224
- options: OfferOption[];
2225
- terms: TermItem[];
2226
- };
2227
- type OfferOptionId = Newtype<string, 'OfferOptionId'>;
2228
- declare const OfferOptionId: (value: string) => OfferOptionId;
2229
- type OfferOptionSlug = Newtype<string, 'OfferOptionSlug'>;
2230
- declare const OfferOptionSlug: (value: string) => OfferOptionSlug;
2231
- /**
2232
- * A chain an offer can be swapped on, with the CoinList contract the swap
2233
- * settles through - the spender to approve before any quote exists.
2234
- *
2235
- * Carries no role, unlike {@link OfferToken}: there is one swap contract per
2236
- * chain and it serves every Ondo asset on it, so which token is being traded
2237
- * does not change the answer.
2238
- */
2239
- type OfferSwapContract = {
2240
- chain: Chain;
2241
- address: EvmContractAddress;
2242
- };
2243
- declare const OfferSwapContract: {
2244
- fromDto: (dto: OfferDetailSwapContractDto) => OfferSwapContract;
2245
- };
2246
- /**
2247
- * A chain a Centrifuge vault takes deposits on, with the CoinList proxy the
2248
- * request goes through. Not a token, so the token registry knows nothing about
2249
- * it: it is the spender the user approves the funding token to, and the `to`
2250
- * the buy and claim transactions are sent to.
2251
- *
2252
- * Its own type rather than an {@link OfferSwapContract}, although the shape is
2253
- * the same, because the meaning is not: a swap contract serves every Ondo
2254
- * asset on its chain, while a proxy belongs to one offer on one chain, so the
2255
- * same chain carries a different address on every vault.
2256
- */
2257
- type OfferVaultContract = {
2258
- chain: Chain;
2259
- address: EvmContractAddress;
2260
- };
2261
- declare const OfferVaultContract: {
2262
- fromDto: (dto: OfferDetailVaultContractDto) => OfferVaultContract;
2263
- /**
2264
- * Drops every proxy on a chain this SDK does not name, as
2265
- * `OfferToken.listFromDto` does: frontline publishes the full offer-token
2266
- * chain list, which runs ahead of {@link Chain}, and one unmodelled chain
2267
- * should not throw away the proxies the SDK can use.
2268
- */
2269
- listFromDto: (dtos: OfferDetailVaultContractDto[]) => OfferVaultContract[];
2270
- };
2271
- /**
2272
- * An offer as `GET /v1/offers/:id` serves it: the same union on `type` as
2273
- * {@link Offer}, each variant carrying only the fields that mean something
2274
- * for it. Narrow on `type` before reading anything beyond
2275
- * {@link OfferDetailBase}.
2276
- */
2277
- type OfferDetail = CoinListTokenSaleOfferDetail | SuperstateSwapOfferDetail | OndoSwapOfferDetail | CentrifugeVaultOfferDetail;
2278
- declare const OfferDetail: {
2279
- fromDto: (dto: OfferDetailDto) => OfferDetail;
2280
- };
2281
- type OfferOption = {
2282
- id: OfferOptionId;
2283
- slug: OfferOptionSlug;
2284
- bidIncrement: number | null;
2285
- floorPriceUsd: number | null;
2286
- minimumPurchaseUsd: number | null;
2287
- priceUsd: string | null;
2288
- saleAgreementUrl: string | null;
2289
- totalTokenSupply: number | null;
2290
- };
2291
- declare const OfferOption: {
2292
- fromDto: (dto: OfferDetailOptionDto) => OfferOption;
2293
- };
2294
- type FaqItem = {
2295
- question: string | null;
2296
- answer: string | null;
2297
- };
2298
- declare const FaqItem: {
2299
- fromDto: (dto: OfferDetailFaqDto) => FaqItem;
2300
- };
2301
- type Link = {
2302
- label: string | null;
2303
- url: string | null;
2304
- };
2305
- declare const Link: {
2306
- fromDto: (dto: OfferDetailLinkDto) => Link;
2307
- };
2308
- type TermItem = {
2309
- key: string | null;
2310
- value: string | null;
2311
- };
2312
- declare const TermItem: {
2313
- fromDto: (dto: OfferDetailTermDto) => TermItem;
2314
- };
2315
- type Milestone = {
2316
- name: string | null;
2317
- schedule: string | null;
2318
- status: 'completed' | 'active' | 'upcoming';
2319
- };
2320
- declare const Milestone: {
2321
- fromDto: (dto: OfferDetailMilestoneDto) => Milestone;
2322
- };
2323
-
2324
- /**
2325
- * The cursor-paginated envelope every list endpoint returns.
2326
- *
2327
- * Generic in its item type, so each resource pairs it with its own item DTO
2328
- * rather than declaring an envelope of its own.
2329
- */
2330
- interface PaginatedResponseDto<T> {
2331
- data: T[];
2332
- starting_after?: string;
2333
- starting_before?: string;
2334
- }
2335
-
2336
- type Cursor = Newtype<string, 'Cursor'>;
2337
- declare const Cursor: (value: string) => Cursor;
2338
- interface PaginatedResponse<T> {
2339
- data: T[];
2340
- startingAfter: Cursor | null;
2341
- startingBefore: Cursor | null;
2342
- }
2343
- declare const PaginatedResponse: {
2344
- fromDto: <A, B>(dto: PaginatedResponseDto<A>, itemMapper: (item: A) => B) => PaginatedResponse<B>;
2345
- /**
2346
- * For a mapper that decides the page as a whole - one that drops items it
2347
- * cannot map, such as `Offer.listFromDto` - rather than item by item. The
2348
- * cursors are the wire's either way: dropping an item changes what the
2349
- * page holds, not where the next page starts.
2350
- */
2351
- fromDtoPage: <A, B>(dto: PaginatedResponseDto<A>, pageMapper: (items: A[]) => B[]) => PaginatedResponse<B>;
2352
- };
2353
- /**
2354
- * Cursor-based pagination input used when requesting paginated API resources.
2355
- * Set `after` or `before` to navigate relative to a known cursor, and `limit`
2356
- * to control the maximum number of returned items.
2357
- */
2358
- interface PaginationParams {
2359
- before?: Cursor;
2360
- after?: Cursor;
2361
- limit?: number;
2362
- }
2363
- declare const PaginationParams: {
2364
- toQueryParams: (params: PaginationParams) => Record<string, QueryParamValue>;
2365
- };
2366
-
2367
- type ParticipationStatusDto = 'prepared' | 'pending' | 'submitted' | 'completed' | 'failed' | 'remit_submitted' | 'remitted' | 'remit_failed';
2368
- type ParticipationDto = {
2369
- object: 'participation';
2370
- id: string;
2371
- offer_id: string;
2372
- offer_option_id: string;
2373
- status: ParticipationStatusDto;
2374
- amount: string;
2375
- amount_string: string;
2376
- asset: AssetDto;
2377
- chain: string;
2378
- inserted_at: string | null | undefined;
2379
- updated_at: string | null | undefined;
2380
- wallet_address: string | null | undefined;
2381
- };
2382
- type CreateParticipationDto = {
2383
- offer_id: string;
2384
- offer_option_id: string;
2385
- chain: string;
2386
- wallet_address: string;
2387
- amount: string;
2388
- asset_id: string;
2389
- approval_transaction_hash: string | null | undefined;
2390
- };
2391
-
2392
- /** Unique identifier for a participation. */
2393
- type ParticipationId = Newtype<string, 'ParticipationId'>;
2394
- /** Casts a string into a typed {@link ParticipationId}. */
2395
- declare const ParticipationId: (value: string) => ParticipationId;
2396
- /** Blockchain identifier for where a participation is funded. */
2397
- type Blockchain = Newtype<string, 'Blockchain'>;
2398
- /** Casts a string into a typed {@link Blockchain}. */
2399
- declare const Blockchain: (value: string) => Blockchain;
2400
- /** Wallet address used for a participation. */
2401
- type WalletAddress = Newtype<`0x${string}`, 'WalletAddress'>;
2402
- /** Casts a `0x`-prefixed string into a typed {@link WalletAddress}. */
2403
- declare const WalletAddress: (value: `0x${string}`) => WalletAddress;
2404
- /** Possible participation lifecycle states returned by the API. */
2405
- type ParticipationStatus = ParticipationStatusDto;
2406
- /** Pagination params for listing participations, with an optional offer filter. */
2407
- interface ParticipationsPaginationParams extends PaginationParams {
2408
- offerId?: OfferId;
2409
- }
2410
- declare const ParticipationsPaginationParams: {
2411
- toQueryParams: (params: ParticipationsPaginationParams) => Record<string, QueryParamValue>;
2412
- };
2413
- /** Domain model for a participation returned by CoinList APIs. */
2414
- type Participation = {
2415
- /** Unique participation id. */
2416
- id: ParticipationId;
2417
- /** Parent offer id. */
2418
- offerId: OfferId;
2419
- /** Selected offer option id. */
2420
- offerOptionId: OfferOptionId;
2421
- /** Current processing status. */
2422
- status: ParticipationStatus;
2423
- /** Raw participation amount from API. */
2424
- amount: string;
2425
- /** Human-readable formatted amount from API. */
2426
- displayAmount: string;
2427
- /** Asset metadata for the participation amount. */
2428
- asset: Asset;
2429
- /** Funding chain identifier. */
2430
- chain: Blockchain;
2431
- /** Creation timestamp, if returned by API. */
2432
- insertedAt: Date | null;
2433
- /** Last update timestamp, if returned by API. */
2434
- updatedAt: Date | null;
2435
- /** Wallet used for participation, blank values normalized to null. */
2436
- walletAddress: WalletAddress | null;
2437
- };
2438
- declare const Participation: {
2439
- /** Maps API DTO shape into the SDK participation domain model. */
2440
- fromDto: (dto: ParticipationDto) => Participation;
2441
- };
2442
- /** Parameters required to create a new participation. */
2443
- type CreateParticipationParams = {
2444
- /** Offer to participate in. */
2445
- offerId: OfferId;
2446
- /** Offer option selected for participation. */
2447
- offerOptionId: OfferOptionId;
2448
- /** Blockchain for funding. */
2449
- chain: Blockchain;
2450
- /** Wallet address that funds the participation. */
2451
- walletAddress: WalletAddress;
2452
- /**
2453
- * Decimal token amount to participate with (e.g. `"100"` for 100 USDC), NOT
2454
- * raw base units. The backend rescales this by the asset's decimals to verify
2455
- * it against the on-chain approval allowance.
2456
- */
2457
- amount: string;
2458
- /** Funding asset id. */
2459
- assetId: AssetId;
2460
- /**
2461
- * Hash of the ERC-20 `approve()` transaction covering this participation.
2462
- * Required: the backend verifies it on-chain (sender, token, spender, and
2463
- * approved amount) before confirming the participation.
2464
- */
2465
- approvalTransactionHash: string;
2466
- };
2467
- declare const CreateParticipationParams: {
2468
- /** Maps participation creation params into API DTO payload. */
2469
- toDto: (params: CreateParticipationParams) => CreateParticipationDto;
2470
- };
2471
-
2472
- /**
2473
- * Read/write operations for token sales: listing and reading the current user's
2474
- * participations, and recording a new one. The on-chain execution flow
2475
- * (`executeTokenSale`) is layered on top of this in the client-side namespace.
2476
- */
2477
- interface CoinListTokenSaleNamespace {
2478
- /**
2479
- * Fetches all participations by iterating through every paginated response,
2480
- * optionally filtered by offer.
2481
- *
2482
- * Requires an authenticated user; throws {@link NotAuthenticatedError}
2483
- * otherwise.
2484
- */
2485
- list(offerId?: OfferId): Promise<Participation[]>;
2486
- /**
2487
- * Fetches a single page of participations, optionally filtered by offer.
2488
- *
2489
- * Requires an authenticated user; throws {@link NotAuthenticatedError}
2490
- * otherwise.
2491
- */
2492
- listPage(params: ParticipationsPaginationParams): Promise<PaginatedResponse<Participation>>;
2493
- /**
2494
- * Fetches a participation by id.
2495
- *
2496
- * Requires an authenticated user; throws {@link NotAuthenticatedError}
2497
- * otherwise.
2498
- */
2499
- get(id: ParticipationId): Promise<Participation>;
2500
- /**
2501
- * Records a participation with CoinList.
2502
- *
2503
- * Requires an authenticated user; throws {@link NotAuthenticatedError}
2504
- * otherwise.
2505
- */
2506
- createParticipation(params: CreateParticipationParams): Promise<Participation>;
2507
- }
2508
- declare class CoinListTokenSaleNamespaceImpl implements CoinListTokenSaleNamespace {
2509
- private readonly ctx;
2510
- protected readonly log: InternalLogger;
2511
- constructor(ctx: UniversalNamespaceContext);
2512
- list(offerId?: OfferId): Promise<Participation[]>;
2513
- listPage(params: ParticipationsPaginationParams): Promise<PaginatedResponse<Participation>>;
2514
- get(id: ParticipationId): Promise<Participation>;
2515
- createParticipation(params: CreateParticipationParams): Promise<Participation>;
2516
- }
2517
-
2518
- /**
2519
- * No `chain` on the read params: Ondo runs no sandbox, so every environment
2520
- * prices against Ondo production on Ethereum mainnet. Accepting a chain would
2521
- * let a caller ask for Sepolia and silently receive mainnet pricing.
2522
- * {@link BuildOndoSwapTransactionParams} is the exception, and says why.
2523
- */
2524
- type GetOndoTradingStatusParams = {
2525
- symbol: AssetSymbol;
2526
- /**
2527
- * Required, and deliberately not defaulted: `tradable` and both order caps
2528
- * describe this side only. Guessing `buy` would hand buy caps to someone
2529
- * sizing a sell. The endpoint answers 422 without it.
2530
- */
2531
- side: OrderBookSide;
2532
- };
2533
- /** How long Ondo should hold the price. Omit to take Ondo's own default. */
2534
- type OndoQuoteDuration = 'short' | 'long';
2535
- /**
2536
- * A quote is sized by the quantity or by the dollar amount. The endpoint takes
2537
- * exactly one; `getOndoQuote` sends whichever is present.
2538
- */
2539
- type OndoQuoteSize = {
2540
- tokenAmount: BlockchainAmount;
2541
- } | {
2542
- notionalValue: DecimalString;
2543
- };
2544
- type GetOndoQuoteParams = {
2545
- symbol: AssetSymbol;
2546
- side: OrderBookSide;
2547
- duration?: OndoQuoteDuration;
2548
- } & OndoQuoteSize;
2549
- /**
2550
- * What both builders take, before the one field whose meaning forks.
2551
- *
2552
- * There is no funding token and no asset here - frontline resolves both from
2553
- * the offer, because Ninshubur signs a request bound to them and a caller that
2554
- * could name them could have CoinList sign for a contract of its own. Which
2555
- * endpoint was called is what says which of the two `amount` counts.
2556
- *
2557
- * `chain` is required although the read params refuse it, because these name a
2558
- * real contract on a real chain rather than asking Ondo for a price.
2559
- */
2560
- type BuildOndoSwapParamsCore = {
2561
- symbol: AssetSymbol;
2562
- chain: EthereumChain;
2563
- /**
2564
- * The wallet that will *send* the transaction, and that receives the other
2565
- * token. The calldata is signed over it, so a transaction built for one
2566
- * wallet and broadcast by another reverts.
2567
- */
2568
- walletAddress: EvmWalletAddress;
2569
- };
2570
- /**
2571
- * What it takes to turn an indicative price into signed, fillable calldata for
2572
- * a purchase: `POST /v1/ondo/swap/buy`.
2573
- *
2574
- * Separate from {@link BuildOndoSellParams} although the fields match today,
2575
- * because `amount` is denominated in a different token on each - which is
2576
- * frontline's own reason for splitting the endpoint rather than taking a
2577
- * `side`. Sharing one type would re-merge the distinction the split exists to
2578
- * make, and the two will diverge the day either side gains a knob.
2579
- */
2580
- type BuildOndoBuyParams = BuildOndoSwapParamsCore & {
2581
- /**
2582
- * The **gross** deposit, in the base units of the funding token - the coin
2583
- * the user chose and approved.
2584
- *
2585
- * Sized by `amount` alone, with no `notionalValue` alternative: the calldata
2586
- * authorises a specific ERC-20 pull, so the number that ends up on chain has
2587
- * to be the number the caller meant rather than one derived from a dollar
2588
- * figure. CoinList's fee comes off it, and Ondo prices the remainder.
2589
- *
2590
- * Its `decimals` are also what the response's `spend_input_decimals` is
2591
- * checked against: frontline resolves the funding token from the offer
2592
- * rather than from this request, so the two are independent answers to the
2593
- * same question and a disagreement means the wrong token was sized.
2594
- */
2595
- amount: BlockchainAmount;
2596
- };
2597
- /**
2598
- * What it takes to turn an indicative price into signed, fillable calldata for
2599
- * a sale: `POST /v1/ondo/swap/sell`.
2600
- *
2601
- * See {@link BuildOndoBuyParams} for why this is its own type.
2602
- */
2603
- type BuildOndoSellParams = BuildOndoSwapParamsCore & {
2604
- /**
2605
- * The quantity of the **asset** to sell, in the asset's own base units - not
2606
- * in the funding token's, which is the same integer meaning something 1e12
2607
- * different.
2608
- *
2609
- * This is the figure the wallet must have approved: a sale delivers the
2610
- * asset, so the swap contract pulls it with `transferFrom` exactly as it
2611
- * pulls the deposit on a purchase.
2612
- *
2613
- * Its `decimals` are checked against the response's `spend_input_decimals`,
2614
- * which frontline reads on-chain from the asset on `chain`. The SDK's own
2615
- * answer comes from the quote, which resolves the asset on Ethereum mainnet,
2616
- * so on a testnet these are two independent resolutions of two different
2617
- * contracts - and the check is what says so.
2618
- */
2619
- amount: BlockchainAmount;
2620
- };
2621
-
2622
- /**
2623
- * Raw JSON models for the Ondo swap endpoints, mirroring
2624
- * `OndoSwapTradingStatus`, `OndoSwapQuote`, `OndoSwapBuy` and `OndoSwapSell`
2625
- * in frontline's OpenAPI schema. The two GETs are free to poll: neither spends
2626
- * an attestation, so a client may call them while the user edits an order. The
2627
- * two POSTs are not - each spends one and hands back signed calldata with a
2628
- * deadline.
2629
- *
2630
- * **One endpoint per side, and therefore one model per side.** The reads take
2631
- * a `side` and answer the same shape either way, so they stay single. The
2632
- * writes do not: a buy commits to an exact quantity, a sell to a range with a
2633
- * floor beneath it, and `amount` is the funding token on one and the asset on
2634
- * the other. Only the transport fields mean the same thing on both.
2635
- * `POST /v1/ondo/swap/transaction` survives as a deprecated alias of the buy
2636
- * under the old `pay_input_*` names; the SDK does not call it.
2637
- *
2638
- * Neither GET takes a `chain`. Ondo runs no sandbox, so every environment
2639
- * prices against Ondo production on Ethereum mainnet. The POSTs do carry one:
2640
- * they target a real contract, which on every environment but production is
2641
- * the Sepolia one with the mocked attestation.
2642
- */
2643
- /**
2644
- * Whether an asset can be traded right now, and the caps if so.
2645
- *
2646
- * Every cap is a *human decimal* string and is nullable — Ondo answers a
2647
- * restricted `/v1/limits/*` with a 403, which frontline turns into
2648
- * `tradable: false` and three nulls rather than an error. A null cap therefore
2649
- * means **Ondo restricted the asset, not that the cap is unlimited**. The
2650
- * response carries no `asset_decimals`, so there is nothing to scale
2651
- * `gross_max_tokens` by.
2652
- *
2653
- * There is no `reason` field. A restriction surfaces only as `tradable: false`
2654
- * plus the nulls; frontline keeps Ondo's reason codes to its own admin surface
2655
- * and does not forward them.
2656
- */
2657
- type OndoTradingStatusDto = {
2658
- object: 'ondo_swap_trading_status';
2659
- /** The `side` the request asked for, echoed back. */
2660
- side: 'buy' | 'sell';
2661
- /** For `side` only — an asset can be sellable while not buyable. */
2662
- tradable: boolean;
2663
- /** Whole tokens, for `side` only. E.g. `"100.000000000000000000"`. */
2664
- gross_max_tokens: string | null;
2665
- /** USD, for `side` only. E.g. `"1234.560000000000000000"`. */
2666
- gross_max_notional_value: string | null;
2667
- /**
2668
- * USD cap for the session the market is currently in, e.g. `"200000"`.
2669
- * Unlike the two above this comes from Ondo's sideless session endpoint, so
2670
- * it applies across buys and sells together.
2671
- */
2672
- gross_max_active_notional_value: string | null;
2673
- };
2674
- /** An indicative, size- and side-aware price for an Ondo asset. */
2675
- type OndoQuoteDto = {
2676
- object: 'ondo_swap_quote';
2677
- /** EIP-155 chain id. Always `"1"`, per the no-sandbox note above. */
2678
- chain_id: string;
2679
- symbol: string;
2680
- /** Ticker of the underlying security, e.g. `"AAPL"` for `"AAPLon"`. */
2681
- ticker: string;
2682
- asset_address: string;
2683
- /** Decimals of the `asset_address` contract. Scales `token_base_units`. */
2684
- asset_decimals: number;
2685
- side: 'buy' | 'sell';
2686
- /**
2687
- * Quantity of the asset in its smallest unit, as a raw uint256 string:
2688
- * `"5000000000000000000"` is 5 tokens at 18 decimals. Map it with
2689
- * `blockchainAmountFromRawOrThrow`, not `parseBlockchainAmountOrThrow`.
2690
- *
2691
- * Not to be confused with the `token_amount` *request* parameter, which is
2692
- * the same quantity in whole tokens. Ondo names both `tokenAmount`, 1e18
2693
- * apart, so echoing one back as the other is a real hazard.
2694
- */
2695
- token_base_units: string;
2696
- /**
2697
- * USD price of one whole token as a human decimal string, e.g.
2698
- * `"225.273151158540753535"`. Already scaled, so it needs none of the
2699
- * handling `token_base_units` does.
2700
- */
2701
- price: string;
2702
- };
2703
- /**
2704
- * The transport half of a built swap, identical on both sides.
2705
- *
2706
- * `spend_input_amount` is the only key here whose *token* depends on the side,
2707
- * and `spend_input_decimals` is what says at what scale. Everything below this
2708
- * point differs, which is why the two responses are two types rather than one
2709
- * with nullable halves.
2710
- *
2711
- * There is no `object` envelope and no `side` echo. `action` says what to do
2712
- * with the body, matching `AllowWalletResponseDto`; which trade it encodes is
2713
- * settled by the endpoint that was called, so nothing on the wire has to say
2714
- * it and nothing has to be checked against it.
2715
- */
2716
- type OndoSwapDtoCore = {
2717
- action: 'broadcast_transaction';
2718
- /** The swap contract the transaction is sent to. */
2719
- to: string;
2720
- /** ABI-encoded `swap(...)` calldata. Broadcast verbatim - never re-encode it. */
2721
- data: string;
2722
- /**
2723
- * When the signed calldata stops being accepted - RFC3339, e.g.
2724
- * `"2026-08-13T23:04:12Z"`. This is Ninshubur's `expiration`, which signs
2725
- * the same instant as the EIP-712 `deadline` in the calldata, so a
2726
- * transaction broadcast after it reverts.
2727
- */
2728
- expires_at: string;
2729
- /**
2730
- * Gross amount the wallet spends, echoing the requested `amount`, in the
2731
- * smallest unit of the token this side spends - the funding token on a buy,
2732
- * the asset on a sell. The approval is compared against this.
2733
- *
2734
- * Named `pay_input_amount` on the deprecated
2735
- * `POST /v1/ondo/swap/transaction`. `pay` was accurate only while a buy was
2736
- * the sole thing this could encode: a sell delivers the asset rather than
2737
- * paying for one.
2738
- */
2739
- spend_input_amount: string;
2740
- /**
2741
- * Decimals `spend_input_amount` is counted in.
2742
- *
2743
- * Frontline reads it on-chain from the token the side spends, which it
2744
- * resolves from the offer rather than from anything the caller sent. That
2745
- * makes it the only published scale for a token the request never names -
2746
- * and an independent answer to the one the SDK derived when it sized the
2747
- * order, which is why both builders compare the two.
2748
- *
2749
- * **The same key, two scales.** It counts whichever token the side spends:
2750
- * the funding token's 6 on a buy, the asset's 18 on a sell. Worth knowing
2751
- * before integrating against both.
2752
- */
2753
- spend_input_decimals: number;
2754
- };
2755
- /**
2756
- * Signed, ready-to-broadcast calldata for a purchase, and the amounts it
2757
- * commits to: `POST /v1/ondo/swap/buy`.
2758
- *
2759
- * Unlike {@link OndoQuoteDto} this **spends an attestation**, so it is not
2760
- * pollable: one call per order, plus one per user-requested refresh. Frontline
2761
- * also reads the wallet's allowance on the funding token before asking
2762
- * Ninshubur for anything, so an unapproved wallet is refused here rather than
2763
- * reverting on chain.
2764
- *
2765
- * The quantity is attested and exact, with no floor beneath it, which is what
2766
- * separates a buy from an {@link OndoSellDto}.
2767
- *
2768
- * **Carries no identity and no price.** No `chain_id`, `symbol`, `ticker` or
2769
- * `price` - the request named the first few and frontline drops Ninshubur's
2770
- * `price` deliberately, because `GET /v1/ondo/swap/quote` already publishes
2771
- * one under that name at a different scale. Anything the UI needs beyond the
2772
- * amounts comes from that GET or from the offer.
2773
- *
2774
- * Two scales are on the wire: `fee` and `notional_value` are in
2775
- * `spend_input_decimals`, and `receive_output_amount` is in
2776
- * `receive_output_decimals`. Neither is interchangeable with the quote's
2777
- * `asset_decimals`, which answers for a different number.
2778
- */
2779
- type OndoBuyDto = OndoSwapDtoCore & {
2780
- /**
2781
- * CoinList's cut of `spend_input_amount`, in the same units. `"0"` until
2782
- * ENG-1718 turns a fee on - frontline rejects a non-zero one today.
2783
- *
2784
- * Taken at execution rather than added on top, so the wallet never approves
2785
- * more than `spend_input_amount`.
2786
- */
2787
- fee: string;
2788
- /**
2789
- * `spend_input_amount` less `fee`, in `spend_input_decimals`: the part that
2790
- * reaches Ondo, what the quantity was priced against, and what the
2791
- * signature commits to.
2792
- */
2793
- notional_value: string;
2794
- /**
2795
- * Quantity of the asset the wallet receives, in the asset's smallest unit.
2796
- * Scale it by `receive_output_decimals`, not by the funding token's and not
2797
- * by {@link OndoQuoteDto}'s `asset_decimals`.
2798
- */
2799
- receive_output_amount: string;
2800
- /**
2801
- * Decimals `receive_output_amount` is counted in.
2802
- *
2803
- * Reported by whatever priced the quantity, rather than looked up from the
2804
- * asset. That is not the same number as {@link OndoQuoteDto}'s
2805
- * `asset_decimals`, which frontline resolves from its own catalogue: the two
2806
- * are allowed to disagree, and only this one answers for the quantity in
2807
- * this response.
2808
- */
2809
- receive_output_decimals: number;
2810
- };
2811
- /**
2812
- * Signed, ready-to-broadcast calldata for a sale, and the range it commits to:
2813
- * `POST /v1/ondo/swap/sell`.
2814
- *
2815
- * Like {@link OndoBuyDto} it **spends an attestation** and expires, so it is
2816
- * called once on confirmation and never on a timer. Frontline reads the
2817
- * wallet's allowance on the **asset** before signing - a sell delivers it -
2818
- * and refuses a short one with a 422 naming that address.
2819
- *
2820
- * **A sell commits to a range rather than a quantity.** Ondo settles through
2821
- * USDon before converting to the settlement token, so the response publishes
2822
- * what to expect and the floor the calldata enforces, each with the fee
2823
- * charged at it. There is no `notional_value`: a sell commits on the output
2824
- * side, so there is no fee-exclusive input to report and frontline declines to
2825
- * relate numbers Ninshubur did not relate.
2826
- *
2827
- * All four amounts below are in `receive_output_decimals`. The one amount that
2828
- * is not is `spend_input_amount`, in `spend_input_decimals` - see
2829
- * {@link OndoSwapDtoCore}.
2830
- *
2831
- * One thing the response does not say, and the calldata does: the floor signed
2832
- * into `data` is **gross** of CoinList's fee, so a caller decoding it finds a
2833
- * larger number than `minimum_quantity`. Both are correct; `minimum_quantity`
2834
- * is what the wallet actually receives.
2835
- */
2836
- type OndoSellDto = OndoSwapDtoCore & {
2837
- /**
2838
- * CoinList's cut at the expected outcome, in the settlement token. Already
2839
- * deducted from `expected_quantity` rather than charged on top of it.
2840
- *
2841
- * `"0"` until ENG-1718 turns a fee on - frontline rejects a non-zero one on
2842
- * either side today.
2843
- */
2844
- expected_fee: string;
2845
- /**
2846
- * What the sale is expected to return, **net of `expected_fee`**, in the
2847
- * settlement token's smallest unit.
2848
- *
2849
- * An expectation rather than a guarantee. What the contract enforces is
2850
- * {@link OndoSellDto.minimum_quantity}.
2851
- */
2852
- expected_quantity: string;
2853
- /**
2854
- * CoinList's cut at the floor, in the same units.
2855
- *
2856
- * A different number from `expected_fee` because the two are charged on
2857
- * different amounts - which is why frontline publishes both rather than one.
2858
- * This is the one to disclose worst-case cost with.
2859
- */
2860
- minimum_fee: string;
2861
- /**
2862
- * The least the wallet can receive, **net of `minimum_fee`**, in the same
2863
- * units. Below it the transaction reverts on chain.
2864
- *
2865
- * Frontline guarantees it is at most `expected_quantity` and greater than
2866
- * zero. The settlement lands somewhere between the two.
2867
- */
2868
- minimum_quantity: string;
2869
- /**
2870
- * Decimals both quantities and both fees are counted in, reported by
2871
- * whatever priced them rather than looked up from the token.
2872
- *
2873
- * Not the same number as {@link OndoQuoteDto}'s `asset_decimals`, which
2874
- * answers for the asset being sold rather than for the coin the proceeds
2875
- * arrive in.
2876
- */
2877
- receive_output_decimals: number;
2878
- };
2879
-
2880
- /**
2881
- * Whether an Ondo asset can be traded right now.
2882
- *
2883
- * The caps only mean anything while trading is open, so they live on the
2884
- * `tradable` branch. They stay {@link DecimalString} rather than
2885
- * {@link BlockchainAmount} because the response carries no `asset_decimals`:
2886
- * there is no honest exponent to attach, and the USD caps arrive with more
2887
- * fractional digits than a stablecoin has decimals.
2888
- *
2889
- * Each cap is independently nullable even when tradable — Ondo may open an
2890
- * asset for trading without publishing every limit.
2891
- *
2892
- * `side` is carried through from the response rather than dropped: the whole
2893
- * status describes one side, so a buy and a sell status are otherwise
2894
- * indistinguishable once a caller holds both.
2895
- */
2896
- type OndoTradingStatus = {
2897
- type: 'tradable';
2898
- side: OrderBookSide;
2899
- /** Largest order in whole tokens. */
2900
- grossMaxTokens: DecimalString | null;
2901
- /** Largest order in USD. */
2902
- grossMaxNotionalValue: DecimalString | null;
2903
- /** USD cap for the session the market is currently in. */
2904
- grossMaxActiveNotionalValue: DecimalString | null;
2905
- } | {
2906
- type: 'not-tradable';
2907
- side: OrderBookSide;
2908
- };
2909
- declare const OndoTradingStatus: {
2910
- fromDto: (dto: OndoTradingStatusDto) => OndoTradingStatus;
2911
- };
2912
- /**
2913
- * An indicative price for an Ondo asset, free to poll while the user edits an
2914
- * order.
2915
- *
2916
- * **No CoinList fee is applied to the quantity or the price.** Ondo prices
2917
- * exactly the amount asked for. A CoinList approval is fee-inclusive, so
2918
- * sizing a quote against one without netting the fee first overstates what the
2919
- * user receives. Showing a gross/net breakdown needs a CoinList swap
2920
- * contract's `preview`, and no such contract exists for Ondo yet.
2921
- *
2922
- * The quote carries no transaction to broadcast and no expiry. Building one is
2923
- * a separate endpoint per side that spends an attestation - see
2924
- * {@link OndoBuyTransaction} and {@link OndoSellTransaction}.
2925
- */
2926
- type OndoQuote = {
2927
- /** Always `ethereum_mainnet`: Ondo runs no sandbox in any environment. */
2928
- chain: EthereumChain;
2929
- ticker: Ticker;
2930
- /**
2931
- * Needed to approve or transfer the asset; the quote is the only source.
2932
- *
2933
- * **Resolved on Ethereum mainnet**, like everything else on this quote, and
2934
- * therefore not necessarily the contract the swap pulls from on the chain
2935
- * the order executes on. Frontline resolves that one per chain and publishes
2936
- * it nowhere, so on a testnet these are two different tokens. Tracked
2937
- * against the frontline stack that follows ENG-1756.
2938
- */
2939
- assetAddress: EvmContractAddress;
2940
- /**
2941
- * The asset as the quote resolves it, from frontline's own catalogue.
2942
- *
2943
- * Its `decimals` scale {@link tokenBaseUnits} and nothing else. They are
2944
- * **not** the scale of a built transaction's spend or output: those are
2945
- * reported by whatever priced them, the sources are allowed to disagree, and
2946
- * only the one that produced a number answers for it.
2947
- */
2948
- asset: Erc20Asset;
2949
- side: OrderBookSide;
2950
- tokenBaseUnits: BlockchainAmount;
2951
- /**
2952
- * USD price of one whole token. Unscaled because Ondo has already scaled it,
2953
- * and by USDon's 18 decimals rather than the stablecoin's 6 — re-scaling it
2954
- * by either would be wrong.
2955
- */
2956
- price: DecimalString;
2957
- };
2958
- declare const OndoQuote: {
2959
- fromDto: (dto: OndoQuoteDto) => OndoQuote;
2960
- };
2961
- /**
2962
- * The half of a built swap that both sides share: the calldata, its deadline,
2963
- * and what the wallet parts with.
2964
- *
2965
- * There is deliberately **no union over the two sides**. Each is built by its
2966
- * own endpoint and its own namespace method, so a caller never holds one
2967
- * without knowing which it is, and a union would only re-pose a question the
2968
- * call site had already answered. What is genuinely common lives here, and
2969
- * {@link executeOndoSwap} takes this rather than either arm - broadcasting
2970
- * knows nothing about the direction of the trade.
2971
- *
2972
- * `side` is not on this type but on each arm, as a literal the SDK authors
2973
- * from the method that was called. The wire stopped echoing one when the
2974
- * endpoint split, and it is still worth carrying: `OndoOrderPlaced` is a union
2975
- * the SDK builds from both, and that union needs a tag.
2976
- */
2977
- type OndoSwapTransactionCore = {
2978
- /**
2979
- * Broadcast as-is. The `to` is the swap contract, which is also the ERC-20
2980
- * spender the user must have approved.
2981
- */
2982
- tx: Tx;
2983
- /**
2984
- * When the calldata stops being accepted. A transaction broadcast after this
2985
- * reverts, so callers must compare against it before signing.
2986
- */
2987
- expiresAt: Date;
2988
- /**
2989
- * Gross amount the wallet spends, in the decimals of the token this side
2990
- * spends: the funding token on a buy, the asset on a sell.
2991
- *
2992
- * The same field at two scales, which is the whole reason the two sides are
2993
- * two types. It is also what the approval has to cover.
2994
- */
2995
- spendInputAmount: BlockchainAmount;
2996
- };
2997
- /**
2998
- * A signed, expiring purchase: a funding token in, an exact quantity of the
2999
- * asset out.
3000
- *
3001
- * Distinct from {@link OndoQuote} in three ways that matter: it costs an
3002
- * attestation to obtain, it expires, and it carries a {@link Tx} the wallet
3003
- * broadcasts verbatim. Treat it as single-use - once broadcast (or once
3004
- * `expiresAt` passes) it is spent, and a new one must be built.
3005
- *
3006
- * **The quantity is attested and exact, with no floor beneath it.** That is
3007
- * what separates it from an {@link OndoSellTransaction}, which commits to a
3008
- * range: nothing here is an estimate.
3009
- *
3010
- * **It carries no other identity.** No chain, ticker or asset: the endpoint
3011
- * publishes none of them, and inventing them from the request would assert
3012
- * what the server resolved rather than report it. What it does publish is the
3013
- * scale of every amount on it, so a caller needs nothing alongside it to read
3014
- * the numbers - only to name the assets, which the offer already does.
3015
- *
3016
- * It carries no price either. See `computeOndoBuyPrice`, which derives it from
3017
- * the amounts the response does carry - the price this transaction fills at,
3018
- * rather than an indicative one that has since moved.
3019
- */
3020
- type OndoBuyTransaction = OndoSwapTransactionCore & {
3021
- side: 'buy';
3022
- /**
3023
- * CoinList's cut, in `spendInputAmount`'s decimals. Zero until ENG-1718
3024
- * lands - frontline rejects a non-zero one on either side today.
3025
- *
3026
- * Taken at execution rather than added on top, so the approval never has to
3027
- * cover more than `spendInputAmount`.
3028
- */
3029
- fee: BlockchainAmount;
3030
- /**
3031
- * `spendInputAmount` less `fee`, in the same decimals: what Ondo priced, and
3032
- * the numerator of the fill price.
3033
- *
3034
- * Read from the response rather than subtracted here. Whether the fee comes
3035
- * off the deposit or goes on top of it is the server's definition to change,
3036
- * and a client that derives this cannot notice when it does.
3037
- */
3038
- notionalValue: BlockchainAmount;
3039
- /**
3040
- * Quantity of the asset the wallet receives, at the scale whatever priced it
3041
- * reported - not at the {@link OndoQuote}'s `asset.decimals`.
3042
- */
3043
- receiveOutputAmount: BlockchainAmount;
3044
- };
3045
- declare const OndoBuyTransaction: {
3046
- fromDto: (dto: OndoBuyDto) => OndoBuyTransaction;
3047
- };
3048
- /**
3049
- * One end of the range a sale commits to: what arrives, and what CoinList took
3050
- * to get it there.
3051
- *
3052
- * The two travel together because they are charged against each other -
3053
- * `quantity` is already **net** of `fee` - and because the pair a caller wants
3054
- * is always both halves of the same outcome. Grouping them is what makes
3055
- * "the expected quantity, less the fee at the floor" unrepresentable rather
3056
- * than merely wrong.
3057
- */
3058
- type OndoSellOutcome = {
3059
- /** What the wallet receives at this outcome, net of {@link fee}. */
3060
- quantity: BlockchainAmount;
3061
- /**
3062
- * CoinList's cut at this outcome, in the same decimals. Zero until ENG-1718
3063
- * lands - frontline rejects a non-zero one on either side today.
3064
- *
3065
- * Already deducted from {@link quantity} rather than charged on top of it.
3066
- */
3067
- fee: BlockchainAmount;
3068
- };
3069
- /**
3070
- * A signed, expiring sale: the asset in, a settlement coin out, somewhere
3071
- * between two published outcomes.
3072
- *
3073
- * Single-use and expiring for the same reasons as an {@link OndoBuyTransaction},
3074
- * and obtained the same way - one endpoint, one attestation.
3075
- *
3076
- * **A sale commits to a range, not a quantity.** Ondo settles through USDon
3077
- * before converting to the settlement token, so {@link expected} is what to
3078
- * expect and {@link minimum} is what the calldata enforces. A screen that
3079
- * shows only the first presents a firm-looking number the contract may
3080
- * legitimately fill below.
3081
- *
3082
- * There is deliberately no counterpart to a buy's `notionalValue`. A sale
3083
- * commits on the output side, so frontline reports no fee-exclusive input and
3084
- * refuses to relate numbers Ninshubur did not relate. What it does relate is
3085
- * each quantity to the fee beside it, which is why {@link OndoSellOutcome}
3086
- * pairs them.
3087
- *
3088
- * One thing this type cannot see: the floor signed into `tx.data` is gross of
3089
- * the fee, so a caller decoding the calldata finds a larger number than
3090
- * `minimum.quantity`. Both are correct; `minimum.quantity` is what the wallet
3091
- * actually receives.
3092
- */
3093
- type OndoSellTransaction = OndoSwapTransactionCore & {
3094
- side: 'sell';
3095
- /** What the sale is expected to return. An expectation, not a guarantee. */
3096
- expected: OndoSellOutcome;
3097
- /**
3098
- * The floor the calldata enforces. A fill below it reverts on chain, so this
3099
- * - not {@link expected} - is what a seller is actually guaranteed.
3100
- */
3101
- minimum: OndoSellOutcome;
3102
- };
3103
- declare const OndoSellTransaction: {
3104
- fromDto: (dto: OndoSellDto) => OndoSellTransaction;
3105
- };
3106
-
3107
- /**
3108
- * Ondo swap reads, plus the write that turns one into a fillable transaction.
3109
- *
3110
- * The two reads are free to poll - neither spends an attestation, so a client
3111
- * may call them while the user edits an order. The two builders are not:
3112
- * budget one call per order placed, plus one per refresh the user asks for.
3113
- *
3114
- * **One builder per side, mirroring the endpoints.** A purchase and a sale
3115
- * agree on how to broadcast and on nothing else: a purchase commits to an
3116
- * exact quantity, a sale to a range with a floor beneath it, and `amount` is
3117
- * the funding token on one and the asset on the other. A single method taking
3118
- * a `side` would have to return a union the caller then re-narrows, having
3119
- * already decided which trade it was placing.
3120
- *
3121
- * **No CoinList fee is applied to a read quote, and no read discloses one.**
3122
- * Ondo prices exactly the amount passed. A CoinList approval is fee-inclusive,
3123
- * so sizing a quote against a user's approval without subtracting the fee
3124
- * first overstates what they receive. A built transaction carries the fee
3125
- * explicitly, and it is zero until one lands (ENG-1718).
3126
- *
3127
- * Every method requires `AuthState === 'logged-in'` and throws
3128
- * {@link NotAuthenticatedError} otherwise.
3129
- */
3130
- interface OndoNamespace {
3131
- getTradingStatus(params: GetOndoTradingStatusParams): Promise<OndoTradingStatus>;
3132
- /**
3133
- * An indicative price for `params`' size, from Ondo's live market.
3134
- *
3135
- * Ondo refuses to quote while the market is closed or paused, or the asset
3136
- * is paused or closed for the session - including for about a minute at
3137
- * every US session change, when `getTradingStatus` may still have reported
3138
- * the asset tradable. The request then rejects with a 409 carrying
3139
- * `code: "not_tradable"`; tell it apart from a failure with
3140
- * {@link isOndoNotTradableError}. Retrying before the market opens fails the
3141
- * same way.
3142
- */
3143
- getQuote(params: GetOndoQuoteParams): Promise<OndoQuote>;
3144
- /**
3145
- * Builds a purchase for a specific wallet and deposit: spends an attestation
3146
- * and returns calldata to broadcast, valid until
3147
- * {@link OndoBuyTransaction.expiresAt}.
3148
- *
3149
- * The wallet must have approved the swap contract to spend `amount` of the
3150
- * offer's **funding token** first. Frontline reads that allowance before
3151
- * asking Ninshubur for anything, and rejects a short one with a 422 carrying
3152
- * `code: "insufficient_allowance"`. See `prepareBuy` on the client
3153
- * namespace, which approves and then builds, in that order.
3154
- *
3155
- * The tokens themselves are the offer's rather than the caller's to name.
3156
- */
3157
- buildBuyTransaction(params: BuildOndoBuyParams): Promise<OndoBuyTransaction>;
3158
- /**
3159
- * Builds a sale for a specific wallet and quantity: spends an attestation
3160
- * and returns calldata to broadcast, valid until
3161
- * {@link OndoSellTransaction.expiresAt}.
3162
- *
3163
- * The approval this one needs is on the **asset**, not on a stablecoin - a
3164
- * sale delivers the asset, so the swap contract pulls it with `transferFrom`
3165
- * exactly as it pulls the deposit on a purchase. Same 422 when it is short,
3166
- * with a message naming that address. See `prepareSell` on the client
3167
- * namespace.
3168
- *
3169
- * Returns a range rather than a quantity: Ondo settles through USDon before
3170
- * converting to the settlement token, so disclose
3171
- * {@link OndoSellTransaction.minimum} and not only `expected`.
3172
- */
3173
- buildSellTransaction(params: BuildOndoSellParams): Promise<OndoSellTransaction>;
3174
- }
3175
- declare class OndoNamespaceImpl implements OndoNamespace {
3176
- private readonly ctx;
3177
- protected readonly log: InternalLogger;
3178
- constructor(ctx: UniversalNamespaceContext);
3179
- getTradingStatus(params: GetOndoTradingStatusParams): Promise<OndoTradingStatus>;
3180
- getQuote(params: GetOndoQuoteParams): Promise<OndoQuote>;
3181
- buildBuyTransaction(params: BuildOndoBuyParams): Promise<OndoBuyTransaction>;
3182
- buildSellTransaction(params: BuildOndoSellParams): Promise<OndoSellTransaction>;
3183
- }
3184
-
3185
- /**
3186
- * Raw JSON models for the Superstate swap endpoints that are still backend
3187
- * calls.
3188
- *
3189
- * The contract *reads* no longer have DTOs: the SDK calls `status()`,
3190
- * `preview()`, `authorized()` and `outputToken()` on-chain through
3191
- * `@/universal/api/rpc`, so their wire shape is the ABI rather than JSON.
3192
- * Allow-listing a wallet stays here because it is a backend write, not a read.
3193
- */
3194
- type AllowWalletResponseDto = {
3195
- action: 'broadcast_transaction';
3196
- to: string;
3197
- data: string;
3198
- } | {
3199
- action: 'none';
3200
- already_allowed: boolean;
3201
- };
3202
-
3203
- /**
3204
- * A read-only quote for a swap: how much goes in, the protocol fee, and how
3205
- * much would come out. All amounts are raw on-chain integers (uint256).
3206
- */
3207
- type SwapPreview = {
3208
- inputAmount: Uint256;
3209
- fee: Uint256;
3210
- outputAmount: Uint256;
3211
- };
3212
- declare const SwapPreview: {
3213
- /** Maps the contract's `Preview { input, fee, output }` struct. */
3214
- fromContract: (preview: {
3215
- input: bigint;
3216
- fee: bigint;
3217
- output: bigint;
3218
- }) => SwapPreview;
3219
- };
3220
- /**
3221
- * The bitmask of operations a swap contract has paused, as `Operable.paused`
3222
- * reports it. Each bit is one operation level; swapping is
3223
- * {@link SWAP_LEVEL}.
3224
- *
3225
- * Meaningful only while the contract is paused, which is why it lives on that
3226
- * arm of {@link SwapStatus} alone: an active contract has nothing paused, and
3227
- * a stopped one is past caring which level was.
3228
- */
3229
- type PauseFlags = Newtype<number, 'PauseFlags'>;
3230
- declare const PauseFlags: (value: number) => PauseFlags;
3231
- /**
3232
- * The on-chain state of a swap contract, as `status()` reports it.
3233
- *
3234
- * - `active` - operating normally.
3235
- * - `paused` - one or more operations are suspended, and may be resumed.
3236
- * `pausedLevels` says which. **This does not by itself mean swapping is
3237
- * down**: a contract can pause an unrelated operation and keep swapping.
3238
- * Ask `isSwapAvailable` rather than reading the state.
3239
- * - `stopped` - permanently halted, and cannot be reactivated.
3240
- */
3241
- type SwapStatus = {
3242
- state: 'active';
3243
- } | {
3244
- state: 'paused';
3245
- pausedLevels: PauseFlags;
3246
- } | {
3247
- state: 'stopped';
3248
- };
3249
- declare const SwapStatus: {
3250
- /**
3251
- * Maps the contract's `Status { uint32 flags; State state }` struct, where
3252
- * `State` is `0 = Active | 1 = Paused | 2 = Stopped`.
3253
- *
3254
- * `flags` is carried onto the `paused` arm only. On the other two the
3255
- * contract sets it to a self-identifying marker rather than to information -
3256
- * so repeating it would invite a caller to read meaning into a constant.
3257
- *
3258
- * @throws ValidationError on a `state` outside the enum. A contract that has
3259
- * grown a fourth state is one the SDK does not model, and guessing `active`
3260
- * would let a halted swap read as a live one.
3261
- */
3262
- fromContract: (status: {
3263
- flags: number;
3264
- state: number;
3265
- }) => SwapStatus;
3266
- };
3267
- /**
3268
- * The backend's response to an allow-wallet request. Either the caller must
3269
- * broadcast an on-chain transaction to complete allow-listing, or nothing is
3270
- * required because the wallet is already allowed.
3271
- */
3272
- type AllowWalletResponse = {
3273
- action: 'broadcast_transaction';
3274
- to: EvmContractAddress;
3275
- data: HexEncodedTransactionData;
3276
- } | {
3277
- action: 'none';
3278
- alreadyAllowed: boolean;
3279
- };
3280
- declare const AllowWalletResponse: {
3281
- fromDto: (dto: AllowWalletResponseDto) => AllowWalletResponse;
3282
- };
3283
-
3284
- /** Parameters shared by contract reads scoped to a chain. */
3285
- type SwapContractRef = {
3286
- contractAddress: EvmContractAddress;
3287
- chain: EthereumChain;
3288
- };
3289
- type GetSwapAuthorizationParams = SwapContractRef & {
3290
- walletAddress: EvmWalletAddress;
3291
- };
3292
- type GetSwapPreviewParams = SwapContractRef & {
3293
- inputToken: EvmContractAddress;
3294
- amount: bigint;
3295
- };
3296
- type AllowWalletParams = {
3297
- offerId: OfferId;
3298
- walletAddress: EvmWalletAddress;
3299
- chain: EthereumChain;
3300
- signature: string;
3301
- };
3302
-
3303
- /**
3304
- * Read/write operations for the on-chain swap flow: quoting a swap, inspecting
3305
- * contract state, and proving/allow-listing wallet ownership.
3306
- *
3307
- * Every read here is a contract call the SDK makes itself. By default those go
3308
- * through CoinList's authenticated JSON-RPC proxy, so a logged-out caller gets
3309
- * the proxy's `401` - surfaced as a viem error wrapping the SDK's `HttpError`,
3310
- * not as `NotAuthenticatedError`, since viem re-wraps whatever a `Transport`
3311
- * throws. Point `Config.rpc` at your own node for this chain and no CoinList
3312
- * session is involved at all. `allowWallet` is the exception: it is a backend
3313
- * write and always needs one, and throws `NotAuthenticatedError` without.
3314
- */
3315
- interface SuperstateSwapNamespace {
3316
- /**
3317
- * Checks whether a wallet is authorized to swap against the given contract.
3318
- */
3319
- getAuthorization(params: GetSwapAuthorizationParams): Promise<boolean>;
3320
- /**
3321
- * Fetches a read-only quote for swapping `amount` of `inputToken`.
3322
- *
3323
- * The contract reverts rather than quoting when it is stopped, or when
3324
- * `inputToken` is not one it accepts, so this surfaces a viem
3325
- * `ContractFunctionRevertedError` naming the contract's own error. Check
3326
- * {@link getStatus} first if you would rather not provoke one.
3327
- */
3328
- getPreview(params: GetSwapPreviewParams): Promise<SwapPreview>;
3329
- /**
3330
- * Reads the current on-chain state of a swap contract. See
3331
- * {@link isSwapAvailable} before concluding that a `paused` contract cannot
3332
- * swap - the two are not the same question.
3333
- */
3334
- getStatus(params: SwapContractRef): Promise<SwapStatus>;
3335
- /**
3336
- * Reads the ERC-20 output token a swap contract pays out, with its metadata.
3337
- */
3338
- getOutputToken(params: SwapContractRef): Promise<Erc20Asset>;
3339
- /**
3340
- * Submits a signed wallet-ownership challenge to allow-list the wallet for
3341
- * an offer, identified by its offer id. Obtain the challenge from
3342
- * `WalletsNamespace.createOwnershipChallenge`.
3343
- *
3344
- * @throws NotAuthenticatedError without a logged-in user.
3345
- */
3346
- allowWallet(params: AllowWalletParams): Promise<AllowWalletResponse>;
3347
- }
3348
- declare class SuperstateSwapNamespaceImpl implements SuperstateSwapNamespace {
3349
- private readonly ctx;
3350
- protected readonly log: InternalLogger;
3351
- constructor(ctx: UniversalNamespaceContext);
3352
- getAuthorization(params: GetSwapAuthorizationParams): Promise<boolean>;
3353
- getPreview(params: GetSwapPreviewParams): Promise<SwapPreview>;
3354
- getStatus(params: SwapContractRef): Promise<SwapStatus>;
3355
- getOutputToken(params: SwapContractRef): Promise<Erc20Asset>;
3356
- allowWallet(params: AllowWalletParams): Promise<AllowWalletResponse>;
3357
- }
3358
-
3359
- /** Request body for `POST /v1/offers/:offer_id/addresses`. */
3360
- type CreateOfferOptionAddressDto = {
3361
- offer_option_id: string;
3362
- wallet_address: string;
3363
- chain: string;
3364
- signature: string;
3365
- };
3366
- /** Binding object returned by the `/v1/offers/:offer_id/addresses` resource. */
3367
- type OfferOptionAddressDto = {
3368
- id: string;
3369
- offer_option_id: string;
3370
- address: string;
3371
- protocol: WalletProtocol;
3372
- created_at: string;
3373
- };
3374
-
3375
- /** Unique identifier for a proven wallet binding on an offer option. */
3376
- type OfferOptionAddressId = Newtype<string, 'OfferOptionAddressId'>;
3377
- /** Casts a string into a typed {@link OfferOptionAddressId}. */
3378
- declare const OfferOptionAddressId: (value: string) => OfferOptionAddressId;
3379
- /**
3380
- * A user's external wallet, proven via a wallet-ownership challenge and bound
3381
- * to an offer option. Returned by the `/v1/offers/:offer_id/addresses` resource.
3382
- */
3383
- type OfferOptionAddress = {
3384
- /** Unique binding id. */
3385
- id: OfferOptionAddressId;
3386
- /** Offer option the wallet is bound to. */
3387
- offerOptionId: OfferOptionId;
3388
- /** The connected external wallet address. */
3389
- address: EvmWalletAddress;
3390
- /**
3391
- * Protocol the binding is scoped to. An EVM address binds once per option
3392
- * regardless of which EVM chain proved ownership.
3393
- */
3394
- protocol: WalletProtocol;
3395
- /** When the binding was created. */
3396
- createdAt: Date;
3397
- };
3398
- declare const OfferOptionAddress: {
3399
- /** Maps the API DTO into the SDK offer-option-address domain model. */
3400
- fromDto: (dto: OfferOptionAddressDto) => OfferOptionAddress;
3401
- };
3402
- /** Parameters required to connect a proven external wallet to an offer option. */
3403
- type ConnectExternalWalletParams = {
3404
- /** Offer the option belongs to. */
3405
- offerId: OfferId;
3406
- /** Offer option to bind the wallet to. */
3407
- offerOptionId: OfferOptionId;
3408
- /** External wallet address that was proven. */
3409
- walletAddress: EvmWalletAddress;
3410
- /** Chain the ownership was proven on. */
3411
- chain: EthereumChain;
3412
- /** Signature of the wallet-ownership challenge message. */
3413
- signature: Hex;
3414
- };
3415
- declare const ConnectExternalWalletParams: {
3416
- /** Maps connect-wallet params into the API DTO payload. */
3417
- toDto: (params: ConnectExternalWalletParams) => CreateOfferOptionAddressDto;
3418
- };
3419
-
3420
- /** Challenge kinds accepted by `POST /v1/wallet-ownership`. */
3421
- type WalletOwnershipChallengeTypeDto = 'plain' | 'siwe';
3422
- /**
3423
- * Request body for `POST /v1/wallet-ownership`. `challenge_type` defaults to
3424
- * `plain` on the backend; the SIWE fields (`domain`, `uri`, `statement`) are
3425
- * required only when `challenge_type` is `siwe` and must be absent otherwise.
3426
- */
3427
- type CreateWalletOwnershipChallengeDto = {
3428
- wallet_address: string;
3429
- chain: string;
3430
- challenge_type?: WalletOwnershipChallengeTypeDto;
3431
- domain?: string;
3432
- uri?: string;
3433
- statement?: string;
3434
- };
3435
- /** Response body for `POST /v1/wallet-ownership`. */
3436
- type WalletOwnershipChallengeDto = {
3437
- message: string;
3438
- expires_at: string;
3439
- };
3440
-
3441
- /** Fields common to every wallet-ownership challenge request. */
3442
- type WalletOwnershipChallengeParamsBase = {
3443
- /** Wallet address to prove ownership of. */
3444
- walletAddress: EvmWalletAddress;
3445
- /** Chain the wallet belongs to. */
3446
- chain: EthereumChain;
3447
- };
3448
- /**
3449
- * How the ownership challenge is framed: a plain message or a Sign-In With
3450
- * Ethereum challenge. Extracted as its own type so SDK consumers can pass it as
3451
- * a standalone param without reaching into the {@link CreateWalletOwnershipChallengeParams}
3452
- * union.
3453
- */
3454
- type WalletChallengeType = CreateWalletOwnershipChallengeParams['challengeType'];
3455
- /**
3456
- * A single-use ownership challenge returned by `POST /v1/wallet-ownership`.
3457
- * The consumer signs {@link message} with their wallet, then submits the
3458
- * signature to connect the wallet to an offer option.
3459
- */
3460
- type WalletOwnershipChallenge = {
3461
- /** The message the wallet must sign. */
3462
- message: string;
3463
- /** When the challenge expires and can no longer be consumed. */
3464
- expiresAt: Date;
3465
- };
3466
- declare const WalletOwnershipChallenge: {
3467
- /** Maps the API DTO into the SDK wallet-ownership-challenge domain model. */
3468
- fromDto: (dto: WalletOwnershipChallengeDto) => WalletOwnershipChallenge;
3469
- };
3470
- /**
3471
- * Parameters for requesting a wallet-ownership challenge. Modeled as a
3472
- * discriminated union on `challengeType` so a `siwe` challenge must carry
3473
- * `domain`/`uri`/`statement`, matching the backend contract at compile time.
3474
- */
3475
- type CreateWalletOwnershipChallengeParams = (WalletOwnershipChallengeParamsBase & {
3476
- /** A bare message the wallet signs. */
3477
- challengeType: 'plain';
3478
- }) | (WalletOwnershipChallengeParamsBase & {
3479
- /** Marks this as a Sign-In With Ethereum challenge. */
3480
- challengeType: 'siwe';
3481
- /** The requesting site's hostname (e.g. `example.com`). */
3482
- domain: string;
3483
- /** The requesting site's URI. */
3484
- uri: string;
3485
- /** Human-readable statement shown in the signing prompt. */
3486
- statement: string;
3487
- });
3488
- declare const CreateWalletOwnershipChallengeParams: {
3489
- /**
3490
- * Maps challenge-request params into the API DTO payload. The discriminated
3491
- * union guarantees SIWE fields are present exactly when `challengeType` is
3492
- * `siwe`, so the mapping narrows on the discriminant.
3493
- */
3494
- toDto: (params: CreateWalletOwnershipChallengeParams) => CreateWalletOwnershipChallengeDto;
3495
- };
3496
-
3497
- type ListOptionAddressesParams = {
3498
- offerId: OfferId;
3499
- /** Offer option whose bindings to list. */
3500
- offerOptionId: OfferOptionId;
3501
- };
3502
- type RemoveOptionAddressParams = {
3503
- offerId: OfferId;
3504
- /** Binding to remove, as returned by {@link WalletsNamespace.list}. */
3505
- addressId: OfferOptionAddressId;
3506
- };
3507
- /**
3508
- * The user's external wallets: proving ownership of one, binding it to an
3509
- * offer option, and managing those bindings.
3510
- *
3511
- * Ownership proof is a provider-agnostic primitive — the swap flow uses the
3512
- * same challenge to allow-list a wallet — so it lives here rather than being
3513
- * duplicated per product namespace.
3514
- *
3515
- * Every method requires an authenticated user and throws
3516
- * {@link NotAuthenticatedError} otherwise.
3517
- */
3518
- interface WalletsNamespace {
3519
- /**
3520
- * Creates a single-use challenge the user signs to prove they control a
3521
- * wallet. Supports both `plain` and `siwe` challenges. Pass the signature of
3522
- * the returned {@link WalletOwnershipChallenge.message} to
3523
- * {@link connectExternal}.
3524
- */
3525
- createOwnershipChallenge(params: CreateWalletOwnershipChallengeParams): Promise<WalletOwnershipChallenge>;
3526
- /**
3527
- * Binds a proven external wallet to an offer option, using a signature of a
3528
- * challenge from {@link createOwnershipChallenge}.
3529
- */
3530
- connectExternal(params: ConnectExternalWalletParams): Promise<OfferOptionAddress>;
3531
- /**
3532
- * Lists the user's proven wallet bindings for one offer option — the single
3533
- * bound address for an `external_wallet` option, or every allow-listed
3534
- * wallet for a `whitelisted_wallet` option.
3535
- */
3536
- list(params: ListOptionAddressesParams): Promise<OfferOptionAddress[]>;
3537
- /**
3538
- * Removes one of the user's wallet bindings and returns the removed binding.
3539
- */
3540
- remove(params: RemoveOptionAddressParams): Promise<OfferOptionAddress>;
3541
- }
3542
- declare class WalletsNamespaceImpl implements WalletsNamespace {
3543
- private readonly ctx;
3544
- private readonly log;
3545
- constructor(ctx: UniversalNamespaceContext);
3546
- createOwnershipChallenge(params: CreateWalletOwnershipChallengeParams): Promise<WalletOwnershipChallenge>;
3547
- connectExternal(params: ConnectExternalWalletParams): Promise<OfferOptionAddress>;
3548
- list(params: ListOptionAddressesParams): Promise<OfferOptionAddress[]>;
3549
- remove(params: RemoveOptionAddressParams): Promise<OfferOptionAddress>;
3550
- }
3551
-
3552
- type DocumentSubmissionStatusDto = 'INITIALIZED' | 'SENT' | 'VIEWED' | 'COMPLETED' | 'DECLINED' | 'EXPIRED';
3553
- type DocumentFormTypeDto = 'w8_ben' | 'w8_ben_e';
3554
- type DocumentSubmissionDto = {
3555
- object: 'document_submission';
3556
- status: DocumentSubmissionStatusDto;
3557
- form_type: DocumentFormTypeDto;
3558
- };
3559
-
3560
- /** Document types that can be signed via {@link CoinListClient.submitDocument}. */
3561
- type DocumentType = 'tax_certification';
3562
- /** Signing-state machine status for a document submission. */
3563
- type DocumentSubmissionStatus = DocumentSubmissionStatusDto;
3564
- /** The tax form derived from the entity's kind (individual vs company/trust). */
3565
- type DocumentFormType = DocumentFormTypeDto;
3566
- /** Result of starting (or resuming) a document signing submission. */
3567
- type DocumentSubmission = {
3568
- status: DocumentSubmissionStatus;
3569
- formType: DocumentFormType;
3570
- };
3571
- declare const DocumentSubmission: {
3572
- fromDto: (dto: DocumentSubmissionDto) => DocumentSubmission;
3573
- };
3574
-
3575
- type KycTokenDto = {
3576
- object: 'kyc_token';
3577
- token: string;
3578
- };
3579
-
3580
- /**
3581
- * Sumsub verification level name. Determines which screens the Sumsub WebSDK
3582
- * shows (levels are configured in the Sumsub dashboard). The backend
3583
- * prescribes the level (and whether the applicant must be reset first) in the
3584
- * requirement statuses response — clients never compute levels themselves.
3585
- */
3586
- type KycLevelName = string;
3587
- /** Short-lived Sumsub WebSDK access token scoped to the current user. */
3588
- type KycToken = {
3589
- token: string;
3590
- };
3591
- declare const KycToken: {
3592
- fromDto: (dto: KycTokenDto) => KycToken;
3593
- };
3594
-
3595
- type PiiKindDto = 'person' | 'company';
3596
- type PiiJurisdictionDto = {
3597
- iso_2: string;
3598
- name: string | null;
3599
- };
3600
- type PiiAddressDto = {
3601
- street: string | null;
3602
- city: string | null;
3603
- state: string | null;
3604
- postal_code: string | null;
3605
- country: string | null;
3606
- };
3607
- type PiiDto = {
3608
- object: 'user_pii';
3609
- kind: PiiKindDto;
3610
- full_legal_name: string | null;
3611
- date_of_birth: string | null;
3612
- jurisdiction: PiiJurisdictionDto | null;
3613
- tax_id: string | null;
3614
- permanent_address: PiiAddressDto;
3615
- };
3616
-
3617
- /** Whether the PII belongs to an individual or a company/trust entity. */
3618
- type PiiKind = PiiKindDto;
3619
- /** ISO 3166-1 alpha-2 country code (e.g. `'US'`). */
3620
- type Iso2CountryCode = Newtype<string, 'Iso2CountryCode'>;
3621
- declare const Iso2CountryCode: (value: string) => Iso2CountryCode;
3622
- /** Jurisdiction derived from the entity's address country. */
3623
- type PiiJurisdiction = {
3624
- iso2: Iso2CountryCode;
3625
- name: string | null;
3626
- };
3627
- declare const PiiJurisdiction: {
3628
- fromDto: (dto: PiiJurisdictionDto) => PiiJurisdiction;
3629
- };
3630
- /** Permanent address on file for the entity. */
3631
- type PiiAddress = {
3632
- street: string | null;
3633
- city: string | null;
3634
- state: string | null;
3635
- postalCode: string | null;
3636
- country: string | null;
3637
- };
3638
- declare const PiiAddress: {
3639
- fromDto: (dto: PiiAddressDto) => PiiAddress;
3640
- };
3641
- /**
3642
- * The current user's PII, used to pre-fill tax forms such as the W-8BEN.
3643
- * Fields the entity hasn't provided are `null`.
3644
- */
3645
- type Pii = {
3646
- kind: PiiKind;
3647
- fullLegalName: string | null;
3648
- dateOfBirth: string | null;
3649
- jurisdiction: PiiJurisdiction | null;
3650
- taxId: string | null;
3651
- permanentAddress: PiiAddress;
3652
- };
3653
- declare const Pii: {
3654
- fromDto: (dto: PiiDto) => Pii;
3655
- };
3656
-
3657
- type RequirementTypeDto = 'kyc_approved' | 'external_wallet' | 'whitelisted_wallet' | 'jurisdiction' | 'accreditation' | 'document';
3658
- type RequirementDto = {
3659
- object: 'requirement';
3660
- id: string;
3661
- type: RequirementTypeDto;
3662
- details: Record<string, unknown> | null;
3663
- };
3664
- type RequirementStatusValueDto = 'not_started' | 'in_progress' | 'action_needed' | 'completed' | 'rejected';
3665
- type RequirementActionNeededReasonDto = 'kyc_not_verified' | 'update_pii_data';
3666
- /**
3667
- * Object form of a requirement status, used when the status carries extra
3668
- * data: the action-needed reason and/or the Sumsub flow that resolves the
3669
- * requirement (kyc_level + kyc_reset, forwarded to the kyc-token endpoint).
3670
- */
3671
- type RequirementStatusObjectDto = {
3672
- status: RequirementStatusValueDto;
3673
- action?: RequirementActionNeededReasonDto;
3674
- kyc_level?: string;
3675
- kyc_reset?: boolean;
3676
- };
3677
- type RequirementStatusesDto = {
3678
- object: 'requirement_statuses';
3679
- offer_id: string;
3680
- statuses: Record<string, RequirementStatusValueDto | RequirementStatusObjectDto>;
3681
- };
3682
-
3683
- type RequirementId = Newtype<string, 'RequirementId'>;
3684
- declare const RequirementId: (value: string) => RequirementId;
3685
- type RequirementType = RequirementTypeDto;
3686
- type RequirementStatusValue = RequirementStatusValueDto;
3687
- type RequirementActionNeededReason = RequirementActionNeededReasonDto;
3688
- type Requirement = {
3689
- id: RequirementId;
3690
- type: RequirementType;
3691
- details: Record<string, unknown> | null;
3692
- };
3693
- declare const Requirement: {
3694
- fromDto: (dto: RequirementDto) => Requirement;
3695
- };
3696
- type RequirementStatusInfo = {
3697
- id: RequirementId;
3698
- status: RequirementStatusValue;
3699
- /** Why the requirement needs action (KYC-backed requirements only). */
3700
- action: RequirementActionNeededReason | null;
3701
- /**
3702
- * The Sumsub verification level that resolves this requirement, prescribed
3703
- * by the backend. Present exactly when an inline Sumsub flow can be started.
3704
- */
3705
- kycLevel?: KycLevelName;
3706
- /**
3707
- * Whether the Sumsub applicant must be reset before starting the flow
3708
- * (redoing an already-approved level, e.g. to update stale PII). Forward to
3709
- * the kyc-token request as-is.
3710
- */
3711
- kycReset?: boolean;
3712
- };
3713
- declare const RequirementStatusInfo: {
3714
- fromStatusesDto: (dto: RequirementStatusesDto) => RequirementStatusInfo[];
3715
- };
3716
-
3717
- type CreateKycTokenParams = {
3718
- /**
3719
- * Sumsub verification level to run. Defaults to the backend's standard
3720
- * level.
3721
- */
3722
- levelName?: KycLevelName;
3723
- /**
3724
- * Resets the Sumsub applicant first, so an already-approved level can be
3725
- * executed again (e.g. to update stale PII). Pass the `kycReset` value from
3726
- * the requirement status, and never on mid-flow token refreshes.
3727
- */
3728
- reset?: boolean;
3729
- };
3730
- type SubmitDocumentParams = {
3731
- /** Currently only `tax_certification` (W-8BEN / W-8BEN-E). */
3732
- documentType: DocumentType;
3733
- /**
3734
- * Signing-form values keyed by the document's DocuSeal field names,
3735
- * forwarded verbatim to pre-fill the document.
3736
- */
3737
- fields: Record<string, string>;
3738
- };
3739
- /**
3740
- * Everything a user must satisfy before they can participate in an offer:
3741
- * reading the checklist and its live statuses, and the operations that satisfy
3742
- * individual requirements — identity verification (KYC) and tax-document
3743
- * signing.
3744
- *
3745
- * Wallet requirements (`external_wallet`, `whitelisted_wallet`) are satisfied
3746
- * through `WalletsNamespace` instead, since wallet proofs are also used
3747
- * outside the requirements flow.
3748
- *
3749
- * Every method requires an authenticated user and throws
3750
- * {@link NotAuthenticatedError} otherwise.
3751
- */
3752
- interface RequirementsNamespace {
3753
- /**
3754
- * Fetches the requirements for every option of an offer, grouped by option
3755
- * id. This is the definition of the checklist; {@link statuses} tells you
3756
- * where the user stands against it.
3757
- */
3758
- forOffer(offerId: OfferId): Promise<Record<OfferOptionId, Requirement[]>>;
3759
- /**
3760
- * Fetches the current user's status for each requirement of an offer.
3761
- */
3762
- statuses(offerId: OfferId): Promise<RequirementStatusInfo[]>;
3763
- /**
3764
- * Creates a short-lived Sumsub WebSDK access token so an identity
3765
- * verification (KYC) flow can be started, e.g. by the `IdentityVerification`
3766
- * component.
3767
- */
3768
- createKycToken(params?: CreateKycTokenParams): Promise<KycToken>;
3769
- /**
3770
- * Fetches the current user's PII, used to pre-fill tax forms such as the
3771
- * W-8BEN. Fields the entity hasn't provided are `null`.
3772
- */
3773
- getPii(): Promise<Pii>;
3774
- /**
3775
- * Starts (or resumes) a document signing submission.
3776
- */
3777
- submitDocument(params: SubmitDocumentParams): Promise<DocumentSubmission>;
3778
- }
3779
- declare class RequirementsNamespaceImpl implements RequirementsNamespace {
3780
- protected readonly ctx: UniversalNamespaceContext;
3781
- protected readonly log: InternalLogger;
3782
- constructor(ctx: UniversalNamespaceContext);
3783
- forOffer(offerId: OfferId): Promise<Record<OfferOptionId, Requirement[]>>;
3784
- statuses(offerId: OfferId): Promise<RequirementStatusInfo[]>;
3785
- createKycToken(params?: CreateKycTokenParams): Promise<KycToken>;
3786
- getPii(): Promise<Pii>;
3787
- submitDocument(params: SubmitDocumentParams): Promise<DocumentSubmission>;
3788
- }
3789
-
3790
- /**
3791
- * Reads over CoinList's offers: the catalogue a user can browse, and the full
3792
- * detail of a single offer.
3793
- *
3794
- * Every method requires an authenticated user and throws
3795
- * {@link NotAuthenticatedError} otherwise. On the server, the same reads are
3796
- * additionally available with an app-level token — see
3797
- * `ServerOffersNamespace`.
3798
- */
3799
- interface OffersNamespace {
3800
- /**
3801
- * Fetches every offer, iterating through all pages. Prefer {@link listPage}
3802
- * when you render a paginated list yourself.
3803
- */
3804
- list(): Promise<Offer[]>;
3805
- /**
3806
- * Fetches a single page of offers. Pass the previous response's
3807
- * `startingAfter` as `after` to advance.
3808
- */
3809
- listPage(params: PaginationParams): Promise<PaginatedResponse<Offer>>;
3810
- /**
3811
- * Fetches the full detail of one offer, including its options. Note this
3812
- * returns {@link OfferDetail} — a richer model than the {@link Offer}
3813
- * summaries {@link list} returns.
3814
- */
3815
- get(id: OfferId): Promise<OfferDetail>;
3816
- }
3817
- declare class OffersNamespaceImpl implements OffersNamespace {
3818
- private readonly ctx;
3819
- private readonly log;
3820
- constructor(ctx: UniversalNamespaceContext);
3821
- list(): Promise<Offer[]>;
3822
- listPage(params: PaginationParams): Promise<PaginatedResponse<Offer>>;
3823
- get(id: OfferId): Promise<OfferDetail>;
3824
- }
3825
-
3826
- /**
3827
- * Raw JSON from the token registry (Nabu), a static CDN serving token display
3828
- * metadata. It is a separate backend from frontline: responses omit optional
3829
- * fields rather than sending `null`, and may grow unknown fields at any time;
3830
- * we only read the fields named here.
3831
- */
3832
- type NabuLogoImageDto = {
3833
- url: string;
3834
- width: number;
3835
- height: number;
3836
- };
3837
- /**
3838
- * A logo is either a single vector (valid at any size) or a dimensioned
3839
- * raster original plus pre-scaled variants at ascending widths.
3840
- */
3841
- type NabuLogoDto = {
3842
- kind: 'VECTOR';
3843
- url: string;
3844
- } | {
3845
- kind: 'RASTER';
3846
- original: NabuLogoImageDto;
3847
- variants: NabuLogoImageDto[];
3848
- };
3849
- /** One token from the registry's `/{chain}/token/{address}` route. */
3850
- type NabuTokenDto = {
3851
- data_version: string;
3852
- schema_version: number;
3853
- chain: string;
3854
- protocol: string;
3855
- chain_id: number;
3856
- kind: string;
3857
- name: string;
3858
- symbol: string;
3859
- decimals: number;
3860
- logo: NabuLogoDto;
3861
- logo_dark?: NabuLogoDto;
3862
- coingecko_id?: string;
3863
- teller_code?: string;
3864
- address: string;
3865
- };
3866
- /**
3867
- * One asset inside a chain snapshot. The snapshot mixes the chain's native
3868
- * coin (`kind: 'COIN'`, no address) with its tokens (`kind: 'TOKEN'`), so
3869
- * `address` is optional here where {@link NabuTokenDto} requires it.
3870
- */
3871
- type NabuChainAssetDto = {
3872
- kind: string;
3873
- name: string;
3874
- symbol: string;
3875
- decimals: number;
3876
- logo: NabuLogoDto;
3877
- logo_dark?: NabuLogoDto;
3878
- address?: string;
3879
- };
3880
- /** The registry's `/{chain}/assets.json` route: one chain, all its assets. */
3881
- type NabuChainAssetsDto = {
3882
- data_version: string;
3883
- schema_version: number;
3884
- chain: string;
3885
- protocol: string;
3886
- assets: NabuChainAssetDto[];
3887
- };
3888
- /** The registry's `/assets.json` route: the complete snapshot, every chain. */
3889
- type NabuRegistryDto = {
3890
- data_version: string;
3891
- schema_version: number;
3892
- chains: Array<{
3893
- chain: string;
3894
- protocol: string;
3895
- assets: NabuChainAssetDto[];
3896
- }>;
3897
- };
3898
-
3899
- /**
3900
- * An absolute URL to a logo image in the token registry. Registry image URLs
3901
- * are content-fingerprinted and served immutable, so a value is safe to cache
3902
- * for as long as you hold it.
3903
- */
3904
- type TokenLogoUrl = Newtype<string, 'TokenLogoUrl'>;
3905
- declare const TokenLogoUrl: (value: string) => TokenLogoUrl;
3906
- type TokenLogoImage = {
3907
- url: TokenLogoUrl;
3908
- width: number;
3909
- height: number;
3910
- };
3911
- /**
3912
- * `VECTOR` is a single SVG. `RASTER` has webp variants at 32/64/128/256/512px
3913
- * widths (never wider than the original): use the smallest one that covers
3914
- * your render size, or `original` if none does.
3915
- */
3916
- type TokenLogo = {
3917
- kind: 'VECTOR';
3918
- url: TokenLogoUrl;
3919
- } | {
3920
- kind: 'RASTER';
3921
- original: TokenLogoImage;
3922
- variants: TokenLogoImage[];
3923
- };
3924
- declare const TokenLogo: {
3925
- /** `baseUrl` is the registry origin; registry URLs are root-relative. */
3926
- fromDto: (dto: NabuLogoDto, baseUrl: string) => TokenLogo;
3927
- };
3928
- /**
3929
- * Display metadata for one token, from CoinList's public token registry.
3930
- *
3931
- * Keyed by `(chain, address)` — never by symbol, which can collide. The
3932
- * registry is curated: a token missing from it is an expected answer, not an
3933
- * error, so lookups return `null` rather than throwing.
3934
- */
3935
- type TokenMetadata = {
3936
- identifier: TokenIdentifier;
3937
- name: string;
3938
- symbol: AssetSymbol;
3939
- decimals: AssetDecimals;
3940
- logo: TokenLogo;
3941
- /** Dark-theme logo; `null` when the registry configures none. */
3942
- logoDark: TokenLogo | null;
3943
- };
3944
- declare const TokenMetadata: {
3945
- /** `baseUrl` is the registry origin; registry logo URLs are root-relative. */
3946
- fromDto: (dto: NabuTokenDto, baseUrl: string) => TokenMetadata;
3947
- /**
3948
- * Maps the complete registry snapshot to every token it lists across the
3949
- * chains this SDK models, skipping native coins and chains outside
3950
- * {@link EthereumChain} (e.g. Solana) rather than failing on them — the
3951
- * registry may serve chains ahead of the SDK's type surface.
3952
- */
3953
- fromRegistryDto: (dto: NabuRegistryDto, baseUrl: string) => TokenMetadata[];
3954
- /**
3955
- * Maps a chain snapshot to the tokens it lists, skipping the chain's native
3956
- * coin (`kind: 'COIN'`, no contract address).
3957
- */
3958
- fromChainAssetsDto: (dto: NabuChainAssetsDto, baseUrl: string) => TokenMetadata[];
3959
- };
3960
-
3961
- /**
3962
- * Token display metadata — name, symbol, decimals, and logos — from
3963
- * CoinList's public token registry, keyed by {@link TokenIdentifier} (the
3964
- * same chain + address pairs `Offer.tokens` carries).
3965
- *
3966
- * Unlike the other namespaces, this one is public: no method requires an
3967
- * authenticated user, and nothing here touches the CoinList API — reads go to
3968
- * the registry's CDN.
3969
- */
3970
- interface TokensNamespace {
3971
- /**
3972
- * Fetches metadata for one token. Returns `null` when the registry does not
3973
- * list the token — the registry is curated, so callers must fall back to
3974
- * their own display defaults rather than treat this as an error.
3975
- */
3976
- get(token: TokenIdentifier): Promise<TokenMetadata | null>;
3977
- /**
3978
- * Fetches every token the registry lists, in one request: the complete
3979
- * snapshot with no `chain`, or one chain's snapshot with it. Prefer this
3980
- * over calling {@link get} in a loop when displaying a catalogue — two
3981
- * hundred tokens across three chains is still a single download.
3982
- *
3983
- * The complete snapshot spans every chain the registry knows; tokens on
3984
- * chains this SDK does not model (e.g. Solana) are left out of the result.
3985
- *
3986
- * Unlike {@link get}, a missing snapshot throws rather than returning `[]`:
3987
- * the registry always publishes the complete snapshot and one per chain it
3988
- * knows, so an absence is a deployment problem, not an empty catalogue.
3989
- */
3990
- list(chain?: EthereumChain): Promise<TokenMetadata[]>;
3991
- }
3992
- declare class TokensNamespaceImpl implements TokensNamespace {
3993
- private readonly api;
3994
- private readonly log;
3995
- /**
3996
- * Takes the registry origin rather than a `UniversalNamespaceContext`: the
3997
- * registry is unauthenticated and on its own host, so the frontline sender
3998
- * and the auth check would both be dead weight here.
3999
- */
4000
- constructor(baseUrl: string, logger?: Logger | null);
4001
- get(token: TokenIdentifier): Promise<TokenMetadata | null>;
4002
- list(chain?: EthereumChain): Promise<TokenMetadata[]>;
4003
- }
4004
-
4005
- /**
4006
- * An instant: milliseconds since the Unix epoch, as `Date.now()` reads it.
4007
- * Distinct from {@link Millis}, a duration, so an instant cannot be passed
4008
- * where a timeout is expected or the other way round.
4009
- */
4010
- type EpochMillis = Newtype<number, 'EpochMillis'>;
4011
- declare const EpochMillis: {
4012
- /**
4013
- * @throws {@link ValidationError} unless `value` is an integer a `Date` can
4014
- * represent: at most {@link MAX_EPOCH_MILLIS} either side of the epoch.
4015
- */
4016
- of: (value: number) => EpochMillis;
4017
- /** The wall clock. Code that needs the time takes a `TimeEff` instead. */
4018
- now: () => EpochMillis;
4019
- /** @throws {@link ValidationError} for an invalid `Date`. */
4020
- fromDate: (date: Date) => EpochMillis;
4021
- /** How long after `from` the instant `to` is; negative if it is before. */
4022
- elapsed: (from: EpochMillis, to: EpochMillis) => Millis;
4023
- plus: (at: EpochMillis, duration: Millis) => EpochMillis;
4024
- };
4025
- /**
4026
- * A duration in milliseconds. May be negative: the gap between two instants
4027
- * read off a wall clock that stepped back in between.
4028
- */
4029
- type Millis = Newtype<number, 'Millis'>;
4030
- declare const Millis: {
4031
- of: (value: number) => Millis;
4032
- };
4033
- /** A duration in whole, non-negative seconds. */
4034
- type Seconds = Newtype<number, 'Seconds'>;
4035
- declare const Seconds: {
4036
- /**
4037
- * @throws {@link ValidationError} unless `value` is a non-negative integer.
4038
- */
4039
- of: (value: number) => Seconds;
4040
- toMillis: (value: Seconds) => Millis;
4041
- };
4042
- /**
4043
- * Whether `expiresAt` has passed at `now`, counting it as passed `buffer`
4044
- * early. The boundary instant itself counts as expired.
4045
- */
4046
- declare function isExpired({ expiresAt, now, buffer, }: {
4047
- expiresAt: EpochMillis;
4048
- now: EpochMillis;
4049
- buffer?: Millis;
4050
- }): boolean;
4051
-
4052
- export { AsyncOfferDetail as $, AuthorizationCode as A, BlockchainAmount as B, CodeVerifier as C, type OAuthAccessToken as D, type Erc20Namespace as E, type OffersNamespace as F, DecimalString as G, StablecoinSymbol as H, type Erc20Asset as I, OfferDetail as J, TokenMetadata as K, type Logger as L, type CentrifugeVaultOfferDetail as M, type OfferType as N, OfferVaultContract as O, Participation as P, type OndoSwapOfferDetail as Q, type RequirementsNamespace as R, type SuperstateSwapNamespace as S, type TokensNamespace as T, type UniversalNamespaceContext as U, type CoinListTokenSaleOfferDetail as V, type WalletError as W, type SuperstateSwapOfferDetail as X, CentrifugeVaultLegId as Y, Seconds as Z, type AsyncOfferType as _, EthereumChain as a, type CentrifugeVaultOffer as a$, Offer as a0, RequirementStatusInfo as a1, type RequirementType as a2, type RequirementStatusValue as a3, OfferOptionAddress as a4, RequirementId as a5, type KycLevelName as a6, DocumentSubmission as a7, type WalletChallengeType as a8, type PinoLoggerOptions as a9, type ProductionLogLevel as aA, RedactedWalletError as aB, type RequestId as aC, type RpcFailureReason as aD, type SafeEvent as aE, type SafeFields as aF, type UnredactedFields as aG, OAuthSession as aH, ClientCredentialsOAuth as aI, type Sender as aJ, PaginationParams as aK, PaginatedResponse as aL, ClientSecret as aM, OfferToken as aN, SwapStatus as aO, type Uint256 as aP, KnownAssetSymbol as aQ, type Newtype as aR, type AllowWalletParams as aS, AllowWalletResponse as aT, Asset as aU, AssetCode as aV, Blockchain as aW, type BuildOndoSwapParamsCore as aX, type CentrifugePositionStatus as aY, CentrifugeVaultClaimProceedsTransaction as aZ, CentrifugeVaultClaimTransaction as a_, AssetDecimals as aa, type BuildCentrifugeVaultBuyParams as ab, CentrifugeVaultQuote as ac, type CentrifugeOrderReason as ad, type CentrifugeOrderability as ae, OndoTradingStatus as af, type BuildOndoBuyParams as ag, type BuildOndoSellParams as ah, OndoQuote as ai, type OndoQuoteSize as aj, type TokenIdentifier as ak, CentrifugeVaultLeg as al, OfferOptionAddressId as am, CentrifugeVaultStatus as an, TokenLogo as ao, type DebugEvent as ap, type FrontlineEventId as aq, HttpError as ar, type HttpResponse as as, KycToken as at, type LogBinding as au, type LogBindings as av, type LogCause as aw, type LogLevel as ax, type LogScope as ay, type LogValue as az, EvmContractAddress as b, type RequirementActionNeededReason as b$, CentrifugeVaultPosition as b0, type CentrifugeVaultReason as b1, CentrifugeVaultRedeemPosition as b2, type CentrifugeVaultTransactionCore as b3, type CentrifugeWalletParams as b4, Chain as b5, ClientId as b6, CodeChallenge as b7, type CoinListTokenSaleOffer as b8, ConnectExternalWalletParams as b9, Milestone as bA, Millis as bB, OAuthRefreshToken as bC, type OfferBase as bD, type OfferDetailBase as bE, OfferEditorial as bF, OfferOption as bG, OfferOptionSlug as bH, OfferSlug as bI, OffersNamespaceImpl as bJ, type OndoQuoteDuration as bK, type OndoSellOutcome as bL, type OndoSwapOffer as bM, PKCEState as bN, type PaginatedResponseDto as bO, ParticipationId as bP, type ParticipationStatus as bQ, ParticipationsPaginationParams as bR, PauseFlags as bS, Pii as bT, PiiAddress as bU, PiiJurisdiction as bV, type PiiKind as bW, type QueryParamValue as bX, type QueryParamValues as bY, RedirectUri as bZ, type RemoveOptionAddressParams as b_, type CreateKycTokenParams as ba, CreateParticipationParams as bb, CreateWalletOwnershipChallengeParams as bc, Cursor as bd, type DocumentFormType as be, type DocumentSubmissionStatus as bf, type DocumentType as bg, ETHEREUM_CHAINS as bh, EpochMillis as bi, Erc20NamespaceImpl as bj, FaqItem as bk, type GetCentrifugeVaultQuoteParams as bl, type GetCentrifugeVaultStatusParams as bm, type GetOndoQuoteParams as bn, type GetOndoTradingStatusParams as bo, type GetSwapAuthorizationParams as bp, type GetSwapPreviewParams as bq, type GetTokenAllowanceParams as br, type GetTokenBalanceParams as bs, HexEncodedTransactionData as bt, Isin as bu, Iso2CountryCode as bv, Link as bw, type ListOptionAddressesParams as bx, MAX_ASSET_DECIMALS as by, MAX_UINT_256 as bz, type CentrifugeNamespace as c, type RpcConfig as c0, SOLANA_CHAINS as c1, STABLE_DECIMALS as c2, SolanaChain as c3, type SubmitDocumentParams as c4, type SuperstateSwapOffer as c5, type SwapContractRef as c6, SwapPreview as c7, TermItem as c8, Ticker as c9, type TokenLogoImage as ca, TokenLogoUrl as cb, type TokenRole as cc, TokensNamespaceImpl as cd, type Tx as ce, WalletAddress as cf, WalletOwnershipChallenge as cg, type WalletProtocol as ch, WalletsNamespaceImpl as ci, apiErrorCode as cj, assertUint256 as ck, isChain as cl, isExpired as cm, isOfferType as cn, parseUint256 as co, AssetSymbol as d, CentrifugeVaultBuyTransaction as e, type CentrifugeClaimDirection as f, CentrifugeNamespaceImpl as g, type CoinListTokenSaleNamespace as h, OfferId as i, OfferOptionId as j, AssetId as k, CoinListTokenSaleNamespaceImpl as l, type OndoNamespace as m, OfferSwapContract as n, OndoBuyTransaction as o, OndoSellTransaction as p, type OndoSwapTransactionCore as q, type OrderBookSide as r, OndoNamespaceImpl as s, type WalletsNamespace as t, Bps as u, EvmWalletAddress as v, SuperstateSwapNamespaceImpl as w, Requirement as x, RequirementsNamespaceImpl as y, type Config as z };