ghost-portal/packages/app-staking/src/StakeList/Account.tsx
Jaco Greeff 338bd517a0
Remove /index imports (swap to bare) (#814)
* Remove /index imports (swap to bare)

* Bump deps
2019-03-14 10:45:58 +01:00

281 lines
6.6 KiB
TypeScript

// Copyright 2017-2019 @polkadot/app-staking authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { SubmittableExtrinsic } from '@polkadot/api/promise/types';
import { DerivedBalancesMap } from '@polkadot/api-derive/types';
import { I18nProps } from '@polkadot/ui-app/types';
import { QueueTx$ExtrinsicAdd } from '@polkadot/ui-app/Status/types';
import { ApiProps } from '@polkadot/ui-api/types';
import React from 'react';
import { AccountId, Balance, Option, ValidatorPrefs } from '@polkadot/types';
import { AddressMini, AddressSummary, Button } from '@polkadot/ui-app';
import { withCalls } from '@polkadot/ui-api';
import Nominating from './Nominating';
import Preferences from './Preferences';
import UnnominateButton from './UnnominateButton';
import translate from '../translate';
type Props = ApiProps & I18nProps & {
accountId: string,
balances: DerivedBalancesMap,
balanceArray: (_address: AccountId | string) => Array<Balance> | undefined,
name: string,
staking_nominating?: Option<AccountId>,
staking_nominatorsFor?: Array<string>,
staking_validatorPreferences?: ValidatorPrefs,
intentions: Array<string>,
isValidator: boolean,
queueExtrinsic: QueueTx$ExtrinsicAdd
};
type State = {
isNominateOpen: boolean,
isNominating: boolean,
isPrefsOpen: boolean
};
class Account extends React.PureComponent<Props, State> {
state: State = {
isNominateOpen: false,
isNominating: false,
isPrefsOpen: false
};
static getDerivedStateFromProps ({ staking_nominating }: Props) {
const isNominating = !!staking_nominating && !staking_nominating.isEmpty;
return {
isNominating
};
}
render () {
const { accountId, balanceArray, name } = this.props;
return (
<article className='staking--Account'>
{this.renderNominating()}
{this.renderPrefs()}
<AddressSummary
balance={balanceArray(accountId)}
name={name}
value={accountId}
identIconSize={96}
>
<div className='staking--Account-expand'>
{this.renderButtons()}
{this.renderNominee()}
{this.renderNominators()}
</div>
</AddressSummary>
</article>
);
}
private renderNominee () {
const { staking_nominating, balanceArray } = this.props;
const { isNominating } = this.state;
if (!isNominating || !staking_nominating || staking_nominating.isNone) {
return null;
}
const nominating = staking_nominating.unwrap();
return (
<AddressMini
balance={balanceArray(nominating)}
value={nominating}
withBalance
/>
);
}
private renderNominators () {
const { staking_nominatorsFor } = this.props;
if (!staking_nominatorsFor) {
return null;
}
return (
<div className='ui--Nominators'>
{staking_nominatorsFor.map((nominator) => (
<AddressMini
isPadded={false}
key={nominator}
value={nominator}
withBalance
/>
))}
</div>
);
}
private renderNominating () {
const { intentions } = this.props;
const { isNominateOpen } = this.state;
if (!isNominateOpen) {
return null;
}
return (
<Nominating
isOpen={isNominateOpen}
onClose={this.toggleNominate}
onNominate={this.nominate}
intentions={intentions}
/>
);
}
private renderPrefs () {
const { accountId, staking_validatorPreferences } = this.props;
const { isPrefsOpen } = this.state;
if (!isPrefsOpen) {
return null;
}
return (
<Preferences
accountId={accountId}
isOpen={isPrefsOpen}
onClose={this.togglePrefs}
onSetPrefs={this.setPrefs}
validatorPreferences={staking_validatorPreferences}
/>
);
}
private renderButtons () {
const { accountId, intentions, staking_nominating, t } = this.props;
const { isNominating } = this.state;
const isIntending = intentions.includes(accountId);
const canStake = !isIntending && !isNominating;
if (canStake) {
return (
<Button.Group>
<Button
isPrimary
onClick={this.stake}
label={t('Stake')}
/>
<Button.Or />
<Button
isPrimary
onClick={this.toggleNominate}
label={t('Nominate')}
/>
</Button.Group>
);
}
if (isNominating) {
return (
<Button.Group>
<UnnominateButton
accountId={accountId || ''}
nominating={staking_nominating || ''}
onClick={this.unnominate}
/>
</Button.Group>
);
}
return (
<Button.Group>
<Button
isNegative
onClick={this.unstake}
label={t('Unstake')}
/>
<Button.Or />
<Button
isPrimary
onClick={this.togglePrefs}
label={t('Set Prefs')}
/>
</Button.Group>
);
}
private send (extrinsic: SubmittableExtrinsic) {
const { accountId, queueExtrinsic } = this.props;
queueExtrinsic({
extrinsic,
accountId
});
}
private toggleNominate = () => {
this.setState(
({ isNominateOpen }: State) => ({
isNominateOpen: !isNominateOpen
})
);
}
private togglePrefs = () => {
this.setState(
({ isPrefsOpen }: State) => ({
isPrefsOpen: !isPrefsOpen
})
);
}
private nominate = (nominee: string) => {
const { api } = this.props;
this.send(api.tx.staking.nominate(nominee));
this.toggleNominate();
}
private unnominate = (index: number) => {
const { api } = this.props;
this.send(api.tx.staking.unnominate(index));
}
private setPrefs = (prefs: ValidatorPrefs) => {
const { api } = this.props;
this.send(api.tx.staking.registerPreferences(this.getIntentionIndex(), prefs));
this.togglePrefs();
}
private stake = () => {
const { api } = this.props;
this.send(api.tx.staking.stake());
}
private unstake = () => {
const { api } = this.props;
this.send(api.tx.staking.unstake(this.getIntentionIndex()));
}
private getIntentionIndex (): number {
const { accountId, intentions } = this.props;
return intentions.indexOf(accountId);
}
}
export default translate(
withCalls<Props>(
['query.staking.nominatorsFor', { paramName: 'accountId' }],
['query.staking.nominating', { paramName: 'accountId' }],
['query.staking.validatorPreferences', { paramName: 'accountId' }]
)(Account)
);