joyApi.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import { WsProvider, ApiPromise } from "@polkadot/api";
  2. import { types } from "@joystream/types";
  3. import { AccountId, Hash } from "@polkadot/types/interfaces";
  4. import { config } from "dotenv";
  5. import BN from "bn.js";
  6. import { Option, Vec } from "@polkadot/types";
  7. import { log } from "./debug"
  8. import { ActiveEra } from "./Types";
  9. config();
  10. export class JoyApi {
  11. endpoint: string;
  12. isReady: Promise<ApiPromise>;
  13. api!: ApiPromise;
  14. constructor(endpoint?: string) {
  15. const wsEndpoint = endpoint || process.env.REACT_APP_WS_PROVIDER || "ws://127.0.0.1:9944";
  16. this.endpoint = wsEndpoint;
  17. this.isReady = (async () => {
  18. const api = await new ApiPromise({ provider: new WsProvider(wsEndpoint), types })
  19. .isReadyOrError;
  20. return api;
  21. })();
  22. }
  23. get init(): Promise<JoyApi> {
  24. return this.isReady.then((instance) => {
  25. this.api = instance;
  26. return this;
  27. });
  28. }
  29. async totalIssuance(blockHash?: Hash) {
  30. const issuance =
  31. blockHash === undefined
  32. ? await this.api.query.balances.totalIssuance()
  33. : await this.api.query.balances.totalIssuance.at(blockHash);
  34. return issuance.toNumber();
  35. }
  36. async systemData() {
  37. const [chain, nodeName, nodeVersion] = await Promise.all([
  38. this.api.rpc.system.chain(),
  39. this.api.rpc.system.name(),
  40. this.api.rpc.system.version(),
  41. ]);
  42. return {
  43. chain: chain.toString(),
  44. nodeName: nodeName.toString(),
  45. nodeVersion: nodeVersion.toString(),
  46. };
  47. }
  48. async finalizedHash() {
  49. return this.api.rpc.chain.getFinalizedHead();
  50. }
  51. async finalizedBlockHeight() {
  52. const finalizedHash = await this.finalizedHash();
  53. const { number } = await this.api.rpc.chain.getHeader(`${finalizedHash}`);
  54. return number.toNumber();
  55. }
  56. async getActiveErasForBlock(address: string, blockStart: number): Promise<ActiveEra[] | undefined> {
  57. const stash = address;
  58. const startHash = (await this.api.rpc.chain.getBlockHash(blockStart));
  59. const startEra = (await this.api.query.staking.activeEra.at(startHash)).unwrap().index.toNumber();
  60. const startTimestamp = new Date((await this.api.query.timestamp.now.at(startHash)).toNumber()).toISOString();
  61. const eraPoints = await this.api.query.staking.erasRewardPoints.at(startHash, startEra)
  62. let data = undefined
  63. eraPoints.individual.forEach((points, author) => {
  64. log(`Author Points [${author}]`);
  65. log(`Individual Points [${points}]`);
  66. if (author.toString() === stash) {
  67. const pn = Number(points.toBigInt())
  68. const activeEra: ActiveEra = {
  69. id: blockStart,
  70. era: startEra,
  71. hash: startHash.toString(),
  72. block: blockStart,
  73. date: startTimestamp,
  74. points: pn
  75. }
  76. log(`Era [${activeEra.era}], Block [${activeEra.block}], Date [${activeEra.date}], Points [${activeEra.points}], Hash [${activeEra.hash}]`);
  77. data = activeEra
  78. }
  79. });
  80. return data
  81. }
  82. async findActiveValidators(hash: Hash, searchPreviousBlocks: boolean): Promise<AccountId[]> {
  83. const block = await this.api.rpc.chain.getBlock(hash);
  84. let currentBlockNr = block.block.header.number.toNumber();
  85. let activeValidators;
  86. do {
  87. let currentHash = (await this.api.rpc.chain.getBlockHash(currentBlockNr)) as Hash;
  88. let allValidators = await this.api.query.staking.snapshotValidators.at(currentHash) as Option<Vec<AccountId>>;
  89. if (!allValidators.isEmpty) {
  90. let max = (await this.api.query.staking.validatorCount.at(currentHash)).toNumber();
  91. activeValidators = Array.from(allValidators.unwrap()).slice(0, max);
  92. }
  93. if (searchPreviousBlocks) {
  94. --currentBlockNr;
  95. } else {
  96. ++currentBlockNr;
  97. }
  98. } while (activeValidators === undefined);
  99. return activeValidators;
  100. }
  101. async validatorsData() {
  102. const validators = await this.api.query.session.validators();
  103. const era = await this.api.query.staking.currentEra();
  104. const totalStake = era.isSome ?
  105. await this.api.query.staking.erasTotalStake(era.unwrap())
  106. : new BN(0);
  107. return {
  108. count: validators.length,
  109. validators: validators.toJSON(),
  110. total_stake: totalStake.toNumber(),
  111. };
  112. }
  113. }