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
65 changes: 59 additions & 6 deletions packages/subgraph/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ type GraphNetwork @entity(immutable: false) {
# Counts
"Active service providers"
countServiceProviders: Int!
"Active data services (verifiers)"
countDataServices: Int!
"Active provisions"
countProvisions: Int!
"Active delegation pools"
Expand Down Expand Up @@ -90,15 +92,66 @@ type ServiceProvider @entity(immutable: false) {
updatedAt: BigInt!
}

type DataService @entity(immutable: false) {
"Data service (verifier) contract address"
id: Bytes!

# Relationships
"Provisions for this data service"
provisions: [Provision!]! @derivedFrom(field: "dataService")
"Delegation pools for this data service"
delegationPools: [DelegationPool!]! @derivedFrom(field: "dataService")

# Counts
"Active service providers with provisions to this data service"
countServiceProviders: Int!
"Active provisions"
countProvisions: Int!
"Active delegation pools"
countDelegationPools: Int!
"Provision slash events"
countProvisionSlashEvents: Int!
"Delegation pool slash events"
countDelegationPoolSlashEvents: Int!

# Tokens
"Total tokens provisioned to this data service"
tokensProvisioned: BigInt!
"Total tokens delegated to service providers for this data service"
tokensDelegated: BigInt!
"Tokens currently thawing from provisions"
tokensThawingFromProvisions: BigInt!
"Tokens currently thawing from delegation pools"
tokensThawingFromDelegationPools: BigInt!

# Slashing
"Total tokens slashed"
tokensSlashed: BigInt!
"Tokens slashed from provisions"
tokensSlashedFromProvisions: BigInt!
"Tokens slashed from delegation pools"
tokensSlashedFromDelegationPools: BigInt!

# Metadata
"Block number when entity was created"
createdAtBlock: BigInt!
"Timestamp when entity was created"
createdAt: BigInt!
"Block number when entity was last updated"
updatedAtBlock: BigInt!
"Timestamp when entity was last updated"
updatedAt: BigInt!
}

type DelegationPool @entity(immutable: false) {
"Composite ID: serviceProvider-verifier"
"Composite ID: serviceProvider-dataService"
id: Bytes!

# Relationships
"Service provider that owns this pool"
serviceProvider: ServiceProvider!
"Verifier address (data service)"
verifier: Bytes!
"Data service (verifier)"
dataService: DataService!

# Pool state
"Total tokens in the pool"
Expand All @@ -124,14 +177,14 @@ type DelegationPool @entity(immutable: false) {
}

type Provision @entity(immutable: false) {
"Composite ID: serviceProvider-verifier"
"Composite ID: serviceProvider-dataService"
id: Bytes!

# Relationships
"Service provider that created this provision"
serviceProvider: ServiceProvider!
"Verifier address (data service)"
verifier: Bytes!
"Data service (verifier)"
dataService: DataService!

# Tokens
"Tokens currently provisioned"
Expand Down
58 changes: 58 additions & 0 deletions packages/subgraph/src/entities/dataService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts"
import { DataService } from "../../generated/schema"
import { BIGINT_ZERO } from "../common/constants"

export class DataServiceResult {
entity: DataService
isNew: boolean

constructor(entity: DataService, isNew: boolean) {
this.entity = entity
this.isNew = isNew
}
}

export function getOrCreateDataService(
id: Bytes,
blockNumber: BigInt,
timestamp: BigInt
): DataServiceResult {
let entity = DataService.load(id)
let isNew = entity == null

if (entity == null) {
entity = new DataService(id)

// Counts
entity.countServiceProviders = 0
entity.countProvisions = 0
entity.countDelegationPools = 0
entity.countProvisionSlashEvents = 0
entity.countDelegationPoolSlashEvents = 0

// Tokens
entity.tokensProvisioned = BIGINT_ZERO
entity.tokensDelegated = BIGINT_ZERO
entity.tokensThawingFromProvisions = BIGINT_ZERO
entity.tokensThawingFromDelegationPools = BIGINT_ZERO

// Slashing
entity.tokensSlashed = BIGINT_ZERO
entity.tokensSlashedFromProvisions = BIGINT_ZERO
entity.tokensSlashedFromDelegationPools = BIGINT_ZERO

// Metadata
entity.createdAtBlock = blockNumber
entity.createdAt = timestamp
entity.updatedAtBlock = blockNumber
entity.updatedAt = timestamp
}

return new DataServiceResult(entity, isNew)
}

export function saveDataService(ds: DataService, block: ethereum.Block): void {
ds.updatedAtBlock = block.number
ds.updatedAt = block.timestamp
ds.save()
}
10 changes: 5 additions & 5 deletions packages/subgraph/src/entities/delegationPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts"
import { DelegationPool } from "../../generated/schema"
import { BIGINT_ZERO } from "../common/constants"

export function getDelegationPoolId(serviceProvider: Bytes, verifier: Bytes): Bytes {
return serviceProvider.concat(verifier)
export function getDelegationPoolId(serviceProvider: Bytes, dataService: Bytes): Bytes {
return serviceProvider.concat(dataService)
}

export class DelegationPoolResult {
Expand All @@ -23,18 +23,18 @@ export class DelegationPoolResult {
*/
export function getOrCreateDelegationPool(
serviceProvider: Bytes,
verifier: Bytes,
dataService: Bytes,
blockNumber: BigInt,
timestamp: BigInt
): DelegationPoolResult {
let id = getDelegationPoolId(serviceProvider, verifier)
let id = getDelegationPoolId(serviceProvider, dataService)
let entity = DelegationPool.load(id)
let isNew = entity == null

if (entity == null) {
entity = new DelegationPool(id)
entity.serviceProvider = serviceProvider
entity.verifier = verifier
entity.dataService = dataService
entity.tokens = BIGINT_ZERO
entity.shares = BIGINT_ZERO
entity.tokensThawing = BIGINT_ZERO
Expand Down
1 change: 1 addition & 0 deletions packages/subgraph/src/entities/graphNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export function getOrCreateGraphNetwork(): GraphNetwork {

// Counts
entity.countServiceProviders = 0
entity.countDataServices = 0
entity.countProvisions = 0
entity.countDelegationPools = 0
entity.countProvisionSlashEvents = 0
Expand Down
10 changes: 5 additions & 5 deletions packages/subgraph/src/entities/provision.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts"
import { Provision } from "../../generated/schema"
import { BIGINT_ZERO } from "../common/constants"

export function getProvisionId(serviceProvider: Bytes, verifier: Bytes): Bytes {
return serviceProvider.concat(verifier)
export function getProvisionId(serviceProvider: Bytes, dataService: Bytes): Bytes {
return serviceProvider.concat(dataService)
}

export class ProvisionResult {
Expand All @@ -18,18 +18,18 @@ export class ProvisionResult {

export function getOrCreateProvision(
serviceProvider: Bytes,
verifier: Bytes,
dataService: Bytes,
blockNumber: BigInt,
timestamp: BigInt
): ProvisionResult {
let id = getProvisionId(serviceProvider, verifier)
let id = getProvisionId(serviceProvider, dataService)
let entity = Provision.load(id)
let isNew = entity == null

if (entity == null) {
entity = new Provision(id)
entity.serviceProvider = serviceProvider
entity.verifier = verifier
entity.dataService = dataService
entity.tokens = BIGINT_ZERO
entity.tokensThawing = BIGINT_ZERO
entity.maxVerifierCut = BIGINT_ZERO
Expand Down
45 changes: 45 additions & 0 deletions packages/subgraph/src/handlers/delegation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "../../generated/HorizonStaking/HorizonStaking"
import { getOrCreateGraphNetwork, saveGraphNetwork } from "../entities/graphNetwork"
import { getOrCreateServiceProvider, saveServiceProvider } from "../entities/serviceProvider"
import { getOrCreateDataService, saveDataService } from "../entities/dataService"
import { getOrCreateDelegationPool, saveDelegationPool } from "../entities/delegationPool"
import { BIGINT_ZERO } from "../common/constants"

Expand Down Expand Up @@ -35,6 +36,15 @@ export function handleTokensDelegated(event: TokensDelegated): void {
pool.entity.shares = pool.entity.shares.plus(shares)
saveDelegationPool(pool.entity, event.block)

// Update DataService
let dataService = getOrCreateDataService(verifierBytes, event.block.number, event.block.timestamp)
assert(!dataService.isNew, "Data service does not exist.")
dataService.entity.tokensDelegated = dataService.entity.tokensDelegated.plus(tokens)
if (pool.isNew) {
dataService.entity.countDelegationPools += 1
}
saveDataService(dataService.entity, event.block)

// Update ServiceProvider
let serviceProvider = getOrCreateServiceProvider(serviceProviderBytes, event.block.number, event.block.timestamp)
assert(!serviceProvider.isNew, "Service provider does not exist.")
Expand Down Expand Up @@ -76,6 +86,12 @@ export function handleTokensUndelegated(event: TokensUndelegated): void {
pool.entity.tokensThawing = pool.entity.tokensThawing.plus(tokens)
saveDelegationPool(pool.entity, event.block)

// Update DataService
let dataService = getOrCreateDataService(verifierBytes, event.block.number, event.block.timestamp)
assert(!dataService.isNew, "Data service does not exist.")
dataService.entity.tokensThawingFromDelegationPools = dataService.entity.tokensThawingFromDelegationPools.plus(tokens)
saveDataService(dataService.entity, event.block)

// Update ServiceProvider
let serviceProvider = getOrCreateServiceProvider(serviceProviderBytes, event.block.number, event.block.timestamp)
assert(!serviceProvider.isNew, "Service provider does not exist.")
Expand Down Expand Up @@ -114,6 +130,19 @@ export function handleDelegatedTokensWithdrawn(event: DelegatedTokensWithdrawn):
pool.entity.tokensThawing = pool.entity.tokensThawing.minus(tokens)
saveDelegationPool(pool.entity, event.block)

// Update DataService
let dataService = getOrCreateDataService(verifierBytes, event.block.number, event.block.timestamp)
assert(!dataService.isNew, "Data service does not exist.")
assert(dataService.entity.tokensThawingFromDelegationPools >= tokens, "Withdraw tokens exceed data service tokens thawing.")
dataService.entity.tokensThawingFromDelegationPools = dataService.entity.tokensThawingFromDelegationPools.minus(tokens)
assert(dataService.entity.tokensDelegated >= tokens, "Withdraw tokens exceed data service tokens delegated.")
dataService.entity.tokensDelegated = dataService.entity.tokensDelegated.minus(tokens)
if (pool.entity.tokens.equals(BIGINT_ZERO)) {
assert(dataService.entity.countDelegationPools > 0, "Data service delegation pool count is zero.")
dataService.entity.countDelegationPools -= 1
}
saveDataService(dataService.entity, event.block)

// Update ServiceProvider
let serviceProvider = getOrCreateServiceProvider(serviceProviderBytes, event.block.number, event.block.timestamp)
assert(!serviceProvider.isNew, "Service provider does not exist.")
Expand Down Expand Up @@ -160,6 +189,16 @@ export function handleDelegationSlashed(event: DelegationSlashed): void {
pool.entity.tokens = pool.entity.tokens.minus(tokens)
saveDelegationPool(pool.entity, event.block)

// Update DataService
let dataService = getOrCreateDataService(verifierBytes, event.block.number, event.block.timestamp)
assert(!dataService.isNew, "Data service does not exist.")
assert(dataService.entity.tokensDelegated >= tokens, "Slash tokens exceed data service tokens delegated.")
dataService.entity.tokensDelegated = dataService.entity.tokensDelegated.minus(tokens)
dataService.entity.countDelegationPoolSlashEvents += 1
dataService.entity.tokensSlashed = dataService.entity.tokensSlashed.plus(tokens)
dataService.entity.tokensSlashedFromDelegationPools = dataService.entity.tokensSlashedFromDelegationPools.plus(tokens)
saveDataService(dataService.entity, event.block)

// Update ServiceProvider
let serviceProvider = getOrCreateServiceProvider(serviceProviderBytes, event.block.number, event.block.timestamp)
assert(!serviceProvider.isNew, "Service provider does not exist.")
Expand Down Expand Up @@ -203,6 +242,12 @@ export function handleTokensToDelegationPoolAdded(event: TokensToDelegationPoolA
pool.entity.tokens = pool.entity.tokens.plus(tokens)
saveDelegationPool(pool.entity, event.block)

// Update DataService
let dataService = getOrCreateDataService(verifierBytes, event.block.number, event.block.timestamp)
assert(!dataService.isNew, "Data service does not exist.")
dataService.entity.tokensDelegated = dataService.entity.tokensDelegated.plus(tokens)
saveDataService(dataService.entity, event.block)

// Update ServiceProvider
let serviceProvider = getOrCreateServiceProvider(serviceProviderBytes, event.block.number, event.block.timestamp)
assert(!serviceProvider.isNew, "Service provider does not exist.")
Expand Down
32 changes: 21 additions & 11 deletions packages/subgraph/src/handlers/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from "../../generated/HorizonStaking/HorizonStaking"
import { getOrCreateGraphNetwork, saveGraphNetwork } from "../entities/graphNetwork"
import { getOrCreateServiceProvider, saveServiceProvider } from "../entities/serviceProvider"
import { getOrCreateDataService, saveDataService } from "../entities/dataService"
import { getOrCreateDelegationPool, saveDelegationPool } from "../entities/delegationPool"
import { config } from "../config"

Expand Down Expand Up @@ -33,12 +34,12 @@ export function handleRebateCollected(event: RebateCollected): void {
}

let indexerBytes = Bytes.fromHexString(indexer.toHexString()) as Bytes
let verifier = Bytes.fromHexString(config.subgraphServiceAddress.toHexString()) as Bytes
let dataServiceBytes = Bytes.fromHexString(config.subgraphServiceAddress.toHexString()) as Bytes

// Update legacy DelegationPool
let pool = getOrCreateDelegationPool(
indexerBytes,
verifier,
dataServiceBytes,
event.block.number,
event.block.timestamp
)
Expand All @@ -49,11 +50,15 @@ export function handleRebateCollected(event: RebateCollected): void {
pool.entity.tokens = pool.entity.tokens.plus(delegationRewards)
saveDelegationPool(pool.entity, event.block)

// Update DataService
let dataService = getOrCreateDataService(dataServiceBytes, event.block.number, event.block.timestamp)
assert(!dataService.isNew, "Data service does not exist.")
dataService.entity.tokensDelegated = dataService.entity.tokensDelegated.plus(delegationRewards)
saveDataService(dataService.entity, event.block)

// Update ServiceProvider
let serviceProvider = getOrCreateServiceProvider(indexerBytes, event.block.number, event.block.timestamp)
if (serviceProvider.isNew) {
return
}
assert(!serviceProvider.isNew, "Service provider does not exist.")
serviceProvider.entity.tokensDelegated = serviceProvider.entity.tokensDelegated.plus(delegationRewards)
saveServiceProvider(serviceProvider.entity, event.block)

Expand Down Expand Up @@ -115,12 +120,12 @@ export function handleAllocationClosed(event: AllocationClosed): void {
return
}

let verifier = Bytes.fromHexString(config.subgraphServiceAddress.toHexString()) as Bytes
let dataServiceBytes = Bytes.fromHexString(config.subgraphServiceAddress.toHexString()) as Bytes

// Get the legacy DelegationPool to read the indexer's reward cut
let pool = getOrCreateDelegationPool(
indexerBytes,
verifier,
dataServiceBytes,
event.block.number,
event.block.timestamp
)
Expand All @@ -144,12 +149,17 @@ export function handleAllocationClosed(event: AllocationClosed): void {
pool.entity.tokens = pool.entity.tokens.plus(delegationRewards)
saveDelegationPool(pool.entity, event.block)

// Update DataService
let dataService = getOrCreateDataService(dataServiceBytes, event.block.number, event.block.timestamp)
assert(!dataService.isNew, "Data service does not exist.")
dataService.entity.tokensDelegated = dataService.entity.tokensDelegated.plus(delegationRewards)
saveDataService(dataService.entity, event.block)

// Update ServiceProvider
let serviceProvider = getOrCreateServiceProvider(indexerBytes, event.block.number, event.block.timestamp)
if (!serviceProvider.isNew) {
serviceProvider.entity.tokensDelegated = serviceProvider.entity.tokensDelegated.plus(delegationRewards)
saveServiceProvider(serviceProvider.entity, event.block)
}
assert(!serviceProvider.isNew, "Service provider does not exist.")
serviceProvider.entity.tokensDelegated = serviceProvider.entity.tokensDelegated.plus(delegationRewards)
saveServiceProvider(serviceProvider.entity, event.block)

// Update GraphNetwork
let graphNetwork = getOrCreateGraphNetwork()
Expand Down
Loading
Loading