stake (#2195)
This commit is contained in:
parent
7f243ce66c
commit
3970847e75
|
@ -277,6 +277,7 @@ name = "anchor-spl"
|
||||||
version = "0.25.0"
|
version = "0.25.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anchor-lang",
|
"anchor-lang",
|
||||||
|
"borsh",
|
||||||
"mpl-token-metadata",
|
"mpl-token-metadata",
|
||||||
"serum_dex",
|
"serum_dex",
|
||||||
"solana-program",
|
"solana-program",
|
||||||
|
|
|
@ -14,12 +14,14 @@ token = ["spl-token"]
|
||||||
associated_token = ["spl-associated-token-account"]
|
associated_token = ["spl-associated-token-account"]
|
||||||
governance = []
|
governance = []
|
||||||
shmem = []
|
shmem = []
|
||||||
|
stake = ["borsh"]
|
||||||
devnet = []
|
devnet = []
|
||||||
metadata = ["mpl-token-metadata"]
|
metadata = ["mpl-token-metadata"]
|
||||||
dex = ["serum_dex"]
|
dex = ["serum_dex"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anchor-lang = { path = "../lang", version = "0.25.0", features = ["derive"] }
|
anchor-lang = { path = "../lang", version = "0.25.0", features = ["derive"] }
|
||||||
|
borsh = { version = "^0.9", optional = true }
|
||||||
serum_dex = { git = "https://github.com/project-serum/serum-dex", rev = "1be91f2", version = "0.4.0", features = ["no-entrypoint"], optional = true }
|
serum_dex = { git = "https://github.com/project-serum/serum-dex", rev = "1be91f2", version = "0.4.0", features = ["no-entrypoint"], optional = true }
|
||||||
solana-program = "~1.10.29"
|
solana-program = "~1.10.29"
|
||||||
spl-token = { version = "~3.3.0", features = ["no-entrypoint"], optional = true }
|
spl-token = { version = "~3.3.0", features = ["no-entrypoint"], optional = true }
|
||||||
|
|
|
@ -16,5 +16,8 @@ pub mod governance;
|
||||||
#[cfg(feature = "shmem")]
|
#[cfg(feature = "shmem")]
|
||||||
pub mod shmem;
|
pub mod shmem;
|
||||||
|
|
||||||
|
#[cfg(feature = "stake")]
|
||||||
|
pub mod stake;
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
pub mod metadata;
|
pub mod metadata;
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
use anchor_lang::{
|
||||||
|
context::CpiContext,
|
||||||
|
solana_program::{
|
||||||
|
account_info::AccountInfo,
|
||||||
|
pubkey::Pubkey,
|
||||||
|
stake::{
|
||||||
|
self,
|
||||||
|
program::ID,
|
||||||
|
state::{StakeAuthorize, StakeState},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Accounts, Result,
|
||||||
|
};
|
||||||
|
use borsh::BorshDeserialize;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
// CPI functions
|
||||||
|
|
||||||
|
pub fn authorize<'info>(
|
||||||
|
ctx: CpiContext<'_, '_, '_, 'info, Authorize<'info>>,
|
||||||
|
stake_authorize: StakeAuthorize,
|
||||||
|
custodian: Option<AccountInfo<'info>>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let ix = stake::instruction::authorize(
|
||||||
|
ctx.accounts.stake.key,
|
||||||
|
ctx.accounts.authorized.key,
|
||||||
|
ctx.accounts.new_authorized.key,
|
||||||
|
stake_authorize,
|
||||||
|
custodian.as_ref().map(|c| c.key),
|
||||||
|
);
|
||||||
|
let mut account_infos = vec![
|
||||||
|
ctx.accounts.stake,
|
||||||
|
ctx.accounts.clock,
|
||||||
|
ctx.accounts.authorized,
|
||||||
|
];
|
||||||
|
if let Some(c) = custodian {
|
||||||
|
account_infos.push(c);
|
||||||
|
}
|
||||||
|
solana_program::program::invoke_signed(&ix, &account_infos, ctx.signer_seeds)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn withdraw<'info>(
|
||||||
|
ctx: CpiContext<'_, '_, '_, 'info, Withdraw<'info>>,
|
||||||
|
amount: u64,
|
||||||
|
custodian: Option<AccountInfo<'info>>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let ix = stake::instruction::withdraw(
|
||||||
|
ctx.accounts.stake.key,
|
||||||
|
ctx.accounts.withdrawer.key,
|
||||||
|
ctx.accounts.to.key,
|
||||||
|
amount,
|
||||||
|
custodian.as_ref().map(|c| c.key),
|
||||||
|
);
|
||||||
|
let mut account_infos = vec![
|
||||||
|
ctx.accounts.stake,
|
||||||
|
ctx.accounts.to,
|
||||||
|
ctx.accounts.clock,
|
||||||
|
ctx.accounts.stake_history,
|
||||||
|
ctx.accounts.withdrawer,
|
||||||
|
];
|
||||||
|
if let Some(c) = custodian {
|
||||||
|
account_infos.push(c);
|
||||||
|
}
|
||||||
|
solana_program::program::invoke_signed(&ix, &account_infos, ctx.signer_seeds)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deactivate_stake<'info>(
|
||||||
|
ctx: CpiContext<'_, '_, '_, 'info, DeactivateStake<'info>>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let ix = stake::instruction::deactivate_stake(ctx.accounts.stake.key, ctx.accounts.staker.key);
|
||||||
|
solana_program::program::invoke_signed(
|
||||||
|
&ix,
|
||||||
|
&[ctx.accounts.stake, ctx.accounts.clock, ctx.accounts.staker],
|
||||||
|
ctx.signer_seeds,
|
||||||
|
)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPI accounts
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct Authorize<'info> {
|
||||||
|
/// The stake account to be updated
|
||||||
|
pub stake: AccountInfo<'info>,
|
||||||
|
|
||||||
|
/// The existing authority
|
||||||
|
pub authorized: AccountInfo<'info>,
|
||||||
|
|
||||||
|
/// The new authority to replace the existing authority
|
||||||
|
pub new_authorized: AccountInfo<'info>,
|
||||||
|
|
||||||
|
/// Clock sysvar
|
||||||
|
pub clock: AccountInfo<'info>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct Withdraw<'info> {
|
||||||
|
/// The stake account to be updated
|
||||||
|
pub stake: AccountInfo<'info>,
|
||||||
|
|
||||||
|
/// The stake account's withdraw authority
|
||||||
|
pub withdrawer: AccountInfo<'info>,
|
||||||
|
|
||||||
|
/// Account to send withdrawn lamports to
|
||||||
|
pub to: AccountInfo<'info>,
|
||||||
|
|
||||||
|
/// Clock sysvar
|
||||||
|
pub clock: AccountInfo<'info>,
|
||||||
|
|
||||||
|
/// StakeHistory sysvar
|
||||||
|
pub stake_history: AccountInfo<'info>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct DeactivateStake<'info> {
|
||||||
|
/// The stake account to be deactivated
|
||||||
|
pub stake: AccountInfo<'info>,
|
||||||
|
|
||||||
|
/// The stake account's stake authority
|
||||||
|
pub staker: AccountInfo<'info>,
|
||||||
|
|
||||||
|
/// Clock sysvar
|
||||||
|
pub clock: AccountInfo<'info>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// State
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct StakeAccount(StakeState);
|
||||||
|
|
||||||
|
impl anchor_lang::AccountDeserialize for StakeAccount {
|
||||||
|
fn try_deserialize(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
|
||||||
|
Self::try_deserialize_unchecked(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
|
||||||
|
StakeState::deserialize(buf).map(Self).map_err(Into::into)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl anchor_lang::AccountSerialize for StakeAccount {}
|
||||||
|
|
||||||
|
impl anchor_lang::Owner for StakeAccount {
|
||||||
|
fn owner() -> Pubkey {
|
||||||
|
ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for StakeAccount {
|
||||||
|
type Target = StakeState;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Stake;
|
||||||
|
|
||||||
|
impl anchor_lang::Id for Stake {
|
||||||
|
fn id() -> Pubkey {
|
||||||
|
ID
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue