기능
자산 민팅
Token Metadata 개요에서 논의했듯이, Solana의 디지털 자산은 토큰을 설명하는 여러 온체인 계정과 오프체인 데이터로 구성됩니다. 이 페이지에서는 이러한 자산을 민팅하는 과정을 살펴보겠습니다.
민팅 과정
대체 가능한, 반-대체 가능한 또는 대체 불가능한 자산을 민팅하고 싶든, 전체적인 과정은 동일합니다:
- 오프체인 데이터 업로드. 먼저 오프체인 데이터가 준비되었는지 확인해야 합니다. 이는 자산을 설명하는 JSON 파일이 어딘가에 저장되어 있어야 한다는 의미입니다. 해당 JSON 파일이 URI를 통해 접근 가능한 한, 어떻게 또는 어디에 저장되는지는 중요하지 않습니다.
- 온체인 계정 생성. 그런 다음 자산의 데이터를 보유할 온체인 계정을 생성해야 합니다. 어떤 정확한 계정이 생성될지는 자산의 토큰 표준에 따라 다르지만, 모든 경우에 메타데이터 계정이 생성되고 오프체인 데이터의 URI를 저장합니다.
- 토큰 민팅. 마지막으로 이 모든 계정과 연관된 토큰을 민팅해야 합니다. 대체 불가능한 자산의 경우, 이는 단순히 0에서 1로 민팅하는 것을 의미합니다. 대체 불가능성은 1보다 큰 공급량을 갖는 것을 금지하기 때문입니다. 대체 가능한 또는 반-대체 가능한 자산의 경우, 원하는 만큼 토큰을 민팅할 수 있습니다.
구체적인 코드 예제를 제공하면서 이러한 단계를 더 자세히 살펴보겠습니다.
오프체인 데이터 업로드
오프체인 데이터를 업로드하기 위해 어떤 서비스든 사용하거나 단순히 자신의 서버에 저장할 수 있지만, Umi SDK가 이를 도울 수 있다는 점에 주목할 가치가 있습니다. 이는 선택한 업로더를 선택할 수 있게 해주고 데이터를 업로드하기 위한 통합된 인터페이스를 제공하는 플러그인 시스템을 사용합니다.
자산 및 JSON 데이터 업로드
const [imageUri] = await umi.uploader.upload([imageFile])
const uri = await umi.uploader.uploadJson({
name: 'My NFT',
description: 'This is my NFT',
image: imageUri,
// ...
})
이제 URI가 있으므로 다음 단계로 넘어갈 수 있습니다.
다음 단계들은 계정을 생성하고 토큰을 민팅하는 방법을 두 단계로 보여줍니다. 페이지 하단에는 이러한 단계를 결합하여 다양한 토큰 유형을 더 쉽게 만들 수 있는 헬퍼에 대한 코드 예제가 있습니다.
Mint 및 Metadata 계정 생성
선택한 토큰 표준에 필요한 모든 온체인 계정을 생성하려면, 단순히 Create V1 명령어를 사용할 수 있습니다. 이는 요청된 토큰 표준에 적응하여 그에 따라 올바른 계정을 생성합니다.
예를 들어, NonFungible 자산은 Metadata 계정과 MasterEdition 계정을 생성하는 반면, Fungible 자산은 Metadata 계정만 생성합니다.
또한 제공된 Mint 계정이 존재하지 않으면 우리를 위해 생성됩니다. 이런 방식으로 메타데이터를 추가하기 전에 토큰을 준비하기 위해 기본 Token 프로그램을 호출할 필요가 없습니다.
이 명령어는 다양한 매개변수를 받으며 우리의 SDK는 매번 모든 것을 채울 필요가 없도록 기본값을 제공하기 위해 최선을 다합니다. 그렇긴 하지만, 관심이 있을 수 있는 매개변수 목록은 다음과 같습니다:
- Mint: 자산의 Mint 계정. 존재하지 않으면 초기화될 것이므로 서명자로 제공되어야 합니다. 일반적으로 이 목적을 위해 새로운 키페어를 생성합니다.
- Authority: Mint 계정의 권한. 이는 Mint 계정에서 토큰을 민팅할 수 있도록 허용된 계정입니다. SDK에서 지원하는 경우 "Identity" 지갑(즉, 연결된 지갑)으로 기본 설정됩니다.
- Name, URI, Seller Fee Basis Points, Creators 등: Metadata 계정에 저장할 자산의 데이터.
- Token Standard: 자산의 토큰 표준.
createV1는 Mint 계정을 초기화하고 Metadata 계정을 생성할 수 있는 헬퍼 함수입니다. mint가 이미 존재하는 경우 메타데이터 계정만 생성합니다. createMetadataAccountV3 사용 방법을 찾고 있다면 대신 이 함수를 사용해야 합니다.
1import { generateSigner, percentAmount } from '@metaplex-foundation/umi';
2import {
3 createV1,
4 TokenStandard,
5} from '@metaplex-foundation/mpl-token-metadata';
6
7// Assuming umi is set up with mplTokenMetadata plugin
8// See getting-started for full setup
9
10const mint = generateSigner(umi);
11
12// Create the onchain accounts (Mint + Metadata + MasterEdition for NFTs)
13await createV1(umi, {
14 mint,
15 authority: umi.identity,
16 name: 'My NFT',
17 uri: 'https://example.com/my-nft.json',
18 sellerFeeBasisPoints: percentAmount(5.5),
19 tokenStandard: TokenStandard.NonFungible,
20}).sendAndConfirm(umi);
21
22console.log('Created NFT accounts');
23console.log('Mint:', mint.publicKey);
1import { generateKeyPairSigner } from '@solana/kit';
2import {
3 getCreateV1InstructionAsync,
4 TokenStandard,
5} from '@metaplex-foundation/mpl-token-metadata-kit';
6
7// Assuming rpc, rpcSubscriptions, and sendAndConfirm are set up
8// See getting-started for full setup
9
10const mint = await generateKeyPairSigner();
11const authority = await generateKeyPairSigner(); // Your wallet
12
13// Create the onchain accounts (Mint + Metadata + MasterEdition for NFTs)
14const createIx = await getCreateV1InstructionAsync({
15 mint,
16 authority,
17 payer: authority,
18 name: 'My NFT',
19 uri: 'https://example.com/my-nft.json',
20 sellerFeeBasisPoints: 550, // 5.5%
21 tokenStandard: TokenStandard.NonFungible,
22});
23
24// Send the transaction
25await sendAndConfirm({
26 instructions: [createIx],
27 payer: authority,
28});
29
30console.log('Created NFT accounts');
31console.log('Mint:', mint.address);
1use mpl_token_metadata::{
2 accounts::Metadata,
3 instructions::CreateV1CpiBuilder,
4 types::{PrintSupply, TokenStandard},
5};
6
7// 1. every account is specified by a reference to their AccountInfo
8
9let create_cpi = CreateV1CpiBuilder::new(token_metadata_program_info)
10 .metadata(metadata_info)
11 .mint(mint_info, true)
12 .authority(payer_info)
13 .payer(payer_info)
14 .update_authority(update_authority_info, false)
15 .master_edition(Some(master_edition_info))
16 .system_program(system_program_info)
17 .sysvar_instructions(sysvar_instructions_info)
18 .spl_token_program(spl_token_program_info)
19 .token_standard(TokenStandard::NonFungible)
20 .name(String::from("My NFT"))
21 .uri(uri)
22 .seller_fee_basis_points(550)
23 .token_standard(TokenStandard::NonFungible)
24 .print_supply(PrintSupply::Zero);
25
26create_cpi.invoke();
Rust에서 mint 계정을 설정할 때, 계정이 서명자인지 여부를 나타내는 bool 플래그를 지정해야 한다는 점에 주목하세요 – mint 계정이 존재하지 않는 경우 서명자여야 합니다.
토큰 민팅
자산에 대한 모든 온체인 계정이 생성되면, 그에 대한 토큰을 민팅할 수 있습니다. 자산이 대체 불가능한 경우 단순히 그 하나뿐인 토큰을 민팅하고, 그렇지 않으면 원하는 만큼 토큰을 민팅할 수 있습니다. 대체 불가능한 자산은 고유한 토큰이 민팅되어야만 유효하므로 해당 토큰 표준에 필수적인 단계라는 점에 주목하세요.
이를 달성하기 위해 Token Metadata 프로그램의 Mint V1 명령어를 사용할 수 있습니다. 다음 매개변수가 필요합니다:
- Mint: 자산의 Mint 계정 주소.
- Authority: 이 명령어를 승인할 수 있는 권한. 대체 불가능한 자산의 경우, 이는 Metadata 계정의 업데이트 권한이고, 그렇지 않으면 Mint 계정의 Mint Authority를 참조합니다.
- Token Owner: 토큰을 받을 지갑의 주소.
- Amount: 민팅할 토큰의 수. 대체 불가능한 자산의 경우, 이는 1만 가능합니다.
- Token Standard: 자산의 토큰 표준(JavaScript SDK에 필요). 프로그램은 이 인수를 필요로 하지 않지만 우리의 SDK는 다른 대부분의 매개변수에 대해 적절한 기본값을 제공할 수 있도록 필요로 합니다.
1import { mintV1, TokenStandard } from '@metaplex-foundation/mpl-token-metadata';
2
3// Assuming umi is set up with mplTokenMetadata plugin
4// mint from createV1
5
6const mintPublicKey = mint.publicKey; // From the created mint
7const tokenOwner = umi.identity.publicKey; // Wallet to receive the token
8
9// Mint the NFT token
10await mintV1(umi, {
11 mint: mintPublicKey,
12 authority: umi.identity,
13 amount: 1,
14 tokenOwner,
15 tokenStandard: TokenStandard.NonFungible,
16}).sendAndConfirm(umi);
17
18console.log('Minted NFT to:', tokenOwner);
1import {
2 getMintV1InstructionAsync,
3 TokenStandard,
4} from '@metaplex-foundation/mpl-token-metadata-kit';
5
6// Assuming rpc, rpcSubscriptions, and sendAndConfirm are set up
7// mint and authority from createV1
8
9const mintAddress = mint.address; // From the created mint
10const tokenOwner = authority.address; // Wallet to receive the token
11
12// Mint the NFT token
13const mintIx = await getMintV1InstructionAsync({
14 mint: mintAddress,
15 authority,
16 payer: authority,
17 amount: 1,
18 tokenOwner,
19 tokenStandard: TokenStandard.NonFungible,
20});
21
22await sendAndConfirm({
23 instructions: [mintIx],
24 payer: authority,
25});
26
27console.log('Minted NFT to:', tokenOwner);
1use mpl_token_metadata::instructions::MintV1CpiBuilder;
2
3// 1. every account is specified by a reference to their AccountInfo
4
5let mint_cpi = MintV1CpiBuilder::new(token_metadata_program_info)
6 .token(token_info)
7 .token_owner(Some(token_owner_info))
8 .metadata(metadata_info)
9 .master_edition(Some(master_edition_info))
10 .mint(mint_info)
11 .payer(payer_info)
12 .authority(update_authority_info)
13 .system_program(system_program_info)
14 .sysvar_instructions(sysvar_instructions_info)
15 .spl_token_program(spl_token_program_info)
16 .spl_ata_program(spl_ata_program_info)
17 .amount(1);
18
19mint_cpi.invoke();
NonFungible을 민팅하는 데 필요하므로 master_edition을 설정하고 있습니다; token 계정이 존재하지 않고 하나가 초기화될 경우 token_owner가 필요합니다.
생성 헬퍼
디지털 자산 생성이 Token Metadata의 중요한 부분이므로, 우리의 SDK는 프로세스를 더 쉽게 만들기 위한 헬퍼 메서드를 제공합니다. 즉, 이러한 헬퍼 메서드는 생성하려는 토큰 표준에 따라 Create V1과 Mint V1 명령어를 다양한 방식으로 결합합니다.
생성 헬퍼
