Skip to content

Commit e144ac2

Browse files
committed
v2 adapter, add isTBD and isIncentives
1 parent 36b1f6f commit e144ac2

18 files changed

+2334
-477
lines changed

protocols/spark.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const spark: Protocol = {
5151
"https://docs.spark.fi/governance/spk-token",
5252
],
5353
notes: ["Sky Farming rewards are only counted when users have claimed them."],
54-
token: "coingecko:spark",
54+
token: "coingecko:spark-2",
5555
protocolIds: ["parent#spark"],
5656
},
5757
categories: {

types/adapters.ts

Lines changed: 125 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,17 @@ export type LinearAdapterResult = {
6161
};
6262
export type ChartData = {
6363
timestamps: number[];
64-
unlocked: number[]; // Net value after burns
65-
rawEmission: number[]; // Original emission without burns
66-
burned: number[]; // Burn amounts
64+
unlocked: number[];
65+
rawEmission: number[];
66+
burned: number[];
6767
isContinuous: boolean;
6868
apiData?: ApiChartData[];
6969
};
7070
export type ApiChartData = {
7171
timestamp: number;
72-
unlocked: number; // Net value after burns
73-
rawEmission: number; // Original emission without burns
74-
burned: number; // Burn amount
72+
unlocked: number;
73+
rawEmission: number;
74+
burned: number;
7575
label?: string;
7676
};
7777
export type TransposedApiChartData = {
@@ -84,12 +84,20 @@ export type ChartYAxisData = {
8484
data: number[];
8585
end: number;
8686
};
87-
export type Protocol = {
87+
export type ProtocolV1 = {
8888
[section: string]: any;
8989
documented?: Documented;
9090
meta: Metadata;
9191
categories: { [key in SectionType]?: string[] | undefined };
9292
};
93+
94+
export interface ProtocolV2 extends Record<string, any> {
95+
meta: MetadataV2;
96+
categories: Categories;
97+
documented?: Documented;
98+
}
99+
100+
export type Protocol = ProtocolV1 | ProtocolV2;
93101
export type Documented = {
94102
replaces: string[];
95103
[section: string]: any;
@@ -175,10 +183,10 @@ export type AllocationDetail = {
175183
recipient: string;
176184
category: string;
177185
unlockType: "cliff" | "linear_start" | "linear_rate_change";
178-
amount?: number;
186+
amount?: number;
179187
previousRatePerWeek?: number;
180188
newRatePerWeek?: number;
181-
}
189+
};
182190

183191
export type UnlockEvent = {
184192
timestamp: number;
@@ -188,8 +196,8 @@ export type UnlockEvent = {
188196
totalTokensCliff?: number;
189197
netChangeInWeeklyRate?: number;
190198
totalNewWeeklyRate?: number;
191-
}
192-
}
199+
};
200+
};
193201

194202
export type TimeSeriesChainData = {
195203
[block: string]: {
@@ -199,4 +207,109 @@ export type TimeSeriesChainData = {
199207
};
200208
export type Allocations = { [category: string]: number };
201209

202-
export type EmissionBreakdown = Record<string, { emission24h: number; emission7d: number; emission30d: number }>;
210+
export type EmissionBreakdown = Record<
211+
string,
212+
{ emission24h: number; emission7d: number; emission30d: number }
213+
>;
214+
215+
export interface MetadataV2 extends Metadata {
216+
version: 2;
217+
}
218+
219+
export interface SectionV2 {
220+
displayName?: string;
221+
methodology?: string;
222+
isIncentive?: boolean;
223+
isTBD?: boolean;
224+
protocols?: string[];
225+
components: ComponentV2[];
226+
}
227+
228+
export interface ComponentV2 {
229+
id: string;
230+
name: string;
231+
methodology?: string;
232+
isIncentive?: boolean;
233+
isTBD?: boolean;
234+
protocols?: string[];
235+
fetch: (backfill?: boolean) => Promise<AdapterResult[]>;
236+
metadata?: ComponentMetadata;
237+
}
238+
239+
export interface ComponentMetadata {
240+
contract?: string;
241+
eventSignature?: string;
242+
[key: string]: any;
243+
}
244+
245+
export type SectionV1Function = (
246+
backfill?: boolean,
247+
) => Promise<AdapterResult[]> | AdapterResult[];
248+
export type SectionV1Array = (SectionV1Function | AdapterResult)[];
249+
250+
export interface ComponentResult {
251+
component: ComponentV2;
252+
results: AdapterResult[];
253+
flags: {
254+
isIncentive: boolean;
255+
isTBD: boolean;
256+
protocols?: string[];
257+
};
258+
}
259+
260+
export interface ProcessedSectionV2 {
261+
sectionName: string;
262+
section: SectionV2;
263+
components: ComponentResult[];
264+
aggregatedResults: AdapterResult[];
265+
hasIncentives: boolean;
266+
hasTBD: boolean;
267+
}
268+
269+
export interface ProcessedProtocolV2 {
270+
protocol: ProtocolV2;
271+
sections: ProcessedSectionV2[];
272+
supplyMetrics: AdjustedSupplyMetrics;
273+
}
274+
275+
export interface AdjustedSupplyMetrics {
276+
maxSupply: number;
277+
adjustedSupply: number;
278+
tbdAmount: number;
279+
incentiveAmount: number;
280+
nonIncentiveAmount: number;
281+
}
282+
283+
export interface ChartDataV2 extends ChartData {
284+
components?: ComponentChartData[];
285+
supplyMetrics?: AdjustedSupplyMetrics;
286+
}
287+
288+
export interface ComponentChartData {
289+
section: string;
290+
component: string;
291+
name: string;
292+
data: ChartData;
293+
flags: {
294+
isIncentive: boolean;
295+
isTBD: boolean;
296+
protocols?: string[];
297+
};
298+
metadata?: {
299+
methodology?: string;
300+
[key: string]: any;
301+
};
302+
}
303+
304+
export function isProtocolV2(protocol: Protocol): protocol is ProtocolV2 {
305+
return (protocol as any).meta?.version === 2;
306+
}
307+
308+
export function isSectionV2(section: any): section is SectionV2 {
309+
return (
310+
section &&
311+
typeof section === "object" &&
312+
"components" in section &&
313+
Array.isArray(section.components)
314+
);
315+
}

utils/block.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ export async function getBlock2(
2828
timestamp: number,
2929
): Promise<number> {
3030
if (["polygon_zkevm", "vision", "era"].includes(chain))
31-
return lookupBlock(timestamp, { chain }).then(blockData => blockData.block);
32-
const res = await (await fetch(
33-
`https://coins.llama.fi/block/${chain}/${timestamp}`,
34-
)).json();
31+
return lookupBlock(timestamp, { chain }).then(
32+
(blockData) => blockData.block,
33+
);
34+
const res = await (
35+
await fetch(`https://coins.llama.fi/block/${chain}/${timestamp}`)
36+
).json();
3537
return res.height;
3638
}

utils/categoryData.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ export function createCategoryData(
6969
rawCurrentAllocations[c] += current;
7070
rawFinalAllocations[c] += final;
7171
});
72-
progressAllocations[c] = calculateProgress(rawCurrentAllocations[c], rawFinalAllocations[c]);
72+
progressAllocations[c] = calculateProgress(
73+
rawCurrentAllocations[c],
74+
rawFinalAllocations[c],
75+
);
7376
});
7477

7578
return {
@@ -79,9 +82,11 @@ export function createCategoryData(
7982
};
8083
}
8184

82-
export function createSectionData(
83-
data: ChartSection[]
84-
): { current: Allocations; final: Allocations, progress: Allocations } {
85+
export function createSectionData(data: ChartSection[]): {
86+
current: Allocations;
87+
final: Allocations;
88+
progress: Allocations;
89+
} {
8590
if (!data.length) return { current: {}, final: {}, progress: {} };
8691
const rawCurrentAllocations: Allocations = {};
8792
const rawFinalAllocations: Allocations = {};
@@ -92,7 +97,7 @@ export function createSectionData(
9297
const s = section;
9398
if (!s) return;
9499
const currentEntryIndex = s.data.timestamps.findIndex(
95-
(t: number) => timestampNow - RESOLUTION_SECONDS < t && t < timestampNow
100+
(t: number) => timestampNow - RESOLUTION_SECONDS < t && t < timestampNow,
96101
);
97102
const finalEntryIndex = s.data.unlocked.length - 1;
98103
const current =

utils/chainCalls.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function filterRawAmounts(
3535

3636
const data = Object.values(chainData);
3737
for (let i = 0; i < data.length; i++) {
38-
if (!('result' in data[i])) data[i].result = i > 0 ? data[i - 1].result : 0
38+
if (!("result" in data[i])) data[i].result = i > 0 ? data[i - 1].result : 0;
3939
const thisBalance = data[i].result;
4040
if (depositIndex == 0 && thisBalance == 0) continue;
4141

utils/clickhouse.ts

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
import { ClickHouseClient, createClient, Row } from '@clickhouse/client';
2-
import { getEnv } from './env';
1+
import { ClickHouseClient, createClient, Row } from "@clickhouse/client";
2+
import { getEnv } from "./env";
33

44
let client: ClickHouseClient | null = null;
55
let connectionPromise: Promise<ClickHouseClient> | null = null;
66

7-
const requiredVars = ['CLICKHOUSE_HOST', 'CLICKHOUSE_USERNAME', 'CLICKHOUSE_PASSWORD'];
7+
const requiredVars = [
8+
"CLICKHOUSE_HOST",
9+
"CLICKHOUSE_USERNAME",
10+
"CLICKHOUSE_PASSWORD",
11+
];
812

913
export async function connectClickhouse() {
1014
if (client) {
@@ -16,37 +20,42 @@ export async function connectClickhouse() {
1620
}
1721

1822
connectionPromise = (async () => {
19-
const missingVars = requiredVars.filter(varName => !getEnv(varName));
23+
const missingVars = requiredVars.filter((varName) => !getEnv(varName));
2024
if (missingVars.length) {
21-
throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`);
25+
throw new Error(
26+
`Missing required environment variables: ${missingVars.join(", ")}`,
27+
);
2228
}
2329

24-
const url = `http://${getEnv('CLICKHOUSE_HOST')}:${getEnv('CLICKHOUSE_PORT')}`;
30+
const url = `http://${getEnv("CLICKHOUSE_HOST")}:${getEnv("CLICKHOUSE_PORT")}`;
2531
client = createClient({
2632
url,
27-
username: getEnv('CLICKHOUSE_USERNAME'),
28-
password: getEnv('CLICKHOUSE_PASSWORD'),
33+
username: getEnv("CLICKHOUSE_USERNAME"),
34+
password: getEnv("CLICKHOUSE_PASSWORD"),
2935
keep_alive: { enabled: true, idle_socket_ttl: 300000 },
3036
compression: { response: true, request: false },
31-
max_open_connections: 10
37+
max_open_connections: 10,
3238
});
3339
return client;
3440
})();
3541

3642
return connectionPromise;
3743
}
3844

39-
export async function queryClickhouse<T extends Row>(sql: string, params?: Record<string, any>): Promise<T[]> {
45+
export async function queryClickhouse<T extends Row>(
46+
sql: string,
47+
params?: Record<string, any>,
48+
): Promise<T[]> {
4049
const client = await connectClickhouse();
4150
try {
42-
const resultSet = await client.query({
43-
query: sql,
51+
const resultSet = await client.query({
52+
query: sql,
4453
query_params: params,
45-
format: 'JSONEachRow'
54+
format: "JSONEachRow",
4655
});
4756
return await resultSet.json<T>();
4857
} catch (error: any) {
49-
if (error?.code === 'ECONNRESET' || error?.code === 'ECONNREFUSED') {
58+
if (error?.code === "ECONNRESET" || error?.code === "ECONNREFUSED") {
5059
await disconnectClickhouse();
5160
}
5261
throw error;
@@ -59,4 +68,4 @@ export async function disconnectClickhouse() {
5968
client = null;
6069
connectionPromise = null;
6170
}
62-
}
71+
}

0 commit comments

Comments
 (0)