1

I used the following code from

https://solana.com/es/developers/guides/token-extensions/metadata-pointer reference.

It's a sample I've seen around which stores Metadata in a metadata-pointer mint account. The code is below if you haven't seen it before.

So it has created the mint account and logged the keys, metadata and mintInfo and now I want to mint some tokens to my wallet.

I tried using the mint Account produced by the refernced code, but I get:

Simulation failed. 
Message: Transaction simulation failed: Error processing Instruction 0: invalid account data for instruction. 
Logs: 
[
  "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [1]",
  "Program log: Instruction: MintTo",
  "Program log: Error: InvalidAccountData",
  "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1081 of 200000 compute units",
  "Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb failed: invalid account data for instruction"
]. 

Would that be because the mint account isn't a token account?

Do I have to create a new token account, then mint to that? Then how to I associate the metadata to the new mint?

Perhaps if I create a new account and an associated account linking my wallet to it then mint to that, I'll have the data to create the medadata account for it?

Original metadata creation.

import {
  Connection,
  Keypair,
  SystemProgram,
  Transaction,
  clusterApiUrl,
  sendAndConfirmTransaction,
} from "@solana/web3.js";

import {
  ExtensionType,
  TOKEN_2022_PROGRAM_ID,
  createInitializeMintInstruction,
  getMintLen,
  createInitializeMetadataPointerInstruction,
  getMint,
  getMetadataPointerState,
  getTokenMetadata,
  TYPE_SIZE,
  LENGTH_SIZE,
} from "@solana/spl-token";
import {
  createInitializeInstruction,
  createUpdateFieldInstruction,
  createRemoveKeyInstruction,
  pack,
  TokenMetadata,
} from "@solana/spl-token-metadata";

// Playground wallet
const payer = pg.wallet.keypair;

// Connection to devnet cluster
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");

// Transaction to send
let transaction: Transaction;
// Transaction signature returned from sent transaction
let transactionSignature: string;

// Generate new keypair for Mint Account
const mintKeypair = Keypair.generate();
// Address for Mint Account
const mint = mintKeypair.publicKey;
// Decimals for Mint Account
const decimals = 2;
// Authority that can mint new tokens
const mintAuthority = pg.wallet.publicKey;
// Authority that can update token metadata
const updateAuthority = pg.wallet.publicKey;

// Metadata to store in Mint Account
const metaData: TokenMetadata = {
  updateAuthority: updateAuthority,
  mint: mint,
  name: "OPOS",
  symbol: "OPOS",
  uri: "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json",
  additionalMetadata: [["description", "Only Possible On Solana"]],
};

// Size of MetadataExtension 2 bytes for type, 2 bytes for length
const metadataExtension = TYPE_SIZE + LENGTH_SIZE;
// Size of metadata
const metadataLen = pack(metaData).length;

// Size of Mint Account with extension
const mintLen = getMintLen([ExtensionType.MetadataPointer]);

// Minimum lamports required for Mint Account
const lamports = await connection.getMinimumBalanceForRentExemption(
  mintLen + metadataExtension + metadataLen
);

// Instruction to invoke System Program to create new account
const createAccountInstruction = SystemProgram.createAccount({
  fromPubkey: payer.publicKey, // Account that will transfer lamports to created account
  newAccountPubkey: mint, // Address of the account to create
  space: mintLen, // Amount of bytes to allocate to the created account
  lamports, // Amount of lamports transferred to created account
  programId: TOKEN_2022_PROGRAM_ID, // Program assigned as owner of created account
});

// Instruction to initialize the MetadataPointer Extension
const initializeMetadataPointerInstruction =
  createInitializeMetadataPointerInstruction(
    mint, // Mint Account address
    updateAuthority, // Authority that can set the metadata address
    mint, // Account address that holds the metadata
    TOKEN_2022_PROGRAM_ID
  );

// Instruction to initialize Mint Account data
const initializeMintInstruction = createInitializeMintInstruction(
  mint, // Mint Account Address
  decimals, // Decimals of Mint
  mintAuthority, // Designated Mint Authority
  null, // Optional Freeze Authority
  TOKEN_2022_PROGRAM_ID // Token Extension Program ID
);

// Instruction to initialize Metadata Account data
const initializeMetadataInstruction = createInitializeInstruction({
  programId: TOKEN_2022_PROGRAM_ID, // Token Extension Program as Metadata Program
  metadata: mint, // Account address that holds the metadata
  updateAuthority: updateAuthority, // Authority that can update the metadata
  mint: mint, // Mint Account address
  mintAuthority: mintAuthority, // Designated Mint Authority
  name: metaData.name,
  symbol: metaData.symbol,
  uri: metaData.uri,
});

// Instruction to update metadata, adding custom field
const updateFieldInstruction = createUpdateFieldInstruction({
  programId: TOKEN_2022_PROGRAM_ID, // Token Extension Program as Metadata Program
  metadata: mint, // Account address that holds the metadata
  updateAuthority: updateAuthority, // Authority that can update the metadata
  field: metaData.additionalMetadata[0][0], // key
  value: metaData.additionalMetadata[0][1], // value
});

// Add instructions to new transaction
transaction = new Transaction().add(
  createAccountInstruction,
  initializeMetadataPointerInstruction,
  initializeMintInstruction,
  initializeMetadataInstruction,
  updateFieldInstruction
);

// Send transaction
transactionSignature = await sendAndConfirmTransaction(
  connection,
  transaction,
  [payer, mintKeypair] // Signers
);

console.log(
  "\nCreate Mint Account:",
  `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`
);

// Retrieve mint information
const mintInfo = await getMint(
  connection,
  mint,
  "confirmed",
  TOKEN_2022_PROGRAM_ID
);

// Retrieve and log the metadata pointer state
const metadataPointer = getMetadataPointerState(mintInfo);
console.log("\nMetadata Pointer:", JSON.stringify(metadataPointer, null, 2));

// Retrieve and log the metadata state
const metadata = await getTokenMetadata(
  connection,
  mint // Mint Account address
);
console.log("\nMetadata:", JSON.stringify(metadata, null, 2));

// Instruction to remove a key from the metadata
const removeKeyInstruction = createRemoveKeyInstruction({
  programId: TOKEN_2022_PROGRAM_ID, // Token Extension Program as Metadata Program
  metadata: mint, // Address of the metadata
  updateAuthority: updateAuthority, // Authority that can update the metadata
  key: metaData.additionalMetadata[0][0], // Key to remove from the metadata
  idempotent: true, // If the idempotent flag is set to true, then the instruction will not error if the key does not exist
});

// Add instruction to new transaction
transaction = new Transaction().add(removeKeyInstruction);

// Send transaction
transactionSignature = await sendAndConfirmTransaction(
  connection,
  transaction,
  [payer]
);

console.log(
  "\nRemove Additional Metadata Field:",
  `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`
);

// Retrieve and log the metadata state
const updatedMetadata = await getTokenMetadata(
  connection,
  mint // Mint Account address
);
console.log("\nUpdated Metadata:", JSON.stringify(updatedMetadata, null, 2));

console.log(
  "\nMint Account:",
  `https://solana.fm/address/${mint}?cluster=devnet-solana`
);
5
  • This is the transaction register of the indicated program. Can anyone see why I can't mint tokens from this to my wallet. The same wallet used to create evrything solscan.io/tx/… Commented Jul 11 at 19:12
  • Please provide the failing code -- the successful code is much less interesting, unfortunately
    – Jon C
    Commented Jul 17 at 21:08
  • Thanks for the response Jon. The error, where it says "Simulation Failed" was in repsonse to a mintTo instruction using the newly generated "mint" account trying to send the new tokens to my wallet. I thought the¨purpose of the "good code¨ was to Create a mint acount and link a metadata acount to that, then all that would be needed would be to mint a quantity to a desired wallet. The main point of the question, is "what exactly is the procedure." I'm thinking that I need to create a mint token and mint it to a wallet in the desired quantity and then somehow link the metadata to it all. Commented Jul 19 at 0:19
  • Without seeing how you're using mintTo, it's impossible to see the problem, unfortunately
    – Jon C
    Commented Jul 19 at 9:39
  • OK, thx. At this point I'm not entirely sure how I set it up, I've tried several things. My feeling was that I should mintTo using the original mint (The one created new) as the basis for minting to a wallet. I'll keep trying to figure it out myself. Thanks Commented Jul 19 at 15:07

1 Answer 1

1

I resolved this "problem".

The example code does actually mint a metadata pointer, which does need to eventually be sent to a wallet which I had tried to do, with the resulting error mentioned above:"invalid account data for instruction".

Although to me that error seems a little misleading it points to the fact that I was trying to mintTo a wallet rather than an "associated token account".

So I needed to execute a "getOrCreateAssociatedTokenAccount" before the "mintTo" instruction and make sure the mintTo instruction pointed to the resultant associated account address.

The Solana documentation gives warnings that before trying to send a newly minted token to a wallet that an account for that token exists for that token... the mint function does not create this account. It's this associated token account that actually ties the new mint to the particular wallet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.