-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #239 from hypercerts-org/develop
Push to PRD
- Loading branch information
Showing
31 changed files
with
1,012 additions
and
586 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { | ||
indexerEnvironment as environment, | ||
Environment, | ||
} from "../utils/constants.js"; | ||
import { Chain } from "viem"; | ||
import { | ||
arbitrum, | ||
arbitrumSepolia, | ||
base, | ||
baseSepolia, | ||
celo, | ||
filecoin, | ||
filecoinCalibration, | ||
optimism, | ||
sepolia, | ||
} from "viem/chains"; | ||
|
||
export class ChainFactory { | ||
static getChain(chainId: number): Chain { | ||
const chains: Record<number, Chain> = { | ||
10: optimism, | ||
314: filecoin, | ||
8453: base, | ||
42161: arbitrum, | ||
42220: celo, | ||
84532: baseSepolia, | ||
314159: filecoinCalibration, | ||
421614: arbitrumSepolia, | ||
11155111: sepolia, | ||
}; | ||
|
||
const chain = chains[chainId]; | ||
if (!chain) throw new Error(`Unsupported chain ID: ${chainId}`); | ||
return chain; | ||
} | ||
|
||
static getSupportedChains(): number[] { | ||
return environment === Environment.TEST | ||
? [84532, 314159, 421614, 11155111] | ||
: [10, 8453, 42220, 42161, 314]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import { | ||
alchemyApiKey, | ||
drpcApiPkey, | ||
infuraApiKey, | ||
} from "../utils/constants.js"; | ||
import { PublicClient, createPublicClient, fallback } from "viem"; | ||
import { ChainFactory } from "./chainFactory.js"; | ||
import { RpcClientFactory } from "./rpcClientFactory.js"; | ||
import { JsonRpcProvider } from "ethers"; | ||
|
||
interface RpcProvider { | ||
getUrl(chainId: number): string | undefined; | ||
} | ||
|
||
class AlchemyProvider implements RpcProvider { | ||
getUrl(chainId: number): string | undefined { | ||
const urls: Record<number, string> = { | ||
10: `https://opt-mainnet.g.alchemy.com/v2/${alchemyApiKey}`, | ||
8453: `https://base-mainnet.g.alchemy.com/v2/${alchemyApiKey}`, | ||
42161: `https://arb-mainnet.g.alchemy.com/v2/${alchemyApiKey}`, | ||
421614: `https://arb-sepolia.g.alchemy.com/v2/${alchemyApiKey}`, | ||
84532: `https://base-sepolia.g.alchemy.com/v2/${alchemyApiKey}`, | ||
11155111: `https://eth-sepolia.g.alchemy.com/v2/${alchemyApiKey}`, | ||
}; | ||
return urls[chainId]; | ||
} | ||
} | ||
|
||
class InfuraProvider implements RpcProvider { | ||
getUrl(chainId: number): string | undefined { | ||
const urls: Record<number, string> = { | ||
10: `https://optimism-mainnet.infura.io/v3/${infuraApiKey}`, | ||
42220: `https://celo-mainnet.infura.io/v3/${infuraApiKey}`, | ||
42161: `https://arbitrum-mainnet.infura.io/v3/${infuraApiKey}`, | ||
421614: `https://arbitrum-sepolia.infura.io/v3/${infuraApiKey}`, | ||
}; | ||
return urls[chainId]; | ||
} | ||
} | ||
|
||
class DrpcProvider implements RpcProvider { | ||
getUrl(chainId: number): string | undefined { | ||
const networks: Record<number, string> = { | ||
10: "optimism", | ||
8453: "base", | ||
42220: "celo", | ||
42161: "arbitrum", | ||
421614: "arbitrum-sepolia", | ||
}; | ||
const network = networks[chainId]; | ||
return network | ||
? `https://lb.drpc.org/ogrpc?network=${network}&dkey=${drpcApiPkey}` | ||
: undefined; | ||
} | ||
} | ||
|
||
class GlifProvider implements RpcProvider { | ||
getUrl(chainId: number): string | undefined { | ||
const urls: Record<number, string> = { | ||
314: `https://node.glif.io/space07/lotus/rpc/v1`, | ||
314159: `https://calibration.node.glif.io/archive/lotus/rpc/v1`, | ||
}; | ||
return urls[chainId]; | ||
} | ||
} | ||
|
||
export class EvmClientFactory { | ||
private static readonly providers: RpcProvider[] = [ | ||
new AlchemyProvider(), | ||
new InfuraProvider(), | ||
new DrpcProvider(), | ||
new GlifProvider(), | ||
]; | ||
|
||
static createViemClient(chainId: number): PublicClient { | ||
const urls = EvmClientFactory.getAllAvailableUrls(chainId); | ||
if (urls.length === 0) | ||
throw new Error(`No RPC URL available for chain ${chainId}`); | ||
|
||
const transports = urls.map((url) => | ||
RpcClientFactory.createViemTransport(chainId, url), | ||
); | ||
|
||
return createPublicClient({ | ||
chain: ChainFactory.getChain(chainId), | ||
transport: fallback(transports), | ||
}); | ||
} | ||
|
||
static createEthersClient(chainId: number): JsonRpcProvider { | ||
const url = EvmClientFactory.getFirstAvailableUrl(chainId); | ||
if (!url) throw new Error(`No RPC URL available for chain ${chainId}`); | ||
return RpcClientFactory.createEthersJsonRpcProvider(chainId, url); | ||
} | ||
|
||
static getAllAvailableUrls(chainId: number): string[] { | ||
return EvmClientFactory.providers | ||
.map((provider) => provider.getUrl(chainId)) | ||
.filter((url): url is string => url !== undefined); | ||
} | ||
|
||
static getRpcUrl(chainId: number): string { | ||
const url = EvmClientFactory.getFirstAvailableUrl(chainId); | ||
if (!url) throw new Error(`No RPC URL available for chain ${chainId}`); | ||
return url; | ||
} | ||
|
||
static getPublicRpcUrl(chainId: number): string { | ||
const chain = ChainFactory.getChain(chainId); | ||
if (!chain.rpcUrls?.default?.http?.[0]) { | ||
throw new Error(`No public RPC URL available for chain ${chainId}`); | ||
} | ||
return chain.rpcUrls.default.http[0]; | ||
} | ||
|
||
// Keep this for backward compatibility | ||
static getFirstAvailableUrl(chainId: number): string | undefined { | ||
return EvmClientFactory.getAllAvailableUrls(chainId)[0]; | ||
} | ||
} | ||
|
||
// Public API | ||
export const getSupportedChains = ChainFactory.getSupportedChains; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { http, Transport } from "viem"; | ||
import { CustomEthersJsonRpcProvider } from "../lib/rpcProviders/customEthersJsonRpcProvider.js"; | ||
import { filecoinApiKey } from "../utils/constants.js"; | ||
import { ChainFactory } from "./chainFactory.js"; | ||
|
||
interface RpcConfig { | ||
url: string; | ||
headers?: Record<string, string>; | ||
timeout?: number; | ||
} | ||
|
||
// Chain-specific RPC configuration factory | ||
class RpcConfigFactory { | ||
private static readonly DEFAULT_TIMEOUT = 20_000; | ||
|
||
static getConfig(chainId: number, url: string): RpcConfig { | ||
const baseConfig: RpcConfig = { | ||
url, | ||
timeout: this.DEFAULT_TIMEOUT, | ||
}; | ||
|
||
// Chain-specific configurations | ||
switch (chainId) { | ||
case 314: | ||
case 314159: | ||
return { | ||
...baseConfig, | ||
headers: { | ||
Authorization: `Bearer ${filecoinApiKey}`, | ||
}, | ||
}; | ||
default: | ||
return baseConfig; | ||
} | ||
} | ||
} | ||
|
||
// Unified client factory for both Viem and Chainsauce clients | ||
export class RpcClientFactory { | ||
// Creates a Viem transport | ||
static createViemTransport(chainId: number, url: string): Transport { | ||
const config = RpcConfigFactory.getConfig(chainId, url); | ||
|
||
const httpConfig: Parameters<typeof http>[1] = { | ||
timeout: config.timeout, | ||
}; | ||
|
||
if (config.headers) { | ||
httpConfig.fetchOptions = { | ||
headers: config.headers, | ||
}; | ||
} | ||
|
||
return http(config.url, httpConfig); | ||
} | ||
|
||
static createEthersJsonRpcProvider(chainId: number, url: string) { | ||
const config = RpcConfigFactory.getConfig(chainId, url); | ||
const chain = ChainFactory.getChain(chainId); | ||
const network = { | ||
chainId: chain.id, | ||
name: chain.name, | ||
ensAddress: chain.contracts?.ensRegistry?.address, | ||
}; | ||
|
||
return new CustomEthersJsonRpcProvider({ | ||
url: config.url, | ||
config: { headers: config.headers }, | ||
network, | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.