Skip to content

Commit

Permalink
added subgraph health store
Browse files Browse the repository at this point in the history
  • Loading branch information
dan13ram committed Oct 7, 2022
1 parent b318453 commit a8e97d3
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 2 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@quest-chains/sdk",
"description": "An SDK for building applications on top of Quest Chains",
"version": "0.1.11",
"version": "0.1.12",
"license": "GPL-3.0",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down
5 changes: 5 additions & 0 deletions src/graphql/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,30 @@ import { Client, createClient, dedupExchange, fetchExchange } from 'urql';
export type NetworkInfo = {
[chainId: string]: {
chainId: string;
subgraphName: string;
subgraphUrl: string;
};
};

export const SUPPORTED_NETWORK_INFO: NetworkInfo = {
'0x89': {
chainId: '0x89',
subgraphName: 'dan13ram/quest-chains-polygon',
subgraphUrl: 'https://api.thegraph.com/subgraphs/name/dan13ram/quest-chains-polygon',
},
'0x64': {
chainId: '0x64',
subgraphName: 'dan13ram/quest-chains-xdai',
subgraphUrl: 'https://api.thegraph.com/subgraphs/name/dan13ram/quest-chains-xdai',
},
'0x5': {
chainId: '0x5',
subgraphName: 'dan13ram/quest-chains-goerli',
subgraphUrl: 'https://api.thegraph.com/subgraphs/name/dan13ram/quest-chains-goerli',
},
'0x13881': {
chainId: '0x13881',
subgraphName: 'dan13ram/quest-chains-mumbai',
subgraphUrl: 'https://api.thegraph.com/subgraphs/name/dan13ram/quest-chains-mumbai',
},
};
Expand Down
75 changes: 75 additions & 0 deletions src/graphql/health.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* eslint-disable no-console, no-await-in-loop */
import { gql, request } from 'graphql-request';

import { SUPPORTED_NETWORK_INFO } from './client';

const GRAPH_HEALTH_ENDPOINT = 'https://api.thegraph.com/index-node/graphql';

const statusQuery = gql`
query getSubgraphStatus($subgraph: String!) {
status: indexingStatusForCurrentVersion(subgraphName: $subgraph) {
chains {
latestBlock {
number
}
}
}
}
`;

const getLatestBlock = async (subgraph: string): Promise<number> => {
const data = await request(GRAPH_HEALTH_ENDPOINT, statusQuery, {
subgraph,
});
return data.status.chains[0].latestBlock.number;
};

const UPDATE_INTERVAL = 10000;

class SubgraphHealthStore {
graphHealth: Record<string, number> = {};

constructor() {
// console.debug('@quest-chains/sdk: health store init');
this.updateSubgraphHealth();
}

public async updateSubgraphHealth() {
await Promise.all(
Object.values(SUPPORTED_NETWORK_INFO).map(async info => {
this.graphHealth[info.chainId] = await getLatestBlock(info.subgraphName);
}),
);
// console.debug('@quest-chains/sdk: updated graph health:', this.graphHealth);
setTimeout(() => this.updateSubgraphHealth(), UPDATE_INTERVAL);
}

status() {
return this.graphHealth;
}
}

const HealthStoreSingleton = (function () {
let instance: SubgraphHealthStore;

function createInstance() {
return new SubgraphHealthStore();
}

return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
},
};
})();

const getSubgraphStatus = () => HealthStoreSingleton.getInstance().status();

const initSubgraphHealthStore = getSubgraphStatus;

initSubgraphHealthStore();

export const getSubgraphLatestBlock = (chainId: string): number => getSubgraphStatus()[chainId];
1 change: 1 addition & 0 deletions src/graphql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export * from './statusForUser';
export * from './rolesForUser';
export * from './types';
export * from './client';
export * from './health';
36 changes: 36 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* eslint-disable no-await-in-loop */

import { Log, TransactionReceipt } from '@ethersproject/abstract-provider';
import { ethers } from 'ethers';

import { getSubgraphLatestBlock } from './graphql/health';

const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));

const UPDATE_INTERVAL = 10000;

const MAX_RETRIES = 6;

export const waitUntilSubgraphIndexed = async (chainId: string, block: number): Promise<boolean> => {
let latestBlock = getSubgraphLatestBlock(chainId);
let tries = 0;
while (latestBlock < block && tries < MAX_RETRIES) {
await sleep(UPDATE_INTERVAL);
tries += 1;
latestBlock = getSubgraphLatestBlock(chainId);
}
return latestBlock >= block;
};

export const getQuestChainAddressFromTx = async (receipt: TransactionReceipt) => {
if (!receipt || !receipt.logs) return '';
const abi = new ethers.utils.Interface(['event QuestChainCreated(uint256 id, address questChain)']);
const eventFragment = abi.events[Object.keys(abi.events)[0]];
const eventTopic = abi.getEventTopic(eventFragment);
const event = receipt.logs.find((e: Log) => e.topics[0] === eventTopic);
if (event) {
const decodedLog = abi.decodeEventLog(eventFragment, event.data, event.topics);
return decodedLog.questChain;
}
return '';
};
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as graphql from './graphql';
import * as contracts from './contracts';
import * as metadata from './metadata';
import * as helpers from './helpers';

export { graphql, contracts, metadata };
export { graphql, contracts, metadata, helpers };

0 comments on commit a8e97d3

Please sign in to comment.