import { ContractPromise } from '@polkadot/api-contract'; import { ContractOptions } from '@polkadot/api-contract/types'; import { useMemo, useState } from 'react'; import { DecodedContractTxResult } from '../../types/contracts.js'; import { SignerOptions } from '../../types/mod.js'; import { call } from '../../utils/mod.js'; import { useAbiMessage } from './useAbiMessage.js'; import { useExtension } from '../useExtension.js'; export type DryRunResult = DecodedContractTxResult; export type Send = ( args?: unknown[], o?: ContractOptions, signerOptions?: SignerOptions, ) => Promise | undefined>; interface DryRun { send: Send; isSubmitting: boolean; result?: DryRunResult; resolved: Boolean; resetState: () => void; } export function useDryRun( contract: ContractPromise | undefined, message: string, ): DryRun { const { account, extension } = useExtension(); const [result, setResult] = useState>(); const [isSubmitting, setIsSubmitting] = useState(false); const abiMessage = useAbiMessage(contract, message); const send: Send = useMemo( () => async (params, options) => { const tx = contract?.tx?.[message]; if (!account || !contract || !extension || !abiMessage || !tx) return; setIsSubmitting(true); try { const resp = await call( contract, abiMessage, account.address, params, options, ); if (!resp || !resp.ok) return; const { gasConsumed, gasRequired, storageDeposit } = resp.value.raw; const requiresNoArguments = tx.meta.args.length === 0; const { partialFee } = await (requiresNoArguments ? tx(options || {}) : tx(options || {}, params)) .paymentInfo(account.address); const r = { ...resp, value: { ...resp.value, gasRequired, gasConsumed, storageDeposit, partialFee, }, }; setIsSubmitting(false); setResult(r); return r; } catch (e: unknown) { console.error(e); setIsSubmitting(false); return; } }, [account, extension, contract, abiMessage], ); return { send, isSubmitting, result, resolved: Boolean(result && !isSubmitting), resetState: () => { setIsSubmitting(false); setResult(undefined); }, }; }