Skip to content

Commit

Permalink
feat: Add mana details to Output page (#1016)
Browse files Browse the repository at this point in the history
* feat: Add mana details to metadata section of Output page (stored with decay, potential, total) for spent and unspent outputs

* feat: Bump SDK-nova commit. Fix OutputPage outputMetadata usage.

* feat: Simplify buildManaDetailsForOutput call

---------

Co-authored-by: Begoña Álvarez de la Cruz <[email protected]>
Co-authored-by: Branko Bosnic <[email protected]>
  • Loading branch information
3 people authored Jan 31, 2024
1 parent adc2050 commit 6cadacd
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 19 deletions.
6 changes: 0 additions & 6 deletions api/src/services/nova/novaApiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,12 @@ import { HexHelper } from "../../utils/hexHelper";
* Class to interact with the nova API.
*/
export class NovaApiService {
/**
* The network in context.
*/
private readonly network: INetwork;

/**
* The client to use for requests.
*/
private readonly client: Client;

constructor(network: INetwork) {
this.network = network;
this.client = ServiceFactory.get<Client>(`client-${network.network}`);
}

Expand Down
2 changes: 2 additions & 0 deletions client/src/app/AppUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export const populateNetworkInfoNova = (networkName: string) => {
name: networkName,
tokenInfo: nodeInfo?.baseToken ?? {},
protocolVersion: protocolInfo?.parameters.version ?? -1,
protocolInfo,
latestConfirmedSlot: nodeInfo?.status?.latestConfirmedBlockSlot ?? -1,
bech32Hrp: protocolInfo?.parameters.bech32Hrp ?? "",
});
}
Expand Down
6 changes: 3 additions & 3 deletions client/src/app/components/nova/OutputView.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import DropdownIcon from "~assets/dropdown-arrow.svg?react";
import classNames from "classnames";
import {
Expand Down Expand Up @@ -34,8 +34,8 @@ interface OutputViewProps {
}

const OutputView: React.FC<OutputViewProps> = ({ outputId, output, showCopyAmount, isPreExpanded, isLinksDisabled }) => {
const [isExpanded, setIsExpanded] = React.useState(isPreExpanded ?? false);
const [isFormattedBalance, setIsFormattedBalance] = React.useState(true);
const [isExpanded, setIsExpanded] = useState(isPreExpanded ?? false);
const [isFormattedBalance, setIsFormattedBalance] = useState(true);
const { bech32Hrp, name: network } = useNetworkInfoNova((s) => s.networkInfo);

const aliasOrNftBech32 = buildAddressForAliasOrNft(outputId, output, bech32Hrp);
Expand Down
69 changes: 61 additions & 8 deletions client/src/app/routes/nova/OutputPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import OutputView from "~/app/components/nova/OutputView";
import { useOutputDetails } from "~/helpers/nova/hooks/useOutputDetails";
import CopyButton from "~/app/components/CopyButton";
import TruncatedId from "~/app/components/stardust/TruncatedId";
import { useNetworkInfoNova } from "~/helpers/nova/networkInfo";
import { buildManaDetailsForOutput, OutputManaDetails } from "~/helpers/nova/manaUtils";
import { Converter } from "~/helpers/stardust/convertUtils";
import "./OutputPage.scss";

interface OutputPageProps {
Expand All @@ -27,6 +30,7 @@ const OutputPage: React.FC<RouteComponentProps<OutputPageProps>> = ({
},
}) => {
const { output, outputMetadataResponse, error } = useOutputDetails(network, outputId);
const { protocolInfo, latestConfirmedSlot } = useNetworkInfoNova((s) => s.networkInfo);

if (error) {
return (
Expand All @@ -45,7 +49,22 @@ const OutputPage: React.FC<RouteComponentProps<OutputPageProps>> = ({
);
}

const { blockId, transactionId, outputIndex, isSpent, transactionIdSpent } = outputMetadataResponse ?? {};
const { blockId, included, spent } = outputMetadataResponse ?? {};

const transactionId = included?.transactionId ?? null;
const createdSlotIndex = (included?.slot as number) ?? null;
const spentSlotIndex = (spent?.slot as number) ?? null;
const isSpent = spentSlotIndex !== null;
const transactionIdSpent = spent?.transactionId ?? null;
const outputIndex = computeOutputIndexFromOutputId(outputId);

let outputManaDetails: OutputManaDetails | null = null;
if (output && createdSlotIndex && protocolInfo) {
const untilSlotIndex = spentSlotIndex ? spentSlotIndex : latestConfirmedSlot > 0 ? latestConfirmedSlot : null;
outputManaDetails = untilSlotIndex
? buildManaDetailsForOutput(output, createdSlotIndex, untilSlotIndex, protocolInfo.parameters)
: null;
}

return (
(output && (
Expand All @@ -60,13 +79,7 @@ const OutputPage: React.FC<RouteComponentProps<OutputPageProps>> = ({
</div>
<div className="section">
<div className="card">
<OutputView
network={network}
outputId={outputId}
output={output}
showCopyAmount={true}
isPreExpanded={true}
/>
<OutputView outputId={outputId} output={output} showCopyAmount={true} isPreExpanded={true} />
</div>

<div className="section--header row row--tablet-responsive middle space-between">
Expand Down Expand Up @@ -125,6 +138,35 @@ const OutputPage: React.FC<RouteComponentProps<OutputPageProps>> = ({
</div>
</div>
)}

{outputManaDetails && (
<>
<div className="section--data">
<div className="label">Stored mana</div>
<div className="value code row middle">
<span className="margin-r-t">{outputManaDetails.storedMana}</span>
</div>
</div>
<div className="section--data">
<div className="label">Stored mana (decayed)</div>
<div className="value code row middle">
<span className="margin-r-t">{outputManaDetails.storedManaDecayed}</span>
</div>
</div>
<div className="section--data">
<div className="label">Potential mana</div>
<div className="value code row middle">
<span className="margin-r-t">{outputManaDetails.potentialMana}</span>
</div>
</div>
<div className="section--data">
<div className="label">Total mana</div>
<div className="value code row middle">
<span className="margin-r-t">{outputManaDetails.totalMana}</span>
</div>
</div>
</>
)}
</div>
</div>
</div>
Expand All @@ -134,4 +176,15 @@ const OutputPage: React.FC<RouteComponentProps<OutputPageProps>> = ({
);
};

function computeOutputIndexFromOutputId(outputId: string | null) {
if (!outputId) {
return null;
}

const outputIndexPart = outputId.slice(-4);
const outputIndexBigEndian = Converter.convertToBigEndian(outputIndexPart);

return Number(outputIndexBigEndian);
}

export default OutputPage;
27 changes: 27 additions & 0 deletions client/src/helpers/nova/manaUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { BasicOutput, Output, ProtocolParameters, Utils } from "@iota/sdk-wasm-nova/web";

export interface OutputManaDetails {
storedMana: string;
storedManaDecayed: string;
potentialMana: string;
totalMana: string;
}

export function buildManaDetailsForOutput(
output: Output,
createdSlotIndex: number,
spentOrLatestSlotIndex: number,
protocolParameters: ProtocolParameters,
): OutputManaDetails {
const decayedMana = Utils.outputManaWithDecay(output, createdSlotIndex, spentOrLatestSlotIndex, protocolParameters);
const storedManaDecayed = BigInt(decayedMana.stored).toString();
const potentialMana = BigInt(decayedMana.potential).toString();
const totalMana = BigInt(decayedMana.stored) + BigInt(decayedMana.potential);

return {
storedMana: (output as BasicOutput).mana?.toString(),
storedManaDecayed,
potentialMana,
totalMana: totalMana.toString(),
};
}
6 changes: 5 additions & 1 deletion client/src/helpers/nova/networkInfo.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { INodeInfoBaseToken } from "@iota/sdk-wasm-nova/web";
import { INodeInfoBaseToken, ProtocolInfo } from "@iota/sdk-wasm-nova/web";
import { create } from "zustand";

interface INetworkInfo {
name: string;
tokenInfo: INodeInfoBaseToken;
protocolVersion: number;
protocolInfo: ProtocolInfo | null;
latestConfirmedSlot: number;
bech32Hrp: string;
}

Expand All @@ -25,6 +27,8 @@ export const useNetworkInfoNova = create<NetworkInfoState>((set) => ({
useMetricPrefix: true,
},
protocolVersion: -1,
protocolInfo: null,
latestConfirmedSlot: -1,
bech32Hrp: "",
},
setNetworkInfo: (networkInfo) => {
Expand Down
2 changes: 1 addition & 1 deletion setup_nova.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
SDK_DIR="iota-sdk"
TARGET_COMMIT="e8713d3b7d6b1f54055916b1a8f226b6cc2ce4c7"
TARGET_COMMIT="08318f6e3f92af609b89c571462ea31b32e7c121"

if [ ! -d "$SDK_DIR" ]; then
git clone -b 2.0 [email protected]:iotaledger/iota-sdk.git
Expand Down

0 comments on commit 6cadacd

Please sign in to comment.