@coinlist-co/react 0.3.0 → 0.4.0

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 (65) hide show
  1. package/dist/{RequirementItem-BvwsFu9e.d.cts → RequirementItem-B-MvcxSr.d.cts} +3 -3
  2. package/dist/{RequirementItem-BpkJQep8.d.ts → RequirementItem-DcYot2uC.d.ts} +3 -3
  3. package/dist/{chunk-IDCROXPS.js → chunk-EHZ6PIGN.js} +6 -4
  4. package/dist/chunk-EHZ6PIGN.js.map +1 -0
  5. package/dist/chunk-NC45IO63.js +777 -0
  6. package/dist/chunk-NC45IO63.js.map +1 -0
  7. package/dist/chunk-RIFATQB5.js +257 -0
  8. package/dist/chunk-RIFATQB5.js.map +1 -0
  9. package/dist/chunk-UGJUTRXC.js +304 -0
  10. package/dist/chunk-UGJUTRXC.js.map +1 -0
  11. package/dist/client/components/index.cjs +60 -59
  12. package/dist/client/components/index.cjs.map +1 -1
  13. package/dist/client/components/index.d.cts +40 -22
  14. package/dist/client/components/index.d.ts +40 -22
  15. package/dist/client/components/index.js +34 -62
  16. package/dist/client/components/index.js.map +1 -1
  17. package/dist/client/core/index.cjs +308 -222
  18. package/dist/client/core/index.cjs.map +1 -1
  19. package/dist/client/core/index.d.cts +4 -4
  20. package/dist/client/core/index.d.ts +4 -4
  21. package/dist/client/core/index.js +14 -14
  22. package/dist/client/hooks/index.cjs +87 -13
  23. package/dist/client/hooks/index.cjs.map +1 -1
  24. package/dist/client/hooks/index.d.cts +102 -9
  25. package/dist/client/hooks/index.d.ts +102 -9
  26. package/dist/client/hooks/index.js +9 -9
  27. package/dist/client/index.cjs +465 -237
  28. package/dist/client/index.cjs.map +1 -1
  29. package/dist/client/index.d.cts +7 -8
  30. package/dist/client/index.d.ts +7 -8
  31. package/dist/client/index.js +24 -18
  32. package/dist/{coinlist-client-B_dJkbwB.d.ts → coinlist-client-BSxpqylo.d.ts} +13 -138
  33. package/dist/{coinlist-client-DBKa6j3f.d.cts → coinlist-client-Cah5c_aF.d.cts} +13 -138
  34. package/dist/participation-DMMEDxON.d.cts +185 -0
  35. package/dist/participation-E-bT-GXJ.d.ts +185 -0
  36. package/dist/{requirement-CxbdY8l4.d.cts → requirement-XWT0T_zO.d.cts} +5 -2
  37. package/dist/{requirement-fJsQ3f9_.d.ts → requirement-XWT0T_zO.d.ts} +5 -2
  38. package/dist/server/index.cjs +519 -14
  39. package/dist/server/index.cjs.map +1 -1
  40. package/dist/server/index.d.cts +73 -4
  41. package/dist/server/index.d.ts +73 -4
  42. package/dist/server/index.js +116 -20
  43. package/dist/server/index.js.map +1 -1
  44. package/dist/useCoinListRequirements-B5-ZPOMz.d.ts +80 -0
  45. package/dist/useCoinListRequirements-Cuc32Tqw.d.cts +80 -0
  46. package/package.json +1 -1
  47. package/dist/chunk-GRVV7NLV.js +0 -282
  48. package/dist/chunk-GRVV7NLV.js.map +0 -1
  49. package/dist/chunk-IADBIDY6.js +0 -76
  50. package/dist/chunk-IADBIDY6.js.map +0 -1
  51. package/dist/chunk-IDCROXPS.js.map +0 -1
  52. package/dist/chunk-P4DTIPEX.js +0 -623
  53. package/dist/chunk-P4DTIPEX.js.map +0 -1
  54. package/dist/chunk-V5M7SA3C.js +0 -161
  55. package/dist/chunk-V5M7SA3C.js.map +0 -1
  56. package/dist/newtype-yKTvFdg_.d.cts +0 -6
  57. package/dist/newtype-yKTvFdg_.d.ts +0 -6
  58. package/dist/oauth-session-DgItaMKN.d.cts +0 -56
  59. package/dist/oauth-session-DnKDI5ou.d.ts +0 -56
  60. package/dist/useCoinListOffers-C5lBlzcC.d.ts +0 -27
  61. package/dist/useCoinListOffers-CguwXaCX.d.cts +0 -27
  62. package/dist/useCoinListRequirements-BECx1cIw.d.ts +0 -31
  63. package/dist/useCoinListRequirements-CX2gV9gJ.d.cts +0 -31
  64. package/dist/useCompleteCoinListOAuth-BRhAqD4_.d.cts +0 -55
  65. package/dist/useCompleteCoinListOAuth-DEZpHjd6.d.ts +0 -55
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/api/pagination.ts","../src/shared/utils.ts","../src/shared/types/offer.ts","../src/shared/types/asset.ts","../src/shared/types/offer-detail.ts","../src/shared/types/participation.ts","../src/shared/types/requirement.ts","../src/shared/types/errors.ts","../src/shared/types/oauth.ts","../src/shared/api/frontline/index.ts","../src/shared/api/http-attributes.ts","../src/shared/api/http.ts","../src/shared/api/frontline/offers.ts","../src/shared/api/frontline/participations.ts","../src/shared/api/frontline/requirements.ts","../src/shared/api/http-client.ts","../src/shared/api/middleware/attach-session-middleware.ts","../src/shared/api/middleware/idempotency-key.ts","../src/shared/api/middleware/request-retry.ts","../src/shared/api/middleware/session-renewal.ts","../src/shared/api/authenticated-api-client.ts"],"sourcesContent":["import type { QueryParamValue } from '@/shared/api/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 PaginatedResponseDto<T> {\n data: T[];\n starting_after?: string;\n starting_before?: string;\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n startingAfter: Cursor | null;\n startingBefore: Cursor | null;\n}\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\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","/**\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 type { OfferDto } from '@/shared/types/dto/offer';\nimport type { Newtype } from '@/shared/types/newtype';\nimport { notBlankStringOrNull } from '@/shared/utils';\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 Offer = {\n id: OfferId;\n slug: OfferSlug;\n tagline: string | null;\n bannerUrl: string | null;\n logoUrl: string | null;\n startsAt: Date;\n endsAt: Date;\n};\n\nexport const Offer = {\n fromDto: (dto: OfferDto): Offer => ({\n id: OfferId(dto.id),\n slug: OfferSlug(dto.slug),\n tagline: notBlankStringOrNull(dto.tagline),\n bannerUrl: notBlankStringOrNull(dto.banner_url),\n logoUrl: notBlankStringOrNull(dto.logo_url),\n startsAt: new Date(dto.starts_at),\n endsAt: new Date(dto.ends_at),\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 { Asset } from '@/shared/types/asset';\nimport type {\n OfferDetailDto,\n OfferDetailFaqDto,\n OfferDetailLinkDto,\n OfferDetailMilestoneDto,\n OfferDetailOptionDto,\n OfferDetailTermDto,\n} from '@/shared/types/dto/offer-detail';\nimport type { Newtype } from '@/shared/types/newtype';\nimport { OfferId, OfferSlug } from '@/shared/types/offer';\nimport { notBlankStringOrNull } from '@/shared/utils';\n\nexport type OfferDetail = {\n id: OfferId;\n slug: OfferSlug;\n name: string;\n\n asset: Asset;\n fundingAssets: Asset[];\n\n about: string | null;\n tagline: string | null;\n bannerUrl: string | null;\n logoUrl: string | null;\n category: string | null;\n\n startsAt: Date;\n endsAt: Date;\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 return {\n id: OfferId(dto.id),\n slug: OfferSlug(dto.slug),\n name: dto.name,\n\n asset: Asset.fromDto(dto.asset),\n fundingAssets: dto.funding_assets.map(Asset.fromDto),\n\n about: notBlankStringOrNull(dto.about),\n tagline: notBlankStringOrNull(dto.tagline),\n bannerUrl: notBlankStringOrNull(dto.banner_url),\n logoUrl: notBlankStringOrNull(dto.logo_url),\n category: notBlankStringOrNull(dto.category),\n\n startsAt: new Date(dto.starts_at),\n endsAt: new Date(dto.ends_at),\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","import type { QueryParamValue } from '@/shared/api/http';\nimport { PaginationParams } from '@/shared/api/pagination';\nimport { Asset, type AssetId } from '@/shared/types/asset';\nimport type {\n CreateParticipationDto,\n ParticipationDto,\n ParticipationStatusDto,\n} from '@/shared/types/dto/participation';\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 { notBlankStringOrNull } from '@/shared/utils';\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<string, 'WalletAddress'>;\n/** Casts a string into a typed {@link WalletAddress}. */\nexport const WalletAddress = (value: 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 /** Raw amount to participate with. */\n amount: string;\n /** Funding asset id. */\n assetId: AssetId;\n /** Optional approval transaction hash, if applicable. */\n approvalTransactionHash?: string | null;\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 ? WalletAddress(walletAddress) : 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 type {\n RequirementDto,\n RequirementStatusesDto,\n RequirementStatusValueDto,\n RequirementTypeDto,\n} from '@/shared/types/dto/requirement';\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;\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};\n\nexport const RequirementStatusInfo = {\n fromStatusesDto: (dto: RequirementStatusesDto): RequirementStatusInfo[] =>\n Object.entries(dto.statuses).map(([id, status]) => ({\n id: RequirementId(id),\n status,\n })),\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","import type { Newtype } from '@/shared/types/newtype';\n\nexport type AuthorizationCode = Newtype<string, 'AuthorizationCode'>;\nexport const AuthorizationCode = (value: string): AuthorizationCode =>\n value as AuthorizationCode;\n\nexport type CodeVerifier = Newtype<string, 'CodeVerifier'>;\nexport const CodeVerifier = (value: string): CodeVerifier =>\n value as CodeVerifier;\n\nexport type CodeChallenge = Newtype<string, 'CodeChallenge'>;\nexport const CodeChallenge = (value: string): CodeChallenge =>\n value as CodeChallenge;\n\nexport type RedirectUri = Newtype<string, 'RedirectUri'>;\nexport const RedirectUri = (value: string): RedirectUri => value as RedirectUri;\n\nexport type ClientId = Newtype<string, 'ClientId'>;\nexport const ClientId = (value: string): ClientId => value as ClientId;\n\nexport type ClientSecret = Newtype<string, 'ClientSecret'>;\nexport const ClientSecret = (value: string): ClientSecret =>\n value as ClientSecret;\n","import type { HttpRequest } from '@/shared/api/http';\n\nexport 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\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","export 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};\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\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;\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} as const;\n","import {\n Attributes,\n type HttpRequestAttributes,\n} from '@/shared/api/http-attributes';\n\nexport type HttpClientConfig = {\n baseUrl: string;\n xApiVersion: string;\n};\n\nexport type QueryParamValue = string | number | boolean | null | undefined;\nexport type QueryParamValues = QueryParamValue | QueryParamValue[];\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 };\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\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 const body = text ? (JSON.parse(text) as TResponse) : null;\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","import type { Sender } from '@/shared/api/frontline';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport {\n fetchAllPages,\n PaginatedResponse,\n type PaginatedResponseDto,\n PaginationParams,\n} from '@/shared/api/pagination';\nimport type { OfferDto } from '@/shared/types/dto/offer';\nimport type { OfferDetailDto } from '@/shared/types/dto/offer-detail';\nimport { Offer, type OfferId } from '@/shared/types/offer';\nimport { OfferDetail } from '@/shared/types/offer-detail';\n\nexport async function fetchAllOffers(api: Sender): Promise<Offer[]> {\n return fetchAllPages((params) => fetchOffersPage(api, params));\n}\n\nexport async function fetchOffersPage(\n api: Sender,\n params: PaginationParams\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.protected(),\n });\n return PaginatedResponse.fromDto(pageDto, Offer.fromDto);\n}\n\nexport async function fetchOfferDetails(\n api: Sender,\n id: OfferId\n): Promise<OfferDetail> {\n const dto = await api.send<OfferDetailDto>({\n method: 'GET',\n url: `/v1/offers/${id}`,\n attributes: Attributes.protected(),\n });\n return OfferDetail.fromDto(dto);\n}\n","import type { Sender } from '@/shared/api/frontline';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport {\n fetchAllPages,\n PaginatedResponse,\n type PaginatedResponseDto,\n} from '@/shared/api/pagination';\nimport type { ParticipationDto } from '@/shared/types/dto/participation';\nimport type { OfferId } from '@/shared/types/offer';\nimport {\n CreateParticipationParams,\n Participation,\n type ParticipationId,\n ParticipationsPaginationParams,\n} from '@/shared/types/participation';\n\nexport async function fetchAllParticipations(\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 type { Sender } from '@/shared/api/frontline';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type {\n OfferRequirementsDto,\n RequirementStatusesDto,\n} from '@/shared/types/dto/requirement';\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): Promise<Record<OfferOptionId, Requirement[]>> {\n const response = await api.send<OfferRequirementsDto>({\n method: 'GET',\n url: `/v1/offers/${offerId}/requirements`,\n attributes: Attributes.protected(),\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 { HEADER_API_VERSION } from '@/shared/api/frontline';\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 [HEADER_API_VERSION]: this.config.xApiVersion,\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","import type { HttpRequest } from '@/shared/api/http';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type { BeforeRequestMiddleware } from '@/shared/api/http-client';\nimport type { OAuthAccessToken } from '@/shared/types/oauth-session';\n\nexport function attachSessionMiddleware(\n fetchAccessToken: (refresh: boolean) => Promise<OAuthAccessToken | null>\n): BeforeRequestMiddleware {\n return async (request: HttpRequest): Promise<HttpRequest> => {\n if (!Attributes.isProtected(request.attributes)) {\n return request;\n }\n\n const accessToken = await fetchAccessToken(false);\n if (accessToken === null) {\n return request;\n }\n\n return {\n ...request,\n headers: {\n ...(request.headers ?? {}),\n Authorization: `Bearer ${accessToken.value}`,\n },\n };\n };\n}\n","import { HEADER_IDEMPOTENCY_KEY } from '@/shared/api/frontline';\nimport type { HttpRequest } from '@/shared/api/http';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type { BeforeRequestMiddleware } from '@/shared/api/http-client';\nimport { getUUIDv4 } from '@/shared/utils';\n\nexport const idempotencyKeyMiddleware: BeforeRequestMiddleware = async (\n request: HttpRequest\n): Promise<HttpRequest> => {\n if (!Attributes.isIdempotent(request.attributes)) {\n return request;\n }\n\n const existingHeaders = request.headers ?? {};\n if (existingHeaders[HEADER_IDEMPOTENCY_KEY]) {\n return request;\n }\n\n return {\n ...request,\n headers: {\n ...existingHeaders,\n [HEADER_IDEMPOTENCY_KEY]: getUUIDv4(),\n },\n };\n};\n","import { Request } from '@/shared/api/http';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type { AfterRequestMiddleware } from '@/shared/api/http-client';\n\nconst MAX_ATTEMPTS = 3;\nconst INITIAL_DELAY_MS = 300;\nconst MAX_DELAY_MS = 2000;\n\nconst RETRYABLE_4XX = new Set([408, 409, 429]);\n\nexport function isRetryableStatus(status: number): boolean {\n return (status >= 500 && status < 600) || RETRYABLE_4XX.has(status);\n}\n\nfunction getRetryDelayMs(attempt: number): number {\n return Math.min(INITIAL_DELAY_MS * 2 ** (attempt - 1), MAX_DELAY_MS);\n}\n\nexport type RequestRetryMiddlewareOptions = {\n /**\n * Optional delay function. Defaults to real setTimeout-based delay.\n * Use a no-op (e.g. () => Promise.resolve()) in tests to avoid slow tests.\n */\n delayFn?: (ms: number) => Promise<void>;\n};\n\n/**\n * Creates the request retry after-request middleware. Inject a no-op delayFn\n * in tests to avoid real delays (unit testing best practice).\n */\nexport function createRequestRetryMiddleware(\n options: RequestRetryMiddlewareOptions = {}\n): AfterRequestMiddleware {\n const delayFn = options.delayFn ?? defaultDelay;\n\n return async ({ request, response, retry }) => {\n if (!isRetryableStatus(response.status)) {\n return response;\n }\n\n const currentAttempt = Attributes.getRetryAttempt(request.attributes);\n if (currentAttempt >= MAX_ATTEMPTS - 1) {\n return response;\n }\n\n const nextAttempt = currentAttempt + 1;\n await delayFn(getRetryDelayMs(nextAttempt));\n\n const nextRequest = Request.concatAttributes(\n request,\n Attributes.retryAttempt(nextAttempt)\n );\n return retry(nextRequest);\n };\n}\n\nfunction defaultDelay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Retries the request up to 3 times with exponential backoff when the response\n * has a retryable status (5xx server errors). Uses request.attributes.retryAttempt\n * to decide delay and whether to retry, so the middleware does not loop when\n * retry() runs the full HTTP middleware chain again.\n */\nexport const requestRetryMiddleware: AfterRequestMiddleware =\n createRequestRetryMiddleware();\n","import { Request } from '@/shared/api/http';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type { AfterRequestMiddleware } from '@/shared/api/http-client';\nimport type { OAuthAccessToken } from '@/shared/types/oauth-session';\n\nexport function renewSessionMiddleware(\n fetchAccessToken: (refresh: boolean) => Promise<OAuthAccessToken | null>\n): AfterRequestMiddleware {\n return async ({ request, response, retry }) => {\n if (response.status !== 401) {\n return response;\n }\n if (!Attributes.isProtected(request.attributes)) {\n return response;\n }\n if (Attributes.wasRenewAttempted(request.attributes)) {\n return response;\n }\n\n const newToken = await fetchAccessToken(true);\n if (newToken) {\n const nextRequest = Request.concatAttributes(\n request,\n Attributes.renewAttempted(true)\n );\n return retry(nextRequest);\n } else {\n return response;\n }\n };\n}\n","import type { HttpClientConfig, HttpRequest } from '@/shared/api/http';\nimport { HttpError } from '@/shared/api/http';\nimport type { BeforeRequestMiddleware } from '@/shared/api/http-client';\nimport { HttpClient } from '@/shared/api/http-client';\nimport { attachSessionMiddleware } from '@/shared/api/middleware/attach-session-middleware';\nimport { idempotencyKeyMiddleware } from '@/shared/api/middleware/idempotency-key';\nimport { requestRetryMiddleware } from '@/shared/api/middleware/request-retry';\nimport { renewSessionMiddleware } from '@/shared/api/middleware/session-renewal';\nimport type { OAuthAccessToken } from '@/shared/types/oauth-session';\n\n/**\n * Isomorphic HTTP client with session attachment, session renewal on 401,\n * idempotency key injection, and request retry. Works in both browser and\n * Node/server environments. Pass `additionalBeforeRequest` to inject\n * environment-specific middleware (e.g. `userAgentMiddleware` on the client).\n */\nexport class AuthenticatedApiClient {\n private readonly httpClient: HttpClient;\n\n constructor(\n config: HttpClientConfig,\n fetchAccessToken: (refresh: boolean) => Promise<OAuthAccessToken | null>,\n additionalBeforeRequest: BeforeRequestMiddleware[] = []\n ) {\n this.httpClient = new HttpClient(config, {\n beforeRequest: [\n attachSessionMiddleware(fetchAccessToken),\n ...additionalBeforeRequest,\n idempotencyKeyMiddleware,\n ],\n afterRequest: [\n renewSessionMiddleware(fetchAccessToken),\n requestRetryMiddleware,\n ],\n });\n }\n\n async send<TResponse>(request: HttpRequest): Promise<TResponse> {\n const response = await this.httpClient.send<TResponse>(request);\n if (response.status >= 200 && response.status < 300) {\n return response.body as TResponse;\n } else {\n throw new HttpError(response);\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,257 @@
1
+ import {
2
+ API_VERSION,
3
+ Attributes,
4
+ AuthenticatedApiClient,
5
+ AuthorizationCode,
6
+ COINLIST_BASE_URL,
7
+ CodeVerifier,
8
+ HEADER_USER_AGENT,
9
+ NotAuthenticatedError,
10
+ OAUTH_PAGE_PATH,
11
+ PUBLIC_API_BASE_URL,
12
+ SUPPORT_NEW_TICKET_URL,
13
+ VERIFY_IDENTITY_ACCREDITATION_PATH,
14
+ VERIFY_IDENTITY_PATH,
15
+ VERIFY_IDENTITY_PROOF_OF_ADDRESS_PATH,
16
+ VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH,
17
+ VERIFY_IDENTITY_VERIFIED_PATH,
18
+ WALLET_PATH,
19
+ arrayBufferToBase64Url,
20
+ createParticipation,
21
+ fetchAllOffers,
22
+ fetchAllParticipations,
23
+ fetchOfferDetails,
24
+ fetchOfferRequirements,
25
+ fetchOffersPage,
26
+ fetchParticipation,
27
+ fetchParticipationsPage,
28
+ fetchRequirementStatuses,
29
+ generateSecureRandomBase64Url,
30
+ getUUIDv4,
31
+ sha256
32
+ } from "./chunk-NC45IO63.js";
33
+
34
+ // src/client/core/api/middleware/device-id.ts
35
+ var DEVICE_ID_KEY = "coinlist.device_id";
36
+ function getDeviceId() {
37
+ let deviceId = localStorage.getItem(DEVICE_ID_KEY);
38
+ if (!deviceId) {
39
+ deviceId = getUUIDv4();
40
+ localStorage.setItem(DEVICE_ID_KEY, deviceId);
41
+ }
42
+ return deviceId;
43
+ }
44
+
45
+ // src/client/core/api/middleware/user-agent.ts
46
+ var userAgentMiddleware = async (request) => {
47
+ if (!Attributes.needUserAgent(request.attributes)) {
48
+ return request;
49
+ }
50
+ const userAgent = generateUserAgent();
51
+ return {
52
+ ...request,
53
+ headers: {
54
+ ...request.headers ?? {},
55
+ [HEADER_USER_AGENT]: userAgent
56
+ }
57
+ };
58
+ };
59
+ function generateUserAgent() {
60
+ const appInfo = `CoinList/1.0`;
61
+ const deviceInfo = "Web Browser";
62
+ const devicePlatform = "DevicePlatform web";
63
+ const deviceAppId = "DeviceAppID co.coinlist.sdk";
64
+ const deviceId = getDeviceId();
65
+ const finalDeviceId = `DeviceID ${deviceId}`;
66
+ return `${appInfo} (${deviceInfo}; ${devicePlatform}; ${deviceAppId}; ${finalDeviceId})`;
67
+ }
68
+
69
+ // src/client/core/api/api-client.ts
70
+ var ApiClient = class {
71
+ constructor(config, fetchAccessToken) {
72
+ this.client = new AuthenticatedApiClient(config, fetchAccessToken, [
73
+ userAgentMiddleware
74
+ ]);
75
+ }
76
+ async send(request) {
77
+ return this.client.send(request);
78
+ }
79
+ };
80
+
81
+ // src/client/core/coinlist-client.ts
82
+ var OAUTH_STATE_KEY = "coinlist.oauth_state";
83
+ var OAUTH_CODE_VERIFIER_KEY = "coinlist.oauth_code_verifier";
84
+ var CoinListClientImpl = class {
85
+ constructor(_config) {
86
+ this._config = _config;
87
+ /** Cached access token: undefined = loading, null = no token, AccessToken = logged in */
88
+ this._accessToken = void 0;
89
+ this.api = new ApiClient(
90
+ {
91
+ baseUrl: _config.baseUrl || PUBLIC_API_BASE_URL,
92
+ xApiVersion: API_VERSION
93
+ },
94
+ this.fetchAccessToken.bind(this)
95
+ );
96
+ }
97
+ async init() {
98
+ await this.fetchAccessToken(true);
99
+ return this.getAuthState();
100
+ }
101
+ async fetchAccessToken(refresh) {
102
+ if (!refresh && this._accessToken !== void 0) return this._accessToken;
103
+ try {
104
+ const accessToken = await this._config.getAccessToken();
105
+ this._accessToken = accessToken;
106
+ return accessToken;
107
+ } catch (_) {
108
+ this._accessToken = null;
109
+ return null;
110
+ }
111
+ }
112
+ getAuthState() {
113
+ if (this._accessToken === void 0) {
114
+ return "unknown";
115
+ }
116
+ return this._accessToken !== null ? "logged-in" : "logged-out";
117
+ }
118
+ async startOAuth() {
119
+ const state = generateSecureRandomBase64Url(32);
120
+ const codeVerifier = generateSecureRandomBase64Url(32);
121
+ const codeChallengeRaw = await sha256(codeVerifier);
122
+ const codeChallenge = arrayBufferToBase64Url(codeChallengeRaw, false);
123
+ sessionStorage.setItem(OAUTH_STATE_KEY, state);
124
+ sessionStorage.setItem(OAUTH_CODE_VERIFIER_KEY, codeVerifier);
125
+ const params = new URLSearchParams({
126
+ client_id: this._config.clientId,
127
+ response_type: "code",
128
+ redirect_uri: this._config.redirectUri,
129
+ code_challenge: codeChallenge,
130
+ code_challenge_method: "S256",
131
+ state
132
+ });
133
+ const baseUrl = this._config.coinlistBaseUrl ?? COINLIST_BASE_URL;
134
+ const url = `${baseUrl}${OAUTH_PAGE_PATH}?${params.toString()}`;
135
+ window.location.href = url;
136
+ }
137
+ completeOAuth() {
138
+ const params = new URLSearchParams(window.location.search);
139
+ const coinlistError = params.get("error");
140
+ if (coinlistError) {
141
+ return { type: "error", reason: "user_canceled" };
142
+ }
143
+ const stateParam = params.get("state");
144
+ if (!stateParam) {
145
+ return { type: "error", reason: "missing_state" };
146
+ }
147
+ const storedState = sessionStorage.getItem(OAUTH_STATE_KEY);
148
+ if (storedState === null || storedState !== stateParam) {
149
+ return { type: "error", reason: "invalid_state" };
150
+ }
151
+ const codeParam = params.get("code");
152
+ if (!codeParam) {
153
+ return { type: "error", reason: "missing_code" };
154
+ }
155
+ const codeVerifierValue = sessionStorage.getItem(OAUTH_CODE_VERIFIER_KEY);
156
+ if (!codeVerifierValue) {
157
+ return { type: "error", reason: "missing_code_verifier" };
158
+ }
159
+ return {
160
+ type: "ok",
161
+ code: AuthorizationCode(codeParam),
162
+ codeVerifier: CodeVerifier(codeVerifierValue)
163
+ };
164
+ }
165
+ logout() {
166
+ this._accessToken = null;
167
+ }
168
+ async fetchAllOffers() {
169
+ this.ensureAuthenticated();
170
+ return fetchAllOffers(this.api);
171
+ }
172
+ async fetchOffersPage(params) {
173
+ this.ensureAuthenticated();
174
+ return fetchOffersPage(this.api, params);
175
+ }
176
+ async fetchOfferDetails(id) {
177
+ this.ensureAuthenticated();
178
+ return fetchOfferDetails(this.api, id);
179
+ }
180
+ async fetchAllParticipations(offerId) {
181
+ this.ensureAuthenticated();
182
+ return fetchAllParticipations(this.api, offerId);
183
+ }
184
+ async fetchParticipationsPage(params) {
185
+ this.ensureAuthenticated();
186
+ return fetchParticipationsPage(this.api, params);
187
+ }
188
+ async fetchParticipation(id) {
189
+ this.ensureAuthenticated();
190
+ return fetchParticipation(this.api, id);
191
+ }
192
+ async createParticipation(params) {
193
+ this.ensureAuthenticated();
194
+ return createParticipation(this.api, params);
195
+ }
196
+ async fetchOfferRequirements(offerId) {
197
+ this.ensureAuthenticated();
198
+ return fetchOfferRequirements(this.api, offerId);
199
+ }
200
+ async fetchRequirementStatuses(offerId) {
201
+ this.ensureAuthenticated();
202
+ return fetchRequirementStatuses(this.api, offerId);
203
+ }
204
+ handleRequirement(requirement) {
205
+ const baseUrl = this._config.coinlistBaseUrl ?? COINLIST_BASE_URL;
206
+ let path;
207
+ switch (requirement.type) {
208
+ case "kyc_approved":
209
+ path = VERIFY_IDENTITY_PATH;
210
+ break;
211
+ case "identity_verified":
212
+ path = VERIFY_IDENTITY_VERIFIED_PATH;
213
+ break;
214
+ case "proof_of_address":
215
+ path = VERIFY_IDENTITY_PROOF_OF_ADDRESS_PATH;
216
+ break;
217
+ case "source_of_funds":
218
+ path = VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH;
219
+ break;
220
+ case "accreditation":
221
+ path = VERIFY_IDENTITY_ACCREDITATION_PATH;
222
+ break;
223
+ case "external_wallet":
224
+ case "whitelisted_wallet":
225
+ path = WALLET_PATH;
226
+ break;
227
+ case "jurisdiction":
228
+ path = null;
229
+ break;
230
+ default: {
231
+ const _exhaustive = requirement.type;
232
+ return;
233
+ }
234
+ }
235
+ if (path === null) return;
236
+ openInNewTab(new URL(path, baseUrl).toString());
237
+ }
238
+ contactSupport() {
239
+ openInNewTab(SUPPORT_NEW_TICKET_URL);
240
+ }
241
+ ensureAuthenticated() {
242
+ if (this.getAuthState() !== "logged-in") {
243
+ throw new NotAuthenticatedError();
244
+ }
245
+ }
246
+ };
247
+ function openInNewTab(url) {
248
+ window.open(url, "_blank", "noopener,noreferrer");
249
+ }
250
+ function createCoinListClient(config) {
251
+ return new CoinListClientImpl(config);
252
+ }
253
+
254
+ export {
255
+ createCoinListClient
256
+ };
257
+ //# sourceMappingURL=chunk-RIFATQB5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client/core/api/middleware/device-id.ts","../src/client/core/api/middleware/user-agent.ts","../src/client/core/api/api-client.ts","../src/client/core/coinlist-client.ts"],"sourcesContent":["'use client';\n\nimport { getUUIDv4 } from '@/shared/utils';\n\nconst DEVICE_ID_KEY = 'coinlist.device_id';\n\n/**\n * Get or create a device ID stored in localStorage.\n * Uses a crypto UUID that persists across sessions.\n */\nexport function getDeviceId(): string {\n let deviceId = localStorage.getItem(DEVICE_ID_KEY);\n\n if (!deviceId) {\n deviceId = getUUIDv4();\n localStorage.setItem(DEVICE_ID_KEY, deviceId);\n }\n\n return deviceId;\n}\n\n/**\n * Clear the stored device ID (useful for testing or logout).\n */\nexport function clearDeviceId(): void {\n localStorage.removeItem(DEVICE_ID_KEY);\n}\n","'use client';\n\nimport { getDeviceId } from '@/client/core/api/middleware/device-id';\nimport { HEADER_USER_AGENT } from '@/shared/api/frontline';\nimport type { HttpRequest } from '@/shared/api/http';\nimport { Attributes } from '@/shared/api/http-attributes';\nimport type { BeforeRequestMiddleware } from '@/shared/api/http-client';\n\nexport const userAgentMiddleware: BeforeRequestMiddleware = async (\n request: HttpRequest\n): Promise<HttpRequest> => {\n if (!Attributes.needUserAgent(request.attributes)) {\n return request;\n }\n\n const userAgent = generateUserAgent();\n return {\n ...request,\n headers: {\n ...(request.headers ?? {}),\n [HEADER_USER_AGENT]: userAgent,\n },\n };\n};\n\n// Generate User-Agent in the required format for Frontline API\n// Format: <app-info> (<device-info>; DevicePlatform <device-platform>; DeviceAppID <device-app-id>; DeviceID <device-id>)\nfunction generateUserAgent(): string {\n const appInfo = `CoinList/1.0`;\n const deviceInfo = 'Web Browser';\n const devicePlatform = 'DevicePlatform web'; // Must be 'web' for validation\n\n const deviceAppId = 'DeviceAppID co.coinlist.sdk'; // SDK app ID\n\n const deviceId = getDeviceId();\n const finalDeviceId = `DeviceID ${deviceId}`;\n\n return `${appInfo} (${deviceInfo}; ${devicePlatform}; ${deviceAppId}; ${finalDeviceId})`;\n}\n","'use client';\n\nimport { userAgentMiddleware } from '@/client/core/api/middleware/user-agent';\nimport { AuthenticatedApiClient } from '@/shared/api/authenticated-api-client';\nimport type { HttpClientConfig, HttpRequest } from '@/shared/api/http';\nimport type { OAuthAccessToken } from '@/shared/types/oauth-session';\n\nexport class ApiClient {\n private readonly client: AuthenticatedApiClient;\n\n constructor(\n config: HttpClientConfig,\n fetchAccessToken: (refresh: boolean) => Promise<OAuthAccessToken | null>\n ) {\n this.client = new AuthenticatedApiClient(config, fetchAccessToken, [\n userAgentMiddleware,\n ]);\n }\n\n async send<TResponse>(request: HttpRequest): Promise<TResponse> {\n return this.client.send<TResponse>(request);\n }\n}\n","'use client';\n\nimport { ApiClient } from '@/client/core/api/api-client';\nimport type {\n AuthState,\n OauthClientResult,\n} from '@/client/core/types/client-types';\nimport {\n API_VERSION,\n COINLIST_BASE_URL,\n OAUTH_PAGE_PATH,\n PUBLIC_API_BASE_URL,\n SUPPORT_NEW_TICKET_URL,\n VERIFY_IDENTITY_ACCREDITATION_PATH,\n VERIFY_IDENTITY_PATH,\n VERIFY_IDENTITY_PROOF_OF_ADDRESS_PATH,\n VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH,\n VERIFY_IDENTITY_VERIFIED_PATH,\n WALLET_PATH,\n} from '@/shared/api/frontline';\nimport * as offersApi from '@/shared/api/frontline/offers';\nimport * as participationsApi from '@/shared/api/frontline/participations';\nimport * as requirementsApi from '@/shared/api/frontline/requirements';\nimport type {\n PaginatedResponse,\n PaginationParams,\n} from '@/shared/api/pagination';\nimport type { Config } from '@/shared/types/config';\nimport { NotAuthenticatedError } from '@/shared/types/errors';\nimport { AuthorizationCode, CodeVerifier } from '@/shared/types/oauth';\nimport type { OAuthAccessToken } from '@/shared/types/oauth-session';\nimport type { Offer, OfferId } from '@/shared/types/offer';\nimport type { OfferDetail, OfferOptionId } from '@/shared/types/offer-detail';\nimport type {\n CreateParticipationParams,\n Participation,\n ParticipationId,\n ParticipationsPaginationParams,\n} from '@/shared/types/participation';\nimport type {\n Requirement,\n RequirementStatusInfo,\n} from '@/shared/types/requirement';\nimport {\n arrayBufferToBase64Url,\n generateSecureRandomBase64Url,\n sha256,\n} from '@/shared/utils';\n\n/** Session storage keys for OAuth PKCE (used by startOauth and completeOauth). */\nexport const OAUTH_STATE_KEY = 'coinlist.oauth_state';\nexport const OAUTH_CODE_VERIFIER_KEY = 'coinlist.oauth_code_verifier';\n\nexport interface ClientConfig extends Config {\n /**\n * The SDK user must provide this function. It is responsible for fetching a\n * valid {@link OAuthAccessToken}, or **null** for logged-out users. If your\n * backend is in TypeScript, it is recommended to use\n * {@link CoinListServer#accessToken} from `@/server/coinlist.server`.\n */\n getAccessToken: () => Promise<OAuthAccessToken | null>;\n /**\n * Recommended to leave undefined. Used to change the CoinList environment;\n * default is production.\n */\n coinlistBaseUrl?: string;\n}\n\nexport interface CoinListClient {\n /**\n * Calls the provided {@link ClientConfig.getAccessToken} lambda to determine\n * the user's {@link AuthState}. This is called automatically by {@link CoinListProvider};\n * you typically do not need to call it yourself unless you are using the client\n * outside of the provider.\n */\n init(): Promise<AuthState>;\n /**\n * Returns the current auth state: `'logged-in'`, `'logged-out'`, or `'unknown'`.\n * Returns **unknown** until {@link CoinListClient.init} has completed. It is\n * recommended to use the `const { isReady, coinlist } = useCoinList()` hook to know when\n * the SDK has initialized, or to manually await {@link CoinListClient.init}\n * before relying on this value.\n */\n getAuthState(): AuthState;\n /**\n * Starts the OAuth flow with PKCE. Generates a random `state` and `code_verifier`,\n * stores them in sessionStorage (for validation in {@link CoinListClient.completeOAuth}\n * on redirect), then redirects the user to the CoinList authorization page. After\n * the user authorizes, they are sent back to your application's redirect URI; call\n * {@link CoinListClient.completeOAuth} on that page to finish the flow.\n */\n startOAuth(): Promise<void>;\n /**\n * Completes the OAuth flow on the FE with PKCE and state validation. Parses the\n * redirect URL (state, code) and validates them against sessionStorage\n * (state, code_verifier). The state check protects against CSRF (cross-site\n * request forgery). Call this on the frontend page the user is redirected\n * to after authorizing.\n *\n * On `ok`: Call your backend to exchange the short-lived `authorizationCode`\n * (and the returned `codeVerifier`) for a long-lived session. If your backend\n * is in TypeScript, you can use {@link CoinListServer#completeOAuth} from\n * `@/server/coinlist.server` (CoinListServer) to perform that exchange.\n *\n * On `error`: `reason` is an {@link OauthClientErrorReason} (e.g. `'missing_state'`, `'invalid_state'`) so you can switch on it and surface a message to the user.\n */\n completeOAuth(): OauthClientResult;\n /**\n * Clears the in-memory access token. Note: you need to manually\n * also logout on the backend via CoinListServer#logout to clear the session cookie.\n */\n logout(): void;\n\n /**\n * Fetches all offers by iterating through every paginated response.\n *\n * This method must be called only when the user's {@link AuthState} is\n * `'logged-in'`. If the user is not authenticated, it throws\n * {@link NotAuthenticatedError}.\n */\n fetchAllOffers(): Promise<Offer[]>;\n /**\n * Fetches a single page of offers.\n *\n * This method must be called only when the user's {@link AuthState} is\n * `'logged-in'`. If the user is not authenticated, it throws\n * {@link NotAuthenticatedError}.\n */\n fetchOffersPage(params: PaginationParams): Promise<PaginatedResponse<Offer>>;\n /**\n * Fetches details for a given offer by its id.\n *\n * This method must be called only when the user's {@link AuthState} is\n * `'logged-in'`. If the user is not authenticated, it throws\n * {@link NotAuthenticatedError}.\n */\n fetchOfferDetails(id: OfferId): Promise<OfferDetail>;\n /**\n * Fetches all participations by iterating through every paginated response.\n *\n * This method must be called only when the user's {@link AuthState} is\n * `'logged-in'`. If the user is not authenticated, it throws\n * {@link NotAuthenticatedError}.\n */\n fetchAllParticipations(offerId?: OfferId): Promise<Participation[]>;\n /**\n * Fetches a single page of participations, optionally filtered by offer.\n *\n * This method must be called only when the user's {@link AuthState} is\n * `'logged-in'`. If the user is not authenticated, it throws\n * {@link NotAuthenticatedError}.\n */\n fetchParticipationsPage(\n params: ParticipationsPaginationParams\n ): Promise<PaginatedResponse<Participation>>;\n /**\n * Fetches a participation by id.\n *\n * This method must be called only when the user's {@link AuthState} is\n * `'logged-in'`. If the user is not authenticated, it throws\n * {@link NotAuthenticatedError}.\n */\n fetchParticipation(id: ParticipationId): Promise<Participation>;\n /**\n * Creates a participation.\n *\n * This method must be called only when the user's {@link AuthState} is\n * `'logged-in'`. If the user is not authenticated, it throws\n * {@link NotAuthenticatedError}.\n */\n createParticipation(\n params: CreateParticipationParams\n ): Promise<Participation>;\n /**\n * Fetches the requirements for all options of a given offer, grouped by option ID.\n *\n * This method must be called only when the user's {@link AuthState} is\n * `'logged-in'`. If the user is not authenticated, it throws\n * {@link NotAuthenticatedError}.\n */\n fetchOfferRequirements(\n offerId: OfferId\n ): Promise<Record<OfferOptionId, Requirement[]>>;\n /**\n * Fetches the user's requirement statuses for a given offer.\n *\n * This method must be called only when the user's {@link AuthState} is\n * `'logged-in'`. If the user is not authenticated, it throws\n * {@link NotAuthenticatedError}.\n */\n fetchRequirementStatuses(offerId: OfferId): Promise<RequirementStatusInfo[]>;\n /**\n * Opens the CoinList page for completing a given requirement in a new tab.\n * For `jurisdiction` requirements there is no CTA, so this is a no-op.\n */\n handleRequirement(requirement: Requirement): void;\n /**\n * Opens the CoinList support ticket page in a new tab.\n */\n contactSupport(): void;\n}\n\nclass CoinListClientImpl implements CoinListClient {\n /** Cached access token: undefined = loading, null = no token, AccessToken = logged in */\n private _accessToken: OAuthAccessToken | null | undefined = undefined;\n private readonly api: ApiClient;\n\n constructor(readonly _config: ClientConfig) {\n this.api = new ApiClient(\n {\n baseUrl: _config.baseUrl || PUBLIC_API_BASE_URL,\n xApiVersion: API_VERSION,\n },\n this.fetchAccessToken.bind(this)\n );\n }\n\n async init(): Promise<AuthState> {\n await this.fetchAccessToken(true);\n return this.getAuthState();\n }\n\n async fetchAccessToken(refresh: boolean): Promise<OAuthAccessToken | null> {\n if (!refresh && this._accessToken !== undefined) return this._accessToken;\n\n try {\n const accessToken = await this._config.getAccessToken();\n this._accessToken = accessToken;\n return accessToken;\n } catch (_) {\n this._accessToken = null;\n return null;\n }\n }\n\n getAuthState(): AuthState {\n if (this._accessToken === undefined) {\n return 'unknown';\n }\n return this._accessToken !== null ? 'logged-in' : 'logged-out';\n }\n\n async startOAuth(): Promise<void> {\n const state = generateSecureRandomBase64Url(32);\n const codeVerifier = generateSecureRandomBase64Url(32);\n\n const codeChallengeRaw = await sha256(codeVerifier);\n const codeChallenge = arrayBufferToBase64Url(codeChallengeRaw, false);\n\n sessionStorage.setItem(OAUTH_STATE_KEY, state);\n sessionStorage.setItem(OAUTH_CODE_VERIFIER_KEY, codeVerifier);\n\n const params = new URLSearchParams({\n client_id: this._config.clientId,\n response_type: 'code',\n redirect_uri: this._config.redirectUri,\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n state,\n });\n const baseUrl = this._config.coinlistBaseUrl ?? COINLIST_BASE_URL;\n const url = `${baseUrl}${OAUTH_PAGE_PATH}?${params.toString()}`;\n window.location.href = url;\n }\n\n completeOAuth(): OauthClientResult {\n const params = new URLSearchParams(window.location.search);\n\n const coinlistError = params.get('error');\n if (coinlistError) {\n return { type: 'error', reason: 'user_canceled' };\n }\n\n const stateParam = params.get('state');\n if (!stateParam) {\n return { type: 'error', reason: 'missing_state' };\n }\n const storedState = sessionStorage.getItem(OAUTH_STATE_KEY);\n if (storedState === null || storedState !== stateParam) {\n return { type: 'error', reason: 'invalid_state' };\n }\n\n const codeParam = params.get('code');\n if (!codeParam) {\n return { type: 'error', reason: 'missing_code' };\n }\n\n const codeVerifierValue = sessionStorage.getItem(OAUTH_CODE_VERIFIER_KEY);\n if (!codeVerifierValue) {\n return { type: 'error', reason: 'missing_code_verifier' };\n }\n\n return {\n type: 'ok',\n code: AuthorizationCode(codeParam),\n codeVerifier: CodeVerifier(codeVerifierValue),\n };\n }\n\n logout(): void {\n this._accessToken = null;\n }\n\n async fetchAllOffers(): Promise<Offer[]> {\n this.ensureAuthenticated();\n return offersApi.fetchAllOffers(this.api);\n }\n\n async fetchOffersPage(\n params: PaginationParams\n ): Promise<PaginatedResponse<Offer>> {\n this.ensureAuthenticated();\n return offersApi.fetchOffersPage(this.api, params);\n }\n\n async fetchOfferDetails(id: OfferId): Promise<OfferDetail> {\n this.ensureAuthenticated();\n return offersApi.fetchOfferDetails(this.api, id);\n }\n\n async fetchAllParticipations(offerId?: OfferId): Promise<Participation[]> {\n this.ensureAuthenticated();\n return participationsApi.fetchAllParticipations(this.api, offerId);\n }\n\n async fetchParticipationsPage(\n params: ParticipationsPaginationParams\n ): Promise<PaginatedResponse<Participation>> {\n this.ensureAuthenticated();\n return participationsApi.fetchParticipationsPage(this.api, params);\n }\n\n async fetchParticipation(id: ParticipationId): Promise<Participation> {\n this.ensureAuthenticated();\n return participationsApi.fetchParticipation(this.api, id);\n }\n\n async createParticipation(\n params: CreateParticipationParams\n ): Promise<Participation> {\n this.ensureAuthenticated();\n return participationsApi.createParticipation(this.api, params);\n }\n\n async fetchOfferRequirements(\n offerId: OfferId\n ): Promise<Record<OfferOptionId, Requirement[]>> {\n this.ensureAuthenticated();\n return requirementsApi.fetchOfferRequirements(this.api, offerId);\n }\n\n async fetchRequirementStatuses(\n offerId: OfferId\n ): Promise<RequirementStatusInfo[]> {\n this.ensureAuthenticated();\n return requirementsApi.fetchRequirementStatuses(this.api, offerId);\n }\n\n handleRequirement(requirement: Requirement): void {\n const baseUrl = this._config.coinlistBaseUrl ?? COINLIST_BASE_URL;\n let path: string | null;\n switch (requirement.type) {\n case 'kyc_approved':\n path = VERIFY_IDENTITY_PATH;\n break;\n case 'identity_verified':\n path = VERIFY_IDENTITY_VERIFIED_PATH;\n break;\n case 'proof_of_address':\n path = VERIFY_IDENTITY_PROOF_OF_ADDRESS_PATH;\n break;\n case 'source_of_funds':\n path = VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH;\n break;\n case 'accreditation':\n path = VERIFY_IDENTITY_ACCREDITATION_PATH;\n break;\n case 'external_wallet':\n case 'whitelisted_wallet':\n path = WALLET_PATH;\n break;\n case 'jurisdiction':\n path = null;\n break;\n default: {\n const _exhaustive: never = requirement.type;\n return;\n }\n }\n if (path === null) return;\n openInNewTab(new URL(path, baseUrl).toString());\n }\n\n contactSupport(): void {\n openInNewTab(SUPPORT_NEW_TICKET_URL);\n }\n\n private ensureAuthenticated() {\n if (this.getAuthState() !== 'logged-in') {\n throw new NotAuthenticatedError();\n }\n }\n}\n\nfunction openInNewTab(url: string): void {\n window.open(url, '_blank', 'noopener,noreferrer');\n}\n\nexport function createCoinListClient(config: ClientConfig): CoinListClient {\n return new CoinListClientImpl(config);\n}\n"],"mappings":"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","names":[]}