Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 134 additions & 48 deletions src/scripts/syncDataWithJsonReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import fs from 'fs-extra';
import { Donation } from '../entities/donation';
import { Project } from '../entities/project';
import { AppDataSource } from '../orm';
import { getStreamDetails } from './helpers';
import { getRoundByBatchNumber, getStreamDetails } from './helpers';
import { repoLocalDir, getReportsSubDir } from './configs';

async function loadReportFile(filePath: string) {
Expand Down Expand Up @@ -36,6 +36,8 @@ function getAllReportFiles(dirPath: string) {
async function processReportForDonations(
donations: Donation[],
reportData: any,
round: any,
isEarlyAccess: boolean,
) {
try {
const participants = reportData.batch.data.participants;
Expand All @@ -53,64 +55,144 @@ async function processReportForDonations(

if (!participantData) {
console.error(`No participant data found for donation ${donation.id}`);
await unassociateDonationIfIsForThisRound(
donation,
round,
isEarlyAccess,
);
continue;
}

const totalValidContribution = ethers.BigNumber.from(
participantData.validContribution.inCollateral,
await updateDonationRewardsData(
participantData,
donation,
round,
isEarlyAccess,
);
// if issuance allocation is not exist, that mean this user has not any valid contributions
let rewardAmount = 0;
if (participantData.issuanceAllocation) {
const issuanceAllocationRow = ethers.BigNumber.from(
participantData.issuanceAllocation,
);
const issuanceAllocation = parseFloat(
ethers.utils.formatUnits(issuanceAllocationRow, 18),
); // Assuming 18 decimal places

const donationTransaction = participantData.transactions.find(
(tx: any) =>
tx.transactionHash.toLowerCase() ===
donation.transactionId.toLowerCase(),
);
}
// todo: can check if there is any transactions that is not in the database
} catch (error) {
console.error(
`Failed to process donations rewards for project ${donations[0].projectId}: ${error.message}`,
);
}
}

if (!donationTransaction) {
console.error(
`No transaction data found for donation ${donation.id}`,
);
continue;
}
async function unassociateDonationIfIsForThisRound(
donation: Donation,
round: any,
isEarlyAccess: boolean,
) {
console.info(`Unassociating donation ${donation.id} if the round is same...`);
if (isEarlyAccess && donation.earlyAccessRoundId === round.id) {
donation.earlyAccessRoundId = null;
await donation.save();
console.info(
`Donation ${donation.id} unassociated form early access round ${round.roundNumber}`,
);
return;
}
if (!isEarlyAccess && donation.qfRoundId === round.id) {
donation.qfRoundId = null;
await donation.save();
console.info(
`Donation ${donation.id} unassociated form qacc round ${round.roundNumber}`,
);
return;
}
console.warn(
`Donation ${donation.id} is not associated to current round!!!\n
Donation qf round id is ${donation.qfRoundId} and donation early access round id is ${donation.earlyAccessRoundId}\n
But report is for ${isEarlyAccess ? 'early access' : 'Qacc'} round with id ${round.id} !!!!`,
);
}

const donationValidContribution = ethers.BigNumber.from(
donationTransaction.validContribution,
);
const contributionPercentage =
parseFloat(ethers.utils.formatUnits(donationValidContribution, 18)) /
parseFloat(ethers.utils.formatUnits(totalValidContribution, 18));
// based the use case of this function, we don't need to save donation in it, because after calling that, we save donation data
function associateDonationToThisRound(
donation: Donation,
round: any,
isEarlyAccess: boolean,
) {
console.info(
`Associating donation ${donation.id} if the round is not matched...`,
);
if (isEarlyAccess && donation.earlyAccessRoundId !== round.id) {
console.warn(
`Associate donation to current round because donation ${donation.id} is not associated correctly!!!\n
Donation qf round id is ${donation.qfRoundId} and donation early access round id is ${donation.earlyAccessRoundId}\n
But report is for early access round with id ${round.id} !!!!`,
);
donation.earlyAccessRoundId = round.id;
donation.qfRoundId = null;
return;
}
if (!isEarlyAccess && donation.qfRoundId !== round.id) {
console.warn(
`Associate donation to current round because donation ${donation.id} is not associated correctly!!!\n
Donation qf round id is ${donation.qfRoundId} and donation early access round id is ${donation.earlyAccessRoundId}\n
But report is for Qacc round with id ${round.id} !!!!`,
);
donation.earlyAccessRoundId = null;
donation.qfRoundId = round.id;
console.info(
`Donation ${donation.id} unassociated form qacc round ${round.roundNumber}`,
);
return;
}
console.info(`Donation is associated correctly from before`);
}

// Calculate the reward proportionally based on the valid contribution
rewardAmount = issuanceAllocation * contributionPercentage;
}
donation.rewardTokenAmount = rewardAmount || 0;
async function updateDonationRewardsData(
participantData: any,
donation: Donation,
round: any,
isEarlyAccess: boolean,
) {
const totalValidContribution = ethers.BigNumber.from(
participantData.validContribution.inCollateral,
);
// if issuance allocation is not exist, that mean this user has not any valid contributions
const issuanceAllocationRow = ethers.BigNumber.from(
participantData.issuanceAllocation || '0',
);
const issuanceAllocation = parseFloat(
ethers.utils.formatUnits(issuanceAllocationRow, 18),
); // Assuming 18 decimal places

const isEarlyAccessRound = reportData.batch.config.isEarlyAccess;
const vestingInfo = getStreamDetails(isEarlyAccessRound);
const donationTransaction = participantData.transactions.find(
(tx: any) =>
tx.transactionHash.toLowerCase() === donation.transactionId.toLowerCase(),
);

donation.cliff = vestingInfo.CLIFF * 1000;
donation.rewardStreamStart = new Date(vestingInfo.START * 1000);
donation.rewardStreamEnd = new Date(vestingInfo.END * 1000);
if (!donationTransaction) {
console.error(`No transaction data found for donation ${donation.id}`);
await unassociateDonationIfIsForThisRound(donation, round, isEarlyAccess);
return;
}

await donation.save();
console.debug(
`Reward data for donation ${donation.id} successfully updated`,
);
}
} catch (error) {
console.error(
`Failed to process donations rewards for project ${donations[0].projectId}: ${error.message}`,
);
const donationValidContribution = ethers.BigNumber.from(
donationTransaction.validContribution,
);
const contributionPercentage =
parseFloat(ethers.utils.formatUnits(donationValidContribution, 18)) /
parseFloat(ethers.utils.formatUnits(totalValidContribution, 18));

// Calculate the reward proportionally based on the valid contribution
const rewardAmount = issuanceAllocation * contributionPercentage;
donation.rewardTokenAmount = rewardAmount || 0;

if (donation.rewardTokenAmount) {
const vestingInfo = getStreamDetails(isEarlyAccess);

donation.cliff = vestingInfo.CLIFF * 1000;
donation.rewardStreamStart = new Date(vestingInfo.START * 1000);
donation.rewardStreamEnd = new Date(vestingInfo.END * 1000);
}

associateDonationToThisRound(donation, round, isEarlyAccess);

await donation.save();
console.debug(`Reward data for donation ${donation.id} successfully updated`);
}

export async function updateRewardsForDonations(batchNumber: number) {
Expand All @@ -125,6 +207,8 @@ export async function updateRewardsForDonations(batchNumber: number) {
],
});

const { round, isEarlyAccess } = await getRoundByBatchNumber(batchNumber);

const donationsByProjectId = _.groupBy(donations, 'projectId');

const reportFilesDir = path.join(repoLocalDir, getReportsSubDir());
Expand Down Expand Up @@ -180,6 +264,8 @@ export async function updateRewardsForDonations(batchNumber: number) {
await processReportForDonations(
donationsByProjectId[projectId],
matchedReportFile,
round,
isEarlyAccess,
);
}
} catch (error) {
Expand Down
Loading