import { z } from 'zod' import DOMPurify from 'isomorphic-dompurify' const sanitizeString = (str: string) => DOMPurify.sanitize(str).trim() const urlSchema = z.string().url("Invalid URL").refine((val) => val.startsWith("http://") || val.startsWith("https://"), { message: "URL must start with http:// or https://", }) export const coinSchema = z.object({ name: z.string() .min(1, "Name is required") .max(50, "Name too long") .regex(/^[\x20-\x7E]+$/, "Name can only contain standard characters") .transform(sanitizeString), ticker: z.string() .min(3, "Ticker must be at least 3 characters") .max(10, "Ticker cannot exceed 10 characters") .regex(/^[a-zA-Z0-9]+$/, "Ticker can only contain letters and numbers") .toUpperCase() .transform(sanitizeString), description: z.string() .max(500, "Description too long") .regex(/^[\x20-\x7E\n\r]*$/, "Description can only contain standard characters") .optional() .transform(val => sanitizeString(val || '')), image: urlSchema.optional().or(z.literal('')), website: urlSchema.optional().or(z.literal('')), twitter: urlSchema.optional().or(z.literal('')), telegram: urlSchema.optional().or(z.literal('')), initialBuy: z.number().min(0).max(100, "Initial buy cannot exceed 100 SOL").optional().default(0), useUserImage: z.boolean().optional(), verified: z.boolean().optional().default(false), boosted: z.boolean().optional().default(false), }) export const commentSchema = z.object({ coinId: z.string().min(1, "Coin ID required"), text: z.string() .min(1) .max(280, "Comment too long") .regex(/^[\x20-\x7E\n\r]+$/, "Comment can only contain standard characters") .transform(sanitizeString), }) export type CreateCoinInput = z.infer export type CreateCommentInput = z.infer export const RESERVED_USERNAMES = [ 'api', 'coin', 'create', 'dashboard', 'login', 'onboarding', 'privacy', 'terms', 'u', 'admin', 'administrator', 'mod', 'moderator', 'support', 'help', 'system', 'sys', 'bot', 'pummmp', 'null', 'undefined', 'void', 'root', 'webmaster', '404', '500' ] export const isReservedUsername = (username: string) => { return RESERVED_USERNAMES.includes(username.toLowerCase()); }