Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: TransactionDetail.js to functional component #297

Merged
merged 1 commit into from
Aug 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 63 additions & 128 deletions src/screens/TransactionDetail.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,163 +5,98 @@
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import ReactLoading from 'react-loading';
import hathorLib from '@hathor/wallet-lib';
import { useParams } from 'react-router-dom';
import TxData from '../components/tx/TxData';
import txApi from '../api/txApi';
import metadataApi from '../api/metadataApi';
import hathorLib from '@hathor/wallet-lib';
import colors from '../index.scss';

/**
* Shows the detail of a transaction or block
*
* @memberof Screens
*/
class TransactionDetail extends React.Component {
constructor(props) {
super(props);

/**
* transaction {Object} Loaded transaction
* - `transaction.meta`: Will be created by `updateTxMetadata` with data from the explorer-service metadata
* loaded {boolean} If had success loading transaction from the server
* success {boolean} If a transaction was returned from the server or an error ocurred
* meta {Object} Metadata of loaded transaction received from the server
* spentOutputs {Object} Spent outputs of loaded transaction received from the server
* confirmationData {Object} Confirmation data of loaded transaction received from the server
*/
this.state = {
transaction: null,
meta: null,
spentOutputs: null,
loaded: false,
success: null,
confirmationData: null,
};
}

componentDidMount() {
this.getTx();
}

/**
* Get accumulated weight and confirmation level of the transaction
*/
getConfirmationData = () => {
txApi.getConfirmationData(this.props.match.params.id).then(
data => {
this.setState({ confirmationData: data });
},
e => {
// Error in request
console.log(e);
}
);
};
function TransactionDetail() {
const { id: txUid } = useParams();

/**
* Update state after receiving the transaction response back from the server
* transaction {Object} Loaded transaction
* - `transaction.meta`: Will be created by `updateTxMetadata` with data from the explorer-service metadata
*/
txReceived(data) {
if (data.success) {
this.setState({
transaction: data.tx,
meta: data.meta,
spentOutputs: data.spent_outputs,
loaded: true,
success: true,
});
} else {
this.setState({ loaded: true, success: false, transaction: null });
}
}
const [transaction, setTransaction] = useState(null);
/* meta {Object} Metadata of loaded transaction received from the server */
const [meta, setMeta] = useState(null);
/* loaded {boolean} If had success loading transaction from the server */
const [loaded, setLoaded] = useState(false);
/* spentOutputs {Object} Spent outputs of loaded transaction received from the server */
const [spentOutputs, setSpentOutputs] = useState(null);
/* confirmationData {Object} Confirmation data of loaded transaction received from the server */
const [confirmationData, setConfirmationData] = useState(null);

/**
* Get transaction in the server
*/
updateTxInfo = id => {
txApi.getTransaction(id).then(
data => {
this.txReceived(data);
if (data.success && !hathorLib.transactionUtils.isBlock(data.tx)) {
this.getConfirmationData();
}
},
e => {
// Error in request
console.log(e);
}
);
};
const updateTxInfo = useCallback(async id => {
const txData = await txApi.getTransaction(id);

/**
* Get transaction metadata from explorer service
*/
updateTxMetadata = id => {
metadataApi.getDagMetadata(id).then(data => {
if (data) {
this.setState(oldState => {
return {
transaction: {
...oldState.transaction,
meta: data,
},
};
});
}
});
};
setLoaded(true);
if (!txData.success) {
setTransaction(null);
setMeta(null);
setSpentOutputs(null);
setConfirmationData(null);
return;
}

/**
* Update transaction information when loading page
*/
getTx() {
this.updateTxInfo(this.props.match.params.id);
this.updateTxMetadata(this.props.match.params.id);
}
// Update state after receiving the transaction response back from the server
setTransaction(txData.tx);
setMeta(txData.meta);
setSpentOutputs(txData.spent_outputs);

/**
* When transaction changed in the page we need to load the new one and the new confirmation data
*/
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.match.params.id !== prevProps.match.params.id) {
this.getTx();
// Get accumulated weight and confirmation level of the transaction
if (!hathorLib.transactionUtils.isBlock(txData.tx)) {
const confirmationDataResponse = await txApi.getConfirmationData(id);
setConfirmationData(confirmationDataResponse);
}

// Get transaction metadata from explorer service, overwriting the one already obtained
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: This logic of overwriting the meta state was already present, I just made it more obvious by removing the intermediate functions that were doing the double work.

This may be fixed or better structured at a future moment, but the scope of this PR is only to refactor and not to change the logic.

const metadataResponse = await metadataApi.getDagMetadata(id);
if (metadataResponse) {
setMeta(metadataResponse);
}
}
}, []);

render() {
const renderTx = () => {
return (
<div>
{this.state.transaction ? (
<TxData
transaction={this.state.transaction}
confirmationData={this.state.confirmationData}
spentOutputs={this.state.spentOutputs}
meta={this.state.meta}
showRaw={true}
showConflicts={true}
/>
) : (
<p className="text-danger">
Transaction with hash {this.props.match.params.id} not found
</p>
)}
</div>
);
};
useEffect(() => {
updateTxInfo(txUid).catch(e => console.error(e));
}, [txUid, updateTxInfo]);

const renderTx = () => {
return (
<div className="flex align-items-center content-wrapper">
{!this.state.loaded ? (
<ReactLoading type="spin" color={colors.purpleHathor} delay={500} />
<div>
{transaction ? (
<TxData
transaction={transaction}
confirmationData={confirmationData}
spentOutputs={spentOutputs}
meta={meta}
showRaw={true}
showConflicts={true}
/>
) : (
renderTx()
<p className="text-danger">Transaction with hash {txUid} not found</p>
)}
</div>
);
}
};

return (
<div className="flex align-items-center content-wrapper">
{!loaded ? <ReactLoading type="spin" color={colors.purpleHathor} delay={500} /> : renderTx()}
</div>
);
}

export default TransactionDetail;