Skip to main content

Overview

TUNA provides two hooks for comment management:
  • useArticleComments - Fetch comments for a specific article
  • usePostComment - Post a new comment to an article

useArticleComments

Fetch all comments for a specific news article from the Sui blockchain.

Function Signature

function useArticleComments(blobId: string): UseQueryResult<Comment[], Error>

Parameters

blobId
string
required
The Walrus blob ID of the article to fetch comments for

Return Type

data
Comment[]
Array of comments sorted by timestamp (newest first)
id
string
Unique comment object ID on Sui
blobId
string
The article’s blob ID this comment belongs to
author
string
Sui address of the comment author
text
string
Comment text content
timestamp
number
Unix timestamp when the comment was posted
tipsReceived
number
Total tips received by this comment in SUI tokens
isLoading
boolean
Whether the query is currently loading
error
Error | null
Error object if the query failed

Usage

import { useArticleComments } from '@tuna/sdk';

function CommentList({ articleBlobId }: { articleBlobId: string }) {
  const { data: comments, isLoading, error } = useArticleComments(articleBlobId);

  if (isLoading) return <div>Loading comments...</div>;
  if (error) return <div>Failed to load comments</div>;
  if (!comments?.length) return <div>No comments yet</div>;

  return (
    <div>
      <h3>{comments.length} Comments</h3>
      {comments.map((comment) => (
        <div key={comment.id}>
          <p>{comment.text}</p>
          <small>
            By {comment.author.slice(0, 6)}...{comment.author.slice(-4)}
          </small>
          <small>💰 {comment.tipsReceived} SUI</small>
        </div>
      ))}
    </div>
  );
}

Query Configuration

  • Query Key: ['comments', blobId]
  • Stale Time: 0 (always refetch)
  • Refetch on Window Focus: Enabled
  • Enabled: Only when blobId is provided
Comments are automatically refetched when the window regains focus to ensure you see the latest discussions.

usePostComment

Post a new comment to an article. Requires a connected Sui wallet.

Function Signature

function usePostComment(): UseMutationResult<void, Error, { blobId: string, text: string }>

Parameters

This hook returns a mutation object. Call the mutate function with:
blobId
string
required
The Walrus blob ID of the article to comment on
text
string
required
The comment text content

Return Type

mutate
(variables: { blobId: string, text: string }) => void
Function to trigger the comment post transaction
mutateAsync
(variables: { blobId: string, text: string }) => Promise<void>
Async version of mutate that returns a Promise
isPending
boolean
Whether the mutation is currently in progress
isSuccess
boolean
Whether the mutation completed successfully
isError
boolean
Whether the mutation encountered an error
error
Error | null
Error object if the mutation failed

Usage

import { usePostComment } from '@tuna/sdk';
import { useState } from 'react';

function CommentForm({ articleBlobId }: { articleBlobId: string }) {
  const [text, setText] = useState('');
  const { mutate, isPending, isError } = usePostComment();

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    mutate(
      { blobId: articleBlobId, text },
      {
        onSuccess: () => {
          setText(''); // Clear form
          alert('Comment posted!');
        }
      }
    );
  };

  return (
    <form onSubmit={handleSubmit}>
      <textarea
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Write a comment..."
        disabled={isPending}
      />
      <button type="submit" disabled={isPending || !text.trim()}>
        {isPending ? 'Posting...' : 'Post Comment'}
      </button>
      {isError && <p>Failed to post comment. Please try again.</p>}
    </form>
  );
}

Automatic Cache Updates

When a comment is successfully posted, the hook automatically:
  1. Invalidates the comments query for that article
  2. Invalidates the article query to update comment count
  3. Waits 2 seconds for blockchain indexing before refetching
// This happens automatically - no action needed
onSuccess: (_, variables) => {
  queryClient.invalidateQueries({ queryKey: ['comments', variables.blobId] });
  queryClient.invalidateQueries({ queryKey: ['article', variables.blobId] });
}
A connected Sui wallet is required to post comments. The hook will throw an error if no wallet is connected.

Error Handling

import { useCurrentAccount } from '@mysten/dapp-kit';
import { usePostComment } from '@tuna/sdk';

function CommentSection({ blobId }: { blobId: string }) {
  const account = useCurrentAccount();
  const { mutate } = usePostComment();

  if (!account) {
    return <div>Please connect your wallet to comment</div>;
  }

  return (
    <button onClick={() => mutate({ blobId, text: 'Great article!' })}>
      Post Comment
    </button>
  );
}

See Also

Build docs developers (and LLMs) love