Avoid rebuilding/parsing ABI the same contract objects every time

This commit is contained in:
Willian Mitsuda 2022-08-23 19:01:30 -03:00
parent 682549fa4c
commit 18a7989a8b
No known key found for this signature in database
6 changed files with 68 additions and 31 deletions

View File

@ -1,18 +1,18 @@
import { BaseProvider } from "@ethersproject/providers";
import { Contract } from "@ethersproject/contracts";
import { Interface } from "@ethersproject/abi";
import { AddressZero } from "@ethersproject/constants";
import { IAddressResolver } from "./address-resolver";
import erc20 from "../../erc20.json";
import { TokenMeta } from "../../types";
const erc20Interface = new Interface(erc20);
const ERC20_PROTOTYPE = new Contract(AddressZero, erc20);
export class ERCTokenResolver implements IAddressResolver<TokenMeta> {
async resolveAddress(
provider: BaseProvider,
address: string
): Promise<TokenMeta | undefined> {
const erc20Contract = new Contract(address, erc20Interface, provider);
const erc20Contract = ERC20_PROTOTYPE.connect(provider).attach(address);
try {
const name = (await erc20Contract.name()) as string;
if (!name.trim()) {

View File

@ -12,6 +12,11 @@ const UNISWAP_V1_FACTORY_ABI = [
const NULL_ADDRESS = "0x0000000000000000000000000000000000000000";
const UNISWAP_V1_FACTORY_PROTOTYPE = new Contract(
UNISWAP_V1_FACTORY,
UNISWAP_V1_FACTORY_ABI
);
export type UniswapV1TokenMeta = {
address: ChecksummedAddress;
} & TokenMeta;
@ -28,11 +33,7 @@ export class UniswapV1Resolver implements IAddressResolver<UniswapV1PairMeta> {
provider: BaseProvider,
address: string
): Promise<UniswapV1PairMeta | undefined> {
const factoryContract = new Contract(
UNISWAP_V1_FACTORY,
UNISWAP_V1_FACTORY_ABI,
provider
);
const factoryContract = UNISWAP_V1_FACTORY_PROTOTYPE.connect(provider);
try {
// First, probe the getToken() function; if it responds with an UniswapV1 exchange

View File

@ -1,5 +1,6 @@
import { BaseProvider } from "@ethersproject/providers";
import { Contract } from "@ethersproject/contracts";
import { AddressZero } from "@ethersproject/constants";
import { IAddressResolver } from "./address-resolver";
import { ChecksummedAddress, TokenMeta } from "../../types";
import { ERCTokenResolver } from "./ERCTokenResolver";
@ -16,6 +17,16 @@ const UNISWAP_V2_PAIR_ABI = [
"function token1() external view returns (address)",
];
const UNISWAP_V2_FACTORY_PROTOTYPE = new Contract(
UNISWAP_V2_FACTORY,
UNISWAP_V2_FACTORY_ABI
);
const UNISWAP_V2_PAIR_PROTOTYPE = new Contract(
AddressZero,
UNISWAP_V2_PAIR_ABI
);
export type UniswapV2TokenMeta = {
address: ChecksummedAddress;
} & TokenMeta;
@ -33,12 +44,9 @@ export class UniswapV2Resolver implements IAddressResolver<UniswapV2PairMeta> {
provider: BaseProvider,
address: string
): Promise<UniswapV2PairMeta | undefined> {
const pairContract = new Contract(address, UNISWAP_V2_PAIR_ABI, provider);
const factoryContract = new Contract(
UNISWAP_V2_FACTORY,
UNISWAP_V2_FACTORY_ABI,
provider
);
const pairContract =
UNISWAP_V2_PAIR_PROTOTYPE.connect(provider).attach(address);
const factoryContract = UNISWAP_V2_FACTORY_PROTOTYPE.connect(provider);
try {
// First, probe the factory() function; if it responds with UniswapV2 factory

View File

@ -1,5 +1,6 @@
import { BaseProvider } from "@ethersproject/providers";
import { Contract } from "@ethersproject/contracts";
import { AddressZero } from "@ethersproject/constants";
import { IAddressResolver } from "./address-resolver";
import { ChecksummedAddress, TokenMeta } from "../../types";
import { ERCTokenResolver } from "./ERCTokenResolver";
@ -17,6 +18,16 @@ const UNISWAP_V3_PAIR_ABI = [
"function fee() external view returns (uint24)",
];
const UNISWAP_V3_FACTORY_PROTOTYPE = new Contract(
UNISWAP_V3_FACTORY,
UNISWAP_V3_FACTORY_ABI
);
const UNISWAP_V3_PAIR_PROTOTYPE = new Contract(
AddressZero,
UNISWAP_V3_PAIR_ABI
);
export type UniswapV3TokenMeta = {
address: ChecksummedAddress;
} & TokenMeta;
@ -35,12 +46,9 @@ export class UniswapV3Resolver implements IAddressResolver<UniswapV3PairMeta> {
provider: BaseProvider,
address: string
): Promise<UniswapV3PairMeta | undefined> {
const poolContract = new Contract(address, UNISWAP_V3_PAIR_ABI, provider);
const factoryContract = new Contract(
UNISWAP_V3_FACTORY,
UNISWAP_V3_FACTORY_ABI,
provider
);
const poolContract =
UNISWAP_V3_PAIR_PROTOTYPE.connect(provider).attach(address);
const factoryContract = UNISWAP_V3_FACTORY_PROTOTYPE.connect(provider);
try {
// First, probe the factory() function; if it responds with UniswapV2 factory

View File

@ -10,6 +10,7 @@ import { Contract } from "@ethersproject/contracts";
import { defaultAbiCoder } from "@ethersproject/abi";
import { BigNumber } from "@ethersproject/bignumber";
import { arrayify, hexDataSlice, isHexString } from "@ethersproject/bytes";
import { AddressZero } from "@ethersproject/constants";
import useSWR from "swr";
import useSWRImmutable from "swr/immutable";
import {
@ -638,13 +639,19 @@ export const useHasCode = (
return data as boolean | undefined;
};
const ERC20_PROTOTYPE = new Contract(AddressZero, erc20);
const tokenMetadataFetcher =
(provider: JsonRpcProvider | undefined) =>
async (
_: "tokenmeta",
address: ChecksummedAddress
): Promise<TokenMeta | null> => {
const erc20Contract = new Contract(address, erc20, provider);
if (provider === undefined) {
return null;
}
const erc20Contract = ERC20_PROTOTYPE.connect(provider).attach(address);
try {
const name = (await erc20Contract.name()) as string;
if (!name.trim()) {

View File

@ -1,6 +1,7 @@
import { JsonRpcProvider, BlockTag } from "@ethersproject/providers";
import { Contract } from "@ethersproject/contracts";
import { BigNumber } from "@ethersproject/bignumber";
import { AddressZero } from "@ethersproject/constants";
import AggregatorV3Interface from "@chainlink/contracts/abi/v0.8/AggregatorV3Interface.json";
import FeedRegistryInterface from "@chainlink/contracts/abi/v0.8/FeedRegistryInterface.json";
import { Fetcher } from "swr";
@ -26,11 +27,20 @@ const feedRegistryFetcherKey = (
return [tokenAddress, blockTag];
};
const FEED_REGISTRY_MAINNET_PROTOTYPE = new Contract(
FEED_REGISTRY_MAINNET,
FeedRegistryInterface
);
const feedRegistryFetcher =
(
provider: JsonRpcProvider | undefined
): Fetcher<FeedRegistryFetcherData, FeedRegistryFetcherKey> =>
async (tokenAddress, blockTag) => {
if (provider === undefined) {
return [undefined, undefined];
}
// It work works on ethereum mainnet and kovan, see:
// https://docs.chain.link/docs/feed-registry/
if (provider!.network.chainId !== 1) {
@ -38,11 +48,7 @@ const feedRegistryFetcher =
}
// Let SWR handle error
const feedRegistry = new Contract(
FEED_REGISTRY_MAINNET,
FeedRegistryInterface,
provider
);
const feedRegistry = FEED_REGISTRY_MAINNET_PROTOTYPE.connect(provider);
const priceData = await feedRegistry.latestRoundData(tokenAddress, USD, {
blockTag,
});
@ -76,6 +82,8 @@ const ethUSDFetcherKey = (blockTag: BlockTag | undefined) => {
return ["ethusd", blockTag];
};
const ETH_USD_FEED_PROTOTYPE = new Contract(AddressZero, AggregatorV3Interface);
const ethUSDFetcher =
(
provider: JsonRpcProvider | undefined
@ -84,7 +92,9 @@ const ethUSDFetcher =
if (provider?.network.chainId !== 1) {
return undefined;
}
const c = new Contract("eth-usd.data.eth", AggregatorV3Interface, provider);
const c =
ETH_USD_FEED_PROTOTYPE.connect(provider).attach("eth-usd.data.eth");
const priceData = await c.latestRoundData({ blockTag });
return priceData;
};
@ -120,6 +130,11 @@ const fastGasFetcherKey = (blockTag: BlockTag | undefined) => {
return ["gasgwei", blockTag];
};
const FAST_GAS_FEED_PROTOTYPE = new Contract(
AddressZero,
AggregatorV3Interface
);
const fastGasFetcher =
(
provider: JsonRpcProvider | undefined
@ -128,10 +143,8 @@ const fastGasFetcher =
if (provider?.network.chainId !== 1) {
return undefined;
}
const c = new Contract(
"fast-gas-gwei.data.eth",
AggregatorV3Interface,
provider
const c = FAST_GAS_FEED_PROTOTYPE.connect(provider).attach(
"fast-gas-gwei.data.eth"
);
const priceData = await c.latestRoundData({ blockTag });
return priceData;