Skip to content

Commit

Permalink
Merge pull request #58 from DefiLlama/daoMaker
Browse files Browse the repository at this point in the history
Dao maker
  • Loading branch information
waynebruce0x authored Jun 20, 2023
2 parents 190a26d + f0e9607 commit cade472
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/node_modules
**/**/*.js
/utils/result.png
/utils/testCharts
result.txt
2 changes: 1 addition & 1 deletion adapters/balance/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export async function balance(
]);

const allTimestamps: number[] = [];
let currentTimestamp = trackedTimestamp;
let currentTimestamp = Math.max(trackedTimestamp, timestampDeployed);

while (!isFuture(currentTimestamp)) {
allTimestamps.push(currentTimestamp);
Expand Down
118 changes: 118 additions & 0 deletions adapters/daomaker/daomaker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { Protocol } from "../../types/adapters";
import { AdapterResult } from "../../types/adapters";
import { stringToTimestamp } from "../../utils/time";
import { CliffAdapterResult } from "../../types/adapters";
import { periodToSeconds } from "../../utils/time";

type Vesting = {
tokenName: string;
totalCount: number;
};
type VestingMode = {
mode: "linear" | "epoch";
cliff?: number;
dailyRewards?: number;
lastDay?: number;
tgeUnlock?: number;
totalVestedLinear?: number;
};
export type DaoMakerApiRes = {
coingecko_api_id: string;
link: string;
title: string;
vestings: Vesting[];
vestingsMode: VestingMode[];
tge: string;
};

function processEpochsData(
vestings: Vesting,
tge: number,
title: string,
): CliffAdapterResult[] {
let workingQty: number = 0;
const section: CliffAdapterResult[] = [];

Object.entries(vestings).map(([v, q]) => {
const epoch: number = Number(v);
const amount = Number(q);
if (isNaN(epoch) || q == 0) return;

section.push({
type: "cliff",
start: tge + epoch * periodToSeconds.day,
amount,
});

workingQty += amount;
});

section.push({
type: "cliff",
start: section[section.length - 1].start + periodToSeconds.week,
amount: 0,
});

if (workingQty < vestings.totalCount * 0.99)
throw new Error(
`The accumulated unlocks for ${vestings.tokenName} in ${title} does not match the total count.`,
);

return section;
}
function processLinearData(
vestings: Vesting,
tge: number,
title: string,
mode: VestingMode,
): AdapterResult[] {
const section: AdapterResult[] = [];

if (!mode.cliff || !mode.lastDay || !mode.totalVestedLinear)
throw new Error(
`unable to parse ${vestings.tokenName} in ${title} because expected linear props are missing`,
);
if (mode.tgeUnlock)
section.push({ type: "cliff", start: tge, amount: mode.tgeUnlock });

section.push({
type: "linear",
start: tge + periodToSeconds.day * mode.cliff,
end: tge + periodToSeconds.day * mode.lastDay,
amount: mode.totalVestedLinear,
});

return section;
}
export default async function daoMaker(api: DaoMakerApiRes): Promise<Protocol> {
const protocol: Protocol = {
meta: {
token: `coingecko:${api.coingecko_api_id}`,
sources: [api.link],
notes: [`Data used in this analysis has been supplied by DAO Maker`],
protocolIds: [],
},
categories: {}, // need
};

const tge: number = stringToTimestamp(api.tge);
api.vestings.map((v: Vesting, i: number) => {
const mode = api.vestingsMode[i];
let sectionData: AdapterResult[];

switch (mode.mode) {
case "epoch":
sectionData = processEpochsData(v, tge, api.title);
break;
case "linear":
sectionData = processLinearData(v, tge, api.title, mode);
break;
default:
throw new Error(`unknown vesting mode`);
}

protocol[v.tokenName] = sectionData;
});

return protocol;
}
3 changes: 3 additions & 0 deletions adapters/forta/contracts.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
type chainContracts = {
owners: string[];
token: string;
timestamp: number;
};
const contracts: { [chain: string]: chainContracts } = {
ethereum: {
timestamp: 1651356000,
owners: [
"0xcf7b521dc1a0c9c52f5455ec44f64da3555ab9f0",
"0x54716b0e8263e6797cfc3fe075fe347256c9411c",
Expand Down Expand Up @@ -31,6 +33,7 @@ const contracts: { [chain: string]: chainContracts } = {
token: "0x41545f8b9472d758bb669ed8eaeeecd7a9c4ec29",
},
polygon: {
timestamp: 1646524800,
owners: ["0xc99884be6eee5533be08152c40df0464b3fae877"],
token: "0x9ff62d1FC52A907B6DCbA8077c2DDCA6E6a9d3e1",
},
Expand Down
8 changes: 7 additions & 1 deletion adapters/forta/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import contracts from "./contracts";
export const unallocated = () =>
Promise.all(
Object.keys(contracts).map((k: any) =>
balance(contracts[k].owners, contracts[k].token, k, "forta", 1651356000),
balance(
contracts[k].owners,
contracts[k].token,
k,
"forta",
contracts[k].timestamp,
),
),
);
export const latest = () => late("forta", 1651356000);
23 changes: 23 additions & 0 deletions protocols/daomaker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import fetch from "node-fetch";
import singleDao, { DaoMakerApiRes } from "../adapters/daomaker/daomaker";
import { Protocol } from "../types/adapters";

export default async function daoMaker(): Promise<Protocol[]> {
const res: DaoMakerApiRes[] = await fetch(
`https://api.daomaker.com/defillama/company/vestings`,
).then((r) => r.json());

const protocols: Protocol[] = [];

await Promise.all(
res.map((api: DaoMakerApiRes) =>
singleDao(api)
.then((r: Protocol) => protocols.push(r))
.catch((e: Error) =>
console.error(`${api.title} failed with: \n ${e} \n`),
),
),
);

return protocols;
}
4 changes: 2 additions & 2 deletions protocols/equilibre.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ const equilibre: Protocol = {
"https://equilibre-finance.gitbook.io/equilibre/emissions",
"https://equilibre-finance.gitbook.io/equilibre/initial-distribution",
],
token: "vara:0xE1da44C0dA55B075aE8E2e4b6986AdC76Ac77d73",
protocolIds: ["566"],
token: "kava:0xE1da44C0dA55B075aE8E2e4b6986AdC76Ac77d73",
protocolIds: ["2586"],
},
categories: {
farming: ["Community"],
Expand Down
20 changes: 13 additions & 7 deletions utils/categoryData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,12 @@ export function createCategoryData(
(t: number) =>
timestampNow - RESOLUTION_SECONDS < t && t < timestampNow,
);
const current = s.data.unlocked[currentEntryIndex];
const final = s.data.unlocked[s.data.unlocked.length - 1];
const finalEntryIndex = s.data.unlocked.length - 1;
const current =
s.data.unlocked[
currentEntryIndex == -1 ? finalEntryIndex : currentEntryIndex
];
const final = s.data.unlocked[finalEntryIndex];
return { current, final };
}

Expand All @@ -67,12 +71,14 @@ export function createCategoryData(
);
if (!s) return { current: 0, final: 0 };

const current: number = s.data.find(
(t: any) =>
timestampNow - RESOLUTION_SECONDS < t.timestamp &&
t.timestamp < timestampNow,
).unlocked;
const final: number = s.data[s.data.length - 1].unlocked;
const current: number =
s.data.find(
(t: any) =>
timestampNow - RESOLUTION_SECONDS < t.timestamp &&
t.timestamp < timestampNow,
)?.unlocked ?? final;

return { current, final };
}

Expand Down
7 changes: 4 additions & 3 deletions utils/chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,17 @@ function buildOptionsObject(data: ChartSection[]): Object {
export async function getChartPng(
data: ChartSection[],
isCI: boolean,
i: number,
): Promise<void> {
const path: string = resolve(__dirname);
const options: Object = buildOptionsObject(data);
let image: Buffer | string = await draw(options, isCI);
let saveLocation = `${path}/result.png`;
let saveLocation = `${path}/testCharts/result${i}.png`;
if (typeof image == "string") {
image = await sendToImageHost(image);
saveLocation = `result.txt`;
saveLocation = `result${i}.txt`;
}
fs.writeFile(saveLocation, image, function(err) {
fs.writeFile(saveLocation, image, function (err) {
if (err) {
return console.log(err);
}
Expand Down
2 changes: 1 addition & 1 deletion utils/convertToRawData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export async function createRawSections(
let categories: { [category: string]: string[] } = {};

await Promise.all(
Object.entries(adapter.default).map(async (a: any[]) => {
Object.entries(adapter).map(async (a: any[]) => {
if (a[0] == "meta") {
metadata = <Metadata>a[1];
if ("incompleteSections" in a[1]) {
Expand Down
15 changes: 11 additions & 4 deletions utils/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ if (process.argv.length < 3) {
}
let protocol = process.argv[2];

export async function parseData(adapter: Protocol): Promise<void> {
export async function parseData(adapter: Protocol, i: number): Promise<void> {
let rawData = await createRawSections(adapter);
const chartData = await createChartData(protocol, rawData);
const categoryData = createCategoryData(chartData, rawData.categories);
if (process.argv[3] != "true")
postDebugLogs(chartData, categoryData, protocol);
await getChartPng(chartData, process.argv[3] == "true");
await getChartPng(chartData, process.argv[3] == "true", i);
}

function postDebugLogs(
Expand Down Expand Up @@ -55,7 +55,14 @@ function postDebugLogs(
console.log(log);
});
}

async function iterate(adapter: Protocol): Promise<void> {
if (typeof adapter.default === "function")
adapter.default = await adapter.default();
if (!adapter.default.length) adapter.default = [adapter.default];
await Promise.all(
adapter.default.map((a: Protocol, i: number) => parseData(a, i)),
);
}
export async function main() {
if (protocol.includes("/"))
protocol = protocol.substring(
Expand All @@ -68,7 +75,7 @@ export async function main() {
return;
} else {
console.log(`==== Processing ${protocol} chart ==== \n`);
await parseData(protocolWrapper);
await iterate(protocolWrapper);
}
} catch (e) {
console.log(e);
Expand Down

0 comments on commit cade472

Please sign in to comment.