Skip to content

Commit

Permalink
commission: list validators with comission under and above the give…
Browse files Browse the repository at this point in the history
…n value (#83)
  • Loading branch information
emostov authored Jan 24, 2022
1 parent a31114c commit b095290
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 2 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,23 @@ payouts lsNominators \
-s 111B8CxcmnWbuDLyGvgUmRezDCK1brRZmvUuQ6SrFdMyc3S \
```

### List count of validator's commission under and above the given value

```bash
payouts commission \
-w wss://rpc.polkadot.io \
-p 0.9
```

## Options

```log
Commands:
index.ts collect Collect pending payouts [default]
index.ts ls List pending payouts
index.ts lsNominators List nominators backing the given stashes
index.ts commission List validators with commission under and above the
given value
Options:
--help Show help [boolean]
Expand Down
29 changes: 28 additions & 1 deletion src/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import fs from 'fs';

import { isValidSeed } from './isValidSeed';
import { log } from './logger';
import { collectPayouts, listNominators, listPendingPayouts } from './services';
import {
collectPayouts,
commissionData,
listNominators,
listPendingPayouts,
} from './services';

const DEBUG = process.env.PAYOUTS_DEBUG;

Expand All @@ -13,6 +18,7 @@ interface HandlerArgs {
stashesFile?: string;
stashes?: (string | number)[];
eraDepth: number;
percent?: number;
}

export async function collect({
Expand Down Expand Up @@ -95,6 +101,27 @@ export async function lsNominators({
});
}

export async function commission({
ws,
percent,
}: Omit<
HandlerArgs,
'stashes' | 'stashesFile' | 'suri' | 'eraDepth'
>): Promise<void> {
const provider = new WsProvider(ws);
const api = await ApiPromise.create({
provider,
});

if (!(typeof percent === 'number')) {
console.log('typeof commision', typeof percent);
log.warn('Internal error proccessing CLI args');
process.exit(1);
}

await commissionData(api, percent);
}

export function parseStashes(
stashesFile?: string,
stashes?: (string | number)[]
Expand Down
18 changes: 17 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import yargs from 'yargs';

import { collect, ls, lsNominators } from './handlers';
import { collect, commission, ls, lsNominators } from './handlers';
import { log } from './logger';

async function main() {
Expand Down Expand Up @@ -70,6 +70,22 @@ async function main() {
// @ts-ignore-
lsNominators
)
.command(
'commission',
'List validators with commission under and above the given value',
// @ts-ignore
(yargs) => {
return yargs.options({
percent: {
alias: 'p',
description: 'Commission, expressed as a percent i.e "10" for 10%',
number: true,
demandOption: true,
},
});
},
commission
)
.parse();
}

Expand Down
84 changes: 84 additions & 0 deletions src/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Exposure,
Nominations,
StakingLedger,
ValidatorPrefs,
} from '@polkadot/types/interfaces';
import { Codec, ISubmittableResult } from '@polkadot/types/types';
import { cryptoWaitReady } from '@polkadot/util-crypto';
Expand Down Expand Up @@ -290,6 +291,89 @@ export async function listNominators({
});
}

export async function commissionData(
api: ApiPromise,
mid: number
): Promise<void> {
const tenMillion = new BN(10_000_000);
const midPer = new BN(mid).mul(tenMillion);

const validators = await api.query.staking.validators.entries<
ValidatorPrefs,
[AccountId]
>();

const activeInfoOpt = await api.query.staking.activeEra<
Option<ActiveEraInfo>
>();
if (activeInfoOpt.isNone) {
process.exit(1);
}
const currEra = activeInfoOpt.unwrap().index.toNumber() - 2;

const greaterThanOrBlockedActive = [];
const greaterThanOrBlockedWaiting = [];
const lessThanActive = [];
const lessThanWaiting = [];
let sum = new BN(0);

// For each validator determine if they are in the active set
const withStatus = await Promise.all(
validators.map(([valIdKey, prefs]) => {
const commission = prefs.commission.unwrap();
const valId = valIdKey.args[0].toString();

sum = sum.add(commission);
return isValidatingInEra(api, valId, currEra).then((isActive) => {
return { isActive, valId, prefs };
});
})
);

// Go through validators and determine if their commision is greter than or less than than the
// given commission (`mid`)
withStatus.forEach((cur) => {
const { prefs, isActive } = cur;
const commission = prefs.commission.unwrap();
sum = sum.add(commission);

if (prefs.blocked.isTrue || commission.gt(midPer)) {
if (isActive) {
greaterThanOrBlockedActive.push(commission);
} else {
greaterThanOrBlockedWaiting.push(commission);
}
} else {
if (isActive) {
lessThanActive.push(commission);
} else {
lessThanWaiting.push(commission);
}
}
});

const sortedCommision = validators
.map(([_, prefs]) => prefs.commission.unwrap())
.sort((a, b) => a.cmp(b));
const mean = sortedCommision[sortedCommision.length / 2];
const allAvg = sum.div(new BN(validators.length));

log.info(`average (floor): ${allAvg.div(tenMillion)}%`);
log.info(`mean (floor): ${mean.div(tenMillion)}%`);
log.info(
`active validators blocked or commission > ${mid}%: ${greaterThanOrBlockedActive.length}`
);
log.info(
`active validators with commission <= ${mid}%: ${lessThanActive.length}`
);
log.info(
`waiting validators blocked or commission > ${mid}%: ${greaterThanOrBlockedWaiting.length}`
);
log.info(
`waiting validators with commission <= ${mid}%: ${lessThanWaiting.length}`
);
}

async function isValidatingInEra(
api: ApiPromise,
stash: string,
Expand Down

0 comments on commit b095290

Please sign in to comment.