# Bounty Manager

## **Introduction**

This guide focusses on the most common patterns of interactions with the Bounty Manager Module. Please refer to the [Technical Reference](https://docs.inverter.network/contracts/technical-reference/modules/logic-module/lm_pc_bounties_v1.sol#public-functions) section to see all public getters and setters.

## **Setup Requirements**

The guide includes code snippets for Inverter Network's TypeScript SDK. Please refer to the relevant code snippets based on the SDK you are using.

1. **Set up Inverter Network SDK**: Refer to the Quick Start guides for detailed instructions. See the [React SDK Guide](https://docs.inverter.network/sdk/react-sdk) or [TypeScript SDK Guide](https://docs.inverter.network/sdk/typescript-sdk) for more information.
2. **Deploy a Workflow**: Refer to the Deploy a Workflow guide for detailed instructions. See the [React SDK Guide ](https://docs.inverter.network/sdk/react-sdk/deploy-a-workflow)or [TypeScript SDK Guide](https://docs.inverter.network/sdk/typescript-sdk/deploy-a-workflow) for more information.
3. **Retrieve a deployed Workflow**: Refer to the Operate a Workflow guide for detailed instructions. See the [React SDK Guide](https://docs.inverter.network/sdk/react-sdk/operate-a-workflow) or [TypeScript SDK Guide](https://docs.inverter.network/sdk/typescript-sdk/operate-a-workflow) for more information.

* **Optionally if your setup needs a specific contract**: Refer to the Deploy a Contract Guide for detailed instructions. See the [React SDK](https://docs.inverter.network/sdk/react-sdk/deploy-a-contract) Guide or [TypeScript SDK](https://docs.inverter.network/sdk/typescript-sdk/deploy-a-contract) Guide for more information.

## Managing Bounty Manager Roles <a href="#grant-or-revoke-role-1" id="grant-or-revoke-role-1"></a>

Managing roles for the Bounty Manager involves several steps, including reading role, generating role IDs, assigning roles, and revoking them.

### Retrieving the roles

The Bounty Manager utilizes several roles to handle the issuance, verification, and claiming of bounties. The first step is to retrieve the available roles in the Bounty Manager, as demonstrated below:

{% code overflow="wrap" %}

```typescript
const VERIFIER_ROLE = await workflow.optionalModule.LM_PC_Bounties_v1.read.VERIFIER_ROLE.run()

const BOUNTY_ISSUER_ROLE = await workflow.optionalModule.LM_PC_Bounties_v1.read.BOUNTY_ISSUER_ROLE.run()

const CLAIMANT_ROLE = await workflow.optionalModule.LM_PC_Bounties_v1.read.CLAIMANT_ROLE.run()
```

{% endcode %}

## **Check If User Has Module Roles**

The following two-step process validates whether a given address has roles assigned to it:

{% code overflow="wrap" %}

```typescript
// Step 1. Generate the role ids
const [GEN_VERIFIER_ROLE, GEN_BOUNTY_ISSUER_ROLE, GEN_CLAIMANT_ROLE] =
      await Promise.all(
        [VERIFIER_ROLE, BOUNTY_ISSUER_ROLE, CLAIMANT_ROLE].map((id) => {
          return workflow.authorizer.read.generateRoleId.run([
            workflow.optionalModule.LM_PC_Bounties_v1.address,
            id,
          ])
        })
      )
      
// Step 2. Check if the user has the role
const [HAS_VERIFIER_ROLE, HAS_BOUNTY_ISSUER_ROLE, HAS_CLAIMANT_ROLE] =
      await Promise.all(
        [GEN_VERIFIER_ROLE, GEN_BOUNTY_ISSUER_ROLE, GEN_CLAIMANT_ROLE].map(
          (genId) => {
            return workflow.authorizer.read.hasRole.run([
              genId,
              <wallet_address>,
            ])
          }
        )
      )
```

{% endcode %}

## Grant and Revoke Role

The following section demonstrates how to grant and revoke roles for a wallet address.

{% code overflow="wrap" %}

```typescript
const walletAddress = sdk.walletClient.account.address

const args = [ 
    <VERIFIER_ROLE | BOUNTY_ISSUER_ROLE | CLAIMANT_ROLE>,
    walletAddress
] as const

// Grant role
const grantRoleTransactionHash = await workflow.optionalModule.LM_PC_Bounties_v1.write.grantModuleRole.run(args)

// Revoke role
const revokeRoleTransactionHash = await workflow.optionalModule.LM_PC_Bounties_v1.write.revokeModuleRole.run(args)
```

{% endcode %}

## Bounty Creation

### Add a Bounty

The following section explains how to add a bounty to the Bounty Manager:

{% code overflow="wrap" %}

```typescript
import { decodeEventLog } from 'viem'
import { getModuleData } from '@inverter-network/abis'

let bountyId = string

const bounty = [
    // Minimum Payment Amount
    '1000',
    // Maximum Payment Amount
    '10000',
    // Details ( type any )
    {
        timestamp: 1734448333
        message: 'hello' 
    }
] as const

const addBountyTransactionHash =
  await workflow.optionalModule.LM_PC_Bounties_v1.write.addBounty.run(bounty, {
    confirmations: 1,
    // !Optional! You can get the list of bounty id's from a different endpoint
    onConfirmation: (receipt) => {
      // Define the ABI for the BountyAdded event
      const BountyAddedAbi = [
        getModuleData('LM_PC_Bounties_v1').abi.find(
          (i) => i.name === 'BountyAdded'
        ),
      ]

      // Decode the logs using the ABI
      const decodedLogs = decodeEventLog({
        abi: BountyAddedAbi,
        data: receipt.logs[0].data,
        topics: receipt.logs[0].topics,
      })

      // Retrieve the bountyId from the decoded logs
      bountyId = decodedLogs.args.bountyId.toString()
    },
  })
```

{% endcode %}

### Add Bounty in Batches

The following section explains how to add multiple bounties in batches

{% code overflow="wrap" %}

```typescript
const bounties = [
    // Minimum Payment Amounts
    ['1000`, '2000', '3000'],
    // Maximum Payment Amount
    ['10000', '20000', '30000'],
    // Details ( type any )
    [{
        timestamp: 1734448333
        message: 'hello' 
    },
    {
        timestamp: 1734448334
        message: 'hello1' 
    },
    {
        timestamp: 1734448335
        message: 'hello2' 
    }]
] as const

const addBountyTransactionHash = await workflow.optionalModule.LM_PC_Bounties_v1.write.addBountyBatch.run(bounties)
```

{% endcode %}

### Read Bounty

The following section explains how to read a given bounty information based on the `bountyId`

{% code overflow="wrap" %}

```typescript
const bountyInformation = await workflow.optionalModule.LM_PC_Bounties_v1.read.getBountyInformation.run(bountyId)

const {
    minimumPayoutAmount
    maximumPayoutAmount
    details: {
        timestamp,
        message
    }
    locked
} = bountyInformation
```

{% endcode %}

## Bounty Claim

### Add Bounty Claim

The following section explains how to submit a bounty claim:

{% code overflow="wrap" %}

```typescript
import { decodeEventLog, parseAbiItem } from 'viem'

let claimId = string

const contributers = 
  [
    // Bounty Id
    bountyId,
    // Contributers
    [{ addr: <wallet_address>, claimAmount: '100' }],
    // Details ( type any )
    {
      claimUrl: 'https://www.google.com',
    },
  ] as const

const claimTransactionHash =
  await workflow.optionalModule.LM_PC_Bounties_v1.write.addClaim.run(
    contributers,
    {
      confirmations: 1,
      // !Optional! You can get the list of claim id's from a different endpoint
      onConfirmation: (receipt) => {
        const claimAddedAbi = parseAbiItem(
          'event ClaimAdded(uint256 indexed claimId,uint256 indexed bountyId,(address,uint256)[] contributors,bytes details)'
        )

        const decodedLogs = decodeEventLog({
          abi: [claimAddedAbi],
          data: receipt.logs[0].data,
          topics: receipt.logs[0].topics,
        })

        claimId = decodedLogs.args.claimId.toString()
      },
    }
  )
```

{% endcode %}

### Read Bounty Claim

The following section explains how to read a submitted bounty claim

{% code overflow="wrap" %}

```typescript
const claimInformation = await workflow.optionalModule.LM_PC_Bounties_v1.read.getClaimInformation.run(claimId)

const {
  details: { claimUrl },
  bountyId,
  claimed,
  contributors,
} = claimInformation
```

{% endcode %}

## Verify Bounty Claim

### Verify a Claim

The following section explains how to verify a claim providing the `claimId` and `contributors` as parameters:

{% code overflow="wrap" %}

```typescript
const transactionHash = await workflow.optionalModule.LM_PC_Bounties_v1.write.verifyClaim.run([
    claimId,
    contributors,
])
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.inverter.network/sdk/guides/bounty-manager.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
