javascriptreactjsweb3jssolanaspl

Error creating token for Token2022Form: TypeError: Cannot read properties of undefined (reading 'call')


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

upd: config code:

const webpack = require("webpack");
const getCacheIdentifier = require("react-dev-utils/getCacheIdentifier");

module.exports = function override(config, webpackEnv) {
console.log("Overriding webpack config...");

// Set up environment flags
const isEnvDevelopment = webpackEnv === "development";
const isEnvProduction = webpackEnv === "production";
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";


// Configure fallbacks for Node environment
const fallback = config.resolve.fallback || {};
Object.assign(fallback, {
    crypto: require.resolve("crypto-browserify"),
    stream: require.resolve("stream-browserify"),
    assert: require.resolve("assert"),
    http: require.resolve("stream-http"),
    https: require.resolve("https-browserify"),
    os: require.resolve("os-browserify"),
    url: require.resolve("url"),
    zlib: require.resolve("browserify-zlib"),
});
config.resolve.fallback = fallback;

// Configure plugins
config.plugins = (config.plugins || []).concat([
    new webpack.ProvidePlugin({
        process: "process/browser",
        Buffer: ["buffer", "Buffer"],
    }),
]);

// Ignore certain warnings
config.ignoreWarnings = [/Failed to parse source map/];

// Add source-map loader
config.module.rules.push({
    test: /\.(js|mjs|jsx)$/,
    enforce: "pre",
    loader: require.resolve("source-map-loader"),
    resolve: {
        fullySpecified: false,
    },
});

// Modify Babel loader configuration
const loaders = config.module.rules.find((rule) =>
    Array.isArray(rule.oneOf)
).oneOf;
loaders.splice(loaders.length - 1, 0, {
    test: /\.(js|mjs|cjs)$/,
    exclude: /@babel(?:\/|\\{1,2})runtime/,
    loader: require.resolve("babel-loader"),
    options: {
        babelrc: false,
        configFile: false,
        compact: false,
        presets: [
            [
                require.resolve("babel-preset-react-app/dependencies"),
                { helpers: true },
            ],
        ],
        cacheDirectory: true,
        cacheCompression: false,
        cacheIdentifier: getCacheIdentifier(
            isEnvProduction ? "production" : isEnvDevelopment && "development",
            [
                "babel-plugin-named-asset-import",
                "babel-preset-react-app",
                "react-dev-utils",
                "react-scripts",
            ]
        ),
        sourceMaps: shouldUseSourceMap,
        inputSourceMap: shouldUseSourceMap,
    },
});

return config;
};

package.json:

{
  "name": "token_minter",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@metaplex-foundation/mpl-token-metadata": "^3.2.1",
    "@metaplex-foundation/umi": "^0.9.1",
    "@metaplex-foundation/umi-bundle-defaults": "^0.9.1",
    "@metaplex-foundation/umi-signer-wallet-adapters": "^0.9.1",
    "@metaplex-foundation/umi-web3js-adapters": "^0.9.1",
    "@solana/pay": "^0.2.5",
    "@solana/spl-token": "^0.4.3",
    "@solana/spl-token-metadata": "^0.1.2",
    "@solana/wallet-adapter-base": "^0.9.23",
    "@solana/wallet-adapter-react": "^0.15.35",
    "@solana/wallet-adapter-react-ui": "^0.9.35",
    "@solana/wallet-adapter-wallets": "^0.19.32",
    "@solana/web3.js": "^1.91.1",
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.6.8",
    "browserify": "^17.0.0",
    "bs58": "^5.0.0",
    "buffer": "^6.0.3",
    "copy-to-clipboard": "^3.3.3",
    "crypto-browserify": "^3.12.0",
    "express": "^4.19.2",
    "http-browserify": "^1.7.0",
    "https-browserify": "^1.0.0",
    "js-cookie": "^3.0.5",
    "process": "^0.11.10",
    "react": "^18.2.0",
    "react-copy-to-clipboard": "^5.1.0",
    "react-dev-utils": "^12.0.1",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.6.0",
    "react-scripts": "5.0.1",
    "stream": "^0.0.2",
    "stream-browserify": "^3.0.0",
    "stream-http": "^3.2.0",
    "web-vitals": "^2.1.4",
   "webpack": "^5.91.0",
    "zlib-browserify": "^0.0.3"
  },
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@craco/craco": "^7.1.0",
    "@types/node": "^20.11.30",
    "@types/react": "^18.2.70",
    "customize-cra": "^1.0.0",
    "node-loader": "^2.0.0",
    "react-app-rewired": "^2.2.1",
    "webpack-cli": "^5.1.4",
    "webpack-node-externals": "^3.0.0"
  },
  "browser": {
    "path": false,
    "stream": false,
    "http": false,
    "https": false
  },
  "resolve": {
    "fallback": {
      "crypto": "crypto-browserify",
      "http": "http-browserify",
      "https": "https-browserify",
      "zlib": "zlib-browserify"
    }
  }
}

Solution

  • I found the problem and its solution. In general, the problem is that CRA has a horrible builder, migrating to vite helped