Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions api/swagger/swagger-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ tags:
description: Explore related operations
- name: rewards
description: Rewards related operations
- name: prizes
description: Prize claiming related operations
paths:
/challenges/undisbursed:
get:
Expand Down Expand Up @@ -4106,6 +4108,74 @@ paths:
"500":
description: Server error
content: {}
/prizes:
get:
tags:
- prizes
operationId: Get Prizes
description: 'Gets a list of active prizes available for claiming. Excludes sensitive information like download URLs.'
responses:
"200":
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/prizes_response'
"500":
description: Server error
content: {}
/prizes/claim:
post:
tags:
- prizes
operationId: Claim Prize
description: 'Claims a prize by verifying a Solana transaction. User must send exactly 2 YAK to the prize receiver address. Returns the prize won and any redeem codes/URLs.'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this 2 YAK on purpose?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes for testing, but I'll drop that in the swagger description

requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/prize_claim_request'
responses:
"200":
description: Success - Prize claimed
content:
application/json:
schema:
$ref: '#/components/schemas/prize_claim_response'
"400":
description: Bad request - Transaction not found, invalid, or signature already used
content: {}
"500":
description: Server error
content: {}
/wallet/{wallet}/prizes:
get:
tags:
- prizes
operationId: Get Wallet Prizes
description: 'Gets all claimed prizes for a wallet. Public endpoint - no authentication required. Excludes sensitive action_data for security.'
parameters:
- name: wallet
in: path
description: The wallet address to get prizes for
required: true
schema:
type: string
example: "HLnpSz9h2S4hiLQ43rnSD9XkcUThA7B8hQMKmDaiTLcC"
responses:
"200":
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/claimed_prizes_response'
"400":
description: Bad request - Missing wallet parameter
content: {}
"500":
description: Server error
content: {}

components:
schemas:
Expand Down
4 changes: 3 additions & 1 deletion api/v1_coins_post_redeem.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,17 +179,19 @@ func (app *ApiServer) v1CoinsPostRedeem(c *fiber.Ctx) error {

// Read and burn code in one go
// Use CTE to capture old remaining_uses value before updating
// Only update if remaining_uses > 0 to prevent race conditions
sql := `WITH old_row AS (
SELECT remaining_uses, reward_address, amount
FROM reward_codes
WHERE code = @code
AND mint = @mint
)
UPDATE reward_codes
SET remaining_uses = GREATEST(reward_codes.remaining_uses - 1, 0)
SET remaining_uses = reward_codes.remaining_uses - 1
FROM old_row
WHERE reward_codes.code = @code
AND reward_codes.mint = @mint
AND reward_codes.remaining_uses > 0
RETURNING
reward_codes.reward_address,
reward_codes.amount,
Expand Down