@coinlist-co/react 0.11.0 → 0.11.1-rc.22d81d4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/chunk-AQIHCFW4.js +279 -0
  2. package/dist/chunk-AQIHCFW4.js.map +1 -0
  3. package/dist/{chunk-B2HCVPCQ.js → chunk-PRG3EDQJ.js} +25 -10
  4. package/dist/chunk-PRG3EDQJ.js.map +1 -0
  5. package/dist/{chunk-UIIXXLA7.js → chunk-ZVB6KWZ2.js} +484 -141
  6. package/dist/chunk-ZVB6KWZ2.js.map +1 -0
  7. package/dist/client/index.cjs +1307 -461
  8. package/dist/client/index.cjs.map +1 -1
  9. package/dist/client/index.d.cts +216 -211
  10. package/dist/client/index.d.ts +216 -211
  11. package/dist/client/index.js +464 -108
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/collections-DrJFEDHl.d.cts +116 -0
  14. package/dist/collections-pLtrj6fw.d.ts +116 -0
  15. package/dist/{config-B5mwS_2l.d.cts → config-C6vlghJY.d.cts} +713 -22
  16. package/dist/{config-B5mwS_2l.d.ts → config-C6vlghJY.d.ts} +713 -22
  17. package/dist/server/index.cjs +766 -209
  18. package/dist/server/index.cjs.map +1 -1
  19. package/dist/server/index.d.cts +80 -3
  20. package/dist/server/index.d.ts +80 -3
  21. package/dist/server/index.js +120 -51
  22. package/dist/server/index.js.map +1 -1
  23. package/dist/shared/index.cjs +486 -123
  24. package/dist/shared/index.cjs.map +1 -1
  25. package/dist/shared/index.d.cts +18 -5
  26. package/dist/shared/index.d.ts +18 -5
  27. package/dist/shared/index.js +8 -2
  28. package/package.json +3 -2
  29. package/dist/chunk-B2HCVPCQ.js.map +0 -1
  30. package/dist/chunk-KDGNDAHA.js +0 -146
  31. package/dist/chunk-KDGNDAHA.js.map +0 -1
  32. package/dist/chunk-UIIXXLA7.js.map +0 -1
  33. package/dist/collections-BhDkYmzV.d.cts +0 -65
  34. package/dist/collections-CZhHoQHr.d.ts +0 -65
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shared/api/http-attributes.ts","../src/shared/api/http.ts","../src/shared/api/pagination.ts","../src/shared/types/errors.ts","../src/shared/types/blockchain/core.ts","../src/shared/types/blockchain/ui.ts","../src/shared/core/blockchain/chain.ts","../src/shared/types/providers/superstate/swap.ts","../src/shared/api/frontline/providers/superstate/swap.ts","../src/shared/core/blockchain/erc20/erc20-namespace.ts","../src/shared/core/blockchain/formatters.ts","../src/shared/core/blockchain/math.ts","../src/shared/types/pagination.ts","../src/shared/types/asset.ts","../src/shared/types/offer.ts","../src/shared/core/utils/crypto.ts","../src/shared/types/offer-detail.ts","../src/shared/types/providers/coin-list/token-sale.ts","../src/shared/api/frontline/providers/coin-list/token-sale.ts","../src/shared/core/checkout/coin-list/token-sale-namespace.ts","../src/shared/types/trading.ts","../src/shared/types/providers/ondo/ondo.ts","../src/shared/api/frontline/providers/ondo/ondo.ts","../src/shared/core/checkout/ondo/ondo-namespace.ts","../src/shared/core/checkout/superstate/swap-namespace.ts","../src/shared/types/document-submission.ts","../src/shared/types/kyc.ts","../src/shared/types/pii.ts","../src/shared/types/requirement.ts","../src/shared/api/frontline/documents.ts","../src/shared/api/frontline/kyc.ts","../src/shared/api/frontline/pii.ts","../src/shared/api/frontline/requirements.ts","../src/shared/core/requirements/requirements-namespace.ts","../src/shared/types/token-metadata.ts","../src/shared/api/nabu/tokens.ts","../src/shared/api/frontline/config.ts","../src/shared/api/http-client.ts","../src/shared/core/tokens/tokens-namespace.ts","../src/shared/types/offer-option-address.ts","../src/shared/types/wallet-ownership-challenge.ts","../src/shared/api/frontline/wallet-connect.ts","../src/shared/core/wallets/wallets-namespace.ts","../src/shared/types/oauth-session.ts","../src/shared/api/frontline/offers.ts"],"sourcesContent":["import type { ClientCredentialsOAuth } from '@/shared/types/oauth-session';\n\nexport type HttpRequestAttributes = {\n protected?: boolean;\n userAgent?: boolean;\n idempotencyKey?: boolean;\n /** Zero-based attempt index: 0 = first request, 1 = first retry, etc. */\n retryAttempt?: number;\n renewAttempted?: boolean;\n clientCredentials?: ClientCredentialsOAuth;\n};\n\nexport type Attributes = Readonly<HttpRequestAttributes>;\n\nconst empty: Attributes = {};\n\nconst concat = (left: Attributes, right: Attributes): Attributes => ({\n ...left,\n ...right,\n});\n\nconst concatAll = (...items: Attributes[]): Attributes => {\n let result = empty;\n for (const item of items) {\n result = concat(result, item);\n }\n return result;\n};\n\nconst protectedRequest = (): Attributes => ({ protected: true });\nconst userAgent = (): Attributes => ({ userAgent: true });\nconst idempotencyKey = (): Attributes => ({\n idempotencyKey: true,\n});\n\nconst clientCredentials = (\n credentials: ClientCredentialsOAuth | undefined\n): Attributes => ({\n clientCredentials: credentials,\n});\n/** Returns attributes with the given retry attempt (zero-based). */\nconst retryAttempt = (attempt: number): Attributes => ({\n retryAttempt: attempt,\n});\nconst renewAttempted = (value: boolean): Attributes => ({\n renewAttempted: value,\n});\n\nconst isProtected = (attrs?: HttpRequestAttributes): boolean =>\n attrs?.protected === true;\nconst needUserAgent = (attrs?: HttpRequestAttributes): boolean =>\n attrs?.userAgent === true;\nconst isIdempotent = (attrs?: HttpRequestAttributes): boolean =>\n attrs?.idempotencyKey === true;\nconst getRetryAttempt = (attrs?: HttpRequestAttributes): number =>\n attrs?.retryAttempt ?? 0;\nconst wasRenewAttempted = (attrs?: HttpRequestAttributes): boolean =>\n attrs?.renewAttempted === true;\nconst getClientCredentials = (\n attrs?: HttpRequestAttributes\n): ClientCredentialsOAuth | undefined => attrs?.clientCredentials;\n\nexport const Attributes = {\n empty,\n concat,\n concatAll,\n protected: protectedRequest,\n isProtected,\n userAgent,\n needUserAgent,\n idempotencyKey,\n isIdempotent,\n retryAttempt,\n getRetryAttempt,\n renewAttempted,\n wasRenewAttempted,\n clientCredentials,\n getClientCredentials,\n} as const;\n","import {\n Attributes,\n type HttpRequestAttributes,\n} from '@/shared/api/http-attributes';\nimport type { QueryParamValue, QueryParamValues } from '@/shared/types/http';\n\nexport type HttpClientConfig = {\n baseUrl: string;\n /**\n * The frontline `X-API-Version` header. Omit for clients against other\n * backends (e.g. the token registry): a version header they don't know\n * would also force a CORS preflight the CDN cannot answer.\n */\n xApiVersion?: string;\n};\n\nexport type HttpRequest<TBody = unknown> =\n | {\n method: 'GET';\n url: string;\n queryParams?: Record<string, QueryParamValues>;\n headers?: Record<string, string>;\n attributes?: HttpRequestAttributes;\n redirect?: RequestRedirect;\n }\n | {\n method: 'POST';\n url: string;\n queryParams?: Record<string, QueryParamValues>;\n headers?: Record<string, string>;\n body: TBody;\n attributes?: HttpRequestAttributes;\n redirect?: RequestRedirect;\n }\n | {\n method: 'DELETE';\n url: string;\n queryParams?: Record<string, QueryParamValues>;\n headers?: Record<string, string>;\n attributes?: HttpRequestAttributes;\n redirect?: RequestRedirect;\n };\nexport type HttpResponse<TBody = unknown> = {\n status: number;\n headers?: Record<string, string>;\n body: TBody | null;\n};\n\nexport class HttpError<TBody = unknown> extends Error {\n readonly response: HttpResponse<TBody>;\n\n constructor(response: HttpResponse<TBody>) {\n super(`Request failed with ${response.status} status`);\n this.name = 'HttpError';\n this.response = response;\n }\n}\n\n/**\n * The machine-readable `code` frontline attaches to an error, or `null` for\n * anything else - a non-HTTP failure, or an error body that carries only a\n * message.\n *\n * Frontline answers a failure with `{ type, message, code?, errors?,\n * event_id? }`, and `code` is the only part of it meant to be branched on:\n * `message` is prose that may be reworded, and `type` distinguishes\n * `invalid_request_error` from `api_error` without saying which one.\n *\n * Reach for this only where a code has a distinct remedy the user can act on.\n * Mapping the whole vocabulary would couple the SDK to strings frontline does\n * not version; falling back to a generic failure is the right default.\n */\nexport function apiErrorCode(error: unknown): string | null {\n if (!(error instanceof HttpError)) return null;\n const body: unknown = error.response.body;\n if (typeof body !== 'object' || body === null) return null;\n const code: unknown = (body as { code?: unknown }).code;\n return typeof code === 'string' ? code : null;\n}\n\nexport async function makeRequest<TResponse = unknown>(\n request: HttpRequest\n): Promise<HttpResponse<TResponse>> {\n const headers: Record<string, string> = {\n Accept: 'application/json',\n ...(request.method === 'POST' && request.body !== undefined\n ? { 'Content-Type': 'application/json' }\n : {}),\n ...(request.headers ?? {}),\n };\n\n const init: RequestInit = {\n method: request.method,\n headers,\n ...(request.redirect !== undefined ? { redirect: request.redirect } : {}),\n };\n\n if (request.method === 'POST' && request.body !== undefined) {\n init.body = JSON.stringify(request.body);\n }\n\n const response = await fetch(\n buildUrlWithQueryParams(request.url, request.queryParams),\n init\n );\n const responseHeaders = headersToRecord(response.headers);\n\n if (response.status === 204 || response.status === 205) {\n return {\n status: response.status,\n body: null,\n headers: responseHeaders,\n };\n }\n\n if (response.status >= 300 && response.status < 400) {\n await response.text();\n return {\n status: response.status,\n body: null,\n headers: responseHeaders,\n };\n }\n\n const text = await response.text();\n let body: TResponse | null;\n try {\n body = text ? (JSON.parse(text) as TResponse) : null;\n } catch (_) {\n // A non-JSON body (an HTML error page from a CDN, proxy, or load\n // balancer) would otherwise surface as a bare SyntaxError with the status\n // lost. Throw the full response instead, so callers can classify the\n // failure by status and still see what the server actually sent.\n throw new HttpError({\n status: response.status,\n headers: responseHeaders,\n body: text,\n });\n }\n\n return {\n status: response.status,\n body,\n headers: responseHeaders,\n };\n}\n\nfunction buildUrlWithQueryParams(\n url: string,\n queryParams?: Record<string, QueryParamValues>\n): string {\n if (!queryParams) {\n return url;\n }\n\n const searchParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(queryParams)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item === undefined || item === null) {\n continue;\n }\n searchParams.append(key, String(item));\n }\n continue;\n }\n\n searchParams.append(key, String(value));\n }\n\n const queryString = searchParams.toString();\n if (!queryString) {\n return url;\n }\n\n return url.includes('?') ? `${url}&${queryString}` : `${url}?${queryString}`;\n}\n\nfunction headersToRecord(headers: Headers): Record<string, string> {\n const record: Record<string, string> = {};\n headers.forEach((value, key) => {\n record[key.toLowerCase()] = value;\n });\n return record;\n}\n\nfunction concatAttributes(\n request: HttpRequest,\n attrs: Attributes\n): HttpRequest {\n const nextAttributes = Attributes.concat(\n request.attributes ?? Attributes.empty,\n attrs\n );\n const nextRequest: typeof request = {\n ...request,\n attributes: nextAttributes,\n };\n return nextRequest;\n}\n\nexport const Request = {\n concatAttributes,\n};\n\nexport type { QueryParamValue, QueryParamValues };\n","import type {\n Cursor,\n PaginatedResponse,\n PaginationParams,\n} from '@/shared/types/pagination';\n\n/**\n * Walks every page of a cursor-paginated endpoint and returns the flattened\n * result.\n *\n * Lives in the API layer rather than beside `PaginationParams` because it\n * drives requests: it is the auto-paginating half that `list()` is built on,\n * while the params and the response envelope are domain models the client and\n * the server both name.\n */\nexport async function fetchAllPages<\n A,\n P extends PaginationParams = PaginationParams,\n>(\n fetchPage: (params: P) => Promise<PaginatedResponse<A>>,\n baseParams?: Omit<P, keyof PaginationParams>\n): Promise<A[]> {\n const items: A[] = [];\n let cursor: Cursor | null = null;\n\n do {\n const params = {\n ...(baseParams ?? {}),\n after: cursor ?? undefined,\n } as P;\n const page = await fetchPage(params);\n items.push(...page.data);\n cursor = page.startingAfter;\n } while (cursor);\n\n return items;\n}\n","/**\n * Error thrown when a feature or code path is not yet implemented.\n */\nexport class NotImplementedError extends Error {\n constructor(message = 'Not implemented yet') {\n super(message);\n this.name = 'NotImplementedError';\n }\n}\n\n/**\n * Error thrown when accessing a feature that requires authentication\n * without being authenticated.\n */\nexport class NotAuthenticatedError extends Error {\n constructor(\n message = 'The user is not authenticated. Go through the OAuth flow first!'\n ) {\n super(message);\n this.name = 'NotAuthenticatedError';\n }\n}\n\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\n }\n}\n","import { ValidationError } from '@/shared/types/errors';\nimport type { Newtype } from '@/shared/types/newtype';\n\nexport type EthereumChain = 'ethereum_mainnet' | 'ethereum_sepolia';\n\n/**\n * The exhaustive chain set: a new {@link EthereumChain} is a compile error\n * here until it is listed, which is what keeps the constructor total.\n */\nexport const ETHEREUM_CHAINS: Record<EthereumChain, true> = {\n ethereum_mainnet: true,\n ethereum_sepolia: true,\n};\n\n/**\n * Validates that a raw backend string names a chain the SDK supports.\n *\n * @throws ValidationError on anything else. Passing an unknown chain through\n * would let downstream EIP-155 lookups blow up far from the response that\n * caused it.\n */\nexport const EthereumChain = (value: string): EthereumChain => {\n if (!Object.keys(ETHEREUM_CHAINS).includes(value)) {\n throw new ValidationError(`Unsupported Ethereum chain: \"${value}\"`);\n }\n return value as EthereumChain;\n};\n\nexport type SolanaChain = 'solana_mainnet' | 'solana_devnet';\n\n/**\n * The exhaustive chain set: a new {@link SolanaChain} is a compile error\n * here until it is listed, which is what keeps the constructor total.\n */\nexport const SOLANA_CHAINS: Record<SolanaChain, true> = {\n solana_mainnet: true,\n solana_devnet: true,\n};\n\n/**\n * Validates that a raw backend string names a chain the SDK supports.\n *\n * @throws ValidationError on anything else. Passing an unknown chain through\n * would let downstream EIP-155 lookups blow up far from the response that\n * caused it.\n */\nexport const SolanaChain = (value: string): SolanaChain => {\n if (!Object.keys(SOLANA_CHAINS).includes(value)) {\n throw new ValidationError(`Unsupported Solana chain: \"${value}\"`);\n }\n return value as SolanaChain;\n};\n\nexport type Chain = EthereumChain | SolanaChain;\n\nexport const Chain = (value: string): Chain => {\n if (\n !Object.keys(ETHEREUM_CHAINS).includes(value) &&\n !Object.keys(SOLANA_CHAINS).includes(value)\n ) {\n throw new ValidationError(`Unsupported chain: \"${value}\"`);\n }\n return value as Chain;\n};\n\n/**\n * Protocol a wallet binding is scoped to. EVM-only for now: an EVM address\n * binds once per option regardless of which EVM chain proved ownership.\n * Frontline's enum also has `:solana`, but we don't handle Solana bindings yet,\n * so this stays `'ethereum'` until Solana support lands.\n */\nexport type WalletProtocol = 'ethereum';\n\n/**\n * EVM addresses keep a `0x${string}` base so they stay assignable to the\n * `0x${string}` shapes that on-chain libraries (viem/wagmi) expect. We only\n * drop the runtime `0x` narrowing: values are trusted at the boundary and\n * branded via the constructor.\n */\nexport type EvmWalletAddress = Newtype<`0x${string}`, 'EvmWalletAddress'>;\nexport const EvmWalletAddress = (value: string): EvmWalletAddress =>\n value as EvmWalletAddress;\n\nexport type EvmContractAddress = Newtype<`0x${string}`, 'EvmContractAddress'>;\nexport const EvmContractAddress = (value: string): EvmContractAddress =>\n value as EvmContractAddress;\n\n/**\n * What uniquely identifies a token: the chain it is deployed on plus its\n * contract address. Never a symbol, which can collide across issuers.\n */\nexport type TokenIdentifier = {\n /** The chain the token contract is deployed on. */\n chain: EthereumChain;\n /**\n * The token's contract address, in any casing — consumers that need the\n * EIP-55 form (e.g. the token registry routes) checksum it themselves.\n */\n address: EvmContractAddress;\n};\n\nexport type HexEncodedTransactionData = Newtype<\n `0x${string}`,\n 'HexEncodedTransactionData'\n>;\nexport const HexEncodedTransactionData = (\n value: string\n): HexEncodedTransactionData => value as HexEncodedTransactionData;\n\n/**\n * A transaction the backend has already encoded for us — the caller only\n * broadcasts it. Used by the flows that hand a wallet a ready-made `to`/`data`\n * pair (allow-listing a wallet, an Ondo swap) rather than encoding a contract\n * call themselves.\n */\nexport type Tx = {\n to: EvmContractAddress;\n data: HexEncodedTransactionData;\n};\n\n/**\n * The largest exponent whose power of ten still fits a uint256: 10^77 fits,\n * 10^78 does not.\n *\n * The bound is arithmetic rather than a token standard's. ERC-20 reports\n * `decimals()` as a `uint8`, so 255 is what a contract *can* say, but every\n * {@link AssetDecimals} in this codebase is paired with a {@link Uint256} raw\n * by construction, and scaling by anything past this leaves that pairing\n * unrepresentable. A value between 78 and 255 would therefore pass a\n * standard-faithful check and then break the first multiplication it reached.\n */\nexport const MAX_ASSET_DECIMALS = 77;\n\n/**\n * How many decimal places one whole token divides into.\n *\n * Validated, unlike its neighbours here — {@link Uint256} is a bare `bigint`\n * with a separate {@link assertUint256} guard, and {@link DecimalString} casts\n * unchecked. The asymmetry is deliberate and follows the value's provenance:\n * an `AssetDecimals` used to come only from literals and the token registry,\n * but backends now publish exponents of their own (`asset_decimals` on an Ondo\n * quote, both scales on a built swap), and those feed `10n ** BigInt(d)`\n * during render. Guarding at construction is what keeps a fractional or\n * unbounded exponent from surfacing as a `RangeError` mid-render — or, at\n * 10^200, as a hung tab — instead of as the failed state the screen has.\n *\n * See docs/ADR-7-VALIDATED-NEWTYPES.md.\n *\n * @throws ValidationError on a non-integer, a negative, or anything above\n * {@link MAX_ASSET_DECIMALS}.\n */\nexport type AssetDecimals = Newtype<number, 'AssetDecimals'>;\nexport const AssetDecimals = (value: number): AssetDecimals => {\n if (!Number.isInteger(value)) {\n throw new ValidationError(`Asset decimals must be an integer: ${value}`);\n }\n if (value < 0 || value > MAX_ASSET_DECIMALS) {\n throw new ValidationError(\n `Asset decimals out of range [0, ${MAX_ASSET_DECIMALS}]: ${value}`\n );\n }\n return value as AssetDecimals;\n};\n\nexport const STABLE_DECIMALS = AssetDecimals(6);\n\n/**\n * A non-negative decimal number the backend sent as a string, kept unscaled.\n *\n * Reach for it when a response gives you a number but not the decimals to\n * scale it by, or gives you one it has already applied. Inventing an exponent\n * for either is how a display ends up orders of magnitude out.\n *\n * Contrast {@link BlockchainAmount}, which pairs a raw uint256 with the\n * decimals it is denominated in and so is only constructible when you know\n * both. Arithmetic on a `DecimalString` needs a decimal library we\n * deliberately do not ship.\n */\nexport type DecimalString = Newtype<string, 'DecimalString'>;\nexport const DecimalString = (value: string): DecimalString =>\n value as DecimalString;\n\nexport const MAX_UINT_256 = 2n ** 256n - 1n;\n\n/**\n * A non-negative integer within uint256 bounds. Kept unbranded (a plain\n * `bigint`) so raw on-chain amounts flow in without ceremony; bounds are\n * enforced where it matters (see {@link combineAmounts}).\n */\nexport type Uint256 = bigint;\n\n/**\n * Asserts a raw bigint falls within uint256 bounds, throwing otherwise. Use at\n * on-chain arithmetic boundaries (bps math, price computation) where a computed\n * value could underflow below zero or overflow above 2^256-1.\n */\nexport const assertUint256 = (value: bigint): Uint256 => {\n if (value < 0n || value > MAX_UINT_256) {\n throw new Error(`Value out of uint256 bounds: ${value}`);\n }\n return value;\n};\n\nexport type BlockchainAmount = Newtype<\n { raw: Uint256; decimals: AssetDecimals },\n 'BlockchainAmount'\n>;\n\n/**\n * Constructs a {@link BlockchainAmount} and exposes arithmetic helpers.\n * TypeScript has no operator overloading, so use `BlockchainAmount.add(a, b)`\n * instead of `+`/`-` on the objects directly.\n */\nexport const BlockchainAmount = Object.assign(\n (value: { raw: Uint256; decimals: AssetDecimals }): BlockchainAmount =>\n value as BlockchainAmount,\n {\n add: (a: BlockchainAmount, b: BlockchainAmount): BlockchainAmount =>\n combineAmounts(a, b, (x, y) => x + y),\n sub: (a: BlockchainAmount, b: BlockchainAmount): BlockchainAmount =>\n combineAmounts(a, b, (x, y) => x - y),\n }\n);\n\n/**\n * Combine two amounts with a raw-bigint `op`. Both operands must share the\n * same `decimals` — adding/subtracting differently-scaled amounts is a\n * programming error, so we throw rather than silently producing garbage.\n * The result is bounds-checked, so an underflow (negative `raw`) or uint256\n * overflow is rejected.\n */\nfunction combineAmounts(\n a: BlockchainAmount,\n b: BlockchainAmount,\n op: (x: bigint, y: bigint) => bigint\n): BlockchainAmount {\n if (a.decimals !== b.decimals) {\n throw new Error(\n 'Cannot combine BlockchainAmounts with different decimals: ' +\n `${a.decimals} vs ${b.decimals}`\n );\n }\n const raw = op(a.raw, b.raw);\n if (raw < 0n || raw > MAX_UINT_256) {\n throw new Error(`BlockchainAmount out of uint256 bounds: ${raw}`);\n }\n return BlockchainAmount({ raw, decimals: a.decimals });\n}\n\nexport type AssetSymbol = Newtype<string, 'AssetSymbol'>;\nexport const AssetSymbol = (value: string): AssetSymbol => value as AssetSymbol;\n\n/**\n * A stablecoin symbol is an {@link AssetSymbol} narrowed to the coins we\n * support. It shares the `AssetSymbol` brand so it stays assignable to it.\n */\nexport type StablecoinSymbol = Newtype<'USDC' | 'USDT', 'AssetSymbol'>;\nexport const StablecoinSymbol = (value: 'USDC' | 'USDT'): StablecoinSymbol =>\n value as StablecoinSymbol;\n\nexport type KnownAssetSymbol = StablecoinSymbol;\nexport const KnownAssetSymbol = StablecoinSymbol;\n\nexport type Erc20Asset = {\n name: string;\n symbol: AssetSymbol;\n decimals: AssetDecimals;\n};\n\nexport type Bps = Newtype<bigint, 'Bps'>;\nexport const Bps = (value: bigint): Bps => value as Bps;\n","import type { Newtype } from '@/shared/types/newtype';\n\nexport type FormattedAmountUi = Newtype<string, 'FormattedAmountUi'>;\nexport const FormattedAmountUi = (value: string): FormattedAmountUi =>\n value as FormattedAmountUi;\n\nexport type FormattedPercentUi = Newtype<string, 'FormattedPercentUi'>;\nexport const FormattedPercentUi = (value: string): FormattedPercentUi =>\n value as FormattedPercentUi;\n\nexport type TxExplorerUrl = Newtype<string, 'TxExplorerUrl'>;\nexport const TxExplorerUrl = (value: string): TxExplorerUrl =>\n value as TxExplorerUrl;\n\n/**\n * A wallet address shortened for display (e.g. `0x1234…5678`). Keeps a\n * `0x${string}` base but drops the runtime `0x` narrowing.\n */\nexport type ShortenedWalletAddress = Newtype<\n `0x${string}`,\n 'ShortenedWalletAddress'\n>;\nexport const ShortenedWalletAddress = (value: string): ShortenedWalletAddress =>\n value as ShortenedWalletAddress;\n\nexport type FormattedAmountAssetUi = Newtype<string, 'FormattedAmountAssetUi'>;\nexport const FormattedAmountAssetUi = (value: string): FormattedAmountAssetUi =>\n value as FormattedAmountAssetUi;\n\nexport type AssetIconUrl = Newtype<string, 'AssetIconUrl'>;\nexport const AssetIconUrl = (value: string): AssetIconUrl =>\n value as AssetIconUrl;\n","import type { Hash } from 'viem';\nimport type { EthereumChain } from '@/shared/types/blockchain/core';\nimport { TxExplorerUrl } from '@/shared/types/blockchain/ui';\nimport { ValidationError } from '@/shared/types/errors';\n\n/**\n * The one EIP-155 table. `satisfies` makes a new {@link EthereumChain} a\n * compile error here until its id is added, which is what keeps both\n * directions below total.\n */\nconst CHAIN_IDS = {\n ethereum_mainnet: 1,\n ethereum_sepolia: 11155111,\n} as const satisfies Record<EthereumChain, number>;\n\nexport function getChainId(chain: EthereumChain): number {\n return CHAIN_IDS[chain];\n}\n\n/**\n * Resolves an EIP-155 chain id to the chain the SDK names it by — the inverse\n * of {@link getChainId}, for backends that report a bare `chain_id`.\n *\n * @throws ValidationError on an unrecognised id. Defaulting to mainnet would\n * let a testnet response read as a live one.\n */\nexport function chainFromId(chainId: string): EthereumChain {\n const chains = Object.keys(CHAIN_IDS) as EthereumChain[];\n const chain = chains.find((c) => String(CHAIN_IDS[c]) === chainId);\n if (!chain) {\n throw new ValidationError(`Unsupported EIP-155 chain id: \"${chainId}\"`);\n }\n return chain;\n}\n\nexport function getNetworkName(chain: EthereumChain): string {\n switch (chain) {\n case 'ethereum_mainnet':\n return 'Ethereum';\n case 'ethereum_sepolia':\n return 'Ethereum Sepolia';\n default: {\n const _exhaustive: never = chain;\n return _exhaustive;\n }\n }\n}\n\nexport function txExplorerUrl(\n chain: EthereumChain,\n txHash: Hash\n): TxExplorerUrl {\n return TxExplorerUrl(`${explorerBaseUrl(chain)}/tx/${txHash}`);\n}\n\nfunction explorerBaseUrl(chain: EthereumChain): string {\n switch (chain) {\n case 'ethereum_mainnet':\n return 'https://etherscan.io';\n case 'ethereum_sepolia':\n return 'https://sepolia.etherscan.io';\n default: {\n const _exhaustive: never = chain;\n return _exhaustive;\n }\n }\n}\n","import {\n assertUint256,\n EvmContractAddress,\n HexEncodedTransactionData,\n type Uint256,\n} from '@/shared/types/blockchain/core';\nimport type {\n AllowWalletResponseDto,\n SwapPreviewDto,\n SwapStatusDto,\n TokenAllowanceDto,\n TokenBalanceDto,\n WalletAuthorizationDto,\n} from '@/shared/types/dto/providers/superstate/swap';\n\n/**\n * Whether a wallet is authorized to interact with a given swap contract.\n */\nexport type SwapAuthorization = {\n authorized: boolean;\n};\n\nexport const SwapAuthorization = {\n fromDto: (dto: WalletAuthorizationDto): SwapAuthorization => ({\n authorized: dto.authorized,\n }),\n};\n\n/**\n * A read-only quote for a swap: how much goes in, the protocol fee, and how\n * much would come out. All amounts are raw on-chain integers (uint256).\n */\nexport type SwapPreview = {\n inputAmount: Uint256;\n fee: Uint256;\n outputAmount: Uint256;\n};\n\nexport const SwapPreview = {\n fromDto: (dto: SwapPreviewDto): SwapPreview => ({\n inputAmount: assertUint256(BigInt(dto.pay_input_amount)),\n fee: assertUint256(BigInt(dto.fee)),\n outputAmount: assertUint256(BigInt(dto.receive_output_amount)),\n }),\n};\n\n/**\n * The on-chain state of a swap contract.\n *\n * - `stopped`: non-zero when the contract is paused/halted.\n * - `swapLevel`: the current swap level/tier.\n */\nexport type SwapStatus = {\n stopped: Uint256;\n swapLevel: Uint256;\n};\n\nexport const SwapStatus = {\n fromDto: (dto: SwapStatusDto): SwapStatus => ({\n stopped: assertUint256(BigInt(dto.stopped)),\n swapLevel: assertUint256(BigInt(dto.swap_level)),\n }),\n};\n\n// TODO: TokenAllowance and TokenBalance are generic ERC-20, not swap — move\n// them and their DTOs to /types/erc-20 alongside Erc20Namespace. Deferred:\n// it touches ~20 importers plus both barrels, so it wants its own PR.\n/**\n * The ERC-20 allowance an owner has granted a spender for a token.\n */\nexport type TokenAllowance = {\n allowance: Uint256;\n};\n\nexport const TokenAllowance = {\n fromDto: (dto: TokenAllowanceDto): TokenAllowance => ({\n allowance: assertUint256(BigInt(dto.allowance)),\n }),\n};\n\n/**\n * The raw ERC-20 balance an owner holds of a token (uint256).\n */\nexport type TokenBalance = {\n balance: Uint256;\n};\n\nexport const TokenBalance = {\n fromDto: (dto: TokenBalanceDto): TokenBalance => ({\n balance: assertUint256(BigInt(dto.balance)),\n }),\n};\n\n/**\n * The backend's response to an allow-wallet request. Either the caller must\n * broadcast an on-chain transaction to complete allow-listing, or nothing is\n * required because the wallet is already allowed.\n */\nexport type AllowWalletResponse =\n | {\n action: 'broadcast_transaction';\n to: EvmContractAddress;\n data: HexEncodedTransactionData;\n }\n | {\n action: 'none';\n alreadyAllowed: boolean;\n };\n\nexport const AllowWalletResponse = {\n fromDto: (dto: AllowWalletResponseDto): AllowWalletResponse => {\n switch (dto.action) {\n case 'broadcast_transaction':\n return {\n action: 'broadcast_transaction',\n to: EvmContractAddress(dto.to),\n data: HexEncodedTransactionData(dto.data),\n };\n case 'none':\n return {\n action: 'none',\n alreadyAllowed: dto.already_allowed,\n };\n default: {\n const _exhaustive: never = dto;\n return _exhaustive;\n }\n }\n },\n};\n","import { Attributes } from '@/shared/api/http-attributes';\nimport type { Sender } from '@/shared/api/http-client';\nimport type {\n GetTokenAllowanceParams,\n GetTokenBalanceParams,\n} from '@/shared/core/blockchain/erc20/erc20-namespace.types';\nimport type {\n AllowWalletParams,\n GetSwapAuthorizationParams,\n GetSwapPreviewParams,\n SwapContractRef,\n} from '@/shared/core/checkout/superstate/swap-namespace.types';\nimport {\n AssetDecimals,\n AssetSymbol,\n type Erc20Asset,\n} from '@/shared/types/blockchain/core';\nimport type {\n AllowWalletResponseDto,\n SwapOutputTokenDto,\n SwapPreviewDto,\n SwapStatusDto,\n TokenAllowanceDto,\n TokenBalanceDto,\n WalletAuthorizationDto,\n} from '@/shared/types/dto/providers/superstate/swap';\nimport {\n AllowWalletResponse,\n SwapAuthorization,\n SwapPreview,\n SwapStatus,\n TokenAllowance,\n TokenBalance,\n} from '@/shared/types/providers/superstate/swap';\n\nexport async function getSwapAuthorization(\n api: Sender,\n params: GetSwapAuthorizationParams\n): Promise<SwapAuthorization> {\n const dto = await api.send<WalletAuthorizationDto>({\n method: 'GET',\n url: '/v1/wallet/authorized',\n queryParams: {\n chain: params.chain,\n contract_address: params.contractAddress,\n wallet_address: params.walletAddress,\n },\n attributes: Attributes.protected(),\n });\n return SwapAuthorization.fromDto(dto);\n}\n\nexport async function getSwapOutputToken(\n api: Sender,\n params: SwapContractRef\n): Promise<Erc20Asset> {\n const dto = await api.send<SwapOutputTokenDto>({\n method: 'GET',\n url: '/v1/swap/output-token',\n queryParams: {\n chain: params.chain,\n contract_address: params.contractAddress,\n },\n attributes: Attributes.protected(),\n });\n return toErc20Asset(dto);\n}\n\nexport async function getSwapPreview(\n api: Sender,\n params: GetSwapPreviewParams\n): Promise<SwapPreview> {\n const dto = await api.send<SwapPreviewDto>({\n method: 'GET',\n url: '/v1/swap/preview',\n queryParams: {\n chain: params.chain,\n contract_address: params.contractAddress,\n input_token: params.inputToken,\n amount: params.amount.toString(),\n },\n attributes: Attributes.protected(),\n });\n return SwapPreview.fromDto(dto);\n}\n\nexport async function getSwapStatus(\n api: Sender,\n params: SwapContractRef\n): Promise<SwapStatus> {\n const dto = await api.send<SwapStatusDto>({\n method: 'GET',\n url: '/v1/swap/status',\n queryParams: {\n chain: params.chain,\n contract_address: params.contractAddress,\n },\n attributes: Attributes.protected(),\n });\n return SwapStatus.fromDto(dto);\n}\n\nexport async function getTokenAllowance(\n api: Sender,\n params: GetTokenAllowanceParams\n): Promise<TokenAllowance> {\n const dto = await api.send<TokenAllowanceDto>({\n method: 'GET',\n url: '/v1/token/allowance',\n queryParams: {\n chain: params.chain,\n token_address: params.tokenAddress,\n owner: params.owner,\n spender: params.spender,\n },\n attributes: Attributes.protected(),\n });\n return TokenAllowance.fromDto(dto);\n}\n\nexport async function getTokenBalance(\n api: Sender,\n params: GetTokenBalanceParams\n): Promise<TokenBalance> {\n const dto = await api.send<TokenBalanceDto>({\n method: 'GET',\n url: '/v1/token/balance',\n queryParams: {\n chain: params.chain,\n token_address: params.tokenAddress,\n owner: params.owner,\n },\n attributes: Attributes.protected(),\n });\n return TokenBalance.fromDto(dto);\n}\n\nexport async function allowWallet(\n api: Sender,\n params: AllowWalletParams\n): Promise<AllowWalletResponse> {\n const dto = await api.send<AllowWalletResponseDto>({\n method: 'POST',\n url: `/v1/offers/${encodeURIComponent(params.offerId)}/allow-wallet`,\n body: {\n wallet_address: params.walletAddress,\n chain: params.chain,\n signature: params.signature,\n },\n attributes: Attributes.protected(),\n });\n return AllowWalletResponse.fromDto(dto);\n}\n\nfunction toErc20Asset(dto: SwapOutputTokenDto): Erc20Asset {\n return {\n name: dto.name,\n symbol: AssetSymbol(dto.symbol),\n decimals: AssetDecimals(dto.decimals),\n };\n}\n","import {\n getTokenAllowance,\n getTokenBalance,\n} from '@/shared/api/frontline/providers/superstate/swap';\nimport type {\n GetTokenAllowanceParams,\n GetTokenBalanceParams,\n} from '@/shared/core/blockchain/erc20/erc20-namespace.types';\nimport type { SharedNamespaceContext } from '@/shared/core/namespace-context';\nimport type {\n TokenAllowance,\n TokenBalance,\n} from '@/shared/types/providers/superstate/swap';\n\n/**\n * Generic ERC-20 reads shared across on-chain flows (swap, token sale): the\n * allowance an owner has granted a spender, and the raw token balance an owner\n * holds. These are plain token reads, not tied to any single product flow.\n */\nexport interface Erc20Namespace {\n /**\n * Reads the ERC-20 allowance an `owner` has granted a `spender`.\n */\n getAllowance(params: GetTokenAllowanceParams): Promise<TokenAllowance>;\n\n /**\n * Reads the raw ERC-20 balance an `owner` holds of a token.\n */\n getBalance(params: GetTokenBalanceParams): Promise<TokenBalance>;\n}\n\nexport class Erc20NamespaceImpl implements Erc20Namespace {\n constructor(private readonly ctx: SharedNamespaceContext) {}\n\n async getAllowance(params: GetTokenAllowanceParams): Promise<TokenAllowance> {\n await this.ctx.ensureUserAuthenticated();\n return getTokenAllowance(this.ctx.api, params);\n }\n\n async getBalance(params: GetTokenBalanceParams): Promise<TokenBalance> {\n await this.ctx.ensureUserAuthenticated();\n return getTokenBalance(this.ctx.api, params);\n }\n}\n","import { formatUnits } from 'viem';\nimport type {\n AssetSymbol,\n BlockchainAmount,\n Bps,\n EvmWalletAddress,\n} from '@/shared/types/blockchain/core';\nimport { AssetDecimals } from '@/shared/types/blockchain/core';\nimport {\n FormattedAmountAssetUi,\n FormattedAmountUi,\n FormattedPercentUi,\n ShortenedWalletAddress,\n} from '@/shared/types/blockchain/ui';\n\nexport function shortenAddress(\n address: EvmWalletAddress\n): ShortenedWalletAddress {\n const short =\n address.length > 10\n ? `${address.slice(0, 6)}…${address.slice(-4)}`\n : address;\n return ShortenedWalletAddress(short);\n}\n\nexport type FormatAmountOptions = {\n maxFractionDigits?: AssetDecimals;\n};\n\nexport function formatAmount(\n amount: BlockchainAmount,\n locale: string,\n options?: FormatAmountOptions\n): FormattedAmountUi {\n const decimal = formatRawAmount(amount);\n let [integerPart, fractionPart = ''] = decimal.split('.');\n\n const maxFractionDigits = options?.maxFractionDigits;\n const minFractionDigits =\n maxFractionDigits !== undefined\n ? Math.min(maxFractionDigits, amount.decimals)\n : Math.min(2, amount.decimals);\n\n if (\n maxFractionDigits !== undefined &&\n fractionPart.length > maxFractionDigits\n ) {\n ({ integerPart, fractionPart } = roundFractionHalfUp(\n integerPart,\n fractionPart,\n maxFractionDigits\n ));\n }\n\n const fraction =\n minFractionDigits === 0 ? '' : fractionPart.padEnd(minFractionDigits, '0');\n\n const integerFormatted = BigInt(integerPart).toLocaleString(locale);\n if (minFractionDigits === 0 && fraction === '') {\n return FormattedAmountUi(integerFormatted);\n }\n\n const decimalSeparator =\n new Intl.NumberFormat(locale)\n .formatToParts(1.1)\n .find((p) => p.type === 'decimal')?.value ?? '.';\n\n return FormattedAmountUi(`${integerFormatted}${decimalSeparator}${fraction}`);\n}\n\n/**\n * Rounds a decimal split into `integerPart`/`fractionPart` strings half-up to\n * `maxFractionDigits`, carrying into the integer part when needed (via BigInt,\n * so precision is preserved beyond `Number.MAX_SAFE_INTEGER`).\n *\n * Precondition: `integerPart` must be non-negative (guaranteed here because\n * `BlockchainAmount.raw` is a `Uint256`). A negative integer part would carry\n * in the wrong direction (toward +∞ instead of away from zero).\n */\nfunction roundFractionHalfUp(\n integerPart: string,\n fractionPart: string,\n maxFractionDigits: number\n): { integerPart: string; fractionPart: string } {\n if (fractionPart.length <= maxFractionDigits) {\n return { integerPart, fractionPart };\n }\n\n if (maxFractionDigits === 0) {\n const roundUp = fractionPart[0] >= '5';\n const integer = BigInt(integerPart) + (roundUp ? 1n : 0n);\n return { integerPart: integer.toString(), fractionPart: '' };\n }\n\n const trimmed = fractionPart.slice(0, maxFractionDigits);\n if (fractionPart[maxFractionDigits] < '5') {\n return { integerPart, fractionPart: trimmed };\n }\n\n const digits = trimmed.split('').map((digit) => Number.parseInt(digit, 10));\n let carry = 1;\n for (let i = digits.length - 1; i >= 0 && carry > 0; i -= 1) {\n const sum = digits[i] + carry;\n if (sum === 10) {\n digits[i] = 0;\n carry = 1;\n } else {\n digits[i] = sum;\n carry = 0;\n }\n }\n\n return {\n integerPart:\n carry > 0 ? (BigInt(integerPart) + 1n).toString() : integerPart,\n fractionPart: digits.join(''),\n };\n}\n\nexport function formatRawAmount(amount: BlockchainAmount): string {\n return formatUnits(amount.raw, amount.decimals);\n}\n\n/**\n * Formats a {@link BlockchainAmount} using compact notation (e.g. `1.37B`,\n * `5M`). Compact notation only surfaces a couple of significant decimals, so\n * the bigint → number narrowing here is intentional and safe: full precision\n * is deliberately dropped in favour of a human-readable summary value.\n */\nexport function formatCompactAmount(\n amount: BlockchainAmount,\n locale: string\n): FormattedAmountUi {\n const value = Number(formatRawAmount(amount));\n const formatted = new Intl.NumberFormat(locale, {\n notation: 'compact',\n maximumFractionDigits: 2,\n }).format(value);\n return FormattedAmountUi(formatted);\n}\n\nexport function formatBpsAsPercent(\n bps: Bps,\n locale: string\n): FormattedPercentUi {\n const whole = bps / 100n;\n const fraction = bps % 100n;\n const wholeFormatted = whole.toLocaleString(locale);\n const decimalSeparator =\n new Intl.NumberFormat(locale)\n .formatToParts(1.1)\n .find((p) => p.type === 'decimal')?.value ?? '.';\n\n if (fraction === 0n) {\n return FormattedPercentUi(`${wholeFormatted}%`);\n }\n\n const fractionFormatted = fraction\n .toString()\n .padStart(2, '0')\n .replace(/0+$/, '');\n\n return FormattedPercentUi(\n `${wholeFormatted}${decimalSeparator}${fractionFormatted}%`\n );\n}\n\nexport function usdAmount(amount: FormattedAmountUi): FormattedAmountAssetUi {\n return FormattedAmountAssetUi(`$${amount}`);\n}\n\nexport function assetAmount(\n amount: FormattedAmountUi,\n symbol: AssetSymbol\n): FormattedAmountAssetUi {\n return FormattedAmountAssetUi(`${amount} ${symbol}`);\n}\n\n/** Placeholder shown when an amount is unavailable (e.g. a loading quote). */\nexport const NA_AMOUNT_ASSET_UI: FormattedAmountAssetUi =\n FormattedAmountAssetUi('-');\n\nconst USD_FRACTION_DIGITS = AssetDecimals(2);\n\n/**\n * Formats a USD amount capped at 2 fractional digits, falling back to the\n * {@link NA_AMOUNT_ASSET_UI} placeholder when the amount is absent.\n */\nexport function formattedUsdPrice(\n amount: BlockchainAmount | null,\n locale: string\n): FormattedAmountAssetUi {\n if (!amount) return NA_AMOUNT_ASSET_UI;\n return usdAmount(\n formatAmount(amount, locale, { maxFractionDigits: USD_FRACTION_DIGITS })\n );\n}\n","import { parseUnits } from 'viem';\nimport {\n type AssetDecimals,\n assertUint256,\n BlockchainAmount,\n MAX_UINT_256,\n} from '@/shared/types/blockchain/core';\nimport { ValidationError } from '@/shared/types/errors';\n\n/** A typed, i18n-agnostic reason a raw amount string failed to parse. */\nexport type AmountParseErrorReason =\n | { type: 'empty' }\n | { type: 'negative' }\n | { type: 'invalid-format' }\n | { type: 'too-many-decimals'; maxDecimals: AssetDecimals }\n /** Scaled up by `decimals`, the amount no longer fits a uint256. */\n | { type: 'overflow' };\n\nexport type AmountParseResult =\n | { valid: true; amount: BlockchainAmount }\n | { valid: false; reason: AmountParseErrorReason };\n\n/**\n * Wraps a raw uint256 base-unit string — what Ondo and the on-chain reads\n * return (\"100000000\" is 100 USDC, not 100 wei-of-nothing) — in a\n * {@link BlockchainAmount} at the given decimals. The value is already scaled,\n * so `decimals` is only the unit tag that travels with it.\n *\n * Distinct from {@link parseBlockchainAmount}, which takes a *human decimal*\n * string and scales it up. Feeding a raw amount to that one silently\n * multiplies it by 10^decimals — pick by what the backend sends, not by which\n * one is closer at hand.\n *\n * @throws ValidationError when the string is not a non-negative uint256\n * integer. A backend that regresses to decimal strings fails loudly here\n * rather than truncating.\n */\nexport function blockchainAmountFromRawOrThrow({\n label,\n raw,\n decimals,\n}: {\n label: string;\n raw: string;\n decimals: AssetDecimals;\n}): BlockchainAmount {\n const trimmed = raw.trim();\n // BigInt('') is 0n, not an error — an absent amount must not read as zero.\n if (trimmed === '') {\n throw new ValidationError(`${label}: not a uint256 integer (\"${raw}\")`);\n }\n let value: bigint;\n try {\n // BigInt() rejects \"0.5\", \"abc\" and \"1e18\" by throwing SyntaxError.\n value = BigInt(trimmed);\n } catch {\n throw new ValidationError(`${label}: not a uint256 integer (\"${raw}\")`);\n }\n try {\n return BlockchainAmount({ raw: assertUint256(value), decimals });\n } catch {\n throw new ValidationError(`${label}: out of uint256 bounds (${value})`);\n }\n}\n\n/**\n * Parses a user-entered decimal string into a {@link BlockchainAmount} at the\n * given token decimals. Rejects scientific notation, negatives, malformed\n * input, more fractional digits than the token supports, and amounts that\n * scale past uint256 — surfacing a typed {@link AmountParseErrorReason} so\n * callers own the display copy.\n */\nexport function parseBlockchainAmount(\n amount: string,\n decimals: AssetDecimals\n): AmountParseResult {\n const trimmed = amount.trim();\n if (trimmed === '') return { valid: false, reason: { type: 'empty' } };\n if (trimmed.startsWith('-')) {\n return { valid: false, reason: { type: 'negative' } };\n }\n // viem accepts \"1e18\" as scientific notation — reject it explicitly\n if (/[eE]/.test(trimmed)) {\n return { valid: false, reason: { type: 'invalid-format' } };\n }\n // reject bare decimal point or missing digits on either side\n if (!/^\\d+(\\.\\d+)?$/.test(trimmed)) {\n return { valid: false, reason: { type: 'invalid-format' } };\n }\n const [, fraction = ''] = trimmed.split('.');\n if (fraction.length > decimals) {\n return {\n valid: false,\n reason: { type: 'too-many-decimals', maxDecimals: decimals },\n };\n }\n try {\n // parseUnits is unbounded: a long enough input scales past uint256, which\n // no on-chain amount can hold. Reporting it as valid would send a\n // truncated or reverting value to a contract.\n const raw = parseUnits(trimmed, decimals);\n if (raw > MAX_UINT_256) {\n return { valid: false, reason: { type: 'overflow' } };\n }\n return {\n valid: true,\n amount: BlockchainAmount({ raw, decimals }),\n };\n } catch {\n return { valid: false, reason: { type: 'invalid-format' } };\n }\n}\n","import type { PaginatedResponseDto } from '@/shared/types/dto/pagination';\nimport type { QueryParamValue } from '@/shared/types/http';\nimport type { Newtype } from '@/shared/types/newtype';\n\nexport type Cursor = Newtype<string, 'Cursor'>;\nexport const Cursor = (value: string) => value as Cursor;\n\n/**\n * Cursor-based pagination input used when requesting paginated API resources.\n * Set `after` or `before` to navigate relative to a known cursor, and `limit`\n * to control the maximum number of returned items.\n */\nexport interface PaginationParams {\n before?: Cursor;\n after?: Cursor;\n limit?: number;\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n startingAfter: Cursor | null;\n startingBefore: Cursor | null;\n}\n\nexport const PaginatedResponse = {\n fromDto: <A, B>(\n dto: PaginatedResponseDto<A>,\n itemMapper: (item: A) => B\n ): PaginatedResponse<B> => ({\n data: dto.data.map(itemMapper),\n startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,\n startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null,\n }),\n};\n\nexport const PaginationParams = {\n toQueryParams: (\n params: PaginationParams\n ): Record<string, QueryParamValue> => {\n const queryParams: Record<string, QueryParamValue> = {};\n if (params.after) {\n queryParams.starting_after = params.after;\n }\n if (params.before) {\n queryParams.starting_before = params.before;\n }\n if (params.limit) {\n queryParams.limit = params.limit;\n }\n return queryParams;\n },\n};\n","import type { AssetDto } from '@/shared/types/dto/asset';\nimport type { Newtype } from '@/shared/types/newtype';\n\nexport type AssetId = Newtype<string, 'AssetId'>;\nexport const AssetId = (value: string) => value as AssetId;\n\nexport type AssetCode = Newtype<string, 'AssetCode'>;\nexport const AssetCode = (value: string) => value as AssetCode;\n\nexport type Asset = {\n id: AssetId;\n code: AssetCode;\n name: string;\n fractionalDigits: number;\n};\n\nexport const Asset = {\n fromDto: (dto: AssetDto): Asset => ({\n id: AssetId(dto.id),\n code: AssetCode(dto.code),\n name: dto.name,\n fractionalDigits: dto.fractional_digits,\n }),\n};\n","import type { OfferDto, OfferTypeDto } from '@/shared/types/dto/offer';\nimport type { Newtype } from '@/shared/types/newtype';\n\nexport type OfferId = Newtype<string, 'OfferId'>;\nexport const OfferId = (value: string) => value as OfferId;\n\nexport type OfferSlug = Newtype<string, 'OfferSlug'>;\nexport const OfferSlug = (value: string) => value as OfferSlug;\n\nexport type OfferType = OfferTypeDto;\n\nexport type Offer = {\n id: OfferId;\n slug: OfferSlug;\n type: OfferType;\n tagline: string;\n bannerUrl: string;\n logoUrl: string;\n startsAt: Date;\n endsAt: Date | null;\n};\n\nexport const Offer = {\n fromDto: (dto: OfferDto): Offer => ({\n id: OfferId(dto.id),\n slug: OfferSlug(dto.slug),\n type: dto.type,\n tagline: dto.tagline,\n bannerUrl: dto.banner_url,\n logoUrl: dto.logo_url,\n startsAt: new Date(dto.starts_at),\n endsAt: dto.ends_at ? new Date(dto.ends_at) : null,\n }),\n};\n","/**\n * Computes SHA-256 digest of the input (UTF-8 string or raw bytes).\n * Uses the Web Crypto API.\n */\nexport async function sha256(data: string | Uint8Array): Promise<ArrayBuffer> {\n const bytes =\n typeof data === 'string' ? new TextEncoder().encode(data) : data;\n const buffer = bytes.buffer.slice(\n bytes.byteOffset,\n bytes.byteOffset + bytes.byteLength\n ) as ArrayBuffer;\n return crypto.subtle.digest('SHA-256', buffer);\n}\n\n/**\n * Converts an ArrayBuffer to Base64-URL encoding (RFC 4648).\n * @param padding - If false, omits trailing '=' padding (e.g. for PKCE).\n */\nexport function arrayBufferToBase64Url(\n buffer: ArrayBuffer,\n padding: boolean = true\n): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n let base64 = btoa(binary);\n base64 = base64.replace(/\\+/g, '-').replace(/\\//g, '_');\n if (!padding) {\n base64 = base64.replace(/=+$/, '');\n }\n return base64;\n}\n\n/**\n * Securely generates random bytes and returns them as Base64-URL (no padding).\n * Suitable for PKCE code_verifier and OAuth state.\n * @param byteLength - Number of random bytes (e.g. 32 for PKCE).\n */\nexport function generateSecureRandomBase64Url(byteLength: number): string {\n const bytes = new Uint8Array(byteLength);\n crypto.getRandomValues(bytes);\n const buffer = bytes.buffer;\n return arrayBufferToBase64Url(buffer, false);\n}\n\n/**\n * Generate a UUID v4 using the standard Web Crypto API (crypto.randomUUID).\n * Falls back to RFC 4122–compliant generation via crypto.getRandomValues in old browsers.\n */\nexport function getUUIDv4(): string {\n if (\n typeof crypto !== 'undefined' &&\n typeof crypto.randomUUID === 'function'\n ) {\n return crypto.randomUUID();\n }\n\n if (\n typeof crypto !== 'undefined' &&\n typeof crypto.getRandomValues === 'function'\n ) {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0'));\n return `${hex.slice(0, 4).join('')}-${hex.slice(4, 6).join('')}-${hex.slice(6, 8).join('')}-${hex.slice(8, 10).join('')}-${hex.slice(10, 16).join('')}`;\n }\n\n return `${Date.now()}-${Math.random().toString(36).slice(2, 12)}`;\n}\n\nexport function notBlankStringOrNull(value?: string | null): string | null {\n if (value?.trim()) {\n return value;\n } else {\n return null;\n }\n}\n","import { notBlankStringOrNull } from '@/shared/core/utils/crypto';\nimport { Asset } from '@/shared/types/asset';\nimport { Chain, EvmContractAddress } from '@/shared/types/blockchain/core';\nimport type {\n OfferDetailDto,\n OfferDetailFaqDto,\n OfferDetailLinkDto,\n OfferDetailMilestoneDto,\n OfferDetailOptionDto,\n OfferDetailTermDto,\n OfferDetailTokenDto,\n} from '@/shared/types/dto/offer-detail';\nimport type { Newtype } from '@/shared/types/newtype';\nimport { OfferId, OfferSlug, type OfferType } from '@/shared/types/offer';\n\nexport type OfferDetail = {\n id: OfferId;\n slug: OfferSlug;\n type: OfferType;\n name: string;\n\n asset: Asset;\n fundingAssets: Asset[];\n tokens: OfferToken[];\n\n about: string | null;\n tagline: string;\n bannerUrl: string;\n logoUrl: string;\n category: string;\n\n startsAt: Date;\n endsAt: Date | null;\n\n faqs: FaqItem[];\n links: Link[];\n milestones: Milestone[];\n options: OfferOption[];\n terms: TermItem[];\n};\n\nexport type OfferOptionId = Newtype<string, 'OfferOptionId'>;\nexport const OfferOptionId = (value: string) => value as OfferOptionId;\n\nexport type OfferOptionSlug = Newtype<string, 'OfferOptionSlug'>;\nexport const OfferOptionSlug = (value: string) => value as OfferOptionSlug;\n\nexport type OfferOption = {\n id: OfferOptionId;\n slug: OfferOptionSlug;\n bidIncrement: number | null;\n floorPriceUsd: number | null;\n minimumPurchaseUsd: number | null;\n priceUsd: string | null;\n saleAgreementUrl: string | null;\n totalTokenSupply: number | null;\n};\n\nexport type FaqItem = {\n question: string | null;\n answer: string | null;\n};\n\nexport type TermItem = {\n key: string | null;\n value: string | null;\n};\n\nexport type Milestone = {\n name: string | null;\n schedule: string | null;\n status: 'completed' | 'active' | 'upcoming';\n};\n\nexport type Link = {\n label: string | null;\n url: string | null;\n};\n\nexport const OfferDetail = {\n fromDto: (dto: OfferDetailDto): OfferDetail => {\n if (!Array.isArray(dto.funding_assets)) {\n throw new Error(`funding_assets must be an array`);\n }\n\n if (!Array.isArray(dto.options)) {\n throw new Error(`options must be an array`);\n }\n\n if (!Array.isArray(dto.terms)) {\n throw new Error(`terms must be an array`);\n }\n\n if (!Array.isArray(dto.links)) {\n throw new Error(`links must be an array`);\n }\n\n if (!Array.isArray(dto.faqs)) {\n throw new Error(`faqs must be an array`);\n }\n\n if (!Array.isArray(dto.milestones)) {\n throw new Error(`milestones must be an array`);\n }\n\n if (!Array.isArray(dto.tokens)) {\n throw new Error(`tokens must be an array`);\n }\n\n return {\n id: OfferId(dto.id),\n slug: OfferSlug(dto.slug),\n type: dto.type,\n name: dto.name,\n\n asset: Asset.fromDto(dto.asset),\n fundingAssets: dto.funding_assets.map(Asset.fromDto),\n tokens: dto.tokens.map(OfferToken.fromDto),\n\n about: notBlankStringOrNull(dto.about),\n tagline: dto.tagline,\n bannerUrl: dto.banner_url,\n logoUrl: dto.logo_url,\n category: dto.category,\n\n startsAt: new Date(dto.starts_at),\n endsAt: dto.ends_at ? new Date(dto.ends_at) : null,\n\n faqs: dto.faqs.map(FaqItem.fromDto),\n links: dto.links.map(Link.fromDto),\n milestones: dto.milestones.map(Milestone.fromDto),\n options: dto.options.map(OfferOption.fromDto),\n terms: dto.terms.map(TermItem.fromDto),\n };\n },\n};\n\nexport const OfferOption = {\n fromDto: (dto: OfferDetailOptionDto): OfferOption => ({\n id: OfferOptionId(dto.id),\n slug: OfferOptionSlug(dto.slug),\n bidIncrement: dto.bid_increment,\n floorPriceUsd: dto.floor_price_usd,\n minimumPurchaseUsd: dto.minimum_purchase_usd,\n priceUsd: dto.price_usd,\n saleAgreementUrl: notBlankStringOrNull(dto.sale_agreement_url),\n totalTokenSupply: dto.total_token_supply,\n }),\n};\n\nexport const FaqItem = {\n fromDto: (dto: OfferDetailFaqDto): FaqItem => ({\n question: notBlankStringOrNull(dto.question),\n answer: notBlankStringOrNull(dto.answer),\n }),\n};\n\nexport const Link = {\n fromDto: (dto: OfferDetailLinkDto): Link => ({\n label: notBlankStringOrNull(dto.label),\n url: notBlankStringOrNull(dto.url),\n }),\n};\n\nexport const TermItem = {\n fromDto: (dto: OfferDetailTermDto): TermItem => ({\n key: notBlankStringOrNull(dto.key),\n value: notBlankStringOrNull(dto.value),\n }),\n};\n\nexport const Milestone = {\n fromDto: (dto: OfferDetailMilestoneDto): Milestone => ({\n name: notBlankStringOrNull(dto.name),\n schedule: notBlankStringOrNull(dto.schedule),\n status: dto.status,\n }),\n};\n\nexport type TokenRole = 'funding' | 'distribution' | 'swap';\n\nexport type OfferToken = {\n role: TokenRole;\n chain: Chain;\n address: EvmContractAddress;\n};\n\nexport const OfferToken = {\n fromDto: (dto: OfferDetailTokenDto): OfferToken => ({\n role: dto.role,\n chain: Chain(dto.chain),\n address: EvmContractAddress(dto.address),\n }),\n};\n","import { notBlankStringOrNull } from '@/shared/core/utils/crypto';\nimport { Asset, type AssetId } from '@/shared/types/asset';\nimport type {\n CreateParticipationDto,\n ParticipationDto,\n ParticipationStatusDto,\n} from '@/shared/types/dto/providers/coin-list/token-sale';\nimport type { QueryParamValue } from '@/shared/types/http';\nimport type { Newtype } from '@/shared/types/newtype';\nimport { OfferId, type OfferId as OfferIdType } from '@/shared/types/offer';\nimport {\n OfferOptionId,\n type OfferOptionId as OfferOptionIdType,\n} from '@/shared/types/offer-detail';\nimport { PaginationParams } from '@/shared/types/pagination';\n\n/** Unique identifier for a participation. */\nexport type ParticipationId = Newtype<string, 'ParticipationId'>;\n/** Casts a string into a typed {@link ParticipationId}. */\nexport const ParticipationId = (value: string) => value as ParticipationId;\n\n/** Blockchain identifier for where a participation is funded. */\nexport type Blockchain = Newtype<string, 'Blockchain'>;\n/** Casts a string into a typed {@link Blockchain}. */\nexport const Blockchain = (value: string) => value as Blockchain;\n\n/** Wallet address used for a participation. */\nexport type WalletAddress = Newtype<`0x${string}`, 'WalletAddress'>;\n/** Casts a `0x`-prefixed string into a typed {@link WalletAddress}. */\nexport const WalletAddress = (value: `0x${string}`) => value as WalletAddress;\n\n/** Possible participation lifecycle states returned by the API. */\nexport type ParticipationStatus = ParticipationStatusDto;\n\n/** Domain model for a participation returned by CoinList APIs. */\nexport type Participation = {\n /** Unique participation id. */\n id: ParticipationId;\n /** Parent offer id. */\n offerId: OfferIdType;\n /** Selected offer option id. */\n offerOptionId: OfferOptionIdType;\n /** Current processing status. */\n status: ParticipationStatus;\n /** Raw participation amount from API. */\n amount: string;\n /** Human-readable formatted amount from API. */\n displayAmount: string;\n /** Asset metadata for the participation amount. */\n asset: Asset;\n /** Funding chain identifier. */\n chain: Blockchain;\n /** Creation timestamp, if returned by API. */\n insertedAt: Date | null;\n /** Last update timestamp, if returned by API. */\n updatedAt: Date | null;\n /** Wallet used for participation, blank values normalized to null. */\n walletAddress: WalletAddress | null;\n};\n\n/** Parameters required to create a new participation. */\nexport type CreateParticipationParams = {\n /** Offer to participate in. */\n offerId: OfferIdType;\n /** Offer option selected for participation. */\n offerOptionId: OfferOptionIdType;\n /** Blockchain for funding. */\n chain: Blockchain;\n /** Wallet address that funds the participation. */\n walletAddress: WalletAddress;\n /**\n * Decimal token amount to participate with (e.g. `\"100\"` for 100 USDC), NOT\n * raw base units. The backend rescales this by the asset's decimals to verify\n * it against the on-chain approval allowance.\n */\n amount: string;\n /** Funding asset id. */\n assetId: AssetId;\n /**\n * Hash of the ERC-20 `approve()` transaction covering this participation.\n * Required: the backend verifies it on-chain (sender, token, spender, and\n * approved amount) before confirming the participation.\n */\n approvalTransactionHash: string;\n};\n\n/** Pagination params for listing participations, with an optional offer filter. */\nexport interface ParticipationsPaginationParams extends PaginationParams {\n offerId?: OfferIdType;\n}\n\nexport const ParticipationsPaginationParams = {\n toQueryParams: (\n params: ParticipationsPaginationParams\n ): Record<string, QueryParamValue> => {\n const queryParams = PaginationParams.toQueryParams(params);\n if (params.offerId) {\n queryParams['filters[0][field]'] = 'offer_id';\n queryParams['filters[0][op]'] = '==';\n queryParams['filters[0][value]'] = params.offerId;\n }\n return queryParams;\n },\n};\n\nexport const Participation = {\n /** Maps API DTO shape into the SDK participation domain model. */\n fromDto: (dto: ParticipationDto): Participation => {\n const walletAddress = notBlankStringOrNull(dto.wallet_address);\n return {\n id: ParticipationId(dto.id),\n offerId: OfferId(dto.offer_id),\n offerOptionId: OfferOptionId(dto.offer_option_id),\n status: dto.status,\n amount: dto.amount,\n displayAmount: dto.amount_string,\n asset: Asset.fromDto(dto.asset),\n chain: Blockchain(dto.chain),\n insertedAt: dto.inserted_at ? new Date(dto.inserted_at) : null,\n updatedAt: dto.updated_at ? new Date(dto.updated_at) : null,\n walletAddress: walletAddress\n ? WalletAddress(walletAddress as `0x${string}`)\n : null,\n };\n },\n};\n\nexport const CreateParticipationParams = {\n /** Maps participation creation params into API DTO payload. */\n toDto: (params: CreateParticipationParams): CreateParticipationDto => ({\n offer_id: params.offerId,\n offer_option_id: params.offerOptionId,\n chain: params.chain,\n wallet_address: params.walletAddress,\n amount: params.amount,\n asset_id: params.assetId,\n approval_transaction_hash: params.approvalTransactionHash,\n }),\n};\n","import { Attributes } from '@/shared/api/http-attributes';\nimport type { Sender } from '@/shared/api/http-client';\nimport { fetchAllPages } from '@/shared/api/pagination';\nimport type { PaginatedResponseDto } from '@/shared/types/dto/pagination';\nimport type { ParticipationDto } from '@/shared/types/dto/providers/coin-list/token-sale';\nimport type { OfferId } from '@/shared/types/offer';\nimport { PaginatedResponse } from '@/shared/types/pagination';\nimport {\n CreateParticipationParams,\n Participation,\n type ParticipationId,\n ParticipationsPaginationParams,\n} from '@/shared/types/providers/coin-list/token-sale';\n\nexport async function fetchParticipations(\n api: Sender,\n offerId?: OfferId\n): Promise<Participation[]> {\n return fetchAllPages<Participation, ParticipationsPaginationParams>(\n (params) => fetchParticipationsPage(api, params),\n { offerId }\n );\n}\n\nexport async function fetchParticipationsPage(\n api: Sender,\n params: ParticipationsPaginationParams\n): Promise<PaginatedResponse<Participation>> {\n const pageDto = await api.send<PaginatedResponseDto<ParticipationDto>>({\n method: 'GET',\n url: '/v1/participations',\n queryParams: ParticipationsPaginationParams.toQueryParams(params),\n attributes: Attributes.protected(),\n });\n return PaginatedResponse.fromDto(pageDto, Participation.fromDto);\n}\n\nexport async function fetchParticipation(\n api: Sender,\n id: ParticipationId\n): Promise<Participation> {\n const dto = await api.send<ParticipationDto>({\n method: 'GET',\n url: `/v1/participations/${id}`,\n attributes: Attributes.protected(),\n });\n return Participation.fromDto(dto);\n}\n\nexport async function createParticipation(\n api: Sender,\n params: CreateParticipationParams\n): Promise<Participation> {\n const dto = await api.send<ParticipationDto>({\n method: 'POST',\n url: '/v1/participations',\n body: CreateParticipationParams.toDto(params),\n attributes: Attributes.protected(),\n });\n return Participation.fromDto(dto);\n}\n","import * as participationsApi from '@/shared/api/frontline/providers/coin-list/token-sale';\nimport type { SharedNamespaceContext } from '@/shared/core/namespace-context';\nimport type { OfferId } from '@/shared/types/offer';\nimport type { PaginatedResponse } from '@/shared/types/pagination';\nimport type {\n CreateParticipationParams,\n Participation,\n ParticipationId,\n ParticipationsPaginationParams,\n} from '@/shared/types/providers/coin-list/token-sale';\n\n/**\n * Read/write operations for token sales: listing and reading the current user's\n * participations, and recording a new one. The on-chain execution flow\n * (`executeTokenSale`) is layered on top of this in the client-side namespace.\n */\nexport interface CoinListTokenSaleNamespace {\n /**\n * Fetches all participations by iterating through every paginated response,\n * optionally filtered by offer.\n *\n * Requires an authenticated user; throws {@link NotAuthenticatedError}\n * otherwise.\n */\n list(offerId?: OfferId): Promise<Participation[]>;\n\n /**\n * Fetches a single page of participations, optionally filtered by offer.\n *\n * Requires an authenticated user; throws {@link NotAuthenticatedError}\n * otherwise.\n */\n listPage(\n params: ParticipationsPaginationParams\n ): Promise<PaginatedResponse<Participation>>;\n\n /**\n * Fetches a participation by id.\n *\n * Requires an authenticated user; throws {@link NotAuthenticatedError}\n * otherwise.\n */\n get(id: ParticipationId): Promise<Participation>;\n\n /**\n * Records a participation with CoinList.\n *\n * Requires an authenticated user; throws {@link NotAuthenticatedError}\n * otherwise.\n */\n createParticipation(\n params: CreateParticipationParams\n ): Promise<Participation>;\n}\n\nexport class CoinListTokenSaleNamespaceImpl\n implements CoinListTokenSaleNamespace\n{\n constructor(private readonly ctx: SharedNamespaceContext) {}\n\n async list(offerId?: OfferId): Promise<Participation[]> {\n await this.ctx.ensureUserAuthenticated();\n return participationsApi.fetchParticipations(this.ctx.api, offerId);\n }\n\n async listPage(\n params: ParticipationsPaginationParams\n ): Promise<PaginatedResponse<Participation>> {\n await this.ctx.ensureUserAuthenticated();\n return participationsApi.fetchParticipationsPage(this.ctx.api, params);\n }\n\n async get(id: ParticipationId): Promise<Participation> {\n await this.ctx.ensureUserAuthenticated();\n return participationsApi.fetchParticipation(this.ctx.api, id);\n }\n\n async createParticipation(\n params: CreateParticipationParams\n ): Promise<Participation> {\n await this.ctx.ensureUserAuthenticated();\n return participationsApi.createParticipation(this.ctx.api, params);\n }\n}\n","import type { Newtype } from '@/shared/types/newtype';\n\nexport type Ticker = Newtype<string, 'Ticker'>;\nexport const Ticker = (value: string): Ticker => value as Ticker;\n\nexport type OrderBookSide = 'buy' | 'sell';\n","import { chainFromId } from '@/shared/core/blockchain/chain';\nimport { blockchainAmountFromRawOrThrow } from '@/shared/core/blockchain/math';\nimport {\n AssetDecimals,\n AssetSymbol,\n type BlockchainAmount,\n DecimalString,\n type Erc20Asset,\n type EthereumChain,\n EvmContractAddress,\n HexEncodedTransactionData,\n type Tx,\n} from '@/shared/types/blockchain/core';\nimport type {\n OndoQuoteDto,\n OndoSwapTransactionDto,\n OndoTradingStatusDto,\n} from '@/shared/types/dto/providers/ondo/ondo';\nimport { ValidationError } from '@/shared/types/errors';\nimport { type OrderBookSide, Ticker } from '@/shared/types/trading';\n\n/**\n * Whether an Ondo asset can be traded right now.\n *\n * The caps only mean anything while trading is open, so they live on the\n * `tradable` branch. They stay {@link DecimalString} rather than\n * {@link BlockchainAmount} because the response carries no `asset_decimals`:\n * there is no honest exponent to attach, and the USD caps arrive with more\n * fractional digits than a stablecoin has decimals.\n *\n * Each cap is independently nullable even when tradable — Ondo may open an\n * asset for trading without publishing every limit.\n *\n * `side` is carried through from the response rather than dropped: the whole\n * status describes one side, so a buy and a sell status are otherwise\n * indistinguishable once a caller holds both.\n */\nexport type OndoTradingStatus =\n | {\n type: 'tradable';\n side: OrderBookSide;\n /** Largest order in whole tokens. */\n grossMaxTokens: DecimalString | null;\n /** Largest order in USD. */\n grossMaxNotionalValue: DecimalString | null;\n /** USD cap for the session the market is currently in. */\n grossMaxActiveNotionalValue: DecimalString | null;\n }\n | {\n type: 'not-tradable';\n side: OrderBookSide;\n };\n\nexport const OndoTradingStatus = {\n fromDto: (dto: OndoTradingStatusDto): OndoTradingStatus => {\n if (!dto.tradable) return { type: 'not-tradable', side: dto.side };\n return {\n type: 'tradable',\n side: dto.side,\n grossMaxTokens: decimalOrNull(dto.gross_max_tokens),\n grossMaxNotionalValue: decimalOrNull(dto.gross_max_notional_value),\n grossMaxActiveNotionalValue: decimalOrNull(\n dto.gross_max_active_notional_value\n ),\n };\n },\n};\n\nconst decimalOrNull = (value: string | null): DecimalString | null =>\n value === null ? null : DecimalString(value);\n\n/**\n * An indicative price for an Ondo asset, free to poll while the user edits an\n * order.\n *\n * **No CoinList fee is applied to the quantity or the price.** Ondo prices\n * exactly the amount asked for. A CoinList approval is fee-inclusive, so\n * sizing a quote against one without netting the fee first overstates what the\n * user receives. Showing a gross/net breakdown needs a CoinList swap\n * contract's `preview`, and no such contract exists for Ondo yet.\n *\n * The quote carries no transaction to broadcast and no expiry. Building one is\n * a separate endpoint that spends an attestation - see\n * {@link OndoSwapTransaction}.\n */\nexport type OndoQuote = {\n /** Always `ethereum_mainnet`: Ondo runs no sandbox in any environment. */\n chain: EthereumChain;\n ticker: Ticker;\n /** Needed to approve or transfer the asset; the quote is the only source. */\n assetAddress: EvmContractAddress;\n /**\n * The asset as the quote resolves it, from frontline's own catalogue.\n *\n * Its `decimals` scale {@link tokenBaseUnits} and nothing else. They are\n * **not** the scale of an {@link OndoSwapTransaction}'s output: that one is\n * reported by whatever priced the quantity, the two sources are allowed to\n * disagree, and only the one that produced a number answers for it.\n */\n asset: Erc20Asset;\n side: OrderBookSide;\n tokenBaseUnits: BlockchainAmount;\n /**\n * USD price of one whole token. Unscaled because Ondo has already scaled it,\n * and by USDon's 18 decimals rather than the stablecoin's 6 — re-scaling it\n * by either would be wrong.\n */\n price: DecimalString;\n};\n\nexport const OndoQuote = {\n fromDto: (dto: OndoQuoteDto): OndoQuote => {\n const assetDecimals = AssetDecimals(dto.asset_decimals);\n return {\n chain: chainFromId(dto.chain_id),\n ticker: Ticker(dto.ticker),\n assetAddress: EvmContractAddress(dto.asset_address),\n asset: {\n name: dto.ticker,\n symbol: AssetSymbol(dto.symbol),\n decimals: assetDecimals,\n },\n side: dto.side,\n tokenBaseUnits: blockchainAmountFromRawOrThrow({\n label: 'tokenBaseUnits',\n raw: dto.token_base_units,\n decimals: assetDecimals,\n }),\n price: DecimalString(dto.price),\n };\n },\n};\n\n/**\n * A signed, expiring buy: the calldata that fills it and the amounts it\n * commits to, from `buildSwapTransaction`.\n *\n * Distinct from {@link OndoQuote} in three ways that matter: it costs an\n * attestation to obtain, it expires, and it carries a {@link Tx} the wallet\n * broadcasts verbatim. Treat it as single-use - once broadcast (or once\n * `expiresAt` passes) it is spent, and a new one must be built.\n *\n * **It carries no identity.** No chain, ticker, asset or side: the endpoint\n * publishes none of them, and inventing them from the request would assert\n * what the server resolved rather than report it. What it does publish is the\n * scale of every amount on it, so a caller needs nothing alongside it to read\n * the numbers - only to name the asset, which the offer already does.\n *\n * It carries no price either. Divide {@link notionalValue} by\n * {@link receiveOutputAmount} - see `computeOndoPrice` - which is the price\n * this transaction actually fills at rather than an indicative one that has\n * since moved.\n */\nexport type OndoSwapTransaction = {\n /**\n * Broadcast as-is. The `to` is the swap contract, which is also the ERC-20\n * spender the user must have approved.\n */\n tx: Tx;\n /**\n * When the calldata stops being accepted. A transaction broadcast after this\n * reverts, so callers must compare against it before signing.\n */\n expiresAt: Date;\n /** Gross amount the wallet pays, in the funding token's decimals. */\n payInputAmount: BlockchainAmount;\n /**\n * CoinList's cut of {@link payInputAmount}, in the same decimals. Taken off\n * the deposit rather than added on top, so the approval never has to cover\n * more than `payInputAmount`. Zero until ENG-1718 lands.\n */\n fee: BlockchainAmount;\n /**\n * `payInputAmount` less `fee`, in the same decimals: what Ondo priced.\n *\n * Read from the response rather than subtracted here. Whether the fee comes\n * off the deposit or goes on top of it is the server's definition to change,\n * and a client that derives this cannot notice when it does.\n */\n notionalValue: BlockchainAmount;\n /**\n * What the buyer receives, at the scale whatever priced the quantity\n * reported - not at the {@link OndoQuote}'s.\n */\n receiveOutputAmount: BlockchainAmount;\n};\n\nexport const OndoSwapTransaction = {\n fromDto: (dto: OndoSwapTransactionDto): OndoSwapTransaction => {\n // Read once each, so a mapper that reached for the wrong exponent on one\n // of the four amounts is a visible mistake rather than a plausible one.\n const inputDecimals = AssetDecimals(dto.pay_input_decimals);\n const outputDecimals = AssetDecimals(dto.receive_output_decimals);\n return {\n tx: {\n to: EvmContractAddress(dto.to),\n data: HexEncodedTransactionData(dto.data),\n },\n expiresAt: parseExpiresAt(dto.expires_at),\n payInputAmount: blockchainAmountFromRawOrThrow({\n label: 'pay_input_amount',\n raw: dto.pay_input_amount,\n decimals: inputDecimals,\n }),\n fee: blockchainAmountFromRawOrThrow({\n label: 'fee',\n raw: dto.fee,\n decimals: inputDecimals,\n }),\n notionalValue: blockchainAmountFromRawOrThrow({\n label: 'notional_value',\n raw: dto.notional_value,\n decimals: inputDecimals,\n }),\n receiveOutputAmount: parseReceiveOutputAmount(\n dto.receive_output_amount,\n outputDecimals\n ),\n };\n },\n};\n\n/**\n * A transaction that yields nothing is not one to sign - the user would pay\n * the deposit and receive no asset - and frontline refuses to emit one\n * (`validate_number(:receive_output_amount, greater_than: 0)`). A zero here is\n * therefore a changed encoding, not a small order.\n *\n * Rejecting it at the boundary is also what lets `computeOndoPrice` divide by\n * it without a fallible result: the failure surfaces as the data hook's ERROR\n * state rather than as a division during render.\n */\nfunction parseReceiveOutputAmount(\n raw: string,\n decimals: AssetDecimals\n): BlockchainAmount {\n const amount = blockchainAmountFromRawOrThrow({\n label: 'receive_output_amount',\n raw,\n decimals,\n });\n if (amount.raw <= 0n) {\n throw new ValidationError(\n `receive_output_amount: must be greater than zero (\"${raw}\")`\n );\n }\n return amount;\n}\n\n/**\n * A transaction whose expiry cannot be read is not safely fillable - the\n * deadline is encoded in the calldata either way, so broadcasting against an\n * unknown one only spends gas on a revert. Fail here instead.\n */\nfunction parseExpiresAt(value: string): Date {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n throw new ValidationError(`expires_at: not a date (\"${value}\")`);\n }\n return date;\n}\n","import type { QueryParamValues } from '@/shared/api/http';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type { Sender } from '@/shared/api/http-client';\nimport { formatRawAmount } from '@/shared/core/blockchain/formatters';\nimport type {\n BuildOndoSwapTransactionParams,\n GetOndoQuoteParams,\n GetOndoTradingStatusParams,\n} from '@/shared/core/checkout/ondo/ondo-namespace.types';\nimport type {\n OndoQuoteDto,\n OndoSwapTransactionDto,\n OndoTradingStatusDto,\n} from '@/shared/types/dto/providers/ondo/ondo';\nimport { ValidationError } from '@/shared/types/errors';\nimport {\n OndoQuote,\n OndoSwapTransaction,\n OndoTradingStatus,\n} from '@/shared/types/providers/ondo/ondo';\n\nexport async function getOndoTradingStatus(\n api: Sender,\n params: GetOndoTradingStatusParams\n): Promise<OndoTradingStatus> {\n const dto = await api.send<OndoTradingStatusDto>({\n method: 'GET',\n url: '/v1/ondo/swap/trading-status',\n queryParams: { symbol: params.symbol, side: params.side },\n attributes: Attributes.protected(),\n });\n return OndoTradingStatus.fromDto(dto);\n}\n\nexport async function getOndoQuote(\n api: Sender,\n params: GetOndoQuoteParams\n): Promise<OndoQuote> {\n const dto = await api.send<OndoQuoteDto>({\n method: 'GET',\n url: '/v1/ondo/swap/quote',\n queryParams: {\n symbol: params.symbol,\n side: params.side,\n duration: params.duration,\n ...sizeParam(params),\n },\n attributes: Attributes.protected(),\n });\n return OndoQuote.fromDto(dto);\n}\n\n/**\n * Builds the transaction that fills a buy: spends an attestation and returns\n * signed calldata with a deadline.\n *\n * `amount` goes out in **base units**, unlike `getOndoQuote`'s `token_amount`\n * which is in whole tokens: this number becomes the ERC-20 pull encoded into\n * the calldata, so it is the on-chain integer, not a human figure. Frontline\n * refuses zero, and refuses a wallet whose allowance does not cover it with a\n * 422 carrying `code: \"insufficient_allowance\"`.\n *\n * The response carries the scale of every amount on it, so nothing has to\n * travel alongside the request to read them back. `pay_input_decimals` is\n * nonetheless checked against the `amount` that was sent - see\n * {@link assertFundingScaleAgrees}.\n */\nexport async function buildOndoSwapTransaction(\n api: Sender,\n params: BuildOndoSwapTransactionParams\n): Promise<OndoSwapTransaction> {\n const dto = await api.send<OndoSwapTransactionDto>({\n method: 'POST',\n url: '/v1/ondo/swap/transaction',\n body: {\n symbol: params.symbol,\n chain: params.chain,\n wallet_address: params.walletAddress,\n amount: params.amount.raw.toString(),\n },\n attributes: Attributes.protected(),\n });\n assertFundingScaleAgrees(dto, params);\n return OndoSwapTransaction.fromDto(dto);\n}\n\n/**\n * Refuses a response denominated in a different scale than the request was.\n *\n * The two are independent resolutions of the same token: the caller sized\n * `amount` in the coin it chose and approved, while frontline reads\n * `decimals()` on-chain from the funding token it resolves from the offer.\n * They should never differ - an approval on some other token reads as a zero\n * allowance, which frontline refuses before it signs anything - so a\n * disagreement here is a changed encoding rather than a user error, the same\n * reasoning `parseReceiveOutputAmount` rejects a zero output under.\n *\n * Worth the check because of where the value lands: `pay_input_amount` at the\n * wrong exponent renders the review screen's **Total** orders of magnitude out,\n * on the screen where the user commits money.\n */\nfunction assertFundingScaleAgrees(\n dto: OndoSwapTransactionDto,\n params: BuildOndoSwapTransactionParams\n): void {\n if (dto.pay_input_decimals !== params.amount.decimals) {\n throw new ValidationError(\n `pay_input_decimals: the swap was priced in ${dto.pay_input_decimals} decimals but the order was sized in ${params.amount.decimals}`\n );\n }\n}\n\n/**\n * `token_amount` is in **whole tokens**, unlike the response's\n * `token_base_units` — Ondo names both `tokenAmount`, 1e18 apart. Hence the\n * unscale on the way out.\n *\n * The size is checked at runtime because the types do not cover it: TypeScript\n * rejects an object carrying *neither*, but against a union of object types it\n * accepts one carrying *both*, and a JavaScript caller gets no check at all.\n */\nfunction sizeParam(\n params: GetOndoQuoteParams\n): Record<string, QueryParamValues> {\n const tokenAmount = 'tokenAmount' in params ? params.tokenAmount : undefined;\n const notionalValue =\n 'notionalValue' in params ? params.notionalValue : undefined;\n\n if (tokenAmount !== undefined) {\n if (notionalValue !== undefined) {\n throw new ValidationError(\n 'An Ondo quote takes tokenAmount or notionalValue, not both'\n );\n }\n return { token_amount: formatRawAmount(tokenAmount) };\n }\n if (notionalValue === undefined) {\n throw new ValidationError(\n 'An Ondo quote must be sized by tokenAmount or notionalValue'\n );\n }\n return { notional_value: notionalValue };\n}\n","import {\n buildOndoSwapTransaction,\n getOndoQuote,\n getOndoTradingStatus,\n} from '@/shared/api/frontline/providers/ondo/ondo';\nimport type {\n BuildOndoSwapTransactionParams,\n GetOndoQuoteParams,\n GetOndoTradingStatusParams,\n} from '@/shared/core/checkout/ondo/ondo-namespace.types';\nimport type { SharedNamespaceContext } from '@/shared/core/namespace-context';\nimport type {\n OndoQuote,\n OndoSwapTransaction,\n OndoTradingStatus,\n} from '@/shared/types/providers/ondo/ondo';\n\n/**\n * Ondo swap reads, plus the write that turns one into a fillable transaction.\n *\n * The two reads are free to poll - neither spends an attestation, so a client\n * may call them while the user edits an order. {@link buildSwapTransaction} is\n * not: budget one call per order placed, plus one per refresh the user asks\n * for.\n *\n * **No CoinList fee is applied to a read quote, and no read discloses one.**\n * Ondo prices exactly the amount passed. A CoinList approval is fee-inclusive,\n * so sizing a quote against a user's approval without subtracting the fee\n * first overstates what they receive. A built transaction carries the fee\n * explicitly, and it is zero until one lands (ENG-1718).\n *\n * Every method requires `AuthState === 'logged-in'` and throws\n * {@link NotAuthenticatedError} otherwise.\n */\nexport interface OndoNamespace {\n getTradingStatus(\n params: GetOndoTradingStatusParams\n ): Promise<OndoTradingStatus>;\n getQuote(params: GetOndoQuoteParams): Promise<OndoQuote>;\n /**\n * Builds the buy for a specific wallet and amount: spends an attestation and\n * returns calldata to broadcast, valid until\n * {@link OndoSwapTransaction.expiresAt}.\n *\n * The wallet must have approved the swap contract to spend `amount` of the\n * offer's funding token first - frontline reads the allowance before asking\n * Ninshubur for anything, and rejects a short one with a 422 carrying\n * `code: \"insufficient_allowance\"`. See `prepareSwap` on the client\n * namespace, which approves and then builds, in that order.\n *\n * Buy-only, and the tokens are the offer's rather than the caller's to name.\n */\n buildSwapTransaction(\n params: BuildOndoSwapTransactionParams\n ): Promise<OndoSwapTransaction>;\n}\n\nexport class OndoNamespaceImpl implements OndoNamespace {\n constructor(private readonly ctx: SharedNamespaceContext) {}\n\n async getTradingStatus(\n params: GetOndoTradingStatusParams\n ): Promise<OndoTradingStatus> {\n await this.ctx.ensureUserAuthenticated();\n return getOndoTradingStatus(this.ctx.api, params);\n }\n\n async getQuote(params: GetOndoQuoteParams): Promise<OndoQuote> {\n await this.ctx.ensureUserAuthenticated();\n return getOndoQuote(this.ctx.api, params);\n }\n\n async buildSwapTransaction(\n params: BuildOndoSwapTransactionParams\n ): Promise<OndoSwapTransaction> {\n await this.ctx.ensureUserAuthenticated();\n return buildOndoSwapTransaction(this.ctx.api, params);\n }\n}\n","import {\n allowWallet,\n getSwapAuthorization,\n getSwapOutputToken,\n getSwapPreview,\n getSwapStatus,\n} from '@/shared/api/frontline/providers/superstate/swap';\nimport type {\n AllowWalletParams,\n GetSwapAuthorizationParams,\n GetSwapPreviewParams,\n SwapContractRef,\n} from '@/shared/core/checkout/superstate/swap-namespace.types';\nimport type { SharedNamespaceContext } from '@/shared/core/namespace-context';\nimport type { Erc20Asset } from '@/shared/types/blockchain/core';\nimport type {\n AllowWalletResponse,\n SwapAuthorization,\n SwapPreview,\n SwapStatus,\n} from '@/shared/types/providers/superstate/swap';\n\n/**\n * Read/write operations for the on-chain swap flow: quoting a swap, inspecting\n * contract state, checking token allowances, and proving/allow-listing wallet\n * ownership.\n */\nexport interface SuperstateSwapNamespace {\n /**\n * Checks whether a wallet is authorized to swap against the given contract.\n */\n getAuthorization(\n params: GetSwapAuthorizationParams\n ): Promise<SwapAuthorization>;\n\n /**\n * Fetches a read-only quote for swapping `amount` of `inputToken`.\n */\n getPreview(params: GetSwapPreviewParams): Promise<SwapPreview>;\n\n /**\n * Reads the current on-chain state of a swap contract.\n */\n getStatus(params: SwapContractRef): Promise<SwapStatus>;\n\n /**\n * Reads the ERC-20 output token a swap contract pays out.\n */\n getOutputToken(params: SwapContractRef): Promise<Erc20Asset>;\n\n /**\n * Submits a signed wallet-ownership challenge to allow-list the wallet for\n * an offer, identified by its offer id. Obtain the challenge from\n * `WalletsNamespace.createOwnershipChallenge`.\n */\n allowWallet(params: AllowWalletParams): Promise<AllowWalletResponse>;\n}\n\nexport class SuperstateSwapNamespaceImpl implements SuperstateSwapNamespace {\n constructor(private readonly ctx: SharedNamespaceContext) {}\n\n async getAuthorization(\n params: GetSwapAuthorizationParams\n ): Promise<SwapAuthorization> {\n await this.ctx.ensureUserAuthenticated();\n return getSwapAuthorization(this.ctx.api, params);\n }\n\n async getPreview(params: GetSwapPreviewParams): Promise<SwapPreview> {\n await this.ctx.ensureUserAuthenticated();\n return getSwapPreview(this.ctx.api, params);\n }\n\n async getStatus(params: SwapContractRef): Promise<SwapStatus> {\n await this.ctx.ensureUserAuthenticated();\n return getSwapStatus(this.ctx.api, params);\n }\n\n async getOutputToken(params: SwapContractRef): Promise<Erc20Asset> {\n await this.ctx.ensureUserAuthenticated();\n return getSwapOutputToken(this.ctx.api, params);\n }\n\n async allowWallet(params: AllowWalletParams): Promise<AllowWalletResponse> {\n await this.ctx.ensureUserAuthenticated();\n return allowWallet(this.ctx.api, params);\n }\n}\n","import type {\n DocumentFormTypeDto,\n DocumentSubmissionDto,\n DocumentSubmissionStatusDto,\n} from '@/shared/types/dto/document-submission';\n\n/** Document types that can be signed via {@link CoinListClient.submitDocument}. */\nexport type DocumentType = 'tax_certification';\n\n/** Signing-state machine status for a document submission. */\nexport type DocumentSubmissionStatus = DocumentSubmissionStatusDto;\n\n/** The tax form derived from the entity's kind (individual vs company/trust). */\nexport type DocumentFormType = DocumentFormTypeDto;\n\n/** Result of starting (or resuming) a document signing submission. */\nexport type DocumentSubmission = {\n status: DocumentSubmissionStatus;\n formType: DocumentFormType;\n};\n\nexport const DocumentSubmission = {\n fromDto: (dto: DocumentSubmissionDto): DocumentSubmission => ({\n status: dto.status,\n formType: dto.form_type,\n }),\n};\n","import type { KycTokenDto } from '@/shared/types/dto/kyc';\n\n/**\n * Sumsub verification level name. Determines which screens the Sumsub WebSDK\n * shows (levels are configured in the Sumsub dashboard). The backend\n * prescribes the level (and whether the applicant must be reset first) in the\n * requirement statuses response — clients never compute levels themselves.\n */\nexport type KycLevelName = string;\n\n/** Short-lived Sumsub WebSDK access token scoped to the current user. */\nexport type KycToken = {\n token: string;\n};\n\nexport const KycToken = {\n fromDto: (dto: KycTokenDto): KycToken => ({\n token: dto.token,\n }),\n};\n","import type {\n PiiAddressDto,\n PiiDto,\n PiiJurisdictionDto,\n PiiKindDto,\n} from '@/shared/types/dto/pii';\nimport type { Newtype } from '@/shared/types/newtype';\n\n/** Whether the PII belongs to an individual or a company/trust entity. */\nexport type PiiKind = PiiKindDto;\n\n/** ISO 3166-1 alpha-2 country code (e.g. `'US'`). */\nexport type Iso2CountryCode = Newtype<string, 'Iso2CountryCode'>;\nexport const Iso2CountryCode = (value: string) => value as Iso2CountryCode;\n\n/** Jurisdiction derived from the entity's address country. */\nexport type PiiJurisdiction = {\n iso2: Iso2CountryCode;\n name: string | null;\n};\n\nexport const PiiJurisdiction = {\n fromDto: (dto: PiiJurisdictionDto): PiiJurisdiction => ({\n iso2: Iso2CountryCode(dto.iso_2),\n name: dto.name,\n }),\n};\n\n/** Permanent address on file for the entity. */\nexport type PiiAddress = {\n street: string | null;\n city: string | null;\n state: string | null;\n postalCode: string | null;\n country: string | null;\n};\n\nexport const PiiAddress = {\n fromDto: (dto: PiiAddressDto): PiiAddress => ({\n street: dto.street,\n city: dto.city,\n state: dto.state,\n postalCode: dto.postal_code,\n country: dto.country,\n }),\n};\n\n/**\n * The current user's PII, used to pre-fill tax forms such as the W-8BEN.\n * Fields the entity hasn't provided are `null`.\n */\nexport type Pii = {\n kind: PiiKind;\n fullLegalName: string | null;\n dateOfBirth: string | null;\n jurisdiction: PiiJurisdiction | null;\n taxId: string | null;\n permanentAddress: PiiAddress;\n};\n\nexport const Pii = {\n fromDto: (dto: PiiDto): Pii => ({\n kind: dto.kind,\n fullLegalName: dto.full_legal_name,\n dateOfBirth: dto.date_of_birth,\n jurisdiction: dto.jurisdiction\n ? PiiJurisdiction.fromDto(dto.jurisdiction)\n : null,\n taxId: dto.tax_id,\n permanentAddress: PiiAddress.fromDto(dto.permanent_address),\n }),\n};\n","import type {\n RequirementActionNeededReasonDto,\n RequirementDto,\n RequirementStatusesDto,\n RequirementStatusValueDto,\n RequirementTypeDto,\n} from '@/shared/types/dto/requirement';\nimport type { KycLevelName } from '@/shared/types/kyc';\nimport type { Newtype } from '@/shared/types/newtype';\n\nexport type RequirementId = Newtype<string, 'RequirementId'>;\nexport const RequirementId = (value: string) => value as RequirementId;\n\nexport type RequirementType = RequirementTypeDto;\nexport type RequirementStatusValue = RequirementStatusValueDto;\nexport type RequirementActionNeededReason = RequirementActionNeededReasonDto;\n\nexport type Requirement = {\n id: RequirementId;\n type: RequirementType;\n details: Record<string, unknown> | null;\n};\n\nexport const Requirement = {\n fromDto: (dto: RequirementDto): Requirement => ({\n id: RequirementId(dto.id),\n type: dto.type,\n details: dto.details,\n }),\n};\n\nexport type RequirementStatusInfo = {\n id: RequirementId;\n status: RequirementStatusValue;\n /** Why the requirement needs action (KYC-backed requirements only). */\n action: RequirementActionNeededReason | null;\n /**\n * The Sumsub verification level that resolves this requirement, prescribed\n * by the backend. Present exactly when an inline Sumsub flow can be started.\n */\n kycLevel?: KycLevelName;\n /**\n * Whether the Sumsub applicant must be reset before starting the flow\n * (redoing an already-approved level, e.g. to update stale PII). Forward to\n * the kyc-token request as-is.\n */\n kycReset?: boolean;\n};\n\nexport const RequirementStatusInfo = {\n fromStatusesDto: (dto: RequirementStatusesDto): RequirementStatusInfo[] =>\n Object.entries(dto.statuses).map(([id, value]) =>\n typeof value === 'string'\n ? { id: RequirementId(id), status: value, action: null }\n : {\n id: RequirementId(id),\n status: value.status,\n action: value.action ?? null,\n kycLevel: value.kyc_level,\n kycReset: value.kyc_reset,\n }\n ),\n};\n","import { Attributes } from '@/shared/api/http-attributes';\nimport type { Sender } from '@/shared/api/http-client';\nimport {\n DocumentSubmission,\n type DocumentType,\n} from '@/shared/types/document-submission';\nimport type { DocumentSubmissionDto } from '@/shared/types/dto/document-submission';\n\n/**\n * Starts (or resumes) a document signing submission for the given type.\n *\n * `fields` are signing-form values keyed by the document's DocuSeal field\n * names (e.g. `\"Full Name\"`, `\"Permanent Address\"`) and are forwarded\n * verbatim to Passport to pre-fill the document. They are not validated or\n * persisted by Frontline.\n */\nexport async function submitDocument(\n api: Sender,\n documentType: DocumentType,\n fields: Record<string, string>\n): Promise<DocumentSubmission> {\n const dto = await api.send<DocumentSubmissionDto>({\n method: 'POST',\n url: `/v1/documents/${documentType}/submission`,\n body: fields,\n attributes: Attributes.protected(),\n });\n return DocumentSubmission.fromDto(dto);\n}\n","import { Attributes } from '@/shared/api/http-attributes';\nimport type { Sender } from '@/shared/api/http-client';\nimport type { KycTokenDto } from '@/shared/types/dto/kyc';\nimport type { KycLevelName } from '@/shared/types/kyc';\nimport { KycToken } from '@/shared/types/kyc';\n\nexport async function createKycToken(\n api: Sender,\n levelName?: KycLevelName,\n reset?: boolean\n): Promise<KycToken> {\n const dto = await api.send<KycTokenDto>({\n method: 'POST',\n url: '/v1/kyc-token',\n body: {\n ...(levelName === undefined ? {} : { level_name: levelName }),\n ...(reset === undefined ? {} : { reset }),\n },\n attributes: Attributes.protected(),\n });\n return KycToken.fromDto(dto);\n}\n","import { Attributes } from '@/shared/api/http-attributes';\nimport type { Sender } from '@/shared/api/http-client';\nimport type { PiiDto } from '@/shared/types/dto/pii';\nimport { Pii } from '@/shared/types/pii';\n\nexport async function fetchPii(api: Sender): Promise<Pii> {\n const dto = await api.send<PiiDto>({\n method: 'GET',\n url: '/v1/pii',\n attributes: Attributes.protected(),\n });\n return Pii.fromDto(dto);\n}\n","import { Attributes } from '@/shared/api/http-attributes';\nimport type { Sender } from '@/shared/api/http-client';\nimport type {\n OfferRequirementsDto,\n RequirementStatusesDto,\n} from '@/shared/types/dto/requirement';\nimport type { ClientCredentialsOAuth } from '@/shared/types/oauth-session';\nimport type { OfferId } from '@/shared/types/offer';\nimport type { OfferOptionId } from '@/shared/types/offer-detail';\nimport { Requirement, RequirementStatusInfo } from '@/shared/types/requirement';\n\nexport async function fetchOfferRequirements(\n api: Sender,\n offerId: OfferId,\n clientCreds: ClientCredentialsOAuth | undefined\n): Promise<Record<OfferOptionId, Requirement[]>> {\n const response = await api.send<OfferRequirementsDto>({\n method: 'GET',\n url: `/v1/offers/${offerId}/requirements`,\n attributes: Attributes.concat(\n Attributes.protected(),\n Attributes.clientCredentials(clientCreds)\n ),\n });\n return Object.fromEntries(\n Object.entries(response.options).map(([optionId, list]) => [\n optionId,\n list.data.map(Requirement.fromDto),\n ])\n );\n}\n\nexport async function fetchRequirementStatuses(\n api: Sender,\n offerId: OfferId\n): Promise<RequirementStatusInfo[]> {\n const response = await api.send<RequirementStatusesDto>({\n method: 'GET',\n url: `/v1/offers/${offerId}/requirements/statuses`,\n attributes: Attributes.protected(),\n });\n return RequirementStatusInfo.fromStatusesDto(response);\n}\n","import * as documentsApi from '@/shared/api/frontline/documents';\nimport * as kycApi from '@/shared/api/frontline/kyc';\nimport * as piiApi from '@/shared/api/frontline/pii';\nimport * as requirementsApi from '@/shared/api/frontline/requirements';\nimport type { SharedNamespaceContext } from '@/shared/core/namespace-context';\nimport type {\n DocumentSubmission,\n DocumentType,\n} from '@/shared/types/document-submission';\nimport type { KycLevelName, KycToken } from '@/shared/types/kyc';\nimport type { OfferId } from '@/shared/types/offer';\nimport type { OfferOptionId } from '@/shared/types/offer-detail';\nimport type { Pii } from '@/shared/types/pii';\nimport type {\n Requirement,\n RequirementStatusInfo,\n} from '@/shared/types/requirement';\n\nexport type CreateKycTokenParams = {\n /**\n * Sumsub verification level to run. Defaults to the backend's standard\n * level.\n */\n levelName?: KycLevelName;\n /**\n * Resets the Sumsub applicant first, so an already-approved level can be\n * executed again (e.g. to update stale PII). Pass the `kycReset` value from\n * the requirement status, and never on mid-flow token refreshes.\n */\n reset?: boolean;\n};\n\nexport type SubmitDocumentParams = {\n /** Currently only `tax_certification` (W-8BEN / W-8BEN-E). */\n documentType: DocumentType;\n /**\n * Signing-form values keyed by the document's DocuSeal field names,\n * forwarded verbatim to pre-fill the document.\n */\n fields: Record<string, string>;\n};\n\n/**\n * Everything a user must satisfy before they can participate in an offer:\n * reading the checklist and its live statuses, and the operations that satisfy\n * individual requirements — identity verification (KYC) and tax-document\n * signing.\n *\n * Wallet requirements (`external_wallet`, `whitelisted_wallet`) are satisfied\n * through `WalletsNamespace` instead, since wallet proofs are also used\n * outside the requirements flow.\n *\n * Every method requires an authenticated user and throws\n * {@link NotAuthenticatedError} otherwise.\n */\nexport interface RequirementsNamespace {\n /**\n * Fetches the requirements for every option of an offer, grouped by option\n * id. This is the definition of the checklist; {@link statuses} tells you\n * where the user stands against it.\n */\n forOffer(offerId: OfferId): Promise<Record<OfferOptionId, Requirement[]>>;\n\n /**\n * Fetches the current user's status for each requirement of an offer.\n */\n statuses(offerId: OfferId): Promise<RequirementStatusInfo[]>;\n\n /**\n * Creates a short-lived Sumsub WebSDK access token so an identity\n * verification (KYC) flow can be started, e.g. by the `IdentityVerification`\n * component.\n */\n createKycToken(params?: CreateKycTokenParams): Promise<KycToken>;\n\n /**\n * Fetches the current user's PII, used to pre-fill tax forms such as the\n * W-8BEN. Fields the entity hasn't provided are `null`.\n */\n getPii(): Promise<Pii>;\n\n /**\n * Starts (or resumes) a document signing submission.\n */\n submitDocument(params: SubmitDocumentParams): Promise<DocumentSubmission>;\n}\n\nexport class RequirementsNamespaceImpl implements RequirementsNamespace {\n constructor(protected readonly ctx: SharedNamespaceContext) {}\n\n async forOffer(\n offerId: OfferId\n ): Promise<Record<OfferOptionId, Requirement[]>> {\n await this.ctx.ensureUserAuthenticated();\n return requirementsApi.fetchOfferRequirements(\n this.ctx.api,\n offerId,\n undefined\n );\n }\n\n async statuses(offerId: OfferId): Promise<RequirementStatusInfo[]> {\n await this.ctx.ensureUserAuthenticated();\n return requirementsApi.fetchRequirementStatuses(this.ctx.api, offerId);\n }\n\n async createKycToken(params?: CreateKycTokenParams): Promise<KycToken> {\n await this.ctx.ensureUserAuthenticated();\n return kycApi.createKycToken(\n this.ctx.api,\n params?.levelName,\n params?.reset\n );\n }\n\n async getPii(): Promise<Pii> {\n await this.ctx.ensureUserAuthenticated();\n return piiApi.fetchPii(this.ctx.api);\n }\n\n async submitDocument(\n params: SubmitDocumentParams\n ): Promise<DocumentSubmission> {\n await this.ctx.ensureUserAuthenticated();\n return documentsApi.submitDocument(\n this.ctx.api,\n params.documentType,\n params.fields\n );\n }\n}\n","import {\n AssetDecimals,\n AssetSymbol,\n EthereumChain,\n EvmContractAddress,\n type TokenIdentifier,\n} from '@/shared/types/blockchain/core';\nimport type {\n NabuChainAssetsDto,\n NabuLogoDto,\n NabuTokenDto,\n} from '@/shared/types/dto/nabu-token';\nimport { ValidationError } from '@/shared/types/errors';\nimport type { Newtype } from '@/shared/types/newtype';\n\n/**\n * An absolute URL to a logo image in the token registry. Registry image URLs\n * are content-fingerprinted and served immutable, so a value is safe to cache\n * for as long as you hold it.\n */\nexport type TokenLogoUrl = Newtype<string, 'TokenLogoUrl'>;\nexport const TokenLogoUrl = (value: string): TokenLogoUrl =>\n value as TokenLogoUrl;\n\nexport type TokenLogoImage = {\n url: TokenLogoUrl;\n width: number;\n height: number;\n};\n\n/**\n * `VECTOR` is a single SVG. `RASTER` has webp variants at 32/64/128/256/512px\n * widths (never wider than the original): use the smallest one that covers\n * your render size, or `original` if none does.\n */\nexport type TokenLogo =\n | { kind: 'VECTOR'; url: TokenLogoUrl }\n | { kind: 'RASTER'; original: TokenLogoImage; variants: TokenLogoImage[] };\n\nexport const TokenLogo = {\n /** `baseUrl` is the registry origin; registry URLs are root-relative. */\n fromDto: (dto: NabuLogoDto, baseUrl: string): TokenLogo =>\n dto.kind === 'VECTOR'\n ? { kind: 'VECTOR', url: resolveLogoUrl(dto.url, baseUrl) }\n : {\n kind: 'RASTER',\n original: logoImageFromDto(dto.original, baseUrl),\n variants: dto.variants.map((v) => logoImageFromDto(v, baseUrl)),\n },\n};\n\n/**\n * Display metadata for one token, from CoinList's public token registry.\n *\n * Keyed by `(chain, address)` — never by symbol, which can collide. The\n * registry is curated: a token missing from it is an expected answer, not an\n * error, so lookups return `null` rather than throwing.\n */\nexport type TokenMetadata = {\n identifier: TokenIdentifier;\n name: string;\n symbol: AssetSymbol;\n decimals: AssetDecimals;\n logo: TokenLogo;\n /** Dark-theme logo; `null` when the registry configures none. */\n logoDark: TokenLogo | null;\n};\n\nexport const TokenMetadata = {\n /** `baseUrl` is the registry origin; registry logo URLs are root-relative. */\n fromDto: (dto: NabuTokenDto, baseUrl: string): TokenMetadata => {\n assertSupportedSchemaVersion(dto.schema_version);\n return {\n identifier: {\n chain: EthereumChain(dto.chain),\n address: EvmContractAddress(dto.address),\n },\n name: dto.name,\n symbol: AssetSymbol(dto.symbol),\n decimals: AssetDecimals(dto.decimals),\n logo: TokenLogo.fromDto(dto.logo, baseUrl),\n logoDark:\n dto.logo_dark === undefined\n ? null\n : TokenLogo.fromDto(dto.logo_dark, baseUrl),\n };\n },\n\n /**\n * Maps a chain snapshot to the tokens it lists, skipping the chain's native\n * coin (`kind: 'COIN'`, no contract address).\n */\n fromChainAssetsDto: (\n dto: NabuChainAssetsDto,\n baseUrl: string\n ): TokenMetadata[] => {\n assertSupportedSchemaVersion(dto.schema_version);\n const chain = EthereumChain(dto.chain);\n return dto.assets\n .filter((asset) => asset.kind === 'TOKEN' && asset.address !== undefined)\n .map((asset) => ({\n identifier: {\n chain,\n // The filter above cannot narrow `address` for the type checker.\n address: EvmContractAddress(asset.address as string),\n },\n name: asset.name,\n symbol: AssetSymbol(asset.symbol),\n decimals: AssetDecimals(asset.decimals),\n logo: TokenLogo.fromDto(asset.logo, baseUrl),\n logoDark:\n asset.logo_dark === undefined\n ? null\n : TokenLogo.fromDto(asset.logo_dark, baseUrl),\n }));\n },\n};\n\n/**\n * The registry bumps schema_version only on breaking changes, so mapping a\n * newer schema with this code would produce silent garbage — fail instead.\n */\nfunction assertSupportedSchemaVersion(version: number): void {\n if (version !== 1) {\n throw new ValidationError(\n `Unsupported token registry schema_version: ${version}`\n );\n }\n}\n\nconst logoImageFromDto = (\n dto: { url: string; width: number; height: number },\n baseUrl: string\n): TokenLogoImage => ({\n url: resolveLogoUrl(dto.url, baseUrl),\n width: dto.width,\n height: dto.height,\n});\n\nconst resolveLogoUrl = (url: string, baseUrl: string): TokenLogoUrl =>\n TokenLogoUrl(\n url.startsWith('http') ? url : `${baseUrl.replace(/\\/$/, '')}${url}`\n );\n","import { getAddress } from 'viem';\nimport { HttpError, type HttpResponse } from '@/shared/api/http';\nimport { HttpClient } from '@/shared/api/http-client';\nimport type {\n EthereumChain,\n TokenIdentifier,\n} from '@/shared/types/blockchain/core';\nimport type {\n NabuChainAssetsDto,\n NabuTokenDto,\n} from '@/shared/types/dto/nabu-token';\nimport { ValidationError } from '@/shared/types/errors';\nimport { TokenMetadata } from '@/shared/types/token-metadata';\n\n/**\n * An {@link HttpClient} against the token registry rather than frontline: no\n * `X-API-Version` (the registry doesn't know it, and the extra header would\n * force a CORS preflight the static CDN cannot answer) and no session\n * middleware (the registry is public).\n */\nexport function createNabuApiClient(baseUrl: string): HttpClient {\n return new HttpClient({ baseUrl });\n}\n\n/**\n * Fetches one token's display metadata from the registry.\n *\n * Returns `null` when the registry does not list the token: the registry is\n * curated, so \"not listed\" is a domain answer, not a failure. The deployment\n * signals it as either a 404 or — Cloudflare Pages' fallback for unknown\n * routes — a 2xx serving its HTML inspection page, so both map to `null`.\n * Everything else throws: a non-2xx status is an {@link HttpError} carrying\n * the registry's response, including a 5xx whose body is an HTML error page.\n */\nexport async function fetchTokenMetadata(\n client: HttpClient,\n token: TokenIdentifier\n): Promise<TokenMetadata | null> {\n // The registry's canonical route uses the EIP-55 checksummed address:\n // lowercase costs a redirect round-trip and wrong mixed casing 404s.\n const address = checksummed(token.address);\n let response: HttpResponse<NabuTokenDto>;\n try {\n response = await client.send<NabuTokenDto>({\n method: 'GET',\n url: `/${token.chain}/token/${address}`,\n });\n } catch (error) {\n if (isRegistryHtmlFallback(error)) {\n return null;\n }\n throw error;\n }\n\n if (response.status === 404) {\n return null;\n }\n assertOk(response);\n if (response.body === null) {\n // Not a \"not listed\" signal — those are the 404 and the HTML fallback. A\n // 2xx with a zero-length body is a broken deploy or a mangling\n // intermediary, and mapping it to null would hide a listed token.\n throw new ValidationError(\n `Token registry returned an empty body for token \"${address}\" on \"${token.chain}\"`\n );\n }\n return TokenMetadata.fromDto(response.body, client.config.baseUrl);\n}\n\n/**\n * Fetches all available tokens the registry lists for `chain`, in a single\n * request against the chain snapshot — fetching N tokens one by one would\n * cost N round-trips for a catalogue that arrives whole anyway.\n *\n * Unlike {@link fetchTokenMetadata}, a missing snapshot throws rather than\n * mapping to an empty answer: the registry publishes a snapshot for every\n * chain it knows, so its absence is a deployment problem — and an invented\n * `[]` would render as \"no metadata\" without anyone noticing.\n */\nexport async function fetchTokensMetadata(\n client: HttpClient,\n chain: EthereumChain\n): Promise<TokenMetadata[]> {\n let response: HttpResponse<NabuChainAssetsDto>;\n try {\n response = await client.send<NabuChainAssetsDto>({\n method: 'GET',\n url: `/${chain}/assets.json`,\n });\n } catch (error) {\n if (isRegistryHtmlFallback(error)) {\n throw new ValidationError(\n `Token registry returned non-JSON for the \"${chain}\" snapshot`\n );\n }\n throw error;\n }\n\n assertOk(response);\n if (response.body === null) {\n throw new ValidationError(\n `Token registry returned an empty \"${chain}\" snapshot`\n );\n }\n return TokenMetadata.fromChainAssetsDto(response.body, client.config.baseUrl);\n}\n\n/**\n * The registry's deployment answers routes that have no static file with its\n * HTML inspection page and a 2xx status. `makeRequest` surfaces any non-JSON\n * body as an {@link HttpError} carrying the status, so \"2xx but not JSON\" is\n * precisely the registry's \"no such file\" signal — while a non-2xx with an\n * HTML body (a CDN 502/503 page, a proxy block page) keeps its status and\n * stays an outage for the caller to see, never a domain answer.\n */\nfunction isRegistryHtmlFallback(error: unknown): boolean {\n return (\n error instanceof HttpError &&\n error.response.status >= 200 &&\n error.response.status < 300\n );\n}\n\nfunction assertOk(response: HttpResponse<unknown>): void {\n if (response.status < 200 || response.status >= 300) {\n // The full response, never a stripped one: HttpError is public API and\n // callers classify failures off `response.body` (e.g. a 429 vs a 502).\n throw new HttpError(response);\n }\n}\n\nfunction checksummed(address: string): string {\n try {\n return getAddress(address);\n } catch (_) {\n throw new ValidationError(`Invalid EVM contract address: \"${address}\"`);\n }\n}\n","export const PUBLIC_API_BASE_URL = 'https://api.coinlist.co';\nexport const HEADER_API_VERSION = 'X-API-Version';\nexport const HEADER_USER_AGENT = 'User-Agent';\nexport const HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';\nexport const API_VERSION = '2025-10-17';\n\nexport const COINLIST_BASE_URL = 'https://coinlist.co';\nexport const OAUTH_PAGE_PATH = '/oauth/authorize';\n\nexport const SUPPORT_NEW_TICKET_URL =\n 'https://support.coinlist.co/support/tickets/new';\n\nexport const VERIFY_IDENTITY_PATH = '/verify-identity';\nexport const VERIFY_IDENTITY_VERIFIED_PATH =\n '/verify-identity/identity_verified';\nexport const VERIFY_IDENTITY_PROOF_OF_ADDRESS_PATH =\n '/verify-identity/proof_of_address';\nexport const VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH =\n '/verify-identity/source_of_funds';\nexport const VERIFY_IDENTITY_ACCREDITATION_PATH =\n '/verify-identity/accreditation_full';\nexport const WALLET_PATH = '/wallet';\n","import { HEADER_API_VERSION } from '@/shared/api/frontline/config';\nimport type {\n HttpClientConfig,\n HttpRequest,\n HttpResponse,\n} from '@/shared/api/http';\nimport { makeRequest } from '@/shared/api/http';\n\nexport type BeforeRequestMiddleware = (\n request: HttpRequest\n) => Promise<HttpRequest>;\n\nexport type AfterRequestMiddleware = (args: {\n request: HttpRequest;\n response: HttpResponse<unknown>;\n retry: (request?: HttpRequest) => Promise<HttpResponse<unknown>>;\n}) => Promise<HttpResponse<unknown>>;\n\nexport type HttpClientMiddleware = {\n beforeRequest?: BeforeRequestMiddleware[];\n afterRequest?: AfterRequestMiddleware[];\n};\n\nexport class HttpClient {\n constructor(\n readonly config: HttpClientConfig,\n readonly middleware: HttpClientMiddleware = {}\n ) {}\n\n async send<TResponse = unknown>(\n request: HttpRequest\n ): Promise<HttpResponse<TResponse>> {\n return this.runRequestWithAfterMiddleware<TResponse>(request);\n }\n\n /**\n * Runs beforeRequest, executeRequest, then the full afterRequest middleware\n * chain. Used by send() and by the retry() callback so that when a\n * middleware calls retry(), the retried response also goes through all\n * afterRequest middleware (e.g. session renewal, retry). Middleware\n * must use request.attributes.retryAttempt (or similar) to avoid infinite\n * recursion when they trigger retries.\n */\n private async runRequestWithAfterMiddleware<TResponse = unknown>(\n request: HttpRequest\n ): Promise<HttpResponse<TResponse>> {\n const preparedRequest = await this.runBeforeRequestMiddleware(\n this.withClientDefaults(request)\n );\n let response = await this.executeRequest<TResponse>(preparedRequest);\n\n for (const middleware of this.middleware.afterRequest ?? []) {\n response = (await middleware({\n request: preparedRequest,\n response,\n retry: (nextRequest = preparedRequest) =>\n this.runRequestWithAfterMiddleware(nextRequest) as Promise<\n HttpResponse<TResponse>\n >,\n })) as HttpResponse<TResponse>;\n }\n\n return response;\n }\n\n private withClientDefaults(request: HttpRequest): HttpRequest {\n const url = this.resolveUrl(request.url);\n const headers = {\n ...(request.headers ?? {}),\n ...(this.config.xApiVersion !== undefined\n ? { [HEADER_API_VERSION]: this.config.xApiVersion }\n : {}),\n };\n\n return {\n ...request,\n url,\n headers,\n };\n }\n\n /**\n * Resolves a request URL against the client's baseUrl.\n *\n * @internal Public only for testing. Do not use in application code; use\n * {@link HttpClient.send} with a path and the client will resolve the URL.\n */\n resolveUrl(url: string): string {\n // If already absolute, use as-is.\n if (url.startsWith('http://') || url.startsWith('https://')) {\n return url;\n }\n // Otherwise append path to baseUrl so base path (e.g. /api) is preserved.\n const base = this.config.baseUrl.replace(/\\/$/, '');\n const path = url.startsWith('/') ? url : `/${url}`;\n return base + path;\n }\n\n private async runBeforeRequestMiddleware(\n initialRequest: HttpRequest\n ): Promise<HttpRequest> {\n let request = initialRequest;\n for (const middleware of this.middleware.beforeRequest ?? []) {\n request = await middleware(request);\n }\n\n return request;\n }\n\n private executeRequest<TResponse = unknown>(\n request: HttpRequest\n ): Promise<HttpResponse<TResponse>> {\n return makeRequest<TResponse>(request);\n }\n}\n\n/**\n * Structural interface satisfied by both {@link AuthenticatedApiClient} and\n * {@link ApiClient}. Used by the shared frontline API functions so they can\n * be called from either the client or server without any browser dependencies.\n */\nexport interface Sender {\n send<T>(request: HttpRequest): Promise<T>;\n}\n","import type { HttpClient } from '@/shared/api/http-client';\nimport {\n createNabuApiClient,\n fetchTokenMetadata,\n fetchTokensMetadata,\n} from '@/shared/api/nabu/tokens';\nimport type {\n EthereumChain,\n TokenIdentifier,\n} from '@/shared/types/blockchain/core';\nimport type { TokenMetadata } from '@/shared/types/token-metadata';\n\n/**\n * Token display metadata — name, symbol, decimals, and logos — from\n * CoinList's public token registry, keyed by {@link TokenIdentifier} (the\n * same chain + address pairs `OfferDetail.tokens` carries).\n *\n * Unlike the other namespaces, this one is public: no method requires an\n * authenticated user, and nothing here touches the CoinList API — reads go to\n * the registry's CDN.\n */\nexport interface TokensNamespace {\n /**\n * Fetches metadata for one token. Returns `null` when the registry does not\n * list the token — the registry is curated, so callers must fall back to\n * their own display defaults rather than treat this as an error.\n */\n get(token: TokenIdentifier): Promise<TokenMetadata | null>;\n\n /**\n * Fetches all available tokens the registry lists for `chain`, in one\n * request. Prefer this over calling {@link get} in a loop when displaying a\n * catalogue: two hundred tokens is still a single snapshot download.\n *\n * Unlike {@link get}, a missing chain snapshot throws rather than returning\n * `[]`: the registry publishes one for every chain it knows, so its absence\n * is a deployment problem, not an empty catalogue.\n */\n list(chain: EthereumChain): Promise<TokenMetadata[]>;\n}\n\nexport class TokensNamespaceImpl implements TokensNamespace {\n private readonly api: HttpClient;\n\n /**\n * Takes the registry origin rather than a `SharedNamespaceContext`: the\n * registry is unauthenticated and on its own host, so the frontline sender\n * and the auth check would both be dead weight here.\n */\n constructor(baseUrl: string) {\n this.api = createNabuApiClient(baseUrl);\n }\n\n get(token: TokenIdentifier): Promise<TokenMetadata | null> {\n return fetchTokenMetadata(this.api, token);\n }\n\n list(chain: EthereumChain): Promise<TokenMetadata[]> {\n return fetchTokensMetadata(this.api, chain);\n }\n}\n","import type { Hex } from 'viem';\nimport {\n type EthereumChain,\n EvmWalletAddress,\n type WalletProtocol,\n} from '@/shared/types/blockchain/core';\nimport type {\n CreateOfferOptionAddressDto,\n OfferOptionAddressDto,\n} from '@/shared/types/dto/offer-option-address';\nimport type { Newtype } from '@/shared/types/newtype';\nimport type { OfferId } from '@/shared/types/offer';\nimport { OfferOptionId } from '@/shared/types/offer-detail';\n\n/** Unique identifier for a proven wallet binding on an offer option. */\nexport type OfferOptionAddressId = Newtype<string, 'OfferOptionAddressId'>;\n/** Casts a string into a typed {@link OfferOptionAddressId}. */\nexport const OfferOptionAddressId = (value: string) =>\n value as OfferOptionAddressId;\n\n/**\n * A user's external wallet, proven via a wallet-ownership challenge and bound\n * to an offer option. Returned by the `/v1/offers/:offer_id/addresses` resource.\n */\nexport type OfferOptionAddress = {\n /** Unique binding id. */\n id: OfferOptionAddressId;\n /** Offer option the wallet is bound to. */\n offerOptionId: OfferOptionId;\n /** The connected external wallet address. */\n address: EvmWalletAddress;\n /**\n * Protocol the binding is scoped to. An EVM address binds once per option\n * regardless of which EVM chain proved ownership.\n */\n protocol: WalletProtocol;\n /** When the binding was created. */\n createdAt: Date;\n};\n\n/** Parameters required to connect a proven external wallet to an offer option. */\nexport type ConnectExternalWalletParams = {\n /** Offer the option belongs to. */\n offerId: OfferId;\n /** Offer option to bind the wallet to. */\n offerOptionId: OfferOptionId;\n /** External wallet address that was proven. */\n walletAddress: EvmWalletAddress;\n /** Chain the ownership was proven on. */\n chain: EthereumChain;\n /** Signature of the wallet-ownership challenge message. */\n signature: Hex;\n};\n\nexport const OfferOptionAddress = {\n /** Maps the API DTO into the SDK offer-option-address domain model. */\n fromDto: (dto: OfferOptionAddressDto): OfferOptionAddress => ({\n id: OfferOptionAddressId(dto.id),\n offerOptionId: OfferOptionId(dto.offer_option_id),\n address: EvmWalletAddress(dto.address),\n protocol: dto.protocol,\n createdAt: new Date(dto.created_at),\n }),\n};\n\nexport const ConnectExternalWalletParams = {\n /** Maps connect-wallet params into the API DTO payload. */\n toDto: (\n params: ConnectExternalWalletParams\n ): CreateOfferOptionAddressDto => ({\n offer_option_id: params.offerOptionId,\n wallet_address: params.walletAddress,\n chain: params.chain,\n signature: params.signature,\n }),\n};\n","import type {\n EthereumChain,\n EvmWalletAddress,\n} from '@/shared/types/blockchain/core';\nimport type {\n CreateWalletOwnershipChallengeDto,\n WalletOwnershipChallengeDto,\n} from '@/shared/types/dto/wallet-ownership-challenge';\n\n/**\n * A single-use ownership challenge returned by `POST /v1/wallet-ownership`.\n * The consumer signs {@link message} with their wallet, then submits the\n * signature to connect the wallet to an offer option.\n */\nexport type WalletOwnershipChallenge = {\n /** The message the wallet must sign. */\n message: string;\n /** When the challenge expires and can no longer be consumed. */\n expiresAt: Date;\n};\n\n/** Fields common to every wallet-ownership challenge request. */\ntype WalletOwnershipChallengeParamsBase = {\n /** Wallet address to prove ownership of. */\n walletAddress: EvmWalletAddress;\n /** Chain the wallet belongs to. */\n chain: EthereumChain;\n};\n\n/**\n * Parameters for requesting a wallet-ownership challenge. Modeled as a\n * discriminated union on `challengeType` so a `siwe` challenge must carry\n * `domain`/`uri`/`statement`, matching the backend contract at compile time.\n */\nexport type CreateWalletOwnershipChallengeParams =\n | (WalletOwnershipChallengeParamsBase & {\n /** A bare message the wallet signs. */\n challengeType: 'plain';\n })\n | (WalletOwnershipChallengeParamsBase & {\n /** Marks this as a Sign-In With Ethereum challenge. */\n challengeType: 'siwe';\n /** The requesting site's hostname (e.g. `example.com`). */\n domain: string;\n /** The requesting site's URI. */\n uri: string;\n /** Human-readable statement shown in the signing prompt. */\n statement: string;\n });\n\n/**\n * How the ownership challenge is framed: a plain message or a Sign-In With\n * Ethereum challenge. Extracted as its own type so SDK consumers can pass it as\n * a standalone param without reaching into the {@link CreateWalletOwnershipChallengeParams}\n * union.\n */\nexport type WalletChallengeType =\n CreateWalletOwnershipChallengeParams['challengeType'];\n\nexport const WalletOwnershipChallenge = {\n /** Maps the API DTO into the SDK wallet-ownership-challenge domain model. */\n fromDto: (dto: WalletOwnershipChallengeDto): WalletOwnershipChallenge => ({\n message: dto.message,\n expiresAt: new Date(dto.expires_at),\n }),\n};\n\nexport const CreateWalletOwnershipChallengeParams = {\n /**\n * Maps challenge-request params into the API DTO payload. The discriminated\n * union guarantees SIWE fields are present exactly when `challengeType` is\n * `siwe`, so the mapping narrows on the discriminant.\n */\n toDto: (\n params: CreateWalletOwnershipChallengeParams\n ): CreateWalletOwnershipChallengeDto => {\n switch (params.challengeType) {\n case 'plain':\n return {\n wallet_address: params.walletAddress,\n chain: params.chain,\n challenge_type: 'plain',\n };\n case 'siwe':\n return {\n wallet_address: params.walletAddress,\n chain: params.chain,\n challenge_type: 'siwe',\n domain: params.domain,\n uri: params.uri,\n statement: params.statement,\n };\n default: {\n const _exhaustive: never = params;\n return _exhaustive;\n }\n }\n },\n};\n","import { Attributes } from '@/shared/api/http-attributes';\nimport type { Sender } from '@/shared/api/http-client';\nimport type { OfferOptionAddressDto } from '@/shared/types/dto/offer-option-address';\nimport type { ListResponseDto } from '@/shared/types/dto/shared';\nimport type { WalletOwnershipChallengeDto } from '@/shared/types/dto/wallet-ownership-challenge';\nimport type { OfferId } from '@/shared/types/offer';\nimport type { OfferOptionId } from '@/shared/types/offer-detail';\nimport {\n ConnectExternalWalletParams,\n OfferOptionAddress,\n type OfferOptionAddressId,\n} from '@/shared/types/offer-option-address';\nimport {\n CreateWalletOwnershipChallengeParams,\n WalletOwnershipChallenge,\n} from '@/shared/types/wallet-ownership-challenge';\n\n/**\n * Creates a single-use wallet-ownership challenge. The consumer signs the\n * returned message with their wallet, then passes the signature to\n * {@link connectExternalWallet}.\n *\n * @throws {NotAuthenticatedError} when the request is unauthenticated (401).\n * @throws {HttpError} on a 422 when params are invalid — an unparseable\n * address, or SIWE fields (`domain`/`uri`/`statement`) that are missing on a\n * `siwe` challenge or present on a `plain` one. The `ApiErrorDto` body\n * carries the validation detail.\n */\nexport async function createWalletOwnershipChallenge(\n api: Sender,\n params: CreateWalletOwnershipChallengeParams\n): Promise<WalletOwnershipChallenge> {\n const dto = await api.send<WalletOwnershipChallengeDto>({\n method: 'POST',\n url: '/v1/wallet-ownership',\n body: CreateWalletOwnershipChallengeParams.toDto(params),\n attributes: Attributes.protected(),\n });\n return WalletOwnershipChallenge.fromDto(dto);\n}\n\n/**\n * Connects a proven external wallet to an offer option. Requires a signature\n * of a previously created, unconsumed wallet-ownership challenge for the same\n * wallet and chain.\n *\n * Single-slot (`external_wallet`) options replace the existing binding in place\n * on re-submit — the binding `id` is stable across a \"change wallet\" — so\n * `max_wallets_reached` only fires for `whitelisted_wallet` options at their cap.\n *\n * @throws {NotAuthenticatedError} when the request is unauthenticated (401).\n * @throws {HttpError} on a 422 for every binding failure; discriminate via the\n * `ApiErrorDto` body. Failures with a machine-readable `code`:\n * `wallet_not_whitelisted`, `max_wallets_reached`. Every other binding failure\n * (protocol mismatch, concurrent-connect lock, etc.) is rendered as an opaque\n * generic 422 with no `code`, by backend design. Challenge-state failures\n * surface by message only: no unconsumed challenge, wallet/chain not matching\n * the challenge, expired, or already used. Expired and already-used are not\n * retry-safe — request a fresh challenge first.\n */\nexport async function connectExternalWallet(\n api: Sender,\n params: ConnectExternalWalletParams\n): Promise<OfferOptionAddress> {\n const dto = await api.send<OfferOptionAddressDto>({\n method: 'POST',\n url: `/v1/offers/${params.offerId}/addresses`,\n body: ConnectExternalWalletParams.toDto(params),\n attributes: Attributes.protected(),\n });\n return OfferOptionAddress.fromDto(dto);\n}\n\n/**\n * Lists the user's proven wallet bindings for a single offer option. Single-slot\n * (`external_wallet`) options return at most one binding; `whitelisted_wallet`\n * options return up to the requirement's `max_wallets`. Works after the offer\n * ends, so partners can read the final bindings.\n *\n * @throws {NotAuthenticatedError} when the request is unauthenticated (401).\n */\nexport async function listOptionAddresses(\n api: Sender,\n offerId: OfferId,\n offerOptionId: OfferOptionId\n): Promise<OfferOptionAddress[]> {\n const { data } = await api.send<ListResponseDto<OfferOptionAddressDto>>({\n method: 'GET',\n url: `/v1/offers/${offerId}/addresses`,\n queryParams: { offer_option_id: offerOptionId },\n attributes: Attributes.protected(),\n });\n return data.map(OfferOptionAddress.fromDto);\n}\n\n/**\n * Removes one of the user's wallet bindings and returns the removed binding.\n *\n * @throws {NotAuthenticatedError} when the request is unauthenticated (401).\n * @throws {HttpError} on a 422 with `code` `offer_ended` once the offer has\n * ended (bindings on an offer that has not yet started stay removable), or a\n * 404 when the binding does not exist or is not the caller's.\n */\nexport async function removeOptionAddress(\n api: Sender,\n offerId: OfferId,\n addressId: OfferOptionAddressId\n): Promise<OfferOptionAddress> {\n const dto = await api.send<OfferOptionAddressDto>({\n method: 'DELETE',\n url: `/v1/offers/${offerId}/addresses/${addressId}`,\n attributes: Attributes.protected(),\n });\n return OfferOptionAddress.fromDto(dto);\n}\n","import * as walletConnectApi from '@/shared/api/frontline/wallet-connect';\nimport type { SharedNamespaceContext } from '@/shared/core/namespace-context';\nimport type { OfferId } from '@/shared/types/offer';\nimport type { OfferOptionId } from '@/shared/types/offer-detail';\nimport type {\n ConnectExternalWalletParams,\n OfferOptionAddress,\n OfferOptionAddressId,\n} from '@/shared/types/offer-option-address';\nimport type {\n CreateWalletOwnershipChallengeParams,\n WalletOwnershipChallenge,\n} from '@/shared/types/wallet-ownership-challenge';\n\nexport type ListOptionAddressesParams = {\n offerId: OfferId;\n /** Offer option whose bindings to list. */\n offerOptionId: OfferOptionId;\n};\n\nexport type RemoveOptionAddressParams = {\n offerId: OfferId;\n /** Binding to remove, as returned by {@link WalletsNamespace.list}. */\n addressId: OfferOptionAddressId;\n};\n\n/**\n * The user's external wallets: proving ownership of one, binding it to an\n * offer option, and managing those bindings.\n *\n * Ownership proof is a provider-agnostic primitive — the swap flow uses the\n * same challenge to allow-list a wallet — so it lives here rather than being\n * duplicated per product namespace.\n *\n * Every method requires an authenticated user and throws\n * {@link NotAuthenticatedError} otherwise.\n */\nexport interface WalletsNamespace {\n /**\n * Creates a single-use challenge the user signs to prove they control a\n * wallet. Supports both `plain` and `siwe` challenges. Pass the signature of\n * the returned {@link WalletOwnershipChallenge.message} to\n * {@link connectExternal}.\n */\n createOwnershipChallenge(\n params: CreateWalletOwnershipChallengeParams\n ): Promise<WalletOwnershipChallenge>;\n\n /**\n * Binds a proven external wallet to an offer option, using a signature of a\n * challenge from {@link createOwnershipChallenge}.\n */\n connectExternal(\n params: ConnectExternalWalletParams\n ): Promise<OfferOptionAddress>;\n\n /**\n * Lists the user's proven wallet bindings for one offer option — the single\n * bound address for an `external_wallet` option, or every allow-listed\n * wallet for a `whitelisted_wallet` option.\n */\n list(params: ListOptionAddressesParams): Promise<OfferOptionAddress[]>;\n\n /**\n * Removes one of the user's wallet bindings and returns the removed binding.\n */\n remove(params: RemoveOptionAddressParams): Promise<OfferOptionAddress>;\n}\n\nexport class WalletsNamespaceImpl implements WalletsNamespace {\n constructor(private readonly ctx: SharedNamespaceContext) {}\n\n async createOwnershipChallenge(\n params: CreateWalletOwnershipChallengeParams\n ): Promise<WalletOwnershipChallenge> {\n await this.ctx.ensureUserAuthenticated();\n return walletConnectApi.createWalletOwnershipChallenge(\n this.ctx.api,\n params\n );\n }\n\n async connectExternal(\n params: ConnectExternalWalletParams\n ): Promise<OfferOptionAddress> {\n await this.ctx.ensureUserAuthenticated();\n return walletConnectApi.connectExternalWallet(this.ctx.api, params);\n }\n\n async list(params: ListOptionAddressesParams): Promise<OfferOptionAddress[]> {\n await this.ctx.ensureUserAuthenticated();\n return walletConnectApi.listOptionAddresses(\n this.ctx.api,\n params.offerId,\n params.offerOptionId\n );\n }\n\n async remove(params: RemoveOptionAddressParams): Promise<OfferOptionAddress> {\n await this.ctx.ensureUserAuthenticated();\n return walletConnectApi.removeOptionAddress(\n this.ctx.api,\n params.offerId,\n params.addressId\n );\n }\n}\n","import type { OAuthSessionDto } from '@/shared/types/dto/oauth-session';\nimport type { Newtype } from '@/shared/types/newtype';\n\nexport type ClientCredentialsOAuth = Newtype<\n OAuthAccessToken,\n 'ClientCredentialsOAuth'\n>;\nexport const ClientCredentialsOAuth = (value: OAuthAccessToken) =>\n value as ClientCredentialsOAuth;\n\nexport type OAuthAccessToken = {\n value: string;\n expiresAt: Date;\n};\n\nexport type OAuthRefreshToken = Newtype<string, 'OAuthRefreshToken'>;\nexport const OAuthRefreshToken = (value: string) => value as OAuthRefreshToken;\n\nexport type OAuthSession = {\n accessToken: OAuthAccessToken;\n refreshToken?: OAuthRefreshToken;\n};\n\nexport const OAuthSession = {\n fromDto: (dto: OAuthSessionDto): OAuthSession => {\n const expiresAt = new Date(Date.now() + dto.expires_in * 1000);\n return {\n accessToken: {\n value: dto.access_token,\n expiresAt,\n },\n ...(dto.refresh_token != null && dto.refresh_token !== ''\n ? { refreshToken: OAuthRefreshToken(dto.refresh_token) }\n : undefined),\n };\n },\n};\n","import { Attributes } from '@/shared/api/http-attributes';\nimport type { Sender } from '@/shared/api/http-client';\nimport { fetchAllPages } from '@/shared/api/pagination';\nimport type { OfferDto } from '@/shared/types/dto/offer';\nimport type { OfferDetailDto } from '@/shared/types/dto/offer-detail';\nimport type { PaginatedResponseDto } from '@/shared/types/dto/pagination';\nimport type { ClientCredentialsOAuth } from '@/shared/types/oauth-session';\nimport { Offer, type OfferId } from '@/shared/types/offer';\nimport { OfferDetail } from '@/shared/types/offer-detail';\nimport { PaginatedResponse, PaginationParams } from '@/shared/types/pagination';\n\nexport async function fetchOffers(\n api: Sender,\n clientCreds: ClientCredentialsOAuth | undefined\n): Promise<Offer[]> {\n return fetchAllPages((params) => fetchOffersPage(api, params, clientCreds));\n}\n\nexport async function fetchOffersPage(\n api: Sender,\n params: PaginationParams,\n clientCreds: ClientCredentialsOAuth | undefined\n): Promise<PaginatedResponse<Offer>> {\n const queryParams = PaginationParams.toQueryParams(params);\n const pageDto = await api.send<PaginatedResponseDto<OfferDto>>({\n method: 'GET',\n url: '/v1/offers',\n queryParams,\n attributes: Attributes.concat(\n Attributes.protected(),\n Attributes.clientCredentials(clientCreds)\n ),\n });\n return PaginatedResponse.fromDto(pageDto, Offer.fromDto);\n}\n\nexport async function fetchOfferDetails(\n api: Sender,\n id: OfferId,\n clientCreds: ClientCredentialsOAuth | undefined\n): Promise<OfferDetail> {\n const dto = await api.send<OfferDetailDto>({\n method: 'GET',\n url: `/v1/offers/${id}`,\n attributes: Attributes.concat(\n Attributes.protected(),\n Attributes.clientCredentials(clientCreds)\n ),\n });\n return OfferDetail.fromDto(dto);\n}\n"],"mappings":"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","names":[]}
@@ -1,65 +0,0 @@
1
- import { ai as ClientId, a_ as RedirectUri, aj as CodeChallenge, aP as PKCEState, C as CodeVerifier, B as BlockchainAmount, b7 as SwapPreview, M as AssetDecimals, ab as Newtype } from './config-B5mwS_2l.cjs';
2
-
3
- type PKCEParams = {
4
- clientId: ClientId;
5
- responseType: 'code';
6
- redirectUri: RedirectUri;
7
- codeChallenge: CodeChallenge;
8
- codeChallengeMethod: 'S256';
9
- state: PKCEState;
10
- codeVerifier: CodeVerifier;
11
- };
12
- type PKCEConfig = {
13
- clientId: ClientId;
14
- redirectUri: RedirectUri;
15
- };
16
- /**
17
- * Generates PKCE parameters for an OAuth2 authorization code flow.
18
- * Pure crypto — no React, no DOM beyond Web Crypto API. Safe to use
19
- * in server-side code and Next.js middleware.
20
- */
21
- declare function generatePKCEParams(config: PKCEConfig): Promise<PKCEParams>;
22
-
23
- /**
24
- * A read-only quote for a swap as domain amounts: how much goes in, the
25
- * protocol fee, and how much would come out. Derived from the raw
26
- * {@link SwapPreview} the swap contract returns.
27
- */
28
- type SwapQuote = {
29
- inputTokenAmount: BlockchainAmount;
30
- fee: BlockchainAmount;
31
- outputTokenAmount: BlockchainAmount;
32
- };
33
- declare const SwapQuote: {
34
- /**
35
- * Assembles a {@link SwapQuote} from a raw contract {@link SwapPreview}. The
36
- * input and fee are denominated in the input token; the output in the output
37
- * token.
38
- */
39
- fromPreview: (preview: SwapPreview, inputDecimals: AssetDecimals, outputDecimals: AssetDecimals) => SwapQuote;
40
- };
41
-
42
- type FormattedAmountUi = Newtype<string, 'FormattedAmountUi'>;
43
- declare const FormattedAmountUi: (value: string) => FormattedAmountUi;
44
- type FormattedPercentUi = Newtype<string, 'FormattedPercentUi'>;
45
- declare const FormattedPercentUi: (value: string) => FormattedPercentUi;
46
- type TxExplorerUrl = Newtype<string, 'TxExplorerUrl'>;
47
- declare const TxExplorerUrl: (value: string) => TxExplorerUrl;
48
- /**
49
- * A wallet address shortened for display (e.g. `0x1234…5678`). Keeps a
50
- * `0x${string}` base but drops the runtime `0x` narrowing.
51
- */
52
- type ShortenedWalletAddress = Newtype<`0x${string}`, 'ShortenedWalletAddress'>;
53
- declare const ShortenedWalletAddress: (value: string) => ShortenedWalletAddress;
54
- type FormattedAmountAssetUi = Newtype<string, 'FormattedAmountAssetUi'>;
55
- declare const FormattedAmountAssetUi: (value: string) => FormattedAmountAssetUi;
56
- type AssetIconUrl = Newtype<string, 'AssetIconUrl'>;
57
- declare const AssetIconUrl: (value: string) => AssetIconUrl;
58
-
59
- /**
60
- * An array guaranteed to hold at least one element. Use it where an empty list
61
- * would be a bug (e.g. the set of assets a swap always offers).
62
- */
63
- type NonEmptyArray<T> = [T, ...T[]];
64
-
65
- export { AssetIconUrl as A, FormattedAmountAssetUi as F, type NonEmptyArray as N, type PKCEConfig as P, SwapQuote as S, TxExplorerUrl as T, ShortenedWalletAddress as a, FormattedPercentUi as b, FormattedAmountUi as c, type PKCEParams as d, generatePKCEParams as g };
@@ -1,65 +0,0 @@
1
- import { ai as ClientId, a_ as RedirectUri, aj as CodeChallenge, aP as PKCEState, C as CodeVerifier, B as BlockchainAmount, b7 as SwapPreview, M as AssetDecimals, ab as Newtype } from './config-B5mwS_2l.js';
2
-
3
- type PKCEParams = {
4
- clientId: ClientId;
5
- responseType: 'code';
6
- redirectUri: RedirectUri;
7
- codeChallenge: CodeChallenge;
8
- codeChallengeMethod: 'S256';
9
- state: PKCEState;
10
- codeVerifier: CodeVerifier;
11
- };
12
- type PKCEConfig = {
13
- clientId: ClientId;
14
- redirectUri: RedirectUri;
15
- };
16
- /**
17
- * Generates PKCE parameters for an OAuth2 authorization code flow.
18
- * Pure crypto — no React, no DOM beyond Web Crypto API. Safe to use
19
- * in server-side code and Next.js middleware.
20
- */
21
- declare function generatePKCEParams(config: PKCEConfig): Promise<PKCEParams>;
22
-
23
- /**
24
- * A read-only quote for a swap as domain amounts: how much goes in, the
25
- * protocol fee, and how much would come out. Derived from the raw
26
- * {@link SwapPreview} the swap contract returns.
27
- */
28
- type SwapQuote = {
29
- inputTokenAmount: BlockchainAmount;
30
- fee: BlockchainAmount;
31
- outputTokenAmount: BlockchainAmount;
32
- };
33
- declare const SwapQuote: {
34
- /**
35
- * Assembles a {@link SwapQuote} from a raw contract {@link SwapPreview}. The
36
- * input and fee are denominated in the input token; the output in the output
37
- * token.
38
- */
39
- fromPreview: (preview: SwapPreview, inputDecimals: AssetDecimals, outputDecimals: AssetDecimals) => SwapQuote;
40
- };
41
-
42
- type FormattedAmountUi = Newtype<string, 'FormattedAmountUi'>;
43
- declare const FormattedAmountUi: (value: string) => FormattedAmountUi;
44
- type FormattedPercentUi = Newtype<string, 'FormattedPercentUi'>;
45
- declare const FormattedPercentUi: (value: string) => FormattedPercentUi;
46
- type TxExplorerUrl = Newtype<string, 'TxExplorerUrl'>;
47
- declare const TxExplorerUrl: (value: string) => TxExplorerUrl;
48
- /**
49
- * A wallet address shortened for display (e.g. `0x1234…5678`). Keeps a
50
- * `0x${string}` base but drops the runtime `0x` narrowing.
51
- */
52
- type ShortenedWalletAddress = Newtype<`0x${string}`, 'ShortenedWalletAddress'>;
53
- declare const ShortenedWalletAddress: (value: string) => ShortenedWalletAddress;
54
- type FormattedAmountAssetUi = Newtype<string, 'FormattedAmountAssetUi'>;
55
- declare const FormattedAmountAssetUi: (value: string) => FormattedAmountAssetUi;
56
- type AssetIconUrl = Newtype<string, 'AssetIconUrl'>;
57
- declare const AssetIconUrl: (value: string) => AssetIconUrl;
58
-
59
- /**
60
- * An array guaranteed to hold at least one element. Use it where an empty list
61
- * would be a bug (e.g. the set of assets a swap always offers).
62
- */
63
- type NonEmptyArray<T> = [T, ...T[]];
64
-
65
- export { AssetIconUrl as A, FormattedAmountAssetUi as F, type NonEmptyArray as N, type PKCEConfig as P, SwapQuote as S, TxExplorerUrl as T, ShortenedWalletAddress as a, FormattedPercentUi as b, FormattedAmountUi as c, type PKCEParams as d, generatePKCEParams as g };