Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: migrate to new chain data source #791

Closed
wants to merge 2 commits into from
Closed
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
114 changes: 63 additions & 51 deletions src/components/chainlist.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { useState, useEffect, useMemo } from 'react'
import { mainnet as mainnetEvmMetadata, testnet as testnetEvmMetadata } from "../../src/data/evm_chains.json"
import { mainnet as mainnetCosmosMetadata, testnet as testnetCosmosMetadata } from "../../src/data/cosmos_chains.json"
import AddKeplr from "./keplr"
import { useState, useEffect, useMemo } from "react";
import {
mainnet as mainnetEvmMetadata,
testnet as testnetEvmMetadata,
} from "../../src/data/evm_chains.json";
import {
mainnet as mainnetCosmosMetadata,
testnet as testnetCosmosMetadata,
} from "../../src/data/cosmos_chains.json";
import AddKeplr from "./keplr";

function ChainListRow({ chainId, name, identifier, environment }) {
return (
Expand All @@ -13,85 +19,93 @@ function ChainListRow({ chainId, name, identifier, environment }) {
<AddKeplr environment={environment} chain={chainId} />
</td>
</tr>
)
);
}


const createChainIndex = (chains) => {
const index = new Map();
for (const chain of chains) {
if (index.has(chain.chain_id)) {
console.error(`duplicate chain ${chain.chain_id}. Removing to be safe`)
index.delete(chain.chain_id)
console.error(`duplicate chain ${chain.chain_id}. Removing to be safe`);
index.delete(chain.chain_id);
}
index.set(chain.network_id, chain)
index.set(chain.network_id, chain);
}
return index
}
return index;
};

export default ({ environment }) => {
const chainIndex = useMemo(() => {
switch (environment) {
case `mainnet`:
return createChainIndex([...mainnetEvmMetadata, ...mainnetCosmosMetadata])
return createChainIndex([
...mainnetEvmMetadata,
...mainnetCosmosMetadata,
]);
case `testnet`:
return createChainIndex([...testnetEvmMetadata, ...testnetCosmosMetadata])
return createChainIndex([
...testnetEvmMetadata,
...testnetCosmosMetadata,
]);
default:
console.error(`invalid environment ${environment}`)
return null
console.error(`invalid environment ${environment}`);
return null;
}
}, [environment]);

const [fetching, setFetching] = useState(false)
const [response, setResponse] = useState(null)
const [error, setError] = useState(null)
const [fetching, setFetching] = useState(false);
const [response, setResponse] = useState(null);
const [error, setError] = useState(null);

useEffect(() => {
if (!response) request();
}, [response])
}, [response]);

const request = async () => {
setFetching(true);

setFetching(true)

const endpoint_url = environment === `testnet`
? `https://lcd-axelar-testnet.imperator.co/axelar/nexus/v1beta1/chains?status=1`
: `https://lcd-axelar.imperator.co/axelar/nexus/v1beta1/chains?status=1`;
const endpoint_url =
environment === `testnet`
? `https://lcd-axelar-testnet.imperator.co/axelar/nexus/v1beta1/chains?status=1`
: `https://lcd-axelar.imperator.co/axelar/nexus/v1beta1/chains?status=1`;

fetch(endpoint_url)
.then(data => data.json())
.then(chains => setResponse(chains))
.catch(error => setError(true))
.finally(() => setFetching(false))
}
.then((data) => data.json())
.then((chains) => setResponse(chains))
.catch((error) => setError(true))
.finally(() => setFetching(false));
};

const tableRowData = useMemo(() => {
if (!response) return null
if (!response) return null;
return response.chains.map((chainIdentifier, idx) => {
const chainData = chainIndex.get(chainIdentifier)
const chainData = chainIndex.get(chainIdentifier);
if (!chainData) {
console.error(`chain ${chainIdentifier} not found in chain index`)
return null
console.error(`chain ${chainIdentifier} not found in chain index`);
return null;
}

return <ChainListRow
key={idx}
chainId={chainData.chain_id}
name={chainData.name}
identifier={chainIdentifier}
environment={environment} />
return (
<ChainListRow
key={idx}
chainId={chainData.chain_id}
name={chainData.name}
identifier={chainIdentifier}
environment={environment}
/>
);
});
}, [response, environment])
}, [response, environment]);

if (fetching)
return <div className="mx-1 mt-5 space-y-4">
Fetching active chains...
</div>
return <div className="mx-1 mt-5 space-y-4">Fetching active chains...</div>;

if (error)
return <div className="mx-1 mt-5 space-y-4">
Error loading chains. Please refresh this page.
</div>
return (
<div className="mx-1 mt-5 space-y-4">
Error loading chains. Please refresh this page.
</div>
);

return (
<div className="mx-1 mt-5 space-y-1">
Expand All @@ -104,10 +118,8 @@ export default ({ environment }) => {
<th>Add Chain</th>
</tr>
</thead>
<tbody>
{tableRowData}
</tbody>
<tbody>{tableRowData}</tbody>
</table>
</div>
)
}
);
};
138 changes: 84 additions & 54 deletions src/components/evm/chains.jsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,78 @@
import AddChain from "../web3";
import Copy from "../copy";
import { ellipse } from "../../utils";
import evm_chains from "../../data/evm_chains.json";
import gateways from "../../data/gateways.json";
import gas_services from "../../data/gas_services.json";
import { useEffect, useState } from "react";

export default ({ environment = "mainnet" }) => {
const _evm_chains = evm_chains?.[environment] || [];
const _gateways = gateways?.[environment] || [];
const _gas_services = gas_services?.[environment] || [];
const CHAIN_CONFIGS = {
mainnet:
"https://axelar-mainnet.s3.us-east-2.amazonaws.com/configs/mainnet-config-1.x.json",
testnet:
"https://axelar-testnet.s3.us-east-2.amazonaws.com/configs/testnet-config-1.x.json",
};

const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
try {
const response = await fetch(CHAIN_CONFIGS[environment]);
console.log("fetching", CHAIN_CONFIGS[environment]);
const data = await response.json();
console.log("data", data);
setData(data);
} catch (error) {
setError(error);
} finally {
setIsLoading(false);
}
};

fetchData();
}, []);

return (
<div className="resource-grid">
{_evm_chains
.filter(c => !c?.is_staging)
.map((c, i) => {
const {
id,
chain_id,
network_id,
name,
provider_params,
image,
} = { ...c };

const explorer_url = provider_params?.[0]?.blockExplorerUrls?.[0];
const gateway_contract_address = _gateways.find(_c => _c?.id === id)?.address;
const gas_service_address = _gas_services.find(_c => _c?.id === id)?.address;
{isLoading && <p>Loading chain data...</p>}
{error && <p>Error: {error.message}</p>}
{data &&
Object.values(data.chains)
.filter((chain) => chain.chainType == "evm")
.map((chain) => {
const newChain = {};

return (
<div
key={i}
className="resource-card"
>
newChain.id = chain.id;
newChain.chain_id = chain.externalChainId;
newChain.network_id = chain.id;
newChain.name = chain.displayName;
newChain.image = chain.iconUrl;
newChain.provider_params = {
chainId: "0x" + parseInt(newChain.chain_id, 10).toString(16),
chainName: chain.displayName,
rpcUrls: chain.rpcUrls,
nativeCurrency: chain.nativeCurrency,
blockExplorerUrls: chain.blockExplorers?.map(
(explorer) => explorer.url
),
};
newChain.explorer_url =
newChain.provider_params.blockExplorerUrls?.[0] || null;
newChain.gateway_contract_address =
chain.config?.contracts?.["AxelarGateway"].address;
newChain.gas_service_address =
chain.config?.contracts?.["AxelarGasService"].address;
console.log("new chain data is", newChain);
return newChain;
})
.map((chain, i) => (
<div className="resource-card" key={i}>
<div className="flex items-start justify-between">
<div className="flex items-center">
{image && (
{chain.image && (
<img
src={image}
src={chain.image}
alt=""
width={32}
height={32}
Expand All @@ -46,17 +81,14 @@ export default ({ environment = "mainnet" }) => {
)}
<div className="flex flex-col">
<span className="text-base font-semibold">
{name}
{chain.name}
</span>
<span className="text-gray-400 dark:text-gray-500 text-sm font-medium">
Chain ID: {chain_id}
Chain ID: {chain.chain_id}
</span>
</div>
</div>
<AddChain
environment={environment}
chain={id}
/>
<AddChain environment={chain.environment} chain={chain.id} />
</div>
<div className="flex flex-col flex-wrap justify-between">
<span className="whitespace-nowrap text-sm text-gray-600 dark:text-gray-400">
Expand All @@ -65,8 +97,8 @@ export default ({ environment = "mainnet" }) => {
<div className="flex items-center text-sm space-x-1">
<Copy
size={18}
title={network_id}
value={network_id}
title={chain.network_id}
value={chain.network_id}
/>
</div>
</div>
Expand All @@ -75,25 +107,25 @@ export default ({ environment = "mainnet" }) => {
Gateway Contract:
</span>
<div className="flex items-center text-sm space-x-1">
{gateway_contract_address ?
{chain.gateway_contract_address ? (
<a
href={`${explorer_url}/address/${gateway_contract_address}`}
href={`${chain.explorer_url}/address/${chain.gateway_contract_address}`}
target="_blank"
rel="noopener noreferrer"
className="no-underline text-blue-500 dark:text-white font-semibold"
>
{ellipse(gateway_contract_address, 14)}
{/* {ellipse(chain.gateway_contract_address, 14)} */}
</a>
:
) : (
<span className="text-gray-500 dark:text-white font-semibold">
-
</span>
}
{gateway_contract_address && (
)}
{chain.gateway_contract_address && (
<Copy
size={18}
hide={true}
value={gateway_contract_address}
value={chain.gateway_contract_address}
/>
)}
</div>
Expand All @@ -103,33 +135,31 @@ export default ({ environment = "mainnet" }) => {
Gas Service Contract:
</span>
<div className="flex items-center text-sm space-x-1">
{gas_service_address ?
{chain.gas_service_address ? (
<a
href={`${explorer_url}/address/${gas_service_address}`}
href={`${chain.explorer_url}/address/${chain.gas_service_address}`}
target="_blank"
rel="noopener noreferrer"
className="no-underline text-blue-500 dark:text-white font-semibold"
>
{ellipse(gas_service_address, 14)}
{ellipse(chain.gas_service_address, 14)}
</a>
:
) : (
<span className="text-gray-500 dark:text-white font-semibold">
-
</span>
}
{gas_service_address && (
)}
{chain.gas_service_address && (
<Copy
size={18}
hide={true}
value={gas_service_address}
value={chain.gas_service_address}
/>
)}
</div>
</div>
</div>
);
})
}
))}
</div>
);
};
};