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
text/typescript
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
};
}