From a2dc7454f808efe100fbd57e192f587612913445 Mon Sep 17 00:00:00 2001 From: KONFeature Date: Fri, 8 Nov 2024 16:48:50 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20More=20detailed=20campaign=20st?= =?UTF-8?q?ats?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ponder/src/api/admin.ts | 92 ++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 3 deletions(-) diff --git a/packages/ponder/src/api/admin.ts b/packages/ponder/src/api/admin.ts index 0c2a1a8..c7e7e68 100644 --- a/packages/ponder/src/api/admin.ts +++ b/packages/ponder/src/api/admin.ts @@ -1,5 +1,5 @@ import { ponder } from "@/generated"; -import { eq } from "@ponder/core"; +import { countDistinct, eq, inArray } from "@ponder/core"; import { type Address, isAddress } from "viem"; // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -78,6 +78,90 @@ ponder.get("/admin/:wallet/campaigns", async (ctx) => { }); // Get all the campaign stats for a wallet +ponder.get("/admin/:wallet/campaignsStats", async (ctx) => { + // Extract wallet + const wallet = ctx.req.param("wallet") as Address; + if (!isAddress(wallet)) { + return ctx.text("Invalid wallet address", 400); + } + + // Get the tables we will query + const { + ProductAdministrator, + Campaign, + ReferralCampaignStats, + InteractionEvent, + Product, + ProductInteractionContract, + } = ctx.tables; + + // Perform the sql query + const campaignsStats = await ctx.db + .select({ + productId: ProductAdministrator.productId, + isOwner: ProductAdministrator.isOwner, + roles: ProductAdministrator.roles, + id: Campaign.id, + bank: Campaign.bankingContractId, + totalInteractions: ReferralCampaignStats.totalInteractions, + openInteractions: ReferralCampaignStats.openInteractions, + readInteractions: ReferralCampaignStats.readInteractions, + referredInteractions: ReferralCampaignStats.referredInteractions, + createReferredLinkInteractions: + ReferralCampaignStats.createReferredLinkInteractions, + purchaseStartedInteractions: + ReferralCampaignStats.purchaseStartedInteractions, + purchaseCompletedInteractions: + ReferralCampaignStats.purchaseCompletedInteractions, + totalRewards: ReferralCampaignStats.totalRewards, + }) + .from(ProductAdministrator) + .innerJoin( + Campaign, + eq(ProductAdministrator.productId, Campaign.productId) + ) + .innerJoin( + ReferralCampaignStats, + eq(Campaign.id, ReferralCampaignStats.campaignId) + ) + .where(eq(ProductAdministrator.user, wallet)); + + // Get the unique wallet on this product + if (campaignsStats.length === 0) { + return ctx.json({ stats: [] }); + } + + // Get all the product ids for this admin + const campaignProductIds = campaignsStats.map((c) => c.productId); + const uniqueProductIds = [...new Set(campaignProductIds)]; + + // Get the total number of unique users per product + const totalPerProducts = await ctx.db + .select({ + productId: Product.id, + wallets: countDistinct(InteractionEvent.user), + }) + .from(InteractionEvent) + .innerJoin( + ProductInteractionContract, + eq(InteractionEvent.interactionId, ProductInteractionContract.id) + ) + .innerJoin( + Product, + eq(ProductInteractionContract.productId, Product.id) + ) + .where(inArray(Product.id, uniqueProductIds)) + .groupBy(Product.id); + + // Return the result as json + return ctx.json({ + stats: campaignsStats, + users: totalPerProducts, + }); +}); + +// Get all the campaign stats for a wallet +// todo: For legacy purpose only, to be removed once prod is updated ponder.get("/admin/:wallet/campaigns/stats", async (ctx) => { // Extract wallet const wallet = ctx.req.param("wallet") as Address; @@ -103,8 +187,10 @@ ponder.get("/admin/:wallet/campaigns/stats", async (ctx) => { referredInteractions: ReferralCampaignStats.referredInteractions, createReferredLinkInteractions: ReferralCampaignStats.createReferredLinkInteractions, - purchaseStartedInteractions: ReferralCampaignStats.purchaseStartedInteractions, - purchaseCompletedInteractions: ReferralCampaignStats.purchaseCompletedInteractions, + purchaseStartedInteractions: + ReferralCampaignStats.purchaseStartedInteractions, + purchaseCompletedInteractions: + ReferralCampaignStats.purchaseCompletedInteractions, totalRewards: ReferralCampaignStats.totalRewards, }) .from(ProductAdministrator) From 93e2ea6d4078ff964831dbaba1106f9d2d8e79c5 Mon Sep 17 00:00:00 2001 From: KONFeature Date: Fri, 8 Nov 2024 17:06:55 +0100 Subject: [PATCH 2/3] =?UTF-8?q?=E2=9C=A8=20Add=20name=20to=20campaign=20st?= =?UTF-8?q?ats?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ponder/src/api/admin.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/ponder/src/api/admin.ts b/packages/ponder/src/api/admin.ts index c7e7e68..fd8fcb5 100644 --- a/packages/ponder/src/api/admin.ts +++ b/packages/ponder/src/api/admin.ts @@ -102,6 +102,7 @@ ponder.get("/admin/:wallet/campaignsStats", async (ctx) => { isOwner: ProductAdministrator.isOwner, roles: ProductAdministrator.roles, id: Campaign.id, + name: Campaign.name, bank: Campaign.bankingContractId, totalInteractions: ReferralCampaignStats.totalInteractions, openInteractions: ReferralCampaignStats.openInteractions, From 4d50dfe1b5f99c46540e7f2b524ef365a4e74e76 Mon Sep 17 00:00:00 2001 From: KONFeature Date: Fri, 8 Nov 2024 17:27:04 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Simplify=20unique=20wa?= =?UTF-8?q?llets=20query?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ponder/src/api/admin.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/packages/ponder/src/api/admin.ts b/packages/ponder/src/api/admin.ts index fd8fcb5..a1e0bf6 100644 --- a/packages/ponder/src/api/admin.ts +++ b/packages/ponder/src/api/admin.ts @@ -91,7 +91,6 @@ ponder.get("/admin/:wallet/campaignsStats", async (ctx) => { Campaign, ReferralCampaignStats, InteractionEvent, - Product, ProductInteractionContract, } = ctx.tables; @@ -139,7 +138,7 @@ ponder.get("/admin/:wallet/campaignsStats", async (ctx) => { // Get the total number of unique users per product const totalPerProducts = await ctx.db .select({ - productId: Product.id, + productId: ProductInteractionContract.productId, wallets: countDistinct(InteractionEvent.user), }) .from(InteractionEvent) @@ -147,12 +146,8 @@ ponder.get("/admin/:wallet/campaignsStats", async (ctx) => { ProductInteractionContract, eq(InteractionEvent.interactionId, ProductInteractionContract.id) ) - .innerJoin( - Product, - eq(ProductInteractionContract.productId, Product.id) - ) - .where(inArray(Product.id, uniqueProductIds)) - .groupBy(Product.id); + .where(inArray(ProductInteractionContract.productId, uniqueProductIds)) + .groupBy(ProductInteractionContract.productId); // Return the result as json return ctx.json({