> For the complete documentation index, see [llms.txt](https://sdk.sageapp.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sdk.sageapp.xyz/post-1/comment.md).

# Comment

Creating a comment will only succeed for a Sui address that has [an associated Sage user.](/user/create.md)

## Create a new Sage comment

In this case `data`, `description`, and `title` are expected to be a markdown string. This allows for formatting, creating links, and more without causing downstream security risks.

The SDK sanitizes inputs on entry, removing html tags and attributes, as well as escaping text.

```tsx
import { useSignAndExecuteTransaction } from '@mysten/dapp-kit';
import { usePost } from '@sage-app/sdk/react';

interface CommentCreateInput {
  amounts: number[];           // payment amounts set to [0, 0]
  data: string;                // markdown string input
  description: string;         // markdown string input
  parentPostId: string;        // address of parent post
  self: string;                // user's wallet address
  soulId: string;              // address of user's owned soul
  title: string;               // markdown string input
}

...

const { mutateAsync: signAndExecuteTransaction } = useSignAndExecuteTransaction();
const { comment } = usePost();

...

const createComment = async (data: CommentCreateInput) => {
  const { ok, err, transaction } = comment(data);
    
  const { digest } = await signAndExecuteTransaction({
    transaction
  });
};
```

## Error Codes

**Authentication** module

<table><thead><tr><th width="104">Code</th><th width="221">Value</th><th>Meaning</th></tr></thead><tbody><tr><td>370</td><td>ENotAuthenticated</td><td>User soul object does not exist, is the wrong type, or not owned by the wallet.</td></tr></tbody></table>

**Post Fees** module

<table><thead><tr><th width="106">Code</th><th width="231.63067626953125">Value</th><th>Meaning</th></tr></thead><tbody><tr><td>370</td><td>EIncorrectCoinType</td><td>Custom payment type does not match configured custom payment coin.</td></tr><tr><td>371</td><td>EIncorrectCustomPayment</td><td>Incorrect custom payment value.</td></tr><tr><td>372</td><td>EIncorrectSuiPayment</td><td>Incorrect sui payment value.</td></tr></tbody></table>

## Querying for New Comment Events

The query API in the SDK sanitizes input from `data`, `description`, and `title.` The contract is not able to sanitizes these values for the developer performantly so that responsibility is placed here.

**Developers must ensure for themselves that \`data\`, \`description\`, and \`title\` are safe before they are used.**

```typescript
import { EventId, SuiClient, getFullnodeUrl } from '@mysten/sui/client';
import { SageClient } from '@sage-app/sdk/client';

...

interface QueryInput {
  cursor?: EventId;
}
const appId = '<YOUR_APP_ID>';
const network = 'mainnet' | 'testnet';
const suiClient = new SuiClient({ url: getFullnodeUrl(network) });

const sageClient = new SageClient({ appId, network, suiClient });

...

const pollNewComments = async ({ cursor }) => {
  const {
    eventCount,
    events,
    hasNextPage,
    nextCursor
  } = await sageClient.queryCommentCreateEvents({ cursor }: QueryInput);
  
  // do something with events
  
  setTimeout(() => pollNewComments({ cursor: nextCursor }), 5000);
};
```

In this case events will take the shape of an array of CommentCreatedEvents:

```typescript
interface CommentCreatedEvent {
  id: string;              // post object address
  app: string;             // name of app where post was created (e.g. "sage")
  createdAt: string;
  createdBy: string;       // user's wallet address
  data: string;            // sanitized markdown string
  description: string;     // sanitized markdown string
  parentPostId: string;    // unique post key (parent)
  title: string;           // sanitized markdown string
}  
```
