@@ -4,67 +4,90 @@ use solana_pubkey::Pubkey;
4
4
use crate :: instructions:: CTokenDefaultAccounts ;
5
5
6
6
/// Account metadata configuration for batch compress instruction
7
- #[ derive( Debug , Default , Copy , Clone ) ]
7
+ #[ derive( Debug , Copy , Clone ) ]
8
8
pub struct BatchCompressMetaConfig {
9
9
pub fee_payer : Option < Pubkey > ,
10
10
pub authority : Option < Pubkey > ,
11
- pub token_pool_pda : Option < Pubkey > ,
12
- pub sender_token_account : Option < Pubkey > ,
13
- pub token_program : Option < Pubkey > ,
14
- pub merkle_tree : Option < Pubkey > ,
11
+ pub token_pool_pda : Pubkey ,
12
+ pub sender_token_account : Pubkey ,
13
+ pub token_program : Pubkey ,
14
+ pub merkle_tree : Pubkey ,
15
15
pub sol_pool_pda : Option < Pubkey > ,
16
16
}
17
17
18
18
impl BatchCompressMetaConfig {
19
+ /// Create a new BatchCompressMetaConfig for direct invocation
19
20
pub fn new (
20
21
fee_payer : Pubkey ,
21
22
authority : Pubkey ,
22
23
token_pool_pda : Pubkey ,
23
24
sender_token_account : Pubkey ,
24
25
token_program : Pubkey ,
25
26
merkle_tree : Pubkey ,
27
+ with_lamports : bool ,
26
28
) -> Self {
29
+ let sol_pool_pda = if with_lamports {
30
+ unimplemented ! ( "TODO hardcode sol pool pda" )
31
+ } else {
32
+ None
33
+ } ;
27
34
Self {
28
35
fee_payer : Some ( fee_payer) ,
29
36
authority : Some ( authority) ,
30
- token_pool_pda : Some ( token_pool_pda ) ,
31
- sender_token_account : Some ( sender_token_account ) ,
32
- token_program : Some ( token_program ) ,
33
- merkle_tree : Some ( merkle_tree ) ,
34
- sol_pool_pda : None ,
37
+ token_pool_pda,
38
+ sender_token_account,
39
+ token_program,
40
+ merkle_tree,
41
+ sol_pool_pda,
35
42
}
36
43
}
37
44
45
+ /// Create a new BatchCompressMetaConfig for client-side (CPI) usage
38
46
pub fn new_client (
39
47
token_pool_pda : Pubkey ,
40
48
sender_token_account : Pubkey ,
41
49
token_program : Pubkey ,
42
50
merkle_tree : Pubkey ,
51
+ with_lamports : bool ,
43
52
) -> Self {
53
+ let sol_pool_pda = if with_lamports {
54
+ unimplemented ! ( "TODO hardcode sol pool pda" )
55
+ } else {
56
+ None
57
+ } ;
44
58
Self {
45
59
fee_payer : None ,
46
60
authority : None ,
47
- token_pool_pda : Some ( token_pool_pda ) ,
48
- sender_token_account : Some ( sender_token_account ) ,
49
- token_program : Some ( token_program ) ,
50
- merkle_tree : Some ( merkle_tree ) ,
51
- sol_pool_pda : None ,
61
+ token_pool_pda,
62
+ sender_token_account,
63
+ token_program,
64
+ merkle_tree,
65
+ sol_pool_pda,
52
66
}
53
67
}
54
-
55
- pub fn with_sol_pool_pda ( mut self , sol_pool_pda : Pubkey ) -> Self {
56
- self . sol_pool_pda = Some ( sol_pool_pda) ;
57
- self
58
- }
59
68
}
60
69
61
70
/// Get the standard account metas for a batch compress instruction
62
71
/// Matches the MintToInstruction account structure used by batch_compress
63
- pub fn get_batch_compress_instruction_account_metas ( config : BatchCompressMetaConfig ) -> Vec < AccountMeta > {
72
+ pub fn get_batch_compress_instruction_account_metas (
73
+ config : BatchCompressMetaConfig ,
74
+ ) -> Vec < AccountMeta > {
64
75
let default_pubkeys = CTokenDefaultAccounts :: default ( ) ;
65
-
76
+
77
+ // Calculate capacity based on whether fee_payer is provided
78
+ // Base accounts: cpi_authority_pda + token_pool_pda + token_program + light_system_program +
79
+ // registered_program_pda + noop_program + account_compression_authority +
80
+ // account_compression_program + merkle_tree +
81
+ // self_program + system_program
82
+ let base_capacity = 10 ;
83
+
84
+ // Direct invoke accounts: fee_payer + authority + mint_placeholder + sol_pool_pda_or_placeholder
85
+ let fee_payer_capacity = if config. fee_payer . is_some ( ) { 4 } else { 0 } ;
86
+
87
+ let total_capacity = base_capacity + fee_payer_capacity;
88
+
66
89
// Start building the account metas to match MintToInstruction structure
67
- let mut metas = Vec :: new ( ) ;
90
+ let mut metas = Vec :: with_capacity ( total_capacity ) ;
68
91
69
92
// Add fee_payer and authority if provided (for direct invoke)
70
93
if let Some ( fee_payer) = config. fee_payer {
@@ -78,51 +101,79 @@ pub fn get_batch_compress_instruction_account_metas(config: BatchCompressMetaCon
78
101
}
79
102
80
103
// cpi_authority_pda
81
- metas. push ( AccountMeta :: new_readonly ( default_pubkeys. cpi_authority_pda , false ) ) ;
82
-
83
- // mint: Option<UncheckedAccount> - None for batch_compress, so we skip this account
84
-
104
+ metas. push ( AccountMeta :: new_readonly (
105
+ default_pubkeys. cpi_authority_pda ,
106
+ false ,
107
+ ) ) ;
108
+
109
+ // mint: Option<UncheckedAccount> - Always None for batch_compress, so we add a placeholder
110
+ if config. fee_payer . is_some ( ) {
111
+ metas. push ( AccountMeta :: new_readonly (
112
+ default_pubkeys. compressed_token_program ,
113
+ false ,
114
+ ) ) ;
115
+ }
116
+
85
117
// token_pool_pda (mut)
86
- let token_pool_pda = config. token_pool_pda . expect ( "Missing token_pool_pda" ) ;
87
- metas. push ( AccountMeta :: new ( token_pool_pda, false ) ) ;
88
-
118
+ metas. push ( AccountMeta :: new ( config. token_pool_pda , false ) ) ;
119
+
89
120
// token_program
90
- let token_program = config. token_program . expect ( "Missing token_program" ) ;
91
- metas. push ( AccountMeta :: new_readonly ( token_program, false ) ) ;
92
-
121
+ metas. push ( AccountMeta :: new_readonly ( config. token_program , false ) ) ;
122
+
93
123
// light_system_program
94
- metas. push ( AccountMeta :: new_readonly ( default_pubkeys. light_system_program , false ) ) ;
95
-
124
+ metas. push ( AccountMeta :: new_readonly (
125
+ default_pubkeys. light_system_program ,
126
+ false ,
127
+ ) ) ;
128
+
96
129
// registered_program_pda
97
- metas. push ( AccountMeta :: new_readonly ( default_pubkeys. registered_program_pda , false ) ) ;
98
-
130
+ metas. push ( AccountMeta :: new_readonly (
131
+ default_pubkeys. registered_program_pda ,
132
+ false ,
133
+ ) ) ;
134
+
99
135
// noop_program
100
- metas. push ( AccountMeta :: new_readonly ( default_pubkeys. noop_program , false ) ) ;
101
-
102
- // account_compression_authority
103
- metas. push ( AccountMeta :: new_readonly ( default_pubkeys. account_compression_authority , false ) ) ;
104
-
136
+ metas. push ( AccountMeta :: new_readonly (
137
+ default_pubkeys. noop_program ,
138
+ false ,
139
+ ) ) ;
140
+
141
+ // account_compression_authority
142
+ metas. push ( AccountMeta :: new_readonly (
143
+ default_pubkeys. account_compression_authority ,
144
+ false ,
145
+ ) ) ;
146
+
105
147
// account_compression_program
106
- metas. push ( AccountMeta :: new_readonly ( default_pubkeys. account_compression_program , false ) ) ;
107
-
148
+ metas. push ( AccountMeta :: new_readonly (
149
+ default_pubkeys. account_compression_program ,
150
+ false ,
151
+ ) ) ;
152
+
108
153
// merkle_tree (mut)
109
- let merkle_tree = config. merkle_tree . expect ( "Missing merkle_tree" ) ;
110
- metas. push ( AccountMeta :: new ( merkle_tree, false ) ) ;
111
-
154
+ metas. push ( AccountMeta :: new ( config. merkle_tree , false ) ) ;
155
+
112
156
// self_program (compressed token program)
113
- metas. push ( AccountMeta :: new_readonly ( default_pubkeys. self_program , false ) ) ;
114
-
157
+ metas. push ( AccountMeta :: new_readonly (
158
+ default_pubkeys. self_program ,
159
+ false ,
160
+ ) ) ;
161
+
115
162
// system_program
116
- metas. push ( AccountMeta :: new_readonly ( default_pubkeys. system_program , false ) ) ;
117
-
118
- // sol_pool_pda (optional, mut)
163
+ metas. push ( AccountMeta :: new_readonly (
164
+ default_pubkeys. system_program ,
165
+ false ,
166
+ ) ) ;
167
+
168
+ // sol_pool_pda (optional, mut) - add placeholder if None but fee_payer is present
119
169
if let Some ( sol_pool_pda) = config. sol_pool_pda {
120
170
metas. push ( AccountMeta :: new ( sol_pool_pda, false ) ) ;
171
+ } else if config. fee_payer . is_some ( ) {
172
+ metas. push ( AccountMeta :: new_readonly (
173
+ default_pubkeys. compressed_token_program ,
174
+ false ,
175
+ ) ) ;
121
176
}
122
-
123
- // Remaining accounts: sender_token_account (first remaining account for batch_compress)
124
- let sender_token_account = config. sender_token_account . expect ( "Missing sender_token_account" ) ;
125
- metas. push ( AccountMeta :: new ( sender_token_account, false ) ) ;
126
177
127
178
metas
128
179
}
0 commit comments