فهرست منبع

increaseStake, decreaseStake + missing stake profile error

Leszek Wiesner 4 سال پیش
والد
کامیت
3de49d2650

+ 1 - 1
cli/src/Api.ts

@@ -247,7 +247,7 @@ export default class Api {
             throw new Error(`Group member profile not found! (member id: ${memberId.toNumber()})`);
         }
 
-        let stake: Balance = this._api.createType("Balance", 0);
+        let stake: Balance | undefined;
         if (worker.role_stake_profile && worker.role_stake_profile.isSome) {
             stake = await this.workerStake(worker.role_stake_profile.unwrap());
         }

+ 1 - 1
cli/src/Types.ts

@@ -105,7 +105,7 @@ export type GroupMember = {
     memberId: MemberId;
     roleAccount: AccountId;
     profile: Profile;
-    stake: Balance;
+    stake?: Balance;
     reward?: Reward;
 }
 

+ 62 - 0
cli/src/commands/working-groups/decreaseWorkerStake.ts

@@ -0,0 +1,62 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase';
+import _ from 'lodash';
+import { apiModuleByGroup } from '../../Api';
+import { WorkerId } from '@joystream/types/lib/working-group';
+import { Balance } from '@polkadot/types/interfaces';
+import { formatBalance } from '@polkadot/util';
+import { minMaxInt } from '../../validators/common';
+import chalk from 'chalk';
+import ExitCodes from '../../ExitCodes';
+
+export default class WorkingGroupsDecreaseWorkerStake extends WorkingGroupsCommandBase {
+    static description =
+        'Decreases given worker stake by an amount that will be returned to the worker role account. ' +
+        'Requires lead access.';
+    static args = [
+        {
+            name: 'workerId',
+            required: true,
+            description: 'Worker ID'
+        },
+    ]
+    static flags = {
+        ...WorkingGroupsCommandBase.flags,
+    };
+
+    async run() {
+        const { args } = this.parse(WorkingGroupsDecreaseWorkerStake);
+
+        const account = await this.getRequiredSelectedAccount();
+        // Lead-only gate
+        await this.getRequiredLead();
+
+        const workerId = parseInt(args.workerId);
+        // This will also make sure the worker is valid
+        const groupMember = await this.getApi().groupMember(this.group, workerId);
+
+        if (!groupMember.stake) {
+            this.error('This worker has no associated role stake profile!', { exit: ExitCodes.InvalidInput });
+        }
+
+        this.log(chalk.white('Current worker stake: ', formatBalance(groupMember.stake)));
+        const balanceValidator = minMaxInt(1, groupMember.stake.toNumber());
+        const balance = await this.promptForParam('Balance', 'amount', undefined, balanceValidator) as Balance;
+
+        await this.requestAccountDecoding(account);
+
+        await this.sendAndFollowExtrinsic(
+            account,
+            apiModuleByGroup[this.group],
+            'decreaseStake',
+            [
+                new WorkerId(workerId),
+                balance
+            ]
+        );
+
+        this.log(chalk.green(
+            `${chalk.white(formatBalance(balance))} from worker ${chalk.white(workerId)} stake `+
+            `has been returned to worker's role account (${chalk.white(groupMember.roleAccount.toString())})!`
+        ));
+    }
+}

+ 8 - 5
cli/src/commands/working-groups/evictWorker.ts

@@ -31,11 +31,14 @@ export default class WorkingGroupsEvictWorker extends WorkingGroupsCommandBase {
         const groupMember = await this.getApi().groupMember(this.group, workerId);
 
         const rationale = await this.promptForParam('Bytes', 'rationale');  // TODO: Terminate worker text limits? (minMaxStr)
-        const shouldSlash = await this.simplePrompt({
-            message: `Should the worker stake (${formatBalance(groupMember.stake)}) be slashed?`,
-            type: 'confirm',
-            default: false
-        });
+        const shouldSlash = groupMember.stake
+            ?
+                await this.simplePrompt({
+                    message: `Should the worker stake (${formatBalance(groupMember.stake)}) be slashed?`,
+                    type: 'confirm',
+                    default: false
+                })
+            : false;
 
         await this.requestAccountDecoding(account);
 

+ 45 - 0
cli/src/commands/working-groups/increaseStake.ts

@@ -0,0 +1,45 @@
+import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase';
+import _ from 'lodash';
+import { apiModuleByGroup } from '../../Api';
+import { Balance } from '@polkadot/types/interfaces';
+import { formatBalance } from '@polkadot/util';
+import { positiveInt } from '../../validators/common';
+import chalk from 'chalk';
+import ExitCodes from '../../ExitCodes';
+
+export default class WorkingGroupsIncreaseStake extends WorkingGroupsCommandBase {
+    static description =
+        'Increases role (lead/worker) stake. Requires active role account to be selected.';
+    static flags = {
+        ...WorkingGroupsCommandBase.flags,
+    };
+
+    async run() {
+        const account = await this.getRequiredSelectedAccount();
+        // Worker-only gate
+        const worker = await this.getRequiredWorker();
+
+        if (!worker.stake) {
+            this.error('Cannot increase stake. No associated role stake profile found!', { exit: ExitCodes.InvalidInput });
+        }
+
+        this.log(chalk.white('Current stake: ', formatBalance(worker.stake)));
+        const balance = await this.promptForParam('Balance', 'amount', undefined, positiveInt()) as Balance;
+
+        await this.requestAccountDecoding(account);
+
+        await this.sendAndFollowExtrinsic(
+            account,
+            apiModuleByGroup[this.group],
+            'increaseStake',
+            [
+                worker.workerId,
+                balance
+            ]
+        );
+
+        this.log(chalk.green(
+            `Worker ${chalk.white(worker.workerId.toNumber())} stake has been increased by ${chalk.white(formatBalance(balance))}`
+        ));
+    }
+}

+ 3 - 1
cli/src/commands/working-groups/overview.ts

@@ -1,6 +1,7 @@
 import WorkingGroupsCommandBase from '../../base/WorkingGroupsCommandBase';
 import { displayHeader, displayNameValueTable, displayTable } from '../../helpers/display';
 import { formatBalance } from '@polkadot/util';
+import { shortAddress } from '../../helpers/display';
 import chalk from 'chalk';
 
 export default class WorkingGroupsOverview extends WorkingGroupsCommandBase {
@@ -31,7 +32,8 @@ export default class WorkingGroupsOverview extends WorkingGroupsCommandBase {
             'Member id': m.memberId.toString(),
             'Member handle': m.profile.handle.toString(),
             'Stake': formatBalance(m.stake),
-            'Earned': formatBalance(m.reward?.totalRecieved)
+            'Earned': formatBalance(m.reward?.totalRecieved),
+            'Role account': shortAddress(m.roleAccount)
         }));
         displayTable(membersRows, 5);
     }

+ 7 - 2
cli/src/commands/working-groups/slashWorker.ts

@@ -6,6 +6,7 @@ import { Balance } from '@polkadot/types/interfaces';
 import { formatBalance } from '@polkadot/util';
 import { minMaxInt } from '../../validators/common';
 import chalk from 'chalk';
+import ExitCodes from '../../ExitCodes';
 
 export default class WorkingGroupsSlashWorker extends WorkingGroupsCommandBase {
     static description = 'Slashes given worker stake. Requires lead access.';
@@ -31,9 +32,13 @@ export default class WorkingGroupsSlashWorker extends WorkingGroupsCommandBase {
         // This will also make sure the worker is valid
         const groupMember = await this.getApi().groupMember(this.group, workerId);
 
+        if (!groupMember.stake) {
+            this.error('This worker has no associated role stake profile!', { exit: ExitCodes.InvalidInput });
+        }
+
         this.log(chalk.white('Current worker stake: ', formatBalance(groupMember.stake)));
         const balanceValidator = minMaxInt(1, groupMember.stake.toNumber());
-        const balance = await this.promptForParam('Balance', undefined, undefined, balanceValidator) as Balance;
+        const balance = await this.promptForParam('Balance', 'amount', undefined, balanceValidator) as Balance;
 
         await this.requestAccountDecoding(account);
 
@@ -47,6 +52,6 @@ export default class WorkingGroupsSlashWorker extends WorkingGroupsCommandBase {
             ]
         );
 
-        this.log(chalk.green(`${chalk.white(formatBalance(balance))} from worker ${chalk.white(workerId)} balance has been succesfully slashed!`));
+        this.log(chalk.green(`${chalk.white(formatBalance(balance))} from worker ${chalk.white(workerId)} stake has been succesfully slashed!`));
     }
 }

+ 5 - 0
cli/src/helpers/display.ts

@@ -1,6 +1,7 @@
 import { cli, Table } from 'cli-ux';
 import chalk from 'chalk';
 import { NameValueObj } from '../Types';
+import { AccountId } from '@polkadot/types/interfaces';
 
 export function displayHeader(caption: string, placeholderSign: string = '_', size: number = 50) {
     let singsPerSide: number = Math.floor((size - (caption.length + 2)) / 2);
@@ -65,3 +66,7 @@ export function toFixedLength(text: string, length: number, spacesOnLeft = false
 
     return text;
 }
+
+export function shortAddress(address: AccountId | string): string {
+    return address.toString().substr(0, 6) + '...' + address.toString().substr(-6);
+}