Skip to content

Commit

Permalink
feat: link to output when transaction is supply increase (#1114)
Browse files Browse the repository at this point in the history
* chore: link to output when transaction is genesis.

Signed-off-by: Eugene Panteleymonchuk <[email protected]>

* chore: put link to right place, clean code

Signed-off-by: Eugene Panteleymonchuk <[email protected]>

* chore: Identify 'outputId' within genesis block during the export of transactions

Signed-off-by: Eugene Panteleymonchuk <[email protected]>

* fix: genesis migration and supply increase markers

---------

Signed-off-by: Eugene Panteleymonchuk <[email protected]>
Co-authored-by: Mario <[email protected]>
Co-authored-by: Begoña Alvarez <[email protected]>
  • Loading branch information
3 people authored Feb 16, 2024
1 parent 507b49b commit 68b9542
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 44 deletions.
2 changes: 1 addition & 1 deletion api/src/models/db/networkType.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
const LEGACY_MAINNET = "legacy-mainnet";
const CHRYSALIS_MAINNET = "chrysalis-mainnet";
const MAINNET = "mainnet";
export const MAINNET = "mainnet";
const DEVNET = "devnet";
export const SHIMMER = "shimmer";
const TESTNET = "testnet";
Expand Down
51 changes: 45 additions & 6 deletions api/src/routes/stardust/transactionhistory/download/post.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { OutputResponse, INodeInfoBaseToken, CommonOutput } from "@iota/sdk";
import { CommonOutput, INodeInfoBaseToken, OutputResponse } from "@iota/sdk";
import JSZip from "jszip";
import moment from "moment";
import { ServiceFactory } from "../../../../factories/serviceFactory";
Expand All @@ -8,6 +8,8 @@ import { ITransactionHistoryDownloadBody } from "../../../../models/api/stardust
import { ITransactionHistoryRequest } from "../../../../models/api/stardust/chronicle/ITransactionHistoryRequest";
import { ITransactionHistoryItem } from "../../../../models/api/stardust/chronicle/ITransactionHistoryResponse";
import { IConfiguration } from "../../../../models/configuration/IConfiguration";
import { INetwork } from "../../../../models/db/INetwork";
import { MAINNET } from "../../../../models/db/networkType";
import { STARDUST } from "../../../../models/db/protocolVersion";
import { NetworkService } from "../../../../services/networkService";
import { ChronicleService } from "../../../../services/stardust/chronicleService";
Expand All @@ -20,13 +22,16 @@ export interface ITransactionHistoryRecord {
isGenesisByDate: boolean;
isSpent: boolean;
transactionId: string;
outputIdFromSupplyIncrease?: string;
timestamp: number;
dateFormatted: string;
balanceChange: number;
balanceChangeFormatted: string;
outputs: OutputWithDetails[];
}

const STARDUST_GENESIS_MILESTONE = 7669900;

/**
* Download the transaction history from chronicle stardust.
* @param _ The configuration.
Expand Down Expand Up @@ -73,14 +78,21 @@ export async function post(
});
const tokenInfo = nodeInfoService.getNodeInfo().baseToken;

const transactions = getTransactionHistoryRecords(groupOutputsByTransactionId(fulfilledOutputs), tokenInfo);
const transactions = getTransactionHistoryRecords(groupOutputsByTransactionId(fulfilledOutputs), tokenInfo, networkConfig);

const headers = ["Timestamp", "TransactionId", "Balance changes"];

let csvContent = `${headers.join(",")}\n`;

for (const transaction of transactions) {
const row = [transaction.dateFormatted, transaction.transactionId, transaction.balanceChangeFormatted].join(",");
let transactionCell = transaction.transactionId;
if (transaction.isGenesisByDate) {
transactionCell = `Stardust Genesis (Chrysalis): ${transactionCell}`;
if (transaction.outputIdFromSupplyIncrease) {
transactionCell = `Supply Increase Output: ${transaction.outputIdFromSupplyIncrease}`;
}
}
const row = [transaction.dateFormatted, transactionCell, transaction.balanceChangeFormatted].join(",");
csvContent += `${row}\n`;
}

Expand Down Expand Up @@ -140,21 +152,26 @@ export const groupOutputsByTransactionId = (outputsWithDetails: OutputWithDetail
export const getTransactionHistoryRecords = (
transactionIdToOutputs: Map<string, OutputWithDetails[]>,
tokenInfo: INodeInfoBaseToken,
networkConfig: INetwork,
): ITransactionHistoryRecord[] => {
const calculatedTransactions: ITransactionHistoryRecord[] = [];

for (const [transactionId, outputs] of transactionIdToOutputs.entries()) {
const lastOutputTime = Math.max(...outputs.map((t) => t.milestoneTimestamp));
const balanceChange = calculateBalanceChange(outputs);

const isGenesisByDate = outputs.map((t) => t.milestoneTimestamp).includes(0);

const isSpent = balanceChange <= 0;
const isGenesisByDate = outputs.some((output) => output.milestoneIndex === STARDUST_GENESIS_MILESTONE);

let outputIdFromSupplyIncrease;
if (isGenesisByDate) {
outputIdFromSupplyIncrease = getStardustGenesisOutputId(outputs, networkConfig, transactionId);
}

calculatedTransactions.push({
isGenesisByDate,
isSpent,
transactionId,
outputIdFromSupplyIncrease,
timestamp: lastOutputTime,
dateFormatted: moment(lastOutputTime * 1000).format("YYYY-MM-DD HH:mm:ss"),
balanceChange,
Expand All @@ -165,6 +182,28 @@ export const getTransactionHistoryRecords = (
return calculatedTransactions;
};

/**
* Get the output id from the stardust genesis.
* @param outputs List of outputs related to transaction
* @param networkConfig Network configuration
* @param transactionId Current trancaction
* @returns The output id from the stardust genesis or undefined.
*/
function getStardustGenesisOutputId(outputs: OutputWithDetails[], networkConfig: INetwork, transactionId: string): string | undefined {
const STARDUST_SUPPLY_INCREASE_OUTPUT_TICKER = "0xb191c4bc825ac6983789e50545d5ef07a1d293a98ad974fc9498cb18";

const outputFromStardustGenesis = outputs.find((output) => {
if (
networkConfig.network === MAINNET &&
output.milestoneIndex === STARDUST_GENESIS_MILESTONE &&
transactionId.includes(STARDUST_SUPPLY_INCREASE_OUTPUT_TICKER)
) {
return true;
}
});
return outputFromStardustGenesis?.outputId;
}

export const calculateBalanceChange = (outputs: OutputWithDetails[]) => {
let totalAmount = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,7 @@ const TransactionHistory: React.FC<TransactionHistoryProps> = ({ network, addres
<tbody>
{transactions?.map((c, idx) => (
<React.Fragment key={idx}>
<TransactionRow
isGenesisByDate={c.isGenesisByDate}
isTransactionFromStardustGenesis={c.isTransactionFromStardustGenesis}
transactionLink={c.transactionLink}
dateFormatted={c.dateFormatted}
balanceChangeFormatted={c.balanceChangeFormatted}
transactionId={c.transactionId}
isSpent={c.isSpent}
isFormattedAmounts={isFormattedAmounts}
setIsFormattedAmounts={setIsFormattedAmounts}
/>
<TransactionRow {...c} isFormattedAmounts={isFormattedAmounts} setIsFormattedAmounts={setIsFormattedAmounts} />
</React.Fragment>
))}
</tbody>
Expand Down
31 changes: 17 additions & 14 deletions client/src/app/components/stardust/history/TransactionIdView.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { STARDUST_SUPPLY_INCREASE_TRANSACTION_ID } from "~/helpers/stardust/transactionsHelper";
import { Link } from "react-router-dom";
import { STARDUST_SUPPLY_INCREASE_OUTPUT_TICKER } from "~/helpers/stardust/transactionsHelper";
import TruncatedId from "../TruncatedId";
import Tooltip from "../../Tooltip";

Expand All @@ -10,21 +11,23 @@ export interface ITransactionIdProps {
}

const TransactionIdView: React.FC<ITransactionIdProps> = ({ transactionId, isTransactionFromStardustGenesis, transactionLink }) => {
if (isTransactionFromStardustGenesis && transactionId.includes(STARDUST_SUPPLY_INCREASE_OUTPUT_TICKER)) {
return (
<Link to={transactionLink}>
<span>Supply Increase</span>
</Link>
);
}

return (
<>
{isTransactionFromStardustGenesis && transactionId.includes(STARDUST_SUPPLY_INCREASE_TRANSACTION_ID) ? (
<span>Stardust Genesis</span>
) : (
<>
<TruncatedId id={transactionId} link={transactionLink} />
{isTransactionFromStardustGenesis && (
<Tooltip tooltipContent="This link opens the transaction on Chrysalis Mainnet" childrenClass="row middle">
<span className="material-icons" style={{ fontSize: "14px" }}>
warning
</span>
</Tooltip>
)}
</>
<TruncatedId id={transactionId} link={transactionLink} />
{isTransactionFromStardustGenesis && (
<Tooltip tooltipContent="This link opens the transaction on Chrysalis Mainnet" childrenClass="row middle">
<span className="material-icons" style={{ fontSize: "14px" }}>
warning
</span>
</Tooltip>
)}
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import moment from "moment/moment";

import { DateHelper } from "~helpers/dateHelper";
import { OutputWithDetails } from "~helpers/hooks/useAddressHistory";
import { STARDUST_SUPPLY_INCREASE_TRANSACTION_ID, TransactionsHelper } from "~helpers/stardust/transactionsHelper";
import { STARDUST_SUPPLY_INCREASE_OUTPUT_TICKER, TransactionsHelper } from "~helpers/stardust/transactionsHelper";
import { formatAmount } from "~helpers/stardust/valueFormatHelper";
import { CHRYSALIS_MAINNET } from "~models/config/networkType";

Expand Down Expand Up @@ -64,12 +64,17 @@ export const getTransactionHistoryRecords = (

const isGenesisByDate = outputs.map((t) => t.milestoneTimestamp).some((milestoneTimestamp) => milestoneTimestamp === 0);

const milestoneIndexes = outputs.map((t) => t.milestoneIndex);
const isTransactionFromStardustGenesis = milestoneIndexes.some((milestoneIndex) =>
TransactionsHelper.isTransactionFromIotaStardustGenesis(network, milestoneIndex),
);
let stardustGenesisOutputId;
const isTransactionFromStardustGenesis = outputs.some(({ milestoneIndex, outputId }) => {
const isGenesis = TransactionsHelper.isTransactionFromIotaStardustGenesis(network, milestoneIndex);
if (isGenesis) {
stardustGenesisOutputId = outputId;
}

return isGenesis;
});

const transactionLink = getTransactionLink(network, transactionId, isTransactionFromStardustGenesis);
const transactionLink = getTransactionLink(network, transactionId, isTransactionFromStardustGenesis, stardustGenesisOutputId);

const isSpent = balanceChange <= 0;

Expand Down Expand Up @@ -106,8 +111,19 @@ export const calculateBalanceChange = (outputs: OutputWithDetails[]) => {
}, 0);
};

export const getTransactionLink = (network: string, transactionId: string, isTransactionFromStardustGenesis: boolean) => {
return isTransactionFromStardustGenesis && !transactionId.includes(STARDUST_SUPPLY_INCREASE_TRANSACTION_ID)
? `/${CHRYSALIS_MAINNET}/search/${transactionId}`
: `/${network}/transaction/${transactionId}`;
export const getTransactionLink = (
network: string,
transactionId: string,
isTransactionFromStardustGenesis: boolean,
outputId?: string,
) => {
if (isTransactionFromStardustGenesis && transactionId.includes(STARDUST_SUPPLY_INCREASE_OUTPUT_TICKER)) {
return `/${network}/output/${outputId}`;
}

if (isTransactionFromStardustGenesis && !transactionId.includes(STARDUST_SUPPLY_INCREASE_OUTPUT_TICKER)) {
return `/${CHRYSALIS_MAINNET}/search/${transactionId}`;
}

return `/${network}/transaction/${transactionId}`;
};
2 changes: 1 addition & 1 deletion client/src/app/routes/stardust/OutputPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const OutputPage: React.FC<RouteComponentProps<OutputPageProps>> = ({
} = outputMetadata ?? {};

const isTransactionFromStardustGenesis = TransactionsHelper.isTransactionFromIotaStardustGenesis(network, milestoneIndexBooked ?? 0);
const transactionLink = getTransactionLink(network, transactionId ?? "", isTransactionFromStardustGenesis);
const transactionLink = getTransactionLink(network, transactionId ?? "", isTransactionFromStardustGenesis, outputId);

return (
(output && (
Expand Down
2 changes: 1 addition & 1 deletion client/src/helpers/stardust/transactionsHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const HEX_PARTICIPATE = "0x5041525449434950415445";
*/
export const STARDUST_GENESIS_MILESTONE = 7669900;

export const STARDUST_SUPPLY_INCREASE_TRANSACTION_ID = "0xb191c4bc825ac6983789e50545d5ef07a1d293a98ad974fc9498cb18";
export const STARDUST_SUPPLY_INCREASE_OUTPUT_TICKER = "0xb191c4bc825ac6983789e50545d5ef07a1d293a98ad974fc9498cb18";

export class TransactionsHelper {
public static async getInputsAndOutputs(
Expand Down

0 comments on commit 68b9542

Please sign in to comment.