Skip to content

Commit f2236d8

Browse files
authored
Merge pull request #86 from staratlasmeta/stegaBOB/feat/spl-part-2
Feat: spl part 2
2 parents b2e97b4 + 84791d2 commit f2236d8

File tree

27 files changed

+567
-470
lines changed

27 files changed

+567
-470
lines changed

Cargo.lock

Lines changed: 21 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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ strum = { version = "0.26.2", features = ["derive"] }
6767
syn = { version = "2.0.40", features = ["extra-traits"] }
6868
tokio = "1.41.1"
6969
typenum = "1.17.0"
70+
ref-cast = "1.0"
7071

7172
[profile.release]
7273
overflow-checks = true

framework/example_programs/faction_enlistment/src/lib.rs

Lines changed: 21 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
// #![allow(clippy::result_large_err)]
2-
31
use star_frame::borsh;
42
use star_frame::borsh::{BorshDeserialize, BorshSerialize};
53
use star_frame::prelude::*;
4+
use star_frame_spl::associated_token::AssociatedTokenAccount;
65
use star_frame_spl::associated_token::AssociatedTokenProgram;
7-
use star_frame_spl::token::{InitMint, MintAccount, TokenProgram};
6+
use star_frame_spl::associated_token::InitAta;
7+
use star_frame_spl::token::InitMint;
8+
use star_frame_spl::token::{MintAccount, TokenProgram};
89

910
#[derive(StarFrameProgram)]
1011
#[program(
@@ -65,29 +66,6 @@ impl StarFrameInstruction for ProcessEnlistPlayerIx {
6566
bump,
6667
_padding: [0; 5],
6768
};
68-
<Init<Signer<MintAccount<'info>>>>::try_from_account_with_args(
69-
&account_set.mint,
70-
(),
71-
Create(InitMint {
72-
decimals: 0,
73-
mint_authority: *account_set.player_account.key(),
74-
freeze_authority: None,
75-
}),
76-
syscalls,
77-
)?;
78-
// AssociatedTokenProgram::cpi(
79-
// &associated_token::Create,
80-
// associated_token::CreateCpiAccounts {
81-
// funder: syscalls.get_funder().unwrap().account_info_cloned(),
82-
// // token_account: account_set.token_account.account_info_cloned(),
83-
// wallet: account_set.player_account.account_info_cloned(),
84-
// mint: account_set.mint.account_info_cloned(),
85-
// system_program: account_set.system_program.account_info_cloned(),
86-
// token_program: account_set.token_program.account_info_cloned(),
87-
// },
88-
// )?
89-
// .invoke(syscalls)?;
90-
9169
Ok(())
9270
}
9371
}
@@ -112,18 +90,19 @@ pub struct ProcessEnlistPlayer<'info> {
11290
pub system_program: Program<'info, SystemProgram>,
11391
pub token_program: Program<'info, TokenProgram>,
11492
pub associated_token_program: Program<'info, AssociatedTokenProgram>,
115-
pub mint: Signer<AccountInfo<'info>>,
116-
// #[validate(arg = Create(InitMint {
117-
// decimals: 0,
118-
// mint_authority: *self.player_account.key(),
119-
// freeze_authority: None,
120-
// }))]
121-
// pub mint: Init<Signer<MintAccount<'info>>>,
122-
// #[validate(arg = Create(InitTokenAccount {
123-
// mint: *self.mint.key(),
124-
// owner: *self.player_account.key(),
125-
// }))]
126-
// pub token_account: Init<Mut<TokenAccount<'info>>>,
93+
#[validate(arg = Create(InitMint {
94+
decimals: 0,
95+
mint_authority: self.player_account.key(),
96+
freeze_authority: Some(self.player_account.key()),
97+
}))]
98+
pub mint: Init<Signer<MintAccount<'info>>>,
99+
#[validate(arg = Create(InitAta {
100+
wallet: &self.player_account,
101+
mint: &self.mint,
102+
system_program: &self.system_program,
103+
token_program: &self.token_program
104+
}))]
105+
pub token_account: Init<AssociatedTokenAccount<'info>>,
127106
}
128107

129108
#[derive(
@@ -178,7 +157,6 @@ mod tests {
178157
use solana_sdk::clock::Clock;
179158
use solana_sdk::signature::{Keypair, Signer};
180159
use star_frame::solana_program::native_token::LAMPORTS_PER_SOL;
181-
use star_frame_spl::associated_token::AssociatedTokenProgram;
182160
use star_frame_spl::token::TokenProgram;
183161

184162
#[cfg(feature = "idl")]
@@ -236,8 +214,8 @@ mod tests {
236214
let faction_id = FactionId::MUD;
237215

238216
let mint_keypair = Keypair::new();
239-
// let token_account =
240-
// AssociatedTokenProgram::find_address(&player_account.pubkey(), &mint_keypair.pubkey());
217+
let token_account =
218+
AssociatedTokenProgram::find_address(&player_account.pubkey(), &mint_keypair.pubkey());
241219

242220
let ix = FactionEnlistment::instruction(
243221
&ProcessEnlistPlayerIx { bump, faction_id },
@@ -248,7 +226,7 @@ mod tests {
248226
token_program: TokenProgram::PROGRAM_ID,
249227
associated_token_program: AssociatedTokenProgram::PROGRAM_ID,
250228
mint: mint_keypair.pubkey(),
251-
// token_account,
229+
token_account,
252230
},
253231
)?;
254232

@@ -265,7 +243,7 @@ mod tests {
265243
.process_transaction_with_metadata(tx.clone())
266244
.await?;
267245

268-
println!("{:?}", txn);
246+
println!("{:#?}", txn);
269247

270248
let clock = banks_client.get_sysvar::<Clock>().await?;
271249
let expected_faction_account = PlayerFactionData {

framework/star_frame/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ solana-program = { workspace = true }
2727
star_frame_proc = { workspace = true }
2828
static_assertions = { workspace = true }
2929
typenum = { workspace = true }
30+
ref-cast.workspace = true
3031

3132
# feature = idl
3233
serde = { workspace = true, features = ["derive"] }

framework/star_frame/src/account_set/data_account.rs

Lines changed: 31 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,10 @@ where
125125
{
126126
/// Validates the owner and the discriminant of the account.
127127
pub fn validate(&self) -> Result<()> {
128-
if self.info.owner != &T::OwnerProgram::PROGRAM_ID {
128+
if self.owner() != &T::OwnerProgram::PROGRAM_ID {
129129
bail!(ProgramError::IllegalOwner);
130130
}
131-
let data = self.info.try_borrow_data()?;
132-
131+
let data = self.info_data_bytes()?;
133132
Self::check_discriminant(&data)?;
134133
Ok(())
135134
}
@@ -146,10 +145,10 @@ where
146145
}
147146

148147
pub fn data<'a>(&'a self) -> Result<RefWrapper<AccountInfoRef<'a>, T::RefData>> {
149-
let r: Ref<'a, _> = self.info.try_borrow_data()?;
148+
let r: Ref<'a, _> = self.info_data_bytes()?;
150149
Self::check_discriminant(&r)?;
151150
let r = try_map_ref(r, |bytes| {
152-
let bytes = &mut &**bytes;
151+
let bytes = &mut &*bytes;
153152
bytes.try_advance(size_of::<
154153
<T::OwnerProgram as StarFrameProgram>::AccountDiscriminant,
155154
>())?;
@@ -162,7 +161,7 @@ where
162161
pub fn data_mut<'a>(
163162
&'a mut self,
164163
) -> Result<RefWrapper<AccountInfoRefMut<'a, 'info, T::OwnerProgram>, T::RefData>> {
165-
let r: RefMut<'a, _> = self.info.try_borrow_mut_data()?;
164+
let r: RefMut<'a, _> = self.info_data_bytes_mut()?;
166165
Self::check_discriminant(&r)?;
167166
let account_info_ref_mut = AccountInfoRefMut {
168167
account_info: &self.info,
@@ -210,111 +209,63 @@ where
210209
type Seeds = T::Seeds;
211210
}
212211

213-
impl<'info, T: ProgramAccount + UnsizedType + ?Sized> CanInitAccount<'info, CreateIfNeeded<()>>
212+
impl<'info, T: ProgramAccount + UnsizedType + ?Sized> CanInitAccount<'info, ()>
214213
for DataAccount<'info, T>
215214
where
216215
T: UnsizedInit<Zeroed>,
217216
{
218-
fn init_account(
219-
&mut self,
220-
_arg: CreateIfNeeded<()>,
221-
syscalls: &impl SyscallInvoke<'info>,
222-
account_seeds: Option<Vec<&[u8]>>,
223-
) -> Result<()> {
224-
self.init_account(CreateIfNeeded((Zeroed,)), syscalls, account_seeds)
225-
}
226-
}
227-
228-
impl<'info, T: ProgramAccount + UnsizedType + ?Sized, InitArg>
229-
CanInitAccount<'info, CreateIfNeeded<(InitArg,)>> for DataAccount<'info, T>
230-
where
231-
T: UnsizedInit<InitArg>,
232-
{
233-
fn init_account(
217+
fn init_account<const IF_NEEDED: bool>(
234218
&mut self,
235-
arg: CreateIfNeeded<(InitArg,)>,
236-
syscalls: &impl SyscallInvoke<'info>,
219+
_arg: (),
237220
account_seeds: Option<Vec<&[u8]>>,
238-
) -> Result<()> {
239-
let funder = syscalls
240-
.get_funder()
241-
.context("Missing `funder` for `CreateIfNeeded`")?;
242-
self.init_account(CreateIfNeeded((arg.0 .0, funder)), syscalls, account_seeds)
243-
}
244-
}
245-
246-
impl<'info, T: ProgramAccount + UnsizedType + ?Sized, InitArg, Funder>
247-
CanInitAccount<'info, CreateIfNeeded<(InitArg, &Funder)>> for DataAccount<'info, T>
248-
where
249-
T: UnsizedInit<InitArg>,
250-
Funder: SignedAccount<'info> + WritableAccount<'info>,
251-
{
252-
fn init_account(
253-
&mut self,
254-
arg: CreateIfNeeded<(InitArg, &Funder)>,
255221
syscalls: &impl SyscallInvoke<'info>,
256-
account_seeds: Option<Vec<&[u8]>>,
257222
) -> Result<()> {
258-
if self.owner() == &SystemProgram::PROGRAM_ID
259-
|| self.account_info().data.borrow_mut()
260-
[..size_of::<<T::OwnerProgram as StarFrameProgram>::AccountDiscriminant>()]
261-
.iter()
262-
.all(|x| *x == 0)
263-
{
264-
self.init_account(Create(arg.0), syscalls, account_seeds)?;
265-
}
266-
Ok(())
223+
self.init_account::<IF_NEEDED>((Zeroed,), account_seeds, syscalls)
267224
}
268225
}
269226

270-
impl<'info, T: ProgramAccount + UnsizedType + ?Sized> CanInitAccount<'info, Create<()>>
227+
impl<'info, T: ProgramAccount + UnsizedType + ?Sized, InitArg> CanInitAccount<'info, (InitArg,)>
271228
for DataAccount<'info, T>
272-
where
273-
T: UnsizedInit<Zeroed>,
274-
{
275-
fn init_account(
276-
&mut self,
277-
_arg: Create<()>,
278-
syscalls: &impl SyscallInvoke<'info>,
279-
account_seeds: Option<Vec<&[u8]>>,
280-
) -> Result<()> {
281-
self.init_account(Create((Zeroed,)), syscalls, account_seeds)
282-
}
283-
}
284-
285-
impl<'info, T: ProgramAccount + UnsizedType + ?Sized, InitArg>
286-
CanInitAccount<'info, Create<(InitArg,)>> for DataAccount<'info, T>
287229
where
288230
T: UnsizedInit<InitArg>,
289231
{
290-
fn init_account(
232+
fn init_account<const IF_NEEDED: bool>(
291233
&mut self,
292-
arg: Create<(InitArg,)>,
293-
syscalls: &impl SyscallInvoke<'info>,
234+
arg: (InitArg,),
294235
account_seeds: Option<Vec<&[u8]>>,
236+
syscalls: &impl SyscallInvoke<'info>,
295237
) -> Result<()> {
296238
let funder = syscalls
297239
.get_funder()
298-
.context("Missing `funder` for `Create`")?;
299-
self.init_account(Create((arg.0 .0, funder)), syscalls, account_seeds)
240+
.context("Missing tagged `funder` for DataAccount `init_account`")?;
241+
self.init_account::<IF_NEEDED>((arg.0, funder), account_seeds, syscalls)
300242
}
301243
}
302244

303245
impl<'info, T: ProgramAccount + UnsizedType + ?Sized, InitArg, Funder>
304-
CanInitAccount<'info, Create<(InitArg, &Funder)>> for DataAccount<'info, T>
246+
CanInitAccount<'info, (InitArg, &Funder)> for DataAccount<'info, T>
305247
where
306248
T: UnsizedInit<InitArg>,
307249
Funder: SignedAccount<'info> + WritableAccount<'info>,
308250
{
309-
fn init_account(
251+
fn init_account<const IF_NEEDED: bool>(
310252
&mut self,
311-
arg: Create<(InitArg, &Funder)>,
312-
syscalls: &impl SyscallInvoke<'info>,
253+
arg: (InitArg, &Funder),
313254
account_seeds: Option<Vec<&[u8]>>,
255+
syscalls: &impl SyscallInvoke<'info>,
314256
) -> Result<()> {
315-
self.check_writable()
316-
.context("InitAccount must be writable")?;
317-
let (arg, funder) = arg.0;
257+
if IF_NEEDED {
258+
let needs_init = self.owner() == &SystemProgram::PROGRAM_ID
259+
|| self.info_data_bytes()?
260+
[..size_of::<<T::OwnerProgram as StarFrameProgram>::AccountDiscriminant>()]
261+
.iter()
262+
.all(|x| *x == 0);
263+
if !needs_init {
264+
return Ok(());
265+
}
266+
}
267+
self.check_writable()?;
268+
let (arg, funder) = arg;
318269
let size =
319270
T::INIT_BYTES + size_of::<<T::OwnerProgram as StarFrameProgram>::AccountDiscriminant>();
320271
self.system_create_account(

0 commit comments

Comments
 (0)