diff --git a/app/src/utils/constants.ts b/app/src/utils/constants.ts index 9b030f77..693eee10 100644 --- a/app/src/utils/constants.ts +++ b/app/src/utils/constants.ts @@ -41,7 +41,7 @@ export const DefaultForageConfig: LocalForageConfig = { // this store should be used for any on-chain/off-chain data but never user data (as we might clear it without notice) name: 'dGrants', // we can bump this version number to bust the users cache - version: 1, + version: 2, }; // LocalForage keys diff --git a/app/src/utils/data/contributions.ts b/app/src/utils/data/contributions.ts index a3a936d2..3f3424f7 100644 --- a/app/src/utils/data/contributions.ts +++ b/app/src/utils/data/contributions.ts @@ -53,27 +53,48 @@ export async function getContributions( if (SUBGRAPH_URL) { try { // make the request - const res = await fetch(SUBGRAPH_URL, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - query: `{ - grantDonations(where: {lastUpdatedBlockNumber_gte: ${fromBlock}, lastUpdatedBlockNumber_lte: ${blockNumber}}) { - grantId - tokenIn - donationAmount - from - hash - rounds - lastUpdatedBlockNumber - } - }`, - }), - }); - // resolve the json - const json = await res.json(); + + const limit = 100; + + const fetchUntilAll = async ( + SUBGRAPH_URL: string, + before: ContributionSubgraph[] = [], + skip = 0 + ): Promise => { + const res = await fetch(SUBGRAPH_URL, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + query: `{ + grantDonations(first: ${limit}, skip: ${ + skip * limit + }, where: {lastUpdatedBlockNumber_gte: ${fromBlock}, lastUpdatedBlockNumber_lte: ${blockNumber}}) { + grantId + tokenIn + donationAmount + from + hash + rounds + lastUpdatedBlockNumber + } + }`, + }), + }); + // resolve the json + const json = await res.json(); + + if (json.data.grantDonations.length) { + const current = [...before, ...json.data.grantDonation]; + return await fetchUntilAll(SUBGRAPH_URL, current, skip + 1); + } else { + return [...before]; + } + }; + + const donationData = await fetchUntilAll(SUBGRAPH_URL); + // update each of the grants - json.data.grantDonations.forEach((contribution: ContributionSubgraph) => { + donationData.forEach((contribution: ContributionSubgraph) => { // update to most recent block collected fromBlock = Math.max(fromBlock, contribution.lastUpdatedBlockNumber); const grantId = BigNumber.from(contribution.grantId).toNumber(); @@ -264,6 +285,10 @@ export function grantDonationListener( }, refs: Record ) { + let timoutManager = 0; + const eachSaveTime = 400; + const processingSet = new Set(); + const listener = async ( grantId: BigNumberish, tokenIn: string, @@ -271,16 +296,26 @@ export function grantDonationListener( grantRounds: string[], event: Event ) => { - // console.log(name, grantId, tokenIn, donationAmount, rounds); + const tx = await event.getTransaction(); + + const wait = (timeout: number) => { + return new Promise((resolve) => { + setTimeout(() => { + return resolve(`Waited: ${timeout}ms`); + }, timeout); + }); + }; + timoutManager += eachSaveTime; + await wait(timoutManager - eachSaveTime + Math.floor(Math.random() * (eachSaveTime / 2))); + if (processingSet.has(`${tx.hash}-${grantId}`)) { + return; + } + processingSet.add(`${tx.hash}-${grantId}`); + const blockNumber = await provider.value.getBlockNumber(); // get tx details to pull contributor details from - const tx = await event.getTransaction(); // log the new contribution - console.log('New contribution: ', { - grantId: BigNumber.from(grantId).toNumber(), - donationAmount: parseFloat(formatUnits(donationAmount, args.donationToken.decimals)), - from: tx.from, - }); + // store the new contribution const contributions = await syncStorage( contributionsKey, @@ -316,6 +351,9 @@ export function grantDonationListener( (a?.blockNumber || 0) > (b?.blockNumber || 0) ? -1 : a?.blockNumber == b?.blockNumber ? 0 : 1 ) as Contribution[]; + timoutManager -= eachSaveTime; + processingSet.delete(`${tx.hash}-${grantId}`); + return { contributions: refs.contributions.value, };