Skip to content

Commit 1fd9141

Browse files
committed
Cpi client and ix builder w/ proc macro support
1 parent 9225f0c commit 1fd9141

File tree

23 files changed

+759
-334
lines changed

23 files changed

+759
-334
lines changed

framework/example_programs/counter/src/lib.rs

Lines changed: 64 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use star_frame::anyhow::bail;
22
use star_frame::borsh::{BorshDeserialize, BorshSerialize};
33
use star_frame::derive_more::{Deref, DerefMut};
4+
use star_frame::empty_star_frame_instruction;
45
use star_frame::prelude::*;
56
use star_frame::solana_program::pubkey::Pubkey;
67

@@ -30,7 +31,6 @@ pub struct CreateCounterIx {
3031
}
3132

3233
#[derive(AccountSet)]
33-
// #[account_set(skip_default_account_set)]
3434
pub struct CreateCounterAccounts<'info> {
3535
#[account_set(funder)]
3636
pub funder: Signer<Mut<SystemAccount<'info>>>,
@@ -54,12 +54,7 @@ impl StarFrameInstruction for CreateCounterIx {
5454
type Accounts<'b, 'c, 'info> = CreateCounterAccounts<'info>;
5555

5656
fn split_to_args<'a>(r: &Self) -> IxArgs<Self> {
57-
IxArgs {
58-
decode: (),
59-
cleanup: (),
60-
run: &r.start_at,
61-
validate: (),
62-
}
57+
IxArgs::run(&r.start_at)
6358
}
6459

6560
fn run_instruction<'info>(
@@ -108,9 +103,7 @@ impl StarFrameInstruction for UpdateCounterSignerIx {
108103
type Accounts<'b, 'c, 'info> = UpdateCounterSignerAccounts<'info>;
109104

110105
fn split_to_args<'a>(_r: &Self) -> IxArgs<Self> {
111-
IxArgs {
112-
..Default::default()
113-
}
106+
IxArgs::default()
114107
}
115108

116109
fn run_instruction<'info>(
@@ -188,27 +181,7 @@ pub struct CloseCounterAccounts<'info> {
188181
#[cleanup(arg = CloseAccountAuto)]
189182
pub counter: Mut<WrappedCounter<'info>>,
190183
}
191-
192-
impl StarFrameInstruction for CloseCounterIx {
193-
type DecodeArg<'a> = ();
194-
type ValidateArg<'a> = ();
195-
type RunArg<'a> = ();
196-
type CleanupArg<'a> = ();
197-
type ReturnType = ();
198-
type Accounts<'b, 'c, 'info> = CloseCounterAccounts<'info>;
199-
200-
fn split_to_args<'a>(_r: &Self) -> IxArgs<Self> {
201-
Default::default()
202-
}
203-
204-
fn run_instruction<'info>(
205-
_account_set: &mut Self::Accounts<'_, '_, 'info>,
206-
_run_args: Self::RunArg<'_>,
207-
_syscalls: &mut impl SyscallInvoke<'info>,
208-
) -> Result<Self::ReturnType> {
209-
Ok(())
210-
}
211-
}
184+
empty_star_frame_instruction!(CloseCounterIx, CloseCounterAccounts);
212185

213186
#[derive(InstructionSet)]
214187
pub enum CounterInstructionSet {
@@ -228,16 +201,11 @@ pub struct CounterProgram;
228201
#[cfg(test)]
229202
mod tests {
230203
use super::*;
231-
use borsh::to_vec;
232204
use bytemuck::checked::try_from_bytes;
233205
use solana_program_test::*;
234-
use solana_sdk::instruction::Instruction as SolanaInstruction;
235206
use solana_sdk::signature::{Keypair, Signer};
236-
use solana_sdk::system_program;
237207
use solana_sdk::transaction::Transaction;
238-
use star_frame::itertools::Itertools;
239208
use star_frame::serde_json;
240-
use star_frame::solana_program::instruction::AccountMeta;
241209

242210
#[test]
243211
fn idl_test() {
@@ -246,7 +214,7 @@ mod tests {
246214
}
247215

248216
#[tokio::test]
249-
async fn test_that_it_works() {
217+
async fn test_that_it_works() -> Result<()> {
250218
let program_test = ProgramTest::new(
251219
"counter",
252220
CounterProgram::PROGRAM_ID,
@@ -263,160 +231,100 @@ mod tests {
263231
};
264232
let (counter_account, bump) =
265233
Pubkey::find_program_address(&seeds.seeds(), &StarFrameDeclaredProgram::PROGRAM_ID);
266-
let ix_data = [
267-
CreateCounterIx::DISCRIMINANT.to_vec(),
268-
to_vec(&CreateCounterIx { start_at }).unwrap(),
269-
]
270-
.into_iter()
271-
.flatten()
272-
.collect_vec();
273-
let instruction = SolanaInstruction::new_with_bytes(
274-
CounterProgram::PROGRAM_ID,
275-
&ix_data,
276-
vec![
277-
AccountMeta::new(payer.pubkey(), true),
278-
AccountMeta::new_readonly(account_key.pubkey(), false),
279-
AccountMeta::new(counter_account, false),
280-
AccountMeta::new_readonly(system_program::ID, false),
281-
],
282-
);
234+
235+
let instruction = CounterProgram::instruction(
236+
&CreateCounterIx { start_at },
237+
CreateCounterClientAccounts {
238+
funder: payer.pubkey(),
239+
owner: account_key.pubkey(),
240+
counter: counter_account,
241+
system_program: SystemProgram::PROGRAM_ID,
242+
},
243+
)?;
244+
283245
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
284246
transaction.sign(&[&payer], recent_blockhash);
285-
banks_client.process_transaction(transaction).await.unwrap();
247+
banks_client.process_transaction(transaction).await?;
286248
let expected = CounterAccount {
287249
version: 0,
288250
owner: account_key.pubkey(),
289251
signer: account_key.pubkey(),
290252
count: 2,
291253
bump,
292254
};
293-
let acc = banks_client
294-
.get_account(counter_account)
295-
.await
296-
.unwrap()
297-
.unwrap();
298-
assert_eq!(expected, *try_from_bytes(&acc.data[8..]).unwrap());
255+
let acc = banks_client.get_account(counter_account).await?.unwrap();
256+
assert_eq!(expected, *try_from_bytes(&acc.data[8..])?);
299257

300258
// Update a counter signer
301-
let ix_data2 = [
302-
UpdateCounterSignerIx::DISCRIMINANT.to_vec(),
303-
to_vec(&UpdateCounterSignerIx {}).unwrap(),
304-
]
305-
.into_iter()
306-
.flatten()
307-
.collect_vec();
308-
let instruction2 = SolanaInstruction::new_with_bytes(
309-
CounterProgram::PROGRAM_ID,
310-
&ix_data2,
311-
vec![
312-
AccountMeta::new_readonly(account_key.pubkey(), true),
313-
AccountMeta::new_readonly(account_key2.pubkey(), false),
314-
AccountMeta::new(counter_account, false),
315-
],
316-
);
259+
let instruction2 = CounterProgram::instruction(
260+
&UpdateCounterSignerIx,
261+
UpdateCounterSignerClientAccounts {
262+
signer: account_key.pubkey(),
263+
new_signer: account_key2.pubkey(),
264+
counter: counter_account,
265+
},
266+
)?;
317267
let mut transaction2 = Transaction::new_with_payer(&[instruction2], Some(&payer.pubkey()));
318268
transaction2.sign(&[&payer, &account_key], recent_blockhash);
319-
banks_client
320-
.process_transaction(transaction2)
321-
.await
322-
.unwrap();
323-
let acc2 = banks_client
324-
.get_account(counter_account)
325-
.await
326-
.unwrap()
327-
.unwrap();
328-
let acc2_data: CounterAccount = *try_from_bytes(&acc2.data[8..]).unwrap();
269+
banks_client.process_transaction(transaction2).await?;
270+
let acc2 = banks_client.get_account(counter_account).await?.unwrap();
271+
let acc2_data: CounterAccount = *try_from_bytes(&acc2.data[8..])?;
329272
assert_eq!(acc2_data.signer, account_key2.pubkey());
330273

331274
// Update count
332-
let count_accounts: Vec<AccountMeta> = vec![
333-
AccountMeta::new_readonly(account_key.pubkey(), true),
334-
AccountMeta::new(counter_account, false),
335-
];
336-
let ix_data3 = [
337-
CountIx::DISCRIMINANT.to_vec(),
338-
to_vec(&CountIx {
275+
let instruction3 = CounterProgram::instruction(
276+
&CountIx {
339277
amount: 7,
340278
subtract: false,
341-
})
342-
.unwrap(),
343-
]
344-
.into_iter()
345-
.flatten()
346-
.collect_vec();
347-
let ix_data4 = [
348-
CountIx::DISCRIMINANT.to_vec(),
349-
to_vec(&CountIx {
279+
},
280+
CountClientAccounts {
281+
owner: account_key.pubkey(),
282+
counter: counter_account,
283+
},
284+
)?;
285+
let instruction4 = CounterProgram::instruction(
286+
&CountIx {
350287
amount: 4,
351288
subtract: true,
352-
})
353-
.unwrap(),
354-
]
355-
.into_iter()
356-
.flatten()
357-
.collect_vec();
358-
let instruction3 = SolanaInstruction::new_with_bytes(
359-
CounterProgram::PROGRAM_ID,
360-
&ix_data3,
361-
count_accounts.clone(),
362-
);
363-
let instruction4 = SolanaInstruction::new_with_bytes(
364-
CounterProgram::PROGRAM_ID,
365-
&ix_data4,
366-
count_accounts.clone(),
367-
);
289+
},
290+
CountClientAccounts {
291+
owner: account_key.pubkey(),
292+
counter: counter_account,
293+
},
294+
)?;
295+
368296
let mut transaction3 =
369297
Transaction::new_with_payer(&[instruction3, instruction4], Some(&payer.pubkey()));
370298
transaction3.sign(&[&payer, &account_key], recent_blockhash);
371-
banks_client
372-
.process_transaction(transaction3)
373-
.await
374-
.unwrap();
375-
let acc3 = banks_client
376-
.get_account(counter_account)
377-
.await
378-
.unwrap()
379-
.unwrap();
380-
let acc3_data: CounterAccount = *try_from_bytes(&acc3.data[8..]).unwrap();
299+
banks_client.process_transaction(transaction3).await?;
300+
let acc3 = banks_client.get_account(counter_account).await?.unwrap();
301+
let acc3_data: CounterAccount = *try_from_bytes(&acc3.data[8..])?;
381302
let old_count = acc2_data.count;
382303
let new_count = acc3_data.count;
383304
assert_eq!(new_count, old_count + 7 - 4);
384305

385306
// Close counter
386-
let refund_acc = banks_client
387-
.get_account(account_key.pubkey())
388-
.await
389-
.unwrap();
307+
let refund_acc = banks_client.get_account(account_key.pubkey()).await?;
390308
assert!(refund_acc.is_none());
391-
let ix_data5 = [
392-
CloseCounterIx::DISCRIMINANT.to_vec(),
393-
to_vec(&CloseCounterIx {}).unwrap(),
394-
]
395-
.into_iter()
396-
.flatten()
397-
.collect_vec();
398-
let instruction5 = SolanaInstruction::new_with_bytes(
399-
CounterProgram::PROGRAM_ID,
400-
&ix_data5,
401-
vec![
402-
AccountMeta::new_readonly(account_key2.pubkey(), true),
403-
AccountMeta::new(account_key.pubkey(), false),
404-
AccountMeta::new(counter_account, false),
405-
],
406-
);
309+
let instruction5 = CounterProgram::instruction(
310+
&CloseCounterIx,
311+
CloseCounterClientAccounts {
312+
signer: account_key2.pubkey(),
313+
funds_to: account_key.pubkey(),
314+
counter: counter_account,
315+
},
316+
)?;
317+
407318
let mut transaction5 = Transaction::new_with_payer(&[instruction5], Some(&payer.pubkey()));
408319
transaction5.sign(&[&payer, &account_key2], recent_blockhash);
409-
banks_client
410-
.process_transaction(transaction5)
411-
.await
412-
.unwrap();
413-
let acc5 = banks_client.get_account(counter_account).await.unwrap();
320+
banks_client.process_transaction(transaction5).await?;
321+
let acc5 = banks_client.get_account(counter_account).await?;
414322
assert!(acc5.is_none());
415323
let refund_acc2 = banks_client
416324
.get_account(account_key.pubkey())
417-
.await
418-
.unwrap()
325+
.await?
419326
.unwrap();
420327
assert_eq!(refund_acc2.lamports, acc3.lamports);
328+
Ok(())
421329
}
422330
}

framework/example_programs/faction_enlistment/src/lib.rs

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ pub struct ProcessEnlistPlayerIx {
4141
impl StarFrameInstruction for ProcessEnlistPlayerIx {
4242
type DecodeArg<'a> = ();
4343
type ValidateArg<'a> = ();
44+
type RunArg<'a> = FactionId;
4445
type CleanupArg<'a> = ();
4546
type ReturnType = ();
46-
type RunArg<'a> = FactionId;
4747
type Accounts<'b, 'c, 'info> = ProcessEnlistPlayer<'info>;
4848

4949
fn split_to_args<'a>(r: &Self) -> IxArgs<Self> {
@@ -140,9 +140,7 @@ mod tests {
140140
use solana_sdk::account::Account;
141141
use solana_sdk::clock::Clock;
142142
use solana_sdk::signature::{Keypair, Signer};
143-
use star_frame::borsh::to_vec;
144-
use star_frame::itertools::Itertools;
145-
use star_frame::solana_program::instruction::AccountMeta;
143+
use solana_sdk::system_program;
146144
use star_frame::solana_program::native_token::LAMPORTS_PER_SOL;
147145

148146
#[test]
@@ -151,11 +149,6 @@ mod tests {
151149
println!("{}", serde_json::to_string_pretty(&idl).unwrap());
152150
}
153151

154-
#[test]
155-
fn info_size() {
156-
println!("{}", std::mem::size_of::<AccountInfo>());
157-
}
158-
159152
#[tokio::test]
160153
async fn banks_test() -> Result<()> {
161154
const SBF_FILE: bool = false;
@@ -201,28 +194,15 @@ mod tests {
201194

202195
let faction_id = FactionId::MUD;
203196

204-
let enlist_ix = ProcessEnlistPlayerIx {
205-
bump,
206-
faction_id,
207-
// buncha_data,
208-
};
209-
let ix_data = [
210-
ProcessEnlistPlayerIx::DISCRIMINANT.to_vec(),
211-
to_vec(&enlist_ix)?,
212-
]
213-
.into_iter()
214-
.flatten()
215-
.collect_vec();
216-
let accounts = vec![
217-
AccountMeta::new(faction_account, false),
218-
AccountMeta::new(player_account.pubkey(), true),
219-
AccountMeta::new_readonly(solana_sdk::system_program::id(), false),
220-
];
221-
let ix = solana_sdk::instruction::Instruction::new_with_bytes(
222-
FactionEnlistment::PROGRAM_ID,
223-
&ix_data,
224-
accounts,
225-
);
197+
let ix = FactionEnlistment::instruction(
198+
&ProcessEnlistPlayerIx { bump, faction_id },
199+
ProcessEnlistPlayerClientAccounts {
200+
player_faction_account: faction_account,
201+
player_account: player_account.pubkey(),
202+
system_program: system_program::ID,
203+
},
204+
)?;
205+
226206
let mut tx = solana_sdk::transaction::Transaction::new_with_payer(
227207
&[ix],
228208
Some(&player_account.pubkey()),

0 commit comments

Comments
 (0)