import { ethers } from "ethers"
import { isNetworkSupported } from "../resources/network-configs.js"
/**
* Validate Ethereum address
*/
export function validateAddress(address: string): { valid: boolean; error?: string } {
try {
ethers.getAddress(address)
return { valid: true }
} catch {
return { valid: false, error: "Invalid Ethereum address format" }
}
}
/**
* Validate trading pair format
*/
export function validateTradingPair(pair: string): { valid: boolean; error?: string } {
const pairRegex = /^[A-Z]{2,10}\/[A-Z]{2,10}$/
if (!pairRegex.test(pair)) {
return { valid: false, error: "Trading pair must be in format 'BASE/QUOTE' (e.g., 'ETH/USD')" }
}
return { valid: true }
}
/**
* Validate network name
*/
export function validateNetwork(network: string): { valid: boolean; error?: string } {
if (!isNetworkSupported(network)) {
return { valid: false, error: `Unsupported network: ${network}` }
}
return { valid: true }
}
/**
* Validate timestamp (Unix timestamp or ISO string)
*/
export function validateTimestamp(timestamp: string): { valid: boolean; error?: string; parsed?: Date } {
try {
// Try Unix timestamp first
const unixTime = parseInt(timestamp)
if (!isNaN(unixTime) && unixTime > 0) {
const date = new Date(unixTime * 1000)
if (date.getTime() > 0) {
return { valid: true, parsed: date }
}
}
// Try ISO string
const isoDate = new Date(timestamp)
if (!isNaN(isoDate.getTime())) {
return { valid: true, parsed: isoDate }
}
return { valid: false, error: "Invalid timestamp format. Use Unix timestamp or ISO 8601 string." }
} catch {
return { valid: false, error: "Invalid timestamp format" }
}
}
/**
* Validate gas limit
*/
export function validateGasLimit(gasLimit: number): { valid: boolean; error?: string } {
if (gasLimit < 21000) {
return { valid: false, error: "Gas limit must be at least 21,000" }
}
if (gasLimit > 30000000) {
return { valid: false, error: "Gas limit too high (max 30,000,000)" }
}
return { valid: true }
}
/**
* Validate subscription ID format
*/
export function validateSubscriptionId(subId: string): { valid: boolean; error?: string } {
const numericRegex = /^\d+$/
if (!numericRegex.test(subId)) {
return { valid: false, error: "Subscription ID must be a numeric string" }
}
return { valid: true }
}
/**
* Validate JavaScript source code (basic validation)
*/
export function validateJavaScriptCode(code: string): { valid: boolean; error?: string } {
if (code.length === 0) {
return { valid: false, error: "Source code cannot be empty" }
}
if (code.length > 100000) {
return { valid: false, error: "Source code too long (max 100KB)" }
}
// Basic syntax check - try to create a function
try {
new Function(code)
return { valid: true }
} catch (error) {
return { valid: false, error: `Invalid JavaScript syntax: ${error instanceof Error ? error.message : String(error)}` }
}
}
/**
* Validate pagination parameters
*/
export function validatePagination(limit?: number, offset?: number): { valid: boolean; error?: string } {
if (limit !== undefined) {
if (limit < 1 || limit > 1000) {
return { valid: false, error: "Limit must be between 1 and 1000" }
}
}
if (offset !== undefined) {
if (offset < 0) {
return { valid: false, error: "Offset must be non-negative" }
}
}
return { valid: true }
}
/**
* Validate request ID format
*/
export function validateRequestId(requestId: string): { valid: boolean; error?: string } {
// Chainlink request IDs are typically 32-byte hex strings
const requestIdRegex = /^0x[a-fA-F0-9]{64}$/
if (!requestIdRegex.test(requestId)) {
return { valid: false, error: "Request ID must be a 32-byte hex string (0x...)" }
}
return { valid: true }
}
/**
* Validate VRF num words parameter
*/
export function validateNumWords(numWords: number): { valid: boolean; error?: string } {
if (numWords < 1 || numWords > 500) {
return { valid: false, error: "Number of words must be between 1 and 500" }
}
return { valid: true }
}
/**
* Sanitize string input to prevent injection attacks
*/
export function sanitizeString(input: string): string {
return input
.replace(/[<>]/g, "") // Remove potential HTML tags
.replace(/['"]/g, "") // Remove quotes that could break SQL
.trim()
}