如何在Solana上铸造一个NFT
Solana 是一个新兴的区块链,旨在解决以太坊的可扩展性问题,这边文章将逐步介绍如何在Solana上创建一个NFT。NFT是Non Fungible Token的缩写,是一种非同质的 Token。当你创建一个NFT时,它类似于创建一个ERC20代币;然而,关键的区别是ERC20永远只发行一种代币。在本指南中,我们将以编程方式创建2个独立的账户,一个账户用于铸造NFT,另一个账户将接收NFT。然后编写代码,在Solana上完成NFT的铸币和发送。如果你在任何时候被卡住了,请随时参考本指南末尾的完整代码。让我们开始铸币吧!
依赖条件:
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,我们将在其中编写所有的代码。
在你选择的编辑器中打开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函数的大括号内。在最后提供了完整的代码,可对照检查。
我们需要完成的第一个任务是创建一个钱包账户,并为其提供资金。我们还需要确保每一步都成功完成,然后再继续下一步。下面是这段代码的样子:
//创建一个新的钱包并获取空投
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铸币器
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函数将用于创建实际代币,它需要以下参数:
关于这个函数及文章中使用的其他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。实现这一目标的代码应该非常熟悉,因为像我们之前那样,利用相同的函数和变量来生成一个新的账号。
// 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并将其发送给某人,花点时间看看下面的代码,以实现这一目标,并阅读注释以了解每个函数的作用:
// 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,你应该看到交易签名,它看起来会像这样:
区块链浏览器中显示的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 赞助支持。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!