Browse Source

report-generator: Show worker rewards

Joystream Stats 3 years ago
parent
commit
4e4836c771

+ 28 - 6
community-contributions/report-generator/src/lib/rewards.ts

@@ -2,6 +2,7 @@ import { ApiPromise } from "@polkadot/api";
 import { Option, Vec } from "@polkadot/types";
 import { AccountId, Balance } from "@polkadot/types/interfaces";
 import { Hash } from "@polkadot/types/interfaces";
+import { Membership } from "@joystream/types/members";
 import { Mint, MintId } from "@joystream/types/mint";
 import { Stake } from "@joystream/types/stake";
 import { WorkerOf } from "@joystream/types/augment-codec/all";
@@ -17,6 +18,7 @@ import {
   getBlockHash,
   getMint,
   getNextWorker,
+  getMember,
   getWorker,
   getWorkerReward,
   getStake,
@@ -41,11 +43,12 @@ export const getWorkerRewards = async (
 
   for (let id = 0; id < nextWorkerId; ++id) {
     const worker: WorkerOf = await getWorker(api, group, hash, id);
-
-    // TODO workers fired before the end will be missed out
-    if (!worker.is_active) continue;
+    const memberId = worker.member_id;
+    const member: Membership = await getMember(api, hash, memberId);
+    const handle = String(member.handle);
+    const account: AccountId = member.root_account;
+    const status = worker.is_active ? `active` : `inactive`;
     let stake: Stake, reward: RewardRelationship;
-
     if (worker.role_stake_profile.isSome) {
       const roleStakeProfile = worker.role_stake_profile.unwrap();
       stake = await getStake(api, roleStakeProfile.stake_id);
@@ -53,14 +56,33 @@ export const getWorkerRewards = async (
 
     if (worker.reward_relationship.isSome) {
       // TODO changing salaries are not reflected
-      const rewardId: RewardRelationshipId = worker.reward_relationship.unwrap();
+      const rewardId: RewardRelationshipId =
+        worker.reward_relationship.unwrap();
       reward = await getWorkerReward(api, hash, rewardId);
     }
-    workers.push({ id, stake, reward });
+    workers.push({ id, stake, reward, status, handle, account, memberId });
   }
   return workers;
 };
 
+export const getWorkerRow = (
+  worker: WorkerReward,
+  earnedStart: number
+): string => {
+  const mtjoy = (mtjoy: number): string => (mtjoy / 1000000).toFixed(1);
+
+  const { id, memberId, account, handle, status, reward } = worker;
+  const earnedEnd = reward.total_reward_received.toNumber();
+  if (!earnedEnd) return ``;
+  const totalEarned = mtjoy(earnedEnd);
+  const earnedTerm = mtjoy(earnedEnd - earnedStart);
+  const amount = reward.amount_per_payout.toNumber();
+  const rewardPerBlock = (amount / Number(reward.payout_interval)).toFixed();
+  const url = `https://pioneer.joystreamstats.live/#/members/${handle}`; // TODO
+  // TODO compare earning to term start and show difference
+  return `| ${id} | [@${handle}](${url}) | ${status} | ${rewardPerBlock} | ${earnedTerm} | ${totalEarned} |\n`;
+};
+
 export const getBurnedTokens = (
   burnAddress: string,
   blocks: [number, CacheEvent[]][]

+ 18 - 33
contributions/tech/report-generator/src/StatisticsCollector.ts

@@ -101,6 +101,7 @@ import {
 import {
   filterMethods,
   getWorkerRewards,
+  getWorkerRow,
   getBurnedTokens,
   getMintInfo,
   getActiveValidators,
@@ -395,9 +396,24 @@ export class StatisticsCollector {
       group,
       endHash
     );
-    workersEnd.forEach(({ stake }) => {
-      if (stake) info.endStake += stake.value.toNumber();
+    let workers = ``;
+    workersEnd.forEach(async (worker) => {
+      if (worker.stake) info.endStake += worker.stake.value.toNumber();
+      if (!worker.reward) return;
+      const workerStart = workersStart.find((w) => w.id === worker.id);
+      const earnedStart = workerStart.reward?.total_reward_received.toNumber();
+      workers += getWorkerRow(worker, earnedStart);
     });
+    const header = `| # | Member | Status | tJOY / Block | M tJOY Term | M tJOY total |\n|--|--|--|--|--|--|\n`;
+    const groupTag =
+      workingGroup === `storage`
+        ? `storageProviders`
+        : workingGroup === `contentDirectory`
+        ? `curators`
+        : workingGroup === `operations`
+        ? `operations`
+        : ``;
+    this.saveStats({ [groupTag]: header + workers });
 
     info.rewards = await this.computeReward(
       roundNrBlocks,
@@ -613,16 +629,6 @@ export class StatisticsCollector {
     const startStorageProviders = await getWorkers(this.api, group, startHash);
     const endStorageProviders = await getWorkers(this.api, group, endHash);
 
-    let storageProviders = "";
-    const nextWorkerId = await getNextWorker(this.api, group, endHash);
-    for (let i = 0; i < nextWorkerId; ++i) {
-      const provider: WorkerOf = await getWorker(this.api, group, endHash, i);
-      if (!provider.is_active) continue;
-      const id = provider.member_id;
-      const { handle, root_account } = await getMember(this.api, endHash, id);
-      storageProviders += `@${handle} | (${root_account})  \n`;
-    }
-
     this.saveStats({
       newStorageProviderReward,
       startStorageProvidersStake,
@@ -637,7 +643,6 @@ export class StatisticsCollector {
         startStorageProviders,
         endStorageProviders
       ),
-      storageProviders,
     });
   }
 
@@ -646,15 +651,6 @@ export class StatisticsCollector {
     const startCurators = await getWorkers(this.api, group, startHash);
     const endCurators = await getWorkers(this.api, group, endHash);
 
-    let nextCuratorId = await getNextWorker(this.api, group, endHash);
-    let curators = "";
-    for (let i = 0; i < nextCuratorId; ++i) {
-      const curator: WorkerOf = await getWorker(this.api, group, endHash, i);
-      if (!curator.is_active) continue;
-      const id = curator.member_id;
-      const { handle, root_account } = await getMember(this.api, endHash, id);
-      curators += `@${handle} | (${root_account})  \n`;
-    }
     this.saveStats({
       startCurators,
       endCurators,
@@ -662,7 +658,6 @@ export class StatisticsCollector {
         this.statistics.startCurators,
         this.statistics.endCurators
       ),
-      curators,
     });
   }
 
@@ -687,17 +682,7 @@ export class StatisticsCollector {
     const startWorkers = await getWorkers(this.api, group, startHash);
     const endWorkers = await getWorkers(this.api, group, endHash);
 
-    let operations = "";
-    let nextOperationsWorkerId = await getNextWorker(this.api, group, endHash);
-    for (let i = 0; i < nextOperationsWorkerId; ++i) {
-      let worker: WorkerOf = await getWorker(this.api, group, endHash, i);
-      if (!worker.is_active) continue;
-      const id = worker.member_id;
-      const { handle, root_account } = await getMember(this.api, endHash, id);
-      operations += `@${handle} | (${root_account})  \n`;
-    }
     this.saveStats({
-      operations,
       newOperationsReward: Number(newOperationsReward),
       startOperationsWorkers: startWorkers,
       endOperationsWorkers: endWorkers,

+ 6 - 0
contributions/tech/report-generator/src/types.ts

@@ -1,5 +1,7 @@
+import { AccountId } from "@polkadot/types/interfaces";
 import { GenericEventData } from "@polkadot/types/generic/Event";
 import { Stake } from "@joystream/types/stake";
+import { MemberId } from "@joystream/types/members";
 import { RewardRelationship } from "@joystream/types/recurring-rewards";
 
 export class Statistics {
@@ -250,6 +252,10 @@ export class CacheEvent {
 
 export interface WorkerReward {
   id: number;
+  memberId: MemberId;
+  account: AccountId;
+  handle: string;
   stake: Stake;
   reward: RewardRelationship;
+  status: string;
 }