> ## Documentation Index
> Fetch the complete documentation index at: https://docs.story.foundation/llms.txt
> Use this file to discover all available pages before exploring further.

# Dispute

> DisputeClient allows you to manage disputes within Story.

## DisputeClient

### Methods

* raiseDispute
* cancelDispute
* resolveDispute
* tagIfRelatedIpInfringed
* disputeAssertion
* disputeIdToAssertionId

### raiseDispute

Raises a dispute on a given ipId

| Method         | Type                                                              |
| -------------- | ----------------------------------------------------------------- |
| `raiseDispute` | `(request: RaiseDisputeRequest) => Promise<RaiseDisputeResponse>` |

Parameters:

* `request.targetIpId`: The IP ID that is the target of the dispute.
* `request.targetTag`: The target tag of the dispute. See [dispute tags](https://docs.story.foundation/docs/dispute-module#dispute-tags). **Example: "IMPROPER\_REGISTRATION"**
* `request.cid`: Content Identifier (CID) for the dispute evidence. This should be obtained by uploading your dispute evidence (documents, images, etc.) to IPFS. **Example: "QmX4zdp8VpzqvtKuEqMo6gfZPdoUx9TeHXCgzKLcFfSUbk"**
* `request.liveness`: The liveness is the time window (in seconds) in which a counter dispute can be presented (30days).
* `request.bond`: \[Optional] **If not specified, it defaults to the minimum bond value**. The amount of wrapper IP that the dispute initiator pays upfront into a pool. To counter that dispute the opposite party of the dispute has to place a bond of the same amount. The winner of the dispute gets the original bond back + 50% of the other party bond. The remaining 50% of the loser party bond goes to the reviewer.

<Note>
  UMA will be adjusting the minimum \$IP bond size as the IP price fluctuates.
  The correct way to obtain the current minimum bond size is via
  `getMinimumBond()` on `OptimisticOracleV3.sol` (OOV3), found on our [aeneid
  testnet](https://aeneid.storyscan.io/address/0xABac6a158431edED06EE6cba37eDE8779F599eE4?tab=read_write_contract#0x4360af3d)
  and
  [mainnet](https://www.storyscan.io/address/0x8EF424F90C6BC1b98153A09c0Cac5072545793e8?tab=read_write_contract#0x4360af3d).
</Note>

* `request.wipOptions`: \[Optional]
  * `request.wipOptions.enableAutoWrapIp`: \[Optional]By default IP is converted to WIP if the current WIP balance does not cover the fees. Set this to `false` to disable this behavior. **Default: true**
  * `request.wipOptions.enableAutoApprove`: \[Optional]Automatically approve WIP usage when WIP is needed but current allowance is not sufficient. Set this to `false` to disable this behavior. **Default: true**

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { parseEther } from "viem";
  import { DisputeTargetTag } from "@story-protocol/core-sdk";

  const response = await client.dispute.raiseDispute({
    targetIpId: "0xC92EC2f4c86458AFee7DD9EB5d8c57920BfCD0Ba",
    // NOTE: you must use your own CID here, because every time it is used,
    // the protocol does not allow you to use it again
    cid: "QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR",
    // you must pick from one of the whitelisted tags here:
    // https://docs.story.foundation/docs/dispute-module#dispute-tags
    targetTag: DisputeTargetTag.IMPROPER_REGISTRATION,
    bond: parseEther("0.1"), // minimum of 0.1
    liveness: 2592000,
  });
  console.log(
    `Dispute raised at transaction hash ${disputeResponse.txHash}, Dispute ID: ${disputeResponse.disputeId}`
  );
  ```

  ```typescript Request Type theme={null}
  export type RaiseDisputeRequest = {
    targetIpId: Address;
    cid: string;
    targetTag: DisputeTargetTag;
    liveness: bigint | number | string;
    bond?: bigint | number | string;
    wipOptions?: {
      enableAutoWrapIp?: boolean;
      enableAutoApprove?: boolean;
    };
  };

  export enum DisputeTargetTag {
    /** Refers to registration of IP that already exists. */
    IMPROPER_REGISTRATION = "IMPROPER_REGISTRATION",
    /**
     * Refers to improper use of an IP Asset across multiple items.
     * For more details, @see {@link https://docs.story.foundation/concepts/programmable-ip-license/overview | Programmable IP License (PIL)} documentation.
     */
    IMPROPER_USAGE = "IMPROPER_USAGE",
    /** Refers to missing payments associated with an IP. */
    IMPROPER_PAYMENT = "IMPROPER_PAYMENT",
    /**
     * Refers to “No-Hate”, “Suitable-for-All-Ages”, “No-Drugs-or-Weapons” and “No-Pornography”.
     * These items can be found in more detail in the {@link https://docs.story.foundation/concepts/programmable-ip-license/overview  | 💊 Programmable IP License (PIL) } legal document.
     */
    CONTENT_STANDARDS_VIOLATION = "CONTENT_STANDARDS_VIOLATION",
    /**
     * Different from the other 4, this is a temporary tag that goes away
     * at the end of a dispute and is replaced by “0x” in case of no infringement or is replaced by one of the other tags.
     */
    IN_DISPUTE = "IN_DISPUTE",
  }
  ```

  ```typescript Response Type theme={null}
  export type RaiseDisputeResponse = {
    txHash?: Hex;
    encodedTxData?: EncodedTxData;
    disputeId?: bigint;
  };
  ```
</CodeGroup>

### cancelDispute

Cancels an ongoing dispute

| Method          | Type                                                                |
| --------------- | ------------------------------------------------------------------- |
| `cancelDispute` | `(request: CancelDisputeRequest) => Promise<CancelDisputeResponse>` |

Parameters:

* `request.disputeId`: The ID of the dispute to be cancelled.
* `request.data`: \[Optional] Additional data used in the cancellation process. **Defaults to "0x"**.

<CodeGroup>
  ```typescript theme={null}
  const response = await client.dispute.cancelDispute({
    disputeId: 1,
  });
  ```

  ```typescript Request Type theme={null}
  export type CancelDisputeRequest = {
    disputeId: number | string | bigint;
    data?: Hex;
  };
  ```

  ```typescript Response Type theme={null}
  export type CancelDisputeResponse = {
    txHash?: Hex;
    encodedTxData?: EncodedTxData;
  };
  ```
</CodeGroup>

### resolveDispute

Resolves a dispute after it has been judged

| Method           | Type                                                                  |
| ---------------- | --------------------------------------------------------------------- |
| `resolveDispute` | `(request: ResolveDisputeRequest) => Promise<ResolveDisputeResponse>` |

Parameters:

* `request.disputeId`: The ID of the dispute to be resolved.
* `request.data`: \[Optional] The data to resolve the dispute. **Defaults to "0x"**.

<CodeGroup>
  ```typescript theme={null}
  const response = await client.dispute.resolveDispute({
    disputeId: 1,
    data: "0x",
  });
  ```

  ```typescript Request Type theme={null}
  export type ResolveDisputeRequest = {
    disputeId: number | string | bigint;
    data?: Hex;
  };
  ```

  ```typescript Response Type theme={null}
  export type ResolveDisputeResponse = {
    txHash?: Hex;
    encodedTxData?: EncodedTxData;
  };
  ```
</CodeGroup>

### tagIfRelatedIpInfringed

Tags a derivative if a parent has been tagged with an infringement tag or a group ip if a group member has been tagged with an infringement tag.

| Method                    | Type                                                                          |
| ------------------------- | ----------------------------------------------------------------------------- |
| `tagIfRelatedIpInfringed` | `(request: TagIfRelatedIpInfringedRequest) => Promise<TransactionResponse[]>` |

Parameters:

* `request.infringementTags[]`: An array of tags relating to the dispute
  * `request.infringementTags[].ipId`: The `ipId` to tag
  * `request.infringementTags[].disputeId`: The dispute id that tagged the related infringing parent IP
* `request.options`: \[Optional]
  * `request.options.useMulticallWhenPossible`: \[Optional] Use multicall to batch the calls into one transaction when possible. If only 1 infringementTag is provided, multicall will not be used. **Default: true**

<CodeGroup>
  ```typescript theme={null}
  const response = await client.dispute.tagIfRelatedIpInfringed({
    infringementTags: [
      {
        ipId: "0xa1BaAA464716eC76A285Ef873d27f97645fE0366",
        disputeId: 1,
      },
    ],
  });
  ```

  ```typescript Request Type theme={null}
  export type TagIfRelatedIpInfringedRequest = {
    infringementTags: {
      ipId: Address;
      disputeId: number | string | bigint;
    }[];
    options?: {
      useMulticallWhenPossible?: boolean;
    };
  };
  ```

  ```typescript Response Type theme={null}
  export type TransactionResponse = {
    txHash: Hex;

    /** Transaction receipt, only available if waitForTransaction is set to true */
    receipt?: TransactionReceipt;
  };
  ```
</CodeGroup>

### disputeAssertion

Counters a dispute that was raised by another party on an IP using counter evidence.

This method can only be called by the IP's owner to counter a dispute by providing counter evidence. The counter evidence (e.g., documents, images) should be uploaded to IPFS, and its corresponding CID is converted to a hash for the request.

If you only have a `disputeId`, call `disputeIdToAssertionId` to get the `assertionId` needed here.

| Method             | Type                                                                 |
| ------------------ | -------------------------------------------------------------------- |
| `disputeAssertion` | `(request: DisputeAssertionRequest) => Promise<TransactionResponse>` |

Parameters:

* `request.ipId`: The IP ID that is the target of the dispute.
* `request.assertionId`: The identifier of the assertion that was disputed. You can get this from the `disputeId` by calling `dispute.disputeIdToAssertionId`.
* `request.counterEvidenceCID`: Content Identifier (CID) for the counter evidence. This should be obtained by uploading your dispute evidence (documents, images, etc.) to IPFS. **Example: "QmX4zdp8VpzqvtKuEqMo6gfZPdoUx9TeHXCgzKLcFfSUbk"**
* `request.wipOptions`: \[Optional]
  * `request.wipOptions.enableAutoWrapIp`: \[Optional]By default IP is converted to WIP if the current WIP balance does not cover the fees. Set this to `false` to disable this behavior. **Default: true**
  * `request.wipOptions.enableAutoApprove`: \[Optional]Automatically approve WIP usage when WIP is needed but current allowance is not sufficient. Set this to `false` to disable this behavior. **Default: true**

<CodeGroup>
  ```typescript theme={null}
  const assertionId = await client.dispute.disputeIdToAssertionId(1);

  const result = await client.dispute.disputeAssertion({
    ipId: "0xa1BaAA464716eC76A285Ef873d27f97645fE0366",
    assertionId: assertionId,
    counterEvidenceCID: "QmX4zdp8VpzqvtKuEqMo6gfZPdoUx9TeHXCgzKLcFfSUbk",
  });
  ```

  ```typescript Request Type theme={null}
  export type DisputeAssertionRequest = {
    ipId: Address;
    assertionId: Hex;
    counterEvidenceCID: string;
    wipOptions?: {
      enableAutoWrapIp?: boolean;
      enableAutoApprove?: boolean;
    };
  };
  ```

  ```typescript Response Type theme={null}
  export type TransactionResponse = {
    txHash: Hex;

    /** Transaction receipt, only available if waitForTransaction is set to true */
    receipt?: TransactionReceipt;
  };
  ```
</CodeGroup>

### disputeIdToAssertionId

Maps a dispute id to an assertion id

| Method                   | Type                                  |
| ------------------------ | ------------------------------------- |
| `disputeIdToAssertionId` | `(disputeId: number) => Promise<Hex>` |

Parameters:

* `request.disputeId`: The dispute ID.

```typescript theme={null}
const result = await client.dispute.disputeIdToAssertionId(1);
```
