Skip to content

Commit

Permalink
✨ Add reward distribution indexing
Browse files Browse the repository at this point in the history
  • Loading branch information
KONFeature committed Jul 3, 2024
1 parent 1586ab8 commit e4fbaf0
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 1 deletion.
2 changes: 1 addition & 1 deletion ponder-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// This file enables type checking and editor autocomplete for this Ponder project.
// After upgrading, you may find that changes have been made to this file.
// If this happens, please commit the changes. Do not manually edit this file.
// See https://ponder.sh/docs/guides/typescript for more information.
// See https://ponder.sh/docs/getting-started/installation#typescript for more information.

declare module "@/generated" {
import type { Virtual } from "@ponder/core";
Expand Down
49 changes: 49 additions & 0 deletions ponder.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default createSchema((p) => ({
// The linked webauthn validators
validators: p.many("MultiWebAuthNValidator.accountId"),
}),

// Validator we are tracking
MultiWebAuthNValidator: p.createTable({
// Id is a concatenation of chain + account address
Expand Down Expand Up @@ -142,4 +143,52 @@ export default createSchema((p) => ({
}),

PressEventType: p.createEnum(["OPEN_ARTICLE", "READ_ARTICLE", "REFERRED"]),

// Rewards related stuff
RewardingContract: p.createTable({
// Address of the rewarding contract
id: p.hex(),

// Address of the token that will be distributed
token: p.hex(),

// All the rewards
rewards: p.many("Reward.contractId"),
}),
Reward: p.createTable({
id: p.string(), // reward contract + user

contractId: p.hex().references("RewardingContract.id"),
contract: p.one("contractId"),

user: p.hex(),

pendingAmount: p.bigint(),
totalAmount: p.bigint(),

rewardAddedEvents: p.many("RewardAddedEvent.rewardId"),
rewardClaimedEvents: p.many("RewardClaimedEvent.rewardId"),
}),
RewardAddedEvent: p.createTable({
id: p.string(),

rewardId: p.string().references("Reward.id"),
reward: p.one("rewardId"),

amount: p.bigint(),

txHash: p.hex(),
timestamp: p.bigint(),
}),
RewardClaimedEvent: p.createTable({
id: p.string(),

rewardId: p.string().references("Reward.id"),
reward: p.one("rewardId"),

amount: p.bigint(),

txHash: p.hex(),
timestamp: p.bigint(),
}),
}));
112 changes: 112 additions & 0 deletions src/campaignReward.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { type Context, ponder } from "@/generated";
import type { Address } from "viem";
import { referralCampaignAbi } from "../abis/frak-campaign-abis";

ponder.on("Campaigns:RewardAdded", async ({ event, context }) => {
const { Reward, RewardAddedEvent } = context.db;

// Try to find a rewarding contract for the given event emitter
const rewardingContract = await getRewardingContract({
contract: event.log.address,
context,
});

// Update the current user reward (insert it if not found)
const rewardId = `${event.log.address}-${event.args.user}`;
await Reward.upsert({
id: rewardId,
create: {
contractId: rewardingContract.id,
user: event.args.user,
pendingAmount: event.args.amount,
totalAmount: event.args.amount,
},
update: ({ current }) => ({
pendingAmount: current.pendingAmount + event.args.amount,
totalAmount: current.totalAmount + event.args.amount,
}),
});

// Insert the reward event
await RewardAddedEvent.create({
id: event.log.id,
data: {
rewardId,
amount: event.args.amount,
txHash: event.log.transactionHash,
timestamp: event.block.timestamp,
},
});
});

ponder.on("Campaigns:RewardClaimed", async ({ event, context }) => {
const { Reward, RewardClaimedEvent } = context.db;

// Try to find a rewarding contract for the given event emitter
const rewardingContract = await getRewardingContract({
contract: event.log.address,
context,
});

// Update the current user reward (insert it if not found)
const rewardId = `${event.log.address}-${event.args.user}`;
await Reward.upsert({
id: rewardId,
create: {
contractId: rewardingContract.id,
user: event.args.user,
pendingAmount: -event.args.amount,
totalAmount: 0n,
},
update: ({ current }) => ({
pendingAmount: current.pendingAmount - event.args.amount,
}),
});

// Insert the reward event
await RewardClaimedEvent.create({
id: event.log.id,
data: {
rewardId,
amount: event.args.amount,
txHash: event.log.transactionHash,
timestamp: event.block.timestamp,
},
});
});

/**
* Get the rewarding contract for the given event emitter
* @param contract
* @param context
*/
async function getRewardingContract({
contract,
context,
}: {
contract: Address;
context: Context;
}) {
const { RewardingContract } = context.db;
// Try to find a rewarding contract for the given event emitter
let rewardingContract = await RewardingContract.findUnique({
id: contract,
});
if (!rewardingContract) {
// If not found, find the token of this campaign
const { token } = await context.client.readContract({
abi: referralCampaignAbi,
address: contract,
functionName: "getConfig",
});

rewardingContract = await RewardingContract.create({
id: contract,
data: {
token,
},
});
}

return rewardingContract;
}

0 comments on commit e4fbaf0

Please sign in to comment.