diff --git a/web/cashtab/src/components/Wallet/Tx.js b/web/cashtab/src/components/Wallet/Tx.js --- a/web/cashtab/src/components/Wallet/Tx.js +++ b/web/cashtab/src/components/Wallet/Tx.js @@ -5,6 +5,7 @@ ArrowUpOutlined, ArrowDownOutlined, ExperimentOutlined, + ExclamationOutlined, } from '@ant-design/icons'; import { currency } from '@components/Common/Ticker'; import makeBlockie from 'ethereum-blockies-base64'; @@ -20,6 +21,9 @@ const GenesisTx = styled(ExperimentOutlined)` color: ${props => props.theme.primary} !important; `; +const UnparsedTx = styled(ExclamationOutlined)` + color: ${props => props.theme.primary} !important; +`; const DateType = styled.div` text-align: left; padding: 12px; @@ -147,48 +151,81 @@ typeof data.blocktime === 'undefined' ? new Date().toLocaleDateString() : new Date(data.blocktime * 1000).toLocaleDateString(); - + // if data only includes height and txid, then the tx could not be parsed by cashtab + // render as such but keep link to block explorer + let unparsedTx = false; + if (!Object.keys(data).includes('outgoingTx')) { + unparsedTx = true; + } return ( - - - {data.outgoingTx ? ( - <> - {data.tokenTx && - data.tokenInfo.transactionType === 'GENESIS' ? ( - + <> + {unparsedTx ? ( + + + + + + Unparsed +
+ {txDate} +
+ Open in Explorer +
+ ) : ( + + + {data.outgoingTx ? ( + <> + {data.tokenTx && + data.tokenInfo.transactionType === 'GENESIS' ? ( + + ) : ( + + )} + ) : ( - + )} - - ) : ( - - )} - - - {data.outgoingTx ? ( - <> - {data.tokenTx && - data.tokenInfo.transactionType === 'GENESIS' ? ( - Genesis +
+ + {data.outgoingTx ? ( + <> + {data.tokenTx && + data.tokenInfo.transactionType === 'GENESIS' ? ( + Genesis + ) : ( + Sent + )} + ) : ( - Sent + Received )} - - ) : ( - Received - )} -
- {txDate} -
- {data.tokenTx ? ( - - {data.tokenTx && data.tokenInfo ? ( - <> - - {currency.tokenIconsUrl !== '' ? ( - + {txDate} + + {data.tokenTx ? ( + + {data.tokenTx && data.tokenInfo ? ( + <> + + {currency.tokenIconsUrl !== '' ? ( + {`identicon + } + /> + ) : ( {`identicon - } - /> - ) : ( - {`identicon - )} - - {data.outgoingTx ? ( - <> - {data.tokenInfo.transactionType === - 'GENESIS' ? ( + + {data.outgoingTx ? ( <> - - +{' '} - {data.tokenInfo.qtyReceived.toString()} -   - {data.tokenInfo.tokenTicker} - - - {data.tokenInfo.tokenName} - + {data.tokenInfo.transactionType === + 'GENESIS' ? ( + <> + + +{' '} + {data.tokenInfo.qtyReceived.toString()} +   + { + data.tokenInfo + .tokenTicker + } + + + { + data.tokenInfo + .tokenName + } + + + ) : ( + <> + + -{' '} + {data.tokenInfo.qtySent.toString()} +   + { + data.tokenInfo + .tokenTicker + } + + + { + data.tokenInfo + .tokenName + } + + + )} ) : ( <> - -{' '} - {data.tokenInfo.qtySent.toString()} + +{' '} + {data.tokenInfo.qtyReceived.toString()}   {data.tokenInfo.tokenTicker} @@ -244,84 +294,79 @@ )} ) : ( - <> - - +{' '} - {data.tokenInfo.qtyReceived.toString()} -  {data.tokenInfo.tokenTicker} - - - {data.tokenInfo.tokenName} - - + Token Tx )} - + ) : ( - Token Tx - )} - - ) : ( - <> - - {data.outgoingTx ? ( - <> - -{' '} - {formatBalance( - fromLegacyDecimals(data.amountSent), - )}{' '} - {currency.ticker} -
- {fiatPrice !== null && !isNaN(data.amountSent) && ( - + <> + + {data.outgoingTx ? ( + <> -{' '} - { - currency.fiatCurrencies[ - fiatCurrency - ].symbol - } - {( + {formatBalance( + fromLegacyDecimals(data.amountSent), + )}{' '} + {currency.ticker} +
+ {fiatPrice !== null && + !isNaN(data.amountSent) && ( + + -{' '} + { + currency.fiatCurrencies[ + fiatCurrency + ].symbol + } + {( + fromLegacyDecimals( + data.amountSent, + ) * fiatPrice + ).toFixed(2)}{' '} + { + currency.fiatCurrencies + .fiatCurrency + } + + )} + + ) : ( + <> + +{' '} + {formatBalance( fromLegacyDecimals( - data.amountSent, - ) * fiatPrice - ).toFixed(2)}{' '} - {currency.fiatCurrencies.fiatCurrency} -
+ data.amountReceived, + ), + )}{' '} + {currency.ticker} +
+ {fiatPrice !== null && + !isNaN(data.amountReceived) && ( + + +{' '} + { + currency.fiatCurrencies[ + fiatCurrency + ].symbol + } + {( + fromLegacyDecimals( + data.amountReceived, + ) * fiatPrice + ).toFixed(2)}{' '} + { + currency.fiatCurrencies + .fiatCurrency + } + + )} + )} - - ) : ( - <> - +{' '} - {formatBalance( - fromLegacyDecimals(data.amountReceived), - )}{' '} - {currency.ticker} -
- {fiatPrice !== null && - !isNaN(data.amountReceived) && ( - - +{' '} - { - currency.fiatCurrencies[ - fiatCurrency - ].symbol - } - {( - fromLegacyDecimals( - data.amountReceived, - ) * fiatPrice - ).toFixed(2)}{' '} - { - currency.fiatCurrencies - .fiatCurrency - } - - )} - - )} -
- + + + )} +
)} - + ); }; diff --git a/web/cashtab/src/components/Wallet/__tests__/__snapshots__/Wallet.test.js.snap b/web/cashtab/src/components/Wallet/__tests__/__snapshots__/Wallet.test.js.snap --- a/web/cashtab/src/components/Wallet/__tests__/__snapshots__/Wallet.test.js.snap +++ b/web/cashtab/src/components/Wallet/__tests__/__snapshots__/Wallet.test.js.snap @@ -3,7 +3,7 @@ exports[`Wallet with BCH balances 1`] = ` Array [
,
0 @@ -119,16 +119,16 @@
,
XEC
eToken @@ -140,7 +140,7 @@ exports[`Wallet with BCH balances and tokens 1`] = ` Array [
,
0 @@ -256,16 +256,16 @@
,
XEC
eToken @@ -277,14 +277,14 @@ exports[`Wallet with BCH balances and tokens and state field 1`] = ` Array [
0.06047469 XEC
,
$ NaN @@ -375,16 +375,16 @@
,
XEC
eToken @@ -396,7 +396,7 @@ exports[`Wallet without BCH balance 1`] = ` Array [
,
0 @@ -512,16 +512,16 @@
,
XEC
eToken diff --git a/web/cashtab/src/hooks/useBCH.js b/web/cashtab/src/hooks/useBCH.js --- a/web/cashtab/src/hooks/useBCH.js +++ b/web/cashtab/src/hooks/useBCH.js @@ -91,18 +91,30 @@ const parsedTxHistory = []; for (let i = 0; i < txData.length; i += 1) { const tx = txData[i]; + const parsedTx = {}; + // Move over info that does not need to be calculated parsedTx.txid = tx.txid; - parsedTx.confirmations = tx.confirmations; parsedTx.height = tx.height; + let destinationAddress = tx.address; + + // If this tx had too many inputs to be parsed by getTxDataWithPassThrough, skip it + // When this occurs, the tx will only have txid and height + // So, it will not have 'vin' + if (!Object.keys(tx).includes('vin')) { + // Populate as a limited-info tx that can be expanded in a block explorer + parsedTxHistory.push(parsedTx); + continue; + } + + parsedTx.confirmations = tx.confirmations; parsedTx.blocktime = tx.blocktime; let amountSent = 0; let amountReceived = 0; // Assume an incoming transaction let outgoingTx = false; let tokenTx = false; - let destinationAddress = tx.address; // If vin includes tx address, this is an outgoing tx // Note that with bch-input data, we do not have input amounts @@ -141,7 +153,6 @@ } } // Construct parsedTx - parsedTx.txid = tx.txid; parsedTx.amountSent = amountSent; parsedTx.amountReceived = amountReceived; parsedTx.tokenTx = tokenTx; @@ -177,9 +188,19 @@ const getTxDataWithPassThrough = async (BCH, flatTx) => { // necessary as BCH.RawTransactions.getTxData does not return address or blockheight - const txDataWithPassThrough = await BCH.RawTransactions.getTxData( - flatTx.txid, - ); + let txDataWithPassThrough = {}; + try { + txDataWithPassThrough = await BCH.RawTransactions.getTxData( + flatTx.txid, + ); + } catch (err) { + console.log( + `Error in BCH.RawTransactions.getTxData(${flatTx.txid})`, + ); + console.log(err); + // Include txid if you don't get it from the attempted response + txDataWithPassThrough.txid = flatTx.txid; + } txDataWithPassThrough.height = flatTx.height; txDataWithPassThrough.address = flatTx.address; return txDataWithPassThrough;