Skip to content

Reward Code Redemption endpoints - #540

Merged
schottra merged 10 commits into
mainfrom
gift-rewards
Nov 10, 2025
Merged

schottra merged 10 commits into
mainfrom
gift-rewards

Conversation

@schottra

@schottra schottra commented Nov 6, 2025 •

Copy link
Copy Markdown
Contributor

Opted to re-use the handlers since there is very little difference in the logic between using a code and not using one.
Can split out if we don't love it.

Not going to work as-is, needs some stuff from an unmerged PR. But the bones are there.

@schottra schottra changed the title Gift rewards Reward Code Redemption endpoints Nov 6, 2025
Comment thread api/v1_coins_post_redeem.go Outdated
if redeemCode != "" {
// Read and burn code in one go
// Use CTE to capture old is_used value before updating
sql := `WITH old_row AS (

@schottra schottra Nov 6, 2025 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Intentional choice to push this query as far down into the function as possible so that arbitrary errors in code that is not the actual claim process will just return early with 4xx/5xx. Once we get to this point, we're burning it and grabbing it in a single query (while also checking if it had already been used).
Note that using a code for the wrong mint and using a code that doesn't exist both return the same error.
If we want that to be different, will need to rework this.

Comment thread api/v1_coins_post_redeem.go Outdated

var rewardStateAddress string
var minVotes int
err = app.pool.QueryRow(c.Context(), `SELECT reward_manager_state, min_votes FROM sol_reward_manager_inits WHERE mint = @mint`, pgx.NamedArgs{

@schottra schottra Nov 6, 2025 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Shortcut here to get min_votes from the table. Technically this could fail if the table has a different value than what's currently on chain. But that feels highly unlikely.

Comment thread api/v1_coins_post_redeem.go Outdated
rewardClaim := oap_rewards.RewardClaim{
RecipientEthAddress: userWalletAddress,
Amount: amount,
RewardID: "code", // TODO: Use shared constant/generator

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this will depend on the result of the query, too, right? like if there's a "gift" reward the code will be the ID?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

All the use cases that use a redeemable code can use 'code' as the rewardId (these don't need to be unique across programatic rewards) and the code itself as the specifier.

Comment thread api/v1_coins_post_redeem.go Outdated
"github.com/jackc/pgx/v5"
)

func getAttestationSignatureForRewardClaimAuthority(rewardClaim oap_rewards.RewardClaim, claimAuthorityKey *ecdsa.PrivateKey) (string, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

doesn't this already exist?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh good call. I didn't know that was a thing.

@schottra
schottra marked this pull request as ready for review November 7, 2025 17:48
@schottra
schottra changed the base branch from main to rj-codes3 November 7, 2025 17:48
Base automatically changed from rj-codes3 to main November 7, 2025 18:15
Comment thread api/v1_coins_post_redeem.go Outdated

response, err := oap.Rewards.GetRewardAttestation(c.Context(), &v1.GetRewardAttestationRequest{
EthRecipientAddress: userWalletAddress,
Amount: uint64(amount) / uint64(math.Pow10(int(coinDecimals))), // Convert from token decimals

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Confirming this is all right?

@schottra
schottra merged commit 6078b18 into main Nov 10, 2025
5 checks passed
@schottra
schottra deleted the gift-rewards branch November 10, 2025 18:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants