Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions app/commons/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import Redis from 'redis'

const redis = process.env.REDIS_URL ? Redis.createClient({
url: process.env.REDIS_URL
}) : null

export class CacheManager {
private static instance: CacheManager
private redis: Redis.RedisClientType | null = null

private constructor() {
if (redis) {
this.redis = redis
this.redis.on('error', (err) => console.error('Redis error:', err))
}
}

static getInstance(): CacheManager {
if (!CacheManager.instance) {
CacheManager.instance = new CacheManager()
}
return CacheManager.instance
}

async get<T>(key: string): Promise<T | null> {
if (!this.redis) return null

try {
const value = await this.redis.get(key)
return value ? JSON.parse(value) : null
} catch (error) {
console.error('Cache get error:', error)
return null
}
}

async set(key: string, value: any, ttlSeconds: number = 300): Promise<void> {
if (!this.redis) return

try {
await this.redis.setEx(key, ttlSeconds, JSON.stringify(value))
} catch (error) {
console.error('Cache set error:', error)
}
}

async del(key: string): Promise<void> {
if (!this.redis) return

try {
await this.redis.del(key)
} catch (error) {
console.error('Cache delete error:', error)
}
}
}

export const withCache = <T extends any[], R>(
fn: (...args: T) => Promise<R>,
keyGenerator: (...args: T) => string,
ttlSeconds: number = 300
) => {
return async (...args: T): Promise<R> => {
const cache = CacheManager.getInstance()
const cacheKey = keyGenerator(...args)

// Try to get from cache first
const cached = await cache.get<R>(cacheKey)
if (cached !== null) {
return cached
}

// Execute function and cache result
const result = await fn(...args)
await cache.set(cacheKey, result, ttlSeconds)

return result
}
}
13 changes: 13 additions & 0 deletions app/commons/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
type EVMParameter,
} from '../types'
import { formatEther, formatUnits } from 'viem'
import { withCache } from './cache'

export const getPath = (subdomain: string) => {
if (subdomain.length === 0) {
Expand Down Expand Up @@ -650,3 +651,15 @@ export function serializeValue(value: any): any {
// Handle other types (strings, numbers, booleans)
return value
}

export const fetchContractAbiRawCached = withCache(
fetchContractAbiRaw,
({ address, chainId }) => `contract_abi:${chainId}:${address}`,
600 // 10 minutes
)

export const getSourceCodeCached = withCache(
getSourceCode,
(chainId, address) => `source_code:${chainId}:${address}`,
3600 // 1 hour
)