Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 46 additions & 26 deletions components/SuperchainContractTable.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,46 @@
import type { ReactElement } from 'react';
import { useEffect, useState } from 'react';
import { AddressTable, TableAddresses } from '@/components/AddressTable';
import toml from 'toml';
import { AddressTable, type TableAddresses } from './AddressTable';

const CONFIG_URL = 'https://raw.githubusercontent.com/ethereum-optimism/superchain-registry/main/superchain/configs/mainnet/superchain.toml';
function getConfigUrl(chain: string): string {
const isTestnet = chain === '11155111';
const network = isTestnet ? 'sepolia' : 'mainnet';
return `https://raw.githubusercontent.com/ethereum-optimism/superchain-registry/main/superchain/configs/${network}/superchain.toml`;
}

function parseSimpleToml(tomlText: string): Record<string, any> {
const result: Record<string, any> = {};
const lines = tomlText.split('\n');

for (const line of lines) {
const trimmed = line.trim();
if (trimmed && !trimmed.startsWith('#') && trimmed.includes('=')) {
const [key, value] = trimmed.split('=', 2);
const cleanKey = key.trim();
const cleanValue = value.trim().replace(/['"]/g, '');

if (/^0x[a-fA-F0-9]{40}$/.test(cleanValue)) {
result[cleanKey] = cleanValue;
}
}
}

return result;
}

function extractAddresses(obj: Record<string, any>): TableAddresses {
const addresses: TableAddresses = {};
for (const [key, value] of Object.entries(obj)) {
if (typeof value === 'string' && /^0x[a-fA-F0-9]{40}$/.test(value)) {
let newKey = key;
if (key === 'protocol_versions_addr') newKey = 'ProtocolVersions';
if (key === 'superchain_config_addr') newKey = 'SuperchainConfig';
if (key === 'op_contracts_manager_proxy_addr') newKey = 'OPContractsManagerProxy';
addresses[newKey] = value;
}
}
return addresses;
}

export function SuperchainContractTable({
chain,
Expand All @@ -19,12 +56,14 @@ export function SuperchainContractTable({
useEffect(() => {
async function fetchAddresses() {
try {
const response = await fetch(CONFIG_URL);
const configUrl = getConfigUrl(chain);
const response = await fetch(configUrl);
if (!response.ok) {
throw new Error('Failed to fetch config');
throw new Error(`Failed to fetch config from ${configUrl}`);
}
const text = await response.text();
const data = toml.parse(text);

const data = parseSimpleToml(text);
setConfig(data);
} catch (err) {
setError(err.message);
Expand All @@ -35,7 +74,7 @@ export function SuperchainContractTable({
}

fetchAddresses();
}, []);
}, [chain]);

if (loading) {
return <div>Loading...</div>;
Expand All @@ -45,25 +84,6 @@ export function SuperchainContractTable({
return <div>Error: {error}</div>;
}

// Helper function to recursively extract Ethereum addresses with renamed keys
function extractAddresses(obj: Record<string, any>, prefix = ''): TableAddresses {
const addresses: TableAddresses = {};
for (const [key, value] of Object.entries(obj)) {
if (typeof value === 'string' && /^0x[a-fA-F0-9]{40}$/.test(value)) {
// Rename specific keys
let newKey = `${prefix}${key}`;
if (key === 'protocol_versions_addr') newKey = 'ProtocolVersions';
if (key === 'superchain_config_addr') newKey = 'SuperchainConfig';
if (key === 'op_contracts_manager_proxy_addr') newKey = 'OPContractsManagerProxy';
addresses[newKey] = value;
} else if (typeof value === 'object' && value !== null) {
Object.assign(addresses, extractAddresses(value, `${key}.`)); // Recurse into nested objects
}
}
return addresses;
}


const addresses = extractAddresses(config || {});

return (
Expand Down
2 changes: 1 addition & 1 deletion words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,8 @@ Sunnyside
superchain
Superchain
SUPERCHAIN
superchainerc
Superchain's
superchainerc
Superlend
Superloans
Superscan
Expand Down