Skip to content

Commit

Permalink
Validate balance history of an account with polkadot.js (#150)
Browse files Browse the repository at this point in the history
* Add script to validate historicalAccountBalances

* Check all txns in a blockNum before emitting error

* Debug

* Log validation results

* Format variable names

* Rearrange code

* Update info

* Rename accounts to balanceHistory
  • Loading branch information
saboonikhil committed Aug 20, 2022
1 parent cfa404d commit 56dfbd6
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 13 deletions.
28 changes: 15 additions & 13 deletions test/validateBalances.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
/**
* Script to validate Ztg balance of an account with polkadot.js
* Script to validate Ztg balance of an account against on-chain balance
*/
import https from 'https'
import { Tools } from "../src/processor/util"
import { AccountInfo } from "@polkadot/types/interfaces/system";
import https from 'https';
import { Tools } from '../src/processor/util';
import { AccountInfo } from '@polkadot/types/interfaces/system';
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // Temporarily stop verifying https certificate

var falseCounter = 0, trueCounter = 0, falseAccs = ``;
// Modify values as per requirement
const WS_NODE_URL = `wss://bsr.zeitgeist.pm`;
const accountLimit = 20; // Number of accounts that need to be validated
const blockNumber = 1601267; // Balances from polkadot.js will be pulled as on this block number on chain
const QUERY_NODE_HOSTNAME = `processor.zeitgeist.pm`;
const ACCOUNTS_LIMIT = 20; // Number of accounts that need to be validated
const BLOCK_NUMBER = 1601267; // Balances from polkadot.js will be pulled as on this block number on chain

// GraphQL query for retrieving Ztg balances of accounts
const query = JSON.stringify({
query: `{
accountBalances(where: {assetId_eq: "Ztg"}, limit: ${accountLimit}) {
accountBalances(where: {assetId_eq: "Ztg"}, limit: ${ACCOUNTS_LIMIT}) {
account {
accountId
}
Expand All @@ -25,7 +26,7 @@ const query = JSON.stringify({
});

const options = {
hostname: 'processor.zeitgeist.pm',
hostname: QUERY_NODE_HOSTNAME,
path: '/graphql',
method: 'POST',
headers: {
Expand All @@ -47,14 +48,15 @@ const req = https.request(options, (res) => {
console.log(JSON.parse(data).errors[0].message);
return;
}
var falseCounter = 0, trueCounter = 0, falseAccs = ``;
const accounts = JSON.parse(data).data.accountBalances;
const sdk = await Tools.getSDK(WS_NODE_URL);

/**
* It is recommended to use `blockNumber` few blocks before finalized head
* It is recommended to use `BLOCK_NUMBER` few blocks before finalized head
* of the chain so that subsquid has the data processed in its database.
*/
const blockHash = await sdk.api.rpc.chain.getBlockHash(blockNumber);
const blockHash = await sdk.api.rpc.chain.getBlockHash(BLOCK_NUMBER);
console.log();

for (var i = 0; i < accounts.length; i++) {
Expand All @@ -75,13 +77,13 @@ const req = https.request(options, (res) => {
console.log(`\nTotal accounts checked: ${trueCounter+falseCounter}`);
console.log(`Balances match for ${trueCounter} accounts`);
if (falseCounter > 0) {
const falseAccsList = falseAccs.split(',');
console.log(`Balances don't match for the below ${falseCounter} account(s):`);
var falseAccsList = falseAccs.split(',');
for (var a in falseAccsList) {
console.log(falseAccsList[a]);
}
}
process.exit();
process.exit(1);
});
});

Expand Down
91 changes: 91 additions & 0 deletions test/validateHistoricalBalances.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* Script to validate Ztg balance history of an account against on-chain data
*/
import https from 'https';
import { Tools } from '../src/processor/util';
import { AccountInfo } from '@polkadot/types/interfaces/system';
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // Temporarily stop verifying https certificate

// Modify values as per requirement
const ACCOUNT_ID = `dE1VdxVn8xy7HFH9dLeebJu3eELFqXXjK8c2cwEuRJXr4QAZA`;
const WS_NODE_URL = `wss://bsr.zeitgeist.pm`;
const QUERY_NODE_HOSTNAME = `processor.zeitgeist.pm`;

// GraphQL query for retrieving balance history of an account
const query = JSON.stringify({
query: `{
historicalAccountBalances(where: {accountId_eq: "${ACCOUNT_ID}", assetId_eq: "Ztg"}, orderBy: blockNumber_ASC) {
balance
blockNumber
event
dBalance
}
}`,
});

const options = {
hostname: QUERY_NODE_HOSTNAME,
path: '/graphql',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': query.length,
'User-Agent': 'Node',
},
};

const req = https.request(options, (res) => {
let data = '';
res.on('data', (d) => {
data += d;
});
res.on('end', async () => {
if (res.statusCode == 200) {
console.log(`Validating response received from ${options.hostname}`);
} else {
console.log(JSON.parse(data).errors[0].message);
return;
}
var balanceDiff = BigInt(0), diffs = ``, blockNums = ``;
const balanceHistory = JSON.parse(data).data.historicalAccountBalances;
const sdk = await Tools.getSDK(WS_NODE_URL);

for (var i = 0; i < balanceHistory.length; i++) {
const blockHash = await sdk.api.rpc.chain.getBlockHash(balanceHistory[i].blockNumber);
const {data: { free: amt }} = (await sdk.api.query.system.account.at(blockHash, ACCOUNT_ID)) as AccountInfo;

if (amt.toString() !== balanceHistory[i].balance.toString()) {
// Avoid redundant errors in case of multiple transactions in a block number
if ((balanceHistory[i+1] !== undefined) ? balanceHistory[i].blockNumber !== balanceHistory[i+1].blockNumber : true) {
console.log(`\nBalances don't match at ${blockHash} [#${balanceHistory[i].blockNumber}]`);
console.log(`On Polkadot.js: ` + amt.toBigInt());
console.log(`On Subsquid: ` + balanceHistory[i].balance);
balanceDiff = amt.toBigInt() - BigInt(balanceHistory[i].balance);
diffs += balanceDiff + `,`;
blockNums += balanceHistory[i].blockNumber + `,`;
}
} else {
console.log(`Balances match at ${blockHash} [#${balanceHistory[i].blockNumber}]`);
}
}
if (balanceDiff == BigInt(0)) {
console.log(`\nBalance history for ${ACCOUNT_ID} is in alliance with on-chain data`);
} else {
console.log(`\nBalance history for ${ACCOUNT_ID} is not in alliance with on-chain data`);
const diffsList = diffs.split(',');
const blockNumsList = blockNums.split(',');
console.log(`The differences found are:`)
for (var i = 0; i < diffsList.length - 1; i++) {
console.log(`${diffsList[i]} units at #${blockNumsList[i]}`)
}
}
process.exit(1);
});
});

req.on('error', (error) => {
console.error(error);
});

req.write(query);
req.end();

0 comments on commit 56dfbd6

Please sign in to comment.