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 🙁