Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,12 @@ type UserIDOInvestment @entity(immutable: false) {
blockTimestamp: BigInt!
}

type UserTotalSpent @entity(immutable: false) {
id: ID! # user address
user: Bytes! # address
totalSpent: BigInt! # uint256 - total amount invested across all IDOs
}

type TotalInvested @entity(immutable: false) {
id: ID!
poolId: BigInt! # uint256
Expand Down
16 changes: 15 additions & 1 deletion src/extendedEntities/investProvider.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BigInt, Bytes, log } from "@graphprotocol/graph-ts"
import { PoolData, TotalInvested, UserIDOInvestment } from "../../generated/schema"
import { PoolData, TotalInvested, UserIDOInvestment, UserTotalSpent } from "../../generated/schema"

export function updateTotalInvested(poolId: BigInt, amount: BigInt): void {
let totalInvested = TotalInvested.load(poolId.toHexString()) // id is string
Expand Down Expand Up @@ -46,3 +46,17 @@ export function updateInvestProviderPoolParams(poolId: BigInt, amount: BigInt):
poolData.save()
}
}

export function updateUserTotalSpent(user: Bytes, amount: BigInt): void {
let userTotalSpent = UserTotalSpent.load(user.toHex())

if (userTotalSpent == null) {
userTotalSpent = new UserTotalSpent(user.toHex())
userTotalSpent.user = user
userTotalSpent.totalSpent = amount
} else {
userTotalSpent.totalSpent = userTotalSpent.totalSpent.plus(amount)
}

userTotalSpent.save()
}
3 changes: 2 additions & 1 deletion src/invest-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
InvestNewPoolCreated,
UpdateParams,
} from "../generated/schema"
import { updateTotalInvested, createTotalInvested, updateUserIDOInvestment, updateInvestProviderPoolParams } from "./extendedEntities/investProvider"
import { updateTotalInvested, createTotalInvested, updateUserIDOInvestment, updateInvestProviderPoolParams, updateUserTotalSpent } from "./extendedEntities/investProvider"
import { updatePoolParams } from "./extendedEntities/poolData"

export function handleEIP712DomainChanged(
Expand Down Expand Up @@ -76,6 +76,7 @@ export function handleInvested(event: InvestedEvent): void {
updateUserIDOInvestment(event.params.poolId, event.params.user, event.params.amount, event.block.timestamp)
updateTotalInvested(event.params.poolId, event.params.amount)
updateInvestProviderPoolParams(event.params.poolId, event.params.amount)
updateUserTotalSpent(event.params.user, event.params.amount)
}

export function handleNewPoolCreated(event: NewPoolCreatedEvent): void {
Expand Down
82 changes: 82 additions & 0 deletions tests/invest-provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ describe("Describe entity assertions", () => {
"0x0000000000000000000000000000000000000002",
)
assert.fieldEquals("UserIDOInvestment", userId, "amount", "100")

// Test UserTotalSpent entity
assert.entityCount("UserTotalSpent", 1)
assert.fieldEquals(
"UserTotalSpent",
userHex,
"user",
"0x0000000000000000000000000000000000000002"
)
assert.fieldEquals("UserTotalSpent", userHex, "totalSpent", "100")
})
})

Expand Down Expand Up @@ -174,5 +184,77 @@ describe("UserIDOInvestment timestamp updates", () => {
assert.entityCount("UserIDOInvestment", 1)
assert.fieldEquals("UserIDOInvestment", id, "amount", "150")
assert.fieldEquals("UserIDOInvestment", id, "blockTimestamp", "2000")

// Test UserTotalSpent accumulation across multiple investments
let userHex = "0x0000000000000000000000000000000000000002"
Copy link

Copilot AI Jul 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hardcoded address string is duplicated from earlier in the test. Consider extracting this as a constant at the top of the test block to improve maintainability and reduce duplication.

Copilot uses AI. Check for mistakes.
assert.entityCount("UserTotalSpent", 1)
assert.fieldEquals("UserTotalSpent", userHex, "totalSpent", "150") // 100 + 50 = 150
})
})

describe("UserTotalSpent cross-IDO accumulation", () => {
beforeAll(() => {
// Create multiple pools and multiple users
let poolId1 = BigInt.fromI32(10)
let poolId2 = BigInt.fromI32(20)
let owner = Address.fromString("0x0000000000000000000000000000000000000001")
let poolAmount = BigInt.fromI32(1000)

// Create first pool
let newPoolCreatedEvent1 = createNewPoolCreatedEvent(poolId1, owner, poolAmount)
handleNewPoolCreated(newPoolCreatedEvent1)

// Create second pool
let newPoolCreatedEvent2 = createNewPoolCreatedEvent(poolId2, owner, poolAmount)
handleNewPoolCreated(newPoolCreatedEvent2)

// User A invests in both pools
let userA = Address.fromString("0x0000000000000000000000000000000000000003")
let amountA1 = BigInt.fromI32(100) // invest 100 in pool 10
let amountA2 = BigInt.fromI32(200) // invest 200 in pool 20

let investedEventA1 = createInvestedEvent(poolId1, userA, amountA1, BigInt.fromI32(1))
handleInvested(investedEventA1)

let investedEventA2 = createInvestedEvent(poolId2, userA, amountA2, BigInt.fromI32(2))
handleInvested(investedEventA2)

// User B invests only in pool 10
let userB = Address.fromString("0x0000000000000000000000000000000000000004")
let amountB1 = BigInt.fromI32(50) // invest 50 in pool 10

let investedEventB1 = createInvestedEvent(poolId1, userB, amountB1, BigInt.fromI32(3))
handleInvested(investedEventB1)
})

afterAll(() => {
clearStore()
})

test("UserTotalSpent accumulates correctly across multiple IDOs", () => {
let userAHex = "0x0000000000000000000000000000000000000003"
let userBHex = "0x0000000000000000000000000000000000000004"

// Should have 2 UserTotalSpent entities (userA and userB)
assert.entityCount("UserTotalSpent", 2)

// User A should have total spent = 100 + 200 = 300
assert.fieldEquals("UserTotalSpent", userAHex, "totalSpent", "300")
assert.fieldEquals("UserTotalSpent", userAHex, "user", userAHex)

// User B should have total spent = 50
assert.fieldEquals("UserTotalSpent", userBHex, "totalSpent", "50")
assert.fieldEquals("UserTotalSpent", userBHex, "user", userBHex)

// Check that UserIDOInvestment entities are created correctly
assert.entityCount("UserIDOInvestment", 3) // userA-pool10, userA-pool20, userB-pool10

let userAPool10Id = "0xa" + "-" + userAHex
let userAPool20Id = "0x14" + "-" + userAHex
let userBPool10Id = "0xa" + "-" + userBHex

assert.fieldEquals("UserIDOInvestment", userAPool10Id, "amount", "100")
assert.fieldEquals("UserIDOInvestment", userAPool20Id, "amount", "200")
assert.fieldEquals("UserIDOInvestment", userBPool10Id, "amount", "50")
})
})