Skip to content

Commit

Permalink
trust no one fetch validators from the rpc as the graphql api is diei…
Browse files Browse the repository at this point in the history
…ng (#266)
  • Loading branch information
aaronmgdr authored Sep 26, 2024
1 parent ddffc40 commit b3ec63f
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 26 deletions.
8 changes: 4 additions & 4 deletions src/config/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ export const TESTNET_API_URL =
export const MAINNET_API_URL =
'https://us-central1-staked-celo-bot.cloudfunctions.net/mainnet-functions';

export const EXPLORER_GRAPH_MAINNET_URL = 'https://explorer.celo.org/mainnet/graphiql';
export const EXPLORER_GRAPH_ALFAJORES_URL = 'https://explorer.celo.org/alfajores/graphiql';
export const EXPLORER_MAINNET_URL = 'https://explorer.celo.org/mainnet';
export const EXPLORER_ALFAJORES_URL = 'https://explorer.celo.org/alfajores';
export const EXPLORER_GRAPH_MAINNET_URL = 'https://celo.blockscout.com/graphiql';
export const EXPLORER_GRAPH_ALFAJORES_URL = 'https://celo-alfajores.blockscout.com/graphiql';
export const EXPLORER_MAINNET_URL = 'https://celo.blockscout.com/';
export const EXPLORER_ALFAJORES_URL = 'https://celo-alfajores.blockscout.com/';

export const TWITTER_URL = 'https://twitter.com/Celo';
export const DISCORD_URL = 'https://discord.com/invite/celo';
Expand Down
62 changes: 40 additions & 22 deletions src/features/validators/data/fetchValidGroups.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,16 @@
import { gql, request } from 'graphql-request';
import { EXPLORER_GRAPH_ALFAJORES_URL, EXPLORER_GRAPH_MAINNET_URL } from 'src/config/consts';
import { accountsABI, validatorsABI } from '@celo/abis';
import { healthyGroupsOnly } from 'src/features/validators/data/healthyGroupsOnly';
import { nonBlockedGroupsOnly } from 'src/features/validators/data/nonBlockedGroupsOnly';
import celoRegistry from 'src/utils/celoRegistry';
import { ChainIds } from 'src/utils/clients';
import { celoAlfajores as Alfajores } from 'viem/chains';
import { createPublicClient, http } from 'viem';
import { celo, celoAlfajores } from 'viem/chains';

export interface ValidatorGroup {
name: string;
address: string;
}

const query = gql`
{
celoValidatorGroups {
name
address
}
}
`;

interface GraphValues {
celoValidatorGroups: ValidatorGroup[];
}

interface ValidGroups {
chainId: number;
groups: ValidatorGroup[];
Expand All @@ -31,21 +19,51 @@ interface ValidGroups {
// returns ValidatorGroups that are healthy and not blocked based on
// criteria defined i https://github.com/celo-org/staked-celo/blob/master/contracts/Manager.sol#L348
export default async function fetchValidGroups(chainId: ChainIds): Promise<ValidGroups> {
const url = Alfajores.id === chainId ? EXPLORER_GRAPH_ALFAJORES_URL : EXPLORER_GRAPH_MAINNET_URL;
const data = await request<GraphValues>(url, query);
const client = createPublicClient({
chain: chainId === celo.id ? celo : celoAlfajores,
transport: http(),
});
client;

const validatorsAddress = await client.readContract({
...celoRegistry,
functionName: 'getAddressForString',
args: ['Validators'],
});

const allPossibleGroups = data.celoValidatorGroups;
const accountsAddress = await client.readContract({
...celoRegistry,
functionName: 'getAddressForString',
args: ['Accounts'],
});

const groupAddresses = allPossibleGroups.map((group) => group.address);
const allPossibleGroups = await client.readContract({
abi: validatorsABI,
address: validatorsAddress,
functionName: 'getRegisteredValidatorGroups',
});

const groupAddresses = allPossibleGroups.map((group) => group);
const [healthyGroups, nonBlockedGroups] = await Promise.all(
[healthyGroupsOnly, nonBlockedGroupsOnly].map((fn) => fn(groupAddresses, chainId))
);
const validGroups = allPossibleGroups.filter(
(group) => healthyGroups.has(group.address) && nonBlockedGroups.has(group.address)
(address) => healthyGroups.has(address) && nonBlockedGroups.has(address)
);

const names = await Promise.all(
validGroups.map((address) => {
return client.readContract({
abi: accountsABI,
address: accountsAddress,
functionName: 'getName',
args: [address],
});
})
);

return {
chainId: chainId,
groups: validGroups,
groups: validGroups.map((address, index) => ({ address, name: names[index] })),
};
}

0 comments on commit b3ec63f

Please sign in to comment.