Skip to content

Commit

Permalink
add new script run update-adapter (#1351)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xpeluche authored Mar 11, 2024
1 parent d1e3378 commit 199f7aa
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"deploy:prod": "pnpm build && NODE_ENV='production' sls deploy --stage prod",
"create-adapter": "tsx scripts/create-adapter.ts",
"delete-adapter": "tsx scripts/delete-adapter.ts",
"update-adapter": "tsx scripts/update-adapter.ts",
"adapter-balances": "tsx scripts/run-adapter-balances.ts",
"update-adapter-balances": "tsx scripts/update-adapter-balances.ts",
"update-adapter-balances-prices": "tsx scripts/update-adapter-balances-prices.ts",
Expand Down
147 changes: 147 additions & 0 deletions scripts/update-adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/* eslint-disable security/detect-non-literal-fs-filename */
import fs from 'node:fs'
import path from 'node:path'
import url from 'node:url'

const __dirname = path.dirname(url.fileURLToPath(import.meta.url))

import { execSync } from 'node:child_process'

import { fromDefiLlamaChain } from '@lib/chains'
import { slugify } from '@lib/fmt'

interface ChainTvl {
tvl: Array<{ date: number }>
}

interface Protocol {
chainTvls: { [key: string]: ChainTvl }
}

interface ChainConfig {
[key: string]: { startDate?: number }
}

const adapterTemplate = (slug: string, chains: string[]) => `
import type { Adapter } from '@lib/adapter';
${chains.map((chain) => `import * as ${slugify(chain)} from './${chain}'`).join(';\n')}
const adapter: Adapter = {
id: '${slug}',
${chains.map((chain) => `'${chain}': ${slugify(chain)}`).join(',\n ')}
};
export default adapter;
`

const chainTemplate = (startDate?: number) => `
import type { AdapterConfig, BaseContext, GetBalancesHandler } from '@lib/adapter'
import { resolveBalances } from '@lib/balance'
export const getContracts = async (ctx: BaseContext) => {
return {
// Contracts grouped by keys. They will be passed to getBalances, filtered by user interaction
contracts: {},
// Optional revalidate time (in seconds).
// Contracts returned by the adapter are cached by default and can be updated by interval with this parameter.
// This is mostly used for Factory contracts, where the number of contracts deployed increases over time
// revalidate: 60 * 60,
}
}
export const getBalances: GetBalancesHandler<typeof getContracts> = async (ctx, contracts) => {
// Any method to check the contracts retrieved above (based on user interaction).
// This function will be run each time a user queries his balances.
// As static contracts info is filled in getContracts, this should ideally only fetch the current amount of each contract (+ underlyings and rewards)
const balances = await resolveBalances<typeof getContracts>(ctx, contracts, {})
return {
groups: [{ balances }],
}
}
export const config: AdapterConfig = {
startDate: ${startDate},
}
`

function help() {
console.log('pnpm run update-adapter {adapter}')
}

async function updateAdapter(slug: string) {
const dst = path.join(__dirname, '..', 'src', 'adapters', slug)
if (!fs.existsSync(dst)) {
console.error(`Adapter ${slug} does not exist. Please create it first.`)
return
}

const protocolRes = await fetch(`https://api.llama.fi/protocol/${slug}`)
const protocol: Protocol = await protocolRes.json()

if (!protocol) {
console.error(`Failed to update adapter: ${slug} doesn't exist on DefiLlama`)
return
}

const existingChains = fs.readdirSync(dst).filter((file) => fs.statSync(path.join(dst, file)).isDirectory())
const chainConfigs: ChainConfig = {}
const addedChains: string[] = []

Object.entries(protocol.chainTvls).forEach(([key, { tvl }]) => {
if (!fromDefiLlamaChain[key]) return

const chainName = fromDefiLlamaChain[key]
const startDate = tvl?.[0]?.date

chainConfigs[chainName] = {
startDate: (Math.min(startDate) || Infinity, startDate),
}

if (!existingChains.includes(chainName)) {
addedChains.push(chainName)
const chainDir = path.join(dst, chainName)
fs.mkdirSync(chainDir, { recursive: true })
fs.writeFileSync(path.join(chainDir, 'index.ts'), chainTemplate(chainConfigs[chainName].startDate))
}
})

const updatedChains = Object.keys(chainConfigs)
fs.writeFileSync(path.join(dst, 'index.ts'), adapterTemplate(slug, updatedChains))

execSync(`npx prettier --write '${dst}/**/*.{ts,js,json,md}'`)

if (addedChains.length > 0) {
console.log(`Adapter ${slug} updated successfully. Added new chains: ${addedChains.join(', ')}.`)
} else {
console.log(`Adapter ${slug} updated successfully. No new chains were added.`)
}
}

async function main() {
// argv[0]: node
// argv[1]: script file path
// argv[2]: adapter slug
if (process.argv.length < 3) {
console.error('Missing arguments')
return help()
}

const slug = process.argv[2]
await updateAdapter(slug)

console.log(`Successfully updated adapter`)
console.log('')
console.log(`pnpm run adapter ${slug}`)
}

main()
.then(() => {
process.exit(0)
})
.catch((e) => {
console.error(e)
process.exit(1)
})
28 changes: 28 additions & 0 deletions src/adapters/virtuswap/arbitrum/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { AdapterConfig, BaseContext, GetBalancesHandler } from '@lib/adapter'
import { resolveBalances } from '@lib/balance'

export const getContracts = async (ctx: BaseContext) => {

Check warning on line 4 in src/adapters/virtuswap/arbitrum/index.ts

View workflow job for this annotation

GitHub Actions / Lint, Build, Test (lts/*, latest, ubuntu-latest)

'ctx' is defined but never used. Allowed unused args must match /^_/u
return {
// Contracts grouped by keys. They will be passed to getBalances, filtered by user interaction
contracts: {},
// Optional revalidate time (in seconds).
// Contracts returned by the adapter are cached by default and can be updated by interval with this parameter.
// This is mostly used for Factory contracts, where the number of contracts deployed increases over time
// revalidate: 60 * 60,
}
}

export const getBalances: GetBalancesHandler<typeof getContracts> = async (ctx, contracts) => {
// Any method to check the contracts retrieved above (based on user interaction).
// This function will be run each time a user queries his balances.
// As static contracts info is filled in getContracts, this should ideally only fetch the current amount of each contract (+ underlyings and rewards)
const balances = await resolveBalances<typeof getContracts>(ctx, contracts, {})

return {
groups: [{ balances }],
}
}

export const config: AdapterConfig = {
startDate: 1709683200,
}
2 changes: 2 additions & 0 deletions src/adapters/virtuswap/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { Adapter } from '@lib/adapter'

import * as arbitrum from './arbitrum'
import * as polygon from './polygon'

const adapter: Adapter = {
id: 'virtuswap',
polygon: polygon,
arbitrum: arbitrum,
}

export default adapter

0 comments on commit 199f7aa

Please sign in to comment.