Skip to content

Commit

Permalink
Feat: Improve displaying payloads on Block page (#983)
Browse files Browse the repository at this point in the history
* feat: Add infra to support OutputPage (nova)

* feat: add block page for nova

* fix: Add initial Block page structure

* fix: Add initial Block page structure

* feat: Add View for tagged data payload and signed transaction payload

* fix: add block payload section and transaction helper

* feat: add block transaction metadata tab

* fix: format

* fix: add max burned mana

* fix: improve block with transaction payload

* fix: improve validation block

* fix: improve candidacy announcement and block page title

* fix: lint

* fix: remove nested transaction from block payload section

* fix: insantiate block using Plain Instance to a class in useBlock

---------

Co-authored-by: Mario Sarcevic <[email protected]>
Co-authored-by: Begoña Álvarez de la Cruz <[email protected]>
  • Loading branch information
3 people authored Jan 25, 2024
1 parent 3d63185 commit 0520137
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 103 deletions.
52 changes: 52 additions & 0 deletions client/src/app/components/nova/ContextInputView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
BlockIssuanceCreditContextInput,
CommitmentContextInput,
ContextInput,
ContextInputType,
RewardContextInput,
} from "@iota/sdk-wasm-nova/web";
import React from "react";
import TruncatedId from "../stardust/TruncatedId";
import { useNetworkInfoNova } from "~/helpers/nova/networkInfo";

interface IContextInputViewProps {
readonly contextInput: ContextInput;
}

const ContextInputView: React.FC<IContextInputViewProps> = ({ contextInput }) => {
const { name: network } = useNetworkInfoNova((s) => s.networkInfo);
if (contextInput.type === ContextInputType.COMMITMENT) {
const input = contextInput as CommitmentContextInput;

return (
<div className="section--data">
<div className="label">Commitment id</div>
<div className="value code">{input.commitmentId}</div>
</div>
);
} else if (contextInput.type === ContextInputType.BLOCK_ISSUANCE_CREDIT) {
const input = contextInput as BlockIssuanceCreditContextInput;

return (
<div className="section--data">
<div className="label">Account</div>
<div className="value code">
<TruncatedId id={input.accountId} link={`/${network}/account/${input.accountId}`} showCopyButton />
</div>
</div>
);
} else if (contextInput.type === ContextInputType.REWARD) {
const input = contextInput as RewardContextInput;

return (
<div className="section--data">
<div className="label">Reward Input Index</div>
<div className="value code">{input.index}</div>
</div>
);
}

return null;
};

export default ContextInputView;
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ interface BlockPayloadSectionProps {

const BlockPayloadSection: React.FC<BlockPayloadSectionProps> = ({ block, inputs, outputs, transferTotal }) => {
const payload = (block.body as BasicBlockBody).payload;

if (payload?.type === PayloadType.SignedTransaction && inputs && outputs && transferTotal !== undefined) {
const transactionPayload = payload as ISignedTransactionPayload;
const transaction = transactionPayload.transaction;
Expand All @@ -36,13 +37,6 @@ const BlockPayloadSection: React.FC<BlockPayloadSectionProps> = ({ block, inputs
)}
</React.Fragment>
);
} else if (payload?.type === PayloadType.CandidacyAnnouncement) {
return (
<div>
{/* todo */}
CandidacyAnnouncement
</div>
);
} else if (payload?.type === PayloadType.TaggedData) {
return (
<div className="section">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,68 +1,97 @@
import classNames from "classnames";
import { TRANSACTION_FAILURE_REASON_STRINGS, TransactionMetadata } from "@iota/sdk-wasm-nova/web";
import { TRANSACTION_FAILURE_REASON_STRINGS, Transaction, TransactionMetadata } from "@iota/sdk-wasm-nova/web";
import React from "react";
import "./TransactionMetadataSection.scss";
import Spinner from "../../../Spinner";
import TruncatedId from "~/app/components/stardust/TruncatedId";
import ContextInputView from "../../ContextInputView";
import { useNetworkInfoNova } from "~/helpers/nova/networkInfo";

interface TransactionMetadataSectionProps {
readonly network: string;
readonly metadata?: TransactionMetadata;
readonly transaction?: Transaction;
readonly transactionMetadata?: TransactionMetadata;
readonly metadataError?: string;
readonly isLinksDisabled: boolean;
}

const TransactionMetadataSection: React.FC<TransactionMetadataSectionProps> = ({ network, metadata, metadataError, isLinksDisabled }) => (
<div className="section metadata-section">
<div className="section--data">
{!metadata && !metadataError && <Spinner />}
{metadataError && <p className="danger">Failed to retrieve metadata. {metadataError}</p>}
{metadata && !metadataError && (
<React.Fragment>
<div className="section--data">
<div className="label">Transaction Id</div>
<div className="value code">
<TruncatedId
id={metadata.transactionId}
showCopyButton
link={isLinksDisabled ? undefined : `/${network}/transaction/${metadata.transactionId}`}
/>
</div>
</div>
<div className="section--data">
<div className="label">Transaction Status</div>
<div className="value row middle capitalize-text">
<div
className={classNames(
"transaction-tangle-state",
{
"transaction-tangle-state__confirmed":
metadata.transactionState === "accepted" || "confirmed" || "finalized",
},
{
"transaction-tangle-state__conflicting": metadata.transactionState === "failed",
},
{ "transaction-tangle-state__pending": metadata.transactionState === "pending" },
const TransactionMetadataSection: React.FC<TransactionMetadataSectionProps> = ({ transaction, transactionMetadata, metadataError }) => {
const { name: network } = useNetworkInfoNova((s) => s.networkInfo);

return (
<div className="section metadata-section">
<div className="section--data">
{!transactionMetadata && !metadataError && <Spinner />}
{metadataError ? (
<p className="danger">Failed to retrieve metadata. {metadataError}</p>
) : (
<React.Fragment>
{transactionMetadata && (
<>
<div className="section--data">
<div className="label">Transaction Status</div>
<div className="value row middle capitalize-text">
<div
className={classNames(
"transaction-tangle-state",
{
"transaction-tangle-state__confirmed":
transactionMetadata.transactionState === "accepted" || "confirmed" || "finalized",
},
{
"transaction-tangle-state__conflicting":
transactionMetadata.transactionState === "failed",
},
{ "transaction-tangle-state__pending": transactionMetadata.transactionState === "pending" },
)}
>
{transactionMetadata.transactionState}
</div>
</div>
</div>
{transactionMetadata.transactionFailureReason && (
<div className="section--data">
<div className="label">Failure Reason</div>
<div className="value">
{TRANSACTION_FAILURE_REASON_STRINGS[transactionMetadata.transactionFailureReason]}
</div>
</div>
)}
</>
)}
{transaction && (
<>
<div className="section--data">
<div className="label">Creation slot</div>
<div className="value code">{transaction.creationSlot}</div>
</div>
{transaction?.contextInputs?.map((contextInput, idx) => (
<ContextInputView contextInput={contextInput} key={idx} />
))}
{transaction?.allotments && (
<div className="section--data">
<div className="label">Mana Allotment Accounts</div>
{transaction?.allotments?.map((allotment, idx) => (
<div className="value code highlight margin-b-t" key={idx}>
<TruncatedId
id={allotment.accountId}
link={`/${network}/account/${allotment.accountId}`}
showCopyButton
/>
</div>
))}
</div>
)}
>
{metadata.transactionState}
</div>
</div>
</div>
{metadata.transactionFailureReason && (
<div className="section--data">
<div className="label">Failure Reason</div>
<div className="value">{TRANSACTION_FAILURE_REASON_STRINGS[metadata.transactionFailureReason]}</div>
</div>
)}
</React.Fragment>
)}
</>
)}
</React.Fragment>
)}
</div>
</div>
</div>
);
);
};

TransactionMetadataSection.defaultProps = {
metadata: undefined,
transactionMetadata: undefined,
transaction: undefined,
metadataError: undefined,
};

Expand Down
Loading

0 comments on commit 0520137

Please sign in to comment.