From c851c2ade303bd126305edb605ea39ca60580daa Mon Sep 17 00:00:00 2001 From: Carlos Date: Thu, 14 Sep 2023 10:32:54 -0500 Subject: [PATCH 1/9] fix eligible donations migration --- ...35872128-AddEligibleNetworksToPreviousQfRounds.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts b/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts index 680bdef1d..f65f5635b 100644 --- a/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts +++ b/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts @@ -13,14 +13,14 @@ export class AddEligibleNetworksToPreviousQfRounds1694635872128 ? [1, 3, 5, 100, 137, 10, 420, 56, 42220, 44787] // Include testnets for staging : [1, 137, 56, 42220, 100, 10]; // Exclude testnets for non-staging - // Convert the eligibleNetworks array to a comma-separated string - const eligibleNetworksString = eligibleNetworks.join(', '); - // Update the "qf_round" table with the new eligibleNetworks values - await queryRunner.query(` + await queryRunner.query( + ` UPDATE "qf_round" - SET eligibleNetworks = '{${eligibleNetworksString}}' - `); + SET eligibleNetworks = $1 + `, + [eligibleNetworks], + ); } public async down(queryRunner: QueryRunner): Promise { From 703164052876c557b100c6d39530455eb1e0e6ef Mon Sep 17 00:00:00 2001 From: Carlos Date: Thu, 14 Sep 2023 11:02:05 -0500 Subject: [PATCH 2/9] fix migration table names for qfround networks --- migration/1694295208252-AddEligibleNetworksToQfRoundEntity.ts | 2 +- .../1694635872128-AddEligibleNetworksToPreviousQfRounds.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/migration/1694295208252-AddEligibleNetworksToQfRoundEntity.ts b/migration/1694295208252-AddEligibleNetworksToQfRoundEntity.ts index 65a9610d3..641648841 100644 --- a/migration/1694295208252-AddEligibleNetworksToQfRoundEntity.ts +++ b/migration/1694295208252-AddEligibleNetworksToQfRoundEntity.ts @@ -5,7 +5,7 @@ export class AddEligibleNetworksToQfRoundEntity1694295208252 { public async up(queryRunner: QueryRunner): Promise { await queryRunner.query(` - ALTER TABLE "qf_round" + ALTER TABLE public.qf_round ADD COLUMN IF NOT EXIST "eligibleNetworks" integer array DEFAULT ARRAY[]::integer[] `); } diff --git a/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts b/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts index f65f5635b..0ad1e998f 100644 --- a/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts +++ b/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts @@ -16,7 +16,7 @@ export class AddEligibleNetworksToPreviousQfRounds1694635872128 // Update the "qf_round" table with the new eligibleNetworks values await queryRunner.query( ` - UPDATE "qf_round" + UPDATE public.qf_round SET eligibleNetworks = $1 `, [eligibleNetworks], @@ -25,7 +25,7 @@ export class AddEligibleNetworksToPreviousQfRounds1694635872128 public async down(queryRunner: QueryRunner): Promise { await queryRunner.query(` - UPDATE "qf_round" + UPDATE public.qf_round SET eligibleNetworks = '{}' `); } From 18197447cb9bd058210a6bce1dbb5ca1fa6c5512 Mon Sep 17 00:00:00 2001 From: Carlos Date: Thu, 14 Sep 2023 14:16:05 -0500 Subject: [PATCH 3/9] fix migration file for eligible networks --- migration/1694295208252-AddEligibleNetworksToQfRoundEntity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/1694295208252-AddEligibleNetworksToQfRoundEntity.ts b/migration/1694295208252-AddEligibleNetworksToQfRoundEntity.ts index 641648841..e7c2e85f4 100644 --- a/migration/1694295208252-AddEligibleNetworksToQfRoundEntity.ts +++ b/migration/1694295208252-AddEligibleNetworksToQfRoundEntity.ts @@ -6,7 +6,7 @@ export class AddEligibleNetworksToQfRoundEntity1694295208252 public async up(queryRunner: QueryRunner): Promise { await queryRunner.query(` ALTER TABLE public.qf_round - ADD COLUMN IF NOT EXIST "eligibleNetworks" integer array DEFAULT ARRAY[]::integer[] + ADD COLUMN IF NOT EXISTS "eligibleNetworks" integer array DEFAULT ARRAY[]::integer[] `); } From ed3025a220fd6e524b5be8f210b3817a26e9e807 Mon Sep 17 00:00:00 2001 From: Carlos Date: Thu, 14 Sep 2023 14:52:28 -0500 Subject: [PATCH 4/9] fix qfround fill networks migration --- .../1694635872128-AddEligibleNetworksToPreviousQfRounds.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts b/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts index 0ad1e998f..d8d6df46f 100644 --- a/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts +++ b/migration/1694635872128-AddEligibleNetworksToPreviousQfRounds.ts @@ -17,7 +17,7 @@ export class AddEligibleNetworksToPreviousQfRounds1694635872128 await queryRunner.query( ` UPDATE public.qf_round - SET eligibleNetworks = $1 + SET "eligibleNetworks" = $1 `, [eligibleNetworks], ); @@ -26,7 +26,7 @@ export class AddEligibleNetworksToPreviousQfRounds1694635872128 public async down(queryRunner: QueryRunner): Promise { await queryRunner.query(` UPDATE public.qf_round - SET eligibleNetworks = '{}' + SET "eligibleNetworks" = '{}' `); } } From ae9f96a4a1b59051bdab82790bd118a7c8529747 Mon Sep 17 00:00:00 2001 From: Carlos Date: Sat, 16 Sep 2023 15:16:13 -0500 Subject: [PATCH 5/9] add query for knowing if wallet was used --- src/repositories/donationRepository.ts | 13 +++++++++++++ src/resolvers/userResolver.ts | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/repositories/donationRepository.ts b/src/repositories/donationRepository.ts index caa7b3ae8..9bf2825fc 100644 --- a/src/repositories/donationRepository.ts +++ b/src/repositories/donationRepository.ts @@ -26,6 +26,19 @@ export const fillQfRoundDonationsUserScores = async (): Promise => { `); }; +export const addressHasDonated = async (address: string) => { + const projectAddress = await Donation.query( + ` + SELECT "id" + FROM donation + where lower("fromWalletAddress") = $1 + limit 1 + `, + [address.toLowerCase()], + ); + return projectAddress.length > 0; +}; + export const createDonation = async (data: { amount: number; project: Project; diff --git a/src/resolvers/userResolver.ts b/src/resolvers/userResolver.ts index a03f3906a..15ace1d8c 100644 --- a/src/resolvers/userResolver.ts +++ b/src/resolvers/userResolver.ts @@ -18,6 +18,8 @@ import { SegmentAnalyticsSingleton } from '../services/segment/segmentAnalyticsS import { AppDataSource } from '../orm'; import { getGitcoinAdapter } from '../adapters/adaptersFactory'; import { logger } from '../utils/logger'; +import { isWalletAddressInPurpleList } from '../repositories/projectAddressRepository'; +import { addressHasDonated } from '../repositories/donationRepository'; @Resolver(of => User) export class UserResolver { @@ -29,6 +31,14 @@ export class UserResolver { // return User.create(data).save(); } + @Query(returns => Boolean) + async walletAddressUsed(@Arg('address') address: string): Promise { + return ( + (await isWalletAddressInPurpleList(address)) || + (await addressHasDonated(address)) + ); + } + @Query(returns => UserByAddressResponse, { nullable: true }) async userByAddress( @Arg('address', type => String) address: string, From 7a0b6c189edf1d01848d9f6e555f66eb18c6870b Mon Sep 17 00:00:00 2001 From: Carlos Date: Sun, 17 Sep 2023 14:15:30 -0500 Subject: [PATCH 6/9] improve query for user related address --- src/resolvers/userResolver.ts | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/resolvers/userResolver.ts b/src/resolvers/userResolver.ts index 15ace1d8c..109655e75 100644 --- a/src/resolvers/userResolver.ts +++ b/src/resolvers/userResolver.ts @@ -1,4 +1,12 @@ -import { Arg, Ctx, Mutation, Query, Resolver } from 'type-graphql'; +import { + Arg, + Ctx, + Field, + Mutation, + ObjectType, + Query, + Resolver, +} from 'type-graphql'; import { Repository } from 'typeorm'; import { User } from '../entities/user'; @@ -21,6 +29,15 @@ import { logger } from '../utils/logger'; import { isWalletAddressInPurpleList } from '../repositories/projectAddressRepository'; import { addressHasDonated } from '../repositories/donationRepository'; +@ObjectType() +class UserRelatedAddressResponse { + @Field(type => Boolean, { nullable: false }) + hasRelatedProject: boolean; + + @Field(type => Boolean, { nullable: false }) + hasDonated: boolean; +} + @Resolver(of => User) export class UserResolver { constructor(private readonly userRepository: Repository) { @@ -31,12 +48,12 @@ export class UserResolver { // return User.create(data).save(); } - @Query(returns => Boolean) - async walletAddressUsed(@Arg('address') address: string): Promise { - return ( - (await isWalletAddressInPurpleList(address)) || - (await addressHasDonated(address)) - ); + @Query(returns => UserRelatedAddressResponse) + async walletAddressUsed(@Arg('address') address: string) { + return { + hasRelatedProject: await isWalletAddressInPurpleList(address), + hasDonated: await addressHasDonated(address), + }; } @Query(returns => UserByAddressResponse, { nullable: true }) From 1a46487eec8974949b741e2395b877e1a9ad7ca4 Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 18 Sep 2023 23:10:33 -0500 Subject: [PATCH 7/9] unify project counts in userByAddress and projectsByUserId --- src/entities/user.ts | 9 ++------- src/repositories/userRepository.ts | 30 +++++++++++++++++++++++++++++- src/resolvers/userResolver.ts | 2 ++ 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/entities/user.ts b/src/entities/user.ts index 6c6817f37..d9f2b17c0 100644 --- a/src/entities/user.ts +++ b/src/entities/user.ts @@ -183,13 +183,7 @@ export class User extends BaseEntity { createdAt: Date; @Field(type => Int, { nullable: true }) - async projectsCount() { - const projectsCount = await Project.createQueryBuilder('project') - .where('project."admin" = :id', { id: String(this.id) }) - .getCount(); - - return projectsCount; - } + projectsCount?: number; @Field(type => Int, { nullable: true }) async donationsCount() { @@ -215,6 +209,7 @@ export class User extends BaseEntity { return likedProjectsCount; } + @Field(type => Int, { nullable: true }) async boostedProjectsCount() { return findPowerBoostingsCountByUserId(this.id); diff --git a/src/repositories/userRepository.ts b/src/repositories/userRepository.ts index 7e074598e..e262d59d3 100644 --- a/src/repositories/userRepository.ts +++ b/src/repositories/userRepository.ts @@ -3,6 +3,7 @@ import { SegmentAnalyticsSingleton } from '../services/segment/segmentAnalyticsS import { Donation } from '../entities/donation'; import { Reaction } from '../entities/reaction'; import { PowerBoosting } from '../entities/powerBoosting'; +import { Project, ProjStatus, ReviewStatus } from '../entities/project'; export const findAdminUserByEmail = async ( email: string, @@ -35,6 +36,7 @@ export const isFirstTimeDonor = async (userId: number): Promise => { export const findUserByWalletAddress = async ( walletAddress: string, includeSensitiveFields = true, + ownerUserId?: number, ): Promise => { const query = User.createQueryBuilder('user').where( `LOWER("walletAddress") = :walletAddress`, @@ -45,8 +47,34 @@ export const findUserByWalletAddress = async ( if (!includeSensitiveFields) { query.select(publicSelectionFields); } + const user = await query.getOne(); + if (!user) return null; - return query.getOne(); + user.projectsCount = await fetchUserProjectsCount( + user!.id, + user?.id === ownerUserId, + ); + + return user; +}; + +export const fetchUserProjectsCount = async ( + userId: number, + ownerViewing: boolean, +) => { + const projectsCount = Project.createQueryBuilder('project').where( + 'project."adminUserId" = :id', + { id: userId }, + ); + + if (!ownerViewing) { + projectsCount.andWhere( + `project.statusId = ${ProjStatus.active} AND project.reviewStatus = :reviewStatus`, + { reviewStatus: ReviewStatus.Listed }, + ); + } + + return projectsCount.getCount(); }; export const findUserById = (userId: number): Promise => { diff --git a/src/resolvers/userResolver.ts b/src/resolvers/userResolver.ts index 109655e75..7a9f9d38f 100644 --- a/src/resolvers/userResolver.ts +++ b/src/resolvers/userResolver.ts @@ -66,6 +66,7 @@ export class UserResolver { const foundUser = await findUserByWalletAddress( address, includeSensitiveFields, + user?.userId, ); return { isSignedIn: Boolean(user), @@ -83,6 +84,7 @@ export class UserResolver { const foundUser = await findUserByWalletAddress( address, includeSensitiveFields, + user?.userId, ); if (!foundUser) return; From 5fec9311400e8732a8dd839c4125f2890803d7b1 Mon Sep 17 00:00:00 2001 From: Carlos Date: Tue, 19 Sep 2023 14:56:05 -0500 Subject: [PATCH 8/9] improve condition for projectCount --- src/repositories/userRepository.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repositories/userRepository.ts b/src/repositories/userRepository.ts index e262d59d3..57ac0cdbf 100644 --- a/src/repositories/userRepository.ts +++ b/src/repositories/userRepository.ts @@ -52,7 +52,7 @@ export const findUserByWalletAddress = async ( user.projectsCount = await fetchUserProjectsCount( user!.id, - user?.id === ownerUserId, + Number(user?.id) === Number(ownerUserId), ); return user; From 28c129944a4c100773e87682a09ef4dc9392ca95 Mon Sep 17 00:00:00 2001 From: Carlos Date: Tue, 19 Sep 2023 16:46:09 -0500 Subject: [PATCH 9/9] fix projectCount query --- src/repositories/userRepository.ts | 7 +++---- src/resolvers/userResolver.ts | 2 -- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/repositories/userRepository.ts b/src/repositories/userRepository.ts index 57ac0cdbf..31f2233d6 100644 --- a/src/repositories/userRepository.ts +++ b/src/repositories/userRepository.ts @@ -36,7 +36,6 @@ export const isFirstTimeDonor = async (userId: number): Promise => { export const findUserByWalletAddress = async ( walletAddress: string, includeSensitiveFields = true, - ownerUserId?: number, ): Promise => { const query = User.createQueryBuilder('user').where( `LOWER("walletAddress") = :walletAddress`, @@ -52,7 +51,7 @@ export const findUserByWalletAddress = async ( user.projectsCount = await fetchUserProjectsCount( user!.id, - Number(user?.id) === Number(ownerUserId), + includeSensitiveFields, ); return user; @@ -60,14 +59,14 @@ export const findUserByWalletAddress = async ( export const fetchUserProjectsCount = async ( userId: number, - ownerViewing: boolean, + includeSensitiveFields: boolean, ) => { const projectsCount = Project.createQueryBuilder('project').where( 'project."adminUserId" = :id', { id: userId }, ); - if (!ownerViewing) { + if (!includeSensitiveFields) { projectsCount.andWhere( `project.statusId = ${ProjStatus.active} AND project.reviewStatus = :reviewStatus`, { reviewStatus: ReviewStatus.Listed }, diff --git a/src/resolvers/userResolver.ts b/src/resolvers/userResolver.ts index 7a9f9d38f..109655e75 100644 --- a/src/resolvers/userResolver.ts +++ b/src/resolvers/userResolver.ts @@ -66,7 +66,6 @@ export class UserResolver { const foundUser = await findUserByWalletAddress( address, includeSensitiveFields, - user?.userId, ); return { isSignedIn: Boolean(user), @@ -84,7 +83,6 @@ export class UserResolver { const foundUser = await findUserByWalletAddress( address, includeSensitiveFields, - user?.userId, ); if (!foundUser) return;