Reputation: 1388
Folks, I'm starting with Solana and it's been rough to learn. Despite the poor error messages and the learning curve of Rust, I'm making my way through it.
I'm trying to develop a new token that will be a fungible asset (0 decimals, supply greater than 1 for the same token).
In another transaction, I already created a mint account and initialized it. Now I'm trying to mint that to another wallet. Basically, this is mint accounts context (for simplicity reasons I've excluded the metadata accounts):
pub struct MintAsset<'info> {
#[account(mut)]
pub mint: Account<'info, token::Mint>,
#[account(mut)]
pub mint_authority: Signer<'info>,
/// CHECK: We're about to create this with Anchor
#[account(mut)]
pub minter_token: UncheckedAccount<'info>,
#[account(mut)]
pub payer: Signer<'info>,
pub rent: Sysvar<'info, Rent>,
pub system_program: Program<'info, System>,
pub token_program: Program<'info, token::Token>,
pub associated_token_program: Program<'info, associated_token::AssociatedToken>,
}
Then, I proceed to run this transaction for minting my tokens
pub fn mint_asset(ctx: Context<MintAsset>, data: MintArgs) -> Result<()> {
associated_token::create(
CpiContext::new(
ctx.accounts.associated_token_program.to_account_info(),
associated_token::Create {
payer: ctx.accounts.mint_authority.to_account_info(),
associated_token: ctx.accounts.minter_token.to_account_info(),
authority: ctx.accounts.mint_authority.to_account_info(),
mint: ctx.accounts.mint.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
token_program: ctx.accounts.token_program.to_account_info(),
rent: ctx.accounts.rent.to_account_info(),
},
),
)?;
token::mint_to(
CpiContext::new(
ctx.accounts.token_program.to_account_info(),
token::MintTo {
mint: ctx.accounts.mint.to_account_info(),
to: ctx.accounts.minter_token.to_account_info(),
authority: ctx.accounts.mint_authority.to_account_info(),
},
),
data.amount,
)?;
Ok(())
}
By using the following test:
async function mintToken(
program: anchor.Program<Pdas>,
wallet: anchor.Wallet,
mintKeypair: anchor.web3.Keypair,
minterWallet: anchor.Wallet,
amount: number
) {
try {
const buyerTokenAddress = await anchor.utils.token.associatedAddress({
mint: mintKeypair.publicKey,
owner: wallet.publicKey,
});
const accounts = {
mint: mintKeypair.publicKey,
mintAuthority: wallet.publicKey,
minterToken: buyerTokenAddress,
payer: wallet.publicKey,
};
const signers = [];
const args = {
amount: new BN(amount),
};
const signature = await program.methods
.mintAsset(args)
.accounts(accounts)
.signers(signers)
.rpc();
} catch (error) {
console.log("MINT ERROR:", inspect({ error }, { depth: null }));
}
}
Now, that test throws an error if for the buyerTokenAddress
I use the minterWallet
as owner. I understand that for owning a token, one must have an associated token account, which, as stated by the documentation, is an
account for a given wallet address is simply a program-derived account consisting of the wallet address itself and the token mint
https://spl.solana.com/associated-token-account
Why's that? I mean, doesn't anyone can mint a this token? I understand that only the mintAuthority
can mint the tokens, but it makes sense to have it as a signer (as accounts struct expect), but (and here's another question) if I put an empty array of signers, the code still runs (again, why is that? I thought I had to provide an signer account at least for mint_authority
).
Should I create a new mint account and initialize it? Wouldn't that be a new token, instead?
What is obvious in Solana token development that I'm missing here? Thanks in advance
Upvotes: 0
Views: 1130
Reputation: 101
I may not be able to answer your first question properly, so I'm leaving that for someone more experienced. For your second question you are right about signer, as you are using anchor it implicitly takes owner wallet from configuration (anchor.toml file) and signs it. if you provide your wallet.key in signer array there will be no difference. because anchor does that so generally that isn't provided in signers[]
Upvotes: 0