如何在Solana上铸造一个NFT

如何在Solana上铸造一个NFT

概述

Solana 是一个新兴的区块链,旨在解决以太坊的可扩展性问题,这边文章将逐步介绍如何在Solana上创建一个NFT。NFT是Non Fungible Token的缩写,是一种非同质的 Token。当你创建一个NFT时,它类似于创建一个ERC20代币;然而,关键的区别是ERC20永远只发行一种代币。在本指南中,我们将以编程方式创建2个独立的账户,一个账户用于铸造NFT,另一个账户将接收NFT。然后编写代码,在Solana上完成NFT的铸币和发送。如果你在任何时候被卡住了,请随时参考本指南末尾的完整代码。让我们开始铸币吧!

依赖条件:

  • 已安装NodeJS
  • 熟悉终端命令/CLI
  • 编辑器
  • 已安装TypeScript

什么是Solana?

Solana的目标很单一。目标是扩大区块链的规模,以便在全球范围内采用。Solana实验室,Solana协议的开发者,正在做一些不同的事情来实现这个梦想。

在调整性能方面,区块链技术有几个关键点。其中之一是共识机制。这就是节点如何一起沟通以得出相同的结论。比特币使用工作证明或PoW。币安智能链,也被称为BSC,使用Staked Authority证明或PoSA。而以太坊正在迁移到Proof of Stake又称PoS。正如你所知道的,当下共识绝不是一个已经解决了的游戏。

Solana使用一种叫做历史证明的共识。历史证明是通过时间戳解决方案来实现的;每笔交易都有一个时间戳,允许它在短短的几分之一秒内被网络的其他成员验证为合法交易。Solana对八项技术进行了解析,他们认为自己是最快、最具扩展性和最安全的区块链。

在本地创建项目

打开终端,导航到一个你想创建项目的文件夹。接下来,按照以下顺序运行命令:

mkdir SolanaNFT
npm install --prefix ./SolanaNFT @solana/web3.js @solana/spl-token 
cd SolanaNFT
touch index.ts

第一个命令创建一个新的项目目录,名为SolanaNFT。用npm install --prefix ./SolanaNFT @solana/web3.js @solana/spl-token, 我们要安装Solana的JavaScript API,@solana/web3.js 和TypeScript库 @solana/spl-token,用于与SPL Token程序交互。最后,通过touch index.ts,我们创建了一个Typescript文件,index.ts,我们将在其中编写所有的代码。

连接到Solana

在你选择的编辑器中打开SolanaNFT项目目录,让我们开始编写一些代码来连接到Solana!

index.ts文件中,我们首先要从 @solana/web3.js@solana/spl-token导入所有我们需要的功能。添加以下两条导入语句:

import { clusterApiUrl, Connection, Keypair, LAMPORTS_PER_SOL } from  "@solana/web3.js";
import { createMint, getOrCreateAssociatedTokenAccount, mintTo, setAuthority, transfer } from  "@solana/spl-token"; 

注意: 如果你在这几行代码中看到错误,那么你很可能没有安装库。确保你在正确的目录中,并再次安装它们。

import语句下面,添加这个函数:

// 连接到SOLANA
(async () => {
  // Connect to cluster
const connection = new Connection(clusterApiUrl('devnet'), "confirmed");

}) 

这里我们正在实例化一个新的连接实例。这需要两个参数,第一个参数是指向Solana网络的URL节点(端点)。在我们的例子中,clusterApiUrl('devnet')是一个方便的方法,指向Solana Devnet的公共节点,我们本教程中要使用Devnet。Solana有3个不同的网络:mainnet、testnet和devnet。devnet是一个低风险的环境,你可以把SOL 空投给自己。

随着连接的建立,我们现在可以创建NFT并执行其他相关步骤。

注意。我们往后写的每一个代码块都应该放在前一个代码块的正下方,都在顶层async函数的大括号内。在最后提供了完整的代码,可对照检查。

创建新钱包和空投SOL

我们需要完成的第一个任务是创建一个钱包账户,并为其提供资金。我们还需要确保每一步都成功完成,然后再继续下一步。下面是这段代码的样子:

//创建一个新的钱包并获取空投 
const fromWallet = Keypair.generate();
const fromAirdropSignature = await connection.requestAirdrop(
  fromWallet.publicKey,
  LAMPORTS_PER_SOL
);

// 等待空投确认
await connection.confirmTransaction(fromAirdropSignature);

记住要在async函数中添加这段代码。现在让我们把它按行解析:

第2行:我们使用之前导入的Keypair类,通过调用generate() 方法来生成一个新的密钥对。这将创建一对新的公钥和私钥,并将其存储在 fromWallet

第4行:请求向我们的钱包空投资金。requestAirdrop() 方法需要一个公钥和你想收到的SOL中的lamports数量。Lamports相当于Solana的Wei,是一个SOL可以被分割成的最小的数量。大多数需要数字的方法将默认是lamport的单位。在我们的例子中,LAMPORTS_PER_SOL是一个常数,代表1 SOL的Lamports数量。

第9行:为了确认空投是否成功,使用confirmTransaction方法并等待其成功。调用允许我们传入一个签名交易作为参数,并让程序等待,直到它被确认,然后再继续代码的其他部分。这很重要,因为我们下一步要支付费用,需要空投的资金。

创建 token 铸币器

我们现在需要创建铸币器,实现token铸币,并获取Token账户。

// 创建一个token铸币器
const mint = await createMint(
connection,
fromWallet,            // Payer of the transact
fromWallet.publicKey,  // Account that will control the minting   
null,        // Account that will control the freezing of the token
0            // Location of the decimal place ); 

createMint函数将用于创建实际代币,它需要以下参数:

  1. 与Solana网络的连接(connection)
  2. 将要支付费用的账户(fromWallet)
  3. 有权铸造此代币的账户的公钥(fromWallet.publicKey)
  4. 有权冻结此代币的账户的公钥。这个参数是可选的(null)
  5. token的小数点位数。

关于这个函数及文章中使用的其他spl-token函数的更多信息,可访问Solana-labs.github.io的文档页面

一旦创建了token 铸币器,我们需要从fromWallet的Solana地址中获取token账户。如果它不存在就创建它。为此,我们将利用getorCreateAssociatedTokenAccount() 函数,传入之前的大部分参数,并将其存储在fromTokenAccount

// Get the token account of the "fromWallet" Solana address. If it does not exist, create it. 
const fromTokenAccount = await getOrCreateAssociatedTokenAccount(
  connection,
  fromWallet,
  mint,
  fromWallet.publicKey
);

译者注: Solana合约(Programs)是无状态的,它们只是指令,而不存储任何数据/状态。数据存储被存储在独立的 账户中,由账户持有数据。当调用Solana合约的函数时,你需要把持有数据账户传给函数。

你可以这样考虑监管权限:NFT驻留在账户中,而你的钱包拥有这个账户。

密钥 -> 钱包 -> 账户 -> NFT (从上到下)

创建钱包及关联账户来接收NFT

我们有一个账户来发送NFT,现在还需要一个账户来接收NFT。实现这一目标的代码应该非常熟悉,因为像我们之前那样,利用相同的函数和变量来生成一个新的账号。

// Generate a new wallet to receive the newly minted tokenconst 
toWallet = Keypair.generate();

// Get the token account of the "toWallet" Solana address. If it does not exist, create it.
const toTokenAccount = await mint.getOrCreateAssociatedAccountInfo(
  connection,
  fromWallet,
  mint,
  toWallet.publicKey
); 

上面的代码块用一组单独的密钥创建了一个钱包(toWallet),然后创建了一个账户,将mint变量链接到我们新创建的钱包。

铸造NFT并发送

现在是时候铸造一个NFT并将其发送给某人,花点时间看看下面的代码,以实现这一目标,并阅读注释以了解每个函数的作用:

// Minting 1 new token to the "fromTokenAccount" account we just returned/created.
let signature = await mintTo(
  connection,
  fromWallet,               // 支付手续费
  mint,                     // Mint for the account 
  fromTokenAccount.address, // 铸造到账号
  fromWallet.publicKey,     // 铸造权限
  1                         // 铸造数量 
);

await setAuthority(
  connection,
  fromWallet,            // 支付手续费
  mint,                  // Account 
  fromWallet.publicKey,  // 当前授权者
  0,                     // 权限类型: "0" 表示铸造 Tokens
  null                   // Setting the new Authority to null
);

signature = await transfer(
  connection,
  fromWallet,               // 支付手续费
  fromTokenAccount.address, // 源账号
  toTokenAccount.address,   // 目标账号
  fromWallet.publicKey,     // 源账号的Owner
  1                         // 转移数量
);

 console.log("SIGNATURE", signature);
})(); 

我们将简要地谈谈setAuthority() 函数,因为它是最关键的部分之一。这个函数将撤销铸币权限,并确保我们不能再创建这种类型的代币。请注意,撤销动作不能被撤销。

要执行该程序,请相继运行以下命令:

tsc index.ts 
node index.js

这两条命令将运行TypeScript文件,生成一个同名的JavaScript文件,并运行该文件。一段时间后,你应该看到终端中记录了一个交易签名。 如果你访问Solana Explorer,你应该看到交易签名,它看起来会像这样: img

区块链浏览器中显示的Solana交易

以下是完整代码(包含链接、铸造NFT及发送):

import { clusterApiUrl, Connection, Keypair, LAMPORTS_PER_SOL } from  "@solana/web3.js";
import { createMint, getOrCreateAssociatedTokenAccount, mintTo, setAuthority, transfer } from  "@solana/spl-token";

(async () => {
  // Connect to cluster
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");

  // Generate a new wallet keypair and airdrop SOL
  const fromWallet = Keypair.generate();
  const fromAirdropSignature = await connection.requestAirdrop(
    fromWallet.publicKey,
    LAMPORTS_PER_SOL
  );

  // Wait for airdrop confirmation
  await connection.confirmTransaction(fromAirdropSignature);

  // Create a new token 
  const mint = await createMint(
    connection, 
    fromWallet,            // Payer of the transaction
    fromWallet.publicKey,  // Account that will control the minting 
    null,                  // Account that will control the freezing of the token 
    0                      // Location of the decimal place 
  );

  // Get the token account of the fromWallet Solana address. If it does not exist, create it.
  const fromTokenAccount = await getOrCreateAssociatedTokenAccount(
    connection,
    fromWallet,
    mint,
    fromWallet.publicKey
  );

  // Generate a new wallet to receive the newly minted token
  const toWallet = Keypair.generate();

  // Get the token account of the toWallet Solana address. If it does not exist, create it.
  const toTokenAccount = await getOrCreateAssociatedTokenAccount(
    connection,
    fromWallet,
    mint,
    toWallet.publicKey
  );

  // Minting 1 new token to the "fromTokenAccount" account we just returned/created.
  let signature = await mintTo(
    connection,
    fromWallet,               // Payer of the transaction fees 
    mint,                     // Mint for the account 
    fromTokenAccount.address, // Address of the account to mint to 
    fromWallet.publicKey,     // Minting authority
    1                         // Amount to mint 
  );

  await setAuthority(
    connection,
    fromWallet,            // Payer of the transaction fees
    mint,                  // Account 
    fromWallet.publicKey,  // Current authority 
    0,                     // Authority type: "0" represents Mint Tokens 
    null                   // Setting the new Authority to null
  );

  signature = await transfer(
    connection,
    fromWallet,               // Payer of the transaction fees 
    fromTokenAccount.address, // Source account 
    toTokenAccount.address,   // Destination account 
    fromWallet.publicKey,     // Owner of the source account 
    1                         // Number of tokens to transfer 
  );

  console.log("SIGNATURE", signature);

})();

总结

恭喜你,从本教程中学到了一些东西,你已经成功地在Solana区块链上创建了一个NFT。你要做的下一步是将这个独一无二的代币,与一些资产联系起来。在现在的市场上,它通常是一张随机生成的具有各种属性的图片,或者是一件独特的艺术品。如果你想了解如何做到这一点,你可以在这个教程中了解如何做到这一点!


本翻译由 Duet Protocol 赞助支持。

点赞 4
收藏 6
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
翻译小组
翻译小组
0x9e64...7c84
大家看到好的文章可以在 GitHub 提 Issue: https://github.com/lbc-team/Pioneer/issues 欢迎关注我的 Twitter: https://twitter.com/UpchainDAO