Split notePreimage generation into partial (#8622)
* Split notePreimage generation into partial * Remove old Add * Move storageFee to proposal calculation * s/Proposal/Partial/ * Renames * Adjust * Text adjust
This commit is contained in:
parent
8bf34a4e59
commit
de4b94fe43
@ -1,141 +0,0 @@
|
||||
// Copyright 2017-2022 @polkadot/app-preimages authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { SubmittableExtrinsic } from '@polkadot/api/types';
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { Button, Extrinsic, InputAddress, InputBalance, Modal, Static, TxButton } from '@polkadot/react-components';
|
||||
import { useApi, useToggle } from '@polkadot/react-hooks';
|
||||
import { Available } from '@polkadot/react-query';
|
||||
import { BN, BN_ZERO } from '@polkadot/util';
|
||||
import { blake2AsHex } from '@polkadot/util-crypto';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
imageHash?: string;
|
||||
}
|
||||
|
||||
interface HashState {
|
||||
encodedHash: string;
|
||||
encodedLength: number;
|
||||
encodedProposal: string;
|
||||
storageFee: BN;
|
||||
}
|
||||
|
||||
const ZERO_HASH = blake2AsHex('');
|
||||
|
||||
function Add ({ className, imageHash }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api, apiDefaultTxSudo } = useApi();
|
||||
const [isAddOpen, toggleAdd] = useToggle();
|
||||
const [accountId, setAccountId] = useState<string | null>(null);
|
||||
const [{ encodedHash, encodedLength, encodedProposal, storageFee }, setHash] = useState<HashState>({ encodedHash: ZERO_HASH, encodedLength: 0, encodedProposal: '', storageFee: BN_ZERO });
|
||||
const [proposal, setProposal] = useState<SubmittableExtrinsic<'promise'>>();
|
||||
|
||||
useEffect((): void => {
|
||||
// get the proposal in hex format, i.e. we don't want the length prefix
|
||||
const encodedProposal = (proposal as SubmittableExtrinsic<'promise'>)?.method.toHex() || '';
|
||||
|
||||
// we are dealing with hex values here, so subtrack the prefix (+ 2 chars per byte)
|
||||
const encodedLength = Math.max(0, Math.round((encodedProposal.length - 2) / 2));
|
||||
|
||||
// we currently don't have a constant exposed, or rather, maybe somewhere else...
|
||||
// const storageFee = api.consts.democracy.preimageByteDeposit.mul(
|
||||
// encodedProposal
|
||||
// ? new BN((encodedProposal.length - 2) / 2)
|
||||
// : BN_ZERO
|
||||
// );
|
||||
|
||||
setHash({ encodedHash: blake2AsHex(encodedProposal), encodedLength, encodedProposal, storageFee: BN_ZERO });
|
||||
}, [api, proposal]);
|
||||
|
||||
const isMatched = imageHash
|
||||
? imageHash === encodedHash
|
||||
: true;
|
||||
|
||||
return (
|
||||
<>
|
||||
{isAddOpen && (
|
||||
<Modal
|
||||
className={className}
|
||||
header={t<string>('Submit preimage')}
|
||||
onClose={toggleAdd}
|
||||
size='large'
|
||||
>
|
||||
<Modal.Content>
|
||||
<Modal.Columns hint={t<string>('This account will pay the fees for the preimage, based on the size thereof.')}>
|
||||
<InputAddress
|
||||
help={t<string>('The account you want to register the preimage from')}
|
||||
label={t<string>('send from account')}
|
||||
labelExtra={
|
||||
<Available
|
||||
label={<span className='label'>{t<string>('transferrable')}</span>}
|
||||
params={accountId}
|
||||
/>
|
||||
}
|
||||
onChange={setAccountId}
|
||||
type='account'
|
||||
/>
|
||||
</Modal.Columns>
|
||||
<Modal.Columns hint={
|
||||
<>
|
||||
<p>{t<string>('The image (proposal) will be stored on-chain against the hash of the contents.')}</p>
|
||||
<p>{t<string>('When submitting a proposal the hash needs to be known. Proposals can be submitted with hash-only, but upon dispatch the preimage needs to be available.')}</p>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Extrinsic
|
||||
defaultValue={apiDefaultTxSudo}
|
||||
label={t<string>('propose')}
|
||||
onChange={setProposal}
|
||||
/>
|
||||
<Static
|
||||
help={t<string>('The hash of the selected proposal, use it for submitting the proposal')}
|
||||
label={t<string>('preimage hash')}
|
||||
value={encodedHash}
|
||||
withCopy
|
||||
/>
|
||||
<Static
|
||||
help={t<string>('The encoded length of the selected proposal, as available on-chain')}
|
||||
label={t<string>('preimage length')}
|
||||
value={encodedLength.toString()}
|
||||
withCopy
|
||||
/>
|
||||
</Modal.Columns>
|
||||
{!storageFee.isZero() && (
|
||||
<Modal.Columns hint={t<string>('The calculated storage costs based on the size and the per-bytes fee.')}>
|
||||
<InputBalance
|
||||
defaultValue={storageFee}
|
||||
help={t<string>('The amount reserved to store this image')}
|
||||
isDisabled
|
||||
label={t<string>('calculated storage fee')}
|
||||
/>
|
||||
</Modal.Columns>
|
||||
)}
|
||||
</Modal.Content>
|
||||
<Modal.Actions>
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
icon='plus'
|
||||
isDisabled={!proposal || !accountId || !isMatched || !encodedProposal}
|
||||
label={t<string>('Submit preimage')}
|
||||
onStart={toggleAdd}
|
||||
params={[encodedProposal]}
|
||||
tx={api.tx.preimage.notePreimage}
|
||||
/>
|
||||
</Modal.Actions>
|
||||
</Modal>
|
||||
)}
|
||||
<Button
|
||||
icon='plus'
|
||||
label={t<string>('Add preimage')}
|
||||
onClick={toggleAdd}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Add);
|
||||
127
packages/page-preimages/src/Preimages/Add/Partial.tsx
Normal file
127
packages/page-preimages/src/Preimages/Add/Partial.tsx
Normal file
@ -0,0 +1,127 @@
|
||||
// Copyright 2017-2022 @polkadot/app-preimages authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { ApiPromise } from '@polkadot/api';
|
||||
import type { SubmittableExtrinsic } from '@polkadot/api/types';
|
||||
import type { BN } from '@polkadot/util';
|
||||
import type { HexString } from '@polkadot/util/types';
|
||||
import type { HashState } from './types';
|
||||
|
||||
import React, { useCallback, useState } from 'react';
|
||||
|
||||
import { Extrinsic, InputBalance, Modal, Static } from '@polkadot/react-components';
|
||||
import { useApi } from '@polkadot/react-hooks';
|
||||
import { BN_ZERO } from '@polkadot/util';
|
||||
import { blake2AsHex } from '@polkadot/util-crypto';
|
||||
|
||||
import { useTranslation } from '../../translate';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
onChange: (state: HashState) => void;
|
||||
}
|
||||
|
||||
const EMPTY_HASH = blake2AsHex('');
|
||||
|
||||
export const EMPTY_PROPOSAL: HashState = {
|
||||
encodedHash: EMPTY_HASH,
|
||||
encodedLength: 0,
|
||||
encodedProposal: null,
|
||||
notePreimageTx: null,
|
||||
storageFee: BN_ZERO
|
||||
};
|
||||
|
||||
function getState (api: ApiPromise, proposal?: SubmittableExtrinsic<'promise'>): HashState {
|
||||
let encodedHash = EMPTY_HASH;
|
||||
let encodedProposal: HexString | null = null;
|
||||
let encodedLength = 0;
|
||||
let notePreimageTx: SubmittableExtrinsic<'promise'> | null = null;
|
||||
let storageFee = BN_ZERO;
|
||||
|
||||
if (proposal) {
|
||||
encodedProposal = proposal.method.toHex();
|
||||
encodedLength = Math.ceil((encodedProposal.length - 2) / 2);
|
||||
encodedHash = blake2AsHex(encodedProposal);
|
||||
notePreimageTx = api.tx.preimage.notePreimage(encodedProposal);
|
||||
|
||||
// we currently don't have a constant exposed, however match to Substrate
|
||||
storageFee = ((api.consts.preimage?.baseDeposit || BN_ZERO) as unknown as BN).add(
|
||||
((api.consts.preimage?.byteDeposit || BN_ZERO) as unknown as BN).muln(encodedLength)
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
encodedHash,
|
||||
encodedLength,
|
||||
encodedProposal,
|
||||
notePreimageTx,
|
||||
storageFee
|
||||
};
|
||||
}
|
||||
|
||||
function Partial ({ className, onChange }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api, apiDefaultTxSudo } = useApi();
|
||||
const [{ encodedHash, encodedLength, storageFee }, setState] = useState<HashState>(EMPTY_PROPOSAL);
|
||||
|
||||
const changeState = useCallback(
|
||||
(state: HashState): void => {
|
||||
setState(state);
|
||||
onChange(state);
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
|
||||
const setProposal = useCallback(
|
||||
(proposal?: SubmittableExtrinsic<'promise'>) =>
|
||||
changeState(getState(api, proposal)),
|
||||
[api, changeState]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal.Columns
|
||||
className={className}
|
||||
hint={
|
||||
<>
|
||||
<p>{t<string>('The image (proposal) will be stored on-chain against the hash of the contents.')}</p>
|
||||
<p>{t<string>('When submitting a proposal the hash needs to be known. Proposals can be submitted with hash-only, but upon dispatch the preimage needs to be available.')}</p>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Extrinsic
|
||||
defaultValue={apiDefaultTxSudo}
|
||||
label={t<string>('propose')}
|
||||
onChange={setProposal}
|
||||
/>
|
||||
<Static
|
||||
help={t<string>('The hash of the selected proposal, use it for submitting the proposal')}
|
||||
label={t<string>('preimage hash')}
|
||||
value={encodedHash}
|
||||
withCopy
|
||||
/>
|
||||
<Static
|
||||
help={t<string>('The encoded length of the selected proposal, as available on-chain')}
|
||||
label={t<string>('preimage length')}
|
||||
value={encodedLength || '0'}
|
||||
withCopy
|
||||
/>
|
||||
</Modal.Columns>
|
||||
{!storageFee.isZero() && (
|
||||
<Modal.Columns
|
||||
className={className}
|
||||
hint={t<string>('The calculated storage costs based on the base and the per-bytes fee.')}
|
||||
>
|
||||
<InputBalance
|
||||
defaultValue={storageFee}
|
||||
help={t<string>('The amount reserved to store this image')}
|
||||
isDisabled
|
||||
label={t<string>('calculated storage fee')}
|
||||
/>
|
||||
</Modal.Columns>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Partial);
|
||||
75
packages/page-preimages/src/Preimages/Add/index.tsx
Normal file
75
packages/page-preimages/src/Preimages/Add/index.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright 2017-2022 @polkadot/app-preimages authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { HashState } from './types';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { Button, InputAddress, Modal, TxButton } from '@polkadot/react-components';
|
||||
import { useToggle } from '@polkadot/react-hooks';
|
||||
import { Available } from '@polkadot/react-query';
|
||||
|
||||
import { useTranslation } from '../../translate';
|
||||
import Proposal, { EMPTY_PROPOSAL } from './Partial';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
imageHash?: string;
|
||||
}
|
||||
|
||||
function Add ({ className, imageHash }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const [isAddOpen, toggleAdd] = useToggle();
|
||||
const [accountId, setAccountId] = useState<string | null>(null);
|
||||
const [{ encodedHash, notePreimageTx }, setProposal] = useState<HashState>(EMPTY_PROPOSAL);
|
||||
|
||||
const isMatched = !imageHash || imageHash === encodedHash;
|
||||
|
||||
return (
|
||||
<>
|
||||
{isAddOpen && (
|
||||
<Modal
|
||||
className={className}
|
||||
header={t<string>('Submit preimage')}
|
||||
onClose={toggleAdd}
|
||||
size='large'
|
||||
>
|
||||
<Modal.Content>
|
||||
<Modal.Columns hint={t<string>('This account will pay the fees for the preimage, based on the size thereof.')}>
|
||||
<InputAddress
|
||||
help={t<string>('The account you want to register the preimage from')}
|
||||
label={t<string>('send from account')}
|
||||
labelExtra={
|
||||
<Available
|
||||
label={<span className='label'>{t<string>('transferrable')}</span>}
|
||||
params={accountId}
|
||||
/>
|
||||
}
|
||||
onChange={setAccountId}
|
||||
type='account'
|
||||
/>
|
||||
</Modal.Columns>
|
||||
<Proposal onChange={setProposal} />
|
||||
</Modal.Content>
|
||||
<Modal.Actions>
|
||||
<TxButton
|
||||
accountId={accountId}
|
||||
extrinsic={notePreimageTx}
|
||||
icon='plus'
|
||||
isDisabled={!accountId || !isMatched || !notePreimageTx}
|
||||
label={t<string>('Submit preimage')}
|
||||
onStart={toggleAdd}
|
||||
/>
|
||||
</Modal.Actions>
|
||||
</Modal>
|
||||
)}
|
||||
<Button
|
||||
icon='plus'
|
||||
label={t<string>('Add preimage')}
|
||||
onClick={toggleAdd}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Add);
|
||||
14
packages/page-preimages/src/Preimages/Add/types.ts
Normal file
14
packages/page-preimages/src/Preimages/Add/types.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2017-2022 @polkadot/app-preimages authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { SubmittableExtrinsic } from '@polkadot/api/types';
|
||||
import type { BN } from '@polkadot/util';
|
||||
import type { HexString } from '@polkadot/util/types';
|
||||
|
||||
export interface HashState {
|
||||
encodedHash: HexString;
|
||||
encodedLength: number;
|
||||
encodedProposal?: HexString | null;
|
||||
notePreimageTx?: SubmittableExtrinsic<'promise'> | null;
|
||||
storageFee: BN;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user