Skip to content

Commit

Permalink
feat: Tally data provider addition (#2176)
Browse files Browse the repository at this point in the history
  • Loading branch information
3scava1i3r authored Sep 15, 2023
1 parent 66cdfdd commit 8aed57f
Show file tree
Hide file tree
Showing 8 changed files with 315 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .example.env
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export JSON_RPC_URL=""
export DUNE_API_KEY=""
export ALCHEMY_API_KEY=""
export GITCOIN_API_KEY=""
export ANKR_API_KEY=""
export ANKR_API_KEY=""
export TALLY_API_KEY=""
2 changes: 2 additions & 0 deletions group-generators/generators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ import t0xci from "./t0xci";
import talentOfTheMonthSolidityMarch2023 from "./talent-of-the-month-solidity-march-2023";
import talentlayer from "./talentlayer";
import talentofthemonthDesignMarch from "./talentofthemonth-design-march";
import tally from './tally';
import tallyHoGithubStargazers from "./tally-ho-github-stargazers";
import tarozzy from "./tarozzy";
import tayaFans from "./taya-fans";
Expand Down Expand Up @@ -1564,6 +1565,7 @@ export const groupGenerators: GroupGeneratorsLibrary = {
"talent-of-the-month-solidity-march-2023": talentOfTheMonthSolidityMarch2023,
"talentlayer": talentlayer,
"talentofthemonth-design-march": talentofthemonthDesignMarch,
"tally": tally,
"tally-ho-github-stargazers": tallyHoGithubStargazers,
"tarozzy": tarozzy,
"taya-fans": tayaFans,
Expand Down
33 changes: 33 additions & 0 deletions group-generators/generators/tally/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { dataProviders } from "@group-generators/helpers/data-providers";
import { GroupWithData, Tags, ValueType } from "topics/group";
import { GenerationContext, GenerationFrequency, GroupGenerator } from "topics/group-generator";

// Generated from factory.sismo.io

const generator: GroupGenerator = {
generationFrequency: GenerationFrequency.Daily,

generate: async (context: GenerationContext): Promise<GroupWithData[]> => {
const TallyProvider = new dataProviders.TallyProvider();

const input = {
name: "Aave",
// proposalId: 315,
};
const tallyGetGovernanceProposers = await TallyProvider.getGovernanceProposers(input);

return [
{
name: "example-tally",
timestamp: context.timestamp,
description: "Tally governance",
specs: "",
data: tallyGetGovernanceProposers,
valueType: ValueType.Score,
tags: [Tags.Vote],
},
];
},
};

export default generator;
11 changes: 10 additions & 1 deletion group-generators/helpers/data-providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ import snapshotInterfaceSchema from "./snapshot/interface-schema.json";
import { SubgraphHostedServiceProvider, SubgraphDecentralizedServiceProvider } from "./subgraph";
import { TalentLayerProvider } from "./talentlayer";
import talentLayerProviderInterfaceSchema from "./talentlayer/interface-schema.json";
import { TallyProvider } from "./tally";
import tallyProviderInterfaceSchema from "./tally/interface-schema.json";
import { TokenProvider } from "./token-provider";
import tokenProviderInterfaceSchema from "./token-provider/interface-schema.json";
import { TransposeProvider } from "./transpose";
Expand All @@ -59,7 +61,6 @@ import {
DataProviders,
supportedArgTypesInterfaces,
} from "topics/data-provider";

export const dataProviders = {
AlchemyProvider,
AttestationStationProvider,
Expand Down Expand Up @@ -95,6 +96,7 @@ export const dataProviders = {
SubgraphDecentralizedServiceProvider,
SnapshotProvider,
TalentLayerProvider,
TallyProvider,
TokenProvider,
TransposeProvider,
UnlockSubgraphProvider,
Expand All @@ -119,6 +121,7 @@ export const dataProvidersInterfacesSchemas: DataProviderInterface[] = [
snapshotInterfaceSchema,
subgraph101InterfaceSchema,
talentLayerProviderInterfaceSchema,
tallyProviderInterfaceSchema,
tokenProviderInterfaceSchema,
unlockProviderInterfaceSchema,
wiwBadgeInterfaceSchema,
Expand Down Expand Up @@ -242,6 +245,12 @@ export const dataProvidersAPIEndpoints = {
getTalentOfTheMonthCount: async (_: any) =>
new TalentLayerProvider().getTalentOfTheMonthCount(_),
},
TallyProvider: {
getGovernanceProposersCount: async (_: any) =>
new TallyProvider().getGovernanceProposersCount(_),
getGovernanceVotersCount: async (_: any) => new TallyProvider().getGovernanceVotersCount(_),
getProposalVotersCount: async (_: any) => new TallyProvider().getProposalVotersCount(_),
},
TokenProvider: {
getERC20HoldersCount: async (_: any) => new TokenProvider().getERC20HoldersCount(_),
getERC721HoldersCount: async (_: any) => new TokenProvider().getERC721HoldersCount(_),
Expand Down
5 changes: 5 additions & 0 deletions group-generators/helpers/data-providers/tally/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import TallyProvider from "./provider";

import { ITallyProvider } from "./types";

export { TallyProvider, ITallyProvider };
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"name": "Tally",
"iconUrl": "",
"providerClassName": "TallyProvider",
"functions": [
{
"name": "Get voters of proposal",
"functionName": "getProposalVoters",
"countFunctionName": "getProposalVotersCount",
"description": "Returns all voters of a specific proposal on Tally.",
"args": [
{
"name": "DAO",
"argName": "governance",
"type": "string",
"example": "aave",
"description": "A specific DAO"
},
{
"name": "proposal ID",
"argName": "proposalId",
"type": "number",
"example": "193",
"description": "A specific proposal identifier"
}
]
},
{
"name": "Get voters of a DAO",
"functionName": "getGovernanceVoters",
"countFunctionName": "getGovernanceVotersCount",
"description": "Returns all voters of a specific governance on Tally. The values of the accounts correspond to their number of votes.",
"args": [
{
"name": "DAO",
"argName": "governance",
"type": "string",
"example": "aave",
"description": "A specific DAO"
}
]
},
{
"name": "Get proposers of a DAO",
"functionName": "getGovernanceProposers",
"countFunctionName": "getGovernanceProposersCount",
"description": "Returns all proposals proposers of a specific DAO on Tally. The values of the accounts correspond to their number of proposal proposed.",
"args": [
{
"name": "DAO",
"argName": "governance",
"type": "string",
"example": "aave",
"description": "A specific DAO"
}
]
}
]
}
172 changes: 172 additions & 0 deletions group-generators/helpers/data-providers/tally/provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import { gql } from "graphql-request";

import {
ITallyProvider,
inputGetGovernanceProposers,
inputGetProposalVoters,
queryData,
} from "./types";
import { GraphQLProvider } from "@group-generators/helpers/data-providers/graphql";
import { FetchedData } from "topics/group";

export default class TallyProvider extends GraphQLProvider implements ITallyProvider {
public constructor() {
super({
url: "https://api.tally.xyz/query",
headers: {
"Api-Key": process.env.TALLY_API_KEY as string,
accept: "application/json",
},
});
}

private async _queryNameToGovernorAddress(): Promise<queryData> {
return this.query(
gql`
query Governors {
governors(chainIds: "eip155:1") {
id
type
name
proposals {
id
title
description
proposer {
address
}
votes {
id
voter {
id
address
}
}
}
}
}
`,
{}
);
}

public async getProposalVoters({
name,
proposalId,
}: inputGetProposalVoters): Promise<FetchedData> {
const data = await this._queryNameToGovernorAddress();

const fetchedData: { [address: string]: number } = {};

if (data && Array.isArray(data.governors)) {
const matchingGovernors = data.governors.filter(
(governor: { name: string }) => governor.name === name
);

for (const governor of matchingGovernors) {
for (const proposals of governor.proposals) {
const propId = proposals.id;

if (parseInt(propId) === proposalId) {
const allVotes = proposals.votes;

allVotes.forEach((voteItem: { id: string; voter: any }) => {
const { voter } = voteItem;
const { address } = voter;
if (fetchedData[address]) {
fetchedData[address]++;
} else {
fetchedData[address] = 1;
}
});
}
}
}

return fetchedData;
}

return fetchedData;
}

public async getProposalVotersCount({
name,
proposalId,
}: inputGetProposalVoters): Promise<number> {
const ProposalVoterData = await this.getProposalVoters({ name, proposalId });

const ProposalVoterCount = Object.keys(ProposalVoterData).length;
return ProposalVoterCount;
}

public async getGovernanceVoters({ name }: inputGetGovernanceProposers): Promise<FetchedData> {
const data: queryData = await this._queryNameToGovernorAddress();
const fetchedData: { [address: string]: number } = {};

if (data && Array.isArray(data.governors)) {
const matchingGovernors = data.governors.filter(
(governor: { name: string }) => governor.name === name
);

for (const governor of matchingGovernors) {
for (const proposals of governor.proposals) {
const votesArray = proposals?.votes;

votesArray.forEach((item: { id: string; voter: any }) => {
const { voter } = item;
const { address } = voter;
if (fetchedData[address]) {
fetchedData[address]++;
} else {
fetchedData[address] = 1;
}
});
}
}

return fetchedData;
}

return fetchedData;
}

public async getGovernanceVotersCount({ name }: inputGetGovernanceProposers): Promise<number> {
const VoterData = await this.getGovernanceVoters({ name });

const VoterCount = Object.keys(VoterData).length;
return VoterCount;
}

public async getGovernanceProposers({ name }: inputGetGovernanceProposers): Promise<FetchedData> {
const data: queryData = await this._queryNameToGovernorAddress();
const fetchedData: { [address: string]: number } = {};

if (data && Array.isArray(data.governors)) {
const matchingGovernors = data.governors.filter(
(governor: { name: string }) => governor.name === name
);

for (const governor of matchingGovernors) {
for (const proposal of governor.proposals) {
const proposerAddress = proposal.proposer.address;

if (fetchedData[proposerAddress]) {
fetchedData[proposerAddress]++;
} else {
fetchedData[proposerAddress] = 1;
}
}
}

return fetchedData;
}
return fetchedData;
}

public async getGovernanceProposersCount({ name }: inputGetGovernanceProposers): Promise<number> {
const proposersData = await this.getGovernanceProposers({ name });

const proposerCount = Object.keys(proposersData).length;
return proposerCount;
}
}
32 changes: 32 additions & 0 deletions group-generators/helpers/data-providers/tally/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { IGraphQLProvider } from "@group-generators/helpers/data-providers/graphql/types";

export type ITallyProvider = IGraphQLProvider;

export interface inputGetGovernanceProposers {
name: string;
}

export interface inputGetProposalVoters {
name: string;
proposalId: number;
}

export interface Delegate {
id: string;
account: { address: string };
stats: {
voteCount: number;
};
}

export interface govArray {
id: string;
type: string;
name: string;
proposals: any[];
delegates: Delegate[];
}

export interface queryData {
governors?: govArray[];
}

0 comments on commit 8aed57f

Please sign in to comment.