Skip to content

Commit 58b60be

Browse files
add c-token rust client helpers
1 parent e1fd709 commit 58b60be

File tree

7 files changed

+618
-0
lines changed

7 files changed

+618
-0
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ members = [
2222
"sdk-libs/macros",
2323
"sdk-libs/sdk",
2424
"sdk-libs/compressed-token-sdk",
25+
"sdk-libs/compressed-token-client",
2526
"sdk-libs/photon-api",
2627
"sdk-libs/program-test",
2728
"xtask",
@@ -163,6 +164,10 @@ account-compression = { path = "programs/account-compression", version = "1.2.0"
163164
light-compressed-token = { path = "programs/compressed-token", version = "1.2.0", features = [
164165
"cpi",
165166
] }
167+
light-compressed-token-client = { path = "sdk-libs/compressed-token-client", version = "0.1.0" }
168+
light-system-program = { path = "anchor-programs/system", version = "1.2.0", features = [
169+
"cpi",
170+
] }
166171
light-system-program-anchor = { path = "anchor-programs/system", version = "1.2.0", features = [
167172
"cpi",
168173
] }
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
[package]
2+
name = "light-compressed-token-client"
3+
version = "0.1.0"
4+
edition = "2021"
5+
license = "Apache-2.0"
6+
repository = "https://github.com/lightprotocol/light-protocol"
7+
description = "Client library for Light Protocol Compressed Token Program"
8+
9+
[features]
10+
default = []
11+
12+
[dependencies]
13+
# Light Protocol dependencies
14+
light-compressed-token = { workspace = true }
15+
light-compressed-account = { workspace = true, features = ["anchor"] }
16+
light-system-program-anchor = { workspace = true }
17+
account-compression = { workspace = true }
18+
19+
# Solana dependencies
20+
solana-sdk = { workspace = true }
21+
solana-pubkey = { workspace = true }
22+
solana-instruction = { workspace = true }
23+
solana-program = { workspace = true }
24+
solana-transaction = { workspace = true }
25+
solana-signature = { workspace = true }
26+
solana-hash = { workspace = true }
27+
solana-account = { workspace = true }
28+
29+
# Anchor
30+
anchor-lang = { workspace = true }
31+
anchor-spl = { workspace = true }
32+
33+
# External dependencies
34+
borsh = { workspace = true }
35+
num-bigint = { workspace = true }
36+
num-traits = { workspace = true }
37+
thiserror = { workspace = true }
38+
39+
[dev-dependencies]
40+
tokio = { workspace = true, features = ["rt", "macros"] }
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Light Compressed Token Client
2+
3+
A Rust client library for interacting with the Compressed Token Program on Solana.
4+
5+
## Overview
6+
7+
- **Compress**: Compress SPL tokens to a recipient.
8+
- **Decompress**: Decompress compressed tokens back to an SPL token account
9+
- **Batch Compress**: Compress SPL tokens to multiple recipients in a single instruction.
10+
11+
## Installation
12+
13+
Add to your `Cargo.toml`:
14+
15+
```toml
16+
[dependencies]
17+
light-compressed-token-client = "0.1.0"
18+
```
19+
20+
## Usage
21+
22+
### Compress to one recipient
23+
24+
```rust
25+
use light_compressed_token_client::{compress, CompressParams};
26+
use solana_pubkey::Pubkey;
27+
28+
let instruction = compress(
29+
payer,
30+
owner,
31+
source_token_account,
32+
mint,
33+
1000, // amount
34+
recipient,
35+
output_state_tree,
36+
)?;
37+
```
38+
39+
### Compress to multiple recipients
40+
41+
```rust
42+
use light_compressed_token_client::batch_compress;
43+
44+
// Compress to multiple recipients
45+
let recipients = vec![
46+
(recipient1, 500),
47+
(recipient2, 300),
48+
(recipient3, 200),
49+
];
50+
51+
let instruction = batch_compress(
52+
payer,
53+
owner,
54+
source_token_account,
55+
mint,
56+
recipients,
57+
output_state_tree,
58+
)?;
59+
```
60+
61+
### Decompress to SPL token account.
62+
63+
```rust
64+
use light_compressed_token_client::{DecompressParams, create_decompress_instruction};
65+
66+
let params = DecompressParams {
67+
payer,
68+
input_compressed_token_accounts: vec![(account, token_data, merkle_context)],
69+
to_address: destination_token_account, // SPL token account, eg ATA.
70+
amount: 1000,
71+
recent_input_state_root_indices: vec![Some(0)], // fetch via get_validity_proof
72+
recent_validity_proof: Some(proof), // fetch via get_validity_proof
73+
output_state_tree: Some(state_tree),
74+
token_program_id: None, // defaults to SPL Token
75+
};
76+
77+
let instruction = create_decompress_instruction(params)?;
78+
```
79+
80+
## Features
81+
82+
- Supports SPL-token and Token-22 mints.
83+
84+
## License
85+
86+
Apache-2.0
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
//! Example demonstrating basic usage of the compressed-token-client library
2+
3+
use light_compressed_token_client::{
4+
batch_compress, compress, create_decompress_instruction, AccountState, CompressedAccount,
5+
DecompressParams, MerkleContext, TokenData, TreeType,
6+
};
7+
use solana_sdk::pubkey::Pubkey;
8+
9+
fn main() {
10+
// Example 1: Simple compression
11+
simple_compress_example();
12+
13+
// Example 2: Batch compression
14+
batch_compress_example();
15+
16+
// Example 3: Decompression
17+
decompress_example();
18+
}
19+
20+
fn simple_compress_example() {
21+
println!("=== Simple Compress Example ===");
22+
23+
let payer = Pubkey::new_unique();
24+
let owner = Pubkey::new_unique();
25+
let source_token_account = Pubkey::new_unique();
26+
let mint = Pubkey::new_unique();
27+
let recipient = Pubkey::new_unique();
28+
let output_state_tree = Pubkey::new_unique();
29+
30+
let instruction = compress(
31+
payer,
32+
owner,
33+
source_token_account,
34+
mint,
35+
1000, // amount
36+
recipient,
37+
output_state_tree,
38+
)
39+
.expect("Failed to create compress instruction");
40+
41+
println!("Created compress instruction:");
42+
println!(" Program ID: {}", instruction.program_id);
43+
println!(" Accounts: {} total", instruction.accounts.len());
44+
println!();
45+
}
46+
47+
fn batch_compress_example() {
48+
println!("=== Batch Compress Example ===");
49+
50+
let payer = Pubkey::new_unique();
51+
let owner = Pubkey::new_unique();
52+
let source_token_account = Pubkey::new_unique();
53+
let mint = Pubkey::new_unique();
54+
let output_state_tree = Pubkey::new_unique();
55+
56+
let recipients = vec![
57+
(Pubkey::new_unique(), 500),
58+
(Pubkey::new_unique(), 300),
59+
(Pubkey::new_unique(), 200),
60+
];
61+
62+
let _instruction = batch_compress(
63+
payer,
64+
owner,
65+
source_token_account,
66+
mint,
67+
recipients.clone(),
68+
output_state_tree,
69+
)
70+
.expect("Failed to create batch compress instruction");
71+
72+
println!(
73+
"Created batch compress instruction for {} recipients:",
74+
recipients.len()
75+
);
76+
for (recipient, amount) in recipients {
77+
println!(" {} -> {} tokens", recipient, amount);
78+
}
79+
println!();
80+
}
81+
82+
fn decompress_example() {
83+
println!("=== Decompress Example ===");
84+
85+
let payer = Pubkey::new_unique();
86+
let owner = Pubkey::new_unique();
87+
let mint = Pubkey::new_unique();
88+
let destination_token_account = Pubkey::new_unique();
89+
let merkle_tree = Pubkey::new_unique();
90+
let queue = Pubkey::new_unique();
91+
92+
// Create mock compressed account data
93+
let compressed_account = CompressedAccount {
94+
owner: light_compressed_token_client::PROGRAM_ID,
95+
lamports: 0,
96+
data: None,
97+
address: None,
98+
};
99+
100+
let token_data = TokenData {
101+
mint,
102+
owner,
103+
amount: 1000,
104+
delegate: None,
105+
state: AccountState::Initialized,
106+
tlv: None,
107+
};
108+
109+
let merkle_context = MerkleContext {
110+
merkle_tree_pubkey: merkle_tree,
111+
queue_pubkey: queue,
112+
leaf_index: 0,
113+
prove_by_index: false,
114+
tree_type: TreeType::StateV2,
115+
};
116+
117+
let params = DecompressParams {
118+
payer,
119+
input_compressed_token_accounts: vec![(compressed_account, token_data, merkle_context)],
120+
to_address: destination_token_account,
121+
amount: 500,
122+
recent_input_state_root_indices: vec![Some(0)],
123+
recent_validity_proof: None,
124+
output_state_tree: Some(merkle_tree),
125+
token_program_id: None,
126+
};
127+
128+
let instruction =
129+
create_decompress_instruction(params).expect("Failed to create decompress instruction");
130+
131+
println!("Created decompress instruction:");
132+
println!(" Program ID: {}", instruction.program_id);
133+
println!(" Decompressing 500 tokens (500 remain compressed)");
134+
println!();
135+
}

0 commit comments

Comments
 (0)