UNPKG

cdp-wallet-onramp-kit

Version:

Complete toolkit for Coinbase Developer Platform (CDP) Embedded Wallets and Onramp integration with reusable components, utilities, and documentation

175 lines (153 loc) 4.42 kB
import { z } from 'zod'; import { NextResponse } from 'next/server'; /** * Validation schema for wallet addresses */ export const walletAddressSchema = z.string().regex( /^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum wallet address format" ); /** * Validation schema for address with blockchains */ export const addressConfigSchema = z.object({ address: walletAddressSchema, blockchains: z.array(z.string().min(1)).min(1, "At least one blockchain is required") }); /** * Validation schema for session token creation (guest checkout) */ export const guestSessionTokenSchema = z.object({ guestCheckout: z.literal(true), assets: z.array(z.string()).optional().default(['ETH', 'USDC']) }); /** * Validation schema for session token creation (with wallet) */ export const walletSessionTokenSchema = z.object({ userAddress: walletAddressSchema, assets: z.array(z.string()).optional().default(['ETH', 'USDC']) }); /** * Combined session token validation schema */ export const sessionTokenSchema = z.union([ guestSessionTokenSchema, walletSessionTokenSchema ]); /** * Validation schema for onramp URL generation */ export const onrampUrlSchema = z.object({ addresses: z.array(addressConfigSchema).min(1, "At least one address is required"), assets: z.array(z.string()).optional(), defaultAsset: z.string().optional(), defaultNetwork: z.string().optional(), presetFiatAmount: z.number() .min(5, "Minimum amount is $5") .max(500, "Maximum amount is $500 (guest checkout limit)") .optional(), presetCryptoAmount: z.number().positive("Crypto amount must be positive").optional(), redirectUrl: z.string().url("Invalid redirect URL").optional(), partnerUserId: z.string().max(50, "Partner user ID must be 50 characters or less").optional() }); /** * Validation schema for amount input */ export const amountSchema = z.number() .min(5, "Minimum amount is $5") .max(500, "Maximum amount is $500"); /** * Validation schema for email input */ export const emailSchema = z.string().email("Invalid email address"); /** * Validation schema for OTP input */ export const otpSchema = z.string() .length(6, "OTP must be 6 digits") .regex(/^\d{6}$/, "OTP must contain only numbers"); /** * Common asset symbols validation */ export const assetSchema = z.enum([ 'ETH', 'USDC', 'BTC', 'USDT', 'DAI', 'WETH', 'MATIC', 'LINK', 'UNI' ]); /** * Network validation */ export const networkSchema = z.enum([ 'base', 'ethereum', 'arbitrum', 'optimism', 'polygon' ]); /** * Error response schema */ export const errorResponseSchema = z.object({ error: z.string(), details: z.any().optional(), code: z.string().optional() }); /** * Success response schema for session token */ export const sessionTokenResponseSchema = z.object({ sessionToken: z.string(), expiresIn: z.number().optional().default(300), // 5 minutes channelId: z.string().optional() }); /** * Success response schema for onramp URL */ export const onrampUrlResponseSchema = z.object({ url: z.string().url(), expiresIn: z.number().optional().default(300), // 5 minutes sessionToken: z.string().optional() }); /** * Utility function to validate and parse request data */ export function validateRequest<T>(schema: z.ZodSchema<T>, data: unknown): T { const result = schema.safeParse(data); if (!result.success) { const errorMessage = result.error.issues .map(issue => `${issue.path.join('.')}: ${issue.message}`) .join('; '); throw new Error(`Validation failed: ${errorMessage}`); } return result.data; } /** * Utility function to create error response */ export function createErrorResponse( error: string, statusCode?: number, suggestions?: string[] ) { return NextResponse.json({ error, ...(statusCode && { statusCode }), ...(suggestions && suggestions.length > 0 && { suggestions }), timestamp: new Date().toISOString(), help: 'Run "npx cdp-wallet-onramp-kit validate" to check your setup' }, { status: statusCode || 500 }); } /** * Utility function to validate environment variables */ export function validateEnvironment(): { isValid: boolean; missing: string[]; } { const required = [ 'CDP_API_KEY_PRIVATE_KEY', 'CDP_API_KEY_NAME' ]; const missing = required.filter(key => !process.env[key]); return { isValid: missing.length === 0, missing }; }