如何修复Class extends value undefined is not a constructor or null错误
解决@metaplex-foundation/mpl-token-metadata的"Class extends value undefined"错误
问题场景
导入以下代码时触发错误:
import { useUmi } from '../../../../components/mint/umi'; import { useSplMinter } from '../../../../components/mint/tokenMinting';
错误信息
Class extends value undefined is not a constructor or null TypeError: Class extends value undefined is not a constructor or null at ./node_modules/@metaplex-foundation/mpl-token-metadata/dist/src/errors.js (http://192.168.0.222:3000/static/js/bundle.js:1873:40) at options.factory (http://192.168.0.222:3000/static/js/bundle.js:118516:31) at __webpack_require__ (http://192.168.0.222:3000/static/js/bundle.js:117945:32) at fn (http://192.168.0.222:3000/static/js/bundle.js:118174:21) at ./node_modules/@metaplex-foundation/mpl-token-metadata/dist/src/hooked/metadataDelegateRoleSeed.js (http://192.168.0.222:3000/static/js/bundle.js:20702:18) at options.factory (http://192.168.0.222:3000/static/js/bundle.js:118516:31) at __webpack_require__ (http://192.168.0.222:3000/static/js/bundle.js:117945:32) at fn (http://192.168.0.222:3000/static/js/bundle.js:118174:21) at ./node_modules/@metaplex-foundation/mpl-token-metadata/dist/src/hooked/index.js (http://192.168.0.222:3000/static/js/bundle.js:20682:14) at options.factory (http://192.168.0.222:3000/static/js/bundle.js:118516:31)
相关代码
TokenCreator组件
import React, {useRef, useState} from 'react'; import { uploadMetadata } from "../../../../action/tokens_api"; import Add from '../../../../assets/images/icons/add.svg'; import './styles/styles.css'; import { useUmi } from '../../../../components/mint/umi'; import { useSplMinter } from '../../../../components/mint/tokenMinting'; const TokenCreator = () => { const fileInputRef = useRef(null); const [name, setName] = useState(''); const [symbol, setSymbol] = useState(''); const [sypply, setSypply] = useState(''); const [description, setDescription] = useState(''); const [file, setFile] = useState(null); const umi = useUmi('network', 'wallet'); const splMinter = useSplMinter(umi); const handleFileInputClick = () => { fileInputRef.current.click(); }; const handleFileInputChange = (event) => { const file = event.target.files[0]; setFile(file); }; const handleCreateToken = async () => { try { const metadataUrl = await uploadMetadata(file, name, description, symbol); console.log('Metadata URL:', metadataUrl); const mintResult = await splMinter.create({ name: name, symbol: symbol, uri: metadataUrl }, '3000000000000000000'); console.log('Mint Result:', mintResult); } catch (error) { console.error('Error creating token:', error); } }; return( <div className='creator'> form here </div> ) } export default TokenCreator;
useUmi hook
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; import { mplTokenMetadata } from '@metaplex-foundation/mpl-token-metadata'; import { walletAdapterIdentity } from '@metaplex-foundation/umi-signer-wallet-adapters'; import API_KEY from'../../action/API_KEY/api_key'; export const useUmi = (network, wallet) => { return ( createUmi(`https://${network}.helius-rpc.com/?api-key=${API_KEY}`) .use(mplTokenMetadata()) .use(walletAdapterIdentity(wallet)) ); };
useSplMinter hook
import { percentAmount, generateSigner, createBigInt } from '@metaplex-foundation/umi'; import { fromWeb3JsInstruction } from '@metaplex-foundation/umi-web3js-adapters'; import { ComputeBudgetProgram } from '@solana/web3.js'; import { TokenStandard, createAndMint } from '@metaplex-foundation/mpl-token-metadata'; export const useSplMinter = (umi) => { const create = async (metadata = { name: '', symbol: '', uri: '' }, amount = '0') => { const mint = generateSigner(umi); const priceIx = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1000000 }); const transaction = createAndMint(umi, { mint, authority: umi.identity, name: metadata.name, symbol: metadata.symbol, uri: metadata.uri, sellerFeeBasisPoints: percentAmount(0), decimals: 9, amount: createBigInt(amount), tokenOwner: umi.identity.publicKey, tokenStandard: TokenStandard.Fungible, }).prepend({ instruction: fromWeb3JsInstruction(priceIx), signers: [], bytesCreatedOnChain: 0, }); const res = await transaction.sendAndConfirm(umi); return { mint: mint.publicKey.toString(), ...res }; }; return { create }; };
解决方案
这个错误核心原因是Metaplex UMI生态包版本不兼容,mpl-token-metadata依赖的UMI核心包版本与项目中安装的UMI版本不一致,导致继承的基类未正确加载。按以下步骤解决:
1. 统一UMI相关包版本
打开项目package.json,确保所有@metaplex-foundation/umi-*前缀的包和@metaplex-foundation/mpl-token-metadata的版本完全一致,比如全部指定为^0.19.0(最新稳定版以官方发布为准),避免混合不同版本。
2. 清理依赖并重新安装
执行命令清理旧依赖后重新安装:
rm -rf node_modules package-lock.json npm install
若使用yarn:
rm -rf node_modules yarn.lock yarn install
3. 修复UMI初始化的空值问题
确保useUmi接收的wallet参数不为undefined,否则会导致UMI实例异常,间接触发依赖库错误。修改useUmi增加校验:
export const useUmi = (network, wallet) => { if (!wallet) { throw new Error('Wallet must be provided to initialize Umi'); } return ( createUmi(`https://${network}.helius-rpc.com/?api-key=${API_KEY}`) .use(mplTokenMetadata()) .use(walletAdapterIdentity(wallet)) ); };
同时在TokenCreator组件中,配合钱包适配器的hook确保钱包连接后再初始化UMI:
import { useWallet } from '@solana/wallet-adapter-react'; const TokenCreator = () => { const { wallet, connected } = useWallet(); // 仅在钱包连接后初始化umi const umi = connected ? useUmi('network', wallet) : null; const splMinter = umi ? useSplMinter(umi) : null; // ...其他逻辑 };
4. 调整事务构建方式(可选)
若版本兼容后仍有问题,改用UMI标准的事务构建方式替代createAndMint的链式调用:
import { createCreateAndMintInstruction } from '@metaplex-foundation/mpl-token-metadata'; // 替换原create函数逻辑 const create = async (metadata = { name: '', symbol: '', uri: '' }, amount = '0') => { const mint = generateSigner(umi); const priceIx = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1000000 }); const createAndMintIx = createCreateAndMintInstruction(umi, { mint, authority: umi.identity, name: metadata.name, symbol: metadata.symbol, uri: metadata.uri, sellerFeeBasisPoints: percentAmount(0), decimals: 9, amount: createBigInt(amount), tokenOwner: umi.identity.publicKey, tokenStandard: TokenStandard.Fungible, }); const transaction = umi.transactions.create([ fromWeb3JsInstruction(priceIx), createAndMintIx ]); const res = await umi.rpc.sendAndConfirmTransaction(transaction, { signers: [mint] }); return { mint: mint.publicKey.toString(), ...res }; };
内容的提问来源于stack exchange,提问作者Rose
相关产品推荐
相关产品推荐

