At the execution stage of function createInitializeInstruction
I receive an error:
Error creating token for Token2022Form: TypeError: Cannot read properties of undefined (reading 'call')
at Hash.CipherBase (index.js:7:1)
at new Hash (browser.js:9:1)
at createHash (browser.js:29:1)
at splDiscriminate (splDiscriminate.ts:4:1)
at createInitializeInstruction (instruction.ts:51:1)
at createInitializeInstructionReact (createInitializeInstructionReact.js:21:1)
at Object.create (main.b9dcefd2038733fdf419.hot-update.js:218:495)
at async handleCreateToken2022 (index.jsx:140:1)
name
, symbol
, umi
have string values, mint
, metadata
, minyAuthority
, updateAuthority
have valid values.
Here’s my code:
import { useState } from 'react';
import {
ComputeBudgetProgram,
Connection,
Keypair,
PublicKey,
sendAndConfirmRawTransaction,
SystemProgram,
Transaction,
BlockheightBasedTransactionConfirmationStrategy
} from '@solana/web3.js';
import {
createInitializeInterestBearingMintInstruction,
createInitializeMetadataPointerInstruction,
createInitializeMintCloseAuthorityInstruction,
createInitializeMintInstruction,
createInitializeNonTransferableMintInstruction,
createInitializePermanentDelegateInstruction,
createInitializeTransferFeeConfigInstruction,
createInitializeTransferHookInstruction,
createMintToInstruction,
createAssociatedTokenAccountInstruction,
getAssociatedTokenAddressSync,
ExtensionType,
getMintLen,
LENGTH_SIZE,
TOKEN_2022_PROGRAM_ID,
TYPE_SIZE} from '@solana/spl-token';
import { TokenMetadata, createInitializeInstruction, pack } from '@solana/spl-token-metadata';
import { useWallet } from "@solana/wallet-adapter-react";
import BigNumber from "bignumber.js";
import API_KEY from "../../action/API_KEY/api_key";
import bs58 from "bs58";
export const useToken22Minter = () => {
const network = 'devnet'
const [connection] = useState(new Connection(`https://${network}.helius-rpc.com/?api-key=${API_KEY}`, 'confirmed'));
const { publicKey } = useWallet();
const wallet = useWallet();
const toPublicKey = (k) => {
if (!k) {
return null;
} return new PublicKey(k);
};
const buildExtensionsInstructions = (mint, config, nonTransferableData) => {
const ixs = [];
const extensionsTypes = [ExtensionType.MetadataPointer];
const hasExtensions = Object.values(config).some(value => value);
if (hasExtensions) {
if (config.transferFee) {
ixs.push(
createInitializeTransferFeeConfigInstruction(
mint,
toPublicKey(config.transferFee.transferAuthority),
toPublicKey(config.transferFee.withdrawAuthority),
config.transferFee.basisPoints,
new BigNumber(config.transferFee.maximumFee.toString()),
TOKEN_2022_PROGRAM_ID
)
);
extensionsTypes.push(ExtensionType.TransferFeeConfig);
}
if (config.transferHook) {
ixs.push(
createInitializeTransferHookInstruction(
mint,
toPublicKey(config.transferHook.authority),
toPublicKey(config.transferHook.programId),
TOKEN_2022_PROGRAM_ID
)
);
extensionsTypes.push(ExtensionType.TransferHook);
}
if (config.permanentDelegate) {
ixs.push(
createInitializePermanentDelegateInstruction(
mint,
toPublicKey(config.permanentDelegate.authority),
TOKEN_2022_PROGRAM_ID
)
);
extensionsTypes.push(ExtensionType.PermanentDelegate);
}
if (config.mintCloseAuthority) {
ixs.push(
createInitializeMintCloseAuthorityInstruction(
mint,
toPublicKey(config.mintCloseAuthority.authority),
TOKEN_2022_PROGRAM_ID
)
);
extensionsTypes.push(ExtensionType.MintCloseAuthority);
}
if (config.interestBearing) {
ixs.push(
createInitializeInterestBearingMintInstruction(
mint,
toPublicKey(config.interestBearing.authority),
config.interestBearing.rate,
TOKEN_2022_PROGRAM_ID
)
);
extensionsTypes.push(ExtensionType.InterestBearingConfig);
}
if (nonTransferableData) {
ixs.push(createInitializeNonTransferableMintInstruction(mint, TOKEN_2022_PROGRAM_ID));
extensionsTypes.push(ExtensionType.NonTransferable);
}
}
return { ixs, extensionsTypes };
};
const create = async (metadata = { name: '', symbol: '', uri: '' }, extensionsConfig, amount, decimals2022) => {
const pubKey = publicKey;
const mint = Keypair.generate();
const ata = getAssociatedTokenAddressSync(mint.publicKey, pubKey, undefined, TOKEN_2022_PROGRAM_ID);
const decimals = decimals2022;
const metaData: TokenMetadata = {
mint: mint.publicKey,
name: metadata.name,
symbol: metadata.symbol,
uri: metadata.uri,
additionalMetadata: [],
};
const { ixs, extensionsTypes } = buildExtensionsInstructions(mint.publicKey, extensionsConfig, extensionsConfig.nonTransferable);
const priceIx = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1000000 });
const mintLen = getMintLen(extensionsTypes);
const metadataLen = TYPE_SIZE + LENGTH_SIZE + pack(metaData).length;
const mintLamports = await connection.getMinimumBalanceForRentExemption(mintLen + metadataLen);
const hash = await connection.getLatestBlockhash('confirmed');
const mintTransaction = new Transaction({
feePayer: pubKey,
blockhash: hash.blockhash,
lastValidBlockHeight: hash.lastValidBlockHeight
}).add(
priceIx,
SystemProgram.createAccount({
fromPubkey: pubKey,
newAccountPubkey: mint.publicKey,
space: mintLen,
lamports: mintLamports,
programId: TOKEN_2022_PROGRAM_ID
}),
createInitializeMetadataPointerInstruction(mint.publicKey, pubKey, mint.publicKey, TOKEN_2022_PROGRAM_ID),
...ixs,
createInitializeMintInstruction(mint.publicKey, decimals, pubKey, null, TOKEN_2022_PROGRAM_ID),
createInitializeInstruction({
programId: TOKEN_2022_PROGRAM_ID,
mint: mint.publicKey,
metadata: mint.publicKey,
name: metaData.name,
symbol: metaData.symbol,
uri: metaData.uri,
mintAuthority: pubKey,
updateAuthority: pubKey,
}),
createAssociatedTokenAccountInstruction(pubKey, ata, pubKey, mint.publicKey, TOKEN_2022_PROGRAM_ID),
createMintToInstruction(mint.publicKey, ata, pubKey, new BigNumber(amount), undefined, TOKEN_2022_PROGRAM_ID)
);
mintTransaction.partialSign(mint);
const signedTx = await wallet.signTransaction(mintTransaction);
const rawTx = signedTx.serialize();
const confirmationStrategy: BlockheightBasedTransactionConfirmationStrategy = {
lastValidBlockHeight: hash.lastValidBlockHeight,
signature: bs58.encode(signedTx.signature),
blockhash: hash.blockhash,
};
const signature = await sendAndConfirmRawTransaction(connection, rawTx, confirmationStrategy);
return { mint: mint.publicKey.toString(), signature };
};
return { create };
};
The code for the createInitializeInstruction function in the @solana/spl-token-metadata library:
import type { StructToEncoderTuple } from '@solana/codecs-data-structures';
import { getBooleanEncoder, getBytesEncoder, getDataEnumCodec, getStructEncoder } from '@solana/codecs-data-structures';
import { getU64Encoder } from '@solana/codecs-numbers';
import { getStringEncoder } from '@solana/codecs-strings';
import { getOptionEncoder } from '@solana/options';
import { splDiscriminate } from '@solana/spl-type-length-value';
import type { PublicKey } from '@solana/web3.js';
import { TransactionInstruction } from '@solana/web3.js';
import type { Field } from './field.js';
import { getFieldCodec, getFieldConfig } from './field.js';
function packInstruction<T extends object>(
layout: StructToEncoderTuple<T>,
discriminator: Uint8Array,
values: T): Buffer {
const encoder = getStructEncoder(layout);
const data = encoder.encode(values);
return Buffer.concat([discriminator, data]);
}/** * Initializes a TLV entry with the basic token-metadata fields. * * Assumes that the provided mint is an SPL token mint, that the metadata * account is allocated and assigned to the program, and that the metadata * account has enough lamports to cover the rent-exempt reserve. */export interface InitializeInstructionArgs { programId: PublicKey;
metadata: PublicKey;
updateAuthority: PublicKey;
mint: PublicKey;
mintAuthority: PublicKey;
name: string;
symbol: string;
uri: string;
}
export function createInitializeInstruction(args: InitializeInstructionArgs): TransactionInstruction {
const { programId, metadata, updateAuthority, mint, mintAuthority, name, symbol, uri } = args;
return new TransactionInstruction({
programId,
keys: [
{ isSigner: false, isWritable: true, pubkey: metadata },
{ isSigner: false, isWritable: false, pubkey: updateAuthority },
{ isSigner: false, isWritable: false, pubkey: mint },
{ isSigner: true, isWritable: false, pubkey: mintAuthority },
],
data: packInstruction(
[
['name', getStringEncoder()],
['symbol', getStringEncoder()],
['uri', getStringEncoder()],
],
splDiscriminate('spl_token_metadata_interface:initialize_account'),
{ name, symbol, uri }
),
});
}/** * If the field does not exist on the account, it will be created. * If the field does exist, it will be overwritten. */export interface UpdateFieldInstruction {
programId: PublicKey;
metadata: PublicKey;
updateAuthority: PublicKey;
field: Field | string;
value: string;
}
export function createUpdateFieldInstruction(args: UpdateFieldInstruction): TransactionInstruction {
const { programId, metadata, updateAuthority, field, value } = args;
return new TransactionInstruction({
programId,
keys: [
{ isSigner: false, isWritable: true, pubkey: metadata },
{ isSigner: true, isWritable: false, pubkey: updateAuthority },
],
data: packInstruction(
[
['field', getDataEnumCodec(getFieldCodec())],
['value', getStringEncoder()],
],
splDiscriminate('spl_token_metadata_interface:updating_field'),
{ field: getFieldConfig(field), value }
),
});
}
export interface RemoveKeyInstructionArgs {
programId: PublicKey;
metadata: PublicKey;
updateAuthority: PublicKey;
key: string;
idempotent: boolean;
}
export function createRemoveKeyInstruction(args: RemoveKeyInstructionArgs) {
const { programId, metadata, updateAuthority, key, idempotent } = args;
return new TransactionInstruction({
programId,
keys: [
{ isSigner: false, isWritable: true, pubkey: metadata },
{ isSigner: true, isWritable: false, pubkey: updateAuthority },
],
data: packInstruction(
[
['idempotent', getBooleanEncoder()],
['key', getStringEncoder()],
],
splDiscriminate('spl_token_metadata_interface:remove_key_ix'),
{ idempotent, key }
),
});
}
export interface UpdateAuthorityInstructionArgs {
programId: PublicKey;
metadata: PublicKey;
oldAuthority: PublicKey;
newAuthority: PublicKey | null;
}
export function createUpdateAuthorityInstruction(args: UpdateAuthorityInstructionArgs): TransactionInstruction {
const { programId, metadata, oldAuthority, newAuthority } = args;
const newAuthorityBuffer = Buffer.alloc(32);
if (newAuthority) {
newAuthorityBuffer.set(newAuthority.toBuffer());
} else {
newAuthorityBuffer.fill(0);
}
return new TransactionInstruction({
programId,
keys: [
{ isSigner: false, isWritable: true, pubkey: metadata },
{ isSigner: true, isWritable: false, pubkey: oldAuthority },
],
data: packInstruction(
[['newAuthority', getBytesEncoder({ size: 32 })]],
splDiscriminate('spl_token_metadata_interface:update_the_authority'),
{ newAuthority: newAuthorityBuffer }
),
});
}
export interface EmitInstructionArgs {
programId: PublicKey;
metadata: PublicKey;
start?: bigint;
end?: bigint;
}
export function createEmitInstruction(args: EmitInstructionArgs): TransactionInstruction {
const { programId, metadata, start, end } = args;
return new TransactionInstruction({
programId,
keys: [{ isSigner: false, isWritable: false, pubkey: metadata }],
data: packInstruction(
[
['start', getOptionEncoder(getU64Encoder())],
['end', getOptionEncoder(getU64Encoder())],
],
splDiscriminate('spl_token_metadata_interface:emitter'),
{ start: start ?? null, end: end ?? null }
),
});}
I would be grateful for any help.
I’m stumped, I’ve looked through a bunch of guides, but the recommendations don’t work for me
2
Answers
Rose I’m relatively new to Solana but I can offer a suggestion. I would try ( learning & utilizing ) the command line interface.
I have experience in various languages & I can almost guarantee your CODE is spot on 100% perfect.
The issue I find with development is ( environment ). That is to say on your machine & however you installed all the dependencies it’s likely theres just some issue in the installation of your setup.
I mean if you run blablaxyz — version im sure things seem fine.
I spent probably 3 days setting up an environment to do some solana development & I can tell you these dependencies from github & wherever are VERY fussy.
As a TRICK i might try not installing on your computer globally & create a folder ((( SOLANA )) and cd into that & reinstall everything into that folder.
Then work out of that master folder & cd into each project …
C:SOLANA
C:SOLANAtest01
C:SOLANAtest02
… and so forth.
More than likely this solves your problem. I myself have never had more issues with any other stack. Solana is very ((( cough cough wink wink BETA ))).
It’s no accident solana explorer says BETA as does the RPC === mainnet-beta.
But ultimately … by using the command line interface which for some reason devs avoid, is actually your best option.
CLI === faster, more reliable, more efficient, less work, less errors.
Why CODE 189 lines is TS or RS or JS when the Solana team has already tried to assist you by PRE-CODING all those commands into the CLI.
Some other possible solutions.
1 / Web3.js might be an issue as I think it’s finecky & if not deprecated it less preferred over umi. Try an UMI version import & code.
2 / The hash comments in the error speak to a decoding issue related to kepairs & that ( import bs58 from "bs58"; ) might need to be ( import * as bs58 from "bs58"; )
3 / I think you might need to actually cite & declare the program ID. I have never seen any solana code samples that just say TOKEN_2022_PROGRAM_ID. Meaning ahead of that is usually a ( const SPL_TOKEN_2022_PROGRAM_ID: PublicKey = publicKey ("TokenzQ—actual pgm id").
4 / And how you run the code might be an issue. In typscript on a given file I can use 4 different commands & get 4 different results.
So maybe try different run commands as well.