Skip to content

Commit

Permalink
Merge pull request #155 from GeneralMagicio/staging
Browse files Browse the repository at this point in the history
staging -> productoin
  • Loading branch information
aminlatifi authored Dec 19, 2024
2 parents 424d898 + 0aa3e84 commit 504457b
Show file tree
Hide file tree
Showing 14 changed files with 274 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main-deploy-only.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
port: ${{ secrets.SSH_PORT }}
script: |
cd QAcc-BE
git reset --hard HEAD~1
git reset --hard origin/main
git checkout main
git pull origin main
docker image prune -a --force
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ jobs:
port: ${{ secrets.SSH_PORT }}
script: |
cd QAcc-BE
git reset --hard HEAD~1
git reset --hard origin/main
git checkout main
git pull origin main
docker image prune -a --force
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main-publish-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
port: ${{ secrets.SSH_PORT }}
script: |
cd QAcc-BE
git reset --hard HEAD~1
git reset --hard origin/main
git checkout main
git pull origin main
docker image prune -a --force
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/staging-deploy-only.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
port: ${{ secrets.SSH_PORT }}
script: |
cd QAcc-BE
git reset --hard HEAD~1
git reset --hard origin/staging
git checkout staging
git pull origin staging
docker image prune -a --force
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/staging-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ jobs:
port: ${{ secrets.SSH_PORT }}
script: |
cd QAcc-BE
git reset --hard HEAD~1
git reset --hard origin/staging
git checkout staging
git pull origin staging
docker image prune -a --force
Expand Down
19 changes: 19 additions & 0 deletions migration/1734475040262-addMatchingFundsToProjectTable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddMatchingFundsToProjectTable1734475040262
implements MigrationInterface
{
name = 'AddMatchingFundsToProjectTable1734475040262';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "project" ADD "matchingFunds" integer`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "project" DROP COLUMN "matchingFunds"`,
);
}
}
19 changes: 19 additions & 0 deletions migration/1734598837452-addProjectTributeModuleAddress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddProjectTributeModuleAddress1734598837452
implements MigrationInterface
{
name = 'AddProjectTributeModuleAddress1734598837452';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "project" ADD "tributeClaimModuleAddress" character varying`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "project" DROP COLUMN "tributeClaimModuleAddress"`,
);
}
}
8 changes: 8 additions & 0 deletions src/entities/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ export class Project extends BaseEntity {
@Column('jsonb', { nullable: true })
abc: Abc;

@Field({ nullable: true })
@Column({ nullable: true })
tributeClaimModuleAddress: string;

@Index('trgm_idx_project_impact_location', { synchronize: false })
@Field({ nullable: true })
@Column({ nullable: true })
Expand Down Expand Up @@ -468,6 +472,10 @@ export class Project extends BaseEntity {
@Column('integer', { array: true, default: [] })
batchNumbersWithSafeTransactions?: number[];

@Field(_type => Int, { nullable: true })
@Column({ type: 'int', nullable: true })
matchingFunds?: number;

// only projects with status active can be listed automatically
static pendingReviewSince(maximumDaysForListing: number) {
const maxDaysForListing = moment()
Expand Down
30 changes: 17 additions & 13 deletions src/resolvers/projectResolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ function createProjectTestCases() {
accessToken = await generateTestAccessToken(user.id);
});

afterEach(async () => {
const project = await Project.findOneBy({ adminUserId: user.id });
if (project) {
await deleteProjectDirectlyFromDb(project.id);
}
});

it('should create project with team members successfully', async () => {
assert.isOk(user);
assert.isOk(accessToken);
Expand Down Expand Up @@ -328,10 +335,10 @@ function createProjectTestCases() {
SEED_DATA.FOOD_SUB_CATEGORIES[1],
],
description: '<div>Sample Project Creation</div>',
adminUserId: SEED_DATA.FIRST_USER.id,
adminUserId: user.id,
address: generateRandomEtheriumAddress(),
};
const accessToken = await generateTestAccessToken(SEED_DATA.FIRST_USER.id);
const accessToken = await generateTestAccessToken(user.id);
const result = await axios.post(
graphqlUrl,
{
Expand All @@ -357,10 +364,10 @@ function createProjectTestCases() {
title: String(new Date().getTime()),
categories: [SEED_DATA.FOOD_SUB_CATEGORIES[0]],
description: 'description',
adminUserId: SEED_DATA.FIRST_USER.id,
adminUserId: user.id,
address: generateRandomEtheriumAddress(),
};
const accessToken = await generateTestAccessToken(SEED_DATA.FIRST_USER.id);
const accessToken = await generateTestAccessToken(user.id);
const addProjectResponse = await axios.post(
graphqlUrl,
{
Expand Down Expand Up @@ -390,10 +397,10 @@ function createProjectTestCases() {
description: 'a'.repeat(PROJECT_DESCRIPTION_MAX_LENGTH + 1),
image:
'https://gateway.pinata.cloud/ipfs/QmauSzWacQJ9rPkPJgr3J3pdgfNRGAaDCr1yAToVWev2QS',
adminUserId: SEED_DATA.FIRST_USER.id,
adminUserId: user.id,
address: generateRandomEtheriumAddress(),
};
const accessToken = await generateTestAccessToken(SEED_DATA.FIRST_USER.id);
const accessToken = await generateTestAccessToken(user.id);
let result = await axios.post(
graphqlUrl,
{
Expand Down Expand Up @@ -443,10 +450,10 @@ function createProjectTestCases() {
description: 'description',
image:
'https://gateway.pinata.cloud/ipfs/QmauSzWacQJ9rPkPJgr3J3pdgfNRGAaDCr1yAToVWev2QS',
adminUserId: SEED_DATA.FIRST_USER.id,
adminUserId: user.id,
address: generateRandomEtheriumAddress(),
};
const accessToken = await generateTestAccessToken(SEED_DATA.FIRST_USER.id);
const accessToken = await generateTestAccessToken(user.id);
const result = await axios.post(
graphqlUrl,
{
Expand Down Expand Up @@ -476,10 +483,7 @@ function createProjectTestCases() {
ReviewStatus.Listed,
);

assert.equal(
result.data.data.createProject.adminUser.id,
SEED_DATA.FIRST_USER.id,
);
assert.equal(result.data.data.createProject.adminUser.id, user.id);
assert.equal(result.data.data.createProject.verified, false);
assert.equal(
result.data.data.createProject.status.id,
Expand All @@ -492,7 +496,7 @@ function createProjectTestCases() {

assert.equal(
result.data.data.createProject.adminUser.walletAddress,
SEED_DATA.FIRST_USER.walletAddress,
user.walletAddress,
);
assert.equal(result.data.data.createProject.image, sampleProject.image);
assert.equal(
Expand Down
97 changes: 97 additions & 0 deletions src/resolvers/qAccResolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
import {
projectUserDonationCap,
projectUserTotalDonationAmounts,
qAccStat,
userCaps,
} from '../../test/graphqlQueries';
import { ProjectRoundRecord } from '../entities/projectRoundRecord';
Expand All @@ -33,6 +34,7 @@ import {
GITCOIN_PASSPORT_MIN_VALID_SCORER_SCORE,
} from '../constants/gitcoin';
import { PrivadoAdapter } from '../adapters/privado/privadoAdapter';
import { AppDataSource } from '../orm';

describe(
'projectUserTotalDonationAmount() test cases',
Expand All @@ -46,6 +48,8 @@ describe(

describe('userCaps() test cases', userCapsTestCases);

describe('qAccStat() test cases', qAccStatTestCases);

function projectUserTotalDonationAmountTestCases() {
it('should return total donation amount of a user for a project', async () => {
it('should return total donation amount of a user for a project', async () => {
Expand Down Expand Up @@ -491,3 +495,96 @@ function userCapsTestCases() {
}
});
}

function qAccStatTestCases() {
let project;
let user;
let qfRound1: QfRound;
beforeEach(async () => {
project = await saveProjectDirectlyToDb(createProjectData());
user = await saveUserDirectlyToDb(generateRandomEtheriumAddress());
qfRound1 = await QfRound.create({
roundNumber: 1,
isActive: true,
name: new Date().toString() + ' - 1',
allocatedFund: 100,
minimumPassportScore: 12,
slug: new Date().getTime().toString() + ' - 1',
beginDate: new Date('2001-01-14'),
endDate: new Date('2001-01-16'),
roundUSDCapPerProject: 10000,
roundUSDCapPerUserPerProject: 2500,
roundUSDCapPerUserPerProjectWithGitcoinScoreOnly: 1000,
tokenPrice: 0.5,
}).save();
sinon.useFakeTimers({
now: new Date('2001-01-15').getTime(),
});
});
afterEach(async () => {
// Clean up the database after each test
await ProjectRoundRecord.delete({});
await Donation.delete({ projectId: project.id });
await QfRound.delete(qfRound1.id);

sinon.restore();
});
it('should return correct qacc stats', async () => {
const qfDonationAmount = Math.round(Math.random() * 1_000_000_00) / 100;
const nonQfDonationAmount = Math.round(Math.random() * 1_000_000_00) / 100;

await saveDonationDirectlyToDb(
{
...createDonationData(),
amount: nonQfDonationAmount,
status: DONATION_STATUS.VERIFIED,
},
user.id,
project.id,
);
await saveDonationDirectlyToDb(
{
...createDonationData(),
amount: qfDonationAmount,
status: DONATION_STATUS.VERIFIED,
qfRoundId: qfRound1.id,
},
user.id,
project.id,
);
const result: AxiosResponse<
ExecutionResult<{
qAccStat: {
totalCollected: number;
qfTotalCollected: number;
contributorsCount: number;
};
}>
> = await axios.post(graphqlUrl, {
query: qAccStat,
});

assert.isOk(result.data);

const dataSource = AppDataSource.getDataSource();
const totalDonations = await dataSource.query(`
SELECT COALESCE(SUM(amount), 0) as totalCollected from donation where status = '${DONATION_STATUS.VERIFIED}'
`);
const qfTotalDonations = await dataSource.query(`
SELECT COALESCE(SUM(amount), 0) as qfTotalCollected from donation where status = '${DONATION_STATUS.VERIFIED}' AND "qfRoundId" IS NOT NULL
`);
// count unique contributors
const contributorsCount = await Donation.createQueryBuilder('donation')
.select('COUNT(DISTINCT "userId")', 'contributorsCount')
.where('donation.status = :status', {
status: DONATION_STATUS.VERIFIED,
})
.getRawOne();

assert.deepEqual(result.data.data?.qAccStat, {
totalCollected: totalDonations[0].totalcollected,
qfTotalCollected: qfTotalDonations[0].qftotalcollected,
contributorsCount: +contributorsCount?.contributorsCount,
});
});
}
22 changes: 22 additions & 0 deletions src/resolvers/qAccResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ class ProjectUserRecordAmounts {
qfTotalDonationAmount: number;
}

@ObjectType()
class QaccStat {
@Field(_type => Float)
totalCollected: number;

@Field(_type => Float)
qfTotalCollected: number;

@Field(_type => Int)
contributorsCount: number;
}

@ObjectType()
class UnusedCapResponse {
@Field(_type => Float)
Expand Down Expand Up @@ -118,4 +130,14 @@ export class QAccResolver {

return response;
}

@Query(_returns => QaccStat)
async qAccStat() {
const state = await qAccService.getQAccStat();
return {
totalCollected: state.totalCollected,
qfTotalCollected: state.qfTotalCollected,
contributorsCount: state.totalContributors,
};
}
}
9 changes: 7 additions & 2 deletions src/scripts/runFundingPotService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ async function generateBatchFile(batchNumber: number, dryRun: boolean) {
? round.cumulativeUSDCapPerUserPerProject
: round.roundUSDCapPerUserPerProject) || '5000'
).toString(), // Default to 5000 for individual cap
INDIVIDUAL_2: isEarlyAccess ? '0' : '250', // Only required for QACC rounds
INDIVIDUAL_2: isEarlyAccess
? '0'
: (
round.roundUSDCapPerUserPerProjectWithGitcoinScoreOnly || '1000'
).toString(), // Only required for QACC rounds if for users with GP score only
TOTAL: (
(isEarlyAccess
? round.cumulativeUSDCapPerProject
Expand Down Expand Up @@ -122,6 +126,7 @@ async function fillProjectsData() {
SAFE: project.abc.projectAddress || '',
ORCHESTRATOR: project.abc.orchestratorAddress || '',
NFT: project.abc.nftContractAddress || '',
MATCHING_FUNDS: project.matchingFunds || '',
};
} else {
console.warn(
Expand Down Expand Up @@ -175,7 +180,7 @@ async function createEnvFile() {
'ANKR_NETWORK_ID=polygon_zkevm',
)
.replace(
'RPC_URL="https://rpc.ankr.com/base_sepolia"',
'RPC_URL="https://sepolia.base.org"',
'RPC_URL="https://zkevm-rpc.com"',
)
.replace('CHAIN_ID=84532', 'CHAIN_ID=1101')
Expand Down
Loading

0 comments on commit 504457b

Please sign in to comment.