当前位置:首页 > NFT资讯 > Solana区块链NFT开发教程

Solana区块链NFT开发教程

admin4天前NFT资讯4

在这个教程中,我们将学习如何编写 Rust 智能合约并使用 Metaplex 在 Solana 上铸造 NFT。

用熟悉的语言学习Web3.0 开发: Java | Php | Python | .Net / C | Golang | Node.JS | Flutter / Dart

在 Solana 开发中,我们回面临许多奇怪的自定义错误和错误,并且由于 Solana 开发生态系统没有 Eth 开发生态系统那么大,因此修复它们 可能非常困难和令人沮丧。但不用担心。当遇到困难时,只需在正确的地方寻找解决方案。

在我的开发过程中,我不断地在Anchor discord 服务器、Metaplex和Superteam服务器上提出疑问,并查看 GitHub 上的其他代码仓库和 Metaplex 程序库本身。

1、项目概况

在这个教程中,我们将使用的工具包括:

  • Solana CLI 工具— 官方 Solana CLI 工具集
  • Anchor Framework — 用于开发 Solana 程序的高级框架。这是必须的,除非你是大神级开发人员,不过在这种情况下你应该不会阅读此博客。哈哈。
  • Solana/web3.js — web3.js的 Solana 版本
  • Solana/spl-token — 使用 spl 通证的包
  • Mocha — 一个 JS 测试工具

2、准备工作

在命令行使用以下命令将你的网络设置为 devnet:

1
solanaconfigset--url devnet

要确认它是否有效,请在执行上述命令后检查输出:

12345
Config File:/Users/anoushkkharangate/.config/solana/cli/config.ymlRPC URL: https://api.devnet.solana.comWebSocket URL: wss://api.devnet.solana.com/(computed)Keypair Path:/Users/anoushkkharangate/.config/solana/id.jsonCommitment: confirmed

接下来,请参考Solana wallet docs设置 文件系统钱包,并使用命令solana airdrop 1添加一些devnet的 sol通证。

最后,使用另一个anchor CLI终端 通过以下命令创建一个anchor项目:

1
anchorinit

确保Anchor.toml也设置为 devnet。

1234567891011
[features]seeds =false[programs.devnet]metaplex_anchor_nft ="Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"[registry]url ="https://anchor.projectserum.com"[provider]cluster ="devnet"wallet ="/Users//.config/solana/id.json"[scripts]test="yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

3、导入依赖项

在项目中,必须有一个名为程序的文件夹。转到programs//Cargo.toml并添加这些依赖项。确保使用版本0.24.2, 可以使用avm来更改它:

1234
[dependencies]anchor-lang ="0.24.2"anchor-spl ="0.24.2"mpl-token-metadata = {version ="1.2.7", features = ["no-entrypoint"]}

由于安全漏洞,Anchor 已删除 0.24.2 之前的所有版本,因此请确保使用该版本

然后转到src 中的lib.rs文件并导入这些:

12345
useanchor_lang::prelude::*;useanchor_lang::solana_program::program::invoke;useanchor_spl::token;useanchor_spl::token::{MintTo, Token};usempl_token_metadata::instruction::{create_master_edition_v3, create_metadata_accounts_v2};

现在我们可以编写 mint 函数了!

4、NFT账户结构实现

首先,让我们mint为函数创建账户结构:

123456789101112131415161718192021222324252627
[derive(Accounts)]pub struct MintNFT<info> {    [account(mut)]    pub mint_authority: Signer<info>,/// CHECK: This isnotdangerous because we dont read or write from this account    [account(mut)]    pub mint: UncheckedAccount<info>,    // [account(mut)]    pub token_program: Program<info, Token>,    /// CHECK: This is not dangerous because we dontreadorwritefrom this account    [account(mut)]    pub metadata: UncheckedAccount<info>,    /// CHECK: This is not dangerous because we dontreadorwritefrom this account    [account(mut)]    pub token_account: UncheckedAccount<info>,    /// CHECK: This is not dangerous because we dontreadorwritefrom this account    pub token_metadata_program: UncheckedAccount<info>,    /// CHECK: This is not dangerous because we dontreadorwritefrom this account    [account(mut)]    pub payer: AccountInfo<info>,    pub system_program: Program<info, System>,    /// CHECK: This isnotdangerous because we dont read or write from this account    pub rent: AccountInfo<info>,    /// CHECK: This isnotdangerous because we dont read or write from this account    [account(mut)]    pub master_edition: UncheckedAccount<info>,}

不要担心未检查的帐户,因为我们会将其传递给 Metaplex 程序,它会为我们检查。

为了在 Anchor 中使用 Unchecked 帐户,我们需要在每个帐户上方添加此注释:

1
/// CHECK: This is not dangerous because we dont read or write from this account

5、NFT合约Mint函数实现

让我们创建一个函数,使用刚刚创建的结构来铸造通证:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
pubfnmint_nft(        ctx: Context,        creator_key: Pubkey,        uri:String,        title:String,    ) ->Result<()> {        msg!("Initializing Mint NFT");letcpi_accounts = MintTo {            mint: ctx.accounts.mint.to_account_info(),            to: ctx.accounts.token_account.to_account_info(),            authority: ctx.accounts.payer.to_account_info(),        }; msg!("CPI Accounts Assigned");letcpi_program = ctx.accounts.token_program.to_account_info();        msg!("CPI Program Assigned");letcpi_ctx = CpiContext::new(cpi_program, cpi_accounts);        msg!("CPI Context Assigned");        token::mint_to(cpi_ctx,1)?;        msg!("Token Minted !!!");letaccount_info =vec![Solana NFT            ctx.accounts.metadata.to_account_info(),            ctx.accounts.mint.to_account_info(),            ctx.accounts.mint_authority.to_account_info(),            ctx.accounts.payer.to_account_info(),            ctx.accounts.token_metadata_program.to_account_info(),            ctx.accounts.token_program.to_account_info(),            ctx.accounts.system_program.to_account_info(),            ctx.accounts.rent.to_account_info(),        ];        msg!("Account Info Assigned");letcreator =vec![Solana NFT            mpl_token_metadata::state::Creator {                address: creator_key,                verified:false,                share:100,            },            mpl_token_metadata::state::Creator {                address: ctx.accounts.mint_authority.key(),                verified:false,                share:0,            },        ];        msg!("Creator Assigned");letsymbol = std::string::ToString::to_string("symb");        invoke(            &create_metadata_accounts_v2(                ctx.accounts.token_metadata_program.key(),                ctx.accounts.metadata.key(),                ctx.accounts.mint.key(),                ctx.accounts.mint_authority.key(),                ctx.accounts.payer.key(),                ctx.accounts.payer.key(),                title,                symbol,                uri,Some(creator),1,true,false,None,None,            ),            account_info.as_slice(),        )?;        msg!("Metadata Account Created !!!");letmaster_edition_infos =vec![Solana NFT            ctx.accounts.master_edition.to_account_info(),            ctx.accounts.mint.to_account_info(),            ctx.accounts.mint_authority.to_account_info(),            ctx.accounts.payer.to_account_info(),            ctx.accounts.metadata.to_account_info(),            ctx.accounts.token_metadata_program.to_account_info(),            ctx.accounts.token_program.to_account_info(),            ctx.accounts.system_program.to_account_info(),            ctx.accounts.rent.to_account_info(),        ];        msg!("Master Edition Account Infos Assigned");        invoke(            &create_master_edition_v3(                ctx.accounts.token_metadata_program.key(),                ctx.accounts.master_edition.key(),                ctx.accounts.mint.key(),                ctx.accounts.payer.key(),                ctx.accounts.mint_authority.key(),                ctx.accounts.metadata.key(),                ctx.accounts.payer.key(),Some(0),            ),            master_edition_infos.as_slice(),        )?;        msg!("Master Edition Nft Minted !!!");Ok(())    }

如果想调试你的程序,最好使用msg!()记录想要检查的任何值。它接受字符串,因此必须使用std::string::ToString来转换。 你的日志将出现在终端或.anchor/program-logs/

有几点需要说明一下。

creator数组需要包含铸造 NFT 的人,但你可以将份额设置为 0,所以这并不重要。这是代码:

123456789101112
letcreator=vec![SolanaNFTmpl_token_metadata::state::Creator{address:creator_key,verified:false,share:100,},mpl_token_metadata::state::Creator{address:ctx.accounts.mint_authority.key(),verified:false,share:0,},];

我还没有实现集合,因为它不在本指南的范围内,但你可以使用以下方法来实现:

1
mpl_token_metadata::instruction::set_and_verify_collection

为什么我在这里将 Max supply 设置为 0?在 Metaplex 中,如果是一种通证,那么你必须将其最大供应量设置为零,因为总供应量 - 声称的供应量 (1-1) 等于 0。

12345678910
&create_master_edition_v3(                ctx.accounts.token_metadata_program.key(),                ctx.accounts.master_edition.key(),                ctx.accounts.mint.key(),                ctx.accounts.payer.key(),                ctx.accounts.mint_authority.key(),                ctx.accounts.metadata.key(),                ctx.accounts.payer.key(),Some(0),// max supply 0            ),

编写函数后,运行anchor build && anchor deploy,应该会看到已部署的程序 ID

将此程序 ID 粘贴到Anchor.tomllib.rs文件中,替换全部的默认ID即Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS

6、调用 Mint 函数

在做任何事情之前,请确保已导入@solana/web3.js@solana/spl-token。 在tests/.ts里面添加这些导入和常量:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
import{  TOKEN_PROGRAM_ID,  createAssociatedTokenAccountInstruction,  getAssociatedTokenAddress,  createInitializeMintInstruction,  MINT_SIZE,}from"@solana/spl-token";import{ LAMPORTS_PER_SOL }from"@solana/web3.js";const{ PublicKey, SystemProgram } = anchor.web3; qconst TOKEN_METADATA_PROGRAM_ID =newanchor.web3.PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");constlamports:number=awaitprogram.provider.connection.getMinimumBalanceForRentExemption(        MINT_SIZE      );constgetMetadata =async(      mint: anchor.web3.PublicKey    ):Promise => {return(awaitanchor.web3.PublicKey.findProgramAddress(          [            Buffer.from("metadata"),            TOKEN_METADATA_PROGRAM_ID.toBuffer(),            mint.toBuffer(),          ],          TOKEN_METADATA_PROGRAM_ID        )      )[0];    };constgetMasterEdition =async(      mint: anchor.web3.PublicKey    ):Promise => {return(awaitanchor.web3.PublicKey.findProgramAddress(          [            Buffer.from("metadata"),            TOKEN_METADATA_PROGRAM_ID.toBuffer(),            mint.toBuffer(),            Buffer.from("edition"),          ],          TOKEN_METADATA_PROGRAM_ID        )      )[0];    };constmintKey: anchor.web3.Keypair = anchor.web3.Keypair.generate();

现在让我们制作通证和关联的通证账户,如下面代码所示:

12345678910111213141516171819202122232425262728293031323334353637
constNftTokenAccount =awaitgetAssociatedTokenAddress(      mintKey.publicKey,      program.provider.wallet.publicKey    );console.log("NFT Account: ", NftTokenAccount.toBase58());constmint_tx =newanchor.web3.Transaction().add(      anchor.web3.SystemProgram.createAccount({fromPubkey: program.provider.wallet.publicKey,newAccountPubkey: mintKey.publicKey,space: MINT_SIZE,programId: TOKEN_PROGRAM_ID,        lamports,      }),      createInitializeMintInstruction(        mintKey.publicKey,0,        program.provider.wallet.publicKey,        program.provider.wallet.publicKey      ),      createAssociatedTokenAccountInstruction(        program.provider.wallet.publicKey,        NftTokenAccount,        program.provider.wallet.publicKey,        mintKey.publicKey      )    );constres =awaitprogram.provider.send(mint_tx, [mintKey]);console.log(awaitprogram.provider.connection.getParsedAccountInfo(mintKey.publicKey)    );console.log("Account: ", res);console.log("Mint key: ", mintKey.publicKey.toString());console.log("User: ", program.provider.wallet.publicKey.toString());constmetadataAddress =awaitgetMetadata(mintKey.publicKey);constmasterEdition =awaitgetMasterEdition(mintKey.publicKey);console.log("Metadata address: ", metadataAddress.toBase58());console.log("MasterEdition: ", masterEdition.toBase58());

注意:mint 和 freeze 权限必须相同,否则不起作用。

createInitializeMintInstruction( mintKey.publicKey, 0,program.provider.wallet.publicKey,// mint authprogram.provider.wallet.publicKey // freeze auth),

现在,调用 mint 函数并传递数据和帐户:

1234567891011121314151617181920
consttx=awaitprogram.rpc.mintNft(mintKey.publicKey,"https://arweave.net/y5e5DJsiwH0s_ayfMwYk-SnrZtVZzHLQDSTZ5dNRUHA","NFT Title",{accounts:{mintAuthority:program.provider.wallet.publicKey,mint:mintKey.publicKey,tokenAccount:NftTokenAccount,tokenProgram:TOKEN_PROGRAM_ID,metadata:metadataAddress,tokenMetadataProgram:TOKEN_METADATA_PROGRAM_ID,payer:program.provider.wallet.publicKey,systemProgram:SystemProgram.programId,rent:anchor.web3.SYSVAR_RENT_PUBKEY,masterEdition:masterEdition,},});console.log("Yourtransactionsignature",tx);

好了!现在只需运行anchor test,就应该能够铸造你的 NFT:

123456789
Account:4swRFMNovHCkXY3gDgAGBXZwpfFuVyxWpWsgXqbYvoZG1M63nZHxyPRm7KTqAjSdTpHn2ivyPr6jQfxeLsB6a1nXMintkey:DehGx61vZPYNaMWm9KYdP91UYXXLu1XKoc2CCu3NZFNbUser:7CtWnYdTNBb3P9eViqSZKUekjcKnMcaasSMC7NbTVKuEMetadataaddress:7ut8YMzGqZAXvRDro8jLKkPnUccdeQxsfzNv1hjzc3BoMasterEdition:  Au76v2ZDnWSLj23TCu9NRVEYWrbVUq6DAGNnCuALaN6oYour transaction signature KwEst87H3dZ5GwQ5CDL1JtiRKwcXJKNzyvQShaTLiGxz4HQGsDA7EW6rrhqwbJ2TqQFRWzZFvhfBU1CpyYH7WhH    ✔ Is initialized! (6950ms)1passing (7s)✨  Done in9.22s.

如果提示任何带有 0x1 等十六进制值的自定义程序错误,请将十六进制值转换为纯文本,然后前往metaplex github 并使用你的浏览器搜索error(

可以在这里查看 NFT:solscan

7、结束语

我希望本指南对所有 Solana 极客有用。当我第一次尝试铸造 NFT 时感到非常困难,希望这篇文章对你有所帮助。 可以从这里下载教程里的代码。


原文链接:http://blog.hubwiz.com/2022/08/03/mint-nft-on-solana/

相关文章

NFT行业下一个风口:音乐NFT

2021年被称为NFT元年,艺术领域掀起了一股NFT热潮并持续至今。由于NFT的核心价值在于数字内容资产化,推动内容资产价值的全面重估,因此NFT技术在音乐、影...

菲律宾人在预测的萧条之前NFT淘金热

46 岁的 AJ DIMARUCOT 是众多使用所谓的不可替代代币 (NFT) 在互联网上收集和销售数字艺术的菲律宾人之一。在 NFT 的所有权方面,菲律宾在...

明星们的NFT头像

随着NFT话题持续火爆,各种头像NTF作品也越来越多,特别是CryptoPunks 加密朋克,bored ape yacht club(BAYC) 无聊猿游艇俱...

CoolCats推出NFT头像系列之一

CrypToadz是一个较新的NFT项目,于9月初推出,本周初需求激增,仅周日的交易量就达到了1900万美元。根据 CryptoSlam 数据,这个像素青蛙头像...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。