From 2a949cd4490a30f79384687240d314be446fd3dc Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 31 Dec 2020 14:20:55 +0530 Subject: [PATCH 01/10] new: handler method for startauction event --- root/schema.graphql | 2 ++ root/src/mappings/staking-info.ts | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/root/schema.graphql b/root/schema.graphql index 5f27f23..0165f50 100644 --- a/root/schema.graphql +++ b/root/schema.graphql @@ -82,6 +82,8 @@ type Validator @entity { nonce: BigInt! unstaked: Boolean! jailEndEpoch: BigInt! + : BigInt! + isInAuction: Bool! } type Delegator @entity { diff --git a/root/src/mappings/staking-info.ts b/root/src/mappings/staking-info.ts index 54bcd89..4ac3598 100644 --- a/root/src/mappings/staking-info.ts +++ b/root/src/mappings/staking-info.ts @@ -26,6 +26,7 @@ import { UnstakeInit, Unstaked, UpdateCommissionRate, + StartAuction, } from '../../generated/StakingInfo/StakingInfo' const STAKING_PARAMS_ID = 'staking:params' @@ -48,6 +49,8 @@ function loadValidator(validatorId: BigInt): Validator { entity.liquidatedRewards = BigInt.fromI32(0) entity.unstaked = false entity.commissionRate = BigInt.fromI32(0) + entity.auctionAmount = BigInt.fromI32(0) + entity.isInAuction = false } return entity as Validator @@ -296,3 +299,13 @@ export function handleThresholdChange(event: ThresholdChange): void { stakingParams.validatorThreshold = event.params.newThreshold stakingParams.save() } + +export function handleStartAuction(event: StartAuction): void { + + let validator = loadValidator(event.params.validatorId) + + validator.auctionAmount = event.params.auctionAmount + validator.isInAuction = true + + validator.save() +} From 3c859c87c9201679ad8d32bf465f09e0a6e72352 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 31 Dec 2020 14:26:04 +0530 Subject: [PATCH 02/10] handler function for confirm auction --- root/src/mappings/staking-info.ts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/root/src/mappings/staking-info.ts b/root/src/mappings/staking-info.ts index 4ac3598..99f8d36 100644 --- a/root/src/mappings/staking-info.ts +++ b/root/src/mappings/staking-info.ts @@ -1,9 +1,9 @@ import { Address, BigInt } from '@graphprotocol/graph-ts' -import { - Delegator, - Validator, - Topup, - StakingParams, +import { + Delegator, + Validator, + Topup, + StakingParams, } from '../../generated/schema' import { ClaimFee, @@ -27,6 +27,7 @@ import { Unstaked, UpdateCommissionRate, StartAuction, + ConfirmAuction, } from '../../generated/StakingInfo/StakingInfo' const STAKING_PARAMS_ID = 'staking:params' @@ -306,6 +307,18 @@ export function handleStartAuction(event: StartAuction): void { validator.auctionAmount = event.params.auctionAmount validator.isInAuction = true - + + validator.save() + +} + +export function handleConfirmAuction(event: ConfirmAuction): void { + + let validator = loadValidator(event.params.oldValidatorId) + + validator.auctionAmount = BigInt.fromI32(0) + validator.isInAuction = false + validator.save() + } From 7bb2eae0035b2d1cf3ba56957d5fa1d8f9e9fd52 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 31 Dec 2020 14:30:51 +0530 Subject: [PATCH 03/10] new: added auction handler methods in subgraph template file --- root/schema.graphql | 2 +- root/subgraph.template.yaml | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/root/schema.graphql b/root/schema.graphql index 0165f50..2b4de36 100644 --- a/root/schema.graphql +++ b/root/schema.graphql @@ -82,7 +82,7 @@ type Validator @entity { nonce: BigInt! unstaked: Boolean! jailEndEpoch: BigInt! - : BigInt! + auctionAmount: BigInt! isInAuction: Bool! } diff --git a/root/subgraph.template.yaml b/root/subgraph.template.yaml index 3ec3f65..043fb9a 100644 --- a/root/subgraph.template.yaml +++ b/root/subgraph.template.yaml @@ -126,8 +126,6 @@ dataSources: handler: handleClaimFee - event: ClaimRewards(indexed uint256,indexed uint256,indexed uint256) handler: handleClaimRewards - # - event: ConfirmAuction(indexed uint256,indexed uint256,indexed uint256) - # handler: handleConfirmAuction - event: DelegatorClaimedRewards(indexed uint256,indexed address,indexed uint256) handler: handleDelegatorClaimedRewards # - event: DelegatorRestaked(indexed uint256,indexed address,indexed uint256) @@ -156,7 +154,6 @@ dataSources: handler: handleStakeUpdate - event: Staked(indexed address,indexed uint256,uint256,indexed uint256,uint256,uint256,bytes) handler: handleStaked - # - event: StartAuction(indexed uint256,indexed uint256,indexed uint256) - event: ThresholdChange(uint256,uint256) handler: handleThresholdChange - event: TopUpFee(indexed address,indexed uint256) @@ -169,6 +166,10 @@ dataSources: handler: handleUnstaked - event: UpdateCommissionRate(indexed uint256,indexed uint256,indexed uint256) handler: handleUpdateCommissionRate + - event: StartAuction(indexed uint256,indexed uint256,indexed uint256) + handler: handleStartAuction + - event: ConfirmAuction(indexed uint256,indexed uint256,indexed uint256) + handler: handleConfirmAuction file: ./src/mappings/staking-info.ts - kind: ethereum/contract From 32f5c070a0b11d06960e605715a00c2d6acf2dfb Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 31 Dec 2020 15:02:49 +0530 Subject: [PATCH 04/10] comment: added code comment, why we're not adding NFT owner field in subgraph --- root/schema.graphql | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/root/schema.graphql b/root/schema.graphql index 2b4de36..19907b6 100644 --- a/root/schema.graphql +++ b/root/schema.graphql @@ -72,6 +72,18 @@ type TokenMapping @entity { type Validator @entity { id: ID! validatorId: BigInt! + # Below could be added, but that causes one + # issue : In handler function how should we be able to + # understand which chain we're currently working with ? + # + # Because that affects our which contract should be called + # for checking ownership of NFT contract + # + # It's better done offline, before serving request, backend can + # query blockchain node for this piece of data using standard `ownerOf` + # function call of standard ERC721, where parameter should be passed `validatorId` + # + # owner: Bytes! signer: Bytes! signerPubKey: Bytes! liquidatedRewards: BigInt! From f843b1be78c07e345748d5f8647ec8e354c0a02b Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 31 Dec 2020 15:21:53 +0530 Subject: [PATCH 05/10] udt: keeping checkpoint txhash, timestamp, can be useful for staking api --- root/schema.graphql | 2 ++ root/src/mappings/checkpoint.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/root/schema.graphql b/root/schema.graphql index 19907b6..1574a94 100644 --- a/root/schema.graphql +++ b/root/schema.graphql @@ -7,6 +7,8 @@ type Checkpoint @entity { start: BigInt! end: BigInt! root: Bytes! + transactionHash: Bytes! + timestamp: BigInt! } type StateSync @entity { diff --git a/root/src/mappings/checkpoint.ts b/root/src/mappings/checkpoint.ts index 0c4f6fe..566f065 100644 --- a/root/src/mappings/checkpoint.ts +++ b/root/src/mappings/checkpoint.ts @@ -17,6 +17,8 @@ export function handleNewHeaderBlock(event: NewHeaderBlock): void { entity.start = event.params.start entity.end = event.params.end entity.root = event.params.root + entity.transactionHash = event.transaction.hash + entity.timestamp = event.block.timestamp // save entity entity.save() From 08f9b6f63a7480eb87ed6cddc0deec22f3c4e79b Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 31 Dec 2020 15:54:22 +0530 Subject: [PATCH 06/10] udt: added explicit field for validator status --- root/schema.graphql | 8 +++++++- root/src/mappings/staking-info.ts | 7 +++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/root/schema.graphql b/root/schema.graphql index 1574a94..9322fec 100644 --- a/root/schema.graphql +++ b/root/schema.graphql @@ -94,7 +94,13 @@ type Validator @entity { totalStaked: BigInt! commissionRate: BigInt! nonce: BigInt! - unstaked: Boolean! + # Meaning of status codes + # + # 0 : Staked + # 1 : Unstaked + # 2 : Jailed + # 3 : Unjailed + status: Int! jailEndEpoch: BigInt! auctionAmount: BigInt! isInAuction: Bool! diff --git a/root/src/mappings/staking-info.ts b/root/src/mappings/staking-info.ts index 99f8d36..489f8de 100644 --- a/root/src/mappings/staking-info.ts +++ b/root/src/mappings/staking-info.ts @@ -48,7 +48,7 @@ function loadValidator(validatorId: BigInt): Validator { entity.deactivationEpoch = BigInt.fromI32(0) entity.jailEndEpoch = BigInt.fromI32(0) entity.liquidatedRewards = BigInt.fromI32(0) - entity.unstaked = false + entity.status = 0 entity.commissionRate = BigInt.fromI32(0) entity.auctionAmount = BigInt.fromI32(0) entity.isInAuction = false @@ -65,6 +65,7 @@ export function handleStaked(event: Staked): void { validator.totalStaked = event.params.total validator.signerPubKey = event.params.signerPubkey validator.nonce = event.params.nonce + validator.status = 0 // save entity validator.save() @@ -74,7 +75,7 @@ export function handleUnstaked(event: Unstaked): void { let validator = loadValidator(event.params.validatorId) // update unstaked status - validator.unstaked = true + validator.status = 1 validator.save() } @@ -109,6 +110,7 @@ export function handleJailed(event: Jailed): void { // save entity with jail end epoch validator.jailEndEpoch = event.params.exitEpoch + validator.status = 2 validator.save() } @@ -117,6 +119,7 @@ export function handleUnJailed(event: UnJailed): void { // save entity with jail end epoch validator.jailEndEpoch = BigInt.fromI32(0) + validator.status = 3 validator.save() } From b78510038ee5e483985181bd6800168ee2db0eb8 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Thu, 31 Dec 2020 18:06:05 +0530 Subject: [PATCH 07/10] udt: updating validator's selfstake and delegated stake fields, while handling events --- root/schema.graphql | 2 ++ root/src/mappings/staking-info.ts | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/root/schema.graphql b/root/schema.graphql index 9322fec..d201338 100644 --- a/root/schema.graphql +++ b/root/schema.graphql @@ -92,6 +92,8 @@ type Validator @entity { activationEpoch: BigInt! deactivationEpoch: BigInt! totalStaked: BigInt! + selfStake: BigInt! + delegatedStake: BigInt! commissionRate: BigInt! nonce: BigInt! # Meaning of status codes diff --git a/root/src/mappings/staking-info.ts b/root/src/mappings/staking-info.ts index 489f8de..a07e5c8 100644 --- a/root/src/mappings/staking-info.ts +++ b/root/src/mappings/staking-info.ts @@ -44,6 +44,8 @@ function loadValidator(validatorId: BigInt): Validator { entity = new Validator(id) entity.validatorId = validatorId entity.totalStaked = BigInt.fromI32(0) + entity.selfStake = BigInt.fromI32(0) + entity.delegatedStake = BigInt.fromI32(0) entity.nonce = BigInt.fromI32(0) entity.deactivationEpoch = BigInt.fromI32(0) entity.jailEndEpoch = BigInt.fromI32(0) @@ -62,7 +64,10 @@ export function handleStaked(event: Staked): void { validator.signer = event.params.signer validator.activationEpoch = event.params.activationEpoch + validator.totalStaked = event.params.total + validator.selfStake = event.params.amount + validator.signerPubKey = event.params.signerPubkey validator.nonce = event.params.nonce validator.status = 0 @@ -76,6 +81,7 @@ export function handleUnstaked(event: Unstaked): void { // update unstaked status validator.status = 1 + validator.selfStake = 0 validator.save() } @@ -129,6 +135,14 @@ export function handleStakeUpdate(event: StakeUpdate): void { // update total staked and nonce validator.totalStaked = event.params.newAmount validator.nonce = event.params.nonce + + // Updating validator's self stake + // + // We only get `totalStake` emitted from contract + // which is why we're subtracting delegated stake + // from totalStaked + validator.selfStake = validator.totalStaked.minus(validator.delegatedStake) + validator.save() } @@ -186,6 +200,14 @@ export function handleShareMinted(event: ShareMinted): void { // save entity delegator.save() + + // -- Also updating delegated stake for validator + let validator = loadValidator(event.params.validatorId) + + validator.delegatedStake = validator.delegatedStake.plus(event.params.amount) + + validator.save() + // -- Saving updation } export function handleShareBurned(event: ShareBurned): void { @@ -200,6 +222,14 @@ export function handleShareBurned(event: ShareBurned): void { // save entity delegator.save() + + // -- Also updating delegated stake for validator + let validator = loadValidator(event.params.validatorId) + + validator.delegatedStake = validator.delegatedStake.minus(event.params.amount) + + validator.save() + // -- Saving updation } export function handleDelegatorUnstaked(event: DelegatorUnstaked): void { From 794c2d826631cd41190c947931fa226f87ebcc3f Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Fri, 1 Jan 2021 11:28:35 +0530 Subject: [PATCH 08/10] chg: copying network address config file to src directory, so that it can be used in mapping handler functions --- root/.gitignore | 1 + root/package.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/root/.gitignore b/root/.gitignore index 74a16f9..4049558 100644 --- a/root/.gitignore +++ b/root/.gitignore @@ -1 +1,2 @@ subgraph.yaml +src/network.json diff --git a/root/package.json b/root/package.json index e0c4a54..69c729b 100644 --- a/root/package.json +++ b/root/package.json @@ -7,8 +7,8 @@ "graph": "graph", "codegen": "graph codegen", "build": "graph build", - "prepare:mainnet": "mustache config/mainnet.json subgraph.template.yaml > subgraph.yaml", - "prepare:goerli": "mustache config/goerli.json subgraph.template.yaml > subgraph.yaml", + "prepare:mainnet": "mustache config/mainnet.json subgraph.template.yaml > subgraph.yaml && cp config/mainnet.json src/network.json", + "prepare:goerli": "mustache config/goerli.json subgraph.template.yaml > subgraph.yaml && cp config/goerli.json src/network.json", "deploy": "graph deploy --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ maticnetwork/mumbai-root-subgraphs", "create-local": "graph create --node http://localhost:8020/ maticnetwork/mumbai-root-subgraphs", "remove-local": "graph remove --node http://localhost:8020/ maticnetwork/mumbai-root-subgraphs", From e2b7a57aabdbea23af230129236264190c3872a4 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Fri, 1 Jan 2021 11:32:19 +0530 Subject: [PATCH 09/10] new: storing nft owner address i.e. validator id owner address in validator entity --- root/schema.graphql | 13 +------------ root/src/mappings/staking-info.ts | 13 +++++++++++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/root/schema.graphql b/root/schema.graphql index d201338..762a40c 100644 --- a/root/schema.graphql +++ b/root/schema.graphql @@ -74,18 +74,7 @@ type TokenMapping @entity { type Validator @entity { id: ID! validatorId: BigInt! - # Below could be added, but that causes one - # issue : In handler function how should we be able to - # understand which chain we're currently working with ? - # - # Because that affects our which contract should be called - # for checking ownership of NFT contract - # - # It's better done offline, before serving request, backend can - # query blockchain node for this piece of data using standard `ownerOf` - # function call of standard ERC721, where parameter should be passed `validatorId` - # - # owner: Bytes! + owner: Bytes! signer: Bytes! signerPubKey: Bytes! liquidatedRewards: BigInt! diff --git a/root/src/mappings/staking-info.ts b/root/src/mappings/staking-info.ts index a07e5c8..6ab68d4 100644 --- a/root/src/mappings/staking-info.ts +++ b/root/src/mappings/staking-info.ts @@ -30,6 +30,14 @@ import { ConfirmAuction, } from '../../generated/StakingInfo/StakingInfo' +// using network address from config file +// to be passed to client when creating instance +// of contract, StakingNft, for calling `ownerOf` function +import NetworkConfig from '../network.json' + +// This is the contract we're going to interact with when `Staked` event is emitted +import {StakingNft} from '../../generated/StakingNft/StakingNft' + const STAKING_PARAMS_ID = 'staking:params' @@ -65,6 +73,11 @@ export function handleStaked(event: Staked): void { validator.signer = event.params.signer validator.activationEpoch = event.params.activationEpoch + // Keeping NFT owner address, to be helpful while responding + // client queries in staking API + let nft = StakingNft.bind(Address.fromString(NetworkConfig.stakingNft.address)) + validator.owner = nft.ownerOf(event.params.validatorId) + validator.totalStaked = event.params.total validator.selfStake = event.params.amount From 54e1f519361577883cf06f1afd1cdd8e02ccd1c2 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Fri, 1 Jan 2021 11:34:12 +0530 Subject: [PATCH 10/10] fix: JSON value path fixed --- root/src/mappings/staking-info.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/root/src/mappings/staking-info.ts b/root/src/mappings/staking-info.ts index 6ab68d4..c68584a 100644 --- a/root/src/mappings/staking-info.ts +++ b/root/src/mappings/staking-info.ts @@ -75,7 +75,7 @@ export function handleStaked(event: Staked): void { // Keeping NFT owner address, to be helpful while responding // client queries in staking API - let nft = StakingNft.bind(Address.fromString(NetworkConfig.stakingNft.address)) + let nft = StakingNft.bind(Address.fromString(NetworkConfig.contracts.stakingNft.address)) validator.owner = nft.ownerOf(event.params.validatorId) validator.totalStaked = event.params.total