Fix actual exec (#3842)
* Fix actual exec * Adjust * Remove (now unused) api * Cleanup state on unmounted * Update * Use isPayable flag
This commit is contained in:
parent
031a38acde
commit
9d51e0462a
@ -10,8 +10,7 @@ import React, { useCallback, useState, useEffect, useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Button, Dropdown, IconLink, InputAddress, InputBalance, Modal, TxButton } from '@polkadot/react-components';
|
||||
import { PromiseContract as ApiContract } from '@polkadot/api-contract';
|
||||
import { useAccountId, useFormField, useToggle } from '@polkadot/react-hooks';
|
||||
import { createValue } from '@polkadot/react-params/values';
|
||||
import { useAccountId, useFormField } from '@polkadot/react-hooks';
|
||||
import { BN_ZERO } from '@polkadot/util';
|
||||
|
||||
import { InputMegaGas, Params } from '../shared';
|
||||
@ -34,23 +33,24 @@ function Call ({ callContract, callMessageIndex, className = '', onChangeCallCon
|
||||
const callMessage = callContract.abi.messages[callMessageIndex];
|
||||
const [accountId, setAccountId] = useAccountId();
|
||||
const [endowment, isEndowmentValid, setEndowment] = useFormField<BN>(BN_ZERO);
|
||||
const [isBusy, , setIsBusy] = useToggle();
|
||||
const [outcomes, setOutcomes] = useState<ContractCallOutcome[]>([]);
|
||||
const [execTx, setExecTx] = useState<SubmittableExtrinsic<'promise'> | null>(null);
|
||||
const [params, setParams] = useState<any[]>(callMessage ? callMessage.args.map(({ type }) => createValue({ type })) : []);
|
||||
const [params, setParams] = useState<any[]>([]);
|
||||
const useWeightHook = useWeight();
|
||||
const { isValid: isWeightValid, weight } = useWeightHook;
|
||||
|
||||
useEffect((): void => {
|
||||
const callMessage = callContract.abi.messages[callMessageIndex];
|
||||
|
||||
setParams(callMessage ? callMessage.args.map(({ type }) => createValue({ type })) : []);
|
||||
setParams([]);
|
||||
}, [callContract, callMessageIndex]);
|
||||
|
||||
useEffect((): void => {
|
||||
endowment && callContract.hasRpcContractsCall && callMessage.isMutating && setExecTx(
|
||||
() => callContract.exec(callMessage, endowment, weight, ...params)
|
||||
);
|
||||
endowment && callMessage.isMutating && setExecTx((): SubmittableExtrinsic<'promise'> | null => {
|
||||
try {
|
||||
return callContract.exec(callMessage, callMessage.isPayable ? endowment : 0, weight, ...params);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}, [accountId, callContract, callMessage, endowment, weight, params]);
|
||||
|
||||
const _onChangeCallMessageIndexString = useCallback(
|
||||
@ -104,7 +104,6 @@ function Call ({ callContract, callMessageIndex, className = '', onChangeCallCon
|
||||
<InputAddress
|
||||
defaultValue={accountId}
|
||||
help={t<string>('Specify the user account to use for this contract call. And fees will be deducted from this account.')}
|
||||
isDisabled={isBusy}
|
||||
label={t<string>('call from account')}
|
||||
onChange={setAccountId}
|
||||
type='account'
|
||||
@ -112,7 +111,6 @@ function Call ({ callContract, callMessageIndex, className = '', onChangeCallCon
|
||||
/>
|
||||
<InputAddress
|
||||
help={t<string>('A deployed contract that has either been deployed or attached. The address and ABI are used to construct the parameters.')}
|
||||
isDisabled={isBusy}
|
||||
label={t<string>('contract to use')}
|
||||
onChange={onChangeCallContractAddress}
|
||||
type='contract'
|
||||
@ -123,7 +121,6 @@ function Call ({ callContract, callMessageIndex, className = '', onChangeCallCon
|
||||
<Dropdown
|
||||
defaultValue={`${callMessageIndex}`}
|
||||
help={t<string>('The message to send to this contract. Parameters are adjusted based on the ABI provided.')}
|
||||
isDisabled={isBusy}
|
||||
isError={callMessage === null}
|
||||
label={t<string>('message to send')}
|
||||
onChange={_onChangeCallMessageIndexString}
|
||||
@ -131,7 +128,6 @@ function Call ({ callContract, callMessageIndex, className = '', onChangeCallCon
|
||||
value={`${callMessageIndex}`}
|
||||
/>
|
||||
<Params
|
||||
isDisabled={isBusy}
|
||||
onChange={setParams}
|
||||
params={
|
||||
callMessage
|
||||
@ -141,10 +137,9 @@ function Call ({ callContract, callMessageIndex, className = '', onChangeCallCon
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{!isViaRpc && (
|
||||
{!isViaRpc && callMessage.isPayable && (
|
||||
<InputBalance
|
||||
help={t<string>('The allotted value for this contract, i.e. the amount transferred to the contract as part of this call.')}
|
||||
isDisabled={isBusy}
|
||||
isError={!isEndowmentValid}
|
||||
isZeroable
|
||||
label={t<string>('value')}
|
||||
@ -197,9 +192,6 @@ function Call ({ callContract, callMessageIndex, className = '', onChangeCallCon
|
||||
icon='sign-in-alt'
|
||||
isDisabled={!isValid}
|
||||
label={t('Execute')}
|
||||
onClick={(): void => setIsBusy(true)}
|
||||
onFailed={(): void => setIsBusy(false)}
|
||||
onSuccess={(): void => setIsBusy(false)}
|
||||
withSpinner
|
||||
/>
|
||||
)
|
||||
|
||||
@ -6,7 +6,7 @@ import { TxButtonProps as Props } from './types';
|
||||
|
||||
import React, { useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { SubmittableResult } from '@polkadot/api';
|
||||
import { useApi } from '@polkadot/react-hooks';
|
||||
import { useApi, useIsMountedRef } from '@polkadot/react-hooks';
|
||||
import { assert, isFunction } from '@polkadot/util';
|
||||
|
||||
import Button from './Button';
|
||||
@ -16,6 +16,7 @@ import { useTranslation } from './translate';
|
||||
function TxButton ({ accountId, className = '', extrinsic: propsExtrinsic, icon, isBasic, isBusy, isDisabled, isIcon, isToplevel, isUnsigned, label, onClick, onFailed, onSendRef, onStart, onSuccess, onUpdate, params, tooltip, tx, withSpinner, withoutLink }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const mountedRef = useIsMountedRef();
|
||||
const { queueExtrinsic } = useContext(StatusContext);
|
||||
const [isSending, setIsSending] = useState(false);
|
||||
const [isStarted, setIsStarted] = useState(false);
|
||||
@ -27,25 +28,27 @@ function TxButton ({ accountId, className = '', extrinsic: propsExtrinsic, icon,
|
||||
|
||||
const _onFailed = useCallback(
|
||||
(result: SubmittableResult | null): void => {
|
||||
setIsSending(false);
|
||||
mountedRef.current && setIsSending(false);
|
||||
|
||||
onFailed && onFailed(result);
|
||||
},
|
||||
[onFailed, setIsSending]
|
||||
[onFailed, setIsSending, mountedRef]
|
||||
);
|
||||
|
||||
const _onSuccess = useCallback(
|
||||
(result: SubmittableResult): void => {
|
||||
setIsSending(false);
|
||||
mountedRef.current && setIsSending(false);
|
||||
|
||||
onSuccess && onSuccess(result);
|
||||
},
|
||||
[onSuccess, setIsSending]
|
||||
[onSuccess, setIsSending, mountedRef]
|
||||
);
|
||||
|
||||
const _onStart = useCallback(
|
||||
() => setIsStarted(true),
|
||||
[setIsStarted]
|
||||
(): void => {
|
||||
mountedRef.current && setIsStarted(true);
|
||||
},
|
||||
[setIsStarted, mountedRef]
|
||||
);
|
||||
|
||||
const _onSend = useCallback(
|
||||
@ -72,9 +75,7 @@ function TxButton ({ accountId, className = '', extrinsic: propsExtrinsic, icon,
|
||||
|
||||
assert(extrinsics?.length, 'Expected generated extrinsic passed to TxButton');
|
||||
|
||||
if (withSpinner) {
|
||||
setIsSending(true);
|
||||
}
|
||||
mountedRef.current && withSpinner && setIsSending(true);
|
||||
|
||||
extrinsics.forEach((extrinsic): void => {
|
||||
queueExtrinsic({
|
||||
@ -90,7 +91,7 @@ function TxButton ({ accountId, className = '', extrinsic: propsExtrinsic, icon,
|
||||
|
||||
onClick && onClick();
|
||||
},
|
||||
[_onFailed, _onStart, _onSuccess, accountId, api.tx, isUnsigned, onClick, onFailed, onSuccess, onUpdate, params, propsExtrinsic, queueExtrinsic, setIsSending, tx, withSpinner]
|
||||
[_onFailed, _onStart, _onSuccess, accountId, api.tx, isUnsigned, onClick, onFailed, onSuccess, onUpdate, params, propsExtrinsic, queueExtrinsic, setIsSending, tx, withSpinner, mountedRef]
|
||||
);
|
||||
|
||||
if (onSendRef) {
|
||||
|
||||
@ -3,13 +3,25 @@
|
||||
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import useIsMountedRef from './useIsMountedRef';
|
||||
|
||||
// Simple wrapper for a true/false toggle
|
||||
export default function useToggle (defaultValue = false, onToggle?: (isActive: boolean) => void): [boolean, () => void, (value: boolean) => void] {
|
||||
const mountedRef = useIsMountedRef();
|
||||
const [isActive, setActive] = useState(defaultValue);
|
||||
|
||||
const toggleActive = useCallback(
|
||||
() => setActive((isActive: boolean) => !isActive),
|
||||
[]
|
||||
const _toggleActive = useCallback(
|
||||
(): void => {
|
||||
mountedRef.current && setActive((isActive) => !isActive);
|
||||
},
|
||||
[mountedRef]
|
||||
);
|
||||
|
||||
const _setActive = useCallback(
|
||||
(isActive: boolean): void => {
|
||||
mountedRef.current && setActive(isActive);
|
||||
},
|
||||
[mountedRef]
|
||||
);
|
||||
|
||||
useEffect(
|
||||
@ -17,5 +29,5 @@ export default function useToggle (defaultValue = false, onToggle?: (isActive: b
|
||||
[isActive, onToggle]
|
||||
);
|
||||
|
||||
return [isActive, toggleActive, setActive];
|
||||
return [isActive, _toggleActive, _setActive];
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user