Squash initial implementation of usd prices
This commit is contained in:
parent
0f6401cc07
commit
859761f2ba
@ -17,11 +17,14 @@ import BlockLink from "./components/BlockLink";
|
||||
import DecoratedAddressLink from "./components/DecoratedAddressLink";
|
||||
import TransactionValue from "./components/TransactionValue";
|
||||
import FormattedBalance from "./components/FormattedBalance";
|
||||
import ETH2USDValue from "./components/ETH2USDValue";
|
||||
import USDValue from "./components/USDValue";
|
||||
import HexValue from "./components/HexValue";
|
||||
import { RuntimeContext } from "./useRuntime";
|
||||
import { useLatestBlockNumber } from "./useLatestBlock";
|
||||
import { blockTxsURL } from "./url";
|
||||
import { useBlockData } from "./useErigonHooks";
|
||||
import { useETHUSDOracle } from "./usePriceOracle";
|
||||
|
||||
type BlockParams = {
|
||||
blockNumberOrHash: string;
|
||||
@ -53,6 +56,7 @@ const Block: React.FC = () => {
|
||||
block && block.gasUsed.mul(10000).div(block.gasLimit).toNumber() / 100;
|
||||
|
||||
const latestBlockNumber = useLatestBlockNumber(provider);
|
||||
const blockETHUSDPrice = useETHUSDOracle(provider, block?.number);
|
||||
|
||||
return (
|
||||
<StandardFrame>
|
||||
@ -99,6 +103,17 @@ const Block: React.FC = () => {
|
||||
<TransactionValue value={netFeeReward} hideUnit />)
|
||||
</>
|
||||
)}
|
||||
{blockETHUSDPrice && (
|
||||
<>
|
||||
{" "}
|
||||
<span className="px-2 border-yellow-200 border rounded-lg bg-yellow-100 text-yellow-600">
|
||||
<ETH2USDValue
|
||||
ethAmount={block.blockReward.add(netFeeReward)}
|
||||
eth2USDValue={blockETHUSDPrice}
|
||||
/>
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</InfoRow>
|
||||
<InfoRow title="Uncles Reward">
|
||||
<TransactionValue value={block.unclesReward} />
|
||||
@ -147,7 +162,9 @@ const Block: React.FC = () => {
|
||||
{extraStr} (Hex:{" "}
|
||||
<span className="font-data">{block.extraData}</span>)
|
||||
</InfoRow>
|
||||
<InfoRow title="Ether Price">N/A</InfoRow>
|
||||
<InfoRow title="Ether Price">
|
||||
<USDValue value={blockETHUSDPrice} />
|
||||
</InfoRow>
|
||||
<InfoRow title="Difficult">{commify(block.difficulty)}</InfoRow>
|
||||
<InfoRow title="Total Difficult">
|
||||
{commify(block.totalDifficulty.toString())}
|
||||
|
@ -8,6 +8,7 @@ import Logs from "./transaction/Logs";
|
||||
import { RuntimeContext } from "./useRuntime";
|
||||
import { SelectionContext, useSelection } from "./useSelection";
|
||||
import { useInternalOperations, useTxData } from "./useErigonHooks";
|
||||
import { useETHUSDOracle } from "./usePriceOracle";
|
||||
|
||||
type TransactionParams = {
|
||||
txhash: string;
|
||||
@ -36,6 +37,8 @@ const Transaction: React.FC = () => {
|
||||
|
||||
const selectionCtx = useSelection();
|
||||
|
||||
const blockETHUSDPrice = useETHUSDOracle(provider, txData?.blockNumber);
|
||||
|
||||
return (
|
||||
<StandardFrame>
|
||||
<StandardSubtitle>Transaction Details</StandardSubtitle>
|
||||
@ -53,6 +56,7 @@ const Transaction: React.FC = () => {
|
||||
txData={txData}
|
||||
internalOps={internalOps}
|
||||
sendsEthToMiner={sendsEthToMiner}
|
||||
ethUSDPrice={blockETHUSDPrice}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="/tx/:txhash/logs/" exact>
|
||||
|
26
src/components/ETH2USDValue.tsx
Normal file
26
src/components/ETH2USDValue.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import React from "react";
|
||||
import { BigNumber, FixedNumber } from "@ethersproject/bignumber";
|
||||
import { commify } from "@ethersproject/units";
|
||||
|
||||
type ETH2USDValueProps = {
|
||||
ethAmount: BigNumber;
|
||||
eth2USDValue: BigNumber;
|
||||
};
|
||||
|
||||
const ETH2USDValue: React.FC<ETH2USDValueProps> = ({
|
||||
ethAmount,
|
||||
eth2USDValue,
|
||||
}) => {
|
||||
const value = ethAmount.mul(eth2USDValue).div(10 ** 8);
|
||||
|
||||
return (
|
||||
<span className="text-xs">
|
||||
$
|
||||
<span className="font-balance">
|
||||
{commify(FixedNumber.fromValue(value, 18).round(2).toString())}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(ETH2USDValue);
|
29
src/components/USDValue.tsx
Normal file
29
src/components/USDValue.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import React from "react";
|
||||
import { BigNumber, FixedNumber } from "@ethersproject/bignumber";
|
||||
import { commify } from "@ethersproject/units";
|
||||
|
||||
const ETH_FEED_DECIMALS = 8;
|
||||
|
||||
type USDValueProps = {
|
||||
value: BigNumber | undefined;
|
||||
};
|
||||
|
||||
const USDValue: React.FC<USDValueProps> = ({ value }) => (
|
||||
<span className="text-sm">
|
||||
{value ? (
|
||||
<>
|
||||
$
|
||||
<span className="font-balance">
|
||||
{commify(
|
||||
FixedNumber.fromValue(value, ETH_FEED_DECIMALS).round(2).toString()
|
||||
)}
|
||||
</span>{" "}
|
||||
<span className="text-xs text-gray-500">/ ETH</span>
|
||||
</>
|
||||
) : (
|
||||
"N/A"
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
|
||||
export default React.memo(USDValue);
|
@ -1,5 +1,5 @@
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { formatEther } from "@ethersproject/units";
|
||||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
import { toUtf8String } from "@ethersproject/strings";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCheckCircle } from "@fortawesome/free-solid-svg-icons/faCheckCircle";
|
||||
@ -19,7 +19,9 @@ import MethodName from "../components/MethodName";
|
||||
import TransactionType from "../components/TransactionType";
|
||||
import RewardSplit from "./RewardSplit";
|
||||
import GasValue from "../components/GasValue";
|
||||
import USDValue from "../components/USDValue";
|
||||
import FormattedBalance from "../components/FormattedBalance";
|
||||
import ETH2USDValue from "../components/ETH2USDValue";
|
||||
import TokenTransferItem from "../TokenTransferItem";
|
||||
import { TransactionData, InternalOperation } from "../types";
|
||||
import PercentageBar from "../components/PercentageBar";
|
||||
@ -31,12 +33,14 @@ type DetailsProps = {
|
||||
txData: TransactionData;
|
||||
internalOps?: InternalOperation[];
|
||||
sendsEthToMiner: boolean;
|
||||
ethUSDPrice: BigNumber | undefined;
|
||||
};
|
||||
|
||||
const Details: React.FC<DetailsProps> = ({
|
||||
txData,
|
||||
internalOps,
|
||||
sendsEthToMiner,
|
||||
ethUSDPrice,
|
||||
}) => {
|
||||
const hasEIP1559 =
|
||||
txData.blockBaseFeePerGas !== undefined &&
|
||||
@ -170,9 +174,12 @@ const Details: React.FC<DetailsProps> = ({
|
||||
</InfoRow>
|
||||
)}
|
||||
<InfoRow title="Value">
|
||||
<span className="rounded bg-gray-100 px-2 py-1 text-xs">
|
||||
{formatEther(txData.value)} Ether
|
||||
</span>
|
||||
<FormattedBalance value={txData.value} /> Ether{" "}
|
||||
{!txData.value.isZero() && ethUSDPrice && (
|
||||
<span className="px-2 border-red-100 border rounded-lg bg-red-50 text-red-600">
|
||||
<ETH2USDValue ethAmount={txData.value} eth2USDValue={ethUSDPrice} />
|
||||
</span>
|
||||
)}
|
||||
</InfoRow>
|
||||
<InfoRow
|
||||
title={
|
||||
@ -257,12 +264,22 @@ const Details: React.FC<DetailsProps> = ({
|
||||
<InfoRow title="Transaction Fee">
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<FormattedBalance value={txData.fee} /> Ether
|
||||
<FormattedBalance value={txData.fee} /> Ether{" "}
|
||||
{ethUSDPrice && (
|
||||
<span className="px-2 border-red-100 border rounded-lg bg-red-50 text-red-600">
|
||||
<ETH2USDValue
|
||||
ethAmount={txData.fee}
|
||||
eth2USDValue={ethUSDPrice}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{hasEIP1559 && <RewardSplit txData={txData} />}
|
||||
</div>
|
||||
</InfoRow>
|
||||
<InfoRow title="Ether Price">N/A</InfoRow>
|
||||
<InfoRow title="Ether Price">
|
||||
<USDValue value={ethUSDPrice} />
|
||||
</InfoRow>
|
||||
<InfoRow title="Input Data">
|
||||
<div className="space-y-1">
|
||||
<div className="flex space-x-1">
|
||||
|
42
src/usePriceOracle.ts
Normal file
42
src/usePriceOracle.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { JsonRpcProvider, BlockTag } from "@ethersproject/providers";
|
||||
import { Contract } from "@ethersproject/contracts";
|
||||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
import AggregatorV3Interface from "@chainlink/contracts/abi/v0.8/AggregatorV3Interface.json";
|
||||
|
||||
export const useETHUSDOracle = (
|
||||
provider: JsonRpcProvider | undefined,
|
||||
blockTag: BlockTag | undefined
|
||||
) => {
|
||||
const ethFeed = useMemo(() => {
|
||||
if (!provider || provider.network.chainId !== 1) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
try {
|
||||
return new Contract("eth-usd.data.eth", AggregatorV3Interface, provider);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return undefined;
|
||||
}
|
||||
}, [provider]);
|
||||
|
||||
const [latestPriceData, setLatestPriceData] = useState<BigNumber>();
|
||||
useEffect(() => {
|
||||
if (!ethFeed || !blockTag) {
|
||||
return;
|
||||
}
|
||||
|
||||
const readData = async () => {
|
||||
try {
|
||||
const priceData = await ethFeed.latestRoundData({ blockTag });
|
||||
setLatestPriceData(BigNumber.from(priceData.answer));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
readData();
|
||||
}, [ethFeed, blockTag]);
|
||||
|
||||
return latestPriceData;
|
||||
};
|
Loading…
Reference in New Issue
Block a user