mirror of
https://github.com/labrinyang/lp-terminal.git
synced 2026-07-28 13:47:44 +00:00
bca538e7e3
One commit because the pieces do not compile apart: the shared copy, the tab shell and the data layer all changed together, and splitting them further would mean inventing intermediate states that never existed. SHEEP CHOICE — the terminal's own swap. Quotes come from a solver that splits one trade across several pools instead of forcing it down a single path, and returns a ready-to-sign Settler transaction; the UI draws the split leg by leg and scores every venue against one shared fee-free baseline, so the card that says it pays most actually does. The Kyber transaction path is gone — Kyber is read-only USD valuation now, and there is no Kyber calldata to sign. BRIDGE — deposits from other chains over Relay, Across and the native portal, priced side by side and sorted by what actually reaches you. No fee on any of them. In-flight transfers get a countdown and survive a reload. ZAP — add liquidity holding neither side of the pair; whatever needs swapping is done in the same flow, with an optional stake-after step. Uniswap V2 liquidity now shows up under POSITIONS. Swaps in flight are persisted, so a refresh mid-swap no longer loses the transaction. Pair labels copy their token and pool addresses, and jump to DexScreener. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
import { ConnectButton } from '@rainbow-me/rainbowkit'
|
|
import { useTranslation } from 'react-i18next'
|
|
import { usePools } from '../hooks/usePools'
|
|
import { HistoryButton } from './HistoryButton'
|
|
import { LangControl } from './LangControl'
|
|
import { NewsButton } from './NewsButton'
|
|
|
|
export type TabId = 'pools' | 'positions' | 'swap' | 'bridge'
|
|
const TABS = [
|
|
{ id: 'pools', labelKey: 'hdr.pools', key: '1' },
|
|
{ id: 'positions', labelKey: 'hdr.positions', key: '2' },
|
|
{ id: 'swap', labelKey: 'hdr.swap', key: '3' },
|
|
{ id: 'bridge', labelKey: 'hdr.bridge', key: '5' },
|
|
] as const
|
|
|
|
export function Header(props: { tab: TabId; onTab: (t: TabId) => void }) {
|
|
const { t } = useTranslation()
|
|
const pools = usePools()
|
|
const p = pools.data?.protocol
|
|
|
|
return (
|
|
<div className="hdr">
|
|
{/* the wordmark contracts to "LP▮" on a phone — at full length the utility
|
|
cluster no longer fits one row, and CONNECT wraps to a second */}
|
|
<span className="brand">
|
|
LP<span className="cursor">▮</span>
|
|
<span className="hide-m">TERMINAL</span>
|
|
</span>
|
|
<div className="tabs">
|
|
{TABS.map((tb) => (
|
|
<button
|
|
key={tb.id}
|
|
className={`tab ${props.tab === tb.id ? 'active' : ''}`}
|
|
onClick={() => props.onTab(tb.id)}
|
|
>
|
|
<span className="key">[{tb.key}]</span>
|
|
{t(tb.labelKey)}
|
|
</button>
|
|
))}
|
|
</div>
|
|
{p && (
|
|
<span className="hdr-meta">
|
|
{t('hdr.blk')} <b>{p.blockNumber.toString()}</b>
|
|
</span>
|
|
)}
|
|
<HistoryButton />
|
|
<NewsButton />
|
|
<LangControl />
|
|
<ConnectButton.Custom>
|
|
{({ account, chain, openAccountModal, openChainModal, openConnectModal, mounted }) => {
|
|
if (!mounted) return <button className="btn ghost">…</button>
|
|
if (!account)
|
|
return (
|
|
<button className="btn" onClick={openConnectModal}>
|
|
{t('hdr.connect')}
|
|
</button>
|
|
)
|
|
if (chain?.unsupported)
|
|
return (
|
|
<button className="btn danger" onClick={openChainModal}>
|
|
{t('hdr.wrongChain')}
|
|
</button>
|
|
)
|
|
return (
|
|
<button className="btn ghost" onClick={openAccountModal}>
|
|
[{account.displayName}
|
|
<span className="hide-m">{account.displayBalance ? ` · ${account.displayBalance}` : ''}</span>]
|
|
</button>
|
|
)
|
|
}}
|
|
</ConnectButton.Custom>
|
|
</div>
|
|
)
|
|
}
|