BountyCovenant on Bitcoin Cash. The creator funds a pool sized to rewardPerWinner * maxWinners, the backend co-signs each claim with a stored claim authority, and the creator can pause or cancel the campaign at any time. Bounties pay in BCH or in a single CashToken category.
All mutating routes require Authorization: Bearer <walletSession> plus the canonical x-user-address header. The wallet session is verified by the requireWalletAuth middleware in backend/src/api/bounties.ts. Read routes (list and detail) are unauthenticated.
List bounties
showDeprecated=true.
| Param | In | Required | Description |
|---|---|---|---|
creator | query | yes | cash address that owns the bounties |
showDeprecated | query | no | include legacy deprecated rows when set to true |
Get a bounty
| Param | In | Required | Description |
|---|---|---|---|
id | path | yes | bounty UUID |
Create bounty
BountyCovenant and returns the funding instructions. Requires requireWalletAuth; the creator is taken from the verified wallet session, not from the body.
| Field | Type | Required | Description |
|---|---|---|---|
title | string | yes | bounty title |
description | string | no | free-form description |
tokenType | "BCH" | "FUNGIBLE_TOKEN" | "CASHTOKENS" | no | defaults to BCH; CASHTOKENS is normalised to FUNGIBLE_TOKEN |
tokenCategory | string | no | required when tokenType is FUNGIBLE_TOKEN |
rewardPerWinner | number | yes | display-unit amount paid to each winner |
maxWinners | integer | yes | positive integer, total winner slots |
startDate | number | no | unix seconds; defaults to now |
endDate | number | no | unix seconds; null for open-ended |
vaultId | string | no | bind to an existing vault; otherwise a standalone vault id is derived |
Funding
GET /funding-info builds an unsigned WalletConnect transaction the creator signs to seed the contract pool plus the covenant state NFT. If the creator’s wallet needs a genesis-utxo consolidation first, the response returns requiresPreparation: true and a preparation transaction to sign before retrying.
POST /confirm-funding records the funding tx hash and moves the campaign to ACTIVE. The backend verifies the tx is indexed on chipnet, consumes a UTXO from the caller’s wallet (audit H-07), and produces the expected contract output with the mutable NFT commitment.
| Field | In | Required | Description |
|---|---|---|---|
txHash | body | yes | broadcast funding transaction hash |
Claim winner
/claim to build a backend-co-signed WalletConnect transaction that pays the winner the fixed reward, then signs and broadcasts it, then calls /confirm-claim with the resulting tx hash. Only the bounty creator may authorise claims; the backend rejects requests whose verified signer does not match campaign.creator.
Build claim
| Field | In | Required | Description |
|---|---|---|---|
winnerAddress | body | yes | cash address that receives the reward (alias: winner) |
proofHash | body | yes | 32-byte hex string (64 chars) - off-chain proof commitment |
signerAddress | body | no | defaults to the verified wallet session address |
Confirm claim
| Field | In | Required | Description |
|---|---|---|---|
winnerAddress | body | yes | winner cash address used for output verification |
amount | body | yes | display-unit amount paid to the winner |
proofHash | body | no | recorded against the claim row |
txHash | body | yes | broadcast claim transaction hash |
winners_count reaches max_winners, the campaign transitions to COMPLETED and no further claims are accepted.
Pause
POST /pause is creator-only and requires the campaign to be ACTIVE. It builds a covenant pause transaction that the creator signs and broadcasts, then POST /confirm-pause verifies the new covenant state output and moves the row to PAUSED.
| Field | In | Required | Description |
|---|---|---|---|
txHash | body | yes | broadcast pause transaction hash (confirm only) |
Cancel
POST /cancel is creator-only and allowed from ACTIVE or PAUSED. The cancel refund is enforced on-chain to the authorityHash baked into the constructor params, so the response also returns the derived authorityReturnAddress and a signerMatchesReturn flag. If the signer’s address does not match, the response includes a warning explaining that recovery requires redeploying with the correct creator authority.
POST /confirm-cancel verifies the refund output paid back to authorityReturnAddress (with the original token category for CashToken bounties) and moves the row to CANCELLED.
| Field | In | Required | Description |
|---|---|---|---|
txHash | body | yes | broadcast cancel transaction hash (confirm only) |
Auth summary
| Route | requireWalletAuth |
|---|---|
GET /api/bounties | no |
GET /api/bounties/:id | no |
GET /api/bounties/:id/funding-info | no |
POST /api/bounties/create | yes |
POST /api/bounties/:id/confirm-funding | yes |
POST /api/bounties/:id/claim | yes |
POST /api/bounties/:id/confirm-claim | yes |
POST /api/bounties/:id/pause | yes |
POST /api/bounties/:id/confirm-pause | yes |
POST /api/bounties/:id/cancel | yes |
POST /api/bounties/:id/confirm-cancel | yes |

