Publish Chain 138 RPC capability metadata
This commit is contained in:
@@ -52,6 +52,30 @@ type TokenListCatalog = {
|
||||
tokens?: TokenListToken[]
|
||||
}
|
||||
|
||||
type CapabilitiesCatalog = {
|
||||
name?: string
|
||||
chainId?: number
|
||||
chainName?: string
|
||||
rpcUrl?: string
|
||||
explorerApiUrl?: string
|
||||
generatedBy?: string
|
||||
walletSupport?: {
|
||||
walletAddEthereumChain?: boolean
|
||||
walletWatchAsset?: boolean
|
||||
notes?: string[]
|
||||
}
|
||||
http?: {
|
||||
supportedMethods?: string[]
|
||||
unsupportedMethods?: string[]
|
||||
notes?: string[]
|
||||
}
|
||||
tracing?: {
|
||||
supportedMethods?: string[]
|
||||
unsupportedMethods?: string[]
|
||||
notes?: string[]
|
||||
}
|
||||
}
|
||||
|
||||
type EthereumProvider = {
|
||||
request: (args: { method: string; params?: unknown[] }) => Promise<unknown>
|
||||
}
|
||||
@@ -107,6 +131,7 @@ export function AddToMetaMask() {
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [networks, setNetworks] = useState<NetworksCatalog | null>(null)
|
||||
const [tokenList, setTokenList] = useState<TokenListCatalog | null>(null)
|
||||
const [capabilities, setCapabilities] = useState<CapabilitiesCatalog | null>(null)
|
||||
|
||||
const ethereum = typeof window !== 'undefined'
|
||||
? (window as unknown as { ethereum?: EthereumProvider }).ethereum
|
||||
@@ -115,29 +140,34 @@ export function AddToMetaMask() {
|
||||
const apiBase = getApiBase().replace(/\/$/, '')
|
||||
const tokenListUrl = `${apiBase}/api/config/token-list`
|
||||
const networksUrl = `${apiBase}/api/config/networks`
|
||||
const capabilitiesUrl = `${apiBase}/api/config/capabilities`
|
||||
|
||||
useEffect(() => {
|
||||
let active = true
|
||||
|
||||
async function loadCatalogs() {
|
||||
try {
|
||||
const [networksResponse, tokenListResponse] = await Promise.all([
|
||||
const [networksResponse, tokenListResponse, capabilitiesResponse] = await Promise.all([
|
||||
fetch(networksUrl),
|
||||
fetch(tokenListUrl),
|
||||
fetch(capabilitiesUrl),
|
||||
])
|
||||
|
||||
const [networksJson, tokenListJson] = await Promise.all([
|
||||
const [networksJson, tokenListJson, capabilitiesJson] = await Promise.all([
|
||||
networksResponse.ok ? networksResponse.json() : null,
|
||||
tokenListResponse.ok ? tokenListResponse.json() : null,
|
||||
capabilitiesResponse.ok ? capabilitiesResponse.json() : null,
|
||||
])
|
||||
|
||||
if (!active) return
|
||||
setNetworks(networksJson)
|
||||
setTokenList(tokenListJson)
|
||||
setCapabilities(capabilitiesJson)
|
||||
} catch {
|
||||
if (!active) return
|
||||
setNetworks(null)
|
||||
setTokenList(null)
|
||||
setCapabilities(null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +176,7 @@ export function AddToMetaMask() {
|
||||
return () => {
|
||||
active = false
|
||||
}
|
||||
}, [networksUrl, tokenListUrl])
|
||||
}, [capabilitiesUrl, networksUrl, tokenListUrl])
|
||||
|
||||
const chains = useMemo(() => {
|
||||
const chainMap = new Map<number, WalletChain>()
|
||||
@@ -246,6 +276,9 @@ export function AddToMetaMask() {
|
||||
|
||||
const tokenCount138 = (tokenList?.tokens || []).filter((token) => token.chainId === 138).length
|
||||
const metadataKeywordString = (tokenList?.keywords || []).join(', ')
|
||||
const supportedHTTPMethods = capabilities?.http?.supportedMethods || []
|
||||
const unsupportedHTTPMethods = capabilities?.http?.unsupportedMethods || []
|
||||
const supportedTraceMethods = capabilities?.tracing?.supportedMethods || []
|
||||
|
||||
return (
|
||||
<div className="space-y-4 rounded-lg border border-gray-200 bg-white p-4 dark:border-gray-700 dark:bg-gray-800">
|
||||
@@ -301,6 +334,18 @@ export function AddToMetaMask() {
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="mb-1 text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Capabilities URL</p>
|
||||
<code className="block break-all rounded bg-gray-100 p-2 text-xs dark:bg-gray-900">{capabilitiesUrl}</code>
|
||||
<div className="mt-2 flex flex-wrap gap-2">
|
||||
<button type="button" onClick={() => copyText(capabilitiesUrl, 'capabilities URL')} className="rounded bg-gray-100 px-3 py-1.5 text-xs text-gray-700 hover:bg-gray-200 dark:bg-gray-900 dark:text-gray-200 dark:hover:bg-gray-700">
|
||||
Copy URL
|
||||
</button>
|
||||
<a href={capabilitiesUrl} target="_blank" rel="noopener noreferrer" className="rounded bg-gray-100 px-3 py-1.5 text-xs text-gray-700 hover:bg-gray-200 dark:bg-gray-900 dark:text-gray-200 dark:hover:bg-gray-700">
|
||||
Open JSON
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="mb-1 text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Token list URL</p>
|
||||
<code className="block break-all rounded bg-gray-100 p-2 text-xs dark:bg-gray-900">{tokenListUrl}</code>
|
||||
@@ -316,6 +361,42 @@ export function AddToMetaMask() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border border-gray-200 p-4 dark:border-gray-700">
|
||||
<div className="text-sm font-semibold text-gray-900 dark:text-white">Chain 138 RPC capabilities</div>
|
||||
<p className="mt-2 text-sm text-gray-600 dark:text-gray-400">
|
||||
This capability matrix documents what public RPC methods wallets can rely on today, what tracing the explorer
|
||||
can use, and where MetaMask will still fall back because the public node does not expose every optional fee method.
|
||||
</p>
|
||||
<div className="mt-4 space-y-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
<p>
|
||||
RPC endpoint:{' '}
|
||||
<span className="font-medium text-gray-900 dark:text-white">
|
||||
{capabilities?.rpcUrl || 'using published explorer fallback'}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
HTTP methods: {supportedHTTPMethods.length > 0 ? supportedHTTPMethods.join(', ') : 'metadata unavailable'}
|
||||
</p>
|
||||
<p>
|
||||
Missing wallet-facing methods:{' '}
|
||||
{unsupportedHTTPMethods.length > 0 ? unsupportedHTTPMethods.join(', ') : 'none listed'}
|
||||
</p>
|
||||
<p>
|
||||
Trace methods: {supportedTraceMethods.length > 0 ? supportedTraceMethods.join(', ') : 'metadata unavailable'}
|
||||
</p>
|
||||
{capabilities?.walletSupport?.notes?.map((note) => (
|
||||
<p key={note} className="text-xs">
|
||||
{note}
|
||||
</p>
|
||||
))}
|
||||
{capabilities?.http?.notes?.map((note) => (
|
||||
<p key={note} className="text-xs">
|
||||
{note}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border border-gray-200 p-4 dark:border-gray-700">
|
||||
<div className="text-sm font-semibold text-gray-900 dark:text-white">Featured Chain 138 tokens</div>
|
||||
<p className="mt-2 text-sm text-gray-600 dark:text-gray-400">
|
||||
|
||||
Reference in New Issue
Block a user