Skip to content
Merged
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
14 changes: 11 additions & 3 deletions src/app/dashboard/reader/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { formatUnits } from "viem";
import { ConnectWallet } from "../../../components/ConnectWallet";
import { RESERVE_LABEL, PLOT_TOKEN, STORY_FACTORY, EXPLORER_URL } from "../../../../lib/contracts/constants";
import { browserClient as publicClient } from "../../../../lib/rpc";
import { formatUsdValue } from "../../../../lib/usd-price";
import { usePlotUsdPrice } from "../../../hooks/usePlotUsdPrice";
import { type Address } from "viem";

/** Truncate formatUnits output to at most `digits` decimal places */
Expand All @@ -25,6 +27,7 @@ const PAGE_SIZE = 10;

export default function ReaderDashboard() {
const { address, isConnected } = useAccount();
const { data: plotUsd } = usePlotUsdPrice();

const {
data,
Expand Down Expand Up @@ -97,10 +100,10 @@ export default function ReaderDashboard() {
<WriterIdentityClient address={address!} />
</p>

<ReaderPortfolio />
<ReaderPortfolio plotUsd={plotUsd} />

{/* --- Trading History --- */}
<TradingHistory address={address!} />
<TradingHistory address={address!} plotUsd={plotUsd} />

{/* --- Donation History --- */}
<section className="mt-8">
Expand Down Expand Up @@ -188,7 +191,7 @@ function DonationRow({ donation, decimals }: { donation: Donation; decimals: num

const TRADE_PAGE_SIZE = 10;

function TradingHistory({ address }: { address: string }) {
function TradingHistory({ address, plotUsd }: { address: string; plotUsd?: number | null }) {
const {
data,
isLoading,
Expand Down Expand Up @@ -287,6 +290,11 @@ function TradingHistory({ address }: { address: string }) {
<div className="flex shrink-0 items-center gap-2">
<span className="text-foreground font-medium">
{formatPrice(t.reserve_amount)} {RESERVE_LABEL}
{plotUsd && (
<span className="text-muted ml-1 text-[10px] font-normal">
(≈ {formatUsdValue(t.reserve_amount * plotUsd)})
</span>
)}
</span>
{t.tx_hash && (
<a
Expand Down
9 changes: 6 additions & 3 deletions src/app/dashboard/writer/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { truncateAddress } from "../../../../lib/utils";
import { formatPrice } from "../../../../lib/format";
import Link from "next/link";
import { ConnectWallet } from "../../../components/ConnectWallet";
import { usePlotUsdPrice } from "../../../hooks/usePlotUsdPrice";
import { type Address } from "viem";

function formatViewCountDashboard(n: number): string {
Expand Down Expand Up @@ -51,6 +52,7 @@ const languageOptions = LANGUAGES.map((l) => ({ value: l, label: l }));

export default function WriterDashboard() {
const { address, isConnected } = useAccount();
const { data: plotUsd } = usePlotUsdPrice();

const { data: storylines = [], isLoading, error } = useQuery({
queryKey: ["writer-storylines", address],
Expand Down Expand Up @@ -91,7 +93,7 @@ export default function WriterDashboard() {

<div className="mt-8 space-y-4">
{storylines.map((s) => (
<StorylineDetail key={s.id} storyline={s} writerAddress={address!} />
<StorylineDetail key={s.id} storyline={s} writerAddress={address!} plotUsd={plotUsd} />
))}
{!isLoading && !error && storylines.length === 0 && (
<p className="text-muted py-8 text-center text-sm">
Expand All @@ -103,7 +105,7 @@ export default function WriterDashboard() {
);
}

function StorylineDetail({ storyline, writerAddress }: { storyline: Storyline; writerAddress: Address }) {
function StorylineDetail({ storyline, writerAddress, plotUsd }: { storyline: Storyline; writerAddress: Address; plotUsd?: number | null }) {
return (
<div className="border-border rounded border px-4 py-4">
<div className="flex items-start justify-between gap-3">
Expand Down Expand Up @@ -172,11 +174,12 @@ function StorylineDetail({ storyline, writerAddress }: { storyline: Storyline; w

{storyline.token_address && (
<div className="mt-3 space-y-2">
<WriterTradingStats storyline={storyline} />
<WriterTradingStats storyline={storyline} plotUsd={plotUsd} />
<ClaimRoyalties
tokenAddress={storyline.token_address as Address}
plotCount={storyline.plot_count}
beneficiary={writerAddress}
plotUsd={plotUsd}
/>
</div>
)}
Expand Down
9 changes: 8 additions & 1 deletion src/components/ClaimRoyalties.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { formatUnits, type Address } from "viem";
import { browserClient } from "../../lib/rpc";
import { mcv2BondAbi, getTokenTVL } from "../../lib/price";
import { MCV2_BOND, RESERVE_LABEL, EXPLORER_URL, PLOT_TOKEN } from "../../lib/contracts/constants";
import { formatUsdValue } from "../../lib/usd-price";

function formatTruncated(value: bigint, decimals: number, digits = 10): string {
const raw = formatUnits(value, decimals);
Expand All @@ -22,9 +23,10 @@ interface ClaimRoyaltiesProps {
tokenAddress: Address;
plotCount: number;
beneficiary: Address;
plotUsd?: number | null;
}

export function ClaimRoyalties({ tokenAddress, plotCount, beneficiary }: ClaimRoyaltiesProps) {
export function ClaimRoyalties({ tokenAddress, plotCount, beneficiary, plotUsd }: ClaimRoyaltiesProps) {
const [txState, setTxState] = useState<TxState>("idle");
const [error, setError] = useState<string | null>(null);
const [claimedAmount, setClaimedAmount] = useState<bigint>(BigInt(0));
Expand Down Expand Up @@ -146,6 +148,11 @@ export function ClaimRoyalties({ tokenAddress, plotCount, beneficiary }: ClaimRo
<span className={`ml-1 font-medium ${unclaimed > BigInt(0) ? "text-accent" : "text-foreground"}`}>
{formatTruncated(unclaimed, decimals)} {RESERVE_LABEL}
</span>
{unclaimed > BigInt(0) && plotUsd && (
<span className="text-muted ml-1 text-[10px]">
(≈ {formatUsdValue(parseFloat(formatUnits(unclaimed, decimals)) * plotUsd)})
</span>
)}
{totalClaimed > BigInt(0) && (
<span className="text-muted ml-1 text-[10px]">
(claimed: {formatTruncated(totalClaimed, decimals)} {RESERVE_LABEL} so far)
Expand Down
13 changes: 12 additions & 1 deletion src/components/ReaderPortfolio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { erc20Abi, mcv2BondAbi, get24hPriceChange, getTokenTVL } from "../../lib
import { MCV2_BOND, RESERVE_LABEL, STORY_FACTORY } from "../../lib/contracts/constants";
import { supabase, type Storyline } from "../../lib/supabase";
import Link from "next/link";
import { formatUsdValue } from "../../lib/usd-price";

interface Holding {
storyline: Storyline;
Expand All @@ -19,7 +20,7 @@ interface Holding {
reserveDecimals: number;
}

export function ReaderPortfolio() {
export function ReaderPortfolio({ plotUsd }: { plotUsd?: number | null }) {
const { address, isConnected } = useAccount();
const { data: holdings, isLoading } = useQuery({
queryKey: ["reader-portfolio", address],
Expand Down Expand Up @@ -128,6 +129,11 @@ export function ReaderPortfolio() {
<span className="text-accent text-sm font-medium">
{formatPrice(formatUnits(totalValue, reserveDecimals))} {RESERVE_LABEL}
</span>
{plotUsd && (
<span className="text-muted ml-1 text-[10px]">
(≈ {formatUsdValue(parseFloat(formatUnits(totalValue, reserveDecimals)) * plotUsd)})
</span>
)}
</div>
{bestPick && bestPick.priceChange !== null && (
<div>
Expand Down Expand Up @@ -166,6 +172,11 @@ export function ReaderPortfolio() {
<div className="text-right">
<div className="text-foreground">
{formatPrice(formatUnits(h.value, h.reserveDecimals))} {RESERVE_LABEL}
{plotUsd && (
<span className="text-muted ml-1 text-[10px]">
(≈ {formatUsdValue(parseFloat(formatUnits(h.value, h.reserveDecimals)) * plotUsd)})
</span>
)}
</div>
{h.priceChange !== null && (
<div
Expand Down
14 changes: 13 additions & 1 deletion src/components/WriterTradingStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import { browserClient } from "../../lib/rpc";
import { mcv2BondAbi, getTokenTVL } from "../../lib/price";
import { MCV2_BOND, RESERVE_LABEL } from "../../lib/contracts/constants";
import { formatPrice } from "../../lib/format";
import { formatUsdValue } from "../../lib/usd-price";
import type { Storyline } from "../../lib/supabase";

interface WriterTradingStatsProps {
storyline: Storyline;
plotUsd?: number | null;
}

export function WriterTradingStats({ storyline }: WriterTradingStatsProps) {
export function WriterTradingStats({ storyline, plotUsd }: WriterTradingStatsProps) {
const tokenAddress = storyline.token_address as Address;

// Fetch price + TVL together so they succeed/fail atomically
Expand Down Expand Up @@ -49,6 +51,11 @@ export function WriterTradingStats({ storyline }: WriterTradingStatsProps) {
<span className="font-semibold text-accent">
{data ? `${formatPrice(data.price)} ${RESERVE_LABEL}` : "—"}
</span>
{data && plotUsd && (
<span className="text-muted ml-1 text-[10px]">
(≈ {formatUsdValue(parseFloat(data.price) * plotUsd)})
</span>
)}
</div>
<div>
<span className="block text-[10px] uppercase tracking-wider">
Expand All @@ -57,6 +64,11 @@ export function WriterTradingStats({ storyline }: WriterTradingStatsProps) {
<span className="font-semibold text-accent">
{data ? `${formatPrice(data.tvl)} ${RESERVE_LABEL}` : "—"}
</span>
{data && plotUsd && (
<span className="text-muted ml-1 text-[10px]">
(≈ {formatUsdValue(parseFloat(data.tvl) * plotUsd)})
</span>
)}
</div>
</div>
);
Expand Down
Loading