# Anchor CPI related
## SPL token transfer CPI
### Method #1
```
#[program]
pub mod locker_manager {
...
pub fn create_locker(
ctx: Context<CreateLocker>,
beneficiary: Pubkey,
deposit_amount: u64,
nonce: u8,
start_ts: i64,
end_ts: i64,
period_count: u64,
// reward_kepper: Option<RewardKeeper>,
) -> Result<()> {
...
transfer(ctx.accounts.transfer_ctx(), deposit_amount)?;
...
Ok(())
}
}
#[derive(Accounts)]
pub struct CreateLocker<'info> {
#[account(zero)]
pub locker: Box<Account<'info, Locker>>,
#[account(mut)]
pub vault: Account<'info, TokenAccount>,
/// CHECK: This is not dangerous because we don't read or write from this account
#[account(mut)]
pub depositor: AccountInfo<'info>,
pub depositor_authority: Signer<'info>,
// Misc.
pub token_program: Program<'info, Token>,
pub rent: Sysvar<'info, Rent>,
pub clock: Sysvar<'info, Clock>,
}
impl<'info> CreateLocker<'info> {
pub fn transfer_ctx(&self) -> CpiContext<'_, '_, '_, 'info, Transfer<'info>> {
CpiContext::new(
self.token_program.to_account_info(),
Transfer {
from: self.depositor.clone(),
to: self.vault.to_account_info(),
authority: self.depositor_authority.to_account_info()
}
)
}
}
```
## Method #2
```
#[program]
pub mod locker_manager {
...
pub fn create_locker(
ctx: Context<CreateLocker>,
beneficiary: Pubkey,
deposit_amount: u64,
nonce: u8,
start_ts: i64,
end_ts: i64,
period_count: u64,
// reward_kepper: Option<RewardKeeper>,
) -> Result<()> {
...
transfer(ctx.accounts.into(), deposit_amount)?;
...
Ok(())
}
}
#[derive(Accounts)]
pub struct CreateLocker<'info> {
#[account(zero)] // TOCHECK: why not mut?
pub locker: Box<Account<'info, Locker>>,
#[account(mut)]
pub vault: Account<'info, TokenAccount>,
/// CHECK: This is not dangerous because we don't read or write from this account
#[account(mut)]
pub depositor: AccountInfo<'info>,
pub depositor_authority: Signer<'info>,
// Misc.
pub token_program: Program<'info, Token>,
pub rent: Sysvar<'info, Rent>,
pub clock: Sysvar<'info, Clock>,
}
impl<'a, 'b, 'c, 'info> From<&mut CreateLocker<'info>>
for CpiContext<'a, 'b, 'c, 'info, Transfer<'info>>
{
fn from(accounts: &mut CreateLocker<'info>) -> CpiContext<'a, 'b, 'c, 'info, Transfer<'info>> {
let cpi_accounts = Transfer {
from: accounts.depositor.clone(),
to: accounts.vault.to_account_info(),
authority: accounts.depositor_authority.to_account_info().clone(),
};
let cpi_program = accounts.token_program.to_account_info().clone();
CpiContext::new(cpi_program, cpi_accounts)
}
}
```