From ab53e2c85a7a94978e9c7af25fd055d0117df3fb Mon Sep 17 00:00:00 2001 From: Amin Latifi Date: Mon, 9 Dec 2024 10:24:07 +0330 Subject: [PATCH] Make batch minting eligible users api backward compatible --- src/resolvers/userResolver.test.ts | 73 ++++++++++++++++++++++++------ src/resolvers/userResolver.ts | 42 +++++++++++++++++ test/graphqlQueries.ts | 12 ++++- 3 files changed, 112 insertions(+), 15 deletions(-) diff --git a/src/resolvers/userResolver.test.ts b/src/resolvers/userResolver.test.ts index 87b2eecb0..f40efde62 100644 --- a/src/resolvers/userResolver.test.ts +++ b/src/resolvers/userResolver.test.ts @@ -18,6 +18,7 @@ import { import { acceptedTermsOfService, batchMintingEligibleUsers, + batchMintingEligibleUsersV2, checkUserPrivadoVerifiedState, refreshUserScores, updateUser, @@ -63,6 +64,10 @@ describe( 'batchMintingEligibleUsers() test cases', batchMintingEligibleUsersTestCases, ); +describe( + 'batchMintingEligibleV2Users() test cases', + batchMintingEligibleUsersV2TestCases, +); // TODO I think we can delete addUserVerification query // describe('addUserVerification() test cases', addUserVerificationTestCases); @@ -1184,13 +1189,53 @@ function batchMintingEligibleUsersTestCases() { // clear all users not empty accepted terms of service await User.delete({ acceptedToS: true }); }); + it('should return users who have accepted terms of service and privado verified', async () => { + const user1 = await saveUserDirectlyToDb(generateRandomEtheriumAddress(), { + privadoVerifiedRequestIds: [PrivadoAdapter.privadoRequestId], + acceptedToS: true, + // 2 days ago + acceptedToSDate: new Date(Date.now() - DAY * 3), + }); + + const user2 = await saveUserDirectlyToDb(generateRandomEtheriumAddress(), { + privadoVerifiedRequestIds: [PrivadoAdapter.privadoRequestId], + acceptedToS: true, + // yesterday + acceptedToSDate: new Date(Date.now() - DAY * 2), + }); + + const user3 = await saveUserDirectlyToDb(generateRandomEtheriumAddress(), { + privadoVerifiedRequestIds: [PrivadoAdapter.privadoRequestId], + acceptedToS: true, + // yesterday + acceptedToSDate: new Date(Date.now() - DAY), + }); - it('should return empty array if there is no user to mint', async () => { const result = await axios.post(graphqlUrl, { query: batchMintingEligibleUsers, }); - assert.deepEqual(result.data.data.batchMintingEligibleUsers.users, []); + assert.deepEqual(result.data.data.batchMintingEligibleUsers.users, [ + user1.walletAddress, + user2.walletAddress, + user3.walletAddress, + ]); + }); +} + +function batchMintingEligibleUsersV2TestCases() { + const DAY = 86400000; + beforeEach(async () => { + // clear all users not empty accepted terms of service + await User.delete({ acceptedToS: true }); + }); + + it('should return empty array if there is no user to mint', async () => { + const result = await axios.post(graphqlUrl, { + query: batchMintingEligibleUsersV2, + }); + + assert.deepEqual(result.data.data.batchMintingEligibleUsersV2.users, []); }); it('should return users who have accepted terms of service and has valid kyc status', async () => { @@ -1216,10 +1261,10 @@ function batchMintingEligibleUsersTestCases() { }); const result = await axios.post(graphqlUrl, { - query: batchMintingEligibleUsers, + query: batchMintingEligibleUsersV2, }); - assert.deepEqual(result.data.data.batchMintingEligibleUsers.users, [ + assert.deepEqual(result.data.data.batchMintingEligibleUsersV2.users, [ { address: user1.walletAddress, kycType: UserKycType.zkId }, { address: user2.walletAddress, kycType: UserKycType.GTCPass }, { address: user3.walletAddress, kycType: UserKycType.GTCPass }, @@ -1238,10 +1283,10 @@ function batchMintingEligibleUsersTestCases() { }); const result = await axios.post(graphqlUrl, { - query: batchMintingEligibleUsers, + query: batchMintingEligibleUsersV2, }); - assert.deepEqual(result.data.data.batchMintingEligibleUsers.users, [ + assert.deepEqual(result.data.data.batchMintingEligibleUsersV2.users, [ { address: user.walletAddress, kycType: UserKycType.zkId }, ]); }); @@ -1262,10 +1307,10 @@ function batchMintingEligibleUsersTestCases() { }); const result = await axios.post(graphqlUrl, { - query: batchMintingEligibleUsers, + query: batchMintingEligibleUsersV2, }); - assert.deepEqual(result.data.data.batchMintingEligibleUsers.users, [ + assert.deepEqual(result.data.data.batchMintingEligibleUsersV2.users, [ { address: user1.walletAddress, kycType: UserKycType.zkId }, ]); }); @@ -1290,27 +1335,27 @@ function batchMintingEligibleUsersTestCases() { }); let result = await axios.post(graphqlUrl, { - query: batchMintingEligibleUsers, + query: batchMintingEligibleUsersV2, variables: { limit: 2, skip: 0, }, }); - assert.deepEqual(result.data.data.batchMintingEligibleUsers.users, [ + assert.deepEqual(result.data.data.batchMintingEligibleUsersV2.users, [ { address: user1.walletAddress, kycType: UserKycType.zkId }, { address: user2.walletAddress, kycType: UserKycType.GTCPass }, ]); result = await axios.post(graphqlUrl, { - query: batchMintingEligibleUsers, + query: batchMintingEligibleUsersV2, variables: { limit: 2, skip: 2, }, }); - assert.deepEqual(result.data.data.batchMintingEligibleUsers.users, [ + assert.deepEqual(result.data.data.batchMintingEligibleUsersV2.users, [ { address: user3.walletAddress, kycType: UserKycType.GTCPass }, ]); }); @@ -1357,10 +1402,10 @@ function batchMintingEligibleUsersTestCases() { }); const result = await axios.post(graphqlUrl, { - query: batchMintingEligibleUsers, + query: batchMintingEligibleUsersV2, }); - assert.deepEqual(result.data.data.batchMintingEligibleUsers.users, [ + assert.deepEqual(result.data.data.batchMintingEligibleUsersV2.users, [ { address: user1.walletAddress, kycType: UserKycType.zkId }, { address: user2.walletAddress, kycType: UserKycType.zkId }, { address: user3.walletAddress, kycType: UserKycType.zkId }, diff --git a/src/resolvers/userResolver.ts b/src/resolvers/userResolver.ts index 4159b2aa2..f3779148a 100644 --- a/src/resolvers/userResolver.ts +++ b/src/resolvers/userResolver.ts @@ -72,6 +72,17 @@ class EligibleUser { @ObjectType() class BatchMintingEligibleUserResponse { + @Field(_addresses => [String], { nullable: false }) + users: string[]; + + @Field(_total => Number, { nullable: false }) + total: number; + + @Field(_offset => Number, { nullable: false }) + skip: number; +} +@ObjectType() +class BatchMintingEligibleUserV2Response { @Field(_addresses => [EligibleUser], { nullable: false }) users: EligibleUser[]; @@ -174,6 +185,37 @@ export class UserResolver { } @Query(_returns => BatchMintingEligibleUserResponse) + async batchMintingEligibleUsers( + @Arg('limit', _type => Int, { nullable: true }) limit: number = 1000, + @Arg('skip', _type => Int, { nullable: true }) skip: number = 0, + @Arg('filterAddress', { nullable: true }) filterAddress: string, + ) { + let query = User.createQueryBuilder('user') + .select('user.walletAddress') + .where('user.acceptedToS = true') + .andWhere(':privadoRequestId = ANY (user.privadoVerifiedRequestIds)', { + privadoRequestId: PrivadoAdapter.privadoRequestId, + }); + if (filterAddress) { + query = query.andWhere(`LOWER("walletAddress") = :walletAddress`, { + walletAddress: filterAddress.toLowerCase(), + }); + } + + const response = await query + .orderBy('user.acceptedToSDate', 'ASC') + .take(limit) + .skip(skip) + .getManyAndCount(); + + return { + users: response[0].map((user: User) => user.walletAddress), + total: response[1], + skip, + }; + } + + @Query(_returns => BatchMintingEligibleUserV2Response) async batchMintingEligibleUsersV2( @Arg('limit', _type => Int, { nullable: true }) limit: number = 1000, @Arg('skip', _type => Int, { nullable: true }) skip: number = 0, diff --git a/test/graphqlQueries.ts b/test/graphqlQueries.ts index 05b115684..e5092380b 100644 --- a/test/graphqlQueries.ts +++ b/test/graphqlQueries.ts @@ -2120,7 +2120,17 @@ export const acceptedTermsOfService = ` export const batchMintingEligibleUsers = ` query ( $limit: Int, $skip: Int, $filterAddress: String) { - batchMintingEligibleUsers: batchMintingEligibleUsersV2(limit: $limit, skip: $skip, filterAddress: $filterAddress) { + batchMintingEligibleUsers(limit: $limit, skip: $skip, filterAddress: $filterAddress) { + users + total + skip + } + } +`; + +export const batchMintingEligibleUsersV2 = ` + query ( $limit: Int, $skip: Int, $filterAddress: String) { + batchMintingEligibleUsersV2(limit: $limit, skip: $skip, filterAddress: $filterAddress) { users { address kycType