Skip to content
Draft
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
5 changes: 5 additions & 0 deletions apps/developer-hub/src/app/price-feeds/core/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { CoreLandingPage } from "../../../components/Pages/CoreLandingPage";

export default function Page() {
return <CoreLandingPage />;
}
193 changes: 193 additions & 0 deletions apps/developer-hub/src/components/Core/architecture-tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
"use client";

import { ArrowRight as ArrowRightIcon } from "@phosphor-icons/react/dist/ssr";
import { Button } from "@pythnetwork/component-library/Button";
import { TabList } from "@pythnetwork/component-library/TabList";
import { Tabs as UnstyledTabs } from "@pythnetwork/component-library/unstyled/Tabs";
import { useState } from "react";

type TabId = "pull" | "pusher" | "historical";

export function ArchitectureTabs() {
const [activeTab, setActiveTab] = useState<TabId>("pull");

function renderDiagram() {
if (activeTab === "historical") {
return (
<div className="flex items-center justify-center gap-6 p-6">
<div className="text-center">
<div className="text-4xl mb-2">📊</div>
<div className="text-gray-700 dark:text-gray-300">
Historical Data
</div>
</div>
</div>
);
}

const nodes =
activeTab === "pull"
? ["Publishers", "Pythnet", "User", "Your Contract"]
: ["Publishers", "Pythnet", "Price Pusher", "Your Contract"];

return (
<div className="w-full overflow-x-auto">
<svg
role="img"
aria-label="Data flow diagram"
className="w-full max-w-2xl mx-auto"
height="160"
viewBox="0 0 800 160"
>
{nodes.map((label, i) => {
const x = 80 + i * 240;
return (
<g key={label}>
<rect
x={x - 70}
y={40}
width={140}
height={56}
rx={12}
className="fill-white dark:fill-[#0B0F1A] stroke-gray-200 dark:stroke-gray-700"
strokeWidth={1}
/>
<text
x={x}
y={72}
textAnchor="middle"
className="fill-gray-900 dark:fill-white"
fontSize="14"
>
{label}
</text>
</g>
);
})}
{[0, 1, 2].map((i) => {
const x1 = 80 + i * 240 + 70;
const x2 = 80 + (i + 1) * 240 - 70;
const points = `${String(x2 - 10)},63 ${String(x2 - 10)},73 ${String(x2)},68`;
return (
<g key={i}>
<line
x1={x1}
y1={68}
x2={x2}
y2={68}
className="stroke-blue-500"
strokeWidth={2}
/>
<polygon points={points} className="fill-blue-500" />
</g>
);
})}
</svg>
</div>
);
}

function renderContent() {
if (activeTab === "pull")
return (
<div className="space-y-4">
<p className="text-gray-700 dark:text-gray-300">
Publishers stream signed updates to Pythnet roughly every 400 ms.
Your app pulls and verifies prices on demand, then your contract
updates via <code className="font-mono">updatePriceFeeds</code>.
</p>
<Button
isDisabled
className="inline-flex items-center gap-2 px-4 py-2"
>
Read Pull Integration Guide
<ArrowRightIcon size={18} />
</Button>
</div>
);

if (activeTab === "pusher")
return (
<div className="space-y-4">
<p className="text-gray-700 dark:text-gray-300">
Automate on-chain updates using a Price Pusher. It listens to
Pythnet and pushes fresh prices to your contracts on your chosen
schedule and conditions.
</p>
<Button
isDisabled
className="inline-flex items-center gap-2 px-4 py-2"
>
Deploy a Price Pusher
<ArrowRightIcon size={18} />
</Button>
</div>
);

if (activeTab === "historical")
return (
<div className="space-y-4">
<p className="text-gray-700 dark:text-gray-300">
Explore cryptographically verifiable historical prices for auditing,
analytics, and backtesting.
</p>
<Button
isDisabled
className="inline-flex items-center gap-2 px-4 py-2"
>
Explore Historical Prices
<ArrowRightIcon size={18} />
</Button>
</div>
);

return null;
}

const items = [
{
id: "pull",
href: "#pull",
children: "Pull",
onPress: () => {
setActiveTab("pull");
},
},
{
id: "pusher",
href: "#pusher",
children: "Price Pusher",
onPress: () => {
setActiveTab("pusher");
},
},
{
id: "historical",
href: "#historical",
children: "Historical",
onPress: () => {
setActiveTab("historical");
},
},
];

return (
<div>
<UnstyledTabs selectedKey={activeTab}>
<TabList
label="Architecture"
currentTab={activeTab}
items={items}
className="flex gap-2 border-b border-gray-200 dark:border-gray-800"
/>
</UnstyledTabs>

<div className="pt-8 space-y-6">
<div className="rounded-lg border border-gray-200 dark:border-gray-800 p-4 bg-white dark:bg-[#0B0F1A]">
{renderDiagram()}
</div>
<div>{renderContent()}</div>
</div>
</div>
);
}
159 changes: 159 additions & 0 deletions apps/developer-hub/src/components/Pages/CoreLandingPage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
"use client";

import { ArrowRight as ArrowRightIcon } from "@phosphor-icons/react/dist/ssr";
import { Button } from "@pythnetwork/component-library/Button";

import { ArchitectureTabs } from "../../Core/architecture-tabs";

export function CoreLandingPage() {
return (
<div className="min-h-screen">
<section>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
<div className="text-center">
<h1 className="text-4xl sm:text-5xl font-extrabold tracking-tight text-gray-900 dark:text-white">
Real-Time Market Data, On-Chain
</h1>
<p className="mt-6 text-lg sm:text-xl text-gray-700 dark:text-gray-300 max-w-3xl mx-auto">
Pyth Core delivers sub-second, signed prices across 100+
blockchains. Fetch live data, automate updates using Price Pusher,
and parse historical prices—all from one oracle network.
</p>

<div className="mt-10 flex flex-col sm:flex-row items-center justify-center gap-4">
<Button
isDisabled
className="inline-flex items-center gap-2 px-5 py-3"
>
Get started by pulling prices
<ArrowRightIcon size={18} />
</Button>
<Button
isDisabled
className="inline-flex items-center gap-2 px-5 py-3 border border-gray-300 dark:border-gray-700 bg-transparent text-gray-900 dark:text-white hover:bg-gray-50 dark:hover:bg-white/5"
>
Set up a Price Pusher
</Button>
</div>
</div>
</div>
</section>

<section className="bg-white dark:bg-darkGray">
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<h2 className="sr-only">What is Pyth Core?</h2>
<p className="text-lg text-gray-700 dark:text-gray-300 leading-relaxed">
Pyth Core provides high-frequency, cryptographically signed price
feeds that you can verify on-chain. Publishers stream updates to
Pythnet roughly every 400 ms. Your dApp pulls and verifies prices
whenever you need them.
</p>
</div>
</section>

<section className="bg-gray-50 dark:bg-[#0B0F1A]">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-8 text-center">
Integration Styles
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<div className="p-6 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-[#0B0F1A]">
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-3">
Pull Oracle
</h3>
<p className="text-gray-700 dark:text-gray-300 mb-4">
The default approach: your dApp fetches and verifies prices
on-demand whenever needed.
</p>
<button
type="button"
onClick={() =>
document
.querySelector("#architecture-section")
?.scrollIntoView({ behavior: "smooth" })
}
className="text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 font-medium"
>
Learn More →
</button>
</div>
<div className="p-6 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-[#0B0F1A]">
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-3">
Sponsored Updates
</h3>
<p className="text-gray-700 dark:text-gray-300 mb-4">
Automate price updates using a Price Pusher for push-like
functionality with your own gas sponsorship.
</p>
<button
type="button"
onClick={() =>
document
.querySelector("#architecture-section")
?.scrollIntoView({ behavior: "smooth" })
}
className="text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 font-medium"
>
Learn More →
</button>
</div>
</div>
</div>
</section>

<section
id="architecture-section"
className="bg-gray-50 dark:bg-[#0B0F1A]"
>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-6">
How it works
</h2>
<ArchitectureTabs />
</div>
</section>

<section className="bg-white dark:bg-darkGray">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-8">
Why Pyth Core
</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
<div className="p-6 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-[#0B0F1A]">
<h3 className="font-semibold text-gray-900 dark:text-white mb-2">
Sub-second Data
</h3>
<p className="text-sm text-gray-700 dark:text-gray-300">
Get signed prices refreshed every ~400 ms.
</p>
</div>
<div className="p-6 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-[#0B0F1A]">
<h3 className="font-semibold text-gray-900 dark:text-white mb-2">
Verifiable
</h3>
<p className="text-sm text-gray-700 dark:text-gray-300">
On-chain signature verification for trustless data.
</p>
</div>
<div className="p-6 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-[#0B0F1A]">
<h3 className="font-semibold text-gray-900 dark:text-white mb-2">
Flexible Integration
</h3>
<p className="text-sm text-gray-700 dark:text-gray-300">
Pull on demand or automate with a Price Pusher.
</p>
</div>
<div className="p-6 rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-[#0B0F1A]">
<h3 className="font-semibold text-gray-900 dark:text-white mb-2">
Historical Archive
</h3>
<p className="text-sm text-gray-700 dark:text-gray-300">
Audit and backtest with cryptographically secure history.
</p>
</div>
</div>
</div>
</section>
</div>
);
}
Loading