Skip to content

Commit

Permalink
Merge branch 'main' into fix/hide-shimmer-graphs-on-mainnet
Browse files Browse the repository at this point in the history
  • Loading branch information
begonaalvarezd authored Feb 16, 2024
2 parents 5d10382 + 68b9542 commit d0ea915
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 85 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
6 changes: 3 additions & 3 deletions api/src/services/stardust/influx/influxQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,14 @@ export const LEDGER_SIZE_DAILY_QUERY = {
export const STORAGE_DEPOSIT_DAILY_QUERY = {
full: `
SELECT
last("total_storage_deposit_amount") * 100 / 1000000 AS "storageDeposit"
last("total_storage_deposit_amount") / 1000000 AS "storageDeposit"
FROM "stardust_ledger_size"
WHERE time < $to
GROUP BY time(1d) fill(null)
`,
partial: `
SELECT
last("total_storage_deposit_amount") * 100 / 1000000 AS "storageDeposit"
last("total_storage_deposit_amount") / 1000000 AS "storageDeposit"
FROM "stardust_ledger_size"
WHERE time >= $from and time <= $to
GROUP BY time(1d) fill(null)
Expand Down Expand Up @@ -315,7 +315,7 @@ export const NFT_STAT_TOTAL_QUERY = `

export const STORAGE_DEPOSIT_TOTAL_QUERY = `
SELECT
last("total_storage_deposit_amount") * 100 AS "lockedStorageDeposit"
last("total_storage_deposit_amount") AS "lockedStorageDeposit"
FROM "stardust_ledger_size";
`;

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
6 changes: 3 additions & 3 deletions client/src/app/routes/stardust/landing/AnalyticStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ const AnalyticStats: React.FC<AnalyticStatsProps> = ({ analytics, circulatingSup

let claimedAndPercentLabels: [string, string] | undefined;
if (analytics?.unclaimedShimmer && circulatingSupply) {
// magic number since influx doesn't account for the unclaimable portion of 20%
const shimmerClaimed = circulatingSupply - (Number.parseInt(analytics.unclaimedShimmer, 10) - 362724101812273);
claimedAndPercentLabels = buildShimmerClaimedStats(shimmerClaimed.toString(), String(circulatingSupply), tokenInfo);
const totalSupplyBigInt = (BigInt(circulatingSupply) * BigInt(100)) / BigInt(80); // https://github.com/iotaledger/explorer/issues/584
const shimmerClaimedBigInt = totalSupplyBigInt - BigInt(analytics.unclaimedShimmer);
claimedAndPercentLabels = buildShimmerClaimedStats(shimmerClaimedBigInt.toString(), totalSupplyBigInt.toString(), tokenInfo);
}

return analytics && !analytics.error ? (
Expand Down
17 changes: 5 additions & 12 deletions client/src/helpers/stardust/preExpandedConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@ import {
CommonOutput,
ExpirationUnlockCondition,
GovernorAddressUnlockCondition,
ReferenceUnlock,
SignatureUnlock,
StateControllerAddressUnlockCondition,
Unlock,
UnlockConditionType,
UnlockType,
Utils,
} from "@iota/sdk-wasm/web";
import { Bech32AddressHelper } from "~/helpers/stardust/bech32AddressHelper";
import { IInput } from "~models/api/stardust/IInput";
import { IOutput } from "~models/api/stardust/IOutput";
import { IPreExpandedConfig } from "~models/components";
import { resolveTransitiveUnlock } from "./resolveTransiviteUnlock";

const OUTPUT_EXPAND_CONDITIONS: UnlockConditionType[] = [
UnlockConditionType.Address,
Expand Down Expand Up @@ -44,15 +42,10 @@ export function getInputsPreExpandedConfig(inputs: IInput[], unlocks: Unlock[],
};
if (input?.output?.output && "unlockConditions" in input.output.output) {
const commmonOutput = input.output.output as unknown as CommonOutput;
let unlock = unlocks[idx];
if (unlock.type === UnlockType.Reference) {
const referenceUnlock = unlock as ReferenceUnlock;
unlock = unlocks[referenceUnlock.reference];
}
const unlockSignatureAddress = Utils.hexPublicKeyToBech32Address(
(unlock as SignatureUnlock).signature.publicKey,
bech32Hrp,
);

const signatureUnlock = resolveTransitiveUnlock(unlocks, idx);
const unlockSignatureAddress = Utils.hexPublicKeyToBech32Address(signatureUnlock.signature.publicKey, bech32Hrp);

preExpandedConfig = {
...preExpandedConfig,
unlockConditions: commmonOutput.unlockConditions?.map((unlockCondition) => {
Expand Down
19 changes: 19 additions & 0 deletions client/src/helpers/stardust/resolveTransiviteUnlock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ReferenceUnlock, SignatureUnlock, Unlock, UnlockType } from "@iota/sdk-wasm/web";

export function resolveTransitiveUnlock(unlocks: Unlock[], unlockIndex: number): SignatureUnlock {
const unlock = unlocks[unlockIndex];
let signatureUnlock: SignatureUnlock;
if (unlock.type === UnlockType.Signature) {
signatureUnlock = unlock as SignatureUnlock;
} else {
let refUnlockIdx = unlockIndex;
// unlock references can be transitive,
// so we need to follow the path until we find the signature
do {
const referenceUnlock = unlocks[refUnlockIdx] as ReferenceUnlock;
signatureUnlock = unlocks[referenceUnlock.reference] as SignatureUnlock;
refUnlockIdx = referenceUnlock.reference;
} while (!signatureUnlock.signature);
}
return signatureUnlock;
}
Loading

0 comments on commit d0ea915

Please sign in to comment.