Skip to content

Commit

Permalink
feat: added command for minting fungible tokens (#321)
Browse files Browse the repository at this point in the history
* feat: added command for minting fungible tokens

* chore: clippy fixes

* chore: removed unnecessary clippy allow tag and modified doc about command
  • Loading branch information
sunguru98 authored Feb 4, 2024
1 parent db35175 commit 55373fb
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 2 deletions.
88 changes: 88 additions & 0 deletions src/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use retry::{delay::Exponential, retry};
use serde::Serialize;
use serde_json::Value;
use solana_client::rpc_client::RpcClient;
use solana_program::program_pack::Pack;
use solana_sdk::{
commitment_config::CommitmentConfig,
pubkey::Pubkey,
Expand All @@ -36,6 +37,7 @@ use spl_associated_token_account::{
};
use spl_token::{
instruction::{initialize_mint, mint_to},
state::Mint,
ID as TOKEN_PROGRAM_ID,
};
use std::{
Expand Down Expand Up @@ -267,6 +269,92 @@ pub fn mint_from_uris(
Ok(())
}

pub fn mint_fungible(
client: &RpcClient,
keypair_path: Option<String>,
mint_address: &str,
amount: u64,
receiver: &Option<String>,
) -> Result<()> {
let solana_opts = parse_solana_config();
let mint_authority_keypair = parse_keypair(keypair_path, solana_opts);

let mint_authority_pubkey = mint_authority_keypair.pubkey();
let mint_pubkey = Pubkey::from_str(mint_address)?;

let mint_account_info = client
.get_account_with_commitment(&mint_pubkey, CommitmentConfig::confirmed())?
.value;

if mint_account_info.is_none() {
return Err(anyhow!("Invalid Mint Address"));
}

let destination_pubkey = if let Some(receiver_str) = receiver {
Pubkey::from_str(receiver_str)?
} else {
mint_authority_pubkey
};

let destination_ata_pubkey = get_associated_token_address(&destination_pubkey, &mint_pubkey);

let destination_ata_pubkey_info = client
.get_account_with_commitment(&destination_ata_pubkey, CommitmentConfig::confirmed())?
.value;

let mut instructions = vec![];

if destination_ata_pubkey_info.is_none() {
instructions.push(create_associated_token_account(
&mint_authority_pubkey,
&destination_pubkey,
&mint_pubkey,
&TOKEN_PROGRAM_ID,
))
}

let mint_data = Mint::unpack(&mint_account_info.unwrap().data)?;

let mint_amount = amount
.checked_mul(10_u64.pow(mint_data.decimals.into()))
.ok_or(anyhow!("Invalid Mint Amount"))?;

let mint_ix = mint_to(
&TOKEN_PROGRAM_ID,
&mint_pubkey,
&destination_ata_pubkey,
&mint_authority_pubkey,
&[&mint_authority_pubkey],
mint_amount,
)?;

instructions.push(mint_ix);

let recent_blockhash = client.get_latest_blockhash()?;
let tx = Transaction::new_signed_with_payer(
&instructions,
Some(&mint_authority_pubkey),
&[&mint_authority_keypair],
recent_blockhash,
);

// Send tx with retries.
let res = retry(
Exponential::from_millis_with_factor(250, 2.0).take(3),
|| client.send_and_confirm_transaction(&tx),
);
let sig = res?;

println!(
"Mint: {:?} minted {:?} tokens successfully!",
mint_address, amount
);

println!("Created in tx: {:?}", &sig);

Ok(())
}

#[allow(clippy::too_many_arguments)]
pub fn mint_one<P: AsRef<Path>>(
client: &RpcClient,
Expand Down
20 changes: 19 additions & 1 deletion src/opt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ pub enum CreateSubcommands {
immutable: bool,
},

/// Create a new SPL Token mint and metadata account.
/// Mint SPL tokens from an existing mint account using the Token Program.
Fungible {
/// Path to the update authority keypair file
#[structopt(short, long)]
Expand Down Expand Up @@ -852,6 +852,24 @@ pub enum FindSubcommands {

#[derive(Debug, StructOpt)]
pub enum MintSubcommands {
/// Mint a normal SPL Token from the Token Program
Fungible {
/// Path to the mint_authority keypair file
#[structopt(short, long)]
keypair: Option<String>,

/// Token Mint address
#[structopt(short = "M", long)]
mint_address: String,

/// Receiving address, if different from mint authority.
#[structopt(short = "R", long)]
receiver: Option<String>,

/// Amount of tokens to mint
#[structopt(short, long)]
amount: u64,
},
/// Mint an asset from the new Token Metadata Program unified handlers.
Asset {
/// Path to the update_authority keypair file
Expand Down
9 changes: 8 additions & 1 deletion src/process_subcommands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ use crate::derive::{
};
use crate::find::find_missing_editions_process;
use crate::mint::{
mint_editions, mint_list, mint_missing_editions, mint_one, process_mint_asset, MintAssetParams,
mint_editions, mint_fungible, mint_list, mint_missing_editions, mint_one, process_mint_asset,
MintAssetParams,
};
use crate::opt::*;
use crate::parse::{is_only_one_option, parse_errors_code, parse_errors_file};
Expand Down Expand Up @@ -498,6 +499,12 @@ pub fn process_find(client: &RpcClient, commands: FindSubcommands) -> Result<()>

pub fn process_mint(client: RpcClient, commands: MintSubcommands) -> Result<()> {
match commands {
MintSubcommands::Fungible {
keypair,
receiver,
amount,
mint_address,
} => mint_fungible(&client, keypair, &mint_address, amount, &receiver),
MintSubcommands::Asset {
keypair,
receiver,
Expand Down

0 comments on commit 55373fb

Please sign in to comment.