Merge branch 'feature/self-destruct-trace' into develop

This commit is contained in:
Willian Mitsuda 2021-07-19 20:50:19 -03:00
commit efaf613c16
20 changed files with 378 additions and 121 deletions

View File

@ -13,7 +13,7 @@ import NavButton from "./components/NavButton";
import Timestamp from "./components/Timestamp";
import GasValue from "./components/GasValue";
import BlockLink from "./components/BlockLink";
import AddressOrENSName from "./components/AddressOrENSName";
import DecoratedAddressLink from "./components/DecoratedAddressLink";
import TransactionValue from "./components/TransactionValue";
import HexValue from "./components/HexValue";
import { RuntimeContext } from "./useRuntime";
@ -159,10 +159,7 @@ const Block: React.FC = () => {
in this block
</InfoRow>
<InfoRow title="Mined by">
<AddressOrENSName
address={block.miner}
minerAddress={block.miner}
/>
<DecoratedAddressLink address={block.miner} miner />
</InfoRow>
<InfoRow title="Block Reward">
<TransactionValue value={block.blockReward.add(block.feeReward)} />

View File

@ -2,22 +2,27 @@ import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCaretRight } from "@fortawesome/free-solid-svg-icons";
import AddressHighlighter from "./components/AddressHighlighter";
import AddressOrENSName from "./components/AddressOrENSName";
import AddressLink from "./components/AddressLink";
import TokenLogo from "./components/TokenLogo";
import DecoratedAddressLink from "./components/DecoratedAddressLink";
import FormattedBalance from "./components/FormattedBalance";
import { TokenMetas, TokenTransfer } from "./types";
import {
AddressContext,
TokenMetas,
TokenTransfer,
TransactionData,
} from "./types";
type TokenTransferItemProps = {
t: TokenTransfer;
txData: TransactionData;
tokenMetas: TokenMetas;
};
const TokenTransferItem: React.FC<TokenTransferItemProps> = ({
t,
txData,
tokenMetas,
}) => (
<div className="flex items-baseline space-x-2 truncate">
<div className="flex items-baseline space-x-2 px-2 py-1 truncate hover:bg-gray-100">
<span className="text-gray-500">
<FontAwesomeIcon icon={faCaretRight} size="1x" />
</span>
@ -25,13 +30,23 @@ const TokenTransferItem: React.FC<TokenTransferItemProps> = ({
<div className="flex space-x-1">
<span className="font-bold">From</span>
<AddressHighlighter address={t.from}>
<AddressOrENSName address={t.from} />
<DecoratedAddressLink
address={t.from}
addressCtx={AddressContext.FROM}
txFrom={t.from === txData.from}
txTo={t.from === txData.to}
/>
</AddressHighlighter>
</div>
<div className="flex space-x-1">
<span className="font-bold">To</span>
<AddressHighlighter address={t.to}>
<AddressOrENSName address={t.to} />
<DecoratedAddressLink
address={t.to}
addressCtx={AddressContext.TO}
txFrom={t.to === txData.from}
txTo={t.to === txData.to}
/>
</AddressHighlighter>
</div>
<div className="col-span-3 flex space-x-1">
@ -42,23 +57,17 @@ const TokenTransferItem: React.FC<TokenTransferItemProps> = ({
decimals={tokenMetas[t.token].decimals}
/>
</span>
<span className="flex space-x-1 items-baseline truncate">
{tokenMetas[t.token] ? (
<>
<div className="self-center">
<TokenLogo address={t.token} name={tokenMetas[t.token].name} />
</div>
<AddressLink
<AddressHighlighter address={t.token}>
<DecoratedAddressLink
address={t.token}
text={`${tokenMetas[t.token].name} (${
tokenMetas[t.token].symbol
})`}
text={
tokenMetas[t.token]
? `${tokenMetas[t.token].name} (${tokenMetas[t.token].symbol})`
: ""
}
tokenMeta={tokenMetas[t.token]}
/>
</>
) : (
<AddressOrENSName address={t.token} />
)}
</span>
</AddressHighlighter>
</div>
</div>
</div>

View File

@ -1,10 +1,4 @@
import React, {
useState,
useEffect,
useCallback,
useMemo,
useContext,
} from "react";
import React, { useState, useEffect, useMemo, useContext } from "react";
import { Route, Switch, useParams } from "react-router-dom";
import { BigNumber, ethers } from "ethers";
import StandardFrame from "./StandardFrame";
@ -13,9 +7,10 @@ import Tab from "./components/Tab";
import Details from "./transaction/Details";
import Logs from "./transaction/Logs";
import erc20 from "./erc20.json";
import { TokenMetas, TokenTransfer, TransactionData, Transfer } from "./types";
import { TokenMetas, TokenTransfer, TransactionData } from "./types";
import { RuntimeContext } from "./useRuntime";
import { SelectionContext, useSelection } from "./useSelection";
import { useInternalTransfers } from "./useErigonHooks";
const TRANSFER_TOPIC =
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
@ -110,42 +105,19 @@ const Transaction: React.FC = () => {
readBlock();
}, [provider, txhash]);
const [transfers, setTransfers] = useState<Transfer[]>();
const intTransfers = useInternalTransfers(provider, txData);
const sendsEthToMiner = useMemo(() => {
if (!txData || !transfers) {
if (!txData || !intTransfers) {
return false;
}
for (const t of transfers) {
for (const t of intTransfers) {
if (t.to === txData.miner) {
return true;
}
}
return false;
}, [txData, transfers]);
const traceTransfers = useCallback(async () => {
if (!provider || !txData) {
return;
}
const r = await provider.send("ots_getTransactionTransfers", [
txData.transactionHash,
]);
const _transfers: Transfer[] = [];
for (const t of r) {
_transfers.push({
from: ethers.utils.getAddress(t.from),
to: ethers.utils.getAddress(t.to),
value: t.value,
});
}
setTransfers(_transfers);
}, [provider, txData]);
useEffect(() => {
traceTransfers();
}, [traceTransfers]);
}, [txData, intTransfers]);
const selectionCtx = useSelection();
@ -164,7 +136,7 @@ const Transaction: React.FC = () => {
<Route path="/tx/:txhash/" exact>
<Details
txData={txData}
transfers={transfers}
internalTransfers={intTransfers}
sendsEthToMiner={sendsEthToMiner}
/>
</Route>

View File

@ -6,7 +6,7 @@ type AddressProps = {
const Address: React.FC<AddressProps> = ({ address }) => (
<span className="font-address text-gray-400 truncate" title={address}>
<p className="truncate">{address}</p>
<span className="truncate">{address}</span>
</span>
);

View File

@ -4,16 +4,23 @@ import { NavLink } from "react-router-dom";
type AddressLinkProps = {
address: string;
text?: string;
dontOverrideColors?: boolean;
};
const AddressLink: React.FC<AddressLinkProps> = ({ address, text }) => (
const AddressLink: React.FC<AddressLinkProps> = ({
address,
text,
dontOverrideColors,
}) => (
<NavLink
className="text-link-blue hover:text-link-blue-hover font-address truncate"
className={`${
dontOverrideColors ? "" : "text-link-blue hover:text-link-blue-hover"
} font-address truncate`}
to={`/address/${address}`}
>
<p className="truncate" title={text ?? address}>
<span className="truncate" title={text ?? address}>
{text ?? address}
</p>
</span>
</NavLink>
);

View File

@ -1,6 +1,4 @@
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCoins } from "@fortawesome/free-solid-svg-icons";
import Address from "./Address";
import AddressLink from "./AddressLink";
import ENSName from "./ENSName";
@ -10,21 +8,18 @@ type AddressOrENSNameProps = {
address: string;
ensName?: string;
selectedAddress?: string;
minerAddress?: string;
text?: string;
dontOverrideColors?: boolean;
};
const AddressOrENSName: React.FC<AddressOrENSNameProps> = ({
address,
ensName,
selectedAddress,
minerAddress,
text,
dontOverrideColors,
}) => (
<div className="flex items-baseline space-x-1 truncate">
{minerAddress !== undefined && minerAddress === address && (
<span className="text-yellow-400" title="Miner address">
<FontAwesomeIcon icon={faCoins} size="1x" />
</span>
)}
<>
{address === selectedAddress ? (
<>
{ensName ? (
@ -36,13 +31,21 @@ const AddressOrENSName: React.FC<AddressOrENSNameProps> = ({
) : (
<>
{ensName ? (
<ENSNameLink name={ensName} address={address} />
<ENSNameLink
name={ensName}
address={address}
dontOverrideColors={dontOverrideColors}
/>
) : (
<AddressLink address={address} />
<AddressLink
address={address}
text={text}
dontOverrideColors={dontOverrideColors}
/>
)}
</>
)}
</div>
</>
);
export default React.memo(AddressOrENSName);

View File

@ -0,0 +1,79 @@
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faMoneyBillAlt,
faBurn,
faCoins,
} from "@fortawesome/free-solid-svg-icons";
import TokenLogo from "./TokenLogo";
import AddressOrENSName from "./AddressOrENSName";
import { AddressContext, TokenMeta, ZERO_ADDRESS } from "../types";
type DecoratedAddressLinkProps = {
address: string;
ensName?: string;
selectedAddress?: string;
text?: string;
addressCtx?: AddressContext;
miner?: boolean;
selfDestruct?: boolean;
txFrom?: boolean;
txTo?: boolean;
tokenMeta?: TokenMeta;
};
const DecoratedAddresssLink: React.FC<DecoratedAddressLinkProps> = ({
address,
ensName,
selectedAddress,
text,
addressCtx,
miner,
selfDestruct,
txFrom,
txTo,
tokenMeta,
}) => {
const mint = addressCtx === AddressContext.FROM && address === ZERO_ADDRESS;
const burn = addressCtx === AddressContext.TO && address === ZERO_ADDRESS;
return (
<div
className={`flex items-baseline space-x-1 ${txFrom ? "bg-red-50" : ""} ${
txTo ? "bg-green-50" : ""
} ${mint ? "italic text-green-500 hover:text-green-700" : ""} ${
burn ? "line-through text-orange-500 hover:text-orange-700" : ""
} ${selfDestruct ? "line-through opacity-70 hover:opacity-100" : ""}`}
>
{mint && (
<span className="text-green-500" title="Mint address">
<FontAwesomeIcon icon={faMoneyBillAlt} size="1x" />
</span>
)}
{burn && (
<span className="text-orange-500" title="Burn address">
<FontAwesomeIcon icon={faBurn} size="1x" />
</span>
)}
{miner && (
<span className="text-yellow-400" title="Miner address">
<FontAwesomeIcon icon={faCoins} size="1x" />
</span>
)}
{tokenMeta && (
<div className="self-center">
<TokenLogo address={address} name={tokenMeta.name} />
</div>
)}
<AddressOrENSName
address={address}
ensName={ensName}
selectedAddress={selectedAddress}
text={text}
dontOverrideColors={mint || burn}
/>
</div>
);
};
export default React.memo(DecoratedAddresssLink);

View File

@ -18,7 +18,7 @@ const ENSName: React.FC<ENSNameProps> = ({ name, address }) => (
width={12}
height={12}
/>
<p className="truncate">{name}</p>
<span className="truncate">{name}</span>
</div>
);

View File

@ -5,11 +5,18 @@ import ENSLogo from "./ensLogo.svg";
type ENSNameLinkProps = {
name: string;
address: string;
dontOverrideColors?: boolean;
};
const ENSNameLink: React.FC<ENSNameLinkProps> = ({ name, address }) => (
const ENSNameLink: React.FC<ENSNameLinkProps> = ({
name,
address,
dontOverrideColors,
}) => (
<NavLink
className="flex items-baseline space-x-1 font-sans text-link-blue hover:text-link-blue-hover truncate"
className={`flex items-baseline space-x-1 font-sans ${
dontOverrideColors ? "" : "text-link-blue hover:text-link-blue-hover"
} truncate`}
to={`/address/${name}`}
title={`${name}: ${address}`}
>
@ -20,7 +27,7 @@ const ENSNameLink: React.FC<ENSNameLinkProps> = ({ name, address }) => (
width={12}
height={12}
/>
<p className="truncate">{name}</p>
<span className="truncate">{name}</span>
</NavLink>
);

View File

@ -0,0 +1,25 @@
import React from "react";
import InternalTransfer from "./InternalTransfer";
import InternalSelfDestruct from "./InternalSelfDestruct";
import { TransactionData, Transfer, TransferType } from "../types";
type InternalOperationProps = {
txData: TransactionData;
transfer: Transfer;
};
const InternalOperation: React.FC<InternalOperationProps> = ({
txData,
transfer,
}) => (
<>
{transfer.type === TransferType.TRANSFER && (
<InternalTransfer txData={txData} transfer={transfer} />
)}
{transfer.type === TransferType.SELF_DESTRUCT && (
<InternalSelfDestruct txData={txData} transfer={transfer} />
)}
</>
);
export default React.memo(InternalOperation);

View File

@ -0,0 +1,73 @@
import React, { useContext } from "react";
import { ethers } from "ethers";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleRight, faBomb } from "@fortawesome/free-solid-svg-icons";
import AddressHighlighter from "./AddressHighlighter";
import DecoratedAddressLink from "./DecoratedAddressLink";
import { RuntimeContext } from "../useRuntime";
import { TransactionData, Transfer } from "../types";
const CHI_ADDRESS = "0x0000000000004946c0e9F43F4Dee607b0eF1fA1c";
const GST2_ADDRESS = "0x0000000000b3F879cb30FE243b4Dfee438691c04";
type InternalSelfDestructProps = {
txData: TransactionData;
transfer: Transfer;
};
const InternalSelfDestruct: React.FC<InternalSelfDestructProps> = ({
txData,
transfer,
}) => {
const { provider } = useContext(RuntimeContext);
const network = provider?.network;
const toMiner = txData.miner !== undefined && transfer.to === txData.miner;
return (
<>
<div className="flex items-baseline space-x-1 text-xs">
<span className="text-gray-500">
<span className="text-red-900">
<FontAwesomeIcon icon={faBomb} size="1x" />
</span>{" "}
SELF DESTRUCT
</span>
<span>Contract</span>
<div className="flex items-baseline">
<AddressHighlighter address={transfer.from}>
<DecoratedAddressLink address={transfer.from} selfDestruct />
</AddressHighlighter>
</div>
{network?.chainId === 1 && transfer.to === CHI_ADDRESS && (
<span className="text-gray-400">(Chi Gastoken)</span>
)}
{network?.chainId === 1 && transfer.to === GST2_ADDRESS && (
<span className="text-gray-400">(GST2 Gastoken)</span>
)}
</div>
{!transfer.value.isZero() && (
<div className="ml-5 flex items-baseline space-x-1 text-xs">
<span className="text-gray-500">
<FontAwesomeIcon icon={faAngleRight} size="1x" /> TRANSFER
</span>
<span>{ethers.utils.formatEther(transfer.value)} Ether</span>
<div className="flex items-baseline">
<span className="text-gray-500">To</span>
<AddressHighlighter address={transfer.to}>
<div
className={`flex items-baseline space-x-1 ${
toMiner ? "rounded px-2 py-1 bg-yellow-100" : ""
}`}
>
<DecoratedAddressLink address={transfer.to} miner={toMiner} />
</div>
</AddressHighlighter>
</div>
</div>
)}
</>
);
};
export default React.memo(InternalSelfDestruct);

View File

@ -1,9 +1,9 @@
import React from "react";
import { ethers } from "ethers";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleRight, faCoins } from "@fortawesome/free-solid-svg-icons";
import { faAngleRight } from "@fortawesome/free-solid-svg-icons";
import AddressHighlighter from "./AddressHighlighter";
import AddressLink from "./AddressLink";
import DecoratedAddressLink from "./DecoratedAddressLink";
import { TransactionData, Transfer } from "../types";
type InternalTransferProps = {
@ -33,12 +33,12 @@ const InternalTransfer: React.FC<InternalTransferProps> = ({
fromMiner ? "rounded px-2 py-1 bg-yellow-100" : ""
}`}
>
{fromMiner && (
<span className="text-yellow-400" title="Miner address">
<FontAwesomeIcon icon={faCoins} size="1x" />
</span>
)}
<AddressLink address={transfer.from} />
<DecoratedAddressLink
address={transfer.from}
miner={fromMiner}
txFrom={transfer.from === txData.from}
txTo={transfer.from === txData.to}
/>
</div>
</AddressHighlighter>
</div>
@ -50,12 +50,12 @@ const InternalTransfer: React.FC<InternalTransferProps> = ({
toMiner ? "rounded px-2 py-1 bg-yellow-100" : ""
}`}
>
{toMiner && (
<span className="text-yellow-400" title="Miner address">
<FontAwesomeIcon icon={faCoins} size="1x" />
</span>
)}
<AddressLink address={transfer.to} />
<DecoratedAddressLink
address={transfer.to}
miner={toMiner}
txFrom={transfer.to === txData.from}
txTo={transfer.to === txData.to}
/>
</div>
</AddressHighlighter>
</div>

22
src/nodeFunctions.ts Normal file
View File

@ -0,0 +1,22 @@
import { ethers } from "ethers";
import { TransactionData, Transfer } from "./types";
export const getTransactionTransfers = async (
provider: ethers.providers.JsonRpcProvider,
txData: TransactionData
) => {
const rawTransfers = await provider.send("ots_getTransactionTransfers", [
txData.transactionHash,
]);
const _transfers: Transfer[] = [];
for (const t of rawTransfers) {
_transfers.push({
type: t.type,
from: ethers.utils.getAddress(t.from),
to: ethers.utils.getAddress(t.to),
value: t.value,
});
}
return _transfers;
};

View File

@ -1,3 +1,3 @@
export const MIN_API_LEVEL = 1;
export const MIN_API_LEVEL = 2;
export const PAGE_SIZE = 25;

View File

@ -4,7 +4,7 @@ import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons";
import MethodName from "../components/MethodName";
import BlockLink from "../components/BlockLink";
import TransactionLink from "../components/TransactionLink";
import AddressOrENSName from "../components/AddressOrENSName";
import DecoratedAddressLink from "../components/DecoratedAddressLink";
import TimestampAge from "../components/TimestampAge";
import AddressHighlighter from "../components/AddressHighlighter";
import TransactionDirection, {
@ -71,11 +71,11 @@ const TransactionItem: React.FC<TransactionItemProps> = ({
<span className="truncate">
{tx.from && (
<AddressHighlighter address={tx.from}>
<AddressOrENSName
<DecoratedAddressLink
address={tx.from}
ensName={ensFrom}
selectedAddress={selectedAddress}
minerAddress={tx.miner}
miner={tx.miner === tx.from}
/>
</AddressHighlighter>
)}
@ -91,11 +91,11 @@ const TransactionItem: React.FC<TransactionItemProps> = ({
<span className="truncate">
{tx.to && (
<AddressHighlighter address={tx.to}>
<AddressOrENSName
<DecoratedAddressLink
address={tx.to}
ensName={ensTo}
selectedAddress={selectedAddress}
minerAddress={tx.miner}
miner={tx.miner === tx.to}
/>
</AddressHighlighter>
)}

View File

@ -9,10 +9,10 @@ import ContentFrame from "../ContentFrame";
import InfoRow from "../components/InfoRow";
import BlockLink from "../components/BlockLink";
import AddressHighlighter from "../components/AddressHighlighter";
import AddressOrENSName from "../components/AddressOrENSName";
import DecoratedAddressLink from "../components/DecoratedAddressLink";
import Copy from "../components/Copy";
import Timestamp from "../components/Timestamp";
import InternalTransfer from "../components/InternalTransfer";
import InternalOperation from "../components/InternalOperation";
import MethodName from "../components/MethodName";
import GasValue from "../components/GasValue";
import FormattedBalance from "../components/FormattedBalance";
@ -21,13 +21,13 @@ import { TransactionData, Transfer } from "../types";
type DetailsProps = {
txData: TransactionData;
transfers?: Transfer[];
internalTransfers?: Transfer[];
sendsEthToMiner: boolean;
};
const Details: React.FC<DetailsProps> = ({
txData,
transfers,
internalTransfers,
sendsEthToMiner,
}) => (
<ContentFrame tabs>
@ -64,7 +64,11 @@ const Details: React.FC<DetailsProps> = ({
<InfoRow title="From">
<div className="flex items-baseline space-x-2 -ml-1">
<AddressHighlighter address={txData.from}>
<AddressOrENSName address={txData.from} minerAddress={txData.miner} />
<DecoratedAddressLink
address={txData.from}
miner={txData.from === txData.miner}
txFrom
/>
</AddressHighlighter>
<Copy value={txData.from} />
</div>
@ -72,14 +76,18 @@ const Details: React.FC<DetailsProps> = ({
<InfoRow title="Interacted With (To)">
<div className="flex items-baseline space-x-2 -ml-1">
<AddressHighlighter address={txData.to}>
<AddressOrENSName address={txData.to} minerAddress={txData.miner} />
<DecoratedAddressLink
address={txData.to}
miner={txData.to === txData.miner}
txTo
/>
</AddressHighlighter>
<Copy value={txData.to} />
</div>
{transfers && (
{internalTransfers && (
<div className="mt-2 space-y-1">
{transfers.map((t, i) => (
<InternalTransfer key={i} txData={txData} transfer={t} />
{internalTransfers.map((t, i) => (
<InternalOperation key={i} txData={txData} transfer={t} />
))}
</div>
)}
@ -89,9 +97,14 @@ const Details: React.FC<DetailsProps> = ({
</InfoRow>
{txData.tokenTransfers.length > 0 && (
<InfoRow title={`Tokens Transferred (${txData.tokenTransfers.length})`}>
<div className="space-y-2">
<div>
{txData.tokenTransfers.map((t, i) => (
<TokenTransferItem key={i} t={t} tokenMetas={txData.tokenMetas} />
<TokenTransferItem
key={i}
t={t}
txData={txData}
tokenMetas={txData.tokenMetas}
/>
))}
</div>
</InfoRow>

View File

@ -1,6 +1,6 @@
import React from "react";
import ContentFrame from "../ContentFrame";
import AddressLink from "../components/AddressLink";
import DecoratedAddressLink from "../components/DecoratedAddressLink";
import { TransactionData } from "../types";
type LogsProps = {
@ -22,7 +22,12 @@ const Logs: React.FC<LogsProps> = ({ txData }) => (
<div className="grid grid-cols-12 gap-x-3 gap-y-5 text-sm">
<div className="font-bold text-right">Address</div>
<div className="col-span-11">
<AddressLink address={l.address} />
<DecoratedAddressLink
address={l.address}
miner={l.address === txData.miner}
txFrom={l.address === txData.from}
txTo={l.address === txData.to}
/>
</div>
</div>
{l.topics.map((t, i) => (
@ -45,6 +50,7 @@ const Logs: React.FC<LogsProps> = ({ txData }) => (
<textarea
className="w-full h-20 bg-gray-50 font-mono focus:outline-none border rounded p-2"
value={l.data}
readOnly
/>
</div>
</div>

View File

@ -57,12 +57,26 @@ export type TransactionData = {
logs: ethers.providers.Log[];
};
// The VOID...
export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
export enum AddressContext {
FROM,
TO,
}
export type From = {
current: string;
depth: number;
};
export enum TransferType {
TRANSFER = 0,
SELF_DESTRUCT = 1,
}
export type Transfer = {
type: TransferType;
from: string;
to: string;
value: BigNumber;

30
src/useErigonHooks.ts Normal file
View File

@ -0,0 +1,30 @@
import { ethers } from "ethers";
import { useState, useEffect } from "react";
import { getTransactionTransfers } from "./nodeFunctions";
import { TransactionData, Transfer } from "./types";
export const useInternalTransfers = (
provider: ethers.providers.JsonRpcProvider | undefined,
txData: TransactionData | undefined
): Transfer[] | undefined => {
const [intTransfers, setIntTransfers] = useState<Transfer[]>();
useEffect(() => {
const traceTransfers = async () => {
if (!provider || !txData) {
return;
}
const _transfers = await getTransactionTransfers(provider, txData);
for (const t of _transfers) {
t.from = provider.formatter.address(t.from);
t.to = provider.formatter.address(t.to);
t.value = provider.formatter.bigNumber(t.value);
}
setIntTransfers(_transfers);
};
traceTransfers();
}, [provider, txData]);
return intTransfers;
};

View File

@ -1,7 +1,7 @@
import React, { useState, useContext } from "react";
export type Selection = {
type: string;
type: "address";
content: string;
};