@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
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/client/components/requirements/RequirementItem.tsx","../src/client/components/design-system/AlertBanner.tsx","../src/client/components/design-system/tokens/typography.ts","../src/client/components/design-system/utils.ts","../src/client/components/design-system/ClButton.tsx","../src/client/components/design-system/StepStatusIcon.tsx"],"sourcesContent":["'use client';\n\nimport { ChevronRight } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { AlertBanner } from '@/client/components/design-system/AlertBanner';\nimport { ClButton } from '@/client/components/design-system/ClButton';\nimport { StepStatusIcon } from '@/client/components/design-system/StepStatusIcon';\nimport { typeClasses } from '@/client/components/design-system/tokens/typography';\nimport { cn } from '@/client/components/design-system/utils';\nimport type {\n Requirement,\n RequirementStatusInfo,\n RequirementStatusValue,\n RequirementType,\n} from '@/shared/types/requirement';\n\nexport type RequirementVariant = 'verification' | 'wallet';\nexport const RequirementVariant = {\n fromType(type: RequirementType): RequirementVariant {\n switch (type) {\n case 'external_wallet':\n case 'whitelisted_wallet':\n return 'wallet';\n default:\n return 'verification';\n }\n },\n};\n\nexport type RequirementStatus =\n | 'required'\n | 'pending'\n | 'completed'\n | 'rejected';\nexport const RequirementStatus = {\n fromStatusValue(status: RequirementStatusValue): RequirementStatus {\n switch (status) {\n case 'not_started':\n case 'action_needed':\n return 'required';\n case 'in_progress':\n return 'pending';\n case 'completed':\n return 'completed';\n case 'rejected':\n return 'rejected';\n }\n },\n};\n\nexport type ChecklistStatus = 'inProgress' | 'eligible' | 'ineligible';\nexport const ChecklistStatus = {\n derive(statuses: RequirementStatusInfo[]): ChecklistStatus {\n if (statuses.some((s) => s.status === 'rejected')) return 'ineligible';\n if (statuses.every((s) => s.status === 'completed')) return 'eligible';\n return 'inProgress';\n },\n};\n\nexport type RequirementItemUi = {\n variant: RequirementVariant;\n status: RequirementStatus;\n label: string;\n description: string;\n walletAddress?: string;\n};\n\nexport const RequirementItemUi = {\n fromDomain(\n req: Requirement,\n statusInfo: RequirementStatusInfo | undefined,\n label: string,\n description: string,\n walletAddress?: string\n ): RequirementItemUi {\n return {\n variant: RequirementVariant.fromType(req.type),\n status: statusInfo\n ? RequirementStatus.fromStatusValue(statusInfo.status)\n : 'required',\n label,\n description,\n walletAddress,\n };\n },\n};\n\nexport interface RequirementItemProps {\n ui: RequirementItemUi;\n expanded?: boolean;\n onToggle?: () => void;\n walletAddress?: string;\n className?: string;\n onAction?: () => void;\n onContactSupport?: () => void;\n}\n\nfunction VerificationActionZone({\n status,\n onAction,\n onContactSupport,\n}: {\n status: RequirementStatus;\n onAction?: () => void;\n onContactSupport?: () => void;\n}): ReactNode {\n switch (status) {\n case 'required':\n return (\n <ClButton size=\"sm\" onClick={onAction}>\n Continue\n </ClButton>\n );\n case 'pending':\n return (\n <AlertBanner\n variant=\"warning\"\n content=\"Under review. We'll notify you when complete.\"\n />\n );\n case 'completed':\n return <AlertBanner variant=\"success\" content=\"Identity verified.\" />;\n case 'rejected':\n return (\n <AlertBanner\n variant=\"error\"\n content={\n <>\n Verification rejected.{' '}\n <button\n type=\"button\"\n onClick={onContactSupport}\n className=\"underline\"\n >\n Contact support\n </button>\n .\n </>\n }\n />\n );\n }\n}\n\nfunction WalletActionZone({\n status,\n walletAddress,\n onAction,\n}: {\n status: RequirementStatus;\n walletAddress?: string;\n onAction?: () => void;\n}): ReactNode {\n if (status === 'completed') {\n return (\n <>\n <ClButton size=\"sm\" variant=\"secondary\" onClick={onAction}>\n Change wallet\n </ClButton>\n <AlertBanner\n variant=\"success\"\n content={walletAddress ?? 'Connected: 0xBa4b...9f2c'}\n />\n </>\n );\n }\n\n if (status === 'rejected') {\n return (\n <>\n <ClButton size=\"sm\" onClick={onAction}>\n Connect wallet\n </ClButton>\n <AlertBanner\n variant=\"error\"\n content=\"This wallet is not eligible for this sale.\"\n />\n </>\n );\n }\n\n return (\n <ClButton size=\"sm\" onClick={onAction}>\n Connect wallet\n </ClButton>\n );\n}\n\nexport function RequirementItem({\n ui,\n expanded = false,\n onToggle,\n className,\n onAction,\n onContactSupport,\n}: RequirementItemProps) {\n return (\n <div className={cn('flex w-full flex-col', className)}>\n <button\n type=\"button\"\n onClick={onToggle}\n aria-expanded={expanded}\n className=\"flex h-14 w-full cursor-pointer items-center justify-between rounded-2xl px-2 transition-colors hover:bg-surface\"\n >\n <div className=\"flex items-center gap-3\">\n <StepStatusIcon status={ui.status} />\n <span\n className={cn(\n typeClasses.body,\n 'whitespace-nowrap font-medium text-text-primary'\n )}\n >\n {ui.label}\n </span>\n </div>\n <ChevronRight\n className={cn(\n 'h-6 w-6 shrink-0 text-text-secondary transition-transform duration-300',\n expanded && 'rotate-90'\n )}\n aria-hidden=\"true\"\n />\n </button>\n\n <div\n className={cn(\n 'grid transition-[grid-template-rows] duration-300 ease-in-out',\n expanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'\n )}\n >\n {/* min-h-0 lets the grid item collapse to 0 when grid-rows is 0fr */}\n <div className=\"min-h-0 overflow-hidden\">\n <div className=\"flex flex-col gap-4 px-2 pb-4\">\n <p className={cn(typeClasses.subhead, 'text-text-secondary')}>\n {ui.description}\n </p>\n {ui.variant === 'verification' ? (\n <VerificationActionZone\n status={ui.status}\n onAction={onAction}\n onContactSupport={onContactSupport}\n />\n ) : (\n <WalletActionZone\n status={ui.status}\n walletAddress={ui.walletAddress}\n onAction={onAction}\n />\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import type { LucideIcon } from 'lucide-react';\nimport { CircleCheck, Info } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { typeClasses } from '@/client/components/design-system/tokens/typography';\nimport { cn } from '@/client/components/design-system/utils';\n\nexport type AlertBannerVariant = 'info' | 'success' | 'warning' | 'error';\n\ninterface AlertBannerProps {\n variant: AlertBannerVariant;\n content: ReactNode;\n icon?: boolean;\n className?: string;\n}\n\nconst variantConfig: Record<\n AlertBannerVariant,\n { container: string; text: string; Icon: LucideIcon }\n> = {\n info: {\n container: 'bg-surface border-border',\n text: 'text-text-secondary',\n Icon: Info,\n },\n success: {\n container: 'bg-success-subtle border-success-border',\n text: 'text-success',\n Icon: CircleCheck,\n },\n warning: {\n container: 'bg-warning-subtle border-warning-border',\n text: 'text-warning',\n Icon: Info,\n },\n error: {\n container: 'bg-error-subtle border-error-border',\n text: 'text-error',\n Icon: Info,\n },\n};\n\nexport function AlertBanner({\n variant,\n content,\n icon = false,\n className,\n}: AlertBannerProps) {\n const { container, text, Icon } = variantConfig[variant];\n\n return (\n <div\n className={cn(\n 'flex items-center rounded-btn border p-3',\n icon && 'gap-2',\n container,\n className\n )}\n >\n {icon && (\n <Icon className={cn('h-4 w-4 shrink-0', text)} aria-hidden=\"true\" />\n )}\n <p className={cn(typeClasses.subhead, text)}>{content}</p>\n </div>\n );\n}\n","/**\n * CoinList Sale SDK — Typography Tokens\n *\n * Scale based on design system.\n * fontSize in px, lineHeight as percentage string, fontWeight as number.\n * Use the cn() Tailwind classes where possible, these values\n * are for programmatic access or non-Tailwind contexts.\n */\n\nexport const typeScale = {\n hero: {\n fontSize: 64,\n lineHeight: '110%',\n fontWeight: 600,\n },\n display: {\n fontSize: 48,\n lineHeight: '110%',\n fontWeight: 600,\n },\n h1: {\n fontSize: 36,\n lineHeight: '120%',\n fontWeight: 600,\n },\n h2: {\n fontSize: 28,\n lineHeight: '125%',\n fontWeight: 600,\n },\n h3: {\n fontSize: 22,\n lineHeight: '130%',\n fontWeight: 600,\n },\n h4: {\n fontSize: 18,\n lineHeight: '135%',\n fontWeight: 500,\n },\n body: {\n fontSize: 16,\n lineHeight: '150%',\n fontWeight: 400,\n },\n subhead: {\n fontSize: 14,\n lineHeight: '150%',\n fontWeight: 400,\n },\n caption: {\n fontSize: 12,\n lineHeight: '140%',\n fontWeight: 400,\n },\n label: {\n fontSize: 14,\n lineHeight: '140%',\n fontWeight: 500,\n },\n data: {\n fontSize: 14,\n lineHeight: '140%',\n fontWeight: 400,\n },\n} as const;\n\n/**\n * Tailwind class mappings for each type style.\n * Use these className strings directly in components.\n *\n * e.g. <h1 className={typeClasses.h1}>Hello</h1>\n */\nexport const typeClasses = {\n hero: 'text-[64px] leading-[110%] font-semibold',\n display: 'text-[48px] leading-[110%] font-semibold',\n h1: 'text-[36px] leading-[120%] font-semibold',\n h2: 'text-[28px] leading-[125%] font-semibold',\n h3: 'text-[22px] leading-[130%] font-semibold',\n h4: 'text-[18px] leading-[135%] font-medium',\n body: 'text-[16px] leading-[150%] font-normal',\n subhead: 'text-[14px] leading-[150%] font-normal',\n caption: 'text-[12px] leading-[140%] font-normal',\n label: 'text-[14px] leading-[140%] font-medium',\n data: 'text-[14px] leading-[140%] font-normal',\n} as const;\n\nexport type TypeScale = keyof typeof typeScale;\n","import { type ClassValue, clsx } from 'clsx';\n\n/**\n * Utility function to merge class names using clsx.\n */\nexport function cn(...inputs: ClassValue[]) {\n return clsx(inputs);\n}\n","'use client';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { type ButtonHTMLAttributes, forwardRef, type ReactNode } from 'react';\nimport { cn } from '@/client/components/design-system/utils';\n\n// Button variants using class-variance-authority for consistent styling\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-3 whitespace-nowrap transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-40 cursor-pointer',\n {\n variants: {\n variant: {\n // Primary — tokens auto-switch: dark bg (#171717) → light bg (#f4f4f5) in dark mode\n primary:\n 'bg-brand-primary text-text-inverse font-semibold hover:bg-brand-primary-hover active:bg-brand-primary-active focus-visible:ring-gray-500',\n // Secondary — bg-section, border-border, text-text-primary all auto-switch\n // hover maps to border token value; active has no token so uses dark: override\n secondary:\n 'bg-section border border-border text-text-primary font-medium hover:bg-border active:bg-[#d9d9d9] dark:active:bg-divider focus-visible:ring-gray-400',\n // Destructive — error tokens auto-switch to translucent dark equivalents\n // hover/active have no tokens so use dark: overrides\n destructive:\n 'bg-error-subtle border border-error-border text-error font-semibold hover:bg-[#fcdcd8] active:bg-[#f9c9c4] dark:hover:bg-[rgba(248,113,113,0.20)] dark:active:bg-[rgba(248,113,113,0.30)] focus-visible:ring-red-400',\n // Ghost — transparent base; hover/active use section/border tokens (auto-switch)\n ghost:\n 'bg-transparent text-text-primary font-medium hover:bg-section active:bg-border focus-visible:ring-gray-400',\n // Link — text-text-primary auto-switches light/dark\n link: 'h-auto p-0 text-text-primary font-medium underline-offset-4 hover:underline focus-visible:ring-gray-500',\n // Destructive link — text-error auto-switches (#b42318 → #f87171 in dark)\n destructiveLink:\n 'h-auto p-0 text-error font-medium hover:text-[#8b1a13] active:text-[#6d1510] dark:hover:text-[#fca5a5] dark:active:text-[#f87171] focus-visible:ring-red-500',\n },\n size: {\n sm: 'h-9 px-4 text-sm tracking-[0.28px]',\n default: 'h-11 px-5 text-sm tracking-[0.28px]',\n lg: 'h-14 px-6 text-base',\n icon: 'h-12 w-12',\n },\n radius: {\n pill: 'rounded-full',\n // compound variants below handle size-specific radii\n rounded: '',\n },\n fullWidth: {\n true: 'w-full',\n false: '',\n },\n },\n compoundVariants: [\n { size: 'sm', radius: 'rounded', className: 'rounded-lg' },\n { size: 'default', radius: 'rounded', className: 'rounded-2xl' },\n { size: 'lg', radius: 'rounded', className: 'rounded-2xl' },\n { size: 'icon', radius: 'rounded', className: 'rounded-md' },\n ],\n defaultVariants: {\n variant: 'primary',\n size: 'default',\n radius: 'pill',\n fullWidth: false,\n },\n }\n);\n\ninterface ClButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n children?: ReactNode;\n isLoading?: boolean;\n loadingText?: string;\n startIcon?: ReactNode;\n endIcon?: ReactNode;\n}\n\nconst ClButton = forwardRef<HTMLButtonElement, ClButtonProps>(\n (\n {\n className,\n variant,\n size,\n radius,\n fullWidth,\n children,\n isLoading = false,\n loadingText,\n startIcon,\n endIcon,\n disabled,\n ...props\n },\n ref\n ) => {\n const isDisabled = disabled || isLoading;\n\n return (\n <button\n className={cn(\n buttonVariants({ variant, size, radius, fullWidth }),\n className\n )}\n ref={ref}\n disabled={isDisabled}\n {...props}\n >\n {isLoading && (\n <span\n className=\"h-4 w-4 shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent opacity-60\"\n aria-hidden=\"true\"\n />\n )}\n\n {startIcon && !isLoading && (\n <span className=\"shrink-0\">{startIcon}</span>\n )}\n\n <span className={cn(isLoading && 'opacity-60')}>\n {isLoading && loadingText ? loadingText : children}\n </span>\n\n {endIcon && !isLoading && <span className=\"shrink-0\">{endIcon}</span>}\n </button>\n );\n }\n);\n\nClButton.displayName = 'ClButton';\n\nexport { ClButton, buttonVariants };\nexport type { ClButtonProps };\n","import type { LucideIcon } from 'lucide-react';\nimport { CircleCheck, CircleX, Info } from 'lucide-react';\nimport { cn } from '@/client/components/design-system/utils';\n\nexport type StepStatus = 'required' | 'pending' | 'completed' | 'rejected';\n\ninterface StepStatusIconProps {\n status: StepStatus;\n className?: string;\n}\n\nconst statusConfig: Record<\n StepStatus,\n { Icon: LucideIcon; colorClass: string; fillClass: string }\n> = {\n required: {\n Icon: Info,\n colorClass: 'text-warning',\n fillClass: '[&_circle]:fill-warning-subtle',\n },\n pending: {\n Icon: Info,\n colorClass: 'text-warning',\n fillClass: '[&_circle]:fill-warning-subtle',\n },\n completed: {\n Icon: CircleCheck,\n colorClass: 'text-success',\n fillClass: '[&_circle]:fill-success-subtle',\n },\n rejected: {\n Icon: CircleX,\n colorClass: 'text-error',\n fillClass: '[&_circle]:fill-error-subtle',\n },\n};\n\nexport function StepStatusIcon({ status, className }: StepStatusIconProps) {\n const { Icon, colorClass, fillClass } = statusConfig[status];\n return (\n <Icon\n className={cn('h-6 w-6 shrink-0', colorClass, fillClass, className)}\n aria-hidden=\"true\"\n />\n );\n}\n"],"mappings":"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","names":["jsx","jsxs","CircleCheck","Info","jsx","Info","CircleCheck","jsx","jsxs"]}
@@ -1,623 +0,0 @@
1
- import {
2
- API_VERSION,
3
- Attributes,
4
- AuthorizationCode,
5
- COINLIST_OAUTH_PAGE_URL,
6
- CodeVerifier,
7
- HEADER_IDEMPOTENCY_KEY,
8
- HEADER_USER_AGENT,
9
- HttpClient,
10
- HttpError,
11
- PUBLIC_API_BASE_URL,
12
- Request,
13
- requestRetryMiddleware
14
- } from "./chunk-GRVV7NLV.js";
15
-
16
- // src/shared/api/pagination.ts
17
- var Cursor = (value) => value;
18
- async function fetchAllPages(fetchPage, baseParams) {
19
- const items = [];
20
- let cursor = null;
21
- do {
22
- const params = {
23
- ...baseParams ?? {},
24
- after: cursor ?? void 0
25
- };
26
- const page = await fetchPage(params);
27
- items.push(...page.data);
28
- cursor = page.startingAfter;
29
- } while (cursor);
30
- return items;
31
- }
32
- var PaginatedResponse = {
33
- fromDto: (dto, itemMapper) => ({
34
- data: dto.data.map(itemMapper),
35
- startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
36
- startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
37
- })
38
- };
39
- var PaginationParams = {
40
- toQueryParams: (params) => {
41
- const queryParams = {};
42
- if (params.after) {
43
- queryParams.starting_after = params.after;
44
- }
45
- if (params.before) {
46
- queryParams.starting_before = params.before;
47
- }
48
- if (params.limit) {
49
- queryParams.limit = params.limit;
50
- }
51
- return queryParams;
52
- }
53
- };
54
-
55
- // src/shared/utils.ts
56
- async function sha256(data) {
57
- const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
58
- const buffer = bytes.buffer.slice(
59
- bytes.byteOffset,
60
- bytes.byteOffset + bytes.byteLength
61
- );
62
- return crypto.subtle.digest("SHA-256", buffer);
63
- }
64
- function arrayBufferToBase64Url(buffer, padding = true) {
65
- const bytes = new Uint8Array(buffer);
66
- let binary = "";
67
- for (let i = 0; i < bytes.length; i++) {
68
- binary += String.fromCharCode(bytes[i]);
69
- }
70
- let base64 = btoa(binary);
71
- base64 = base64.replace(/\+/g, "-").replace(/\//g, "_");
72
- if (!padding) {
73
- base64 = base64.replace(/=+$/, "");
74
- }
75
- return base64;
76
- }
77
- function generateSecureRandomBase64Url(byteLength) {
78
- const bytes = new Uint8Array(byteLength);
79
- crypto.getRandomValues(bytes);
80
- const buffer = bytes.buffer;
81
- return arrayBufferToBase64Url(buffer, false);
82
- }
83
- function getUUIDv4() {
84
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
85
- return crypto.randomUUID();
86
- }
87
- if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
88
- const bytes = new Uint8Array(16);
89
- crypto.getRandomValues(bytes);
90
- bytes[6] = bytes[6] & 15 | 64;
91
- bytes[8] = bytes[8] & 63 | 128;
92
- const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
93
- 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("")}`;
94
- }
95
- return `${Date.now()}-${Math.random().toString(36).slice(2, 12)}`;
96
- }
97
- function notBlankStringOrNull(value) {
98
- if (value?.trim()) {
99
- return value;
100
- } else {
101
- return null;
102
- }
103
- }
104
-
105
- // src/shared/types/offer.ts
106
- var OfferId = (value) => value;
107
- var OfferSlug = (value) => value;
108
- var Offer = {
109
- fromDto: (dto) => ({
110
- id: OfferId(dto.id),
111
- slug: OfferSlug(dto.slug),
112
- tagline: notBlankStringOrNull(dto.tagline),
113
- bannerUrl: notBlankStringOrNull(dto.banner_url),
114
- logoUrl: notBlankStringOrNull(dto.logo_url),
115
- startsAt: new Date(dto.starts_at),
116
- endsAt: new Date(dto.ends_at)
117
- })
118
- };
119
-
120
- // src/shared/types/asset.ts
121
- var AssetId = (value) => value;
122
- var AssetCode = (value) => value;
123
- var Asset = {
124
- fromDto: (dto) => ({
125
- id: AssetId(dto.id),
126
- code: AssetCode(dto.code),
127
- name: dto.name,
128
- fractionalDigits: dto.fractional_digits
129
- })
130
- };
131
-
132
- // src/shared/types/offer-detail.ts
133
- var OfferOptionId = (value) => value;
134
- var OfferOptionSlug = (value) => value;
135
- var OfferDetail = {
136
- fromDto: (dto) => {
137
- if (!Array.isArray(dto.funding_assets)) {
138
- throw new Error(`funding_assets must be an array`);
139
- }
140
- if (!Array.isArray(dto.options)) {
141
- throw new Error(`options must be an array`);
142
- }
143
- if (!Array.isArray(dto.terms)) {
144
- throw new Error(`terms must be an array`);
145
- }
146
- if (!Array.isArray(dto.links)) {
147
- throw new Error(`links must be an array`);
148
- }
149
- if (!Array.isArray(dto.faqs)) {
150
- throw new Error(`faqs must be an array`);
151
- }
152
- if (!Array.isArray(dto.milestones)) {
153
- throw new Error(`milestones must be an array`);
154
- }
155
- return {
156
- id: OfferId(dto.id),
157
- slug: OfferSlug(dto.slug),
158
- name: dto.name,
159
- asset: Asset.fromDto(dto.asset),
160
- fundingAssets: dto.funding_assets.map(Asset.fromDto),
161
- about: notBlankStringOrNull(dto.about),
162
- tagline: notBlankStringOrNull(dto.tagline),
163
- bannerUrl: notBlankStringOrNull(dto.banner_url),
164
- logoUrl: notBlankStringOrNull(dto.logo_url),
165
- category: notBlankStringOrNull(dto.category),
166
- startsAt: new Date(dto.starts_at),
167
- endsAt: new Date(dto.ends_at),
168
- faqs: dto.faqs.map(FaqItem.fromDto),
169
- links: dto.links.map(Link.fromDto),
170
- milestones: dto.milestones.map(Milestone.fromDto),
171
- options: dto.options.map(OfferOption.fromDto),
172
- terms: dto.terms.map(TermItem.fromDto)
173
- };
174
- }
175
- };
176
- var OfferOption = {
177
- fromDto: (dto) => ({
178
- id: OfferOptionId(dto.id),
179
- slug: OfferOptionSlug(dto.slug),
180
- bidIncrement: dto.bid_increment,
181
- floorPriceUsd: dto.floor_price_usd,
182
- minimumPurchaseUsd: dto.minimum_purchase_usd,
183
- priceUsd: dto.price_usd,
184
- saleAgreementUrl: notBlankStringOrNull(dto.sale_agreement_url),
185
- totalTokenSupply: dto.total_token_supply
186
- })
187
- };
188
- var FaqItem = {
189
- fromDto: (dto) => ({
190
- question: notBlankStringOrNull(dto.question),
191
- answer: notBlankStringOrNull(dto.answer)
192
- })
193
- };
194
- var Link = {
195
- fromDto: (dto) => ({
196
- label: notBlankStringOrNull(dto.label),
197
- url: notBlankStringOrNull(dto.url)
198
- })
199
- };
200
- var TermItem = {
201
- fromDto: (dto) => ({
202
- key: notBlankStringOrNull(dto.key),
203
- value: notBlankStringOrNull(dto.value)
204
- })
205
- };
206
- var Milestone = {
207
- fromDto: (dto) => ({
208
- name: notBlankStringOrNull(dto.name),
209
- schedule: notBlankStringOrNull(dto.schedule),
210
- status: dto.status
211
- })
212
- };
213
-
214
- // src/shared/types/participation.ts
215
- var ParticipationId = (value) => value;
216
- var Blockchain = (value) => value;
217
- var WalletAddress = (value) => value;
218
- var ParticipationsPaginationParams = {
219
- toQueryParams: (params) => {
220
- const queryParams = PaginationParams.toQueryParams(params);
221
- if (params.offerId) {
222
- queryParams["filters[0][field]"] = "offer_id";
223
- queryParams["filters[0][op]"] = "==";
224
- queryParams["filters[0][value]"] = params.offerId;
225
- }
226
- return queryParams;
227
- }
228
- };
229
- var Participation = {
230
- /** Maps API DTO shape into the SDK participation domain model. */
231
- fromDto: (dto) => {
232
- const walletAddress = notBlankStringOrNull(dto.wallet_address);
233
- return {
234
- id: ParticipationId(dto.id),
235
- offerId: OfferId(dto.offer_id),
236
- offerOptionId: OfferOptionId(dto.offer_option_id),
237
- status: dto.status,
238
- amount: dto.amount,
239
- displayAmount: dto.amount_string,
240
- asset: Asset.fromDto(dto.asset),
241
- chain: Blockchain(dto.chain),
242
- insertedAt: dto.inserted_at ? new Date(dto.inserted_at) : null,
243
- updatedAt: dto.updated_at ? new Date(dto.updated_at) : null,
244
- walletAddress: walletAddress ? WalletAddress(walletAddress) : null
245
- };
246
- }
247
- };
248
- var CreateParticipationParams = {
249
- /** Maps participation creation params into API DTO payload. */
250
- toDto: (params) => ({
251
- offer_id: params.offerId,
252
- offer_option_id: params.offerOptionId,
253
- chain: params.chain,
254
- wallet_address: params.walletAddress,
255
- amount: params.amount,
256
- asset_id: params.assetId,
257
- approval_transaction_hash: params.approvalTransactionHash
258
- })
259
- };
260
-
261
- // src/shared/types/requirement.ts
262
- var RequirementId = (value) => value;
263
- var Requirement = {
264
- fromDto: (dto) => ({
265
- id: RequirementId(dto.id),
266
- type: dto.type,
267
- details: dto.details
268
- })
269
- };
270
- var RequirementStatusInfo = {
271
- fromStatusesDto: (dto) => Object.entries(dto.statuses).map(([id, status]) => ({
272
- id: RequirementId(id),
273
- status
274
- }))
275
- };
276
-
277
- // src/client/core/api/middleware/attach-session-middleware.ts
278
- function attachSessionMiddleware(fetchAccessToken) {
279
- return async (request) => {
280
- if (!Attributes.isProtected(request.attributes)) {
281
- return request;
282
- }
283
- const accessToken = await fetchAccessToken(false);
284
- if (accessToken === null) {
285
- return request;
286
- }
287
- return {
288
- ...request,
289
- headers: {
290
- ...request.headers ?? {},
291
- Authorization: `Bearer ${accessToken.value}`
292
- }
293
- };
294
- };
295
- }
296
-
297
- // src/client/core/api/middleware/session-renewal.ts
298
- function renewSessionMiddleware(fetchAccessToken) {
299
- return async ({ request, response, retry }) => {
300
- if (response.status !== 401) {
301
- return response;
302
- }
303
- if (!Attributes.isProtected(request.attributes)) {
304
- return response;
305
- }
306
- if (Attributes.wasRenewAttempted(request.attributes)) {
307
- return response;
308
- }
309
- const newToken = await fetchAccessToken(true);
310
- if (newToken) {
311
- const nextRequest = Request.concatAttributes(
312
- request,
313
- Attributes.renewAttempted(true)
314
- );
315
- return retry(nextRequest);
316
- } else {
317
- return response;
318
- }
319
- };
320
- }
321
-
322
- // src/client/core/api/middleware/device-id.ts
323
- var DEVICE_ID_KEY = "coinlist.device_id";
324
- function getDeviceId() {
325
- let deviceId = localStorage.getItem(DEVICE_ID_KEY);
326
- if (!deviceId) {
327
- deviceId = getUUIDv4();
328
- localStorage.setItem(DEVICE_ID_KEY, deviceId);
329
- }
330
- return deviceId;
331
- }
332
-
333
- // src/client/core/api/middleware/user-agent.ts
334
- var userAgentMiddleware = async (request) => {
335
- if (!Attributes.needUserAgent(request.attributes)) {
336
- return request;
337
- }
338
- const userAgent = generateUserAgent();
339
- return {
340
- ...request,
341
- headers: {
342
- ...request.headers ?? {},
343
- [HEADER_USER_AGENT]: userAgent
344
- }
345
- };
346
- };
347
- function generateUserAgent() {
348
- const appInfo = `CoinList/1.0`;
349
- const deviceInfo = "Web Browser";
350
- const devicePlatform = "DevicePlatform web";
351
- const deviceAppId = "DeviceAppID co.coinlist.sdk";
352
- const deviceId = getDeviceId();
353
- const finalDeviceId = `DeviceID ${deviceId}`;
354
- return `${appInfo} (${deviceInfo}; ${devicePlatform}; ${deviceAppId}; ${finalDeviceId})`;
355
- }
356
-
357
- // src/shared/api/middleware/idempotency-key.ts
358
- var idempotencyKeyMiddleware = async (request) => {
359
- if (!Attributes.isIdempotent(request.attributes)) {
360
- return request;
361
- }
362
- const existingHeaders = request.headers ?? {};
363
- if (existingHeaders[HEADER_IDEMPOTENCY_KEY]) {
364
- return request;
365
- }
366
- return {
367
- ...request,
368
- headers: {
369
- ...existingHeaders,
370
- [HEADER_IDEMPOTENCY_KEY]: getUUIDv4()
371
- }
372
- };
373
- };
374
-
375
- // src/client/core/api/api-client.ts
376
- var ApiClient = class {
377
- constructor(config, fetchAccessToken) {
378
- this.config = config;
379
- this.fetchAccessToken = fetchAccessToken;
380
- this.httpClient = new HttpClient(this.config, {
381
- beforeRequest: [
382
- attachSessionMiddleware(this.fetchAccessToken),
383
- userAgentMiddleware,
384
- idempotencyKeyMiddleware
385
- ],
386
- afterRequest: [
387
- renewSessionMiddleware(this.fetchAccessToken),
388
- requestRetryMiddleware
389
- ]
390
- });
391
- }
392
- async send(request) {
393
- const response = await this.httpClient.send(request);
394
- if (response.status >= 200 && response.status < 300) {
395
- return response.body;
396
- } else {
397
- throw new HttpError(response);
398
- }
399
- }
400
- };
401
-
402
- // src/shared/types/errors.ts
403
- var NotAuthenticatedError = class extends Error {
404
- constructor(message = "The user is not authenticated. Go through the OAuth flow first!") {
405
- super(message);
406
- this.name = "NotAuthenticatedError";
407
- }
408
- };
409
-
410
- // src/client/core/coinlist-client.ts
411
- var OAUTH_STATE_KEY = "coinlist.oauth_state";
412
- var OAUTH_CODE_VERIFIER_KEY = "coinlist.oauth_code_verifier";
413
- var CoinListClientImpl = class {
414
- constructor(_config) {
415
- this._config = _config;
416
- /** Cached access token: undefined = loading, null = no token, AccessToken = logged in */
417
- this._accessToken = void 0;
418
- this.api = new ApiClient(
419
- {
420
- baseUrl: _config.baseUrl || PUBLIC_API_BASE_URL,
421
- xApiVersion: API_VERSION
422
- },
423
- this.fetchAccessToken.bind(this)
424
- );
425
- }
426
- async init() {
427
- await this.fetchAccessToken(true);
428
- return this.getAuthState();
429
- }
430
- async fetchAccessToken(refresh) {
431
- if (!refresh && this._accessToken !== void 0) return this._accessToken;
432
- try {
433
- const accessToken = await this._config.getAccessToken();
434
- this._accessToken = accessToken;
435
- return accessToken;
436
- } catch (_) {
437
- this._accessToken = null;
438
- return null;
439
- }
440
- }
441
- getAuthState() {
442
- if (this._accessToken === void 0) {
443
- return "unknown";
444
- }
445
- return this._accessToken !== null ? "logged-in" : "logged-out";
446
- }
447
- async startOAuth() {
448
- const state = generateSecureRandomBase64Url(32);
449
- const codeVerifier = generateSecureRandomBase64Url(32);
450
- const codeChallengeRaw = await sha256(codeVerifier);
451
- const codeChallenge = arrayBufferToBase64Url(codeChallengeRaw, false);
452
- sessionStorage.setItem(OAUTH_STATE_KEY, state);
453
- sessionStorage.setItem(OAUTH_CODE_VERIFIER_KEY, codeVerifier);
454
- const params = new URLSearchParams({
455
- client_id: this._config.clientId,
456
- response_type: "code",
457
- redirect_uri: this._config.redirectUri,
458
- code_challenge: codeChallenge,
459
- code_challenge_method: "S256",
460
- state
461
- });
462
- const oauthPageUrl = this._config.authorizationPageUrl ?? COINLIST_OAUTH_PAGE_URL;
463
- const url = `${oauthPageUrl}?${params.toString()}`;
464
- window.location.href = url;
465
- }
466
- completeOAuth() {
467
- const params = new URLSearchParams(window.location.search);
468
- const coinlistError = params.get("error");
469
- if (coinlistError) {
470
- return { type: "error", reason: "user_canceled" };
471
- }
472
- const stateParam = params.get("state");
473
- if (!stateParam) {
474
- return { type: "error", reason: "missing_state" };
475
- }
476
- const storedState = sessionStorage.getItem(OAUTH_STATE_KEY);
477
- if (storedState === null || storedState !== stateParam) {
478
- return { type: "error", reason: "invalid_state" };
479
- }
480
- const codeParam = params.get("code");
481
- if (!codeParam) {
482
- return { type: "error", reason: "missing_code" };
483
- }
484
- const codeVerifierValue = sessionStorage.getItem(OAUTH_CODE_VERIFIER_KEY);
485
- if (!codeVerifierValue) {
486
- return { type: "error", reason: "missing_code_verifier" };
487
- }
488
- return {
489
- type: "ok",
490
- code: AuthorizationCode(codeParam),
491
- codeVerifier: CodeVerifier(codeVerifierValue)
492
- };
493
- }
494
- logout() {
495
- this._accessToken = null;
496
- }
497
- async fetchAllOffers() {
498
- this.ensureAuthenticated();
499
- return await fetchAllPages(this.fetchOffersPage.bind(this));
500
- }
501
- async fetchOffersPage(params) {
502
- this.ensureAuthenticated();
503
- const queryParams = PaginationParams.toQueryParams(params);
504
- if (this._config.sandbox) {
505
- queryParams.sandbox = true;
506
- }
507
- const pageDto = await this.api.send({
508
- method: "GET",
509
- url: "/v1/offers",
510
- queryParams,
511
- attributes: Attributes.protected()
512
- });
513
- return PaginatedResponse.fromDto(pageDto, Offer.fromDto);
514
- }
515
- async fetchOfferDetails(id) {
516
- this.ensureAuthenticated();
517
- const offerDetailDto = await this.api.send({
518
- method: "GET",
519
- url: `/v1/offers/${id}`,
520
- attributes: Attributes.protected()
521
- });
522
- return OfferDetail.fromDto(offerDetailDto);
523
- }
524
- async fetchAllParticipations(offerId) {
525
- this.ensureAuthenticated();
526
- return await fetchAllPages(
527
- this.fetchParticipationsPage.bind(this),
528
- { offerId }
529
- );
530
- }
531
- async fetchParticipationsPage(params) {
532
- this.ensureAuthenticated();
533
- const pageDto = await this.api.send(
534
- {
535
- method: "GET",
536
- url: "/v1/participations",
537
- queryParams: ParticipationsPaginationParams.toQueryParams(params),
538
- attributes: Attributes.protected()
539
- }
540
- );
541
- return PaginatedResponse.fromDto(pageDto, Participation.fromDto);
542
- }
543
- async fetchParticipation(id) {
544
- this.ensureAuthenticated();
545
- const participationDto = await this.api.send({
546
- method: "GET",
547
- url: `/v1/participations/${id}`,
548
- attributes: Attributes.protected()
549
- });
550
- return Participation.fromDto(participationDto);
551
- }
552
- async createParticipation(params) {
553
- this.ensureAuthenticated();
554
- const participationDto = await this.api.send({
555
- method: "POST",
556
- url: "/v1/participations",
557
- body: CreateParticipationParams.toDto(params),
558
- attributes: Attributes.protected()
559
- });
560
- return Participation.fromDto(participationDto);
561
- }
562
- async fetchOfferRequirements(offerId) {
563
- this.ensureAuthenticated();
564
- const response = await this.api.send({
565
- method: "GET",
566
- url: `/v1/offers/${offerId}/requirements`,
567
- attributes: Attributes.protected()
568
- });
569
- return Object.fromEntries(
570
- Object.entries(response.options).map(([optionId, list]) => [
571
- optionId,
572
- list.data.map(Requirement.fromDto)
573
- ])
574
- );
575
- }
576
- async fetchRequirementStatuses(offerId) {
577
- this.ensureAuthenticated();
578
- const response = await this.api.send({
579
- method: "GET",
580
- url: `/v1/offers/${offerId}/requirements/statuses`,
581
- attributes: Attributes.protected()
582
- });
583
- return RequirementStatusInfo.fromStatusesDto(response);
584
- }
585
- ensureAuthenticated() {
586
- if (this.getAuthState() !== "logged-in") {
587
- throw new NotAuthenticatedError();
588
- }
589
- }
590
- };
591
- function createCoinListClient(config) {
592
- return new CoinListClientImpl(config);
593
- }
594
-
595
- export {
596
- Cursor,
597
- fetchAllPages,
598
- PaginatedResponse,
599
- PaginationParams,
600
- NotAuthenticatedError,
601
- OfferId,
602
- OfferSlug,
603
- Offer,
604
- OfferOptionId,
605
- OfferOptionSlug,
606
- OfferDetail,
607
- OfferOption,
608
- FaqItem,
609
- Link,
610
- TermItem,
611
- Milestone,
612
- ParticipationId,
613
- Blockchain,
614
- WalletAddress,
615
- ParticipationsPaginationParams,
616
- Participation,
617
- CreateParticipationParams,
618
- RequirementId,
619
- Requirement,
620
- RequirementStatusInfo,
621
- createCoinListClient
622
- };
623
- //# sourceMappingURL=chunk-P4DTIPEX.js.map