Add bonding preferences (#842)
This commit is contained in:
parent
6997337f99
commit
9ee5280adb
@ -13,9 +13,10 @@ import { AccountId, Balance, Option, ValidatorPrefs } from '@polkadot/types';
|
||||
import { AddressMini, AddressSummary, Button } from '@polkadot/ui-app';
|
||||
import { withCalls } from '@polkadot/ui-api';
|
||||
|
||||
import Bonding from './Bonding';
|
||||
import Nominating from './Nominating';
|
||||
import Preferences from './Preferences';
|
||||
import UnnominateButton from './UnnominateButton';
|
||||
// import UnnominateButton from './UnnominateButton';
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = ApiProps & I18nProps & {
|
||||
@ -32,6 +33,7 @@ type Props = ApiProps & I18nProps & {
|
||||
};
|
||||
|
||||
type State = {
|
||||
isBondingOpen: boolean,
|
||||
isNominateOpen: boolean,
|
||||
isPrefsOpen: boolean,
|
||||
nominee: AccountId | null
|
||||
@ -39,6 +41,7 @@ type State = {
|
||||
|
||||
class Account extends React.PureComponent<Props, State> {
|
||||
state: State = {
|
||||
isBondingOpen: false,
|
||||
isNominateOpen: false,
|
||||
isPrefsOpen: false,
|
||||
nominee: null
|
||||
@ -57,6 +60,7 @@ class Account extends React.PureComponent<Props, State> {
|
||||
|
||||
return (
|
||||
<article className='staking--Account'>
|
||||
{this.renderBonding()}
|
||||
{this.renderNominating()}
|
||||
{this.renderPrefs()}
|
||||
<AddressSummary
|
||||
@ -75,6 +79,19 @@ class Account extends React.PureComponent<Props, State> {
|
||||
);
|
||||
}
|
||||
|
||||
private renderBonding () {
|
||||
const { accountId } = this.props;
|
||||
const { isBondingOpen } = this.state;
|
||||
|
||||
return (
|
||||
<Bonding
|
||||
accountId={accountId}
|
||||
isOpen={isBondingOpen}
|
||||
onClose={this.toggleBonding}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
private renderNominee () {
|
||||
const { balanceArray } = this.props;
|
||||
const { nominee } = this.state;
|
||||
@ -117,10 +134,6 @@ class Account extends React.PureComponent<Props, State> {
|
||||
const { intentions } = this.props;
|
||||
const { isNominateOpen } = this.state;
|
||||
|
||||
if (!isNominateOpen) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Nominating
|
||||
isOpen={isNominateOpen}
|
||||
@ -135,10 +148,6 @@ class Account extends React.PureComponent<Props, State> {
|
||||
const { accountId, staking_validatorPreferences } = this.props;
|
||||
const { isPrefsOpen } = this.state;
|
||||
|
||||
if (!isPrefsOpen) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Preferences
|
||||
accountId={accountId}
|
||||
@ -151,56 +160,68 @@ class Account extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
private renderButtons () {
|
||||
const { accountId, intentions, t } = this.props;
|
||||
const { nominee } = this.state;
|
||||
const isIntending = intentions.includes(accountId);
|
||||
const canStake = !isIntending && !nominee;
|
||||
|
||||
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 (nominee) {
|
||||
return (
|
||||
<Button.Group>
|
||||
<UnnominateButton
|
||||
accountId={accountId || ''}
|
||||
nominating={nominee}
|
||||
onClick={this.unnominate}
|
||||
/>
|
||||
</Button.Group>
|
||||
);
|
||||
}
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<Button.Group>
|
||||
<Button
|
||||
isNegative
|
||||
onClick={this.unstake}
|
||||
label={t('Unstake')}
|
||||
/>
|
||||
<Button.Or />
|
||||
<Button
|
||||
isPrimary
|
||||
onClick={this.togglePrefs}
|
||||
label={t('Set Prefs')}
|
||||
onClick={this.toggleBonding}
|
||||
label={t('Bond')}
|
||||
/>
|
||||
</Button.Group>
|
||||
);
|
||||
|
||||
// const { accountId, intentions, t } = this.props;
|
||||
// const { nominee } = this.state;
|
||||
// const isIntending = intentions.includes(accountId);
|
||||
// const canStake = !isIntending && !nominee;
|
||||
|
||||
// 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 (nominee) {
|
||||
// return (
|
||||
// <Button.Group>
|
||||
// <UnnominateButton
|
||||
// accountId={accountId || ''}
|
||||
// nominating={nominee}
|
||||
// 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) {
|
||||
@ -212,22 +233,6 @@ class Account extends React.PureComponent<Props, State> {
|
||||
});
|
||||
}
|
||||
|
||||
private toggleNominate = () => {
|
||||
this.setState(
|
||||
({ isNominateOpen }: State) => ({
|
||||
isNominateOpen: !isNominateOpen
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private togglePrefs = () => {
|
||||
this.setState(
|
||||
({ isPrefsOpen }: State) => ({
|
||||
isPrefsOpen: !isPrefsOpen
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private nominate = (nominee: string) => {
|
||||
const { api } = this.props;
|
||||
|
||||
@ -236,11 +241,11 @@ class Account extends React.PureComponent<Props, State> {
|
||||
this.toggleNominate();
|
||||
}
|
||||
|
||||
private unnominate = (index: number) => {
|
||||
const { api } = this.props;
|
||||
// private unnominate = (index: number) => {
|
||||
// const { api } = this.props;
|
||||
|
||||
this.send(api.tx.staking.unnominate(index));
|
||||
}
|
||||
// this.send(api.tx.staking.unnominate(index));
|
||||
// }
|
||||
|
||||
private setPrefs = (prefs: ValidatorPrefs) => {
|
||||
const { api } = this.props;
|
||||
@ -250,23 +255,41 @@ class Account extends React.PureComponent<Props, State> {
|
||||
this.togglePrefs();
|
||||
}
|
||||
|
||||
private stake = () => {
|
||||
const { api } = this.props;
|
||||
// private stake = () => {
|
||||
// const { api } = this.props;
|
||||
|
||||
this.send(api.tx.staking.stake());
|
||||
}
|
||||
// this.send(api.tx.staking.stake());
|
||||
// }
|
||||
|
||||
private unstake = () => {
|
||||
const { api } = this.props;
|
||||
// private unstake = () => {
|
||||
// const { api } = this.props;
|
||||
|
||||
this.send(api.tx.staking.unstake(this.getIntentionIndex()));
|
||||
}
|
||||
// this.send(api.tx.staking.unstake(this.getIntentionIndex()));
|
||||
// }
|
||||
|
||||
private getIntentionIndex (): number {
|
||||
const { accountId, intentions } = this.props;
|
||||
|
||||
return intentions.indexOf(accountId);
|
||||
}
|
||||
|
||||
private toggleBonding = () => {
|
||||
this.setState(({ isBondingOpen }) => ({
|
||||
isBondingOpen: !isBondingOpen
|
||||
}));
|
||||
}
|
||||
|
||||
private toggleNominate = () => {
|
||||
this.setState(({ isNominateOpen }: State) => ({
|
||||
isNominateOpen: !isNominateOpen
|
||||
}));
|
||||
}
|
||||
|
||||
private togglePrefs = () => {
|
||||
this.setState(({ isPrefsOpen }: State) => ({
|
||||
isPrefsOpen: !isPrefsOpen
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(
|
||||
|
||||
127
packages/app-staking/src/StakeList/Bonding.tsx
Normal file
127
packages/app-staking/src/StakeList/Bonding.tsx
Normal file
@ -0,0 +1,127 @@
|
||||
// Copyright 2017-2019 @polkadot/ui-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 { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React from 'react';
|
||||
import { Button, InputAddress, InputBalance, Modal, TxButton, Dropdown } from '@polkadot/ui-app';
|
||||
|
||||
import translate from '../translate';
|
||||
|
||||
type Props = I18nProps & {
|
||||
accountId: string,
|
||||
isOpen: boolean,
|
||||
onClose: () => void
|
||||
};
|
||||
|
||||
type State = {
|
||||
bondValue?: BN,
|
||||
controller?: string,
|
||||
destination: number
|
||||
};
|
||||
|
||||
const stashOptions = [
|
||||
{ text: 'Stash account (increase the amount at stake)', value: 0 },
|
||||
{ text: 'Stash account (do not increase the amount at stake)', value: 1 },
|
||||
{ text: 'Controller account', value: 2 }
|
||||
];
|
||||
|
||||
class Bonding extends React.PureComponent<Props, State> {
|
||||
state: State = {
|
||||
destination: 0
|
||||
};
|
||||
|
||||
render () {
|
||||
const { accountId, isOpen, onClose, t } = this.props;
|
||||
const { bondValue, controller, destination } = this.state;
|
||||
const canSubmit = !!bondValue && bondValue.gtn(0) && !!controller;
|
||||
|
||||
if (!isOpen) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className='staking--Bonding'
|
||||
dimmer='inverted'
|
||||
open
|
||||
size='small'
|
||||
>
|
||||
{this.renderContent()}
|
||||
<Modal.Actions>
|
||||
<Button.Group>
|
||||
<Button
|
||||
isNegative
|
||||
onClick={onClose}
|
||||
label={t('Cancel')}
|
||||
/>
|
||||
<Button.Or />
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
isDisabled={!canSubmit}
|
||||
isPrimary
|
||||
label={t('Bond')}
|
||||
onClick={onClose}
|
||||
params={[controller, bondValue, destination]}
|
||||
tx='staking.bond'
|
||||
/>
|
||||
</Button.Group>
|
||||
</Modal.Actions>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
private renderContent () {
|
||||
const { accountId, t } = this.props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal.Header>
|
||||
{t('Bonding Preferences')}
|
||||
</Modal.Header>
|
||||
<Modal.Content className='ui--signer-Signer-Content'>
|
||||
<InputAddress
|
||||
className='medium'
|
||||
isDisabled
|
||||
label={t('stash account')}
|
||||
value={accountId}
|
||||
/>
|
||||
<InputAddress
|
||||
autoFocus
|
||||
className='medium'
|
||||
label={t('controller account')}
|
||||
onChange={this.onChangeController}
|
||||
/>
|
||||
<InputBalance
|
||||
className='medium'
|
||||
label={t('value bonded')}
|
||||
onChange={this.onChangeValue}
|
||||
/>
|
||||
<Dropdown
|
||||
className='medium'
|
||||
defaultValue={0}
|
||||
label={t('payment destination')}
|
||||
onChange={this.onChangeDestination}
|
||||
options={stashOptions}
|
||||
/>
|
||||
</Modal.Content>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
private onChangeController = (controller: string) => {
|
||||
this.setState({ controller });
|
||||
}
|
||||
|
||||
private onChangeDestination = (destination: number) => {
|
||||
this.setState({ destination });
|
||||
}
|
||||
|
||||
private onChangeValue = (bondValue?: BN) => {
|
||||
this.setState({ bondValue });
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(Bonding);
|
||||
@ -31,7 +31,7 @@ class Nominating extends React.PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
render () {
|
||||
const { isOpen, style } = this.props;
|
||||
const { isOpen } = this.props;
|
||||
|
||||
if (!isOpen) {
|
||||
return null;
|
||||
@ -43,7 +43,6 @@ class Nominating extends React.PureComponent<Props, State> {
|
||||
dimmer='inverted'
|
||||
open
|
||||
size='small'
|
||||
style={style}
|
||||
>
|
||||
{this.renderContent()}
|
||||
{this.renderButtons()}
|
||||
|
||||
@ -43,7 +43,7 @@ class Preferences extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { isOpen, style } = this.props;
|
||||
const { isOpen } = this.props;
|
||||
|
||||
if (!isOpen) {
|
||||
return null;
|
||||
@ -51,11 +51,10 @@ class Preferences extends React.PureComponent<Props, State> {
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className='staking--Nominating'
|
||||
className='staking--Preferences'
|
||||
dimmer='inverted'
|
||||
open
|
||||
size='small'
|
||||
style={style}
|
||||
>
|
||||
{this.renderContent()}
|
||||
{this.renderButtons()}
|
||||
|
||||
@ -5,15 +5,13 @@
|
||||
import { DerivedBalancesMap } from '@polkadot/api-derive/types';
|
||||
import { AppProps, I18nProps } from '@polkadot/ui-app/types';
|
||||
import { ApiProps } from '@polkadot/ui-api/types';
|
||||
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
|
||||
import { ComponentProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import { Route, Switch } from 'react-router';
|
||||
import { AccountId, Balance } from '@polkadot/types';
|
||||
import Tabs, { TabItem } from '@polkadot/ui-app/Tabs';
|
||||
import accountObservable from '@polkadot/ui-keyring/observable/accounts';
|
||||
import { withCalls, withMulti, withObservable } from '@polkadot/ui-api';
|
||||
import { withCalls, withMulti } from '@polkadot/ui-api';
|
||||
|
||||
import './index.css';
|
||||
|
||||
@ -22,7 +20,6 @@ import Overview from './Overview';
|
||||
import translate from './translate';
|
||||
|
||||
type Props = AppProps & ApiProps & I18nProps & {
|
||||
allAccounts?: SubjectInfo,
|
||||
balances?: DerivedBalancesMap,
|
||||
intentions?: Array<AccountId>,
|
||||
session_validators?: Array<AccountId>
|
||||
@ -70,20 +67,14 @@ class App extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { allAccounts, api } = this.props;
|
||||
const { tabs } = this.state;
|
||||
const { basePath } = this.props;
|
||||
const hasAccounts = allAccounts && Object.keys(allAccounts).length !== 0;
|
||||
const hidden = hasAccounts && api.tx.staking.stake
|
||||
? []
|
||||
: ['actions'];
|
||||
|
||||
return (
|
||||
<main className='staking--App'>
|
||||
<header>
|
||||
<Tabs
|
||||
basePath={basePath}
|
||||
hidden={hidden}
|
||||
items={tabs}
|
||||
/>
|
||||
</header>
|
||||
@ -132,7 +123,6 @@ class App extends React.PureComponent<Props, State> {
|
||||
export default withMulti(
|
||||
App,
|
||||
translate,
|
||||
withObservable(accountObservable.subject, { propName: 'allAccounts' }),
|
||||
withCalls<Props>(
|
||||
'query.session.validators',
|
||||
['query.staking.intentions', { propName: 'intentions' }],
|
||||
|
||||
@ -20,6 +20,7 @@ type Props = ApiProps & {
|
||||
accountId?: string,
|
||||
isDisabled?: boolean,
|
||||
label: React.ReactNode,
|
||||
onClick?: () => any,
|
||||
onFailed?: TxCallback,
|
||||
onSuccess?: TxCallback,
|
||||
onUpdate?: TxCallback,
|
||||
@ -42,7 +43,7 @@ class TxButtonInner extends React.PureComponent<Props & InjectedProps> {
|
||||
}
|
||||
|
||||
private send = (): void => {
|
||||
const { accountId, api, onFailed, onSuccess, onUpdate, params, queueExtrinsic, tx } = this.props;
|
||||
const { accountId, api, onClick, onFailed, onSuccess, onUpdate, params, queueExtrinsic, tx } = this.props;
|
||||
const [section, method] = tx.split('.');
|
||||
|
||||
assert(api.tx[section] && api.tx[section][method], `Unable to find api.tx.${section}.${method}`);
|
||||
@ -54,6 +55,8 @@ class TxButtonInner extends React.PureComponent<Props & InjectedProps> {
|
||||
txSuccessCb: onSuccess,
|
||||
txUpdateCb: onUpdate
|
||||
});
|
||||
|
||||
onClick && onClick();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user