如何使用 Crossmint 的铸造 API 空投 Solana NFT
该文章详细介绍了如何使用Crossmint API和QuickNode工具批量空投Solana NFT,包括设置项目、定义类型和常量、创建NFT、验证空投结果等步骤。
概述
传递 NFT从未如此简单。无论你是一家希望开始使用NFT的Web2公司,还是有一个希望通过NFT奖励的Web3社区,Crossmint的Mint API允许你只需一个POST请求就能向用户铸造NFT。Crossmint的NFT API可以直接通过QuickNode的市场获得,因此开始起来更加轻松。在本指南中,你将创建一个简单的脚本,允许你将 NFT 直接铸造并交付给一列客户(通过钱包地址或电子邮件地址?)。
你将要做什么
在本指南中,我们将:
- 创建带有Crossmint API附加功能的QuickNode端点
- 创建NFT元数据
- 使用Crossmint API(使用TypeScript)将NFT空投到Solana钱包和电子邮件地址的组合列表中
- 验证空投是否成功
- 将空投细节记录到
.json文件中
你将需要什么
要跟随本指南,你将需要以下内容:
- JavaScript/TypeScript编程语言的基础知识
- 安装Nodejs(版本16.15或更高)
- 安装npm或yarn(我们将使用yarn来初始化我们的项目并安装必要的包。如果你更喜欢使用npm,也可以)
- TypeScript经验和已安装ts-node
设置你的项目
在终端中创建一个新的项目目录:
mkdir crossmint-drop
cd crossmint-drop
为你的应用创建一个文件,app.ts:
echo > app.ts
使用“yes”标志初始化你的项目,以使用新包的默认值:
yarn init --yes
#or
npm init --yes
创建一个启用.json导入的tsconfig.json:
tsc -init --resolveJsonModule true --target es2020
创建一个results文件夹,用于保存我们空投的输出:
mkdir results
安装Solana Web3依赖项
虽然本练习不是必需的,但我们将使用Solana-Web3库在调用Crossmint API之前验证钱包地址。我们还将使用Axios来向Crossmint发出HTTP请求。在终端中输入:
yarn add @solana/web3.js@1 axios
#or
npm install @solana/web3.js@1 axios
我们需要从这些库和fs中获取一些组件,以便将结果写入文件。在你选择的IDE中打开crossmint-drop文件夹(我们将使用VSCode),并在app.ts的第1行添加以下导入语句:
import { PublicKey } from '@solana/web3.js';
import axios from 'axios';
import fs from 'fs';
使用你的QuickNode端点连接到Solana集群
要快速访问Crossmint API,以便你能够使用一行代码创建并发送NFT给用户,即使他们没有加密钱包,你需要创建带有Crossmint附加功能的QuickNode端点。在此处注册免费账户。创建一个新的Solana Devnet端点,并确保用Crossmint NFT Mint API进行配置:

复制HTTP提供程序链接:

在app.ts中的导入语句下,声明你的RPC(我们在运行脚本时需要这一点):
const QUICKNODE_RPC = 'https://example.solana-devnet.quiknode.pro/0123456/';
你的环境应该看起来像这样。

你已准备就绪。让我们开始构建应用!
声明类型
我们将为脚本使用TypeScript,因此我们将定义一些类型和接口,以帮助保持代码的整洁和准确。如果你是JavaScript开发人员或不喜欢使用TypeScript,也没关系。
在代码中的// 类型部分创建,并在应用的顶部(在导入后)添加以下代码:
// TYPES
type Email = string;
type StringPubKey = string;
type Destination = Email | StringPubKey;
interface NftMetadata {
name: string,
image: string,
description: string
attributes: {trait_type: string, value: string}[],
properties: {
files: {uri: string, type: string}[],
category: string
}
}
interface MintNftProps {
destination: Destination,
qnEndpoint: string,
collectionId: string,
nftInfo: NftMetadata
}
interface FetchMintProps {
qnEndpoint: string,
collectionId: string,
crossmintId: string
}
interface MintResult {
destination: string,
crossmintId: string,
mint: string
}
以下是每个声明的小介绍:
- 首先,我们将我们的_destination_声明为_Email_或_StringPubKey_(这将是我们希望用户的NFT发送到的位置)。
- 接下来,我们定义了我们的_NftMetadata_,它接受关于我们的NFT的基本信息,包括一个_traits_数组。
- _MintNftProps_定义了我们将在铸造函数中使用的输入。我们需要一个接收地址,一个QuickNode端点,集合ID,以及正在铸造的NFT的元数据。
- _FetchNftProps_定义了我们将用来检查铸造状态的输入。
- _MintResult_概述了我们将如何记录结果(包括接收地址、来自CrossMint的唯一ID以及铸造地址——在Solana区块链上的唯一公钥)。
定义关键常量
让我们为我们的项目定义一些关键常量。在你的类型下面,添加:
// CONSTANTS
const QUICKNODE_RPC = 'https://example.solana-devnet.quiknode.pro/0123456/';
const COLLECTION_ID = 'default-solana';
const DROP_LIST: Destination[] = [\
'quickguides@test.com',\
'CTrLzkrcnqgqSTmzJ146ZTRkLAvwcjnxGSZBvqC5BH3w',\
'quickdemo@test.com',\
'DemoKMZWkk483hX4mUrcJoo3zVvsKhm8XXs28TuwZw9H'\
];
const DELAY = 1000;
- 我们首先将
QUICKNODE_RPC移动到其余常量同处。 - 然后将我们的
COLLECTION_ID设置为default-solana。这是Crossmint NFT在Solana上的默认铸造值。如果你计划启动一系列NFT,创建自己的集合可能是明智的。你可以使用cm_createCollection方法做到这一点(文档)。出于本示例的目的,我们将使用默认值。 - 一份我们希望发送NFT的电子邮件地址和Solana钱包地址列表(我们将设置我们的应用程序以能够同时处理两者)。Crossmint的Mint API为新用户创建钱包,使你可以将NFT发送到他们的电子邮件地址,并轻松地引导新用户。
- 我们将添加一个简单的延迟,以防止触发任何速率限制。我们建议你查看Crossmint的最佳实践,如果你计划发起任何大规模的NFT空投。我们将
DELAY设置为1秒(1,000毫秒)。
让我们添加一个额外的工具常量,即wait函数。我们将使用它在API调用之间创建延迟:
async function wait(ms: number):Promise<void> {
return new Promise<void>((resolve) => {
setTimeout(() => {
resolve();
}, ms);
});
}
好的!让我们进入Crossmint API。
创建铸造函数
让我们创建一个HTTP请求到Crossmint来铸造我们的NFT。此函数将完成三件事:
- 验证我们的接收地址是否为有效的电子邮件地址或Solana公钥
- 组装POST请求
- 发送POST请求并处理响应
在app.ts中,添加一个requestCrossMintNft函数:
const requestCrossMintNft = async ({ destination, qnEndpoint, collectionId, nftInfo }: MintNftProps) => {
// 正则表达式验证电子邮件地址
const emailRegex: RegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
// 验证并定义接收者(作为电子邮件地址或Solana钱包,否则抛出错误)
let recipient: string;
if (emailRegex.test(destination)) {
recipient = `email:${destination}:sol`;
} else if (new PublicKey(destination)) {
recipient = `solana:${destination}`;
}
else {
throw new Error('无效的接收地址(必须是有效的电子邮件地址或Solana钱包地址)。');
}
// 组装POST请求
const metadata = {
"name": nftInfo.name,
"image": nftInfo.image,
"description": nftInfo.description
};
const data = {
jsonrpc: "2.0",
id: 1,
method: "cm_mintNFT",
params: [collectionId, recipient, metadata], // https://docs.crossmint.com/docs/cm-mintnft
};
const config = {
headers: {
"Content-Type": "application/json",
},
};
// 发送POST请求
return new Promise<string>(async (resolve, reject) => {
try {
let response = await axios.post(qnEndpoint, data, config);
resolve(response.data.result.id as string);
} catch (error) {
reject("发送请求到CrossMint时出现错误。检查输入。");
}
});
}
我们所做的事情如下:
- 首先,我们使用JavaScript正则表达式(RegExp)和Solana _PublicKey_类来检查提供的地址是否为有效的目的地。基于你的分发列表(例如,如果你只发送到电子邮件地址,你就不需要Solana PublicKey检查,反之亦然),可以随意修改此内容。如果无效,我们将抛出错误。
正则表达式
如果你从未使用过正则表达式,emailRegex模式检查输入字符串是否以一个或多个来自集合a-z、A-Z、0-9、.!#$%&'*+/=?^_{|}~-的字符开始,后面跟上@符号,然后是一个或多个来自集合a-z、A-Z、0-9及连字符-的字符,有61个字符的最大限制,并且可以选择在最后添加一个点.后面跟上更多字符,至多61个字符,来自集合a-z、A-Z、0-9和连字符-。
-
然后,我们根据Crossmint文档组装我们的POST请求。请注意,我们的
metadata是使用我们的nftInfo参数编译的。这意味着我们可以为每个铸造的NFT创建自定义属性! -
最后,我们返回一个承诺以POST
cm_mintNFT方法。如果收到成功的响应,承诺将返回Crossmint ID(一个唯一的交易标识符)。
创建获取铸造函数
在我们向Crossmint发送铸造请求后,我们需要一种方法来验证我们的铸造是否成功(到目前为止,我们只知道Crossmint成功接收了我们的请求,而不知道Solana是否确认了铸造的NFT)。为此,我们可以使用从前一步返回的ID进行状态检查。
创建一个新函数,fetchMintAddress:
const fetchMintAddress = async ({ collectionId, qnEndpoint, crossmintId }: FetchMintProps) => {
// 组装POST请求
const data = {
jsonrpc: "2.0",
id: 1,
method: "cm_getNFTMintStatus",
params: [collectionId,crossmintId], //https://docs.crossmint.com/docs/cm-getnftmintstatus
};
const config = {
headers: {
"Content-Type": "application/json",
},
};
// 发送POST请求
return new Promise<string>(async (resolve, _reject) => {
try {
let response = await axios.post(qnEndpoint, data, config);
resolve(response.data.result.onChain.mintHash as string);
} catch (error) {
//reject("获取铸造地址时出错。");
}
});
}
从结构上看,这与我们上一步非常相似:
- 我们组装POST请求(这次调用
cm_getNFTMintStatus并传入从上一步返回的crossmintId)。 - 发送POST请求,并在成功时返回铸造的NFT的唯一链上铸造哈希。
将这两者结合起来,你可以运行这两个函数以铸造单个NFT,但我们想要一些乐趣——让我们空投一堆?
创建批量空投函数
我们具备了使用Crossmint API铸造和确认NFT所需的所有工具——我们需要一种能够执行批量投放并具有自定义每个NFT的能力的方法。我们需要创建一个dropNfts函数,它将:
- 使用
.map为dropList中的每个_目的地_创建一个承诺。 - 基于某个唯一特征定义我们的元数据(在此情况下,我们将使用索引
i为每个NFT赋予一个唯一的名称和特性。你可以根据自己的风格更新元数据!)。 - 创建一个承诺:
- 使用
requestCrossMintNft请求Crossmint铸造NFT - 通过调用等待1分钟来等待铸造的发生。(注意:这是我们演示的简单方法。根据你的需求,你可能希望设置一些查询/重试逻辑。)
- 使用
fetchMintAddress验证铸造是否成功 - 返回关于投放NFT的信息
- 使用
- 使用
Promise.allSettled()执行所有承诺 - 在
results目录中创建我们结果的日志
以下函数有点长,但我们已经在前面的步骤中完成了所有繁重的工作!在app.ts中创建一个dropNfts函数,该函数接受_目的地_列表、你的QuickNode端点和集合ID:
const dropNfts = async (dropList: Destination[], qnEndpoint: string, collectionId: string) => {
console.log('生成承诺中...');
let promises = dropList.map((drop, i) => {
// 1-定义自定义元数据
const nftNumber = (i+1).toString();
const nftInfo = {
name: `Demo Airdrop # ${nftNumber}`,
image: 'https://arweave.net/UTFFfaVA3HoFcxwoMHEcvBLq19HrW6FuzpyygXqxduk',
description: '通过Quicknode附加功能使用Crossmint铸造API的演示空投NFT',
attributes: [\
{\
trait_type: "background",\
value: "blue"\
},\
{\
trait_type: "type",\
value: "pixel"\
},\
{\
trait_type: "id",\
value: nftNumber\
}\
],
properties: {
files: [\
{\
"uri": "https://arweave.net/UTFFfaVA3HoFcxwoMHEcvBLq19HrW6FuzpyygXqxduk",\
"type": "image/png"\
}\
],
category: "image"
}
};
// 2-创建承诺
return new Promise< MintResult >(async (resolve, reject)=>{
setTimeout(async ()=>{
try {
let crossmintId = await requestCrossMintNft({
destination: drop,
qnEndpoint,
collectionId,
nftInfo
});
if (!crossmintId) throw new Error('未收到CrossMint ID。');
await wait(60000); // 等待1分钟
let mint = await fetchMintAddress({
collectionId,
qnEndpoint,
crossmintId
});
resolve({
destination: drop,
crossmintId: crossmintId,
mint: mint ?? ''
});
} catch (error) {
reject('发送请求到CrossMint时出现未知错误。');
}
},i * DELAY);
})
});
// 3-执行承诺
console.log('执行承诺...(这将需要1分钟以上)');
let results = await Promise.allSettled(promises);
// 4-保存结果
console.log('正在写入结果到./results/results.json');
let data = JSON.stringify(results);
fs.writeFileSync('./results/results.json',data);
}
太棒了!让我们开始吧。
空投你的NFT ?
在你的app.ts末尾,调用你的dropNfts函数:
dropNfts(DROP_LIST, QUICKNODE_RPC, COLLECTION_ID);
在终端中输入以下内容:
ts-node app
大约等待一分钟后,你应该看到新生成的results.json,其中包含你的铸造结果数组:
[\
{\
"status": "fulfilled",\
"value": {\
"destination": "quickguides@test.com",\
"crossmintId": "60f33f72-a8d8-41ce-b28a-bc899aa7b929",\
"mint": "AbJjT4j9MYQTya9aZ9qmCd36dspwoMnhfsEpZL91sFwG"\
}\
},\
{\
"status": "fulfilled",\
"value": {\
"destination": "DemoKMZWkk483hX4mUrcJoo3zVvsKhm8XXs28TuwZw9H",\
"crossmintId": "0c4836cb-26dc-48a2-a55f-5d3ca40699da",\
"mint": "5RRDSrq6ME5Yz9qXcKRvSQeGD1F2AEnURnjfCs7BTEvN"\
}\
},\
// 等等。\
]
干得不错!
结束语
就这样,你可以批量空投NFT给你的web2和web3客户!如果你在本指南中遇到任何问题或只是想展示你的NFT项目,请联系我们,通过Discord或Twitter告诉我们你在做什么!
- 原文链接: quicknode.com/guides/sol...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~