Add explorer liquidity access and live route proxies

This commit is contained in:
defiQUG
2026-03-27 12:02:36 -07:00
parent d02ee71cf6
commit 2491336b8e
17 changed files with 2746 additions and 125 deletions

View File

@@ -0,0 +1,257 @@
import Link from 'next/link'
import { Card } from '@/libs/frontend-ui-primitives/Card'
const publicApiBase = '/token-aggregation/api/v1'
const livePools = [
{
pair: 'cUSDT / cUSDC',
poolAddress: '0xff8d3b8fDF7B112759F076B69f4271D4209C0849',
reserves: '10,000,000 / 10,000,000',
},
{
pair: 'cUSDT / USDT',
poolAddress: '0x6fc60DEDc92a2047062294488539992710b99D71',
reserves: '10,000,000 / 10,000,000',
},
{
pair: 'cUSDC / USDC',
poolAddress: '0x0309178ae30302D83c76d6Dd402a684eF3160eec',
reserves: '10,000,000 / 10,000,000',
},
{
pair: 'cUSDT / cXAUC',
poolAddress: '0x1AA55E2001E5651349AfF5A63FD7A7Ae44f0F1b0',
reserves: '2,666,965 / 519.477000',
},
{
pair: 'cUSDC / cXAUC',
poolAddress: '0xEA9Ac6357CaCB42a83b9082B870610363B177cBa',
reserves: '1,000,000 / 194.782554',
},
{
pair: 'cEURT / cXAUC',
poolAddress: '0xbA99bc1eAAC164569d5AcA96C806934DDaF970Cf',
reserves: '1,000,000 / 225.577676',
},
]
const publicEndpoints = [
{
name: 'Canonical route matrix',
method: 'GET',
href: `${publicApiBase}/routes/matrix`,
notes: 'All live and optional non-live route inventory with counts and filters.',
},
{
name: 'Live ingestion export',
method: 'GET',
href: `${publicApiBase}/routes/ingestion?family=LiFi`,
notes: 'Flat live-route export for adapter ingestion and route discovery.',
},
{
name: 'Partner payload templates',
method: 'GET',
href: `${publicApiBase}/routes/partner-payloads?partner=0x&amount=1000000&includeUnsupported=true`,
notes: 'Builds exact 1inch, 0x, and LiFi request templates from live routes.',
},
{
name: 'Resolve supported partner payloads',
method: 'POST',
href: `${publicApiBase}/routes/partner-payloads/resolve`,
notes: 'Accepts partner, amount, and addresses and returns supported payloads by default.',
},
{
name: 'Dispatch supported partner payload',
method: 'POST',
href: `${publicApiBase}/routes/partner-payloads/dispatch`,
notes: 'Resolves then dispatches a single supported partner payload when the chain is supported.',
},
{
name: 'Internal Chain 138 execution plan',
method: 'POST',
href: `${publicApiBase}/routes/internal-execution-plan`,
notes: 'Returns the internal DODO PMM fallback plan when external partner support is unavailable.',
},
]
const routeHighlights = [
'Direct live routes: cUSDT <-> cUSDC, cUSDT <-> USDT, cUSDC <-> USDC, cUSDT <-> cXAUC, cUSDC <-> cXAUC, cEURT <-> cXAUC.',
'Multi-hop public routes exist through cXAUC for cEURT <-> cUSDT, cEURT <-> cUSDC, and an alternate cUSDT <-> cUSDC path.',
'Mainnet bridge discovery is live for cUSDT -> USDT and cUSDC -> USDC through the configured UniversalCCIPBridge lane.',
'External partner templates are available for 1inch, 0x, and LiFi, but Chain 138 remains unsupported on those public partner networks today.',
'When partner support is unavailable, the explorer can surface the internal DODO PMM execution plan instead of a dead end.',
]
const requestExamples = [
{
title: 'Inspect the full route matrix',
code: `GET ${publicApiBase}/routes/matrix?includeNonLive=true`,
},
{
title: 'Filter live same-chain swap routes on Chain 138',
code: `GET ${publicApiBase}/routes/ingestion?fromChainId=138&routeType=swap`,
},
{
title: 'Generate partner templates for review',
code: `GET ${publicApiBase}/routes/partner-payloads?partner=LiFi&amount=1000000&includeUnsupported=true`,
},
{
title: 'Resolve a dispatch candidate',
code: `POST ${publicApiBase}/routes/partner-payloads/resolve`,
},
{
title: 'Build the internal fallback plan',
code: `POST ${publicApiBase}/routes/internal-execution-plan`,
},
]
export default function LiquidityPage() {
return (
<main className="container mx-auto px-4 py-8">
<div className="mb-8 max-w-4xl">
<div className="mb-3 inline-flex rounded-full border border-amber-200 bg-amber-50 px-3 py-1 text-xs font-semibold uppercase tracking-[0.2em] text-amber-700">
Chain 138 Liquidity Access
</div>
<h1 className="mb-3 text-4xl font-bold text-gray-900 dark:text-white">
Public liquidity, route discovery, and execution access points
</h1>
<p className="text-lg leading-8 text-gray-600 dark:text-gray-400">
This explorer page pulls together the live public DODO PMM liquidity on Chain 138 and the
token-aggregation endpoints that DEX aggregators, integrators, and operators can use for
route discovery, payload generation, and internal fallback execution planning.
</p>
</div>
<div className="mb-8 grid gap-4 md:grid-cols-3">
<Card>
<div className="text-sm text-gray-500 dark:text-gray-400">Live public pools</div>
<div className="mt-2 text-3xl font-bold text-gray-900 dark:text-white">6</div>
<div className="mt-2 text-sm text-gray-600 dark:text-gray-400">
Verified public DODO PMM pools on Chain 138.
</div>
</Card>
<Card>
<div className="text-sm text-gray-500 dark:text-gray-400">Public access path</div>
<div className="mt-2 text-lg font-bold text-gray-900 dark:text-white">/token-aggregation/api/v1</div>
<div className="mt-2 text-sm text-gray-600 dark:text-gray-400">
Explorer-hosted proxy path for route, quote, and reporting APIs.
</div>
</Card>
<Card>
<div className="text-sm text-gray-500 dark:text-gray-400">Partner status</div>
<div className="mt-2 text-3xl font-bold text-gray-900 dark:text-white">Fallback Ready</div>
<div className="mt-2 text-sm text-gray-600 dark:text-gray-400">
Mainnet stable bridge routing is live; 1inch, 0x, and LiFi templates remain available for partner integrations, with internal fallback for unsupported Chain 138 execution.
</div>
</Card>
</div>
<div className="mb-8 grid gap-6 lg:grid-cols-[1.2fr_0.8fr]">
<Card title="Live Pool Snapshot">
<div className="space-y-4">
{livePools.map((pool) => (
<div
key={pool.poolAddress}
className="rounded-2xl border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/40"
>
<div className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
<div>
<div className="text-base font-semibold text-gray-900 dark:text-white">{pool.pair}</div>
<div className="mt-1 break-all text-xs text-gray-500 dark:text-gray-400">
Pool: {pool.poolAddress}
</div>
</div>
<div className="text-sm font-medium text-gray-700 dark:text-gray-300">
Reserves: {pool.reserves}
</div>
</div>
</div>
))}
</div>
</Card>
<Card title="What Integrators Need To Know">
<div className="space-y-3 text-sm leading-6 text-gray-600 dark:text-gray-400">
{routeHighlights.map((item) => (
<p key={item}>{item}</p>
))}
</div>
</Card>
</div>
<div className="mb-8">
<Card title="Explorer Access Points">
<div className="grid gap-4 md:grid-cols-2">
{publicEndpoints.map((endpoint) => (
<a
key={endpoint.href}
href={endpoint.href}
className="rounded-2xl border border-gray-200 bg-white p-5 transition hover:border-primary-400 hover:shadow-md dark:border-gray-700 dark:bg-gray-800"
>
<div className="flex items-center justify-between gap-3">
<div className="text-base font-semibold text-gray-900 dark:text-white">{endpoint.name}</div>
<span className="rounded-full bg-primary-50 px-2.5 py-1 text-xs font-semibold uppercase tracking-wide text-primary-700 dark:bg-primary-900/30 dark:text-primary-300">
{endpoint.method}
</span>
</div>
<div className="mt-3 break-all rounded-xl bg-gray-50 p-3 text-xs text-gray-700 dark:bg-gray-900 dark:text-gray-300">
{endpoint.href}
</div>
<div className="mt-3 text-sm leading-6 text-gray-600 dark:text-gray-400">{endpoint.notes}</div>
</a>
))}
</div>
</Card>
</div>
<div className="mb-8 grid gap-6 lg:grid-cols-[1fr_1fr]">
<Card title="Quick Request Examples">
<div className="space-y-4">
{requestExamples.map((example) => (
<div key={example.title} className="rounded-2xl border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/40">
<div className="mb-2 text-sm font-semibold text-gray-900 dark:text-white">{example.title}</div>
<code className="block break-all text-xs leading-6 text-gray-700 dark:text-gray-300">
{example.code}
</code>
</div>
))}
</div>
</Card>
<Card title="Related Explorer Tools">
<div className="space-y-4 text-sm leading-6 text-gray-600 dark:text-gray-400">
<p>
Use the wallet page for network onboarding and the explorer token list URL, then use this
page for route and execution discovery.
</p>
<p>
The route APIs complement the existing route decision tree and market-data APIs already
proxied through the explorer.
</p>
<div className="flex flex-wrap gap-3">
<Link
href="/wallet"
className="rounded-full bg-primary-600 px-4 py-2 text-sm font-medium text-white transition hover:bg-primary-700"
>
Open wallet tools
</Link>
<a
href={`${publicApiBase}/routes/tree?chainId=138&amountIn=1000000`}
className="rounded-full border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 transition hover:border-primary-400 hover:text-primary-700 dark:border-gray-600 dark:text-gray-300 dark:hover:text-primary-300"
>
Route tree API
</a>
<a
href="/docs.html"
className="rounded-full border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 transition hover:border-primary-400 hover:text-primary-700 dark:border-gray-600 dark:text-gray-300 dark:hover:text-primary-300"
>
Explorer docs
</a>
</div>
</div>
</Card>
</div>
</main>
)
}

View File

@@ -1,7 +1,7 @@
'use client'
import { useCallback, useEffect, useState } from 'react'
import { Card } from '@/libs/frontend-ui-primitives'
import { Card } from '@/libs/frontend-ui-primitives/Card'
import Link from 'next/link'
import { blocksApi } from '@/services/api/blocks'
@@ -93,12 +93,37 @@ export default function Home() {
</div>
))}
</div>
<div className="mt-4">
<div className="mt-4">
<Link href="/blocks" className="text-primary-600 hover:underline">
View all blocks
</Link>
</div>
</Card>
<div className="mt-8 grid grid-cols-1 gap-4 lg:grid-cols-2">
<Card title="Liquidity & Routes">
<p className="text-sm leading-6 text-gray-600 dark:text-gray-400">
Explore the public Chain 138 DODO PMM liquidity mesh, the canonical route matrix, and the
partner payload endpoints exposed through the explorer.
</p>
<div className="mt-4">
<Link href="/liquidity" className="text-primary-600 hover:underline">
Open liquidity access
</Link>
</div>
</Card>
<Card title="Wallet & Token Discovery">
<p className="text-sm leading-6 text-gray-600 dark:text-gray-400">
Add Chain 138, Ethereum Mainnet, and ALL Mainnet to MetaMask, then use the explorer token
list URL so supported tokens appear automatically.
</p>
<div className="mt-4">
<Link href="/wallet" className="text-primary-600 hover:underline">
Open wallet tools
</Link>
</div>
</Card>
</div>
</main>
)
}

View File

@@ -1,4 +1,5 @@
import { AddToMetaMask } from '@/components/wallet/AddToMetaMask'
import Link from 'next/link'
export default function WalletPage() {
return (
@@ -8,6 +9,13 @@ export default function WalletPage() {
Connect Chain 138 (DeFi Oracle Meta Mainnet) and Ethereum Mainnet to MetaMask and other Web3 wallets. Use the token list URL so tokens and oracles are discoverable.
</p>
<AddToMetaMask />
<div className="mt-6 rounded-lg border border-gray-200 bg-white p-4 text-sm text-gray-600 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400">
Need swap and liquidity discovery too? Visit the{' '}
<Link href="/liquidity" className="font-medium text-primary-600 hover:underline dark:text-primary-400">
Liquidity Access
</Link>{' '}
page for live Chain 138 pools, route matrix links, partner payload templates, and the internal fallback execution plan endpoints.
</div>
</main>
)
}

View File

@@ -0,0 +1,65 @@
const footerLinkClass =
'text-gray-600 dark:text-gray-400 hover:text-primary-600 dark:hover:text-primary-400 transition-colors'
export default function Footer() {
const year = new Date().getFullYear()
return (
<footer className="mt-auto border-t border-gray-200 dark:border-gray-700 bg-white/90 dark:bg-gray-900/90 backdrop-blur">
<div className="container mx-auto px-4 py-8">
<div className="grid gap-6 md:grid-cols-[1.5fr_1fr_1fr]">
<div className="space-y-3">
<div className="text-lg font-semibold text-gray-900 dark:text-white">
SolaceScanScout
</div>
<p className="max-w-xl text-sm leading-6 text-gray-600 dark:text-gray-400">
Built from Blockscout foundations and Solace Bank Group PLC frontend
work. Explorer data is powered by Blockscout, Chain 138 RPC, and the
companion MetaMask Snap.
</p>
<p className="text-xs text-gray-500 dark:text-gray-500">
© {year} Solace Bank Group PLC. All rights reserved.
</p>
</div>
<div>
<div className="mb-3 text-sm font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">
Resources
</div>
<ul className="space-y-2 text-sm">
<li><a className={footerLinkClass} href="/docs.html">Documentation</a></li>
<li><a className={footerLinkClass} href="/liquidity">Liquidity Access</a></li>
<li><a className={footerLinkClass} href="/privacy.html">Privacy Policy</a></li>
<li><a className={footerLinkClass} href="/terms.html">Terms of Service</a></li>
<li><a className={footerLinkClass} href="/acknowledgments.html">Acknowledgments</a></li>
</ul>
</div>
<div>
<div className="mb-3 text-sm font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">
Contact
</div>
<div className="space-y-2 text-sm text-gray-600 dark:text-gray-400">
<p>
Support:{' '}
<a className={footerLinkClass} href="mailto:support@d-bis.org">
support@d-bis.org
</a>
</p>
<p>
Snap site:{' '}
<a className={footerLinkClass} href="https://explorer.d-bis.org/snap/">
explorer.d-bis.org/snap/
</a>
</p>
<p className="text-xs leading-5 text-gray-500 dark:text-gray-500">
Questions about the explorer, chain metadata, route discovery, or liquidity access
can be sent to the support mailbox above.
</p>
</div>
</div>
</div>
</div>
</footer>
)
}

View File

@@ -91,9 +91,21 @@ export default function Navbar() {
<div className="container mx-auto px-4">
<div className="flex items-center justify-between h-16">
<div className="flex items-center gap-4 md:gap-8">
<Link href="/" className="text-xl font-bold text-primary-600 dark:text-primary-400 flex flex-col" onClick={() => setMobileMenuOpen(false)}>
<span>SolaceScanScout</span>
<span className="text-xs font-normal text-gray-500 dark:text-gray-400">The Defi Oracle Meta Explorer</span>
<Link
href="/"
className="group inline-flex flex-col rounded-xl px-3 py-2 text-xl font-bold text-primary-600 transition-colors hover:bg-primary-50 dark:text-primary-400 dark:hover:bg-gray-700/70"
onClick={() => setMobileMenuOpen(false)}
aria-label="Go to explorer home"
>
<span className="flex items-center gap-2">
<span className="inline-flex h-8 w-8 items-center justify-center rounded-lg bg-primary-600 text-white shadow-sm transition-transform group-hover:-translate-y-0.5 dark:bg-primary-500">
<svg className="h-4 w-4" viewBox="0 0 24 24" fill="currentColor" aria-hidden>
<path d="M12 2.5 3.5 6.5v11l8.5 4 8.5-4v-11L12 2.5Zm0 2.24 6.44 3.03L12 10.8 5.56 7.77 12 4.74Zm-7 4.63L11 13.1v6.07L5 16.4V9.37Zm9 9.8v-6.07l6-2.92v6.03l-6 2.96Z" />
</svg>
</span>
<span>SolaceScanScout</span>
</span>
<span className="mt-0.5 text-xs font-normal text-gray-500 transition-colors group-hover:text-gray-700 dark:text-gray-400 dark:group-hover:text-gray-200">The Defi Oracle Meta Explorer</span>
</Link>
<div className="hidden md:flex items-center gap-1">
<NavDropdown
@@ -110,6 +122,7 @@ export default function Navbar() {
>
<DropdownItem href="/search">Search</DropdownItem>
<DropdownItem href="/wallet">Wallet</DropdownItem>
<DropdownItem href="/liquidity">Liquidity</DropdownItem>
</NavDropdown>
</div>
</div>
@@ -154,6 +167,7 @@ export default function Navbar() {
<ul className="pl-4 mt-1 space-y-0.5">
<li><Link href="/search" className={`block px-3 py-2 rounded-md ${navLink}`} onClick={() => setMobileMenuOpen(false)}>Search</Link></li>
<li><Link href="/wallet" className={`block px-3 py-2 rounded-md ${navLink}`} onClick={() => setMobileMenuOpen(false)}>Wallet</Link></li>
<li><Link href="/liquidity" className={`block px-3 py-2 rounded-md ${navLink}`} onClick={() => setMobileMenuOpen(false)}>Liquidity</Link></li>
</ul>
)}
</div>