mirror of
https://github.com/mortdeus/legacy-cc.git
synced 2026-10-09 12:22:24 +00:00
1773 lines
59 KiB
Rust
1773 lines
59 KiB
Rust
#[cfg(feature = "serde")]
|
|
// use crate::serializer::{deserialize_u128_as_string, serialize_u128_as_string};
|
|
use borsh::{BorshDeserialize, BorshSerialize};
|
|
use inflector::Inflector;
|
|
use solana_program::{
|
|
account_info::AccountInfo,
|
|
entrypoint::ProgramResult,
|
|
instruction::{AccountMeta, Instruction},
|
|
program::{invoke, invoke_signed},
|
|
program_error::ProgramError,
|
|
pubkey::Pubkey,
|
|
};
|
|
use std::io::Read;
|
|
// use std::fmt;
|
|
use strum_macros::{Display, EnumString};
|
|
|
|
#[derive(Clone, Debug, PartialEq, EnumString, Display)]
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
pub enum PumpProgramIx {
|
|
Initialize,
|
|
SetParams(SetParamsIxArgs),
|
|
Create(CreateIxArgs),
|
|
Buy(BuyIxArgs),
|
|
Sell(SellIxArgs),
|
|
Withdraw,
|
|
}
|
|
|
|
impl PumpProgramIx {
|
|
pub fn name(&self) -> String {
|
|
// Use the ToString derived method to get the enum variant name
|
|
self.to_string().to_camel_case()
|
|
}
|
|
pub fn deserialize(buf: &[u8]) -> std::io::Result<Self> {
|
|
let mut reader = buf;
|
|
let mut maybe_discm = [0u8; 8];
|
|
reader.read_exact(&mut maybe_discm)?;
|
|
match maybe_discm {
|
|
INITIALIZE_IX_DISCM => Ok(Self::Initialize),
|
|
SET_PARAMS_IX_DISCM => Ok(Self::SetParams(SetParamsIxArgs::deserialize(&mut reader)?)),
|
|
CREATE_IX_DISCM => Ok(Self::Create(CreateIxArgs::deserialize(&mut reader)?)),
|
|
BUY_IX_DISCM => Ok(Self::Buy(BuyIxArgs::deserialize(&mut reader)?)),
|
|
SELL_IX_DISCM => Ok(Self::Sell(SellIxArgs::deserialize(&mut reader)?)),
|
|
WITHDRAW_IX_DISCM => Ok(Self::Withdraw),
|
|
_ => Err(std::io::Error::new(
|
|
std::io::ErrorKind::Other,
|
|
format!("discm {:?} not found", maybe_discm),
|
|
)),
|
|
}
|
|
}
|
|
pub fn serialize<W: std::io::Write>(&self, mut writer: W) -> std::io::Result<()> {
|
|
match self {
|
|
Self::Initialize => writer.write_all(&INITIALIZE_IX_DISCM),
|
|
Self::SetParams(args) => {
|
|
writer.write_all(&SET_PARAMS_IX_DISCM)?;
|
|
args.serialize(&mut writer)
|
|
}
|
|
Self::Create(args) => {
|
|
writer.write_all(&CREATE_IX_DISCM)?;
|
|
args.serialize(&mut writer)
|
|
}
|
|
Self::Buy(args) => {
|
|
writer.write_all(&BUY_IX_DISCM)?;
|
|
args.serialize(&mut writer)
|
|
}
|
|
Self::Sell(args) => {
|
|
writer.write_all(&SELL_IX_DISCM)?;
|
|
args.serialize(&mut writer)
|
|
}
|
|
Self::Withdraw => writer.write_all(&WITHDRAW_IX_DISCM),
|
|
}
|
|
}
|
|
pub fn try_to_vec(&self) -> std::io::Result<Vec<u8>> {
|
|
let mut data = Vec::new();
|
|
self.serialize(&mut data)?;
|
|
Ok(data)
|
|
}
|
|
}
|
|
fn invoke_instruction<'info, A: Into<[AccountInfo<'info>; N]>, const N: usize>(
|
|
ix: &Instruction,
|
|
accounts: A,
|
|
) -> ProgramResult {
|
|
let account_info: [AccountInfo<'info>; N] = accounts.into();
|
|
invoke(ix, &account_info)
|
|
}
|
|
fn invoke_instruction_signed<'info, A: Into<[AccountInfo<'info>; N]>, const N: usize>(
|
|
ix: &Instruction,
|
|
accounts: A,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
let account_info: [AccountInfo<'info>; N] = accounts.into();
|
|
invoke_signed(ix, &account_info, seeds)
|
|
}
|
|
pub const INITIALIZE_IX_ACCOUNTS_LEN: usize = 3;
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub struct InitializeAccounts<'me, 'info> {
|
|
pub global: &'me AccountInfo<'info>,
|
|
pub user: &'me AccountInfo<'info>,
|
|
pub system_program: &'me AccountInfo<'info>,
|
|
}
|
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
|
pub struct InitializeKeys {
|
|
pub global: Pubkey,
|
|
pub user: Pubkey,
|
|
pub system_program: Pubkey,
|
|
}
|
|
impl From<InitializeAccounts<'_, '_>> for InitializeKeys {
|
|
fn from(accounts: InitializeAccounts) -> Self {
|
|
Self {
|
|
global: *accounts.global.key,
|
|
user: *accounts.user.key,
|
|
system_program: *accounts.system_program.key,
|
|
}
|
|
}
|
|
}
|
|
impl From<InitializeKeys> for [AccountMeta; INITIALIZE_IX_ACCOUNTS_LEN] {
|
|
fn from(keys: InitializeKeys) -> Self {
|
|
[
|
|
AccountMeta {
|
|
pubkey: keys.global,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.user,
|
|
is_signer: true,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.system_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
]
|
|
}
|
|
}
|
|
impl From<[Pubkey; INITIALIZE_IX_ACCOUNTS_LEN]> for InitializeKeys {
|
|
fn from(pubkeys: [Pubkey; INITIALIZE_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
global: pubkeys[0],
|
|
user: pubkeys[1],
|
|
system_program: pubkeys[2],
|
|
}
|
|
}
|
|
}
|
|
impl<'info> From<InitializeAccounts<'_, 'info>>
|
|
for [AccountInfo<'info>; INITIALIZE_IX_ACCOUNTS_LEN]
|
|
{
|
|
fn from(accounts: InitializeAccounts<'_, 'info>) -> Self {
|
|
[
|
|
accounts.global.clone(),
|
|
accounts.user.clone(),
|
|
accounts.system_program.clone(),
|
|
]
|
|
}
|
|
}
|
|
impl<'me, 'info> From<&'me [AccountInfo<'info>; INITIALIZE_IX_ACCOUNTS_LEN]>
|
|
for InitializeAccounts<'me, 'info>
|
|
{
|
|
fn from(arr: &'me [AccountInfo<'info>; INITIALIZE_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
global: &arr[0],
|
|
user: &arr[1],
|
|
system_program: &arr[2],
|
|
}
|
|
}
|
|
}
|
|
pub const INITIALIZE_IX_DISCM: [u8; 8] = [175, 175, 109, 31, 13, 152, 155, 237];
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct InitializeIxData;
|
|
impl InitializeIxData {
|
|
pub fn deserialize(buf: &[u8]) -> std::io::Result<Self> {
|
|
let mut reader = buf;
|
|
let mut maybe_discm = [0u8; 8];
|
|
reader.read_exact(&mut maybe_discm)?;
|
|
if maybe_discm != INITIALIZE_IX_DISCM {
|
|
return Err(std::io::Error::new(
|
|
std::io::ErrorKind::Other,
|
|
format!(
|
|
"discm does not match. Expected: {:?}. Received: {:?}",
|
|
INITIALIZE_IX_DISCM, maybe_discm
|
|
),
|
|
));
|
|
}
|
|
Ok(Self)
|
|
}
|
|
pub fn serialize<W: std::io::Write>(&self, mut writer: W) -> std::io::Result<()> {
|
|
writer.write_all(&INITIALIZE_IX_DISCM)
|
|
}
|
|
pub fn try_to_vec(&self) -> std::io::Result<Vec<u8>> {
|
|
let mut data = Vec::new();
|
|
self.serialize(&mut data)?;
|
|
Ok(data)
|
|
}
|
|
}
|
|
pub fn initialize_ix_with_program_id(
|
|
program_id: Pubkey,
|
|
keys: InitializeKeys,
|
|
) -> std::io::Result<Instruction> {
|
|
let metas: [AccountMeta; INITIALIZE_IX_ACCOUNTS_LEN] = keys.into();
|
|
Ok(Instruction {
|
|
program_id,
|
|
accounts: Vec::from(metas),
|
|
data: InitializeIxData.try_to_vec()?,
|
|
})
|
|
}
|
|
pub fn initialize_ix(keys: InitializeKeys) -> std::io::Result<Instruction> {
|
|
initialize_ix_with_program_id(crate::ID, keys)
|
|
}
|
|
pub fn initialize_invoke_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: InitializeAccounts<'_, '_>,
|
|
) -> ProgramResult {
|
|
let keys: InitializeKeys = accounts.into();
|
|
let ix = initialize_ix_with_program_id(program_id, keys)?;
|
|
invoke_instruction(&ix, accounts)
|
|
}
|
|
pub fn initialize_invoke(accounts: InitializeAccounts<'_, '_>) -> ProgramResult {
|
|
initialize_invoke_with_program_id(crate::ID, accounts)
|
|
}
|
|
pub fn initialize_invoke_signed_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: InitializeAccounts<'_, '_>,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
let keys: InitializeKeys = accounts.into();
|
|
let ix = initialize_ix_with_program_id(program_id, keys)?;
|
|
invoke_instruction_signed(&ix, accounts, seeds)
|
|
}
|
|
pub fn initialize_invoke_signed(
|
|
accounts: InitializeAccounts<'_, '_>,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
initialize_invoke_signed_with_program_id(crate::ID, accounts, seeds)
|
|
}
|
|
pub fn initialize_verify_account_keys(
|
|
accounts: InitializeAccounts<'_, '_>,
|
|
keys: InitializeKeys,
|
|
) -> Result<(), (Pubkey, Pubkey)> {
|
|
for (actual, expected) in [
|
|
(*accounts.global.key, keys.global),
|
|
(*accounts.user.key, keys.user),
|
|
(*accounts.system_program.key, keys.system_program),
|
|
] {
|
|
if actual != expected {
|
|
return Err((actual, expected));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn initialize_verify_writable_privileges<'me, 'info>(
|
|
accounts: InitializeAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_writable in [accounts.global, accounts.user] {
|
|
if !should_be_writable.is_writable {
|
|
return Err((should_be_writable, ProgramError::InvalidAccountData));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn initialize_verify_signer_privileges<'me, 'info>(
|
|
accounts: InitializeAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_signer in [accounts.user] {
|
|
if !should_be_signer.is_signer {
|
|
return Err((should_be_signer, ProgramError::MissingRequiredSignature));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn initialize_verify_account_privileges<'me, 'info>(
|
|
accounts: InitializeAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
initialize_verify_writable_privileges(accounts)?;
|
|
initialize_verify_signer_privileges(accounts)?;
|
|
Ok(())
|
|
}
|
|
pub const SET_PARAMS_IX_ACCOUNTS_LEN: usize = 5;
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub struct SetParamsAccounts<'me, 'info> {
|
|
pub global: &'me AccountInfo<'info>,
|
|
pub user: &'me AccountInfo<'info>,
|
|
pub system_program: &'me AccountInfo<'info>,
|
|
pub event_authority: &'me AccountInfo<'info>,
|
|
pub program: &'me AccountInfo<'info>,
|
|
}
|
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
|
pub struct SetParamsKeys {
|
|
pub global: Pubkey,
|
|
pub user: Pubkey,
|
|
pub system_program: Pubkey,
|
|
pub event_authority: Pubkey,
|
|
pub program: Pubkey,
|
|
}
|
|
impl From<SetParamsAccounts<'_, '_>> for SetParamsKeys {
|
|
fn from(accounts: SetParamsAccounts) -> Self {
|
|
Self {
|
|
global: *accounts.global.key,
|
|
user: *accounts.user.key,
|
|
system_program: *accounts.system_program.key,
|
|
event_authority: *accounts.event_authority.key,
|
|
program: *accounts.program.key,
|
|
}
|
|
}
|
|
}
|
|
impl From<SetParamsKeys> for [AccountMeta; SET_PARAMS_IX_ACCOUNTS_LEN] {
|
|
fn from(keys: SetParamsKeys) -> Self {
|
|
[
|
|
AccountMeta {
|
|
pubkey: keys.global,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.user,
|
|
is_signer: true,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.system_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.event_authority,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
]
|
|
}
|
|
}
|
|
impl From<[Pubkey; SET_PARAMS_IX_ACCOUNTS_LEN]> for SetParamsKeys {
|
|
fn from(pubkeys: [Pubkey; SET_PARAMS_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
global: pubkeys[0],
|
|
user: pubkeys[1],
|
|
system_program: pubkeys[2],
|
|
event_authority: pubkeys[3],
|
|
program: pubkeys[4],
|
|
}
|
|
}
|
|
}
|
|
impl<'info> From<SetParamsAccounts<'_, 'info>>
|
|
for [AccountInfo<'info>; SET_PARAMS_IX_ACCOUNTS_LEN]
|
|
{
|
|
fn from(accounts: SetParamsAccounts<'_, 'info>) -> Self {
|
|
[
|
|
accounts.global.clone(),
|
|
accounts.user.clone(),
|
|
accounts.system_program.clone(),
|
|
accounts.event_authority.clone(),
|
|
accounts.program.clone(),
|
|
]
|
|
}
|
|
}
|
|
impl<'me, 'info> From<&'me [AccountInfo<'info>; SET_PARAMS_IX_ACCOUNTS_LEN]>
|
|
for SetParamsAccounts<'me, 'info>
|
|
{
|
|
fn from(arr: &'me [AccountInfo<'info>; SET_PARAMS_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
global: &arr[0],
|
|
user: &arr[1],
|
|
system_program: &arr[2],
|
|
event_authority: &arr[3],
|
|
program: &arr[4],
|
|
}
|
|
}
|
|
}
|
|
pub const SET_PARAMS_IX_DISCM: [u8; 8] = [27, 234, 178, 52, 147, 2, 187, 141];
|
|
#[derive(BorshDeserialize, BorshSerialize, Clone, Debug, PartialEq, Default)]
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
pub struct SetParamsIxArgs {
|
|
pub fee_recipient: Pubkey,
|
|
pub initial_virtual_token_reserves: u64,
|
|
pub initial_virtual_sol_reserves: u64,
|
|
pub initial_real_token_reserves: u64,
|
|
pub token_total_supply: u64,
|
|
pub fee_basis_points: u64,
|
|
}
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct SetParamsIxData(pub SetParamsIxArgs);
|
|
impl From<SetParamsIxArgs> for SetParamsIxData {
|
|
fn from(args: SetParamsIxArgs) -> Self {
|
|
Self(args)
|
|
}
|
|
}
|
|
impl SetParamsIxData {
|
|
pub fn deserialize(buf: &[u8]) -> std::io::Result<Self> {
|
|
let mut reader = buf;
|
|
let mut maybe_discm = [0u8; 8];
|
|
reader.read_exact(&mut maybe_discm)?;
|
|
if maybe_discm != SET_PARAMS_IX_DISCM {
|
|
return Err(std::io::Error::new(
|
|
std::io::ErrorKind::Other,
|
|
format!(
|
|
"discm does not match. Expected: {:?}. Received: {:?}",
|
|
SET_PARAMS_IX_DISCM, maybe_discm
|
|
),
|
|
));
|
|
}
|
|
Ok(Self(SetParamsIxArgs::deserialize(&mut reader)?))
|
|
}
|
|
pub fn serialize<W: std::io::Write>(&self, mut writer: W) -> std::io::Result<()> {
|
|
writer.write_all(&SET_PARAMS_IX_DISCM)?;
|
|
self.0.serialize(&mut writer)
|
|
}
|
|
pub fn try_to_vec(&self) -> std::io::Result<Vec<u8>> {
|
|
let mut data = Vec::new();
|
|
self.serialize(&mut data)?;
|
|
Ok(data)
|
|
}
|
|
}
|
|
pub fn set_params_ix_with_program_id(
|
|
program_id: Pubkey,
|
|
keys: SetParamsKeys,
|
|
args: SetParamsIxArgs,
|
|
) -> std::io::Result<Instruction> {
|
|
let metas: [AccountMeta; SET_PARAMS_IX_ACCOUNTS_LEN] = keys.into();
|
|
let data: SetParamsIxData = args.into();
|
|
Ok(Instruction {
|
|
program_id,
|
|
accounts: Vec::from(metas),
|
|
data: data.try_to_vec()?,
|
|
})
|
|
}
|
|
pub fn set_params_ix(keys: SetParamsKeys, args: SetParamsIxArgs) -> std::io::Result<Instruction> {
|
|
set_params_ix_with_program_id(crate::ID, keys, args)
|
|
}
|
|
pub fn set_params_invoke_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: SetParamsAccounts<'_, '_>,
|
|
args: SetParamsIxArgs,
|
|
) -> ProgramResult {
|
|
let keys: SetParamsKeys = accounts.into();
|
|
let ix = set_params_ix_with_program_id(program_id, keys, args)?;
|
|
invoke_instruction(&ix, accounts)
|
|
}
|
|
pub fn set_params_invoke(
|
|
accounts: SetParamsAccounts<'_, '_>,
|
|
args: SetParamsIxArgs,
|
|
) -> ProgramResult {
|
|
set_params_invoke_with_program_id(crate::ID, accounts, args)
|
|
}
|
|
pub fn set_params_invoke_signed_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: SetParamsAccounts<'_, '_>,
|
|
args: SetParamsIxArgs,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
let keys: SetParamsKeys = accounts.into();
|
|
let ix = set_params_ix_with_program_id(program_id, keys, args)?;
|
|
invoke_instruction_signed(&ix, accounts, seeds)
|
|
}
|
|
pub fn set_params_invoke_signed(
|
|
accounts: SetParamsAccounts<'_, '_>,
|
|
args: SetParamsIxArgs,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
set_params_invoke_signed_with_program_id(crate::ID, accounts, args, seeds)
|
|
}
|
|
pub fn set_params_verify_account_keys(
|
|
accounts: SetParamsAccounts<'_, '_>,
|
|
keys: SetParamsKeys,
|
|
) -> Result<(), (Pubkey, Pubkey)> {
|
|
for (actual, expected) in [
|
|
(*accounts.global.key, keys.global),
|
|
(*accounts.user.key, keys.user),
|
|
(*accounts.system_program.key, keys.system_program),
|
|
(*accounts.event_authority.key, keys.event_authority),
|
|
(*accounts.program.key, keys.program),
|
|
] {
|
|
if actual != expected {
|
|
return Err((actual, expected));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn set_params_verify_writable_privileges<'me, 'info>(
|
|
accounts: SetParamsAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_writable in [accounts.global, accounts.user] {
|
|
if !should_be_writable.is_writable {
|
|
return Err((should_be_writable, ProgramError::InvalidAccountData));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn set_params_verify_signer_privileges<'me, 'info>(
|
|
accounts: SetParamsAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_signer in [accounts.user] {
|
|
if !should_be_signer.is_signer {
|
|
return Err((should_be_signer, ProgramError::MissingRequiredSignature));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn set_params_verify_account_privileges<'me, 'info>(
|
|
accounts: SetParamsAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
set_params_verify_writable_privileges(accounts)?;
|
|
set_params_verify_signer_privileges(accounts)?;
|
|
Ok(())
|
|
}
|
|
pub const CREATE_IX_ACCOUNTS_LEN: usize = 14;
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub struct CreateAccounts<'me, 'info> {
|
|
pub mint: &'me AccountInfo<'info>,
|
|
pub mint_authority: &'me AccountInfo<'info>,
|
|
pub bonding_curve: &'me AccountInfo<'info>,
|
|
pub associated_bonding_curve: &'me AccountInfo<'info>,
|
|
pub global: &'me AccountInfo<'info>,
|
|
pub mpl_token_metadata: &'me AccountInfo<'info>,
|
|
pub metadata: &'me AccountInfo<'info>,
|
|
pub user: &'me AccountInfo<'info>,
|
|
pub system_program: &'me AccountInfo<'info>,
|
|
pub token_program: &'me AccountInfo<'info>,
|
|
pub associated_token_program: &'me AccountInfo<'info>,
|
|
pub rent: &'me AccountInfo<'info>,
|
|
pub event_authority: &'me AccountInfo<'info>,
|
|
pub program: &'me AccountInfo<'info>,
|
|
}
|
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
|
pub struct CreateKeys {
|
|
pub mint: Pubkey,
|
|
pub mint_authority: Pubkey,
|
|
pub bonding_curve: Pubkey,
|
|
pub associated_bonding_curve: Pubkey,
|
|
pub global: Pubkey,
|
|
pub mpl_token_metadata: Pubkey,
|
|
pub metadata: Pubkey,
|
|
pub user: Pubkey,
|
|
pub system_program: Pubkey,
|
|
pub token_program: Pubkey,
|
|
pub associated_token_program: Pubkey,
|
|
pub rent: Pubkey,
|
|
pub event_authority: Pubkey,
|
|
pub program: Pubkey,
|
|
}
|
|
impl From<CreateAccounts<'_, '_>> for CreateKeys {
|
|
fn from(accounts: CreateAccounts) -> Self {
|
|
Self {
|
|
mint: *accounts.mint.key,
|
|
mint_authority: *accounts.mint_authority.key,
|
|
bonding_curve: *accounts.bonding_curve.key,
|
|
associated_bonding_curve: *accounts.associated_bonding_curve.key,
|
|
global: *accounts.global.key,
|
|
mpl_token_metadata: *accounts.mpl_token_metadata.key,
|
|
metadata: *accounts.metadata.key,
|
|
user: *accounts.user.key,
|
|
system_program: *accounts.system_program.key,
|
|
token_program: *accounts.token_program.key,
|
|
associated_token_program: *accounts.associated_token_program.key,
|
|
rent: *accounts.rent.key,
|
|
event_authority: *accounts.event_authority.key,
|
|
program: *accounts.program.key,
|
|
}
|
|
}
|
|
}
|
|
impl From<CreateKeys> for [AccountMeta; CREATE_IX_ACCOUNTS_LEN] {
|
|
fn from(keys: CreateKeys) -> Self {
|
|
[
|
|
AccountMeta {
|
|
pubkey: keys.mint,
|
|
is_signer: true,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.mint_authority,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.bonding_curve,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.associated_bonding_curve,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.global,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.mpl_token_metadata,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.metadata,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.user,
|
|
is_signer: true,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.system_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.token_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.associated_token_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.rent,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.event_authority,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
]
|
|
}
|
|
}
|
|
impl From<[Pubkey; CREATE_IX_ACCOUNTS_LEN]> for CreateKeys {
|
|
fn from(pubkeys: [Pubkey; CREATE_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
mint: pubkeys[0],
|
|
mint_authority: pubkeys[1],
|
|
bonding_curve: pubkeys[2],
|
|
associated_bonding_curve: pubkeys[3],
|
|
global: pubkeys[4],
|
|
mpl_token_metadata: pubkeys[5],
|
|
metadata: pubkeys[6],
|
|
user: pubkeys[7],
|
|
system_program: pubkeys[8],
|
|
token_program: pubkeys[9],
|
|
associated_token_program: pubkeys[10],
|
|
rent: pubkeys[11],
|
|
event_authority: pubkeys[12],
|
|
program: pubkeys[13],
|
|
}
|
|
}
|
|
}
|
|
impl<'info> From<CreateAccounts<'_, 'info>> for [AccountInfo<'info>; CREATE_IX_ACCOUNTS_LEN] {
|
|
fn from(accounts: CreateAccounts<'_, 'info>) -> Self {
|
|
[
|
|
accounts.mint.clone(),
|
|
accounts.mint_authority.clone(),
|
|
accounts.bonding_curve.clone(),
|
|
accounts.associated_bonding_curve.clone(),
|
|
accounts.global.clone(),
|
|
accounts.mpl_token_metadata.clone(),
|
|
accounts.metadata.clone(),
|
|
accounts.user.clone(),
|
|
accounts.system_program.clone(),
|
|
accounts.token_program.clone(),
|
|
accounts.associated_token_program.clone(),
|
|
accounts.rent.clone(),
|
|
accounts.event_authority.clone(),
|
|
accounts.program.clone(),
|
|
]
|
|
}
|
|
}
|
|
impl<'me, 'info> From<&'me [AccountInfo<'info>; CREATE_IX_ACCOUNTS_LEN]>
|
|
for CreateAccounts<'me, 'info>
|
|
{
|
|
fn from(arr: &'me [AccountInfo<'info>; CREATE_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
mint: &arr[0],
|
|
mint_authority: &arr[1],
|
|
bonding_curve: &arr[2],
|
|
associated_bonding_curve: &arr[3],
|
|
global: &arr[4],
|
|
mpl_token_metadata: &arr[5],
|
|
metadata: &arr[6],
|
|
user: &arr[7],
|
|
system_program: &arr[8],
|
|
token_program: &arr[9],
|
|
associated_token_program: &arr[10],
|
|
rent: &arr[11],
|
|
event_authority: &arr[12],
|
|
program: &arr[13],
|
|
}
|
|
}
|
|
}
|
|
pub const CREATE_IX_DISCM: [u8; 8] = [24, 30, 200, 40, 5, 28, 7, 119];
|
|
#[derive(BorshDeserialize, BorshSerialize, Clone, Debug, PartialEq, Default)]
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
pub struct CreateIxArgs {
|
|
pub name: String,
|
|
pub symbol: String,
|
|
pub uri: String,
|
|
pub creator: Pubkey,
|
|
}
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct CreateIxData(pub CreateIxArgs);
|
|
impl From<CreateIxArgs> for CreateIxData {
|
|
fn from(args: CreateIxArgs) -> Self {
|
|
Self(args)
|
|
}
|
|
}
|
|
impl CreateIxData {
|
|
pub fn deserialize(buf: &[u8]) -> std::io::Result<Self> {
|
|
let mut reader = buf;
|
|
let mut maybe_discm = [0u8; 8];
|
|
reader.read_exact(&mut maybe_discm)?;
|
|
if maybe_discm != CREATE_IX_DISCM {
|
|
return Err(std::io::Error::new(
|
|
std::io::ErrorKind::Other,
|
|
format!(
|
|
"discm does not match. Expected: {:?}. Received: {:?}",
|
|
CREATE_IX_DISCM, maybe_discm
|
|
),
|
|
));
|
|
}
|
|
Ok(Self(CreateIxArgs::deserialize(&mut reader)?))
|
|
}
|
|
pub fn serialize<W: std::io::Write>(&self, mut writer: W) -> std::io::Result<()> {
|
|
writer.write_all(&CREATE_IX_DISCM)?;
|
|
self.0.serialize(&mut writer)
|
|
}
|
|
pub fn try_to_vec(&self) -> std::io::Result<Vec<u8>> {
|
|
let mut data = Vec::new();
|
|
self.serialize(&mut data)?;
|
|
Ok(data)
|
|
}
|
|
}
|
|
pub fn create_ix_with_program_id(
|
|
program_id: Pubkey,
|
|
keys: CreateKeys,
|
|
args: CreateIxArgs,
|
|
) -> std::io::Result<Instruction> {
|
|
let metas: [AccountMeta; CREATE_IX_ACCOUNTS_LEN] = keys.into();
|
|
let data: CreateIxData = args.into();
|
|
Ok(Instruction {
|
|
program_id,
|
|
accounts: Vec::from(metas),
|
|
data: data.try_to_vec()?,
|
|
})
|
|
}
|
|
pub fn create_ix(keys: CreateKeys, args: CreateIxArgs) -> std::io::Result<Instruction> {
|
|
create_ix_with_program_id(crate::ID, keys, args)
|
|
}
|
|
pub fn create_invoke_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: CreateAccounts<'_, '_>,
|
|
args: CreateIxArgs,
|
|
) -> ProgramResult {
|
|
let keys: CreateKeys = accounts.into();
|
|
let ix = create_ix_with_program_id(program_id, keys, args)?;
|
|
invoke_instruction(&ix, accounts)
|
|
}
|
|
pub fn create_invoke(accounts: CreateAccounts<'_, '_>, args: CreateIxArgs) -> ProgramResult {
|
|
create_invoke_with_program_id(crate::ID, accounts, args)
|
|
}
|
|
pub fn create_invoke_signed_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: CreateAccounts<'_, '_>,
|
|
args: CreateIxArgs,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
let keys: CreateKeys = accounts.into();
|
|
let ix = create_ix_with_program_id(program_id, keys, args)?;
|
|
invoke_instruction_signed(&ix, accounts, seeds)
|
|
}
|
|
pub fn create_invoke_signed(
|
|
accounts: CreateAccounts<'_, '_>,
|
|
args: CreateIxArgs,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
create_invoke_signed_with_program_id(crate::ID, accounts, args, seeds)
|
|
}
|
|
pub fn create_verify_account_keys(
|
|
accounts: CreateAccounts<'_, '_>,
|
|
keys: CreateKeys,
|
|
) -> Result<(), (Pubkey, Pubkey)> {
|
|
for (actual, expected) in [
|
|
(*accounts.mint.key, keys.mint),
|
|
(*accounts.mint_authority.key, keys.mint_authority),
|
|
(*accounts.bonding_curve.key, keys.bonding_curve),
|
|
(
|
|
*accounts.associated_bonding_curve.key,
|
|
keys.associated_bonding_curve,
|
|
),
|
|
(*accounts.global.key, keys.global),
|
|
(*accounts.mpl_token_metadata.key, keys.mpl_token_metadata),
|
|
(*accounts.metadata.key, keys.metadata),
|
|
(*accounts.user.key, keys.user),
|
|
(*accounts.system_program.key, keys.system_program),
|
|
(*accounts.token_program.key, keys.token_program),
|
|
(
|
|
*accounts.associated_token_program.key,
|
|
keys.associated_token_program,
|
|
),
|
|
(*accounts.rent.key, keys.rent),
|
|
(*accounts.event_authority.key, keys.event_authority),
|
|
(*accounts.program.key, keys.program),
|
|
] {
|
|
if actual != expected {
|
|
return Err((actual, expected));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn create_verify_writable_privileges<'me, 'info>(
|
|
accounts: CreateAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_writable in [
|
|
accounts.mint,
|
|
accounts.bonding_curve,
|
|
accounts.associated_bonding_curve,
|
|
accounts.metadata,
|
|
accounts.user,
|
|
] {
|
|
if !should_be_writable.is_writable {
|
|
return Err((should_be_writable, ProgramError::InvalidAccountData));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn create_verify_signer_privileges<'me, 'info>(
|
|
accounts: CreateAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_signer in [accounts.mint, accounts.user] {
|
|
if !should_be_signer.is_signer {
|
|
return Err((should_be_signer, ProgramError::MissingRequiredSignature));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn create_verify_account_privileges<'me, 'info>(
|
|
accounts: CreateAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
create_verify_writable_privileges(accounts)?;
|
|
create_verify_signer_privileges(accounts)?;
|
|
Ok(())
|
|
}
|
|
pub const BUY_IX_ACCOUNTS_LEN: usize = 12;
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub struct BuyAccounts<'me, 'info> {
|
|
pub global: &'me AccountInfo<'info>,
|
|
pub fee_recipient: &'me AccountInfo<'info>,
|
|
pub mint: &'me AccountInfo<'info>,
|
|
pub bonding_curve: &'me AccountInfo<'info>,
|
|
pub associated_bonding_curve: &'me AccountInfo<'info>,
|
|
pub associated_user: &'me AccountInfo<'info>,
|
|
pub user: &'me AccountInfo<'info>,
|
|
pub system_program: &'me AccountInfo<'info>,
|
|
pub token_program: &'me AccountInfo<'info>,
|
|
pub rent: &'me AccountInfo<'info>,
|
|
pub event_authority: &'me AccountInfo<'info>,
|
|
pub program: &'me AccountInfo<'info>,
|
|
}
|
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
|
pub struct BuyKeys {
|
|
pub global: Pubkey,
|
|
pub fee_recipient: Pubkey,
|
|
pub mint: Pubkey,
|
|
pub bonding_curve: Pubkey,
|
|
pub associated_bonding_curve: Pubkey,
|
|
pub associated_user: Pubkey,
|
|
pub user: Pubkey,
|
|
pub system_program: Pubkey,
|
|
pub token_program: Pubkey,
|
|
pub rent: Pubkey,
|
|
pub event_authority: Pubkey,
|
|
pub program: Pubkey,
|
|
}
|
|
impl From<BuyAccounts<'_, '_>> for BuyKeys {
|
|
fn from(accounts: BuyAccounts) -> Self {
|
|
Self {
|
|
global: *accounts.global.key,
|
|
fee_recipient: *accounts.fee_recipient.key,
|
|
mint: *accounts.mint.key,
|
|
bonding_curve: *accounts.bonding_curve.key,
|
|
associated_bonding_curve: *accounts.associated_bonding_curve.key,
|
|
associated_user: *accounts.associated_user.key,
|
|
user: *accounts.user.key,
|
|
system_program: *accounts.system_program.key,
|
|
token_program: *accounts.token_program.key,
|
|
rent: *accounts.rent.key,
|
|
event_authority: *accounts.event_authority.key,
|
|
program: *accounts.program.key,
|
|
}
|
|
}
|
|
}
|
|
impl From<BuyKeys> for [AccountMeta; BUY_IX_ACCOUNTS_LEN] {
|
|
fn from(keys: BuyKeys) -> Self {
|
|
[
|
|
AccountMeta {
|
|
pubkey: keys.global,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.fee_recipient,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.mint,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.bonding_curve,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.associated_bonding_curve,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.associated_user,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.user,
|
|
is_signer: true,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.system_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.token_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.rent,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.event_authority,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
]
|
|
}
|
|
}
|
|
impl From<[Pubkey; BUY_IX_ACCOUNTS_LEN]> for BuyKeys {
|
|
fn from(pubkeys: [Pubkey; BUY_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
global: pubkeys[0],
|
|
fee_recipient: pubkeys[1],
|
|
mint: pubkeys[2],
|
|
bonding_curve: pubkeys[3],
|
|
associated_bonding_curve: pubkeys[4],
|
|
associated_user: pubkeys[5],
|
|
user: pubkeys[6],
|
|
system_program: pubkeys[7],
|
|
token_program: pubkeys[8],
|
|
rent: pubkeys[9],
|
|
event_authority: pubkeys[10],
|
|
program: pubkeys[11],
|
|
}
|
|
}
|
|
}
|
|
impl<'info> From<BuyAccounts<'_, 'info>> for [AccountInfo<'info>; BUY_IX_ACCOUNTS_LEN] {
|
|
fn from(accounts: BuyAccounts<'_, 'info>) -> Self {
|
|
[
|
|
accounts.global.clone(),
|
|
accounts.fee_recipient.clone(),
|
|
accounts.mint.clone(),
|
|
accounts.bonding_curve.clone(),
|
|
accounts.associated_bonding_curve.clone(),
|
|
accounts.associated_user.clone(),
|
|
accounts.user.clone(),
|
|
accounts.system_program.clone(),
|
|
accounts.token_program.clone(),
|
|
accounts.rent.clone(),
|
|
accounts.event_authority.clone(),
|
|
accounts.program.clone(),
|
|
]
|
|
}
|
|
}
|
|
impl<'me, 'info> From<&'me [AccountInfo<'info>; BUY_IX_ACCOUNTS_LEN]> for BuyAccounts<'me, 'info> {
|
|
fn from(arr: &'me [AccountInfo<'info>; BUY_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
global: &arr[0],
|
|
fee_recipient: &arr[1],
|
|
mint: &arr[2],
|
|
bonding_curve: &arr[3],
|
|
associated_bonding_curve: &arr[4],
|
|
associated_user: &arr[5],
|
|
user: &arr[6],
|
|
system_program: &arr[7],
|
|
token_program: &arr[8],
|
|
rent: &arr[9],
|
|
event_authority: &arr[10],
|
|
program: &arr[11],
|
|
}
|
|
}
|
|
}
|
|
pub const BUY_IX_DISCM: [u8; 8] = [102, 6, 61, 18, 1, 218, 235, 234];
|
|
#[derive(BorshDeserialize, BorshSerialize, Clone, Debug, PartialEq, Default)]
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
pub struct BuyIxArgs {
|
|
pub amount: u64,
|
|
pub max_sol_cost: u64,
|
|
}
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct BuyIxData(pub BuyIxArgs);
|
|
impl From<BuyIxArgs> for BuyIxData {
|
|
fn from(args: BuyIxArgs) -> Self {
|
|
Self(args)
|
|
}
|
|
}
|
|
impl BuyIxData {
|
|
pub fn deserialize(buf: &[u8]) -> std::io::Result<Self> {
|
|
let mut reader = buf;
|
|
let mut maybe_discm = [0u8; 8];
|
|
reader.read_exact(&mut maybe_discm)?;
|
|
if maybe_discm != BUY_IX_DISCM {
|
|
return Err(std::io::Error::new(
|
|
std::io::ErrorKind::Other,
|
|
format!(
|
|
"discm does not match. Expected: {:?}. Received: {:?}",
|
|
BUY_IX_DISCM, maybe_discm
|
|
),
|
|
));
|
|
}
|
|
Ok(Self(BuyIxArgs::deserialize(&mut reader)?))
|
|
}
|
|
pub fn serialize<W: std::io::Write>(&self, mut writer: W) -> std::io::Result<()> {
|
|
writer.write_all(&BUY_IX_DISCM)?;
|
|
self.0.serialize(&mut writer)
|
|
}
|
|
pub fn try_to_vec(&self) -> std::io::Result<Vec<u8>> {
|
|
let mut data = Vec::new();
|
|
self.serialize(&mut data)?;
|
|
Ok(data)
|
|
}
|
|
}
|
|
pub fn buy_ix_with_program_id(
|
|
program_id: Pubkey,
|
|
keys: BuyKeys,
|
|
args: BuyIxArgs,
|
|
) -> std::io::Result<Instruction> {
|
|
let metas: [AccountMeta; BUY_IX_ACCOUNTS_LEN] = keys.into();
|
|
let data: BuyIxData = args.into();
|
|
Ok(Instruction {
|
|
program_id,
|
|
accounts: Vec::from(metas),
|
|
data: data.try_to_vec()?,
|
|
})
|
|
}
|
|
pub fn buy_ix(keys: BuyKeys, args: BuyIxArgs) -> std::io::Result<Instruction> {
|
|
buy_ix_with_program_id(crate::ID, keys, args)
|
|
}
|
|
pub fn buy_invoke_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: BuyAccounts<'_, '_>,
|
|
args: BuyIxArgs,
|
|
) -> ProgramResult {
|
|
let keys: BuyKeys = accounts.into();
|
|
let ix = buy_ix_with_program_id(program_id, keys, args)?;
|
|
invoke_instruction(&ix, accounts)
|
|
}
|
|
pub fn buy_invoke(accounts: BuyAccounts<'_, '_>, args: BuyIxArgs) -> ProgramResult {
|
|
buy_invoke_with_program_id(crate::ID, accounts, args)
|
|
}
|
|
pub fn buy_invoke_signed_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: BuyAccounts<'_, '_>,
|
|
args: BuyIxArgs,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
let keys: BuyKeys = accounts.into();
|
|
let ix = buy_ix_with_program_id(program_id, keys, args)?;
|
|
invoke_instruction_signed(&ix, accounts, seeds)
|
|
}
|
|
pub fn buy_invoke_signed(
|
|
accounts: BuyAccounts<'_, '_>,
|
|
args: BuyIxArgs,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
buy_invoke_signed_with_program_id(crate::ID, accounts, args, seeds)
|
|
}
|
|
pub fn buy_verify_account_keys(
|
|
accounts: BuyAccounts<'_, '_>,
|
|
keys: BuyKeys,
|
|
) -> Result<(), (Pubkey, Pubkey)> {
|
|
for (actual, expected) in [
|
|
(*accounts.global.key, keys.global),
|
|
(*accounts.fee_recipient.key, keys.fee_recipient),
|
|
(*accounts.mint.key, keys.mint),
|
|
(*accounts.bonding_curve.key, keys.bonding_curve),
|
|
(
|
|
*accounts.associated_bonding_curve.key,
|
|
keys.associated_bonding_curve,
|
|
),
|
|
(*accounts.associated_user.key, keys.associated_user),
|
|
(*accounts.user.key, keys.user),
|
|
(*accounts.system_program.key, keys.system_program),
|
|
(*accounts.token_program.key, keys.token_program),
|
|
(*accounts.rent.key, keys.rent),
|
|
(*accounts.event_authority.key, keys.event_authority),
|
|
(*accounts.program.key, keys.program),
|
|
] {
|
|
if actual != expected {
|
|
return Err((actual, expected));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn buy_verify_writable_privileges<'me, 'info>(
|
|
accounts: BuyAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_writable in [
|
|
accounts.fee_recipient,
|
|
accounts.bonding_curve,
|
|
accounts.associated_bonding_curve,
|
|
accounts.associated_user,
|
|
accounts.user,
|
|
] {
|
|
if !should_be_writable.is_writable {
|
|
return Err((should_be_writable, ProgramError::InvalidAccountData));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn buy_verify_signer_privileges<'me, 'info>(
|
|
accounts: BuyAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_signer in [accounts.user] {
|
|
if !should_be_signer.is_signer {
|
|
return Err((should_be_signer, ProgramError::MissingRequiredSignature));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn buy_verify_account_privileges<'me, 'info>(
|
|
accounts: BuyAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
buy_verify_writable_privileges(accounts)?;
|
|
buy_verify_signer_privileges(accounts)?;
|
|
Ok(())
|
|
}
|
|
pub const SELL_IX_ACCOUNTS_LEN: usize = 12;
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub struct SellAccounts<'me, 'info> {
|
|
pub global: &'me AccountInfo<'info>,
|
|
pub fee_recipient: &'me AccountInfo<'info>,
|
|
pub mint: &'me AccountInfo<'info>,
|
|
pub bonding_curve: &'me AccountInfo<'info>,
|
|
pub associated_bonding_curve: &'me AccountInfo<'info>,
|
|
pub associated_user: &'me AccountInfo<'info>,
|
|
pub user: &'me AccountInfo<'info>,
|
|
pub system_program: &'me AccountInfo<'info>,
|
|
pub associated_token_program: &'me AccountInfo<'info>,
|
|
pub token_program: &'me AccountInfo<'info>,
|
|
pub event_authority: &'me AccountInfo<'info>,
|
|
pub program: &'me AccountInfo<'info>,
|
|
}
|
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
|
pub struct SellKeys {
|
|
pub global: Pubkey,
|
|
pub fee_recipient: Pubkey,
|
|
pub mint: Pubkey,
|
|
pub bonding_curve: Pubkey,
|
|
pub associated_bonding_curve: Pubkey,
|
|
pub associated_user: Pubkey,
|
|
pub user: Pubkey,
|
|
pub system_program: Pubkey,
|
|
pub associated_token_program: Pubkey,
|
|
pub token_program: Pubkey,
|
|
pub event_authority: Pubkey,
|
|
pub program: Pubkey,
|
|
}
|
|
impl From<SellAccounts<'_, '_>> for SellKeys {
|
|
fn from(accounts: SellAccounts) -> Self {
|
|
Self {
|
|
global: *accounts.global.key,
|
|
fee_recipient: *accounts.fee_recipient.key,
|
|
mint: *accounts.mint.key,
|
|
bonding_curve: *accounts.bonding_curve.key,
|
|
associated_bonding_curve: *accounts.associated_bonding_curve.key,
|
|
associated_user: *accounts.associated_user.key,
|
|
user: *accounts.user.key,
|
|
system_program: *accounts.system_program.key,
|
|
associated_token_program: *accounts.associated_token_program.key,
|
|
token_program: *accounts.token_program.key,
|
|
event_authority: *accounts.event_authority.key,
|
|
program: *accounts.program.key,
|
|
}
|
|
}
|
|
}
|
|
impl From<SellKeys> for [AccountMeta; SELL_IX_ACCOUNTS_LEN] {
|
|
fn from(keys: SellKeys) -> Self {
|
|
[
|
|
AccountMeta {
|
|
pubkey: keys.global,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.fee_recipient,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.mint,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.bonding_curve,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.associated_bonding_curve,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.associated_user,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.user,
|
|
is_signer: true,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.system_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.associated_token_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.token_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.event_authority,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
]
|
|
}
|
|
}
|
|
impl From<[Pubkey; SELL_IX_ACCOUNTS_LEN]> for SellKeys {
|
|
fn from(pubkeys: [Pubkey; SELL_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
global: pubkeys[0],
|
|
fee_recipient: pubkeys[1],
|
|
mint: pubkeys[2],
|
|
bonding_curve: pubkeys[3],
|
|
associated_bonding_curve: pubkeys[4],
|
|
associated_user: pubkeys[5],
|
|
user: pubkeys[6],
|
|
system_program: pubkeys[7],
|
|
associated_token_program: pubkeys[8],
|
|
token_program: pubkeys[9],
|
|
event_authority: pubkeys[10],
|
|
program: pubkeys[11],
|
|
}
|
|
}
|
|
}
|
|
impl<'info> From<SellAccounts<'_, 'info>> for [AccountInfo<'info>; SELL_IX_ACCOUNTS_LEN] {
|
|
fn from(accounts: SellAccounts<'_, 'info>) -> Self {
|
|
[
|
|
accounts.global.clone(),
|
|
accounts.fee_recipient.clone(),
|
|
accounts.mint.clone(),
|
|
accounts.bonding_curve.clone(),
|
|
accounts.associated_bonding_curve.clone(),
|
|
accounts.associated_user.clone(),
|
|
accounts.user.clone(),
|
|
accounts.system_program.clone(),
|
|
accounts.associated_token_program.clone(),
|
|
accounts.token_program.clone(),
|
|
accounts.event_authority.clone(),
|
|
accounts.program.clone(),
|
|
]
|
|
}
|
|
}
|
|
impl<'me, 'info> From<&'me [AccountInfo<'info>; SELL_IX_ACCOUNTS_LEN]>
|
|
for SellAccounts<'me, 'info>
|
|
{
|
|
fn from(arr: &'me [AccountInfo<'info>; SELL_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
global: &arr[0],
|
|
fee_recipient: &arr[1],
|
|
mint: &arr[2],
|
|
bonding_curve: &arr[3],
|
|
associated_bonding_curve: &arr[4],
|
|
associated_user: &arr[5],
|
|
user: &arr[6],
|
|
system_program: &arr[7],
|
|
associated_token_program: &arr[8],
|
|
token_program: &arr[9],
|
|
event_authority: &arr[10],
|
|
program: &arr[11],
|
|
}
|
|
}
|
|
}
|
|
pub const SELL_IX_DISCM: [u8; 8] = [51, 230, 133, 164, 1, 127, 131, 173];
|
|
#[derive(BorshDeserialize, BorshSerialize, Clone, Debug, PartialEq, Default)]
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
pub struct SellIxArgs {
|
|
pub amount: u64,
|
|
pub min_sol_output: u64,
|
|
}
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct SellIxData(pub SellIxArgs);
|
|
impl From<SellIxArgs> for SellIxData {
|
|
fn from(args: SellIxArgs) -> Self {
|
|
Self(args)
|
|
}
|
|
}
|
|
impl SellIxData {
|
|
pub fn deserialize(buf: &[u8]) -> std::io::Result<Self> {
|
|
let mut reader = buf;
|
|
let mut maybe_discm = [0u8; 8];
|
|
reader.read_exact(&mut maybe_discm)?;
|
|
if maybe_discm != SELL_IX_DISCM {
|
|
return Err(std::io::Error::new(
|
|
std::io::ErrorKind::Other,
|
|
format!(
|
|
"discm does not match. Expected: {:?}. Received: {:?}",
|
|
SELL_IX_DISCM, maybe_discm
|
|
),
|
|
));
|
|
}
|
|
Ok(Self(SellIxArgs::deserialize(&mut reader)?))
|
|
}
|
|
pub fn serialize<W: std::io::Write>(&self, mut writer: W) -> std::io::Result<()> {
|
|
writer.write_all(&SELL_IX_DISCM)?;
|
|
self.0.serialize(&mut writer)
|
|
}
|
|
pub fn try_to_vec(&self) -> std::io::Result<Vec<u8>> {
|
|
let mut data = Vec::new();
|
|
self.serialize(&mut data)?;
|
|
Ok(data)
|
|
}
|
|
}
|
|
pub fn sell_ix_with_program_id(
|
|
program_id: Pubkey,
|
|
keys: SellKeys,
|
|
args: SellIxArgs,
|
|
) -> std::io::Result<Instruction> {
|
|
let metas: [AccountMeta; SELL_IX_ACCOUNTS_LEN] = keys.into();
|
|
let data: SellIxData = args.into();
|
|
Ok(Instruction {
|
|
program_id,
|
|
accounts: Vec::from(metas),
|
|
data: data.try_to_vec()?,
|
|
})
|
|
}
|
|
pub fn sell_ix(keys: SellKeys, args: SellIxArgs) -> std::io::Result<Instruction> {
|
|
sell_ix_with_program_id(crate::ID, keys, args)
|
|
}
|
|
pub fn sell_invoke_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: SellAccounts<'_, '_>,
|
|
args: SellIxArgs,
|
|
) -> ProgramResult {
|
|
let keys: SellKeys = accounts.into();
|
|
let ix = sell_ix_with_program_id(program_id, keys, args)?;
|
|
invoke_instruction(&ix, accounts)
|
|
}
|
|
pub fn sell_invoke(accounts: SellAccounts<'_, '_>, args: SellIxArgs) -> ProgramResult {
|
|
sell_invoke_with_program_id(crate::ID, accounts, args)
|
|
}
|
|
pub fn sell_invoke_signed_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: SellAccounts<'_, '_>,
|
|
args: SellIxArgs,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
let keys: SellKeys = accounts.into();
|
|
let ix = sell_ix_with_program_id(program_id, keys, args)?;
|
|
invoke_instruction_signed(&ix, accounts, seeds)
|
|
}
|
|
pub fn sell_invoke_signed(
|
|
accounts: SellAccounts<'_, '_>,
|
|
args: SellIxArgs,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
sell_invoke_signed_with_program_id(crate::ID, accounts, args, seeds)
|
|
}
|
|
pub fn sell_verify_account_keys(
|
|
accounts: SellAccounts<'_, '_>,
|
|
keys: SellKeys,
|
|
) -> Result<(), (Pubkey, Pubkey)> {
|
|
for (actual, expected) in [
|
|
(*accounts.global.key, keys.global),
|
|
(*accounts.fee_recipient.key, keys.fee_recipient),
|
|
(*accounts.mint.key, keys.mint),
|
|
(*accounts.bonding_curve.key, keys.bonding_curve),
|
|
(
|
|
*accounts.associated_bonding_curve.key,
|
|
keys.associated_bonding_curve,
|
|
),
|
|
(*accounts.associated_user.key, keys.associated_user),
|
|
(*accounts.user.key, keys.user),
|
|
(*accounts.system_program.key, keys.system_program),
|
|
(
|
|
*accounts.associated_token_program.key,
|
|
keys.associated_token_program,
|
|
),
|
|
(*accounts.token_program.key, keys.token_program),
|
|
(*accounts.event_authority.key, keys.event_authority),
|
|
(*accounts.program.key, keys.program),
|
|
] {
|
|
if actual != expected {
|
|
return Err((actual, expected));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn sell_verify_writable_privileges<'me, 'info>(
|
|
accounts: SellAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_writable in [
|
|
accounts.fee_recipient,
|
|
accounts.bonding_curve,
|
|
accounts.associated_bonding_curve,
|
|
accounts.associated_user,
|
|
accounts.user,
|
|
] {
|
|
if !should_be_writable.is_writable {
|
|
return Err((should_be_writable, ProgramError::InvalidAccountData));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn sell_verify_signer_privileges<'me, 'info>(
|
|
accounts: SellAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_signer in [accounts.user] {
|
|
if !should_be_signer.is_signer {
|
|
return Err((should_be_signer, ProgramError::MissingRequiredSignature));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn sell_verify_account_privileges<'me, 'info>(
|
|
accounts: SellAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
sell_verify_writable_privileges(accounts)?;
|
|
sell_verify_signer_privileges(accounts)?;
|
|
Ok(())
|
|
}
|
|
pub const WITHDRAW_IX_ACCOUNTS_LEN: usize = 11;
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub struct WithdrawAccounts<'me, 'info> {
|
|
pub global: &'me AccountInfo<'info>,
|
|
pub mint: &'me AccountInfo<'info>,
|
|
pub bonding_curve: &'me AccountInfo<'info>,
|
|
pub associated_bonding_curve: &'me AccountInfo<'info>,
|
|
pub associated_user: &'me AccountInfo<'info>,
|
|
pub user: &'me AccountInfo<'info>,
|
|
pub system_program: &'me AccountInfo<'info>,
|
|
pub token_program: &'me AccountInfo<'info>,
|
|
pub rent: &'me AccountInfo<'info>,
|
|
pub event_authority: &'me AccountInfo<'info>,
|
|
pub program: &'me AccountInfo<'info>,
|
|
}
|
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
|
pub struct WithdrawKeys {
|
|
pub global: Pubkey,
|
|
pub mint: Pubkey,
|
|
pub bonding_curve: Pubkey,
|
|
pub associated_bonding_curve: Pubkey,
|
|
pub associated_user: Pubkey,
|
|
pub user: Pubkey,
|
|
pub system_program: Pubkey,
|
|
pub token_program: Pubkey,
|
|
pub rent: Pubkey,
|
|
pub event_authority: Pubkey,
|
|
pub program: Pubkey,
|
|
}
|
|
impl From<WithdrawAccounts<'_, '_>> for WithdrawKeys {
|
|
fn from(accounts: WithdrawAccounts) -> Self {
|
|
Self {
|
|
global: *accounts.global.key,
|
|
mint: *accounts.mint.key,
|
|
bonding_curve: *accounts.bonding_curve.key,
|
|
associated_bonding_curve: *accounts.associated_bonding_curve.key,
|
|
associated_user: *accounts.associated_user.key,
|
|
user: *accounts.user.key,
|
|
system_program: *accounts.system_program.key,
|
|
token_program: *accounts.token_program.key,
|
|
rent: *accounts.rent.key,
|
|
event_authority: *accounts.event_authority.key,
|
|
program: *accounts.program.key,
|
|
}
|
|
}
|
|
}
|
|
impl From<WithdrawKeys> for [AccountMeta; WITHDRAW_IX_ACCOUNTS_LEN] {
|
|
fn from(keys: WithdrawKeys) -> Self {
|
|
[
|
|
AccountMeta {
|
|
pubkey: keys.global,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.mint,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.bonding_curve,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.associated_bonding_curve,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.associated_user,
|
|
is_signer: false,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.user,
|
|
is_signer: true,
|
|
is_writable: true,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.system_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.token_program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.rent,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.event_authority,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
AccountMeta {
|
|
pubkey: keys.program,
|
|
is_signer: false,
|
|
is_writable: false,
|
|
},
|
|
]
|
|
}
|
|
}
|
|
impl From<[Pubkey; WITHDRAW_IX_ACCOUNTS_LEN]> for WithdrawKeys {
|
|
fn from(pubkeys: [Pubkey; WITHDRAW_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
global: pubkeys[0],
|
|
mint: pubkeys[1],
|
|
bonding_curve: pubkeys[2],
|
|
associated_bonding_curve: pubkeys[3],
|
|
associated_user: pubkeys[4],
|
|
user: pubkeys[5],
|
|
system_program: pubkeys[6],
|
|
token_program: pubkeys[7],
|
|
rent: pubkeys[8],
|
|
event_authority: pubkeys[9],
|
|
program: pubkeys[10],
|
|
}
|
|
}
|
|
}
|
|
impl<'info> From<WithdrawAccounts<'_, 'info>> for [AccountInfo<'info>; WITHDRAW_IX_ACCOUNTS_LEN] {
|
|
fn from(accounts: WithdrawAccounts<'_, 'info>) -> Self {
|
|
[
|
|
accounts.global.clone(),
|
|
accounts.mint.clone(),
|
|
accounts.bonding_curve.clone(),
|
|
accounts.associated_bonding_curve.clone(),
|
|
accounts.associated_user.clone(),
|
|
accounts.user.clone(),
|
|
accounts.system_program.clone(),
|
|
accounts.token_program.clone(),
|
|
accounts.rent.clone(),
|
|
accounts.event_authority.clone(),
|
|
accounts.program.clone(),
|
|
]
|
|
}
|
|
}
|
|
impl<'me, 'info> From<&'me [AccountInfo<'info>; WITHDRAW_IX_ACCOUNTS_LEN]>
|
|
for WithdrawAccounts<'me, 'info>
|
|
{
|
|
fn from(arr: &'me [AccountInfo<'info>; WITHDRAW_IX_ACCOUNTS_LEN]) -> Self {
|
|
Self {
|
|
global: &arr[0],
|
|
mint: &arr[1],
|
|
bonding_curve: &arr[2],
|
|
associated_bonding_curve: &arr[3],
|
|
associated_user: &arr[4],
|
|
user: &arr[5],
|
|
system_program: &arr[6],
|
|
token_program: &arr[7],
|
|
rent: &arr[8],
|
|
event_authority: &arr[9],
|
|
program: &arr[10],
|
|
}
|
|
}
|
|
}
|
|
pub const WITHDRAW_IX_DISCM: [u8; 8] = [183, 18, 70, 156, 148, 109, 161, 34];
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct WithdrawIxData;
|
|
impl WithdrawIxData {
|
|
pub fn deserialize(buf: &[u8]) -> std::io::Result<Self> {
|
|
let mut reader = buf;
|
|
let mut maybe_discm = [0u8; 8];
|
|
reader.read_exact(&mut maybe_discm)?;
|
|
if maybe_discm != WITHDRAW_IX_DISCM {
|
|
return Err(std::io::Error::new(
|
|
std::io::ErrorKind::Other,
|
|
format!(
|
|
"discm does not match. Expected: {:?}. Received: {:?}",
|
|
WITHDRAW_IX_DISCM, maybe_discm
|
|
),
|
|
));
|
|
}
|
|
Ok(Self)
|
|
}
|
|
pub fn serialize<W: std::io::Write>(&self, mut writer: W) -> std::io::Result<()> {
|
|
writer.write_all(&WITHDRAW_IX_DISCM)
|
|
}
|
|
pub fn try_to_vec(&self) -> std::io::Result<Vec<u8>> {
|
|
let mut data = Vec::new();
|
|
self.serialize(&mut data)?;
|
|
Ok(data)
|
|
}
|
|
}
|
|
pub fn withdraw_ix_with_program_id(
|
|
program_id: Pubkey,
|
|
keys: WithdrawKeys,
|
|
) -> std::io::Result<Instruction> {
|
|
let metas: [AccountMeta; WITHDRAW_IX_ACCOUNTS_LEN] = keys.into();
|
|
Ok(Instruction {
|
|
program_id,
|
|
accounts: Vec::from(metas),
|
|
data: WithdrawIxData.try_to_vec()?,
|
|
})
|
|
}
|
|
pub fn withdraw_ix(keys: WithdrawKeys) -> std::io::Result<Instruction> {
|
|
withdraw_ix_with_program_id(crate::ID, keys)
|
|
}
|
|
pub fn withdraw_invoke_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: WithdrawAccounts<'_, '_>,
|
|
) -> ProgramResult {
|
|
let keys: WithdrawKeys = accounts.into();
|
|
let ix = withdraw_ix_with_program_id(program_id, keys)?;
|
|
invoke_instruction(&ix, accounts)
|
|
}
|
|
pub fn withdraw_invoke(accounts: WithdrawAccounts<'_, '_>) -> ProgramResult {
|
|
withdraw_invoke_with_program_id(crate::ID, accounts)
|
|
}
|
|
pub fn withdraw_invoke_signed_with_program_id(
|
|
program_id: Pubkey,
|
|
accounts: WithdrawAccounts<'_, '_>,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
let keys: WithdrawKeys = accounts.into();
|
|
let ix = withdraw_ix_with_program_id(program_id, keys)?;
|
|
invoke_instruction_signed(&ix, accounts, seeds)
|
|
}
|
|
pub fn withdraw_invoke_signed(
|
|
accounts: WithdrawAccounts<'_, '_>,
|
|
seeds: &[&[&[u8]]],
|
|
) -> ProgramResult {
|
|
withdraw_invoke_signed_with_program_id(crate::ID, accounts, seeds)
|
|
}
|
|
pub fn withdraw_verify_account_keys(
|
|
accounts: WithdrawAccounts<'_, '_>,
|
|
keys: WithdrawKeys,
|
|
) -> Result<(), (Pubkey, Pubkey)> {
|
|
for (actual, expected) in [
|
|
(*accounts.global.key, keys.global),
|
|
(*accounts.mint.key, keys.mint),
|
|
(*accounts.bonding_curve.key, keys.bonding_curve),
|
|
(
|
|
*accounts.associated_bonding_curve.key,
|
|
keys.associated_bonding_curve,
|
|
),
|
|
(*accounts.associated_user.key, keys.associated_user),
|
|
(*accounts.user.key, keys.user),
|
|
(*accounts.system_program.key, keys.system_program),
|
|
(*accounts.token_program.key, keys.token_program),
|
|
(*accounts.rent.key, keys.rent),
|
|
(*accounts.event_authority.key, keys.event_authority),
|
|
(*accounts.program.key, keys.program),
|
|
] {
|
|
if actual != expected {
|
|
return Err((actual, expected));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn withdraw_verify_writable_privileges<'me, 'info>(
|
|
accounts: WithdrawAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_writable in [
|
|
accounts.bonding_curve,
|
|
accounts.associated_bonding_curve,
|
|
accounts.associated_user,
|
|
accounts.user,
|
|
] {
|
|
if !should_be_writable.is_writable {
|
|
return Err((should_be_writable, ProgramError::InvalidAccountData));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn withdraw_verify_signer_privileges<'me, 'info>(
|
|
accounts: WithdrawAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
for should_be_signer in [accounts.user] {
|
|
if !should_be_signer.is_signer {
|
|
return Err((should_be_signer, ProgramError::MissingRequiredSignature));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn withdraw_verify_account_privileges<'me, 'info>(
|
|
accounts: WithdrawAccounts<'me, 'info>,
|
|
) -> Result<(), (&'me AccountInfo<'info>, ProgramError)> {
|
|
withdraw_verify_writable_privileges(accounts)?;
|
|
withdraw_verify_signer_privileges(accounts)?;
|
|
Ok(())
|
|
}
|