소개
시작하기
Last updated August 27, 2026
이 가이드는 MPL-Distro와 Umi 프레임워크로 기존 토큰을 두 지갑에 보냅니다.
요약
MPL-Distro 런치에는 기존 SPL 토큰 mint, 보존된 오프체인 Merkle 할당, 배포 볼트에 충분한 토큰이 필요합니다.
prepareDistribution으로 루트와 증명을 만듭니다.- Permissionless 제출로 7일
Wallet배포를 만듭니다. - 클레임이 시작되기 전에 모든 할당의 합을 입금합니다.
- 트리에 커밋된 정확한 amount, nonce, 증명을 제출합니다.
만들게 될 것
두 수신자 배포를 만들고 350,000 토큰 기본 단위를 입금한 뒤, 첫 수신자의 100,000 단위 클레임을 제출합니다.
CLI에서 생성과 자금 투입
Metaplex CLI로 배포를 만들고 토큰을 입금하거나 출금할 수 있습니다. Merkle 증명 생성과 클레임 제출은 이 SDK 워크스루에서 합니다.
바로가기: 사전 요구사항 · 설치 · 생성 · 자금 투입 · 클레임 · 오류
빠른 시작
MPL-Distro 빠른 시작에는 네 개의 필수 단계가 있습니다.
- MPL-Distro 클라이언트를 설치하고 Umi에
mplDistro()를 등록합니다. - 할당 루트, 증명, amount, nonce를 생성하고 보존합니다.
- 배포를 만들고 전체 토큰 할당을 입금합니다.
distribute로 증명을 제출하고 클레임 영수증을 확인합니다.
사전 요구사항
MPL-Distro에는 자금이 있는 Solana 서명자와 원본 SPL Token 프로그램이 소유한 기존 mint가 필요합니다.
- Node.js 20 이상
- 임대료, 트랜잭션 수수료, 0.002 SOL 클레임 프로토콜 수수료용 SOL을 가진 Umi identity
- 기존 SPL 토큰 mint와 그 권한자의 자금이 있는 associated token account
- 토큰 기본 단위로 표현한 수신자 주소와 할당량(mint의 최소 단위. decimals가 6인 토큰은 1.0 토큰당
1_000_000단위)
예제는 Token-2022 mint를 받지 않습니다. 원본 SPL Token 프로그램 mint를 사용하세요.
MPL-Distro SDK 설치
트랜잭션을 준비하고 제출하는 애플리케이션에 MPL-Distro 클라이언트와 Umi 피어 의존성을 설치합니다.
npm install @metaplex-foundation/mpl-distro@^0.4 \
@metaplex-foundation/umi@^1.1 \
@metaplex-foundation/umi-bundle-defaults \
@metaplex-foundation/mpl-toolbox@^0.10
Core 에셋 서명자로 클레임할 때만 @metaplex-foundation/mpl-core를 설치하세요.
지갑 배포 생성
수신자 목록을 Merkle 루트로 커밋하고 반환된 증명을 오프체인에 저장해 배포를 만듭니다.
1import {
2 AllowedDistributor,
3 createDistribution,
4 DistributionType,
5 findDistributionPda,
6 mplDistro,
7 prepareDistribution,
8} from '@metaplex-foundation/mpl-distro'
9import { generateSigner, publicKey } from '@metaplex-foundation/umi'
10import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
11
12const umi = createUmi(
13 process.env.RPC_URL ?? 'https://api.devnet.solana.com'
14).use(mplDistro())
15
16// Use umi.use(keypairIdentity(yourKeypair)) when the Umi identity
17// should be the distribution authority.
18
19const mint = publicKey(process.env.TOKEN_MINT!)
20const recipients = [
21 { address: publicKey(process.env.RECIPIENT_1!), amount: 100_000n },
22 { address: publicKey(process.env.RECIPIENT_2!), amount: 250_000n },
23]
24const { root, proofs, treeHeight } = prepareDistribution(recipients)
25const seed = generateSigner(umi)
26const now = BigInt(Math.floor(Date.now() / 1000))
27
28await createDistribution(umi, {
29 mint,
30 seed,
31 merkleRoot: root,
32 treeHeight,
33 startTime: now,
34 endTime: now + 7n * 24n * 60n * 60n,
35 totalClaimants: BigInt(recipients.length),
36 name: 'Community distribution',
37 distributionType: DistributionType.Wallet,
38 allowedDistributor: AllowedDistributor.Permissionless,
39 subsidizeReceipts: false,
40}).sendAndConfirm(umi)
41
42const [distribution] = findDistributionPda(umi, {
43 mint,
44 seed: seed.publicKey,
45})
46
47// Store each recipient's amount, nonce, and proof in your claim service.
48console.log('Distribution:', distribution)
49console.log('Proofs:', proofs)
50
51// Distribution: <distribution PDA>
52// Proofs: <one proof array per recipient>
seed 서명자는 mint에 대해 배포 주소를 고유하게 만들므로 같은 토큰에 둘 이상의 배포를 둘 수 있습니다. 결과 PDA는 ["distribution", mint, seed]를 쓰므로, 주소를 다시 유도하려면 seed 공개 키를 보관해야 합니다.
클레임 중 할당 데이터는 불변
권한자는 startTime <= now <= endTime 동안 Merkle 루트, 트리 높이, 시작 시각, claimant 수를 바꿀 수 없습니다. 클레임을 열기 전에 전체 할당 파일을 검증하고 백업하세요.
지갑 배포에 자금 투입
모든 할당의 합 이상을 프로그램 소유 associated token account에 입금해 배포에 자금을 넣습니다. 현재 배포 권한자가 deposit에 서명해야 합니다.
1import {
2 deposit,
3 mplDistro,
4} from '@metaplex-foundation/mpl-distro'
5import { publicKey } from '@metaplex-foundation/umi'
6import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
7
8const umi = createUmi(
9 process.env.RPC_URL ?? 'https://api.devnet.solana.com'
10).use(mplDistro())
11
12// The Umi identity must be the current distribution authority.
13
14const distribution = publicKey(process.env.DISTRIBUTION_ADDRESS!)
15const mint = publicKey(process.env.TOKEN_MINT!)
16const totalAmount = 350_000n
17
18await deposit(umi, {
19 distribution,
20 mint,
21 amount: totalAmount,
22}).sendAndConfirm(umi)
23
24// The distribution ATA contains 350000 base units.
이 튜토리얼은 토큰만 입금합니다. 선택적 클레임 영수증 임대료 보조금은 자금 투입과 회수에서 다룹니다.
지갑 할당 클레임
커밋된 목록에서 생성한 동일한 수신자, amount, nonce, 증명을 제출해 할당을 클레임합니다.
1import {
2 distribute,
3 mplDistro,
4 prepareDistribution,
5} from '@metaplex-foundation/mpl-distro'
6import { publicKey } from '@metaplex-foundation/umi'
7import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
8
9const umi = createUmi(
10 process.env.RPC_URL ?? 'https://api.devnet.solana.com'
11).use(mplDistro())
12
13// The payer may be the recipient or a third-party distributor, depending on
14// the distribution's allowedDistributor setting.
15
16const distribution = publicKey(process.env.DISTRIBUTION_ADDRESS!)
17const mint = publicKey(process.env.TOKEN_MINT!)
18const recipients = [
19 { address: publicKey(process.env.RECIPIENT_1!), amount: 100_000n },
20 { address: publicKey(process.env.RECIPIENT_2!), amount: 250_000n },
21]
22const recipientIndex = 0
23const { proofs } = prepareDistribution(recipients)
24
25await distribute(umi, {
26 distribution,
27 mint,
28 recipient: recipients[recipientIndex].address,
29 amount: recipients[recipientIndex].amount,
30 proof: proofs[recipientIndex],
31 nonce: 0,
32}).sendAndConfirm(umi)
33
34// The recipient ATA receives 100000 base units and a claim receipt is created.
프로그램은 필요하면 수신자의 정규 associated token account를 만들고, 볼트에서 토큰을 전송하며, 클레임 영수증을 만듭니다. 같은 할당의 두 번째 트랜잭션은 AlreadyClaimed로 실패합니다.
MPL-Distro 계정 확인
확인 후 배포와 결정적 클레임 영수증을 가져와 클레임을 검증합니다.
1import {
2 fetchClaimReceipt,
3 fetchDistribution,
4 findClaimReceiptPda,
5 mplDistro,
6} from '@metaplex-foundation/mpl-distro'
7import { publicKey } from '@metaplex-foundation/umi'
8import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
9
10const umi = createUmi(
11 process.env.RPC_URL ?? 'https://api.devnet.solana.com'
12).use(mplDistro())
13
14const distribution = publicKey(process.env.DISTRIBUTION_ADDRESS!)
15const recipients = [
16 { address: publicKey(process.env.RECIPIENT_1!), amount: 100_000n },
17 { address: publicKey(process.env.RECIPIENT_2!), amount: 250_000n },
18]
19const recipientIndex = 0
20
21const [receipt] = findClaimReceiptPda(umi, {
22 distribution,
23 recipient: recipients[recipientIndex].address,
24 amount: recipients[recipientIndex].amount,
25 nonce: 0,
26})
27
28const [distributionAccount, receiptAccount] = await Promise.all([
29 fetchDistribution(umi, distribution),
30 fetchClaimReceipt(umi, receipt),
31])
32
33console.log(distributionAccount.claimCount)
34console.log(receiptAccount.amount)
35
36// claimCount includes this allocation and the receipt stores 100000
일반적인 MPL-Distro 오류
MPL-Distro 오류는 일치하지 않는 증명, 창, 권한, 볼트 잔액을 식별합니다.
| 오류 | 원인 | 해결 |
|---|---|---|
InvalidClaimProof | 주소, amount, nonce, 또는 증명이 커밋된 리프와 다름 | 같은 보존된 할당 레코드에서 모든 값을 불러오세요 |
DistributionNotStarted | 클러스터 타임스탬프가 startTime보다 앞섬 | 구성된 Unix 타임스탬프까지 기다리세요 |
DistributionEnded | 클러스터 타임스탬프가 endTime보다 뒤 | 권한자가 새 배포를 만들어야 합니다 |
AlreadyClaimed | 클레임 영수증 PDA가 이미 존재함 | 할당을 완료로 취급하세요 |
InsufficientFunds | 기록된 배포 잔액이 클레임 금액보다 적음 | 활성 창 전·중·후에 더 입금하거나 이전 출금을 검토하세요 |
RecipientMustSign | recipient 게이트 클레임에서 수신자 서명자가 빠짐 | 수신자를 서명자로 제출하세요 |
InvalidDistributor | permissioned distributor가 일치하지 않음 | 구성된 distributor 서명자를 사용하세요 |
검증된 구성
시작하기 흐름은 현재 MPL-Distro 클라이언트 테스트와 생성된 명령 빌더를 따릅니다.
| 구성 요소 | 버전 |
|---|---|
@metaplex-foundation/mpl-distro | 0.4.x |
@metaplex-foundation/umi | 1.1.x 이상 |
@metaplex-foundation/mpl-toolbox | 0.10.x |
| Token program | 원본 SPL Token 프로그램 |
참고사항
시작하기 흐름은 작은 지갑 배포를 보여 줍니다. 프로덕션 전달이 증명 저장, 클레임 페이지, 미클레임 토큰 회수를 다룹니다.
- Unix 타임스탬프는 초이며 JavaScript 밀리초가 아닙니다.
- 토큰 기본 단위 수량과 타임스탬프에는
bigint를 사용하세요. prepareDistribution은 1,000개 할당에서 메모리 최적화 구현으로 전환합니다.- 매우 큰 할당 구축은 제어된 Node.js 프로세스에서 실행하고, mainnet에 자금을 넣기 전에 증명 전달을 테스트하세요.
- Permissionless 지불자는 다른 지갑의 클레임을 제출할 수 있지만, 토큰은 그 수신자에게만 갑니다.
FAQ
MPL-Distro가 토큰 mint를 만드나요?
아니요. 배포를 만들기 전에 SPL 토큰 mint를 만들고 자금을 넣으세요.
Merkle 증명은 어디에 저장해야 하나요?
프로그램은 루트만 저장하므로 각 주소, amount, nonce, 증명을 내구성 있는 데이터베이스 또는 클레임 파일에 저장하세요. 프로덕션 전달을 참조하세요.
한 지갑이 여러 할당을 받을 수 있나요?
예. 그 외에는 동일한 지갑과 amount 할당마다 다른 nonce를 지정하세요.
