carbon-points-store-decoder

Crates.iocarbon-points-store-decoder
lib.rscarbon-points-store-decoder
version0.12.1
created_at2025-11-05 15:19:53.563138+00
updated_at2026-01-21 23:33:23.649533+00
descriptionRust decoder for Star Atlas Points Store program on Solana
homepagehttps://github.com/staratlasmeta/star-atlas-decoders
repositoryhttps://github.com/staratlasmeta/star-atlas-decoders
max_upload_size
id1918142
size177,517
Owners (github:immington-industries:owners)

documentation

README

Carbon Points Store Decoder

Rust decoder for the Star Atlas Points Store program on Solana, generated using Carbon CLI.

Program Information

  • Program ID: PsToRxhEPScGt1Bxpm7zNDRzaMk31t8Aox7fyewoVse
  • Network: Solana Mainnet
  • Description: Star Atlas Points Store program for managing token purchases with points and epoch-based token redemptions. Enables players to spend points to buy tokens directly or participate in time-locked redemption pools with dynamic pricing based on participation.

Features

  • Decodes all Points Store account types
  • Full instruction parsing support
  • Integration with Carbon indexing framework
  • Support for direct token purchases and epoch-based redemptions
  • Faction-based redemption configurations

Usage

Add this crate to your Cargo.toml:

[dependencies]
carbon-points-store-decoder = "0.12.0"

Decoding Accounts

use carbon_points_store_decoder::{PointsStoreDecoder, PointsStoreAccount};
use carbon_core::account::AccountDecoder;

let decoder = PointsStoreDecoder;
let decoded_account = decoder.decode_account(&account);

if let Some(decoded) = decoded_account {
    match decoded.data {
        PointsStoreAccount::PointsStore(store) => {
            println!("Points Store: {:?}", store);
            println!("Point Category: {}", store.point_category);
            println!("Profile: {}", store.profile);
            println!("Bank: {}", store.bank);
            println!("Price (points per token): {}", store.price);
            println!("Signer Bump: {}", store.signer_bump);
        }
        PointsStoreAccount::RedemptionConfig(config) => {
            println!("Redemption Config: {:?}", config);
            println!("Point Category: {}", config.point_category);
            println!("Profile: {}", config.profile);
            println!("Faction: {}", config.faction);
            println!("Bank: {}", config.bank);
            println!("Allow Only Current Epoch: {}", config.allow_only_current_epoch != 0);

            // Access the redemption_epochs array (deserialized from remaining data)
            println!("Number of redemption epochs: {}", config.redemption_epochs.len());
            for epoch in &config.redemption_epochs {
                println!("  Day {}: {} total points, {} total tokens",
                         epoch.day_index, epoch.total_points, epoch.total_tokens);
                println!("    Redeemed: {} points, {} tokens",
                         epoch.redeemed_points, epoch.redeemed_tokens);
                if epoch.total_points > 0 {
                    let tokens_remaining = epoch.total_tokens - epoch.redeemed_tokens;
                    println!("    Tokens remaining: {}", tokens_remaining);
                }
            }
        }
        PointsStoreAccount::UserRedemption(redemption) => {
            println!("User Redemption: {:?}", redemption);
            println!("Profile: {}", redemption.profile);
            println!("Point Category: {}", redemption.point_category);
            println!("User Points Account: {}", redemption.user_points_account);
            println!("Config: {}", redemption.config);
            println!("Points: {}", redemption.points);
            println!("Day Index: {}", redemption.day_index);
        }
    }
}

Working with Faction Values

The RedemptionConfig.faction field is stored as a u8. Map values to factions:

// Faction values (from profile-faction program)
const FACTION_UNALIGNED: u8 = 0;
const FACTION_MUD: u8 = 1;
const FACTION_ONI: u8 = 2;
const FACTION_USTUR: u8 = 3;

let faction_name = match config.faction {
    0 => "Unaligned",
    1 => "MUD",
    2 => "ONI",
    3 => "Ustur",
    _ => "Unknown",
};

println!("Redemption config is for faction: {}", faction_name);

Working with Boolean Flags

The Points Store program uses u8 fields for boolean flags. Check them like this:

// Check if redemptions are limited to current epoch only
if config.allow_only_current_epoch != 0 {
    println!("Only the current epoch can be redeemed");
} else {
    println!("Past epochs can also be redeemed");
}

Account Types

This decoder supports all Points Store account types:

  • PointsStore - A store where tokens can be purchased directly with points at a fixed price

    • Stores the point category, managing profile, token bank, and price per token
    • Includes a signer bump for PDA-based token transfers
    • Simple direct exchange: spend X points, receive Y tokens
  • RedemptionConfig - Configuration for epoch-based token redemptions

    • Enables time-locked redemption pools where users contribute points
    • Tokens are distributed proportionally based on each user's contribution
    • Faction-specific configurations allow different redemption rules per faction
    • Includes fully deserialized redemption_epochs array from remaining data (each epoch tracks total/redeemed points and tokens for a specific day)
    • Can restrict redemptions to only the current epoch
  • UserRedemption - Tracks a user's points contribution for a specific redemption epoch

    • Links to the user's profile and points account
    • Stores the points submitted for redemption
    • Tied to a specific day index (24-hour epoch)
    • Used to calculate proportional token distribution when claiming

Store vs Redemption

The Points Store program provides two mechanisms for exchanging points for tokens:

Direct Store Purchase

  • Fixed pricing: Set price per token
  • Immediate exchange: Spend points, receive tokens instantly
  • Simple model: Like buying items from a store

Epoch-Based Redemption

  • Pool-based: Users contribute points to a daily pool
  • Proportional distribution: Tokens distributed based on contribution percentage
  • Time-locked: Must wait for epoch to complete
  • Dynamic pricing: Effective rate depends on total participation
  • Faction-specific: Different configs for different factions

Example: If 1000 tokens are available for an epoch, and you contributed 100 points out of a total 1000 points submitted, you can claim 100 tokens (10% of the pool).

Documentation

Full documentation is available at docs.rs.

Repository

See the main repository for build instructions and contribution guidelines.

License

Licensed under the Apache-2.0 license.

Commit count: 104

cargo fmt