Skip to content

Commit

Permalink
Cleanup Epoch and EpochStake schema's entities
Browse files Browse the repository at this point in the history
GraphQL schema changes:

- Epoch counter's unique entity ID Singleton have been replaced by
epoch-counter to have a more meaningful name.
- EpochStake entities only contains the fields staking provider address
and amount. participation and stakeData fields have been removed to
avoid redundant data.
- The timestamp field name of an epoch have been replaced by
timestamp. The total amount of token staked in a epoch entity is
saved in totalAmount field (previously totalStaked).
- Now, the first epoch (number 0) is the period between the token
staking contract deployment and the first staking event.
- Comments format have been homogenized.

Src files changes:

- Added src/utils/epochs.ts code with some utilities related to the
management of the epochs and its counter.
- Modified HandleStaked function in mapping.ts to follow the new schema
(handleToppedUp and handleUnstaked are pending).
- Unstaked handle function adapted to new schema
- ToppedUp handle function adapted to new schema
  • Loading branch information
manumonti committed Jun 8, 2022
1 parent 8ea5e6c commit 61b986a
Show file tree
Hide file tree
Showing 5 changed files with 799 additions and 861 deletions.
22 changes: 12 additions & 10 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type Account @entity {
}

type StakeData @entity {
# Staking provider address.
# ID is the staking provider address
id: ID!
owner: Account!
stakeType: StakeType!
Expand All @@ -27,17 +27,18 @@ type StakeData @entity {
}

type EpochStake @entity {
id: ID! # staking prov add + epoch counter
stakeData: StakeData!
# ID is the staking prov. add. + epoch counter
id: ID!
stakingProvider: Bytes! # address
amount: BigInt!
participation: BigDecimal
}

type Epoch @entity {
id: ID! # epoch counter
startTime: BigInt!
# ID is a counter starting 0
id: ID!
timestamp: BigInt!
duration: BigInt
totalStaked: BigInt!
totalAmount: BigInt!
stakes: [EpochStake!]!
}

Expand All @@ -49,6 +50,7 @@ type MinStakeAmount @entity {
}

type EpochCounter @entity {
# Singleton entity, id = epoch-counter
id: ID!
count: Int!
}
Expand All @@ -60,14 +62,14 @@ interface Delegation {
}

type StakeDelegation implements Delegation @entity {
# The delegatee address
# ID is the delegatee address
id: ID!
totalWeight: BigInt!
stakeDelegators: [StakeData!] @derivedFrom(field: "delegatee")
}

type TokenholderDelegation implements Delegation @entity {
# The delegatee address
# ID is the delegatee address
id: ID!
# The voting weight from the snapshot mechanism in the token and staking
# contracts. For Tokenholder DAO, there are currently two voting power
Expand All @@ -89,7 +91,7 @@ type ConfirmedOperator @entity {
}

type DAOMetric @entity {
"Singleton entity, id = dao-metrics"
# Singleton entity, id = dao-metrics
id: ID!
liquidTotal: BigInt!
stakedTotal: BigInt!
Expand Down
235 changes: 65 additions & 170 deletions src/mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
} from "../generated/TokenStaking/TokenStaking"
import {
StakeData,
EpochCounter,
Epoch,
EpochStake,
ConfirmedOperator,
Expand All @@ -20,20 +19,20 @@ import {
} from "../generated/schema"
import {
getDaoMetric,
getEpochCount,
getEpochStakeId,
populateNewEpochStakes,
getOrCreateLastEpoch,
increaseEpochCount,
getOrCreateStakeDelegation,
getOrCreateTokenholderDelegation,
} from "./utils"

export function handleStaked(event: Staked): void {
const blockTimestamp = event.block.timestamp

let epochCounter = EpochCounter.load("Singleton")
if (!epochCounter) {
epochCounter = new EpochCounter("Singleton")
epochCounter.count = 0
}
const stakingProvider = event.params.stakingProvider
const stakeAmount = event.params.amount

const stakeData = new StakeData(event.params.stakingProvider.toHexString())
const stakeData = new StakeData(stakingProvider.toHexString())
let type: string
switch (event.params.stakeType) {
case 0:
Expand All @@ -52,7 +51,6 @@ export function handleStaked(event: Staked): void {
account.save()
}

const stakeAmount = event.params.amount
stakeData.stakeType = type
stakeData.owner = account.id
stakeData.beneficiary = event.params.beneficiary
Expand All @@ -65,62 +63,29 @@ export function handleStaked(event: Staked): void {
.plus(stakeData.nuInTStake)
stakeData.save()

const lastEpochId = (epochCounter.count - 1).toString()
const lastEpoch = Epoch.load(lastEpochId)

const totalStaked = lastEpoch
? lastEpoch.totalStaked.plus(event.params.amount)
: event.params.amount
let epochStakes: string[] = []

if (lastEpoch) {
lastEpoch.duration = blockTimestamp.minus(lastEpoch.startTime)
lastEpoch.save()

epochStakes = lastEpoch.stakes
for (let i = 0; i < epochStakes.length; i++) {
const epochStake = EpochStake.load(epochStakes[i])
const epStId = crypto
.keccak256(
ByteArray.fromUTF8(
epochStake!.stakeData + epochCounter.count.toString()
)
)
.toHexString()
epochStake!.id = epStId
epochStake!.participation = epochStake!.amount.divDecimal(
totalStaked.toBigDecimal()
)
epochStake!.save()
epochStakes[i] = epochStake!.id
}
}

const epStId = crypto
.keccak256(ByteArray.fromUTF8(stakeData.id + epochCounter.count.toString()))
.toHexString()
const newEpochStake = new EpochStake(epStId)
newEpochStake.stakeData = stakeData.id
newEpochStake.amount = event.params.amount
newEpochStake.participation = newEpochStake.amount.divDecimal(
totalStaked.toBigDecimal()
)
newEpochStake.save()

epochStakes.push(newEpochStake.id)

const epoch = new Epoch(epochCounter.count.toString())
epoch.startTime = blockTimestamp
epoch.totalStaked = totalStaked
const lastEpoch = getOrCreateLastEpoch()
const timestamp = event.block.timestamp
lastEpoch.duration = timestamp.minus(lastEpoch.timestamp)
lastEpoch.save()

const epochStakes = populateNewEpochStakes(lastEpoch.stakes)
const epochStakeId = getEpochStakeId(stakingProvider.toHexString())
const epochStake = new EpochStake(epochStakeId)
epochStake.stakingProvider = stakingProvider
epochStake.amount = stakeAmount
epochStake.save()
epochStakes.push(epochStake.id)

const epoch = new Epoch(getEpochCount().toString())
epoch.timestamp = timestamp
epoch.totalAmount = lastEpoch.totalAmount.plus(stakeAmount)
epoch.stakes = epochStakes
epoch.save()

epochCounter.count++
epochCounter.save()
increaseEpochCount()
}

export function handleToppedUp(event: ToppedUp): void {
const blockTimestamp = event.block.timestamp
const stakingProvider = event.params.stakingProvider
const amount = event.params.amount

Expand All @@ -147,10 +112,8 @@ export function handleToppedUp(event: ToppedUp): void {
.substring(0, 10)
)

const stakeData = StakeData.load(
event.params.stakingProvider.toHexString()
) as StakeData
stakeData.totalStaked = stakeData.totalStaked.plus(event.params.amount)
const stakeData = StakeData.load(stakingProvider.toHexString()) as StakeData
stakeData.totalStaked = stakeData.totalStaked.plus(amount)

if (topUpFunctionId.equals(topUpTFunctionId)) {
stakeData.tStake = stakeData.tStake.plus(amount)
Expand All @@ -170,79 +133,39 @@ export function handleToppedUp(event: ToppedUp): void {
}
stakeData.save()

const epochCounter = EpochCounter.load("Singleton")
const lastEpochId = (epochCounter!.count - 1).toString()
const lastEpoch = Epoch.load(lastEpochId)

const totalStaked = lastEpoch!.totalStaked.plus(event.params.amount)
let stakeInPreviousEpoch = false
let epochStakes: string[] = []

lastEpoch!.duration = blockTimestamp.minus(lastEpoch!.startTime)
lastEpoch!.save()

epochStakes = lastEpoch!.stakes
for (let i = 0; i < epochStakes.length; i++) {
const epochStake = EpochStake.load(epochStakes[i])
const epStId = crypto
.keccak256(
ByteArray.fromUTF8(
epochStake!.stakeData + epochCounter!.count.toString()
)
)
.toHexString()
epochStake!.id = epStId

// If this stake is the one to be topped up, increase the amount
if (epochStake!.stakeData == event.params.stakingProvider.toHexString()) {
stakeInPreviousEpoch = true
epochStake!.amount = epochStake!.amount.plus(event.params.amount)
}

epochStake!.participation = epochStake!.amount.divDecimal(
totalStaked.toBigDecimal()
)
epochStake!.save()
epochStakes[i] = epochStake!.id
const lastEpoch = getOrCreateLastEpoch()
const timestamp = event.block.timestamp
lastEpoch.duration = timestamp.minus(lastEpoch.timestamp)
lastEpoch.save()

const epochStakes = populateNewEpochStakes(lastEpoch.stakes)
const epochStakeId = getEpochStakeId(stakingProvider.toHexString())
let epochStake = EpochStake.load(epochStakeId)
if (!epochStake) {
epochStake = new EpochStake(epochStakeId)
epochStake.stakingProvider = stakingProvider
epochStake.amount = BigInt.zero()
epochStakes.push(epochStake.id)
}
epochStake.amount = epochStake.amount.plus(amount)
epochStake.save()

// If the topped-up-stake is not in the previous epoch, add it
if (!stakeInPreviousEpoch) {
const epStId = crypto
.keccak256(
ByteArray.fromUTF8(
event.params.stakingProvider.toHexString() +
epochCounter!.count.toString()
)
)
.toHexString()
const newEpochStake = new EpochStake(epStId)
newEpochStake.stakeData = event.params.stakingProvider.toHexString()
newEpochStake.amount = event.params.amount
newEpochStake.participation = newEpochStake.amount.divDecimal(
totalStaked.toBigDecimal()
)
newEpochStake.save()
epochStakes.push(newEpochStake.id)
}

const epoch = new Epoch(epochCounter!.count.toString())
epoch.startTime = blockTimestamp
epoch.totalStaked = totalStaked
const epoch = new Epoch(getEpochCount().toString())
epoch.timestamp = timestamp
epoch.totalAmount = lastEpoch.totalAmount.minus(amount)
epoch.stakes = epochStakes
epoch.save()

epochCounter!.count++
epochCounter!.save()
increaseEpochCount()
}

export function handleUnstaked(event: Unstaked): void {
const blockTimestamp = event.block.timestamp
const stakingProvider = event.params.stakingProvider
const amount = event.params.amount

const unstakeFunctionId = ByteArray.fromHexString(
event.transaction.input.toHexString().substring(0, 10)
)
const stakingProvider = event.params.stakingProvider
const amount = event.params.amount

const unstakeTFunctionId = ByteArray.fromHexString(
crypto
Expand Down Expand Up @@ -292,57 +215,29 @@ export function handleUnstaked(event: Unstaked): void {
stakeData.keepInTStake = stakes.value1
stakeData.nuInTStake = stakes.value2
}

stakeData.save()

const epochCounter = EpochCounter.load("Singleton")
const lastEpochId = (epochCounter!.count - 1).toString()
const lastEpoch = Epoch.load(lastEpochId)

const totalStaked = lastEpoch!.totalStaked.minus(event.params.amount)
let emptyStakeArrayIndex: i32 = -1
let epochStakes: string[] = []

lastEpoch!.duration = blockTimestamp.minus(lastEpoch!.startTime)
lastEpoch!.save()

epochStakes = lastEpoch!.stakes
for (let i = 0; i < epochStakes.length; i++) {
const epochStake = EpochStake.load(epochStakes[i])
const epStId = crypto
.keccak256(
ByteArray.fromUTF8(
epochStake!.stakeData + epochCounter!.count.toString()
)
)
.toHexString()
epochStake!.id = epStId

// If this stake is the one to be unstaked, decrease the amount
if (epochStake!.stakeData == event.params.stakingProvider.toHexString()) {
epochStake!.amount = epochStake!.amount.minus(event.params.amount)
emptyStakeArrayIndex = epochStake!.amount.isZero() ? i : -1
}

epochStake!.participation = epochStake!.amount.divDecimal(
totalStaked.toBigDecimal()
)
epochStake!.save()
epochStakes[i] = epochStake!.id
}

if (emptyStakeArrayIndex >= 0) {
epochStakes.splice(emptyStakeArrayIndex, 1)
const lastEpoch = getOrCreateLastEpoch()
const timestamp = event.block.timestamp
lastEpoch.duration = timestamp.minus(lastEpoch.timestamp)
lastEpoch.save()

const epochStakes = populateNewEpochStakes(lastEpoch.stakes)
const epochStakeId = getEpochStakeId(stakingProvider.toHexString())
const epochStake = EpochStake.load(epochStakeId)
epochStake!.amount = epochStake!.amount.minus(amount)
epochStake!.save()
if (epochStake!.amount.isZero()) {
epochStakes.splice(epochStakes.indexOf(epochStakeId), 1)
}

const epoch = new Epoch(epochCounter!.count.toString())
epoch.startTime = blockTimestamp
epoch.totalStaked = totalStaked
const epoch = new Epoch(getEpochCount().toString())
epoch.timestamp = timestamp
epoch.totalAmount = lastEpoch.totalAmount.minus(amount)
epoch.stakes = epochStakes
epoch.save()

epochCounter!.count++
epochCounter!.save()
increaseEpochCount()
}

export function handleDelegateChanged(event: DelegateChanged): void {
Expand Down
Loading

0 comments on commit 61b986a

Please sign in to comment.