在函数执行阶段
createInitializeInstruction
我收到错误:
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
具有字符串值,mint
、metadata
、minyAuthority
、updateAuthority
具有有效值。
这是我的代码:
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 };
};
@solana/spl-token-metadata 库中 createInitializeInstruction 函数的代码:
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 }
),
});}
如有任何帮助,我将不胜感激。
我很困惑,我浏览了一堆指南,但这些建议对我不起作用
Rose 我对 Solana 比较陌生,但我可以提供建议。我会尝试(学习和利用)命令行界面。
我有多种语言的经验,我几乎可以保证你的代码 100% 完美。
我在开发中发现的问题是(环境)。也就是说,在您的计算机上,无论您如何安装所有依赖项,都可能在安装设置时出现一些问题。
我的意思是,如果你运行 blablaxyz -- 版本,我确信一切看起来都很好。
我花了大约 3 天的时间设置一个环境来进行一些 solana 开发,我可以告诉你这些来自 github 的依赖项以及任何非常挑剔的地方。
作为一个技巧,我可能会尝试不在您的计算机上全局安装并创建一个文件夹 ((( SOLANA )) 并 cd 到该文件夹中并将所有内容重新安装到该文件夹中。
然后从该主文件夹中工作并进入每个项目......
C:\SOLANA C:\SOLANA est01 C:\SOLANA est02
...等等。
这很可能可以解决您的问题。我自己从未在任何其他堆栈上遇到过更多问题。 Solana 非常(((咳咳眨眼BETA)))。
solana explorer 说 BETA 并非偶然,RPC === mainnet-beta 也是如此。
但最终......通过使用命令行界面(出于某种原因开发人员避免使用)实际上是您的最佳选择。
CLI === 更快、更可靠、更高效、更少的工作、更少的错误。
为什么 CODE 189 行是 TS 或 RS 或 JS,而 Solana 团队已经尝试通过将所有这些命令预编码到 CLI 中来帮助您。