1
0

provider.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import { ethers } from "ethers";
  2. import { Contract as EthcallContract, Provider as EthcallProvider } from "ethcall";
  3. import { ERC721_ABI } from "@/utils/abi/erc721";
  4. import { UNIPAIR_ABI } from "@/utils/abi/uniswapPair";
  5. import { ERC20_ABI } from "@/utils/abi/erc20";
  6. // Validate environment
  7. export const INFURA_RPC = process.env.NEXT_PUBLIC_INFURA_RPC;
  8. export const CONTRACT_ADDRESS = process.env.NEXT_PUBLIC_CONTRACT_ADDRESS;
  9. if (!INFURA_RPC || !CONTRACT_ADDRESS) {
  10. throw new Error("Missing environment variables: NEXT_PUBLIC_INFURA_RPC or NEXT_PUBLIC_CONTRACT_ADDRESS");
  11. }
  12. // Singleton Ethers Provider
  13. class EthersProviderSingleton {
  14. private static _instance: ethers.JsonRpcProvider | null = null;
  15. static getInstance(): ethers.JsonRpcProvider {
  16. if (!this._instance) {
  17. if (!INFURA_RPC) {
  18. throw new Error("Missing INFURA_RPC");
  19. }
  20. this._instance = new ethers.JsonRpcProvider(INFURA_RPC);
  21. }
  22. return this._instance;
  23. }
  24. }
  25. // Singleton Main ERC20 Contract
  26. class TokenContractSingleton {
  27. static getContract(address: string): ethers.Contract {
  28. return new ethers.Contract(address, ERC20_ABI, EthersProviderSingleton.getInstance());
  29. }
  30. }
  31. // Singleton Main ERC721 Contract
  32. class MainContractSingleton {
  33. private static _instance: ethers.Contract | null = null;
  34. static getInstance(): ethers.Contract {
  35. if (!this._instance) {
  36. if (!CONTRACT_ADDRESS) {
  37. throw new Error("Missing CONTRACT_ADDRESS");
  38. }
  39. this._instance = new ethers.Contract(CONTRACT_ADDRESS, ERC721_ABI, EthersProviderSingleton.getInstance());
  40. }
  41. return this._instance;
  42. }
  43. }
  44. // Singleton Main Ethcall Contract
  45. class MainEthcallContractSingleton {
  46. private static _instance: EthcallContract | null = null;
  47. static getInstance(): EthcallContract {
  48. if (!this._instance) {
  49. if (!CONTRACT_ADDRESS) {
  50. throw new Error("Missing CONTRACT_ADDRESS");
  51. }
  52. this._instance = new EthcallContract(CONTRACT_ADDRESS, ERC721_ABI);
  53. }
  54. return this._instance;
  55. }
  56. }
  57. // Singleton Ethcall Provider (Async)
  58. class EthcallProviderSingleton {
  59. private static _instance: EthcallProvider | null = null;
  60. static async getInstance(): Promise<EthcallProvider> {
  61. if (this._instance) return this._instance;
  62. const provider = EthersProviderSingleton.getInstance();
  63. const network = await provider.getNetwork();
  64. const chainId = Number(network.chainId);
  65. const ethCallProvider = new EthcallProvider(chainId, provider);
  66. this._instance = ethCallProvider;
  67. return ethCallProvider;
  68. }
  69. }
  70. // Factory for Uniswap Pair Contract
  71. class UniswapPairFactory {
  72. static getContract(address: string): ethers.Contract {
  73. return new ethers.Contract(address, UNIPAIR_ABI, EthersProviderSingleton.getInstance());
  74. }
  75. }
  76. // Exported API
  77. export const getProvider = () => EthersProviderSingleton.getInstance();
  78. export const getMainContract = () => MainContractSingleton.getInstance();
  79. export const getMainEthcallContract = () => MainEthcallContractSingleton.getInstance();
  80. export const getEthcallProvider = () => EthcallProviderSingleton.getInstance();
  81. export const getUniswapPairContract = UniswapPairFactory.getContract;
  82. export const getTokenContract = TokenContractSingleton.getContract;