From c269fdde42b33db95f73ef5ec926d3f6bb77519c Mon Sep 17 00:00:00 2001 From: anizeani <36300021+anizeani@users.noreply.github.com> Date: Mon, 3 Jan 2022 12:56:58 -0600 Subject: [PATCH] Tx should happen when InBlock and not wait until Block IsFinalized (#95) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #46, #101, #102 TransactionHandler saves tx when InBlock and not when Finalized to get faster UX. block hash and tx hash are displayed with link to subscan and copy button to copy hash to clipboard. Remarks: 1. I changed the font-size to 14 and removed the margin from the left of the status text (InBlock/Finalized + block/tx hashes), so that all the text fits in the window. Else, part of the hash is out of the window bound and you need to switch slide to the youtube slide to see the rest of the hash. 4. NEW: I have now added an error message to the status bar when a tx failed with its reasoning. Please add your remark if you want the error output differently or any other remark :) 5. ALSO NEW: I have added the display of the estimated fee. I fixed now a first estimated fee value for 0.1 ksm contribution (its 42.6662 µKSM). I'm not sure if this can change dramatically in the future, but when another value is entered, the estimated fee will be calculated. Inputting the estimated fee into the calculation of the available balance is somewhat problematic. the reason is, to get the estimate, we make a dummy contribution call "api.tx.crowdloan.contribute(paraId, data.value * Math.pow(10, 12), null).paymentInfo(sender)" The problem is now, if somebody enters a large contribution value (above 1000 or 10000 ksm), the dummy call overflows since 10^12 * 10^4 is too large and the page crashes. --- src/Participate.js | 23 ++++++-- src/css/App.css | 3 +- src/substrate-lib/components/TxButton.js | 74 +++++++++++++++--------- 3 files changed, 67 insertions(+), 33 deletions(-) diff --git a/src/Participate.js b/src/Participate.js index f9b5914..165f5b6 100644 --- a/src/Participate.js +++ b/src/Participate.js @@ -1,5 +1,4 @@ import React, { useState, useEffect, useMemo } from 'react'; - import './css/App.css'; import { Container, @@ -53,6 +52,7 @@ export default function Participate (props) { const [accountAddress, setAccountAddress] = useState(null); const [accountBalance, setAccountBalance] = useState(0); + const [estimatedFee, setEstimatedFee] = useState('42.3329 µKSM'); const minimumParticipation = 100000000000; // 0.1 const divide = 1000000000000; @@ -116,16 +116,27 @@ export default function Participate (props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const onChange = (_, data) => { + const onChange = async (_, data) => { setFormState((prev) => ({ ...prev, [data.state]: data.value })); + // let estimate = 0; if (!crowdLoanEnded) { + if (data.value >= 0.1) { + try { + const txExcecuteDummy = api.tx.crowdloan.contribute(paraId, data.value * Math.pow(10, 12), null); + const info = await txExcecuteDummy.paymentInfo(accountAddress); + setEstimatedFee(() => info.partialFee.toHuman()); + } catch (error) { + console.log(error); + } + // estimate = parseInt(info.partialFee); + } if (accountBalance < minimumParticipation) { setDisableButton(true); setStatus('You do not have enough balance'); } else if (data.value === '' || data.value < minimumParticipation / divide) { setDisableButton(true); setStatus('Please enter amount equal or greater than ' + minimumParticipation / divide); - } else if (data.value > (accountBalance / divide)) { + } else if (data.value > accountBalance / divide) { setDisableButton(true); setStatus('Please enter amount equal or less than ' + formatBalance(accountBalance)); } else { @@ -389,7 +400,11 @@ export default function Participate (props) { - + +
+ Estimated fees: {estimatedFee}
Please make sure when contributing, that your balance can cover the fees +
+
type === 'QUERY'; const isSudo = () => type === 'SUDO-TX'; const isUncheckedSudo = () => type === 'UNCHECKED-SUDO-TX'; @@ -68,8 +71,8 @@ function TxButton ({ return fromAcct; }; - const txResHandlerSaveTransaction = (status) => { - const hash = status.asFinalized.toString(); + const txResHandlerSaveTransaction = async (status) => { + const blockHash = status.asInBlock.toString(); if (isSigned()) { if (document.getElementById('grc') && document.getElementById('erc')) { saveParticipateInfo( @@ -79,7 +82,7 @@ function TxButton ({ document.getElementById('erc') ? document.getElementById('erc').value : new URL(window.location.href).searchParams.get('ref'), - hash + blockHash ); } else if (document.getElementById('erc')) { saveParticipateInfo( @@ -89,21 +92,51 @@ function TxButton ({ document.getElementById('erc') ? document.getElementById('erc').value : new URL(window.location.href).searchParams.get('ref'), - hash + blockHash ); } else if (document.getElementById('grc')) { - saveParticipateInfo(accountAddress, formState, document.getElementById('grc').value, '', hash); + saveParticipateInfo(accountAddress, formState, document.getElementById('grc').value, '', blockHash); } setLoading(false); } - setStatus(`😉 Finalized. Block hash: ${hash}`); + setStatus(viewTransactionInfo(status)); }; - const txResHandler = ({ status }) => { - status.isFinalized + const viewTransactionInfo = (status) => { + const _blockhash = (status.type === 'InBlock') ? status.asInBlock.toString() : status.asFinalized.toString(); + return ( +

+ {contributionError ? `Transaction failed: ${contributionError}` : ''} +
+ 😉 {status.type}. Block hash: {_blockhash}