简介

生产交付

Last updated August 27, 2026

MPL-Distro 在链上只存储 Merkle 根。生产空投将每笔分配的证明持久化在链下,并为接收方提供提交途径。

摘要

生产交付是围绕 MPL-Distro 分发的链下工作:存储领取记录、将其提供给正确的领取人,并在窗口结束时回收剩余。

没有托管的领取界面

MPL-Distro 不提供领取网站,也不提供电子邮件、短信或 Discord identity。Metaplex CLI 可以创建、注资、查看和回收分发;它不生成 Merkle 证明,也不提交领取。通过你已在使用的任何渠道通知用户;链上叶子仍然是钱包或 旧版 NFT mint。

跳转至: 前置条件 · 提交模式 · 持久化记录 · 交付证明 · 回收代币

快速开始

生产 MPL-Distro 空投在链上程序周围有五个交付步骤。

  1. 构建完整分配列表并用 prepareDistribution 生成根。
  2. 为每笔分配持久化一条领取记录,然后创建并注资分发。
  3. 从按钱包或 NFT mint 键控的领取页面或查询 API 提供每条记录。
  4. 用存储的 amount、nonce 和证明提交 distributedistributeToLegacyNft
  5. endTime 之后提取未领取代币和未使用的收据租金补贴。

前置条件

生产交付从现有 SPL 代币 mint 和已完成的分配列表开始。

  • 一份 入门指南 分发(或后端中相同的创建和存款步骤)
  • 领取记录的持久存储(数据库、对象存储或可下载文件)
  • 已为租金、网络费和 0.002 SOL 协议费注资的领取交易支付方
  • 分发类型:钱包旧版 NFT

分配量是代币基本单位。对于 6 位小数的 mint,1.0 代币是 1_000_000

选择领取提交模式

allowedDistributor 决定谁可以提交有效证明;它不改变代币去向。

模式谁签署领取典型生产形态
Permissionless任意有资金的支付方用户或中继者付费的领取页面;代币仍到达叶子
Recipient叶子钱包或当前 NFT 所有者受益人必须批准交易的领取页面
Permissioned配置的 permissionedDistributor一个后端是唯一允许提交证明的签名者

代币始终到达叶子的规范 associated token accountLegacyNft 则为当前 NFT 所有者的 ATA)。Permissionless 提交不能将资金重定向到支付方。

将分发权限方和任何 permissioned-distributor 密钥放在浏览器应用程序之外。

持久化分配记录

每笔领取需要该叶子在 prepareDistribution 中使用的相同地址、amount、nonce 和证明。链上账户无法仅从根重建这些值。

从完整列表开始,然后在相同索引存储证明:

allocations.json
[
{
"address": "8SoWVrwJ6vPa3rcdNBkhznR54yJ6iQqPSmgcXVGnwtEu",
"amount": "10000000",
"nonce": "0"
},
{
"address": "GjwcWFQYzemBtpUoN5fMAP2FZviTtMRWCmrppGuTthJS",
"amount": "5000000",
"nonce": "0"
}
]
persistClaimRecords.ts
1import { mplDistro, prepareDistribution } from '@metaplex-foundation/mpl-distro'
2import { publicKey } from '@metaplex-foundation/umi'
3import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
4
5const umi = createUmi(
6 process.env.RPC_URL ?? 'https://api.devnet.solana.com'
7).use(mplDistro())
8
9const allocations = [
10 { address: publicKey(process.env.RECIPIENT_1!), amount: 100_000n, nonce: 0n },
11 { address: publicKey(process.env.RECIPIENT_2!), amount: 250_000n, nonce: 0n },
12]
13
14const { root, proofs, treeHeight } = prepareDistribution(allocations)
15
16const claimRecords = allocations.map((allocation, index) => ({
17 address: allocation.address,
18 amount: allocation.amount.toString(),
19 nonce: (allocation.nonce ?? 0n).toString(),
20 proof: proofs[index],
21}))
22
23// Persist claimRecords with the distribution PDA after createDistribution.
24console.log(root, treeHeight, claimRecords.length)
25
26// One durable record per allocation: address, amount, nonce, and proof.

createDistribution 之后,在每条记录上存储分发 PDA。领取交易需要该地址以及 mintamountnonceproof

字段用于说明
address叶子 identity钱包公钥或旧版 NFT mint
amount叶子数据字符串或 bigint 形式的代币基本单位
nonce叶子数据默认为 0;同一地址和 amount 出现两次时需要
proofdistribute每个树层级一个 32 字节兄弟哈希,按 SDK 顺序
distributiondistribute创建后 findDistributionPda 的 PDA

打开领取前存储证明

startTime <= now <= endTime 期间,权限方不能更改 Merkle 根、树高度、开始时间或 claimant 数量。窗口开始前请备份完整分配文件。

交付 Merkle 证明

应用程序查找一条存储记录并将其传给 distributedistributeToLegacyNft。MPL-Distro 不索引接收方。

常见交付形态:

  1. 领取页面。 用户连接钱包、支付网络费,并提交其存储的证明。
  2. 查询 API。 服务将 address{ amount, nonce, proof, distribution } 映射给你的前端或中继者。
  3. 赞助领取。 接收方(或资格检查)仍触发领取。中继者支付 SOL,使用户不需要有资金的钱包。代币仍到达叶子 ATA。

赞助领取不能替代在一次后端循环中发送每一笔分配。每笔 Distro 领取仍支付 0.002 SOL 协议费。若每位接收方都将立即收到代币且无需领取步骤,请使用直接 SPL 代币 转账。

当部分分配可能未被领取、你需要公开 Merkle 承诺和时间窗口,或中继者应仅为实际领取的人付费时,请使用 Distro。

对于 LegacyNft,按 NFT mint 键控查询。在领取时解析当前所有者;除非你本意是 钱包分发,否则不要将快照所有者冻结到叶子中。

不要从链上根重建证明。用不同哈希、字节序或叶子集生成的证明会以 InvalidClaimProof 失败。

打开领取窗口

仅当集群时间位于包含性 startTimeendTime 窗口内且金库持有足够代币时,领取才会成功。

在向每位接收方开放列表之前,用 入门指南 流程创建、存款并提交第一笔测试领取。确认:

  • 持久化文件中的样本证明与 distribute 匹配。
  • 协议费支付方有足够 SOL 支付 0.002 SOL 费用和收据租金,或已为 收据补贴 注资。
  • 权限方密钥未暴露给领取前端。

监控领取

成功领取会创建永久领取收据 PDA。获取该账户,或比较分发上的 claimCount / claimAmount,即可知道哪些分配已完成。

将该精确 (distribution, recipient, amount, nonce) 元组上的 AlreadyClaimed 视为成功。LegacyNft mint 的所有权转移不会重置收据。

回收未领取代币

仅当分发非活动时(startTime 之前或 endTime 之后),分发权限方才提取剩余代币和未使用的补贴 SOL。

withdrawwithdrawSubsidy注资与回收。在结束时间戳周围留出运营余量,以免最后一批领取与回收交易竞态。

生产交付检查清单

在用户依赖之前,将链下文件对照链上根进行校验。

  • amount 值之和由金库存款覆盖。
  • 每份持久化证明都是同一列表、同一顺序的 prepareDistribution 输出。
  • 当泄露的证明不得足以提交时使用 Recipient 模式。
  • 领取前端从不持有分发权限方。
  • 未领取代币有可以在 endTime 之后调用 withdraw 的所有者。

注意事项

MPL-Distro 不能替代你的分配数据库、通知渠道或领取 UI。

  • totalClaimants 是元数据,并不限制成功证明的数量。
  • 领取收据不会被关闭,因此收据租金保持已分配。
  • 大型列表应在受控 Node.js 进程中构建;prepareDistribution 在 1,000 个叶子时切换实现。

常见问题

MPL-Distro 会托管领取网站吗?

不会。程序只存储 Merkle 根。应用程序必须持久化证明并提供领取页面或 API。

电子邮件或 Discord 句柄可以作为 Merkle 叶子吗?

不可以。叶子是钱包公钥或旧版 NFT mint。链下渠道可以通知用户,但它们不是链上 identity。

公开 Merkle 证明安全吗?

Permissionless 模式下,任何持有有效证明的人都可以提交领取;代币仍到达叶子地址。当仅凭证明访问不得授权提交时,请使用 Recipient 模式。

后端是否应自行提交每一份 Merkle 证明?

不应该。从后端提交每一份证明通常比 SPL 代币 转账更贵,因为每笔 Distro 领取都支付协议费。使用中继者让没有 SOL 的用户仍能领取,或在部分分配可能未被领取且你需要 Merkle 窗口时使用 Distro。

何时可以回收未领取代币?

权限方可以在开始时间戳之前或结束时间戳之后提取代币。当 startTime <= clusterTime <= endTime 时提取会被拒绝。