Skip to content

Instantly share code, notes, and snippets.

@knopki
Created May 25, 2023 10:11
Show Gist options
  • Select an option

  • Save knopki/af27fc41796287535e9c6927c7ff9d8d to your computer and use it in GitHub Desktop.

Select an option

Save knopki/af27fc41796287535e9c6927c7ff9d8d to your computer and use it in GitHub Desktop.
Equilibrium/Genshiro balances monitor

Install @polkadot/api npm package. Set NODE_ADDR environment variable to "wss://node.ksm.genshiro.io" for Genshiro or "wss://node.pol.equilibrium.io" for Equilibrium. Set MASTER_ADDR to your substrate address. Run and see balances changes in log.

const { ApiPromise, WsProvider } = require('@polkadot/api');
const DECIMALS = 9;
const MASTER_ADDR = process.env.MASTER_ADDR || "cZgDYsXQ6xsPHFSUbtyZEGfeGnKMH5YrANnXD4cze5zLVdn8H";
const NODE_WS = process.env.NODE_ADDR || 'wss://node.ksm.genshiro.io';
const ACCOUNT_TYPES = ["Master", "Bailsman", "Trader", "Borrower"]
function log(msg) {
const ts = new Date().toISOString().slice(0, 19).replace("T", " ");
process.stderr.write(`${ts} ${msg}\n`);
}
function hex2a(hexx) {
const hex = hexx.toString();
let str = '';
for (let i = 0; i < hex.length; i += 2) {
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16))
};
return str;
}
async function printChainInfo(api) {
// Retrieve the chain & node information information via rpc calls
const [chain, nodeName, nodeVersion] = await Promise.all([
api.rpc.system.chain(),
api.rpc.system.name(),
api.rpc.system.version()
]);
log(`You are connected to chain ${chain} using ${nodeName} v${nodeVersion}`);
}
async function getAssetsMap(api) {
const assets = (await api.query.eqAssets.assets()).toJSON()
return new Map(assets.map(asset => ([asset.id, hex2a(asset.id.toString(16))])));
}
async function getAccounts(api, masterAddr) {
const typeToAccMapFn = async t => {
const addr = t == "Master"
? masterAddr
: (await api.query.subaccounts.subaccount(masterAddr, t)).unwrapOr(null);
return addr ? [t, addr] : null;
};
return new Map(
(await Promise.all(ACCOUNT_TYPES.map(typeToAccMapFn))).filter(Boolean)
);
}
function printBalances(accType, nonce, lock, balances) {
log(`Account ${accType} at nonce ${nonce}`);
log(`Account ${accType} has locked amount of native asset of ${lock / 10**DECIMALS}`);
for (const [asset, value] of balances.entries()) {
log(`Account ${accType} has ${value / 10**DECIMALS} ${asset}`);
}
}
async function sub(api, assetsMap, accountsAddrs, callback) {
const accTypes = [...accountsAddrs.keys()];
const mapBalance = (info) => {
const { nonce, data: { v0: { lock, balance } } } = info.toJSON();
const balances = new Map();
for (const [assetId, num] of balance) {
const assetSymbol = assetsMap.get(assetId);
const assetBalance = ((num?.positive || 0) - (num?.negative || 0));
balances.set(assetSymbol, assetBalance);
}
return { nonce, lock, balances };
};
return api.query.system.account.multi([...accountsAddrs.values()], (balances) => {
const acctsBalances = Array(balances.length)
.fill()
.map((_, idx) => [accTypes[idx], mapBalance(balances[idx])]);
for (const [accType, { nonce, lock, balances }] of acctsBalances) {
callback(accType, nonce, lock, balances);
}
});
}
async function main() {
const provider = new WsProvider(NODE_WS);
const api = await ApiPromise.create({ provider });
await printChainInfo(api);
// retrieve assets map
const assetsMap = await getAssetsMap(api);
log(`Available assets: ${[...assetsMap.values()].join(", ")}`);
// get subaccounts
const accountsAddrs = await getAccounts(api, MASTER_ADDR);
for (const [t, addr] of accountsAddrs.entries()) {
log(`${t} account address: ${addr}`);
}
// subscribe balance updates
const unsub = await sub(api, assetsMap, accountsAddrs, printBalances);
let stopped = false;
for (const signal of ["SIGINT", "SIGTERM"]) {
process.on(signal, (signal) => {
log(`${signal} received; closing...`);
unsub();
stopped = true;
});
}
while (!stopped) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
main().catch(console.error).finally(() => process.exit());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment