diff --git a/packages/app-accounts/src/Account.tsx b/packages/app-accounts/src/Account.tsx index 8529f9cd8dd0..ba23adc9357a 100644 --- a/packages/app-accounts/src/Account.tsx +++ b/packages/app-accounts/src/Account.tsx @@ -7,12 +7,14 @@ import { I18nProps } from '@polkadot/ui-app/types'; import React from 'react'; import styled from 'styled-components'; -import { AddressSummary, Available, Balance, Bonded, Button, CryptoType, Nonce, Unlocking } from '@polkadot/ui-app'; +import { AddressSummary, Available, Balance, Bonded, Button, CryptoType, Icon, Nonce, Unlocking } from '@polkadot/ui-app'; import keyring from '@polkadot/ui-keyring'; import Backup from './modals/Backup'; import ChangePass from './modals/ChangePass'; import Forgetting from './modals/Forgetting'; +import Transfer from './modals/Transfer'; + import translate from './translate'; type Props = I18nProps & { @@ -23,7 +25,8 @@ type State = { isBackupOpen: boolean, isEditable: boolean, isForgetOpen: boolean, - isPasswordOpen: boolean + isPasswordOpen: boolean, + isTransferOpen: boolean }; const Wrapper = styled.article` @@ -111,7 +114,8 @@ class Account extends React.PureComponent { isBackupOpen: false, isEditable: !(keyring.getAccount(props.address).getMeta().isInjected), isForgetOpen: false, - isPasswordOpen: false + isPasswordOpen: false, + isTransferOpen: false }; } @@ -187,7 +191,7 @@ class Account extends React.PureComponent { private renderModals () { const { address } = this.props; - const { isBackupOpen, isForgetOpen, isPasswordOpen } = this.state; + const { isBackupOpen, isForgetOpen, isPasswordOpen, isTransferOpen } = this.state; if (!address) { return null; @@ -226,6 +230,16 @@ class Account extends React.PureComponent { ); } + if (isTransferOpen) { + modals.push( + + ); + } + return modals; } @@ -253,6 +267,14 @@ class Account extends React.PureComponent { }); } + private toggleTransfer = (): void => { + const { isTransferOpen } = this.state; + + this.setState({ + isTransferOpen: !isTransferOpen + }); + } + private onForget = (): void => { const { address, t } = this.props; @@ -314,32 +336,39 @@ class Account extends React.PureComponent { const { t } = this.props; const { isEditable } = this.state; - if (!isEditable) { - return null; - } - return (
+ {isEditable && ( + <> +
); diff --git a/packages/app-accounts/src/modals/Transfer.tsx b/packages/app-accounts/src/modals/Transfer.tsx new file mode 100644 index 000000000000..58fb1c895ebe --- /dev/null +++ b/packages/app-accounts/src/modals/Transfer.tsx @@ -0,0 +1,247 @@ +// Copyright 2017-2019 @polkadot/app-accounts 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 { ApiProps } from '@polkadot/ui-api/types'; +import { DerivedFees, DerivedBalances } from '@polkadot/api-derive/types'; +import { I18nProps } from '@polkadot/ui-app/types'; +import { SubmittableExtrinsic } from '@polkadot/api/promise/types'; + +import BN from 'bn.js'; +import React from 'react'; +import styled from 'styled-components'; +import { Button, InputAddress, InputBalance, Modal, TxButton } from '@polkadot/ui-app'; +import Checks, { calcSignatureLength } from '@polkadot/ui-signer/Checks'; +import { withApi, withCalls, withMulti } from '@polkadot/ui-api'; +import { ZERO_FEES } from '@polkadot/ui-signer/Checks/constants'; + +import translate from '../translate'; + +type Props = ApiProps & I18nProps & { + address: string, + balances_fees?: DerivedFees, + balances_votingBalance?: DerivedBalances, + onClose: () => void, + system_accountNonce?: BN +}; + +type State = { + amount: BN, + extrinsic: SubmittableExtrinsic | null, + hasAvailable: boolean, + maxBalance?: BN, + recipientId: string | null +}; + +const ZERO = new BN(0); + +const Wrapper = styled.div` + article.padded { + box-shadow: none; + margin: .75rem 15rem; + padding: 0; + } + + label.with-help { + flex-basis: 10rem; + } + + .ui--Labelled-content { + flex: initial; + width: 40em; + } +`; + +class Transfer extends React.PureComponent { + state: State = { + amount: ZERO, + extrinsic: null, + hasAvailable: true, + maxBalance: ZERO, + recipientId: null + }; + + componentDidUpdate (prevProps: Props, prevState: State) { + const { balances_fees } = this.props; + const { extrinsic, recipientId } = this.state; + + const hasLengthChanged = ((extrinsic && extrinsic.encodedLength) || 0) !== ((prevState.extrinsic && prevState.extrinsic.encodedLength) || 0); + + if ((recipientId && prevState.recipientId !== recipientId) || + (balances_fees !== prevProps.balances_fees) || + hasLengthChanged + ) { + this.setMaxBalance(); + } + } + + render () { + return ( + + {this.renderContent()} + {this.renderButtons()} + + ); + } + + private nextState (newState: Partial): void { + this.setState((prevState: State): State => { + const { api } = this.props; + const { amount = prevState.amount, recipientId = prevState.recipientId, hasAvailable = prevState.hasAvailable, maxBalance = prevState.maxBalance } = newState; + const extrinsic = recipientId + ? api.tx.balances.transfer(recipientId, amount) + : null; + + return { + amount, + extrinsic, + hasAvailable, + maxBalance, + recipientId + }; + }); + } + + private renderButtons () { + const { address, onClose, t } = this.props; + const { extrinsic, hasAvailable } = this.state; + + return ( + + +