Last active
November 4, 2022 04:54
-
-
Save ZaK3939/c0e3526a4e4707038a5d08eae1513191 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { targetEnv, isLocal } from "../env"; | |
import { getCache, putCache } from "./ddbCache"; | |
const TABLE_NAME = "cache-" + targetEnv; | |
const DEFAULT_TTL = 90000; | |
export type CachedContractCallOptions = { | |
tableName?: string; | |
ttl?: number; | |
toJson?: boolean; | |
} | |
function convertOutput(result: any, toJson?: boolean): string { | |
if (toJson) { | |
return JSON.stringify(result); | |
} | |
if ((result as any)._isBigNumber) { | |
return result.toString(); | |
} | |
return result; | |
} | |
/** | |
* WARNING supported contract return types are number (BigNumber), string, struct | |
* other data types are not guaranteed to work | |
* set "opts.toJson" to true if smart contract return type is struct or a list of structs | |
* and this will convert output to json string | |
* @param contract | |
* @param functionName | |
* @param args | |
* @param opts | |
* @returns | |
*/ | |
export async function cachedContractCall(contract: any, functionName: string, args: any[], opts?: CachedContractCallOptions): Promise<string> { | |
if (isLocal) { | |
return convertOutput(await contract[functionName](...args), opts?.toJson); | |
} | |
let networkName; | |
if (!contract.provider.uniqueNetwork) { | |
networkName = "unknown"; | |
console.warn("unknown network"); | |
} | |
else { | |
networkName = typeof(contract.provider.uniqueNetwork) == "string" ? contract.provider.uniqueNetwork : contract.provider.uniqueNetwork.name; | |
} | |
const cacheKey = `${contract.address}.${networkName}.${functionName}.${JSON.stringify(args)}`; | |
const tableName = opts?.tableName ?? TABLE_NAME; | |
const ttl = opts?.ttl ?? DEFAULT_TTL; | |
console.log("try get cache", tableName, cacheKey) | |
let result = await getCache(cacheKey, tableName); | |
if (result) { | |
console.log("hit cache for", cacheKey); | |
return result; | |
} | |
// if not found in cache, call contract directly | |
result = await contract[functionName](...args); | |
result = convertOutput(result, opts?.toJson); | |
await putCache(cacheKey, result, ttl, tableName); | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import aws from "aws-sdk"; | |
import { targetEnv, isLocal } from "../env"; | |
const ddbClient = new aws.DynamoDB.DocumentClient({ region: "ap-northeast-1" }); | |
const TABLE_NAME = "cache-" + targetEnv; | |
const PREFIX = "CACHE"; | |
/** | |
* put a key-value pair to cache | |
* @param key | |
* @param value | |
* @param ttlMs | |
* @param tableNameOverride | |
* @returns success status | |
*/ | |
export async function putCache(key: string, value: string, ttlMs: number, tableNameOverride?: string): Promise<boolean> { | |
if (isLocal) { return false; } | |
const hashKey = [PREFIX, key].join("-"); | |
const expire = Date.now() + ttlMs; | |
try { | |
await ddbClient.put({ | |
TableName: tableNameOverride || TABLE_NAME, | |
Item: { | |
HashKey: hashKey, | |
Value: value, | |
Expire: expire | |
} | |
}).promise(); | |
return true; | |
} | |
catch (e) { | |
if (value.length > 2000) { | |
console.error(`ddbCache put error: ${JSON.stringify(e)}, key: ${key}, ttlMs: ${ttlMs}`); | |
} | |
else { | |
console.error(`ddbCache put error: ${JSON.stringify(e)}, key: ${key}, value: ${value}, ttlMs: ${ttlMs}`); | |
} | |
} | |
return false; | |
} | |
export async function getCache(key: string, tableNameOverride?: string): Promise<string | null> { | |
if (isLocal) { return null; } | |
const hashKey = [PREFIX, key].join("-"); | |
let result: string | null = null; | |
try { | |
const data = await ddbClient.get({ | |
TableName: tableNameOverride || TABLE_NAME, | |
Key: { | |
HashKey: hashKey | |
} | |
}).promise(); | |
if (data?.Item?.Value && data?.Item?.Expire) { | |
if (parseInt(data.Item.Expire) > Date.now()) { | |
result = data.Item.Value; | |
} | |
} | |
} | |
catch (e) { | |
console.error(`ddbCache get error: ${JSON.stringify(e)}, key: ${key}`); | |
} | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment