From eeef78a5591fb475d77760b942310ad1cb30cc10 Mon Sep 17 00:00:00 2001 From: Anastasia Rodionova Date: Fri, 5 Jan 2024 19:24:09 +0100 Subject: [PATCH] Add more networks --- apps/web/src/app/data.ts | 22 ++++++++++++++++-- apps/web/src/lib/contract-loader.ts | 23 ++++++++++++++----- apps/web/src/lib/etherscan.ts | 3 +++ apps/web/src/lib/rpc-provider.ts | 8 +++++-- .../src/abi-strategy/etherscan-abi.ts | 3 +++ .../src/abi-strategy/request-model.ts | 1 + .../src/helpers/networks.ts | 21 +++++++++++++++++ .../src/transaction-decoder.ts | 3 ++- 8 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 packages/transaction-decoder/src/helpers/networks.ts diff --git a/apps/web/src/app/data.ts b/apps/web/src/app/data.ts index 2d53302..e3190fd 100644 --- a/apps/web/src/app/data.ts +++ b/apps/web/src/app/data.ts @@ -26,12 +26,30 @@ export const supportedChains = [ { name: "Ethereum Mainnet", chainID: 1, - rpcUrl: process.env.MAINNET_RPC_URL as string, + rpcUrl: + (process.env.MAINNET_RPC_URL as string) || "https://rpc.ankr.com/eth", }, { name: "Goerli Testnet", chainID: 5, - rpcUrl: process.env.GOERLI_RPC_URL as string, + rpcUrl: + (process.env.GOERLI_RPC_URL as string) || + "https://rpc.ankr.com/eth_goerli", + }, + { + name: "Base mainnet", + chainID: 8453, + rpcUrl: process.env.BASE_RPC_URL as string, + supportTraceAPI: false, + batching: false, + }, + { + name: "Manta pacific", + chainID: 169, + rpcUrl: + (process.env.MANTA_RPC_URL as string) || + "https://pacific-rpc.manta.network/http", + supportTraceAPI: false, }, ]; diff --git a/apps/web/src/lib/contract-loader.ts b/apps/web/src/lib/contract-loader.ts index 135231d..2a073e4 100644 --- a/apps/web/src/lib/contract-loader.ts +++ b/apps/web/src/lib/contract-loader.ts @@ -4,6 +4,7 @@ import { ContractMetaStore, EtherscanStrategyResolver, SourcifyStrategyResolver, + BlockscoutStrategyResolver, RPCProvider, } from "@3loop/transaction-decoder"; import { Effect, Layer } from "effect"; @@ -20,6 +21,11 @@ export const AbiStoreLive = Layer.succeed( }), SourcifyStrategyResolver(), ], + 169: [ + BlockscoutStrategyResolver({ + endpoint: "https://pacific-explorer.manta.network/api", + }), + ], }, set: ({ address = {} }) => Effect.gen(function* (_) { @@ -30,12 +36,17 @@ export const AbiStoreLive = Layer.succeed( Effect.all( addressMatches.map(([key, value]) => Effect.promise(() => - prisma.contractAbi.create({ - data: { - address: key.toLowerCase(), - abi: value, - }, - }), + prisma.contractAbi + .create({ + data: { + address: key, + abi: value, + }, + }) + .catch((e) => { + console.error("Failed to cache abi", e); + return null; + }), ), ), { diff --git a/apps/web/src/lib/etherscan.ts b/apps/web/src/lib/etherscan.ts index 642b21b..a629d35 100644 --- a/apps/web/src/lib/etherscan.ts +++ b/apps/web/src/lib/etherscan.ts @@ -3,6 +3,9 @@ const endpoints: { [k: number]: string } = { 3: "https://api-ropsten.etherscan.io/api", 4: "https://api-rinkeby.etherscan.io/api", 5: "https://api-goerli.etherscan.io/api", + 8453: "https://api.basescan.org/api", + 84531: "https://api-goerli.basescan.org/api", + 84532: "https://api-sepolia.basescan.org/api", }; export interface Transfer { diff --git a/apps/web/src/lib/rpc-provider.ts b/apps/web/src/lib/rpc-provider.ts index fb21727..8df5592 100644 --- a/apps/web/src/lib/rpc-provider.ts +++ b/apps/web/src/lib/rpc-provider.ts @@ -21,16 +21,20 @@ export function getProvider(chainID: number): RPCProviderObject | null { if (provider != null) { return provider; } - const url = providerConfigs[chainID]?.rpcUrl; if (url != null) { + const batchMaxCount = providerConfigs[chainID]?.batching ? 100 : 1; + provider = { - provider: new JsonRpcProvider(url), + provider: new JsonRpcProvider(url, undefined, { + batchMaxCount: batchMaxCount, + }), config: { supportTraceAPI: providerConfigs[chainID]?.supportTraceAPI, }, }; + providers[chainID] = provider; return provider; } diff --git a/packages/transaction-decoder/src/abi-strategy/etherscan-abi.ts b/packages/transaction-decoder/src/abi-strategy/etherscan-abi.ts index 1ab7d46..c6fd7b8 100644 --- a/packages/transaction-decoder/src/abi-strategy/etherscan-abi.ts +++ b/packages/transaction-decoder/src/abi-strategy/etherscan-abi.ts @@ -7,6 +7,9 @@ const endpoints: { [k: number]: string } = { 4: 'https://api-rinkeby.etherscan.io/api', 5: 'https://api-goerli.etherscan.io/api', 11155111: 'https://api-sepolia.etherscan.io/api', + 8453: 'https://api.basescan.org/api', + 84531: 'https://api-goerli.basescan.org/api', + 84532: 'https://api-sepolia.basescan.org/api', } async function fetchContractABI( diff --git a/packages/transaction-decoder/src/abi-strategy/request-model.ts b/packages/transaction-decoder/src/abi-strategy/request-model.ts index 43c4679..01fe402 100644 --- a/packages/transaction-decoder/src/abi-strategy/request-model.ts +++ b/packages/transaction-decoder/src/abi-strategy/request-model.ts @@ -16,6 +16,7 @@ export class ResolveStrategyABIError { ) {} } +//NOTE: we store address as key to be able to know adddress to abi mapping for caching export interface ContractABI { address?: Record func?: Record diff --git a/packages/transaction-decoder/src/helpers/networks.ts b/packages/transaction-decoder/src/helpers/networks.ts new file mode 100644 index 0000000..7144ad0 --- /dev/null +++ b/packages/transaction-decoder/src/helpers/networks.ts @@ -0,0 +1,21 @@ +export const chainIdToNetwork: { [key: number]: string } = { + 1: 'mainnet', + 3: 'ropsten', + 4: 'rinkeby', + 5: 'goerli', + 42: 'kovan', + 11155111: 'sepolia', + 42161: 'arbitrum', + 421613: 'arbitrum-goerli', + 8453: 'base', + 84531: 'base-goerli', + 84532: 'base-sepolia', + 56: 'bnb', + 97: 'bnbt', + 137: 'polygon', + 80001: 'mumbai', + 59144: 'linea', + 59140: 'linea-goerli', + 169: 'manta-pacific', + 3441005: 'manta-pacific-testnet', +} diff --git a/packages/transaction-decoder/src/transaction-decoder.ts b/packages/transaction-decoder/src/transaction-decoder.ts index feccbe7..813a07d 100644 --- a/packages/transaction-decoder/src/transaction-decoder.ts +++ b/packages/transaction-decoder/src/transaction-decoder.ts @@ -14,6 +14,7 @@ import { getProxyStorageSlot } from './decoding/proxies.js' import { getAndCacheAbi } from './abi-loader.js' import { getAndCacheContractMeta } from './contract-meta-loader.js' import traverse from 'traverse' +import { chainIdToNetwork } from './helpers/networks.js' export class UnsupportedEvent { readonly _tag = 'UnsupportedEvent' @@ -194,7 +195,7 @@ export const decodeTransaction = ({ }, traceCalls: decodedTraceRight, nativeValueSent: value, - chainSymbol: Network.from(Number(transaction.chainId)).name, + chainSymbol: chainIdToNetwork[Number(transaction.chainId)] ?? 'unknown', chainID: Number(transaction.chainId), interactions, effectiveGasPrice: receipt.gasPrice.toString(),