Squash initial implementation of usd prices

This commit is contained in:
Willian Mitsuda 2021-08-31 02:56:05 -03:00
parent 0f6401cc07
commit 859761f2ba
6 changed files with 142 additions and 7 deletions

View File

@ -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())}

View File

@ -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>

View 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);

View 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);

View File

@ -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
View 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;
};