From f19202c81e5b268b8bd99590e4f8455f638a795a Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Fri, 6 Sep 2019 11:43:05 +0200 Subject: [PATCH] Extra warning & no max on isUnsafeChain (#1588) --- .../src/Actions/Account/BondExtra.tsx | 12 ++++-- .../Account/InputValidationController.tsx | 9 +++- .../Actions/Account/SetControllerAccount.tsx | 37 +++++++---------- packages/app-staking/src/Actions/NewStake.tsx | 41 +++++++------------ packages/app-staking/src/unsafeChains.ts | 9 ++++ 5 files changed, 54 insertions(+), 54 deletions(-) create mode 100644 packages/app-staking/src/unsafeChains.ts diff --git a/packages/app-staking/src/Actions/Account/BondExtra.tsx b/packages/app-staking/src/Actions/Account/BondExtra.tsx index 057de6590f..35d60bf9cf 100644 --- a/packages/app-staking/src/Actions/Account/BondExtra.tsx +++ b/packages/app-staking/src/Actions/Account/BondExtra.tsx @@ -17,10 +17,12 @@ import { ZERO_BALANCE, ZERO_FEES } from '@polkadot/react-signer/Checks/constants import { bnMax } from '@polkadot/util'; import translate from '../../translate'; +import detectUnsafe from '../../unsafeChains'; interface Props extends I18nProps, ApiProps, CalculateBalanceProps { controllerId: string; isOpen: boolean; + isUnsafeChain: boolean; onClose: () => void; stashId: string; } @@ -92,7 +94,7 @@ class BondExtra extends TxComponent { } private renderContent (): React.ReactNode { - const { stashId, t } = this.props; + const { isUnsafeChain, stashId, t } = this.props; const { maxBalance } = this.state; const available = {t('available ')}; @@ -117,7 +119,7 @@ class BondExtra extends TxComponent { maxValue={maxBalance} onChange={this.onChangeValue} onEnter={this.sendTx} - withMax + withMax={!isUnsafeChain} /> @@ -182,6 +184,10 @@ export default withMulti( withCalls( 'derive.balances.fees', ['derive.balances.all', { paramName: 'stashId' }], - ['query.system.accountNonce', { paramName: 'stashId' }] + ['query.system.accountNonce', { paramName: 'stashId' }], + ['rpc.system.chain', { + propName: 'isUnsafeChain', + transform: detectUnsafe + }] ) ); diff --git a/packages/app-staking/src/Actions/Account/InputValidationController.tsx b/packages/app-staking/src/Actions/Account/InputValidationController.tsx index f1660817ea..1fd78946f1 100644 --- a/packages/app-staking/src/Actions/Account/InputValidationController.tsx +++ b/packages/app-staking/src/Actions/Account/InputValidationController.tsx @@ -18,6 +18,7 @@ interface Props extends ApiProps, I18nProps { bondedId?: string | null; controllerId: string | null; defaultController?: string; + isUnsafeChain?: boolean; onError: (error: string | null) => void; stashId?: string | null; } @@ -26,19 +27,23 @@ interface State { error: string | null; } +const DISTINCT = 'Distinct stash and controller accounts are recommended to ensure fund security.'; + class ValidateController extends React.PureComponent { public state: State = { error: null }; - public static getDerivedStateFromProps ({ accountId, bondedId, controllerId, defaultController, onError, stashId, t }: Props, prevState: State): State { + public static getDerivedStateFromProps ({ accountId, bondedId, controllerId, defaultController, isUnsafeChain, onError, stashId, t }: Props, prevState: State): State { const error = ((): string | null => { if (defaultController === controllerId) { // don't show an error if the selected controller is the default // this applies when changing controller return null; } else if (controllerId === accountId) { - return t('Distinct stash and controller accounts are recommended to ensure fund security'); + return isUnsafeChain + ? t(`${DISTINCT} You will be allowed to make the transaction, but take care to not tie up all funds, only use a portion of the available funds during this period.`) + : t(DISTINCT); } else if (bondedId) { return t('A controller account should not map to another stash. This selected controller is a stash, controlled by {{bondedId}}', { replace: { bondedId } }); } else if (stashId) { diff --git a/packages/app-staking/src/Actions/Account/SetControllerAccount.tsx b/packages/app-staking/src/Actions/Account/SetControllerAccount.tsx index 2be1706721..e1c06e4baa 100644 --- a/packages/app-staking/src/Actions/Account/SetControllerAccount.tsx +++ b/packages/app-staking/src/Actions/Account/SetControllerAccount.tsx @@ -7,24 +7,22 @@ import { I18nProps } from '@polkadot/react-components/types'; import React from 'react'; import { Button, Icon, InputAddress, Modal, TxButton, TxComponent } from '@polkadot/react-components'; import { withCalls, withMulti } from '@polkadot/react-api'; -import { Text } from '@polkadot/types'; import translate from '../../translate'; -import { NO_VALIDATION_CHAINS } from '../NewStake'; +import detectUnsafe from '../../unsafeChains'; import InputValidationController from '../Account/InputValidationController'; interface Props extends I18nProps { defaultControllerId: string; + isUnsafeChain?: boolean; isValidating?: boolean; onClose: () => void; stashId: string; - systemChain?: Text; } interface State { controllerError: string | null; controllerId: string | null; - ignoreController: boolean; } class SetControllerAccount extends TxComponent { @@ -33,25 +31,14 @@ class SetControllerAccount extends TxComponent { this.state = { controllerError: null, - controllerId: null, - ignoreController: false - }; - } - - public static getDerivedStateFromProps ({ systemChain }: Props): Pick | null { - if (!systemChain) { - return null; - } - - return { - ignoreController: NO_VALIDATION_CHAINS.includes(systemChain.toString()) + controllerId: null }; } public render (): React.ReactNode { - const { defaultControllerId, onClose, stashId, t } = this.props; - const { controllerError, controllerId, ignoreController } = this.state; - const canSubmit = ignoreController || (!controllerError && !!controllerId && (defaultControllerId !== controllerId)); + const { defaultControllerId, isUnsafeChain, onClose, stashId, t } = this.props; + const { controllerError, controllerId } = this.state; + const canSubmit = isUnsafeChain || (!controllerError && !!controllerId && (defaultControllerId !== controllerId)); return ( { } private renderContent (): React.ReactNode { - const { defaultControllerId, stashId, t } = this.props; - const { controllerId, controllerError, ignoreController } = this.state; + const { defaultControllerId, isUnsafeChain, stashId, t } = this.props; + const { controllerId, controllerError } = this.state; return ( <> @@ -106,7 +93,7 @@ class SetControllerAccount extends TxComponent { className='medium' defaultValue={defaultControllerId} help={t('The controller is the account that will be used to control any nominating or validating actions. Should not match another stash or controller.')} - isError={!ignoreController && !!controllerError} + isError={!isUnsafeChain && !!controllerError} label={t('controller account')} onChange={this.onChangeController} type='account' @@ -116,6 +103,7 @@ class SetControllerAccount extends TxComponent { accountId={stashId} defaultController={defaultControllerId} controllerId={controllerId} + isUnsafeChain={isUnsafeChain} onError={this.onControllerError} /> @@ -153,6 +141,9 @@ export default withMulti( SetControllerAccount, translate, withCalls( - ['rpc.system.chain', { propName: 'systemChain' }] + ['rpc.system.chain', { + propName: 'isUnsafeChain', + transform: detectUnsafe + }] ) ); diff --git a/packages/app-staking/src/Actions/NewStake.tsx b/packages/app-staking/src/Actions/NewStake.tsx index 8a49f9a3f3..f31ce4b02b 100644 --- a/packages/app-staking/src/Actions/NewStake.tsx +++ b/packages/app-staking/src/Actions/NewStake.tsx @@ -11,15 +11,15 @@ import React from 'react'; import { SubmittableExtrinsic } from '@polkadot/api/promise/types'; import { Button, Dropdown, InputAddress, InputBalanceBonded, Modal, TxButton, TxComponent } from '@polkadot/react-components'; import { withCalls, withMulti } from '@polkadot/react-api'; -import { Text } from '@polkadot/types'; import translate from '../translate'; +import detectUnsafe from '../unsafeChains'; import InputValidationController from './Account/InputValidationController'; import { rewardDestinationOptions } from './constants'; interface Props extends ApiProps, I18nProps, CalculateBalanceProps { + isUnsafeChain?: boolean; onClose: () => void; - systemChain?: Text; } interface State { @@ -28,12 +28,9 @@ interface State { controllerId: string | null; destination: number; extrinsic: SubmittableExtrinsic | null; - ignoreController: boolean; stashId: string | null; } -export const NO_VALIDATION_CHAINS = ['Development', 'Kusama CC1', 'Kusama']; - class NewStake extends TxComponent { public state: State; @@ -45,26 +42,15 @@ class NewStake extends TxComponent { controllerId: null, destination: 0, extrinsic: null, - ignoreController: false, stashId: null }; } - public static getDerivedStateFromProps ({ systemChain }: Props): Pick | null { - if (!systemChain) { - return null; - } - - return { - ignoreController: NO_VALIDATION_CHAINS.includes(systemChain.toString()) - }; - } - public render (): React.ReactNode { - const { onClose, t } = this.props; - const { bondValue, controllerError, controllerId, extrinsic, ignoreController, stashId } = this.state; + const { isUnsafeChain, onClose, t } = this.props; + const { bondValue, controllerError, controllerId, extrinsic, stashId } = this.state; const hasValue = !!bondValue && bondValue.gtn(0); - const canSubmit = (hasValue && (ignoreController || (!controllerError && !!controllerId))); + const canSubmit = (hasValue && (isUnsafeChain || (!controllerError && !!controllerId))); return ( { } private renderContent (): React.ReactNode { - const { t } = this.props; - const { controllerId, controllerError, bondValue, destination, ignoreController, stashId } = this.state; + const { isUnsafeChain, t } = this.props; + const { controllerId, controllerError, bondValue, destination, stashId } = this.state; const hasValue = !!bondValue && bondValue.gtn(0); return ( @@ -118,7 +104,7 @@ class NewStake extends TxComponent { { { onChange={this.onChangeValue} onEnter={this.sendTx} stashId={stashId} - withMax + withMax={!isUnsafeChain} /> { private nextState (newState: Partial): void { this.setState((prevState: State): State => { const { api } = this.props; - const { bondValue = prevState.bondValue, controllerError = prevState.controllerError, controllerId = prevState.controllerId, destination = prevState.destination, ignoreController = prevState.ignoreController, stashId = prevState.stashId } = newState; + const { bondValue = prevState.bondValue, controllerError = prevState.controllerError, controllerId = prevState.controllerId, destination = prevState.destination, stashId = prevState.stashId } = newState; const extrinsic = (bondValue && controllerId) ? api.tx.staking.bond(controllerId, bondValue, destination) : null; @@ -171,7 +158,6 @@ class NewStake extends TxComponent { controllerId, destination, extrinsic, - ignoreController, stashId }; }); @@ -202,6 +188,9 @@ export default withMulti( NewStake, translate, withCalls( - ['rpc.system.chain', { propName: 'systemChain' }] + ['rpc.system.chain', { + propName: 'isUnsafeChain', + transform: detectUnsafe + }] ) ); diff --git a/packages/app-staking/src/unsafeChains.ts b/packages/app-staking/src/unsafeChains.ts new file mode 100644 index 0000000000..efd2034223 --- /dev/null +++ b/packages/app-staking/src/unsafeChains.ts @@ -0,0 +1,9 @@ +// 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. + +export const UNSAFE_CHAINS = ['Development', 'Kusama CC1', 'Kusama']; + +export default function detectUnsafe (chain: Text | string): boolean { + return UNSAFE_CHAINS.includes(chain.toString()); +}