From 1694e93a209c815abedcf5d8f34c90f6d2000f15 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Mon, 16 Mar 2026 16:29:48 +0000 Subject: [PATCH] [#196] Post-creation buttons: View your story + Go home MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - usePublish now exposes transaction receipt for callers to decode - Create page decodes StorylineCreated event to get new storyline ID - Success buttons: "View your story" → /story/[id], "Go home" → / - Replaces old "Discover" + "Create another" buttons Fixes #196 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/create/page.tsx | 46 ++++++++++++++++++++++++++++++++--------- src/hooks/usePublish.ts | 10 ++++++--- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/app/create/page.tsx b/src/app/create/page.tsx index 3e1c1554..66b251b1 100644 --- a/src/app/create/page.tsx +++ b/src/app/create/page.tsx @@ -8,11 +8,17 @@ import { MAX_CONTENT_LENGTH, } from "../../../lib/content"; import { usePublish, type PublishState } from "../../hooks/usePublish"; -import { storyFactoryAbi } from "../../../lib/contracts/abi"; +import { storyFactoryAbi, storylineCreatedEvent } from "../../../lib/contracts/abi"; import { STORY_FACTORY } from "../../../lib/contracts/constants"; +import { decodeEventLog, encodeEventTopics } from "viem"; import Link from "next/link"; import { ConnectWallet } from "../../components/ConnectWallet"; +const STORYLINE_CREATED_TOPIC = encodeEventTopics({ + abi: [storylineCreatedEvent], + eventName: "StorylineCreated", +})[0]; + const STATE_LABELS: Record = { idle: "", uploading: "Uploading to IPFS...", @@ -29,7 +35,7 @@ export default function CreateStorylinePage() { const [content, setContent] = useState(""); const hasDeadline = true; // mandatory 7-day deadline for all storylines - const { state, error, execute, reset } = usePublish(); + const { state, error, receipt, execute, reset } = usePublish(); const { valid, charCount } = validateContentLength(content); const titleValid = title.trim().length > 0; const canSubmit = @@ -49,22 +55,42 @@ export default function CreateStorylinePage() { } if (state === "published") { + // Decode storylineId from receipt logs + let newStorylineId: number | null = null; + if (receipt) { + const log = receipt.logs.find((l) => l.topics[0] === STORYLINE_CREATED_TOPIC); + if (log) { + try { + const decoded = decodeEventLog({ + abi: storyFactoryAbi, + data: log.data, + topics: log.topics, + }); + if (decoded.eventName === "StorylineCreated") { + newStorylineId = Number(decoded.args.storylineId); + } + } catch { /* ignore decode errors */ } + } + } + return (

Storyline created!

+ {newStorylineId != null && ( + + View your story + + )} - Discover + Go home -
); diff --git a/src/hooks/usePublish.ts b/src/hooks/usePublish.ts index 003dea2c..955efcdf 100644 --- a/src/hooks/usePublish.ts +++ b/src/hooks/usePublish.ts @@ -4,7 +4,7 @@ import { useState, useCallback, useRef } from "react"; import { useWriteContract } from "wagmi"; import { hashContent } from "../../lib/content"; import { publicClient } from "../../lib/rpc"; -import type { Hex, Abi } from "viem"; +import type { Hex, Abi, TransactionReceipt } from "viem"; export type PublishState = | "idle" @@ -39,6 +39,7 @@ export function usePublish() { const [state, setState] = useState("idle"); const [error, setError] = useState(null); const [txHash, setTxHash] = useState(undefined); + const [receipt, setReceipt] = useState(undefined); const cachedCid = useRef<{ cid: string; contentHash: string } | null>(null); const { writeContractAsync } = useWriteContract(); @@ -81,7 +82,9 @@ export function usePublish() { // 3. Wait for tx confirmation setState("pending"); - await publicClient.waitForTransactionReceipt({ hash }); + const receipt = await publicClient.waitForTransactionReceipt({ hash }); + + setReceipt(receipt); // 4. Trigger indexer setState("indexing"); @@ -108,8 +111,9 @@ export function usePublish() { setState("idle"); setError(null); setTxHash(undefined); + setReceipt(undefined); cachedCid.current = null; }, []); - return { state, error, txHash, execute, reset }; + return { state, error, txHash, receipt, execute, reset }; }