Balance reporting of LSD validators
This tutorial allows anyone to do Balance Reporting in batches for all the LSd validators.
NOTE: Do not forget to change the provider network from goerli to mainnet. The code shared below shows balance reporting for goerli network
Create a .env
file
In the project directory, create a .env
file which contains following values:
- INFURA_PROJECT_ID
- INFURA_PROJECT_SECRET
- PRIV_KEY
- BEACON_NODE
Project dependencies
- dotenv
- ethers
- graphql
- graphql-request
- Stakehouse SDK
To install the above dependencies run the following command
yarn add dotenv ethers@5.7.2 graphql graphql-request @blockswaplab/stakehouse-sdk
ethers
v6 and above causes issues with the SDK hence, it is recommended to installethers
v5. The SDK usesethers
v5.7.2
Balance reporting script
Create a .js
file with any appropriate name, and copy the code shared below.
require('dotenv').config();
const { ethers } = require('ethers');
const { gql, request } = require('graphql-request');
const { StakehouseSDK } = require('@blockswaplab/stakehouse-sdk');
const INFURA_PROJECT_ID = process.env.INFURA_PROJECT_ID;
const INFURA_PROJECT_SECRET = process.env.INFURA_PROJECT_SECRET;
const PRIV_KEY = process.env.PRIV_KEY;
const BEACON_NODE = process.env.BEACON_NODE;
const queryAllBLSPublicKeys = async (sdk) => {
const sdkConstants = await sdk.constants;
const lookupQuery = gql`
query listOfKnots {
lsdvalidators {
id
}
}
`;
const response = await request(
sdkConstants.stakehouseUrls.LSD_SUBGRAPH_ENDPOINT,
lookupQuery
);
if (!response) {
throw new Error('Invalid response fetching KNOTs')
}
if(response.lsdvalidators === 'undefined' || response.lsdvalidators == null || response.lsdvalidators.length == 0) {
return;
}
return response.lsdvalidators;
};
const getValidatorData = async (sdk, blsPublicKeys) => {
const sdkConstants = await sdk.constants;
const lookupQuery = gql`
query knotDetials($id_in: [String!]!) {
knots(where: {
id_in: $id_in
}) {
id
stakeHouse
}
}
`;
const response = await request(
sdkConstants.stakehouseUrls.SUBGRAPH_ENDPOINTS,
lookupQuery,
{
id_in: blsPublicKeys
}
);
if (!response) {
throw new Error('Invalid response fetching KNOTs')
}
if(response.knots === 'undefined' || response.knots == null || response.knots.length == 0) {
return;
}
return response.knots;
};
const reportBalancePromise = (sdk, blsPublicKey, stakehouseAddress) => {
const res = sdk.reportBalance(
BEACON_NODE,
blsPublicKey,
stakehouseAddress
);
return res;
};
const main = async () => {
// change goerli to mainnet
const provider = new ethers.providers.InfuraProvider("goerli", {
projectId: INFURA_PROJECT_ID,
projectSecret: INFURA_PROJECT_SECRET
});
const signer = new ethers.Wallet(PRIV_KEY, provider);
const sdk = new StakehouseSDK(signer);
const listOfBlsPublicKeys = await queryAllBLSPublicKeys(sdk);
let blsPublicKeys = [];
for(let i=0; i<listOfBlsPublicKeys.length; ++i) {
blsPublicKeys.push(listOfBlsPublicKeys[i].id)
}
const validatorData = await getValidatorData(sdk, blsPublicKeys);
console.log(validatorData);
let promises = [];
for(let i=0; i<validatorData.length; ++i) {
const blsPublicKey = validatorData[i].id;
const stakehouseAddress = validatorData[i].stakeHouse;
promises.push(reportBalancePromise(sdk, blsPublicKey, stakehouseAddress));
}
await Promise.allSettled(promises).then(
async(result) => {
for(let i=0; i<result.length; ++i) {
console.log(validatorData[i].id, result[i]);
}
}
).catch(
(e) => {
console.log(e);
}
);
};
main();