From 9f5d17e6ef1dea11865de137c68ec591cf442487 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Mon, 16 Mar 2026 16:12:43 +0000 Subject: [PATCH] [#192] Update stale 72h refs and use dynamic decimals in ClaimRoyalties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CLI status comment: 72h → 7 days - PROPOSAL + ROADMAP docs: 72h → 7-day, optional → mandatory - ClaimRoyalties: fetch reserve token decimals via getTokenTVL instead of hardcoding 18 Fixes #192 Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/PROPOSAL-plotlink.md | 4 ++-- docs/ROADMAP.md | 6 +++--- packages/cli/src/commands/status.ts | 2 +- src/components/ClaimRoyalties.tsx | 15 +++++++++++---- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/PROPOSAL-plotlink.md b/docs/PROPOSAL-plotlink.md index 8bc09e52..55dece5f 100644 --- a/docs/PROPOSAL-plotlink.md +++ b/docs/PROPOSAL-plotlink.md @@ -76,7 +76,7 @@ Chains a new plot to an existing storyline. Access-controlled to the storyline w 1. Validates writer identity (`msg.sender == writer`) 2. Validates CID length (46–100 bytes) 3. Checks storyline is not sunset -4. Enforces 72h deadline if enabled (`block.timestamp <= lastPlotTime + 72 hours`) +4. Enforces mandatory 7-day deadline (`block.timestamp <= lastPlotTime + 168 hours`) 5. Increments `plotCount` and updates `lastPlotTime` 6. Emits `PlotChained` event @@ -122,7 +122,7 @@ struct Storyline { address token; // storyline token address on Mint Club uint256 plotCount; // total plots chained (genesis = 1) uint256 lastPlotTime; // timestamp of last plot - bool hasDeadline; // whether 72h deadline is enabled + bool hasDeadline; // mandatory 7-day deadline (always true) bool sunset; // true if deadline expired } ``` diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 49a2337c..93db9d3d 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -208,7 +208,7 @@ Safety net for when the inline indexer misses a plot. ### P2-4: StoryFactory — chainPlot() -**Context**: §4.3 — access-controlled to the storyline writer. Validates CID length (46–100 bytes), checks the storyline isn't sunset, enforces 72h deadline if enabled. Increments plotCount and lastPlotTime. Emits PlotChained event with CID + contentHash. Measured gas: 39,826 (below the ~47k estimate). +**Context**: §4.3 — access-controlled to the storyline writer. Validates CID length (46–100 bytes), checks the storyline isn't sunset, enforces mandatory 7-day deadline. Increments plotCount and lastPlotTime. Emits PlotChained event with CID + contentHash. Measured gas: 39,826 (below the ~47k estimate). **Sub-tickets**: - **P2-4a**: Implement `chainPlot()` with all validations as specified in §4.3. @@ -275,7 +275,7 @@ After gas measurements are available, update the proposal document. ### P3-2: Create Storyline Flow -**Context**: §4.1 (Write Flow) + §3.7 (Deadline). The writer fills in a title, writes the opening chapter (genesis plot), and optionally enables the 72h deadline. The publishing flow has 5 UX states defined in §4.1: uploading → confirm in wallet → publishing to Base → indexing → published. On failure, the CID should be cached locally so retries skip the IPFS upload. +**Context**: §4.1 (Write Flow) + §3.7 (Deadline). The writer fills in a title, writes the opening chapter (genesis plot), with a mandatory 7-day deadline. The publishing flow has 5 UX states defined in §4.1: uploading → confirm in wallet → publishing to Base → indexing → published. On failure, the CID should be cached locally so retries skip the IPFS upload. **Sub-tickets**: - **P3-2a**: Build the Create Storyline page/form — title input, content textarea with Unicode-aware character counter (500–10,000), hasDeadline toggle. @@ -300,7 +300,7 @@ After gas measurements are available, update the proposal document. **Sub-tickets**: - **P3-4a**: Build the story page layout — fetch storyline + all plots from Supabase, render as a continuous reading experience. Show writer address, plot count, title. -- **P3-4b**: Add deadline countdown component — if `has_deadline` is true, show remaining time until sunset based on `last_plot_time + 72h`. +- **P3-4b**: Add deadline countdown component — show remaining time until sunset based on `last_plot_time + 7 days`. - **P3-4c**: Add sunset state display — if storyline is sunset, show a "Story complete" badge with total plot count. --- diff --git a/packages/cli/src/commands/status.ts b/packages/cli/src/commands/status.ts index 62cc346c..f360bf6d 100644 --- a/packages/cli/src/commands/status.ts +++ b/packages/cli/src/commands/status.ts @@ -132,7 +132,7 @@ export function registerStatus(program: Command): void { console.log(`Last plot: ${new Date(dbRow.last_plot_time).toISOString()}`); } - // Deadline remaining (72h from last plot) + // Deadline remaining (7 days from last plot) if (dbRow.has_deadline && dbRow.last_plot_time && !dbRow.sunset) { const DEADLINE_HOURS = 168; const deadlineMs = diff --git a/src/components/ClaimRoyalties.tsx b/src/components/ClaimRoyalties.tsx index e0403d5c..729adbda 100644 --- a/src/components/ClaimRoyalties.tsx +++ b/src/components/ClaimRoyalties.tsx @@ -5,7 +5,7 @@ import { useWriteContract } from "wagmi"; import { useQuery } from "@tanstack/react-query"; import { formatUnits, type Address } from "viem"; import { publicClient } from "../../lib/rpc"; -import { mcv2BondAbi } from "../../lib/price"; +import { mcv2BondAbi, getTokenTVL } from "../../lib/price"; import { MCV2_BOND, IS_TESTNET, EXPLORER_URL } from "../../lib/contracts/constants"; type TxState = "idle" | "confirming" | "pending" | "done" | "error"; @@ -42,6 +42,13 @@ export function ClaimRoyalties({ tokenAddress, plotCount, beneficiary }: ClaimRo refetchInterval: 30000, }); + // Fetch reserve token decimals dynamically + const { data: tvlData } = useQuery({ + queryKey: ["claim-decimals", tokenAddress], + queryFn: () => getTokenTVL(tokenAddress), + }); + const decimals = tvlData?.decimals ?? 18; + const unclaimed = royaltyInfo?.unclaimed ?? BigInt(0); const eligible = plotCount >= 2; const canClaim = eligible && unclaimed > BigInt(0); @@ -107,14 +114,14 @@ export function ClaimRoyalties({ tokenAddress, plotCount, beneficiary }: ClaimRo Chain at least 2 plots ({plotCount}/2)
  • - Unclaimed > 0 ({formatUnits(unclaimed, 18)} {reserveLabel}) + Unclaimed > 0 ({formatUnits(unclaimed, decimals)} {reserveLabel})
  • )} - {formatUnits(unclaimed, 18)} {reserveLabel} + {formatUnits(unclaimed, decimals)} {reserveLabel}