@polkadot/types/interfaces#FeeDetails TypeScript Examples

The following examples show how to use @polkadot/types/interfaces#FeeDetails. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: useEstimatedFeePayload.ts    From parity-bridges-ui with GNU General Public License v3.0 4 votes vote down vote up
useEstimatedFeePayload = (
  transactionState: TransactionState,
  dispatchTransaction: Dispatch<TransactionsActionType>
) => {
  const { createType, stateCall } = useApiCallsContext();

  const laneId = useLaneId();
  const sourceTargetDetails = useSourceTarget();
  const {
    sourceChainDetails: {
      chain: sourceChain,
      apiConnection: { api: sourceApi }
    },
    targetChainDetails: {
      apiConnection: { api: targetApi },
      chain: targetChain
    }
  } = sourceTargetDetails;
  const { account, senderAccountBalance, senderCompanionAccountBalance } = useAccountContext();
  const { action, isBridged } = useGUIContext();
  const { estimatedFeeMethodName } = getSubstrateDynamicNames(targetChain);
  const previousPayloadEstimatedFeeLoading = usePrevious(transactionState.payloadEstimatedFeeLoading);
  const { bridgedMessages } = getSubstrateDynamicNames(targetChain);

  const dispatch = useCallback(
    (error: string | null, data: PayloadEstimatedFee | null, loading: boolean) =>
      dispatchTransaction(
        TransactionActionCreators.setPayloadEstimatedFee({
          payloadEstimatedFeeError: error,
          payloadEstimatedFee: data,
          payloadEstimatedFeeLoading: loading,
          sourceTargetDetails,
          createType,
          isBridged,
          senderAccountBalance,
          senderCompanionAccountBalance,
          chainDecimals: targetApi.registry.chainDecimals[0]
        })
      ),
    [
      createType,
      dispatchTransaction,
      isBridged,
      senderAccountBalance,
      senderCompanionAccountBalance,
      sourceTargetDetails,
      targetApi.registry.chainDecimals
    ]
  );

  const calculateFeeAndPayload = useCallback(
    async (currentTransactionState: TransactionState) => {
      if (currentTransactionState.action === TransactionTypes.INTERNAL_TRANSFER) {
        const { estimatedFee, weight } = await getFeeAndWeightForInternals({
          api: sourceApi,
          transactionState: currentTransactionState
        });
        const payload = {
          sourceAccount: currentTransactionState.senderAccount,
          transferAmount: currentTransactionState.transferAmount!.toNumber(),
          receiverAddress: currentTransactionState.receiverAddress,
          weight
        };
        return { estimatedSourceFee: estimatedFee, payload };
      }
      const { call, weight } = await getTransactionCallWeight({
        action,
        account,
        targetApi,
        transactionState: currentTransactionState
      });

      if (!call || !weight) {
        return emptyData;
      }

      const callToCompact = currentTransactionState.action === TransactionTypes.CUSTOM ? call : call.slice(2);
      const payload = {
        call: compactAddLength(callToCompact),
        origin: {
          SourceAccount: account!.addressRaw
        },
        dispatch_fee_payment: currentTransactionState.payFee,
        spec_version: targetApi.consts.system.version.specVersion.toNumber(),
        weight
      };

      const payloadType = createType(sourceChain as keyof InterfaceTypes, 'OutboundPayload', payload);
      logger.info(`OutboundPayload: ${JSON.stringify(payload)}`);
      logger.info(`OutboundPayload.toHex(): ${payloadType.toHex()}`);
      const messageFeeType = createType(sourceChain as keyof InterfaceTypes, 'MessageFeeData', {
        lane_id: laneId,
        payload: payloadType.toHex()
      });

      // estimatedFeeMessageDelivery
      const estimatedFeeCall = await stateCall(sourceChain, estimatedFeeMethodName, messageFeeType.toHex());
      const estimatedFeeType = createType(sourceChain as keyof InterfaceTypes, 'Option<Balance>', estimatedFeeCall);
      const estimatedFeeMessageDelivery = estimatedFeeType.toString();

      // estimatedFeeBridgeCall
      const bridgeMessage = sourceApi.tx[bridgedMessages].sendMessage(laneId, payload, estimatedFeeCall);
      const submitMessageTransactionFee = await sourceApi.rpc.payment.queryFeeDetails(bridgeMessage.toHex());
      const estimatedFeeBridgeCallBalance = (submitMessageTransactionFee as FeeDetails).inclusionFee.unwrap()
        .adjustedWeightFee;
      const estimatedFeeBridgeCall = estimatedFeeBridgeCallBalance.toString();

      // estimatedSourceFee calculation based on the sum of estimatedFeeMessageDelivery + estimatedFeeBridgeCallBalance
      const estimatedSourceFeeBN = new BN(estimatedFeeMessageDelivery).add(estimatedFeeBridgeCallBalance.toBn());
      const estimatedSourceFee = estimatedSourceFeeBN.toString();

      // estimatedTargetFee
      const targetFeeDetails = await targetApi.rpc.payment.queryFeeDetails(u8aToHex(call));
      const estimatedTargetFee = (targetFeeDetails as FeeDetails).inclusionFee.unwrap().adjustedWeightFee.toString();

      return {
        estimatedSourceFee,
        estimatedFeeMessageDelivery,
        estimatedFeeBridgeCall,
        estimatedTargetFee,
        payload
      };
    },
    [
      account,
      action,
      bridgedMessages,
      createType,
      estimatedFeeMethodName,
      laneId,
      sourceApi,
      sourceChain,
      stateCall,
      targetApi
    ]
  );

  useEffect(() => {
    const { shouldEvaluatePayloadEstimatedFee, payloadEstimatedFeeLoading } = transactionState;

    if (shouldEvaluatePayloadEstimatedFee && payloadEstimatedFeeLoading) {
      logger.info(
        'Transaction information changed while estimated fee is being calculating. Batching the new calculation.'
      );
      dispatchTransaction(TransactionActionCreators.setBatchedEvaluationPayloadEstimatedFee(transactionState));
    }
    if (shouldEvaluatePayloadEstimatedFee && !payloadEstimatedFeeLoading) {
      genericCall({
        //@ts-ignore
        call: () => calculateFeeAndPayload(transactionState),
        dispatch,
        emptyData
      });
    }
  }, [calculateFeeAndPayload, dispatch, dispatchTransaction, transactionState]);

  useEffect(() => {
    const { batchedTransactionState, payloadEstimatedFeeLoading } = transactionState;

    if (
      previousPayloadEstimatedFeeLoading &&
      !payloadEstimatedFeeLoading &&
      batchedTransactionState &&
      senderAccountBalance &&
      senderCompanionAccountBalance
    ) {
      genericCall({
        //@ts-ignore
        call: () => calculateFeeAndPayload(batchedTransactionState),
        dispatch,
        emptyData
      });
      dispatchTransaction(TransactionActionCreators.setBatchedEvaluationPayloadEstimatedFee(null));
    }
  }, [
    account,
    calculateFeeAndPayload,
    dispatch,
    dispatchTransaction,
    previousPayloadEstimatedFeeLoading,
    senderAccountBalance,
    senderCompanionAccountBalance,
    transactionState
  ]);
}