이전 섹션에서는 계정을 가져와 Solana 네트워크에서 데이터를 읽는 방법을 배웠습니다. Solana 네트워크에 데이터를 쓰려면 트랜잭션이 필요합니다. 트랜잭션에는 하나 이상의 명령어가 포함되며, 각 명령어는 프로그램을 호출합니다.
프로그램은 각 명령어의 비즈니스 로직을 정의합니다. 트랜잭션을 전송하면 Solana 런타임이 트랜잭션의 명령어를 순서대로 실행합니다. 트랜잭션은 원자적입니다. 트랜잭션 내의 모든 명령어가 성공하거나, 전체 트랜잭션이 실패합니다.
이 섹션의 예제에서는 다음을 수행하는 방법을 보여줍니다:
- 계정 간 SOL 전송
- 새 토큰 민트 생성
SOL 전송
아래 예제는 한 계정에서 다른 계정으로 SOL을 전송합니다. 계정의 소유자로 지정된 프로그램만 계정의 데이터를 수정하거나 잔액에서 lamport를 차감할 수 있습니다. 지갑 계정은 System Program이 소유하므로, 지갑 계정 간 SOL 전송에는 System Program의 transfer 명령어를 호출하는 명령어가 필요합니다. 소스 계정도 트랜잭션에 서명해야 합니다.
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";import { getTransferSolInstruction } from "@solana-program/system";const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));const receiver = await generateKeyPairSigner();const transferInstruction = getTransferSolInstruction({source: client.payer,destination: receiver.address,amount: lamports(10_000_000n)});const result = await client.sendTransaction([transferInstruction]);console.log("Transaction Signature:", result.context.signature);const { value: senderBalance } = await client.rpc.getBalance(client.payer.address).send();const { value: receiverBalance } = await client.rpc.getBalance(receiver.address).send();console.log("Sender Balance:", senderBalance);console.log("Receiver Balance:", receiverBalance);
로컬 테스트 validator용 Kit 클라이언트를 생성합니다. 이 코드 스니펫은 지불자 서명자를 추가하고, 로컬 RPC 엔드포인트에 연결하고, 에어드랍을 활성화하고, 전송을 위한 테스트 SOL로 지불자에게 자금을 공급합니다.
const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));
수신자를 위한 서명자를 생성합니다. 송신자는 client.payer이며, 이는
generatedPayer()에 의해 생성되고 airdropPayer()에 의해 자금이
공급되었습니다.
const receiver = await generateKeyPairSigner();
getTransferSolInstruction() 헬퍼는 System Program 명령어를 생성합니다. 이
명령어는 source 서명자에서
destination 주소로 지정된 amount
lamport만큼 SOL을 전송합니다.
const transferInstruction = getTransferSolInstruction({source: client.payer,destination: receiver.address,amount: lamports(10_000_000n)});
명령어 배열과 함께 client.sendTransaction()를 호출합니다. Kit 클라이언트는
명령어들을 하나의 트랜잭션으로 구성하고, 명령어에 연결된 서명자로 서명한 후,
트랜잭션을 전송하고 확인을 기다립니다.
const result = await client.sendTransaction([transferInstruction]);console.log("Transaction Signature:", result.context.signature);
트랜잭션이 확인된 후, client.rpc를 사용하여 두 잔액을 모두 가져옵니다.
const { value: senderBalance } = await client.rpc.getBalance(client.payer.address).send();const { value: receiverBalance } = await client.rpc.getBalance(receiver.address).send();
토큰 생성
아래 예제는 Token Extensions Program을 사용하여 새로운 토큰 mint를 생성합니다. mint account는 소수점 자릿수, 공급량, mint 권한 및 동결 권한과 같은 토큰의 전역 설정을 정의하는 계정입니다.
mint account를 생성하려면 두 가지 명령어가 필요합니다:
- System Program을 호출하여 Token Extensions Program이 소유하는 새 계정을 생성합니다.
- Token Extensions Program을 호출하여 해당 계정을 mint로 초기화합니다.
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";import { getCreateAccountInstruction } from "@solana-program/system";import {fetchMint,getInitializeMintInstruction,getMintSize,TOKEN_2022_PROGRAM_ADDRESS} from "@solana-program/token-2022";const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));const mint = await generateKeyPairSigner();const space = BigInt(getMintSize());const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();const createAccountInstruction = getCreateAccountInstruction({payer: client.payer,newAccount: mint,space,lamports: rent,programAddress: TOKEN_2022_PROGRAM_ADDRESS});const initializeMintInstruction = getInitializeMintInstruction({mint: mint.address,decimals: 2,mintAuthority: client.payer.address,freezeAuthority: client.payer.address,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS});const result = await client.sendTransaction([createAccountInstruction,initializeMintInstruction]);console.log("Mint Address:", mint.address);console.log("Transaction Signature:", result.context.signature);const mintAccount = await fetchMint(client.rpc, mint.address);console.log("Mint Account:", mintAccount);
Kit 클라이언트를 생성하고 자금을 지원한 다음, 새 mint account의 주소로 사용할 서명자를 생성합니다. 클라이언트 페이어는 계정 생성 비용을 지불하고 트랜잭션 수수료를 납부합니다.
const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));const mint = await generateKeyPairSigner();
mint account 크기를 바이트 단위로 계산한 후, 해당 데이터를 계정에 저장하는 데 필요한 lamport를 계산하기 위해 RPC 요청을 보냅니다. 이 필수 잔액을 rent라고 합니다.
const space = BigInt(getMintSize());const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();
첫 번째 명령어는 System Program을 호출합니다. 이 명령어는
payer를 사용하여 newAccount에 자금을
지원하고, mint account space를 할당하며, rent 면제
lamports를 전송하고, Token Extensions Program에 소유권을
programAddress로 할당합니다.
const createAccountInstruction = getCreateAccountInstruction({payer: client.payer,newAccount: mint,space,lamports: rent,programAddress: TOKEN_2022_PROGRAM_ADDRESS});
두 번째 명령어는 Token Extensions Program을 호출합니다. 이 명령어는
mint 주소를 decimals 값,
mintAuthority,
freezeAuthority로 초기화하고, mint account를
소유하는 tokenProgram을 지정합니다.
const initializeMintInstruction = getInitializeMintInstruction({mint: mint.address,decimals: 2,mintAuthority: client.payer.address,freezeAuthority: client.payer.address,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS});
두 명령어를 하나의 트랜잭션으로 전송합니다. 계정 생성 명령어는 민트 초기화 명령어보다 먼저 와야 합니다. Token Extensions Program이 계정에 민트 데이터를 기록하려면 mint account가 먼저 존재해야 하기 때문입니다.
const result = await client.sendTransaction([createAccountInstruction,initializeMintInstruction]);
트랜잭션이 확인된 후 mint account를 가져옵니다.
const mintAccount = await fetchMint(client.rpc, mint.address);console.log("Mint Account:", mintAccount);
Is this page helpful?