mirror of
https://github.com/pezkuwichain/pezkuwi-apps.git
synced 2026-04-22 15:57:59 +00:00
7a4bbeac25
- Update @pezkuwi/extension-inject to ^0.62.13 with proper /types exports - Update @pezkuwi/extension-dapp to ^0.62.13 - Update @pezkuwi/extension-compat-metamask to ^0.62.13 - Fix IconTheme type to include 'bizinikiwi' and 'pezkuwi' themes - Fix endpoint array issues (getTeleports -> direct array references) - Add type assertions for external package compatibility (acala, moonbeam, parallel) - Fix subspace.ts dynamic class typing - Fix conviction type in page-referenda - Update Pallet type names to Pezpallet prefix across codebase - Define InjectedExtension types locally for module resolution - Add styled-components DefaultTheme augmentation - Add react-copy-to-clipboard type declaration for React 18 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
98 lines
3.8 KiB
TypeScript
98 lines
3.8 KiB
TypeScript
// Copyright 2017-2026 @pezkuwi/react-signer authors & contributors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
import type { SubmittableExtrinsic } from '@pezkuwi/api/promise/types';
|
|
import type { DeriveBalancesAll } from '@pezkuwi/api-derive/types';
|
|
import type { RuntimeDispatchInfo } from '@pezkuwi/types/interfaces';
|
|
import type { ExtendedSignerOptions } from './types.js';
|
|
|
|
import React, { useEffect, useState } from 'react';
|
|
import { Trans } from 'react-i18next';
|
|
|
|
import { Expander, MarkWarning } from '@pezkuwi/react-components';
|
|
import { useApi, useCall, useIsMountedRef } from '@pezkuwi/react-hooks';
|
|
import { BN, formatBalance, nextTick } from '@pezkuwi/util';
|
|
|
|
import { useTranslation } from './translate.js';
|
|
|
|
interface Props {
|
|
accountId?: string | null;
|
|
className?: string;
|
|
extrinsic?: SubmittableExtrinsic | null;
|
|
isHeader?: boolean;
|
|
onChange?: (hasAvailable: boolean) => void;
|
|
tip?: BN;
|
|
signerOptions: ExtendedSignerOptions;
|
|
}
|
|
|
|
function PaymentInfo ({ accountId, className = '', extrinsic, isHeader, signerOptions }: Props): React.ReactElement<Props> | null {
|
|
const { t } = useTranslation();
|
|
const { api } = useApi();
|
|
const [dispatchInfo, setDispatchInfo] = useState<RuntimeDispatchInfo | null>(null);
|
|
const balances = useCall<DeriveBalancesAll>(api.derive.balances?.all, [accountId]);
|
|
const mountedRef = useIsMountedRef();
|
|
|
|
useEffect((): void => {
|
|
accountId && extrinsic && extrinsic.hasPaymentInfo &&
|
|
nextTick(async (): Promise<void> => {
|
|
setDispatchInfo(null);
|
|
|
|
try {
|
|
const info = await extrinsic.paymentInfo(accountId, signerOptions);
|
|
|
|
if (signerOptions?.assetId) {
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const convertedFee = new BN((await api.call.assetConversionApi.quotePriceTokensForExactTokens(
|
|
signerOptions?.assetId as any,
|
|
{
|
|
interior: 'Here',
|
|
parents: 1
|
|
} as any,
|
|
info.partialFee,
|
|
true
|
|
)).toString());
|
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
mountedRef.current && setDispatchInfo({ ...info, partialFee: convertedFee });
|
|
} else {
|
|
mountedRef.current && setDispatchInfo(info);
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
});
|
|
}, [api, accountId, extrinsic, mountedRef, signerOptions]);
|
|
|
|
if (!dispatchInfo || !extrinsic) {
|
|
return null;
|
|
}
|
|
|
|
const isFeeError = api.consts.balances && !(api.tx.balances?.transferAllowDeath?.is(extrinsic) || api.tx.balances?.transfer?.is(extrinsic)) && balances?.accountId.eq(accountId) && (
|
|
(balances.transferable || balances.availableBalance).lte(dispatchInfo.partialFee) ||
|
|
balances.freeBalance.sub(dispatchInfo.partialFee).lte(api.consts.balances.existentialDeposit)
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<Expander
|
|
className={className}
|
|
isHeader={isHeader}
|
|
summary={
|
|
<Trans i18nKey='feesForSubmission'>
|
|
Fees of <span className='highlight'>
|
|
{formatBalance(dispatchInfo.partialFee, { decimals: signerOptions?.feeAsset?.metadata.decimals.toNumber() ?? api.registry.chainDecimals.at(0), withSiFull: true }).split(' ').slice(0, -1).join(' ')}{' '}
|
|
{signerOptions?.feeAsset?.metadata.symbol.toHuman()?.toString() ?? api.registry.chainTokens.at(0) }
|
|
</span> will be applied to the submission
|
|
</Trans>
|
|
}
|
|
/>
|
|
{isFeeError && (
|
|
<MarkWarning content={t('The account does not have enough free funds (excluding locked/bonded/reserved) available to cover the transaction fees without dropping the balance below the account existential amount.')} />
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default React.memo(PaymentInfo);
|