@@ -62,13 +62,12 @@ pub struct DecompressParams {
62
62
63
63
/// Create a compress instruction
64
64
///
65
- /// This instruction transfers tokens from an SPL token account to compressed token accounts .
65
+ /// This instruction compresses tokens from an SPL token account to N recipients .
66
66
pub fn create_compress_instruction (
67
67
params : CompressParams ,
68
68
) -> Result < Instruction , CompressedTokenError > {
69
69
let token_program = params. token_program_id . unwrap_or ( anchor_spl:: token:: ID ) ;
70
70
71
- // Create output compressed accounts
72
71
let output_compressed_accounts = if let Some ( ref batch_recipients) = params. batch_recipients {
73
72
batch_recipients
74
73
. iter ( )
@@ -87,32 +86,30 @@ pub fn create_compress_instruction(
87
86
merkle_tree: params. output_state_tree,
88
87
} ]
89
88
} ;
90
-
91
- // Calculate total amount
92
89
let total_amount: u64 = output_compressed_accounts. iter ( ) . map ( |x| x. amount ) . sum ( ) ;
93
90
94
- // Create the instruction using the transfer SDK
95
- let mut ix = match transfer_sdk:: create_transfer_instruction (
91
+ // TODO: refactor.
92
+ let ix = match transfer_sdk:: create_transfer_instruction (
96
93
& params. payer ,
97
94
& params. owner ,
98
- & [ ] , // empty input merkle context for compression
95
+ & [ ] ,
99
96
& output_compressed_accounts,
100
- & [ ] , // empty root indices for compression
101
- & None , // no proof needed for compression
102
- & [ ] , // empty input token data for compression
103
- & [ ] , // empty input compressed accounts for compression
97
+ & [ ] ,
98
+ & None ,
99
+ & [ ] ,
100
+ & [ ] ,
104
101
params. mint ,
105
- None , // no delegate
106
- true , // is_compress = true
107
- Some ( total_amount) , // compress_or_decompress_amount
108
- Some ( crate :: get_token_pool_pda ( & params. mint ) ) , // token_pool_pda
109
- Some ( params. source ) , // compress_or_decompress_token_account
110
- false , // don't sort outputs
111
- None , // no delegate change account
112
- None , // no lamports change account
113
- token_program == spl_token_2022:: ID , // is_token_22
114
- & [ ] , // no additional token pools
115
- false , // with_transaction_hash = false
102
+ None ,
103
+ true ,
104
+ Some ( total_amount) ,
105
+ Some ( crate :: get_token_pool_pda ( & params. mint ) ) ,
106
+ Some ( params. source ) ,
107
+ false ,
108
+ None ,
109
+ None ,
110
+ token_program == spl_token_2022:: ID ,
111
+ & [ ] ,
112
+ false ,
116
113
) {
117
114
Ok ( ix) => ix,
118
115
Err ( e) => {
@@ -128,7 +125,7 @@ pub fn create_compress_instruction(
128
125
129
126
/// Create a decompress instruction
130
127
///
131
- /// This instruction transfers tokens from compressed token accounts to an SPL token account.
128
+ /// This instruction decompresses compressed tokens to an SPL token account.
132
129
pub fn create_decompress_instruction (
133
130
params : DecompressParams ,
134
131
) -> Result < Instruction , CompressedTokenError > {
@@ -140,7 +137,6 @@ pub fn create_decompress_instruction(
140
137
141
138
let token_program = params. token_program_id . unwrap_or ( anchor_spl:: token:: ID ) ;
142
139
143
- // Extract components from input accounts
144
140
let ( compressed_accounts, token_data, merkle_contexts) : ( Vec < _ > , Vec < _ > , Vec < _ > ) = params
145
141
. input_compressed_token_accounts
146
142
. into_iter ( )
@@ -155,13 +151,9 @@ pub fn create_decompress_instruction(
155
151
} ,
156
152
) ;
157
153
158
- // Get mint from first token data
159
154
let mint = token_data[ 0 ] . mint ;
160
-
161
- // Get owner from first token data
162
155
let owner = token_data[ 0 ] . owner ;
163
156
164
- // Create output state for remaining tokens (if any)
165
157
let input_total: u64 = token_data. iter ( ) . map ( |td| td. amount ) . sum ( ) ;
166
158
let remaining_amount = input_total. saturating_sub ( params. amount ) ;
167
159
@@ -178,7 +170,7 @@ pub fn create_decompress_instruction(
178
170
vec ! [ ]
179
171
} ;
180
172
181
- // Create the instruction using the transfer SDK
173
+ // TODO: refactor.
182
174
transfer_sdk:: create_transfer_instruction (
183
175
& params. payer ,
184
176
& owner,
@@ -189,26 +181,24 @@ pub fn create_decompress_instruction(
189
181
& token_data,
190
182
& compressed_accounts,
191
183
mint,
192
- None , // no delegate
193
- false , // is_compress = false
194
- Some ( params. amount ) , // compress_or_decompress_amount
195
- Some ( crate :: get_token_pool_pda ( & mint) ) , // token_pool_pda
196
- Some ( params. to_address ) , // compress_or_decompress_token_account
197
- false , // don't sort outputs
198
- None , // no delegate change account
199
- None , // no lamports change account
200
- token_program == spl_token_2022:: ID , // is_token_22
201
- & [ ] , // no additional token pools
202
- false , // with_transaction_hash = false
184
+ None ,
185
+ false ,
186
+ Some ( params. amount ) ,
187
+ Some ( crate :: get_token_pool_pda ( & mint) ) ,
188
+ Some ( params. to_address ) ,
189
+ false ,
190
+ None ,
191
+ None ,
192
+ token_program == spl_token_2022:: ID ,
193
+ & [ ] ,
194
+ false ,
203
195
)
204
196
. map_err ( |e| {
205
197
CompressedTokenError :: SerializationError ( format ! ( "Failed to create instruction: {:?}" , e) )
206
198
} )
207
199
}
208
200
209
- /// Helper function to create a simple compress instruction
210
- ///
211
- /// This is a convenience function for the most common compress use case.
201
+ /// Create a compress instruction with a single recipient.
212
202
pub fn compress (
213
203
payer : Pubkey ,
214
204
owner : Pubkey ,
@@ -231,27 +221,32 @@ pub fn compress(
231
221
} )
232
222
}
233
223
234
- /// Helper function to create a batch compress instruction
235
- ///
236
- /// Compress tokens to multiple recipients in a single transaction.
224
+ /// Creates a compress instruction to compress tokens to multiple recipients.
237
225
pub fn batch_compress (
238
226
payer : Pubkey ,
239
227
owner : Pubkey ,
240
228
source_token_account : Pubkey ,
241
229
mint : Pubkey ,
242
- recipients : Vec < ( Pubkey , u64 ) > ,
230
+ recipients : Vec < Pubkey > ,
231
+ amounts : Vec < u64 > ,
243
232
output_state_tree : Pubkey ,
244
233
) -> Result < Instruction , CompressedTokenError > {
234
+ if recipients. len ( ) != amounts. len ( ) {
235
+ return Err ( CompressedTokenError :: InvalidParams (
236
+ "Recipients and amounts must have the same length" . to_string ( ) ,
237
+ ) ) ;
238
+ }
239
+
245
240
create_compress_instruction ( CompressParams {
246
241
payer,
247
242
owner,
248
243
source : source_token_account,
249
- to_address : Pubkey :: default ( ) , // Not used in batch mode
244
+ to_address : Pubkey :: default ( ) ,
250
245
mint,
251
- amount : 0 , // Not used in batch mode
246
+ amount : 0 ,
252
247
output_state_tree,
253
248
token_program_id : None ,
254
- batch_recipients : Some ( recipients) ,
249
+ batch_recipients : Some ( recipients. into_iter ( ) . zip ( amounts ) . collect ( ) ) ,
255
250
} )
256
251
}
257
252
@@ -293,12 +288,21 @@ mod tests {
293
288
let output_state_tree = Pubkey :: new_unique ( ) ;
294
289
295
290
let recipients = vec ! [
296
- ( Pubkey :: new_unique( ) , 500 ) ,
297
- ( Pubkey :: new_unique( ) , 300 ) ,
298
- ( Pubkey :: new_unique( ) , 200 ) ,
291
+ Pubkey :: new_unique( ) ,
292
+ Pubkey :: new_unique( ) ,
293
+ Pubkey :: new_unique( ) ,
299
294
] ;
295
+ let amounts = vec ! [ 500 , 300 , 200 ] ;
300
296
301
- let result = batch_compress ( payer, owner, source, mint, recipients, output_state_tree) ;
297
+ let result = batch_compress (
298
+ payer,
299
+ owner,
300
+ source,
301
+ mint,
302
+ recipients,
303
+ amounts,
304
+ output_state_tree,
305
+ ) ;
302
306
303
307
assert ! ( result. is_ok( ) ) ;
304
308
let instruction = result. unwrap ( ) ;
0 commit comments