mirror of
https://github.com/alexgo-io/DefiLlama-Adapters.git
synced 2026-01-12 22:43:12 +08:00
Small cleanup dexVolumes folder (#3443)
* Add .vscode folder to .gitignore * Add v0 test script * Fix types * Fix chain blocks type * Change dex volumes readme * Fix ts errors * Remove workbench.colorCustomizations * Finally fix ts errors * Chore test script * Revert "Remove workbench.colorCustomizations" This reverts commit 8e8721096f2d148495511442e6d822f30e576f42. * Revert back since it doesn't solve the issue * Upgrade trilom/file-changes-action from 1.2.3 -> 1.2.4
This commit is contained in:
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -6,7 +6,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: file_changes
|
||||
uses: trilom/file-changes-action@v1.2.3
|
||||
uses: trilom/file-changes-action@v1.2.4
|
||||
with:
|
||||
output: 'json'
|
||||
fileOutput: 'json'
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,3 +8,4 @@ historical-data.js
|
||||
yarn.lock
|
||||
.DS_Store
|
||||
projects/pooltogether/index.js
|
||||
.vscode
|
||||
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.background": "#591417",
|
||||
"titleBar.activeBackground": "#7C1C20",
|
||||
"titleBar.activeForeground": "#FEFBFB"
|
||||
}
|
||||
}
|
||||
7
dexVolumes/README.md
Normal file
7
dexVolumes/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# DEX volumes
|
||||
|
||||
> **_NOTE:_** Under developement.
|
||||
|
||||
## Test an adapter
|
||||
|
||||
`npm run test-dex 1inch`
|
||||
@@ -1,12 +0,0 @@
|
||||
const { getCurrentBlocks } = require("@defillama/sdk/build/computeTVL/blocks");
|
||||
const { volume } = require("../pancakeswap");
|
||||
|
||||
const test = async () => {
|
||||
const { timestamp, chainBlocks } = await getCurrentBlocks();
|
||||
console.log(chainBlocks, "chainBlocks");
|
||||
volume.bsc.fetch(timestamp).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
};
|
||||
|
||||
test();
|
||||
63
dexVolumes/cli/testAdapter.ts
Normal file
63
dexVolumes/cli/testAdapter.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import * as path from 'path'
|
||||
import type { ChainBlocks, DexAdapter, VolumeAdapter } from '../dexVolume.type';
|
||||
import { chainsForBlocks } from "@defillama/sdk/build/computeTVL/blocks";
|
||||
import { Chain } from '@defillama/sdk/build/general';
|
||||
import handleError from '../../utils/handleError';
|
||||
import { checkArguments, getLatestBlockRetry, printVolumes } from './utils';
|
||||
|
||||
// Add handler to rejections/exceptions
|
||||
process.on('unhandledRejection', handleError)
|
||||
process.on('uncaughtException', handleError)
|
||||
|
||||
// Check if all arguments are present
|
||||
checkArguments(process.argv)
|
||||
|
||||
// Get path of module import
|
||||
const passedFile = path.resolve(process.cwd(), `dexVolumes/${process.argv[2]}`);
|
||||
(async () => {
|
||||
console.info(`Running ${process.argv[2].toUpperCase()} adapter`)
|
||||
// Import module to test
|
||||
let module: DexAdapter = (await import(passedFile)).default
|
||||
|
||||
if ("volume" in module) {
|
||||
// Get adapter
|
||||
const volumeAdapter = module.volume
|
||||
const volumes = await runAdapter(volumeAdapter)
|
||||
printVolumes(volumes)
|
||||
} else if ("breakdown" in module) {
|
||||
const breakdownAdapter = module.breakdown
|
||||
const allVolumes = await Promise.all(Object.entries(breakdownAdapter).map(async ([version, adapter]) =>
|
||||
await runAdapter(adapter).then(res => ({ version, res }))
|
||||
))
|
||||
allVolumes.forEach((promise) => {
|
||||
console.info(promise.version)
|
||||
printVolumes(promise.res)
|
||||
})
|
||||
} else console.info("No compatible adapter found")
|
||||
})()
|
||||
|
||||
async function runAdapter(volumeAdapter: VolumeAdapter) {
|
||||
// Get chains to check
|
||||
const chains = Object.keys(volumeAdapter).filter(item => typeof volumeAdapter[item] === 'object');
|
||||
// Get lastest block
|
||||
const chainBlocks: ChainBlocks = {};
|
||||
await Promise.all(
|
||||
chains.map(async (chainRaw) => {
|
||||
const chain: Chain = chainRaw === "ava" ? "avax" : chainRaw as Chain
|
||||
if (chainsForBlocks.includes(chain as Chain) || chain === "ethereum") {
|
||||
const latestBlock = await getLatestBlockRetry(chain)
|
||||
if (!latestBlock) throw new Error("latestBlock")
|
||||
chainBlocks[chain] = latestBlock.number - 10
|
||||
}
|
||||
})
|
||||
);
|
||||
// Get volumes
|
||||
const unixTimestamp = Math.round(Date.now() / 1000) - 60;
|
||||
const volumes = await Promise.all(Object.keys(chainBlocks).map(
|
||||
async chain => volumeAdapter[chain].fetch(unixTimestamp, chainBlocks)
|
||||
.then(res => {
|
||||
return { timestamp: unixTimestamp, totalVolume: res.totalVolume, dailyVolume: res.dailyVolume }
|
||||
})
|
||||
))
|
||||
return volumes
|
||||
}
|
||||
29
dexVolumes/cli/utils.ts
Normal file
29
dexVolumes/cli/utils.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { getLatestBlock } from "@defillama/sdk/build/util";
|
||||
import { FetchResult } from "../dexVolume.type";
|
||||
|
||||
export function checkArguments(argv: string[]) {
|
||||
if (argv.length < 3) {
|
||||
console.error(`Missing argument, you need to provide the filename of the adapter to test.
|
||||
Eg: ts-node dexVolumes/cli/testAdapter.js dexVolumes/myadapter.js`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
export async function getLatestBlockRetry(chain: string) {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
try {
|
||||
return await getLatestBlock(chain);
|
||||
} catch (e) {
|
||||
throw new Error(`Couln't get block heights for chain "${chain}"\n${e}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function printVolumes(volumes: FetchResult[]) {
|
||||
volumes.forEach(element => {
|
||||
console.info("----------")
|
||||
console.info(`Daily: ${element.dailyVolume}`)
|
||||
console.info(`Total: ${element.totalVolume}`)
|
||||
console.info("----------")
|
||||
});
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
export type ChainBlocks = {
|
||||
[x: string]: number;
|
||||
[x: string]: number
|
||||
};
|
||||
|
||||
export type FetchResult = {
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
const sdk = require("@defillama/sdk");
|
||||
const retry = require("async-retry");
|
||||
const axios = require("axios");
|
||||
|
||||
async function getBlock(timestamp, chain, chainBlocks, undefinedOk = false) {
|
||||
if (
|
||||
chainBlocks?.[chain] !== undefined ||
|
||||
(process.env.HISTORICAL === undefined && undefinedOk)
|
||||
) {
|
||||
return chainBlocks[chain];
|
||||
} else {
|
||||
if (chain === "celo") {
|
||||
return Number(
|
||||
(
|
||||
await retry(
|
||||
async (bail) =>
|
||||
await axios.get(
|
||||
"https://explorer.celo.org/api?module=block&action=getblocknobytime×tamp=" +
|
||||
timestamp +
|
||||
"&closest=before"
|
||||
)
|
||||
)
|
||||
).data.result.blockNumber
|
||||
);
|
||||
}
|
||||
return sdk.api.util
|
||||
.lookupBlock(timestamp, { chain })
|
||||
.then((blockData) => blockData.block);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getBlock,
|
||||
};
|
||||
@@ -1,38 +0,0 @@
|
||||
const { request, gql } = require("graphql-request");
|
||||
|
||||
const {
|
||||
DEFAULT_DAILY_VOLUME_FACTORY,
|
||||
DEFAULT_DAILY_VOLUME_FIELD,
|
||||
} = require("./getUniSubgraphVolume");
|
||||
|
||||
const getStartTimestamp =
|
||||
({
|
||||
endpoints,
|
||||
chain,
|
||||
dailyDataField = `${DEFAULT_DAILY_VOLUME_FACTORY}s`,
|
||||
volumeField = DEFAULT_DAILY_VOLUME_FIELD,
|
||||
dateField = "date",
|
||||
first = 1000,
|
||||
}) =>
|
||||
async () => {
|
||||
const query = gql`
|
||||
{
|
||||
${dailyDataField}(first: ${first}) {
|
||||
${dateField}
|
||||
${volumeField}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const result = await request(endpoints[chain], query);
|
||||
|
||||
const days = result?.[dailyDataField];
|
||||
|
||||
const firstValidDay = days.find((data) => data[volumeField] !== "0");
|
||||
|
||||
return firstValidDay[dateField];
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getStartTimestamp,
|
||||
};
|
||||
46
dexVolumes/helper/getStartTimestamp.ts
Normal file
46
dexVolumes/helper/getStartTimestamp.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { request, gql } from "graphql-request";
|
||||
|
||||
import { DEFAULT_DAILY_VOLUME_FACTORY, DEFAULT_DAILY_VOLUME_FIELD } from "./getUniSubgraphVolume";
|
||||
|
||||
interface IGetStartTimestamp {
|
||||
endpoints: {
|
||||
[chain: string]: string;
|
||||
}
|
||||
chain: string
|
||||
dailyDataField: string
|
||||
volumeField: string
|
||||
dateField?: string
|
||||
first?: number
|
||||
}
|
||||
|
||||
const getStartTimestamp =
|
||||
({
|
||||
endpoints,
|
||||
chain,
|
||||
dailyDataField = `${DEFAULT_DAILY_VOLUME_FACTORY}s`,
|
||||
volumeField = DEFAULT_DAILY_VOLUME_FIELD,
|
||||
dateField = "date",
|
||||
first = 1000,
|
||||
}: IGetStartTimestamp) =>
|
||||
async () => {
|
||||
const query = gql`
|
||||
{
|
||||
${dailyDataField}(first: ${first}) {
|
||||
${dateField}
|
||||
${volumeField}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const result = await request(endpoints[chain], query);
|
||||
|
||||
const days = result?.[dailyDataField];
|
||||
|
||||
const firstValidDay = days.find((data: any) => data[volumeField] !== "0");
|
||||
|
||||
return firstValidDay[dateField];
|
||||
};
|
||||
|
||||
export {
|
||||
getStartTimestamp,
|
||||
};
|
||||
@@ -1,5 +1,7 @@
|
||||
const { request, gql } = require("graphql-request");
|
||||
const { getBlock } = require("./getBlock");
|
||||
import { Chain } from "@defillama/sdk/build/general";
|
||||
import { request, gql } from "graphql-request";
|
||||
import { getBlock } from "../../projects/helper/getBlock";
|
||||
import { ChainBlocks } from "../dexVolume.type";
|
||||
|
||||
const getUniqStartOfTodayTimestamp = (date = new Date()) => {
|
||||
var date_utc = Date.UTC(
|
||||
@@ -11,7 +13,7 @@ const getUniqStartOfTodayTimestamp = (date = new Date()) => {
|
||||
date.getUTCSeconds()
|
||||
);
|
||||
var startOfDay = new Date(date_utc);
|
||||
var timestamp = startOfDay / 1000;
|
||||
var timestamp = startOfDay.getTime() / 1000;
|
||||
return Math.floor(timestamp / 86400) * 86400;
|
||||
};
|
||||
|
||||
@@ -24,6 +26,24 @@ const DEFAULT_TOTAL_VOLUME_FIELD = "totalVolumeUSD";
|
||||
const DEFAULT_DAILY_VOLUME_FACTORY = "uniswapDayData";
|
||||
const DEFAULT_DAILY_VOLUME_FIELD = "dailyVolumeUSD";
|
||||
|
||||
interface IGetChainVolumeParams {
|
||||
graphUrls: {
|
||||
[chains: string]: string
|
||||
},
|
||||
totalVolume: {
|
||||
factory: string,
|
||||
field: string
|
||||
},
|
||||
dailyVolume?: {
|
||||
factory: string,
|
||||
field: string
|
||||
},
|
||||
customDailyVolume?: string,
|
||||
hasDailyVolume?: boolean
|
||||
hasTotalVolume?: boolean
|
||||
getCustomBlock?: (timestamp: number) => Promise<number>
|
||||
}
|
||||
|
||||
function getChainVolume({
|
||||
graphUrls,
|
||||
totalVolume = {
|
||||
@@ -38,7 +58,7 @@ function getChainVolume({
|
||||
hasDailyVolume = true,
|
||||
hasTotalVolume = true,
|
||||
getCustomBlock = undefined,
|
||||
}) {
|
||||
}: IGetChainVolumeParams) {
|
||||
const totalVolumeQuery = gql`
|
||||
${totalVolume.factory}(
|
||||
block: { number: $block }
|
||||
@@ -56,18 +76,18 @@ function getChainVolume({
|
||||
${dailyVolume.field}
|
||||
}
|
||||
`;
|
||||
|
||||
const graphQuery = gql`
|
||||
query get_volume($block: Int, $id: Int) {
|
||||
query get_volume($block: Int, $id: Int) {
|
||||
${hasTotalVolume ? totalVolumeQuery : ""}
|
||||
${hasDailyVolume ? dailyVolumeQuery : ""}
|
||||
}
|
||||
`;
|
||||
return (chain) => {
|
||||
return async (timestamp, chainBlocks) => {
|
||||
}
|
||||
`;
|
||||
return (chain: Chain) => {
|
||||
return async (timestamp: number, chainBlocks: ChainBlocks) => {
|
||||
const block =
|
||||
(getCustomBlock && (await getCustomBlock(timestamp))) ||
|
||||
(await getBlock(timestamp, chain, chainBlocks));
|
||||
getCustomBlock ?
|
||||
await getCustomBlock(timestamp) :
|
||||
await getBlock(timestamp, chain, chainBlocks);
|
||||
const id = getUniswapDateId();
|
||||
const graphRes = await request(graphUrls[chain], graphQuery, {
|
||||
block,
|
||||
@@ -87,7 +107,7 @@ query get_volume($block: Int, $id: Int) {
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getUniqStartOfTodayTimestamp,
|
||||
getChainVolume,
|
||||
DEFAULT_TOTAL_VOLUME_FACTORY,
|
||||
@@ -2,6 +2,7 @@ import { getChainVolume } from "../helper/getUniSubgraphVolume";
|
||||
import { getStartTimestamp } from "../helper/getStartTimestamp";
|
||||
import { FANTOM } from "../helper/chains";
|
||||
import { DexVolumeAdapter } from "../dexVolume.type";
|
||||
import { Chain } from "@defillama/sdk/build/general";
|
||||
|
||||
const endpoints = {
|
||||
// [AVAX]: "https://api.thegraph.com/subgraphs/name/soulswapfinance/avalanche-exchange
|
||||
@@ -35,7 +36,7 @@ const volume = Object.keys(endpoints).reduce(
|
||||
(acc, chain) => ({
|
||||
...acc,
|
||||
[chain]: {
|
||||
fetch: graphs(chain),
|
||||
fetch: graphs(chain as Chain),
|
||||
start: getStartTimestamp({ ...startTimeQuery, chain }),
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
XDAI,
|
||||
} from "../helper/chains";
|
||||
import { DexVolumeAdapter } from "../dexVolume.type";
|
||||
import { Chain } from "@defillama/sdk/build/general";
|
||||
|
||||
const endpoints = {
|
||||
[ARBITRUM]:
|
||||
@@ -67,7 +68,7 @@ const volume = Object.keys(endpoints).reduce(
|
||||
(acc, chain) => ({
|
||||
...acc,
|
||||
[chain]: {
|
||||
fetch: graphs(chain),
|
||||
fetch: graphs(chain as Chain),
|
||||
start: getStartTimestamp({ ...startTimeQuery, chain }),
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import path from "path";
|
||||
import * as path from "path";
|
||||
import axios from "axios";
|
||||
import { ethers } from "ethers";
|
||||
import { providers } from "./utils/ethers"
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"weeklyChanges": "git pull && git diff $(git log -1 --before=@{7.days.ago} --format=%H) --stat | grep -E \"projects/\" | cut -d / -f 2 | cut -d \" \" -f 1 | uniq | wc -l",
|
||||
"dev": "babel-watch curve.js",
|
||||
"test-interactive": "node utils/testInteractive"
|
||||
"test-interactive": "node utils/testInteractive",
|
||||
"test-dex": "ts-node dexVolumes/cli/testAdapter.ts"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
|
||||
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
// This is an alias to @tsconfig/node16: https://github.com/tsconfig/bases
|
||||
"extends": "ts-node/node16/tsconfig.json",
|
||||
// Most ts-node options can be specified here using their programmatic names.
|
||||
"ts-node": {
|
||||
// It is faster to skip typechecking.
|
||||
// Remove if you want ts-node to do typechecking.
|
||||
"transpileOnly": true,
|
||||
"files": true,
|
||||
"compilerOptions": {
|
||||
// compilerOptions specified here will override those declared below,
|
||||
// but *only* in ts-node. Useful if you want ts-node and tsc to use
|
||||
// different options with a single tsconfig.json.
|
||||
}
|
||||
},
|
||||
"compilerOptions": {
|
||||
// typescript options here
|
||||
"typeRoots": ["./typings/", "./node_modules/@types/"]
|
||||
}
|
||||
}
|
||||
8
typings/getBlock.d.ts
vendored
Normal file
8
typings/getBlock.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
type ChainBlocks = {
|
||||
[chain: string]: number
|
||||
} //tmp fix
|
||||
type Chain = string
|
||||
|
||||
declare module '*/getBlock' {
|
||||
function getBlock(timestamp: number, chain: Chain, chainBlocks: ChainBlocks, undefinedOk?: boolean): Promise<number | ChainBlocks['']>
|
||||
}
|
||||
1
typings/handleError.d.ts
vendored
Normal file
1
typings/handleError.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
declare module '*/handleError';
|
||||
1
typings/index.d.ts
vendored
Normal file
1
typings/index.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
declare module '*/helper/chains';
|
||||
Reference in New Issue
Block a user