Skip to content

Commit f056c1a

Browse files
authored
Merge branch 'DefiLlama:master' into master
2 parents 1637df8 + 66d16be commit f056c1a

File tree

1,168 files changed

+18499
-12544
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,168 files changed

+18499
-12544
lines changed

adapters/types.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export type FetchOptions = {
4141
getEndBlock: () => Promise<number>,
4242
dateString: string,
4343
preFetchedResults?: any,
44+
moduleUID: string, // randomly generated unique identifier for the module, useful for caching
4445
}
4546

4647
export type FetchGetLogsOptions = {
@@ -78,9 +79,6 @@ export type BaseAdapterChainConfig = {
7879
start?: IStartTimestamp | number | string; // date can be in "YYYY-MM-DD" format
7980
fetch?: Fetch | FetchV2;
8081
runAtCurrTime?: boolean;
81-
meta?: {
82-
methodology?: string | IJSON<string>
83-
}
8482
}
8583

8684
export type BaseAdapter = {
@@ -155,6 +153,12 @@ export type FetchResultFees = FetchResultBase & {
155153
dailyBribesRevenue?: FetchResponseValue;
156154
dailyTokenTaxes?: FetchResponseValue;
157155
totalHoldersRevenue?: FetchResponseValue;
156+
dailyOtherIncome?: FetchResponseValue;
157+
totalOtherIncome?: FetchResponseValue;
158+
dailyOperatingIncome?: FetchResponseValue;
159+
totalOperatingIncome?: FetchResponseValue;
160+
dailyNetIncome?: FetchResponseValue;
161+
totalNetIncome?: FetchResponseValue;
158162
};
159163

160164
// INCENTIVES
@@ -201,11 +205,12 @@ export const whitelistedDimensionKeys = new Set([
201205
'dailyVolume', 'totalVolume', 'shortOpenInterestAtEnd', 'longOpenInterestAtEnd', 'openInterestAtEnd', 'dailyBridgeVolume', 'totalBridgeVolume',
202206
'totalFees', 'dailyFees', 'dailyUserFees', 'totalRevenue', 'dailyRevenue', 'dailyProtocolRevenue', 'dailyHoldersRevenue', 'dailySupplySideRevenue', 'totalProtocolRevenue', 'totalSupplySideRevenue', 'totalUserFees', 'dailyBribesRevenue', 'dailyTokenTaxes', 'totalHoldersRevenue',
203207
'tokenIncentives',
208+
'dailyOtherIncome', 'totalOtherIncome', 'dailyOperatingIncome', 'totalOperatingIncome', 'dailyNetIncome', 'totalNetIncome',
204209
'totalPremiumVolume', 'totalNotionalVolume', 'dailyPremiumVolume', 'dailyNotionalVolume',
205210
])
206211
export const accumulativeKeySet = new Set([
207212
'totalVolume', 'totalBridgeVolume', 'tokenIncentives', 'totalPremiumVolume', 'totalNotionalVolume',
208-
'totalFees', 'totalRevenue', 'totalProtocolRevenue', 'totalSupplySideRevenue', 'totalUserFees', 'totalHoldersRevenue',
213+
'totalFees', 'totalRevenue', 'totalProtocolRevenue', 'totalSupplySideRevenue', 'totalUserFees', 'totalHoldersRevenue', 'totalOtherIncome', 'totalOperatingIncome', 'totalNetIncome'
209214
])
210215

211216
// End of specific adaptors type

adapters/utils/runAdapter.ts

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as _env from '../../helpers/env';
44
import { getBlock } from "../../helpers/getBlock";
55
import { getUniqStartOfTodayTimestamp } from '../../helpers/getUniSubgraphFees';
66
import { getDateString } from '../../helpers/utils';
7-
import { accumulativeKeySet, BaseAdapter, BaseAdapterChainConfig, ChainBlocks, Fetch, FetchGetLogsOptions, FetchOptions, FetchV2, SimpleAdapter, } from '../types';
7+
import { accumulativeKeySet, BaseAdapter, BaseAdapterChainConfig, ChainBlocks, Fetch, FetchGetLogsOptions, FetchOptions, FetchResponseValue, FetchResultV2, FetchV2, SimpleAdapter, } from '../types';
88

99
// to trigger inclusion of the env.ts file
1010
const _include_env = _env.getEnv('BITLAYER_RPC')
@@ -111,6 +111,7 @@ async function _runAdapter({
111111
}: AdapterRunOptions) {
112112
const cleanCurrentDayTimestamp = endTimestamp
113113
const adapterVersion = module.version
114+
const moduleUID = module._randomUID
114115

115116
const chainBlocks: ChainBlocks = {} // we need it as it is used in the v1 adapters
116117
const { prefetch, allowNegativeValue = false, } = module
@@ -124,6 +125,15 @@ async function _runAdapter({
124125
if (chains.some(c => !c) || chains.includes('undefined')) {
125126
throw new Error(`Invalid chain labels: ${chains.filter(c => !c || c === 'undefined').join(', ')}`)
126127
}
128+
129+
const badChainNames = chains.filter(chain => !/^[a-z0-9_]+$/.test(chain));
130+
if (badChainNames.length) {
131+
throw new Error(`
132+
Invalid chain names: ${badChainNames.join(', ')}
133+
Chain names should only contain lowercase letters, numbers and underscores
134+
`)
135+
}
136+
127137
const validStart = {} as {
128138
[chain: string]: {
129139
canRun: boolean,
@@ -137,7 +147,7 @@ async function _runAdapter({
137147
if (typeof prefetch === 'function') {
138148
const firstChain = chains.find(chain => validStart[chain]?.canRun);
139149
if (firstChain) {
140-
const options = await getOptionsObject(cleanCurrentDayTimestamp, firstChain, chainBlocks);
150+
const options = await getOptionsObject({ timestamp: cleanCurrentDayTimestamp, chain: firstChain, chainBlocks, moduleUID });
141151
preFetchedResults = await prefetch(options);
142152
}
143153
}
@@ -185,7 +195,7 @@ async function _runAdapter({
185195

186196
const fetchFunction = adapterObject![chain].fetch
187197
try {
188-
const options = await getOptionsObject(cleanCurrentDayTimestamp, chain, chainBlocks)
198+
const options = await getOptionsObject({ timestamp: cleanCurrentDayTimestamp, chain, chainBlocks, moduleUID })
189199
if (preFetchedResults !== null) {
190200
options.preFetchedResults = preFetchedResults;
191201
}
@@ -202,6 +212,12 @@ async function _runAdapter({
202212
const ignoreKeys = ['timestamp', 'block']
203213
const improbableValue = 2e11 // 200 billion
204214

215+
// validate and inject missing record if any
216+
validateAdapterResult(result)
217+
218+
// add missing metrics if need
219+
addMissingMetrics(chain, result)
220+
205221
for (const [recordType, value] of Object.entries(result)) {
206222
if (ignoreKeys.includes(recordType)) continue;
207223
if (value === undefined || value === null) { // dont store undefined or null values
@@ -269,7 +285,7 @@ async function _runAdapter({
269285
}
270286
}
271287

272-
async function getOptionsObject(timestamp: number, chain: string, chainBlocks: ChainBlocks): Promise<FetchOptions> {
288+
async function getOptionsObject({ timestamp, chain, chainBlocks, moduleUID = genUID(10) }: { timestamp: number, chain: string, chainBlocks: ChainBlocks, moduleUID?: string }): Promise<FetchOptions> {
273289
const withinTwoHours = Math.trunc(Date.now() / 1000) - timestamp < 24 * 60 * 60 // 24 hours
274290
const createBalances: () => Balances = () => {
275291
let _chain = chain
@@ -326,6 +342,7 @@ async function _runAdapter({
326342
getStartBlock,
327343
getEndBlock,
328344
dateString: getDateString(startOfDay),
345+
moduleUID,
329346
}
330347
}
331348

@@ -370,3 +387,54 @@ async function _runAdapter({
370387
}
371388

372389
}
390+
391+
function createBalanceFrom(options: { chain: string, timestamp: number | undefined, amount: FetchResponseValue }): Balances {
392+
const { chain, timestamp, amount } = options
393+
394+
const balance = new Balances({ chain, timestamp })
395+
if (amount) {
396+
if (typeof amount === 'number' || typeof amount === 'string') {
397+
balance.addUSDValue(amount)
398+
} else {
399+
balance.addBalances(amount)
400+
}
401+
}
402+
return balance;
403+
}
404+
405+
function subtractBalance(options: { balance: Balances, amount: FetchResponseValue }) {
406+
const { balance, amount } = options
407+
if (amount) {
408+
if (typeof amount === 'number' || typeof amount === 'string') {
409+
const otherBalance = createBalanceFrom({ chain: balance.chain, timestamp: balance.timestamp, amount })
410+
balance.subtract(otherBalance)
411+
} else {
412+
balance.subtract(amount)
413+
}
414+
}
415+
}
416+
417+
function validateAdapterResult(result: any) {
418+
// validate metrics
419+
// this is to ensure that we do this validation only for the new adapters
420+
if (result.dailyFees && result.dailyFees instanceof Balances && result.dailyFees.hasBreakdownBalances()) {
421+
// should include atleast SupplySideRevenue or ProtocolRevenue or Revenue
422+
if (!result.dailySupplySideRevenue && !result.dailyProtocolRevenue && !result.dailyRevenue) {
423+
throw Error('found dailyFees record but missing all dailyRevenue, dailySupplySideRevenue, dailyProtocolRevenue records')
424+
}
425+
}
426+
}
427+
428+
function addMissingMetrics(chain: string, result: any) {
429+
// add missing metrics for Balances which has breakdown labels only
430+
// this is to ensure that we dont change behavior of existing adapters
431+
if (result.dailyFees && result.dailyFees instanceof Balances && result.dailyFees.hasBreakdownBalances()) {
432+
433+
// if we have supplySideRevenue but missing revenue, add revenue = fees - supplySideRevenue
434+
if (result.dailySupplySideRevenue && !result.dailyrevenue) {
435+
result.dailyRevenue = createBalanceFrom({ chain, timestamp: result.timestamp, amount: result.dailyFees })
436+
subtractBalance({ balance: result.dailyRevenue, amount: result.dailySupplySideRevenue })
437+
}
438+
439+
}
440+
}

aggregator-derivatives/defiapp/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { FetchResult, SimpleAdapter } from "../../adapters/types";
44
import { httpGet } from "../../utils/fetchURL";
55
import { CHAIN } from "../../helpers/chains";
6+
import { getEnv } from "../../helpers/env";
67

78
const tsToISO = (ts: number) => new Date(ts * 1e3).toISOString();
89

@@ -14,7 +15,7 @@ const fetch = async (_: any, _b: any, options: any): Promise<FetchResult> => {
1415
const response = await httpGet(`https://api.defi.app/api/stats/volume-perps/between?startTime=${tsToISO(startDate)}&endTime=${tsToISO(endDate)}`, {
1516
headers: {
1617
"Content-Type": "application/json",
17-
"X-API-KEY": process.env.DEFIAPP_API_KEY,
18+
"X-API-KEY": getEnv('DEFIAPP_API_KEY'),
1819
User: "defillama",
1920
},
2021
});
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { SimpleAdapter, FetchV2, FetchResultV2 } from "../../adapters/types";
2+
import { CHAIN } from "../../helpers/chains";
3+
import {
4+
calculateAdjustsVolume, calculateClosesVolume,
5+
calculateOpensVolume, CONFIG,
6+
fetchVolume,
7+
leverageAdjustsQuery,
8+
leverageClosesQuery,
9+
leverageOpensQuery
10+
} from "../flat-money/helper";
11+
12+
13+
14+
15+
const fetch: FetchV2 = async ({ startTimestamp, endTimestamp, chain }): Promise<FetchResultV2> => {
16+
const config = CONFIG[chain];
17+
if (!config) throw new Error(`Unsupported chain: ${chain}`);
18+
19+
const { decimals, } = config;
20+
21+
const [
22+
dailyOpensData,
23+
dailyAdjustsData,
24+
dailyClosesData,
25+
] = await Promise.all([
26+
fetchVolume(chain as CHAIN, leverageOpensQuery, "leverageOpens", startTimestamp, endTimestamp),
27+
fetchVolume(chain as CHAIN, leverageAdjustsQuery, "leverageAdjusts", startTimestamp, endTimestamp),
28+
fetchVolume(chain as CHAIN, leverageClosesQuery, "leverageCloses", startTimestamp, endTimestamp),
29+
]);
30+
31+
return {
32+
dailyVolume: calculateOpensVolume(dailyOpensData, decimals.amount)
33+
+ calculateAdjustsVolume(dailyAdjustsData, decimals.amount)
34+
+ calculateClosesVolume(dailyClosesData, decimals.amount),
35+
};
36+
};
37+
38+
39+
40+
const adapter: SimpleAdapter = {
41+
adapter: Object.fromEntries(
42+
Object.entries(CONFIG).filter(([chain, config]) => chain === CHAIN.BASE).map(([chain, config]) => [
43+
chain,
44+
{ fetch, start: config.startTimestamp }
45+
])
46+
),
47+
version: 2
48+
};
49+
50+
51+
export default adapter;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { SimpleAdapter, FetchV2, FetchResultV2 } from "../../adapters/types";
2+
import { CHAIN } from "../../helpers/chains";
3+
import {
4+
calculateAdjustsVolume, calculateClosesVolume,
5+
calculateOpensVolume, CONFIG,
6+
fetchVolume,
7+
leverageAdjustsQuery,
8+
leverageClosesQuery,
9+
leverageOpensQuery
10+
} from "../flat-money/helper";
11+
12+
const fetch: FetchV2 = async ({ startTimestamp, endTimestamp, chain }): Promise<FetchResultV2> => {
13+
const config = CONFIG[chain];
14+
if (!config) throw new Error(`Unsupported chain: ${chain}`);
15+
16+
const { decimals, } = config;
17+
18+
const [
19+
dailyOpensData,
20+
dailyAdjustsData,
21+
dailyClosesData,
22+
] = await Promise.all([
23+
fetchVolume(chain as CHAIN, leverageOpensQuery, "leverageOpens", startTimestamp, endTimestamp),
24+
fetchVolume(chain as CHAIN, leverageAdjustsQuery, "leverageAdjusts", startTimestamp, endTimestamp),
25+
fetchVolume(chain as CHAIN, leverageClosesQuery, "leverageCloses", startTimestamp, endTimestamp),
26+
]);
27+
28+
return {
29+
dailyVolume: calculateOpensVolume(dailyOpensData, decimals.amount)
30+
+ calculateAdjustsVolume(dailyAdjustsData, decimals.amount)
31+
+ calculateClosesVolume(dailyClosesData, decimals.amount),
32+
};
33+
};
34+
35+
36+
37+
const adapter: SimpleAdapter = {
38+
adapter: Object.fromEntries(
39+
Object.entries(CONFIG).filter(([chain, config]) => chain === CHAIN.OPTIMISM || chain === CHAIN.ARBITRUM).map(([chain, config]) => [
40+
chain,
41+
{ fetch, start: config.startTimestamp }
42+
])
43+
),
44+
version: 2
45+
};
46+
47+
48+
export default adapter;

0 commit comments

Comments
 (0)