From 5c1d560d0c1e658aef14752baa7c2ec3ea706c5b Mon Sep 17 00:00:00 2001 From: Jefferson Mantovani Date: Mon, 6 Oct 2025 21:57:47 -0300 Subject: [PATCH] refactor: dynamize network config --- src/blockchain/addresses.ts | 48 +++++---------- src/blockchain/provider.ts | 10 ++-- src/blockchain/sellerMethods.ts | 6 +- src/composables/useUser.ts | 7 ++- src/config/networks.ts | 103 ++++++++++++++++++++++++++++++++ src/model/Networks.ts | 22 +++---- 6 files changed, 143 insertions(+), 53 deletions(-) create mode 100644 src/config/networks.ts diff --git a/src/blockchain/addresses.ts b/src/blockchain/addresses.ts index d7499cc..0fd7e8c 100644 --- a/src/blockchain/addresses.ts +++ b/src/blockchain/addresses.ts @@ -1,23 +1,13 @@ import { useUser } from "@/composables/useUser"; import { NetworkEnum, TokenEnum } from "@/model/NetworkEnum"; import { createPublicClient, http, type Address } from "viem"; -import { sepolia, rootstockTestnet } from "viem/chains"; - -const Tokens: { [key in NetworkEnum]: { [key in TokenEnum]: Address } } = { - [NetworkEnum.sepolia]: { - BRZ: "0x3eBE67A2C7bdB2081CBd34ba3281E90377462289", - // BRX: "0x3eBE67A2C7bdB2081CBd34ba3281E90377462289", - }, - [NetworkEnum.rootstock]: { - BRZ: "0xfE841c74250e57640390f46d914C88d22C51e82e", - // BRX: "0xfE841c74250e57640390f46d914C88d22C51e82e", - }, -}; +import { getContractAddress, getRpcUrl, getNetworkConfig, getViemChain } from "@/config/networks"; export const getTokenByAddress = (address: Address) => { const user = useUser(); - const networksTokens = Tokens[user.networkName.value]; - for (const [token, tokenAddress] of Object.entries(networksTokens)) { + const networkConfig = getNetworkConfig(user.networkName.value); + + for (const [token, tokenAddress] of Object.entries(networkConfig.contracts.tokenAddresses)) { if (tokenAddress.toLowerCase() === address.toLowerCase()) { return token; } @@ -30,35 +20,29 @@ export const getTokenAddress = ( network?: NetworkEnum ): Address => { const user = useUser(); - return Tokens[network ? network : user.networkName.value][ - token - ]; + const networkId = network ? network : user.networkName.value; + + const tokenAddress = getContractAddress(networkId, token); + return tokenAddress as Address; }; export const getP2PixAddress = (network?: NetworkEnum): Address => { const user = useUser(); - const possibleP2PixAddresses: { [key in NetworkEnum]: Address } = { - [NetworkEnum.sepolia]: "0xb7cD135F5eFD9760981e02E2a898790b688939fe", - [NetworkEnum.rootstock]: "0x57Dcba05980761169508886eEdc6f5E7EC0411Dc", - }; - - return possibleP2PixAddresses[ - network ? network : user.networkName.value - ]; + const networkId = network ? network : user.networkName.value; + + const p2pixAddress = getContractAddress(networkId, 'p2pix'); + return p2pixAddress as Address; }; export const getProviderUrl = (network?: NetworkEnum): string => { const user = useUser(); - const possibleProvidersUrls: { [key in NetworkEnum]: string } = { - [NetworkEnum.sepolia]: import.meta.env.VITE_SEPOLIA_API_URL, - [NetworkEnum.rootstock]: import.meta.env.VITE_RSK_API_URL, - }; - - return possibleProvidersUrls[network || user.networkName.value]; + const networkId = network || user.networkName.value; + + return getRpcUrl(networkId); }; export const getProviderByNetwork = (network: NetworkEnum) => { - const chain = network === NetworkEnum.sepolia ? sepolia : rootstockTestnet; + const chain = getViemChain(network); return createPublicClient({ chain, transport: http(getProviderUrl(network)), diff --git a/src/blockchain/provider.ts b/src/blockchain/provider.ts index f1d06d0..949ad94 100644 --- a/src/blockchain/provider.ts +++ b/src/blockchain/provider.ts @@ -9,17 +9,18 @@ import { PublicClient, WalletClient, } from "viem"; -import { sepolia, rootstockTestnet } from "viem/chains"; import { useUser } from "@/composables/useUser"; +import { getViemChain } from "@/config/networks"; let walletClient: WalletClient | null = null; const getPublicClient = (): PublicClient => { const user = useUser(); const rpcUrl = getProviderUrl(); + const chain = getViemChain(user.networkName.value); + return createPublicClient({ - chain: - Number(user.networkName.value) === sepolia.id ? sepolia : rootstockTestnet, + chain, transport: http(rpcUrl), }); }; @@ -45,8 +46,7 @@ const getContract = async (onlyRpcProvider = false) => { const connectProvider = async (p: any): Promise => { const user = useUser(); - const chain = - Number(user.networkName.value) === sepolia.id ? sepolia : rootstockTestnet; + const chain = getViemChain(user.networkName.value); const [account] = await p!.request({ method: "eth_requestAccounts" }); diff --git a/src/blockchain/sellerMethods.ts b/src/blockchain/sellerMethods.ts index 6a06991..b4f5a5d 100644 --- a/src/blockchain/sellerMethods.ts +++ b/src/blockchain/sellerMethods.ts @@ -1,7 +1,7 @@ import { getContract, getPublicClient, getWalletClient } from "./provider"; import { getTokenAddress, getP2PixAddress } from "./addresses"; import { parseEther, toHex } from "viem"; -import { sepolia, rootstockTestnet } from "viem/chains"; +import { getViemChain } from "@/config/networks"; import { mockTokenAbi } from "./abi"; import { useUser } from "@/composables/useUser"; @@ -33,7 +33,7 @@ const approveTokens = async (participant: Participant): Promise => { if ( allowance < parseEther(participant.offer.toString()) ) { // Approve tokens - const chain = user.networkId.value === sepolia.id ? sepolia : rootstockTestnet; + const chain = getViemChain(user.networkName.value); const hash = await walletClient.writeContract({ address: tokenAddress, abi: mockTokenAbi, @@ -65,7 +65,7 @@ const addDeposit = async (): Promise => { if (!sellerId.id) { throw new Error("Failed to create participant"); } - const chain = user.networkId.value === sepolia.id ? sepolia : rootstockTestnet; + const chain = getViemChain(user.networkName.value); const hash = await walletClient.writeContract({ address, abi, diff --git a/src/composables/useUser.ts b/src/composables/useUser.ts index 4a51ce6..f2402c4 100644 --- a/src/composables/useUser.ts +++ b/src/composables/useUser.ts @@ -3,11 +3,12 @@ import { NetworkEnum, TokenEnum } from "../model/NetworkEnum"; import type { ValidDeposit } from "@/model/ValidDeposit"; import type { Participant } from "../utils/bbPay"; import type { Address } from "viem" +import { DEFAULT_NETWORK, getNetworkConfig } from "@/config/networks"; const walletAddress = ref
(null); const balance = ref(""); -const networkId = ref(11155111); -const networkName = ref(NetworkEnum.sepolia); +const networkId = ref(parseInt(getNetworkConfig(DEFAULT_NETWORK).chainId, 16)); +const networkName = ref(DEFAULT_NETWORK); const selectedToken = ref(TokenEnum.BRZ); const loadingLock = ref(false); const sellerView = ref(false); @@ -32,7 +33,7 @@ export function useUser() { }; const setNetworkId = (network: string | number) => { - networkName.value = Number(network) as NetworkEnum || NetworkEnum.sepolia; + networkName.value = Number(network) as NetworkEnum || DEFAULT_NETWORK; networkId.value = Number(network); }; diff --git a/src/config/networks.ts b/src/config/networks.ts new file mode 100644 index 0000000..3658801 --- /dev/null +++ b/src/config/networks.ts @@ -0,0 +1,103 @@ +import { NetworkEnum } from "@/model/NetworkEnum"; +import { sepolia, rootstockTestnet, type Chain } from "viem/chains"; + +export interface NetworkConfig { + id: NetworkEnum; + chainId: string; + chainName: string; + token: string; + rpcUrl: string; + blockExplorerUrl: string; + iconPath: string; + viemChain: Chain; + contracts: { + p2pixAddress: string; + tokenAddresses: Record; + }; +} + +export const NETWORK_CONFIGS: Record = { + [NetworkEnum.sepolia]: { + id: NetworkEnum.sepolia, + chainId: "0xAA36A7", + chainName: "Sepolia Testnet", + token: "ETH", + rpcUrl: import.meta.env.VITE_SEPOLIA_API_URL, + blockExplorerUrl: "https://sepolia.etherscan.io", + iconPath: "/ethereum.svg", + viemChain: sepolia, + contracts: { + p2pixAddress: "0xb7cD135F5eFD9760981e02E2a898790b688939fe", + tokenAddresses: { + BRZ: "0x3eBE67A2C7bdB2081CBd34ba3281E90377462289", + }, + }, + }, + [NetworkEnum.rootstock]: { + id: NetworkEnum.rootstock, + chainId: "0x1F", + chainName: "Rootstock Testnet", + token: "tRBTC", + rpcUrl: import.meta.env.VITE_ROOTSTOCK_API_URL, + blockExplorerUrl: "https://explorer.testnet.rsk.co", + iconPath: "/rootstock.svg", + viemChain: rootstockTestnet, + contracts: { + p2pixAddress: "0x57Dcba05980761169508886eEdc6f5E7EC0411Dc", + tokenAddresses: { + BRZ: "0xfE841c74250e57640390f46d914C88d22C51e82e", + }, + }, + }, +}; + +export const DEFAULT_NETWORK = NetworkEnum.sepolia; + +export const ENABLED_NETWORKS: NetworkEnum[] = [ + NetworkEnum.sepolia, + NetworkEnum.rootstock, +]; + +export const getNetworkConfig = (networkId: NetworkEnum): NetworkConfig => { + return NETWORK_CONFIGS[networkId]; +}; + +export const getEnabledNetworks = (): NetworkConfig[] => { + return ENABLED_NETWORKS.map(id => NETWORK_CONFIGS[id]); +}; + +export const isNetworkEnabled = (networkId: NetworkEnum): boolean => { + return ENABLED_NETWORKS.includes(networkId); +}; + +export const getNetworkByChainId = (chainId: string): NetworkConfig | null => { + const network = Object.values(NETWORK_CONFIGS).find( + config => config.chainId === chainId + ); + return network || null; +}; + +export const getContractAddress = ( + networkId: NetworkEnum, + contractType: 'p2pix' | string +): string => { + const config = getNetworkConfig(networkId); + + if (contractType === 'p2pix') { + return config.contracts.p2pixAddress; + } + + return config.contracts.tokenAddresses[contractType] || ''; +}; + +export const getRpcUrl = (networkId: NetworkEnum): string => { + return getNetworkConfig(networkId).rpcUrl; +}; + +export const getBlockExplorerUrl = (networkId: NetworkEnum): string => { + return getNetworkConfig(networkId).blockExplorerUrl; +}; + +export const getViemChain = (networkId: NetworkEnum): Chain => { + return getNetworkConfig(networkId).viemChain; +}; diff --git a/src/model/Networks.ts b/src/model/Networks.ts index 14b797d..a136e11 100644 --- a/src/model/Networks.ts +++ b/src/model/Networks.ts @@ -1,4 +1,5 @@ import { NetworkEnum } from "@/model/NetworkEnum"; +import { getNetworkConfig } from "@/config/networks"; export interface NetworkConfig { chainId: string; @@ -8,19 +9,20 @@ export interface NetworkConfig { blockExplorerUrl?: string; } +// Mapeamento para compatibilidade com código existente export const Networks: { [key in NetworkEnum]: NetworkConfig } = { [NetworkEnum.sepolia]: { - chainId: "0xAA36A7", - chainName: "Sepolia Testnet", - token: "ETH", - rpcUrl: import.meta.env.VITE_SEPOLIA_API_URL, - blockExplorerUrl: "https://sepolia.etherscan.io", + chainId: getNetworkConfig(NetworkEnum.sepolia).chainId, + chainName: getNetworkConfig(NetworkEnum.sepolia).chainName, + token: getNetworkConfig(NetworkEnum.sepolia).token, + rpcUrl: getNetworkConfig(NetworkEnum.sepolia).rpcUrl, + blockExplorerUrl: getNetworkConfig(NetworkEnum.sepolia).blockExplorerUrl, }, [NetworkEnum.rootstock]: { - chainId: "0x1F", - chainName: "Rootstock Testnet", - token: "tRBTC", - rpcUrl: import.meta.env.VITE_ROOTSTOCK_API_URL, - blockExplorerUrl: "https://explorer.testnet.rsk.co", + chainId: getNetworkConfig(NetworkEnum.rootstock).chainId, + chainName: getNetworkConfig(NetworkEnum.rootstock).chainName, + token: getNetworkConfig(NetworkEnum.rootstock).token, + rpcUrl: getNetworkConfig(NetworkEnum.rootstock).rpcUrl, + blockExplorerUrl: getNetworkConfig(NetworkEnum.rootstock).blockExplorerUrl, }, };