Update fees, mortal & tips (#1590)

* Update fees, mortal & tips

* Linting

* Revert findCall

* Fix fee calculation (take version byte  into account)

* Remove MAX (weights), add weight note

* does not *
This commit is contained in:
Jaco Greeff 2019-09-18 14:53:51 +02:00 committed by GitHub
parent b987e33e04
commit f35b2d4428
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 58 additions and 53 deletions

View File

@ -14,7 +14,7 @@ import React from 'react';
import styled from 'styled-components';
import { Button, InputAddress, InputBalance, Modal, TxButton } from '@polkadot/react-components';
import { Available } from '@polkadot/react-query';
import Checks, { calcSignatureLength } from '@polkadot/react-signer/Checks';
import Checks, { calcTxLength } from '@polkadot/react-signer/Checks';
import { withApi, withCalls, withMulti } from '@polkadot/react-api';
import { ZERO_FEES } from '@polkadot/react-signer/Checks/constants';
import { bnMax } from '@polkadot/util';
@ -214,7 +214,7 @@ class Transfer extends React.PureComponent<Props, State> {
prevMax = maxBalance;
extrinsic = api.tx.balances.transfer(recipientId, prevMax);
const txLength = calcSignatureLength(extrinsic, accountNonce);
const txLength = calcTxLength(extrinsic, accountNonce);
const fees = transactionBaseFee
.add(transactionByteFee.mul(txLength))
.add(transferFee)

View File

@ -10,7 +10,7 @@ import { CalculateBalanceProps } from '../../types';
import BN from 'bn.js';
import React from 'react';
import { Available, Button, InputAddress, InputBalance, Modal, TxButton, TxComponent } from '@polkadot/react-components';
import { calcSignatureLength } from '@polkadot/react-signer/Checks';
import { calcTxLength } from '@polkadot/react-signer/Checks';
import { SubmittableExtrinsic } from '@polkadot/api/promise/types';
import { withCalls, withApi, withMulti } from '@polkadot/react-api';
import { ZERO_BALANCE, ZERO_FEES } from '@polkadot/react-signer/Checks/constants';
@ -159,7 +159,7 @@ class BondExtra extends TxComponent<Props, State> {
? api.tx.staking.bondExtra(maxAdditional)
: null;
const txLength = calcSignatureLength(extrinsic, system_accountNonce);
const txLength = calcTxLength(extrinsic, system_accountNonce);
const fees = transactionBaseFee.add(transactionByteFee.mul(txLength));
maxBalance = bnMax(availableBalance.sub(fees), ZERO);

View File

@ -10,7 +10,7 @@ import BN from 'bn.js';
import React from 'react';
import { ApiProps } from '@polkadot/react-api/types';
import { BitLengthOption } from '@polkadot/react-components/constants';
import { calcSignatureLength } from '@polkadot/react-signer/Checks';
import { calcTxLength } from '@polkadot/react-signer/Checks';
import { InputNumber } from '@polkadot/react-components';
import { SubmittableExtrinsic } from '@polkadot/api/promise/types';
import { withCalls, withMulti, withApi } from '@polkadot/react-api';
@ -124,7 +124,7 @@ class InputBalanceBonded extends React.PureComponent<Props, State> {
extrinsic = api.tx.staking.bonExtra(prevMax);
}
const txLength = calcSignatureLength(extrinsic, system_accountNonce);
const txLength = calcTxLength(extrinsic, system_accountNonce);
const fees = transactionBaseFee.add(transactionByteFee.mul(txLength));
maxBalance = bnMax(freeBalance.sub(fees), ZERO);

View File

@ -15,6 +15,8 @@ import Dropdown from './Dropdown';
import Input, { KEYS, KEYS_PRE } from './Input';
import translate from './translate';
const ALLOW_MAX = false;
interface Props extends BareProps, I18nProps {
autoFocus?: boolean;
bitLength?: BitLength;
@ -115,7 +117,7 @@ class InputNumber extends React.PureComponent<Props, State> {
type='text'
value={value}
>
{(withMax && !!maxValue) && this.renderMaxButton()}
{(ALLOW_MAX && withMax && !!maxValue) && this.renderMaxButton()}
{isSi && this.renderSiDropdown()}
</Input>
);

View File

@ -6,7 +6,7 @@ import { DerivedContractFees } from '@polkadot/api-derive/types';
import { ExtraFees as State } from './types';
import BN from 'bn.js';
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Compact, UInt } from '@polkadot/types';
interface Props {
@ -15,14 +15,14 @@ interface Props {
onChange: (fees: State) => void;
}
export default class ContractCall extends React.PureComponent<Props, State> {
public state: State = {
export default function ContractCall ({ endowment, fees, onChange }: Props): React.ReactElement<Props> | null {
const [state, setState] = useState<State>({
extraFees: new BN(0),
extraAmount: new BN(0),
extraWarn: false
};
});
public static getDerivedStateFromProps ({ endowment, fees, onChange }: Props, state: State): State {
useEffect((): void => {
const extraFees = new BN(fees.callBaseFee);
const extraAmount = endowment instanceof Compact
? endowment.toBn()
@ -38,10 +38,8 @@ export default class ContractCall extends React.PureComponent<Props, State> {
onChange(update);
}
return update;
}
setState(update);
}, [endowment, fees]);
public render (): React.ReactNode {
return null;
}
return null;
}

View File

@ -6,7 +6,7 @@ import { DerivedContractFees } from '@polkadot/api-derive/types';
import { ExtraFees as State } from './types';
import BN from 'bn.js';
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Compact, UInt } from '@polkadot/types';
interface Props {
@ -15,14 +15,14 @@ interface Props {
onChange: (fees: State) => void;
}
export default class ContractDeploy extends React.PureComponent<Props, State> {
public state: State = {
export default function ContractDeploy ({ endowment, fees, onChange }: Props): React.ReactElement<Props> | null {
const [state, setState] = useState<State>({
extraFees: new BN(0),
extraAmount: new BN(0),
extraWarn: false
};
});
public static getDerivedStateFromProps ({ endowment, fees, onChange }: Props, state: State): State {
useEffect((): void => {
const extraFees = new BN(fees.createBaseFee).add(fees.contractFee);
const extraAmount = endowment instanceof Compact
? endowment.toBn()
@ -38,10 +38,8 @@ export default class ContractDeploy extends React.PureComponent<Props, State> {
onChange(update);
}
return update;
}
setState(update);
}, [endowment, fees]);
public render (): React.ReactNode {
return null;
}
return null;
}

View File

@ -44,17 +44,22 @@ interface Props extends ApiProps, I18nProps {
isSendable: boolean;
onChange?: (hasAvailable: boolean) => void;
system_accountNonce?: BN;
tip?: BN;
}
const LENGTH_PUBLICKEY = 32 + 1; // publicKey + prefix
const LENGTH_SIGNATURE = 64;
const LENGTH_ERA = 1;
export const SIGNATURE_SIZE = LENGTH_PUBLICKEY + LENGTH_SIGNATURE + LENGTH_ERA;
const LENGTH_ADDRESS = 32 + 1; // publicKey + prefix
const LENGTH_ERA = 2; // assuming mortals
const LENGTH_SIGNATURE = 64; // assuming ed25519 or sr25519
const LENGTH_VERSION = 1; // 0x80 & version
export const calcSignatureLength = (extrinsic?: IExtrinsic | null, accountNonce?: BN): BN => {
export const calcTxLength = (extrinsic?: IExtrinsic | null, nonce?: BN, tip?: BN): BN => {
return new BN(
SIGNATURE_SIZE +
(accountNonce ? compactToU8a(accountNonce).length : 0) +
LENGTH_VERSION +
LENGTH_ADDRESS +
LENGTH_SIGNATURE +
LENGTH_ERA +
compactToU8a(nonce || 0).length +
compactToU8a(tip || 0).length +
(extrinsic ? extrinsic.encodedLength : 0)
);
};
@ -73,7 +78,7 @@ export class FeeDisplay extends React.PureComponent<Props, State> {
overLimit: false
};
public static getDerivedStateFromProps ({ accountId, balances_all = ZERO_BALANCE, api, extrinsic, balances_fees = ZERO_FEES_BALANCES, system_accountNonce = new BN(0) }: Props, prevState: State): State | null {
public static getDerivedStateFromProps ({ accountId, balances_all = ZERO_BALANCE, api, extrinsic, balances_fees = ZERO_FEES_BALANCES, system_accountNonce = new BN(0), tip }: Props, prevState: State): State | null {
if (!accountId || !extrinsic) {
return null;
}
@ -81,7 +86,7 @@ export class FeeDisplay extends React.PureComponent<Props, State> {
const fn = api.findCall(extrinsic.callIndex);
const extMethod = fn.method;
const extSection = fn.section;
const txLength = calcSignatureLength(extrinsic, system_accountNonce);
const txLength = calcTxLength(extrinsic, system_accountNonce, tip);
const isSameExtrinsic = prevState.extMethod === extMethod && prevState.extSection === extSection;
const extraAmount = isSameExtrinsic
@ -195,11 +200,12 @@ export class FeeDisplay extends React.PureComponent<Props, State> {
fees: formatBalance(allFees)
}
})}</div>
<div><Icon name='arrow right' />{t('{{total}} total transaction amount (fees + value)', {
<div><Icon name='arrow right' />{t('{{total}} estimated total amount (fees + value)', {
replace: {
total: formatBalance(allTotal)
}
})}</div>
<div><Icon name='dot circle outline' />{t('Estimation does not account for the transaction weight')}</div>
</article>
);
}

View File

@ -190,7 +190,7 @@ class Signer extends React.PureComponent<Props, State> {
}
private renderContent (): React.ReactNode {
const { currentItem, isQrScanning, isQrVisible, isSendable, qrAddress, qrPayload } = this.state;
const { currentItem, isQrScanning, isQrVisible, isSendable, qrAddress, qrPayload, tip } = this.state;
if (!currentItem) {
return null;
@ -200,6 +200,7 @@ class Signer extends React.PureComponent<Props, State> {
<Transaction
hideDetails={isQrVisible}
isSendable={isSendable}
tip={tip}
value={currentItem}
>
{

View File

@ -5,6 +5,7 @@
import { I18nProps } from '@polkadot/react-components/types';
import { QueueTx } from '@polkadot/react-components/Status/types';
import BN from 'bn.js';
import React from 'react';
import { GenericCall } from '@polkadot/types';
import { Call, InputAddress, Modal } from '@polkadot/react-components';
@ -16,10 +17,11 @@ interface Props extends I18nProps {
children?: React.ReactNode;
hideDetails?: boolean;
isSendable: boolean;
tip?: BN;
value: QueueTx;
}
function Transaction ({ children, hideDetails, isSendable, value: { accountId, extrinsic, isUnsigned }, t }: Props): React.ReactElement<Props> | null {
function Transaction ({ children, hideDetails, isSendable, value: { accountId, extrinsic, isUnsigned }, t, tip }: Props): React.ReactElement<Props> | null {
if (!extrinsic) {
return null;
}
@ -55,6 +57,7 @@ function Transaction ({ children, hideDetails, isSendable, value: { accountId, e
accountId={accountId}
extrinsic={extrinsic}
isSendable={isSendable}
tip={tip}
/>
)}
</>

View File

@ -3,12 +3,11 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { BareProps } from '@polkadot/react-components/types';
import { QueueProps } from '@polkadot/react-components/Status/types';
import './index.css';
import React from 'react';
import { QueueConsumer } from '@polkadot/react-components/Status/Context';
import React, { useContext } from 'react';
import QueueContext from '@polkadot/react-components/Status/Context';
import Modal from './Modal';
@ -17,20 +16,18 @@ interface Props extends BareProps {
}
export default function Signer ({ children, className, style }: Props): React.ReactElement<Props> {
const { txqueue, queueSetTxStatus } = useContext(QueueContext);
return (
<>
{children}
<QueueConsumer>
{({ txqueue, queueSetTxStatus }: QueueProps): React.ReactNode => (
<Modal
className={className}
key='signer-modal'
queue={txqueue}
queueSetTxStatus={queueSetTxStatus}
style={style}
/>
)}
</QueueConsumer>
<Modal
className={className}
key='signer-modal'
queue={txqueue}
queueSetTxStatus={queueSetTxStatus}
style={style}
/>
</>
);
}