use super::rpc::RpcContext;
use solana_program::system_instruction::create_account;
use solana_pubkey::Pubkey;
use solana_signer::Signer;
use spl_associated_token_account::{get_associated_token_address_with_program_id, instruction::create_associated_token_account_idempotent};
use spl_token_2022::{
extension::{
transfer_fee::instruction::{initialize_transfer_fee_config, set_transfer_fee},
ExtensionType,
},
instruction::{initialize_mint2, mint_to},
state::Mint,
ID as TOKEN_2022_PROGRAM_ID,
};
use std::error::Error;
#[derive(Default)]
pub struct SetupAtaConfig {
pub amount: Option<u64>,
}
pub async fn setup_mint_te(ctx: &RpcContext, extensions: &[ExtensionType]) -> Result<Pubkey, Box<dyn Error>> {
let mint = ctx.get_next_keypair();
let mut instructions = vec![];
let space = ExtensionType::try_calculate_account_len::<Mint>(extensions)?;
let rent = ctx.rpc.get_minimum_balance_for_rent_exemption(space).await?;
instructions.push(create_account(&ctx.signer.pubkey(), &mint.pubkey(), rent, space as u64, &TOKEN_2022_PROGRAM_ID));
for extension in extensions {
if extension == &ExtensionType::TransferFeeConfig {
instructions.push(initialize_transfer_fee_config(
&TOKEN_2022_PROGRAM_ID,
&mint.pubkey(),
Some(&ctx.signer.pubkey()),
Some(&ctx.signer.pubkey()),
100, 1_000_000_000, )?);
}
}
instructions.push(initialize_mint2(
&TOKEN_2022_PROGRAM_ID,
&mint.pubkey(),
&ctx.signer.pubkey(),
None, 6, )?);
for extension in extensions {
if extension == &ExtensionType::TransferFeeConfig {
instructions.push(set_transfer_fee(
&TOKEN_2022_PROGRAM_ID,
&mint.pubkey(),
&ctx.signer.pubkey(),
&[],
150, 1_000_000_000, )?);
}
}
ctx.send_transaction_with_signers(instructions, vec![&mint]).await?;
Ok(mint.pubkey())
}
pub async fn setup_mint_te_fee(ctx: &RpcContext) -> Result<Pubkey, Box<dyn Error>> {
setup_mint_te(ctx, &[ExtensionType::TransferFeeConfig]).await
}
pub async fn setup_ata_te(ctx: &RpcContext, mint: Pubkey, config: Option<SetupAtaConfig>) -> Result<Pubkey, Box<dyn Error>> {
let config = config.unwrap_or_default();
let ata = get_associated_token_address_with_program_id(&ctx.signer.pubkey(), &mint, &TOKEN_2022_PROGRAM_ID);
let mut instructions = vec![create_associated_token_account_idempotent(
&ctx.signer.pubkey(),
&ctx.signer.pubkey(),
&mint,
&TOKEN_2022_PROGRAM_ID,
)];
if let Some(amount) = config.amount {
instructions.push(mint_to(&TOKEN_2022_PROGRAM_ID, &mint, &ata, &ctx.signer.pubkey(), &[], amount)?);
}
ctx.send_transaction(instructions).await?;
Ok(ata)
}