Skip to content

Commit 9bf7fcc

Browse files
authored
feat: add cargo decoder (#35)
### TL;DR Added a new Cargo program decoder for Star Atlas resource container management. ### What changed? - Added a new `carbon-cargo-decoder` crate for the Star Atlas Cargo program (`Cargo2VNTPPTi9c1vq1Jw5d3BWUNr18MjRtSupAghKEk`) - Implemented account types: `CargoPod`, `CargoType`, and `CargoStatsDefinition` - Added instruction parsing for all Cargo program instructions - Created custom `CargoPermissions` bitflags with helper methods for permission management - Added serialization support for account types - Updated README, justfile, and project documentation to include the new decoder ### Why make this change? The Cargo program is a critical component of the Star Atlas ecosystem, managing resource containers (pods) with dynamic stat tracking and cargo types. This decoder enables developers to interact with and analyze Cargo program data, supporting use cases like resource management, inventory tracking, and game economy analysis. The custom permission bitflags provide an ergonomic way to work with the program's permission system.
2 parents 524a475 + 0d70ce2 commit 9bf7fcc

38 files changed

+1759
-65
lines changed

Cargo.lock

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 33 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
<a href="https://crates.io/crates/carbon-atlas-fee-payer-decoder">
2929
<img src="https://img.shields.io/crates/v/carbon-atlas-fee-payer-decoder?logo=rust&label=atlas-fee-payer" />
3030
</a>
31+
<a href="https://crates.io/crates/carbon-cargo-decoder">
32+
<img src="https://img.shields.io/crates/v/carbon-cargo-decoder?logo=rust&label=cargo" />
33+
</a>
3134
<a href="https://crates.io/crates/carbon-crew-decoder">
3235
<img src="https://img.shields.io/crates/v/carbon-crew-decoder?logo=rust&label=crew" />
3336
</a>
@@ -57,66 +60,56 @@ This project generates and maintains Rust decoders for Star Atlas programs on So
5760
### Supported Decoders
5861

5962
- **sage-starbased**: SAGE Starbase program (`SAGE2HAwep459SNq61LHvjxPk4pLPEJLoMETef7f7EE`)
60-
- Fetches IDL directly from Solana mainnet
61-
- Custom deserialization for Fleet and StarbasePlayer accounts
63+
- Fleet and starbase management for Star Atlas
64+
- Custom patches for remaining data deserialization
6265

6366
- **sage-holosim**: SAGE Holosim program (`SAgEeT8u14TE69JXtanGSgNkEdoPUcLabeyZD2uw8x9`)
64-
- Uses local IDL file from `./idl/` directory
65-
- Custom deserialization for Fleet and StarbasePlayer accounts
67+
- Fleet and starbase management for Star Atlas (uses local IDL)
68+
- Custom patches for remaining data deserialization
6669

6770
- **atlas-staking**: Atlas Staking program (`ATLocKpzDbTokxgvnLew3d7drZkEzLzDpzwgrgWKDbmc`)
68-
- Fetches IDL directly from Solana mainnet
6971
- ATLAS token staking with configurable rewards and cooldown periods
70-
- Minimal patches needed - adds serialization support for account types
72+
- Minimal patches for serialization support
7173

7274
- **locked-voter**: Locked Voter program (`Lock7kBijGCQLEFAmXcengzXKA88iDNQPriQ7TbgeyG`)
73-
- Fetches IDL directly from Solana mainnet
7475
- POLIS governance and voting with escrow and whitelist controls
75-
- Minimal patches needed - adds serialization support for account types
76+
- Minimal patches for serialization support
7677

7778
- **marketplace**: Galactic Marketplace program (`traderDnaR5w6Tcoi3NFm53i48FTDNbGjBSZwWXDRrg`)
78-
- Fetches IDL directly from Solana mainnet
7979
- NFT marketplace with order books, currency management, and royalty tiers
80-
- Minimal patches needed - adds serialization support for account types
80+
- Minimal patches for serialization support
8181

8282
- **atlas-fee-payer**: ATLAS Fee Payer program (`APR1MEny25pKupwn72oVqMH4qpDouArsX8zX4VwwfoXD`)
83-
- Fetches IDL directly from Solana mainnet
8483
- Fee payment management for Star Atlas transactions
85-
- Minimal patches needed - adds serialization support for account types
84+
- Minimal patches for serialization support
85+
86+
- **cargo**: Cargo program (`Cargo2VNTPPTi9c1vq1Jw5d3BWUNr18MjRtSupAghKEk`)
87+
- Resource container management with dynamic stat tracking
88+
- Custom patches for remaining data deserialization
8689

8790
- **crew**: Crew Management program (`CREWiq8qbxvo4SKkAFpVnc6t7CRQC4tAAscsNAENXgrJ`)
88-
- Fetches IDL directly from Solana mainnet
8991
- Crew management for Star Atlas ships and operations
90-
- Uses serde_big_array for large byte arrays
91-
- Minimal patches needed - adds serialization support for account types
92+
- Minimal patches for serialization support
9293

9394
- **profile-vault**: Profile Vault program (`pv1ttom8tbyh83C1AVh6QH2naGRdVQUVt3HY1Yst5sv`)
94-
- Fetches IDL directly from Solana mainnet
9595
- Profile vault management for Star Atlas player profiles
96-
- Minimal patches needed - adds serialization support for account types
96+
- Minimal patches for serialization support
9797

9898
- **srsly**: Fleet Rentals (SRSLY) program (`SRSLY1fq9TJqCk1gNSE7VZL2bztvTn9wm4VR8u8jMKT`)
99-
- Fetches IDL directly from Solana mainnet
10099
- Fleet rental contracts and automated payment processing
101-
- Custom patches - adds serialization support and f64 rate field workaround
100+
- Custom patches for numeric field handling
102101

103102
- **tcomp**: Tensor cNFT Compressed program (`TCMPhJdwDryooaGtiocG1u3xcYbRpiJzb283XfCZsDp`)
104-
- Fetches IDL directly from Solana mainnet
105103
- Compressed NFT marketplace for trading cNFTs
106-
- Uses serde_big_array for large byte arrays
107-
- Minimal patches needed - adds serialization support for account types
104+
- Minimal patches for serialization support
108105

109106
- **player-profile**: Player Profile program (`pprofELXjL5Kck7Jn5hCpwAL82DpTkSYBENzahVtbc9`)
110-
- Fetches IDL directly from Solana mainnet
111107
- Player identity and role-based access control for Star Atlas
112-
- Custom patches - adds serialization and ergonomic permission bitflags with helper methods
113-
- Includes permission checking, key expiration validation, and role management
108+
- Custom patches for remaining data deserialization
114109

115110
- **profile-faction**: Profile Faction program (`pFACSRuobDmvfMKq1bAzwj27t6d2GJhSCHb1VcfnRmq`)
116-
- Fetches IDL directly from Solana mainnet
117111
- Player faction affiliation management for Star Atlas universe
118-
- Custom patches - adds serialization and type-safe Faction enum
119-
- Supports Unaligned, MUD, ONI, and Ustur factions
112+
- Custom patches for type-safe faction handling
120113

121114
## Prerequisites
122115

@@ -142,46 +135,18 @@ Run `./scripts/check-tools.sh` to verify all required tools are installed:
142135
```
143136
star-atlas-decoders/
144137
├── carbon-decoders/ # Published decoder crates
145-
│ ├── sage-starbased-decoder/
146-
│ ├── sage-holosim-decoder/
147-
│ ├── atlas-staking-decoder/
148-
│ ├── locked-voter-decoder/
149-
│ ├── marketplace-decoder/
150-
│ ├── atlas-fee-payer-decoder/
151-
│ ├── crew-decoder/
152-
│ ├── profile-vault-decoder/
153-
│ ├── srsly-decoder/
154-
│ ├── tcomp-decoder/
155-
│ ├── player-profile-decoder/
156-
│ └── profile-faction-decoder/
157138
├── dist/ # Temporary build directory (gitignored)
158139
├── patches/ # Custom patches for decoders
159-
│ ├── sage-starbased-01-accounts.patch
160-
│ ├── sage-holosim-01-disable-ix-combat-log-event.patch
161-
│ ├── atlas-staking-01-accounts-serialize.patch
162-
│ ├── locked-voter-01-accounts-serialize.patch
163-
│ ├── marketplace-01-accounts-serialize.patch
164-
│ ├── atlas-fee-payer-01-accounts-serialize.patch
165-
│ ├── crew-01-accounts-serialize.patch
166-
│ ├── profile-vault-01-accounts-serialize.patch
167-
│ ├── srsly-01-accounts-serialize.patch
168-
│ ├── srsly-02-rate-f64-workaround.patch
169-
│ ├── tcomp-01-accounts-serialize.patch
170-
│ ├── player-profile-01-accounts-serialize.patch
171-
│ ├── player-profile-02-permissions-helpers.patch
172-
│ ├── player-profile-03-remaining-data.patch
173-
│ └── player-profile-04-instruction-remaining-accounts.patch
174-
│ ├── profile-faction-01-accounts-serialize.patch
175-
│ └── profile-faction-02-use-faction-enum.patch
176140
├── idl/ # Local IDL files
177141
├── scripts/ # CI and utility scripts
178-
│ ├── ci.sh # Full CI pipeline
179-
│ └── check-tools.sh # Tool verification
142+
│ ├── ci-clean.sh # Full CI pipeline
143+
│ ├── ci.sh # GitHub CI pipeline
144+
│ └── check-tools.sh # Tool verification
180145
├── docs/ # Documentation
146+
│ ├── adding-new-decoder.md
181147
│ ├── patch-development-workflow.md
182-
│ └── readmes/ # Individual decoder READMEs
183-
└── justfile # Build automation
184-
148+
│ └── readmes/ # Individual decoder READMEs
149+
└── justfile # Build automation
185150
```
186151

187152
## Development Workflow
@@ -269,13 +234,17 @@ just list-patches
269234

270235
The decoders include custom deserialization for accounts with:
271236

272-
- **Variable-length "remaining data" fields**: e.g., Fleet's `fleet_state`
273-
- **Dynamic arrays not in IDL**: e.g., StarbasePlayer's `ship_escrows`
237+
- **Variable-length "remaining data" fields**: e.g., Fleet's `fleet_state`, CargoType's `cargo_stats`, CargoPod's `cargo_contents`
238+
- **Dynamic arrays not in IDL**: e.g., StarbasePlayer's `ship_escrows`, Profile's `profile_keys`
274239
- **Complex nested structures**: Custom BorshDeserialize implementations
275240

276241
Example accounts with custom deserialization:
277242
- `Fleet`: Includes `fleet_state` enum for current fleet activity
278243
- `StarbasePlayer`: Includes dynamic `ship_escrows` list
244+
- `CargoType`: Includes `cargo_stats` array (length = `stats_count`)
245+
- `CargoPod`: Includes `cargo_contents` array of u64 values
246+
247+
> For detailed patch implementations, see the `patches/` directory and individual decoder READMEs in `docs/readmes/`.
279248
280249
## Technical Details
281250

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[package]
2+
name = "carbon-cargo-decoder"
3+
version = "0.10.0"
4+
edition = "2024"
5+
description = "Rust decoder for Star Atlas Cargo program on Solana"
6+
license = "Apache-2.0"
7+
repository = "https://github.com/staratlasmeta/star-atlas-decoders"
8+
homepage = "https://github.com/staratlasmeta/star-atlas-decoders"
9+
readme = "README.md"
10+
keywords = ["solana", "star-atlas", "decoder"]
11+
categories = ["encoding"]
12+
rust-version = "1.85"
13+
14+
[lib]
15+
crate-type = ["rlib"]
16+
17+
[dependencies]
18+
bitflags = "2.6"
19+
carbon-core = "0.10.0"
20+
carbon-proc-macros = "0.10.0"
21+
carbon-macros = "0.10.0"
22+
solana-account = "2.2.1"
23+
solana-instruction = { version = "2.3.0", default-features = false }
24+
solana-pubkey = { version = "2.4.0", features = ["borsh", "serde", "bytemuck"] }
25+
serde = { version = "1.0", features = ["derive"] }
26+
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Carbon Cargo Decoder
2+
3+
<p align="center">
4+
<a href="https://crates.io/crates/carbon-cargo-decoder">
5+
<img src="https://img.shields.io/crates/v/carbon-cargo-decoder?logo=rust" />
6+
</a>
7+
<a href="https://docs.rs/carbon-cargo-decoder">
8+
<img src="https://img.shields.io/docsrs/carbon-cargo-decoder?logo=docsdotrs" />
9+
</a>
10+
<a href="https://github.com/staratlasmeta/star-atlas-decoders/blob/main/LICENSE">
11+
<img src="https://img.shields.io/badge/license-Apache%202.0-blue" />
12+
</a>
13+
</p>
14+
15+
Rust decoder for the Star Atlas Cargo program on Solana, generated using [Carbon CLI](https://github.com/sevenlabs-hq/carbon).
16+
17+
## Program Information
18+
19+
- **Program ID**: `Cargo2VNTPPTi9c1vq1Jw5d3BWUNr18MjRtSupAghKEk`
20+
- **Network**: Solana Mainnet
21+
- **Description**: Star Atlas Cargo program for managing resource containers (pods) with dynamic stat tracking, cargo types, and token-based resource management.
22+
23+
## Features
24+
25+
- Decodes all Cargo account types
26+
- Full instruction parsing support
27+
- Integration with Carbon indexing framework
28+
- Permission bitflags support for cargo operations
29+
- Support for dynamic cargo stats and pod management
30+
31+
## Usage
32+
33+
Add this crate to your `Cargo.toml`:
34+
35+
```toml
36+
[dependencies]
37+
carbon-cargo-decoder = "0.10.0"
38+
```
39+
40+
### Decoding Accounts
41+
42+
```rust
43+
use carbon_cargo_decoder::{CargoDecoder, CargoAccount};
44+
use carbon_core::account::AccountDecoder;
45+
46+
let decoder = CargoDecoder;
47+
let decoded_account = decoder.decode_account(&account);
48+
49+
if let Some(decoded) = decoded_account {
50+
match decoded.data {
51+
CargoAccount::CargoPod(pod) => {
52+
println!("Cargo Pod: {:?}", pod);
53+
println!("Authority: {}", pod.authority);
54+
println!("Open Token Accounts: {}", pod.open_token_accounts);
55+
}
56+
CargoAccount::CargoType(cargo_type) => {
57+
println!("Cargo Type: {:?}", cargo_type);
58+
println!("Mint: {}", cargo_type.mint);
59+
println!("Stats Count: {}", cargo_type.stats_count);
60+
}
61+
CargoAccount::CargoStatsDefinition(definition) => {
62+
println!("Stats Definition: {:?}", definition);
63+
println!("Authority: {}", definition.authority);
64+
println!("Sequence ID: {}", definition.seq_id);
65+
}
66+
}
67+
}
68+
```
69+
70+
### Working with Permissions
71+
72+
The decoder includes ergonomic permission handling with bitflags:
73+
74+
```rust
75+
use carbon_cargo_decoder::CargoPermissions;
76+
77+
// Create permissions from u64 or bytes
78+
let perms = CargoPermissions::from_u64(0b111);
79+
80+
// Check individual permissions
81+
if perms.contains(CargoPermissions::MANAGE_DEFINITION) {
82+
println!("Can manage cargo definitions");
83+
}
84+
85+
if perms.contains(CargoPermissions::CREATE_CARGO_TYPE) {
86+
println!("Can create new cargo types");
87+
}
88+
89+
if perms.contains(CargoPermissions::MANAGE_CARGO_TYPE) {
90+
println!("Can update existing cargo types");
91+
}
92+
93+
// Combine permissions
94+
let admin_perms = CargoPermissions::MANAGE_DEFINITION
95+
| CargoPermissions::CREATE_CARGO_TYPE
96+
| CargoPermissions::MANAGE_CARGO_TYPE;
97+
98+
// Convert to/from bytes for storage
99+
let bytes = admin_perms.to_le_bytes();
100+
let restored = CargoPermissions::from_le_bytes(bytes);
101+
```
102+
103+
### Account Types
104+
105+
This decoder supports all Cargo account types:
106+
- `CargoPod` - Container for resources with dynamic stat tracking
107+
- `CargoType` - Definition of a specific cargo type with associated stats
108+
- `CargoStatsDefinition` - Global configuration for cargo stat definitions
109+
110+
### Permission Flags
111+
112+
The `CargoPermissions` bitflags type includes:
113+
- `MANAGE_DEFINITION` - Can initialize and update cargo definitions
114+
- `CREATE_CARGO_TYPE` - Can create new cargo types
115+
- `MANAGE_CARGO_TYPE` - Can update existing cargo types
116+
117+
## Documentation
118+
119+
Full documentation is available at [docs.rs](https://docs.rs/carbon-cargo-decoder).
120+
121+
## Repository
122+
123+
See the [main repository](https://github.com/staratlasmeta/star-atlas-decoders) for build instructions and contribution guidelines.
124+
125+
## License
126+
127+
Licensed under the [Apache-2.0](https://github.com/staratlasmeta/star-atlas-decoders/blob/main/LICENSE) license.

0 commit comments

Comments
 (0)