diff --git a/packages/page-assets/src/useAssetIds.ts b/packages/page-assets/src/useAssetIds.ts index 8a50975a2c..e3cdb11ea4 100644 --- a/packages/page-assets/src/useAssetIds.ts +++ b/packages/page-assets/src/useAssetIds.ts @@ -7,7 +7,7 @@ import type { EventRecord } from '@polkadot/types/interfaces'; import { createNamedHook, useApi, useEventChanges, useMapKeys } from '@polkadot/react-hooks'; -const keyOptions = { +const OPT_KEY = { transform: (keys: StorageKey<[u32]>[]): u32[] => keys.map(({ args: [id] }) => id) }; @@ -27,9 +27,9 @@ function filter (records: EventRecord[]): Changes { return { added, removed }; } -function useAssetIdsImpl (): u32[] { +function useAssetIdsImpl (): u32[] | undefined { const { api } = useApi(); - const startValue = useMapKeys(api.query.assets.asset, keyOptions); + const startValue = useMapKeys(api.query.assets.asset, OPT_KEY); return useEventChanges([ api.events.assets.Created, diff --git a/packages/page-nfts/src/useCollectionIds.ts b/packages/page-nfts/src/useCollectionIds.ts index d81755fa60..260dc417a6 100644 --- a/packages/page-nfts/src/useCollectionIds.ts +++ b/packages/page-nfts/src/useCollectionIds.ts @@ -29,7 +29,7 @@ function filter (records: EventRecord[]): Changes { return { added, removed }; } -function useCollectionIdsImpl (): u32[] { +function useCollectionIdsImpl (): u32[] | undefined { const { api } = useApi(); const startValue = useMapKeys(api.query.uniques.class, OPT_KEYS); diff --git a/packages/page-preimages/src/Add.tsx b/packages/page-preimages/src/Add.tsx new file mode 100644 index 0000000000..5c97629e10 --- /dev/null +++ b/packages/page-preimages/src/Add.tsx @@ -0,0 +1,127 @@ +// 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, Input, InputAddress, InputBalance, Modal, 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; + encodedProposal: string; + storageFee: BN; +} + +const ZERO_HASH = blake2AsHex(''); + +function Add ({ className, imageHash }: Props): React.ReactElement { + const { t } = useTranslation(); + const { api, apiDefaultTxSudo } = useApi(); + const [isAddOpen, toggleAdd] = useToggle(); + const [accountId, setAccountId] = useState(null); + const [{ encodedHash, encodedProposal, storageFee }, setHash] = useState({ encodedHash: ZERO_HASH, encodedProposal: '', storageFee: BN_ZERO }); + const [proposal, setProposal] = useState>(); + + useEffect((): void => { + const encodedProposal = (proposal as SubmittableExtrinsic<'promise'>)?.method.toHex() || ''; + const storageFee = api.consts.democracy.preimageByteDeposit.mul( + encodedProposal + ? new BN((encodedProposal.length - 2) / 2) + : BN_ZERO + ); + + setHash({ encodedHash: blake2AsHex(encodedProposal), encodedProposal, storageFee }); + }, [api, proposal]); + + const isMatched = imageHash + ? imageHash === encodedHash + : true; + + return ( + <> + {isAddOpen && ( + ('Submit preimage')} + onClose={toggleAdd} + size='large' + > + + ('This account will pay the fees for the preimage, based on the size thereof.')}> + ('The account you want to register the preimage from')} + label={t('send from account')} + labelExtra={ + {t('transferrable')}} + params={accountId} + /> + } + onChange={setAccountId} + type='account' + /> + + +

{t('The image (proposal) will be stored on-chain against the hash of the contents.')}

+

{t('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.')}

+ + } + > + ('propose')} + onChange={setProposal} + /> + ('The hash of the selected proposal, use it for submitting the proposal')} + isDisabledError={!isMatched} + label={t('preimage hash')} + value={encodedHash} + /> +
+ ('The calculated storage costs based on the size and the per-bytes fee.')}> + ('The amount reserved to store this image')} + isDisabled + label={t('calculated storage fee')} + /> + +
+ + ('Submit preimage')} + onStart={toggleAdd} + params={[encodedProposal]} + tx={api.tx.preimage.notePreimage} + /> + +
+ )} +