명령어
명령어는 솔라나 블록체인과 상호작용하기 위한 기본 구성 요소입니다. 명령어는 본질적으로 솔라나 네트워크를 사용하는 모든 사람이 호출할 수 있는 공개 함수입니다. 각 명령어는 특정 작업을 수행하는 데 사용됩니다. 명령어의 실행 로직은 프로그램에 저장되며, 각 프로그램은 자체적인 명령어 세트를 정의합니다. 솔라나 네트워크와 상호작용하려면 하나 이상의 명령어를 트랜잭션에 추가하여 처리를 위해 네트워크로 전송합니다.
SOL 전송 예제
아래 다이어그램은 트랜잭션과 명령어가 함께 작동하여 사용자가 네트워크와 상호작용할 수 있게 하는 방법을 보여줍니다. 이 예제에서는 SOL이 한 계정에서 다른 계정으로 전송됩니다.
송신자 계정의 메타데이터는 트랜잭션에 서명해야 함을 나타냅니다. (이를 통해 시스템 프로그램이 lamport를 차감할 수 있습니다.) 송신자와 수신자 계정 모두 lamport 잔액을 변경하기 위해 쓰기 가능해야 합니다. 이 명령어를 실행하기 위해 송신자의 지갑은 서명과 SOL 전송 명령어가 포함된 메시지가 담긴 트랜잭션을 전송합니다.
SOL 전송 다이어그램
트랜잭션이 전송된 후, 시스템 프로그램은 전송 명령어를 처리하고 두 계정의 lamport 잔액을 업데이트합니다.
SOL 전송 처리 다이어그램
아래 예제는 위 다이어그램과 관련된 코드를 보여줍니다. (시스템 프로그램의 전송 명령어를 참조하세요.)
import {airdropFactory,appendTransactionMessageInstructions,createSolanaRpc,createSolanaRpcSubscriptions,createTransactionMessage,generateKeyPairSigner,getSignatureFromTransaction,lamports,pipe,sendAndConfirmTransactionFactory,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,signTransactionMessageWithSigners} from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";// Create a connection to clusterconst rpc = createSolanaRpc("http://localhost:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");// Generate sender and recipient keypairsconst sender = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();const LAMPORTS_PER_SOL = 1_000_000_000n;const transferAmount = lamports(LAMPORTS_PER_SOL / 100n); // 0.01 SOL// Fund sender with airdropawait airdropFactory({ rpc, rpcSubscriptions })({recipientAddress: sender.address,lamports: lamports(LAMPORTS_PER_SOL), // 1 SOLcommitment: "confirmed"});// Check balance before transferconst { value: preBalance1 } = await rpc.getBalance(sender.address).send();const { value: preBalance2 } = await rpc.getBalance(recipient.address).send();// Create a transfer instruction for transferring SOL from sender to recipientconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount // 0.01 SOL in lamports});// Add the transfer instruction to a new transactionconst { value: latestBlockhash } = await rpc.getLatestBlockhash().send();const transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(sender, tx),(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions([transferInstruction], tx));// Send the transaction to the networkconst signedTransaction =await signTransactionMessageWithSigners(transactionMessage);await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction,{ commitment: "confirmed" });const transactionSignature = getSignatureFromTransaction(signedTransaction);// Check balance after transferconst { value: postBalance1 } = await rpc.getBalance(sender.address).send();const { value: postBalance2 } = await rpc.getBalance(recipient.address).send();console.log("Sender prebalance:",Number(preBalance1) / Number(LAMPORTS_PER_SOL));console.log("Recipient prebalance:",Number(preBalance2) / Number(LAMPORTS_PER_SOL));console.log("Sender postbalance:",Number(postBalance1) / Number(LAMPORTS_PER_SOL));console.log("Recipient postbalance:",Number(postBalance2) / Number(LAMPORTS_PER_SOL));console.log("Transaction Signature:", transactionSignature);
Console
Click to execute the code.
명령어
3개 구성 요소로 나뉜 명령어가 포함된 트랜잭션을 보여주는 다이어그램
Instruction
는
다음 정보로 구성됩니다:
Instruction struct
pub struct Instruction {/// Pubkey of the program that executes this instruction.pub program_id: Pubkey,/// Metadata describing accounts that should be passed to the program.pub accounts: Vec<AccountMeta>,/// Opaque data passed to the program for its own interpretation.pub data: Vec<u8>,}
프로그램 ID
명령어의 program_id
는 명령어의
비즈니스 로직을 포함하는 프로그램의 공개 키 주소입니다.
계정 메타데이터
명령어의 accounts
배열은
AccountMeta
구조체의 배열입니다. 명령어가 상호작용하는 각 계정에 대한 메타데이터를 제공해야
합니다. (이를 통해 트랜잭션은 동일한 계정을 수정하지 않는 한 명령어를 병렬로
실행할 수 있습니다.)
아래 다이어그램은 단일 명령어를 포함하는 트랜잭션을 보여줍니다. 명령어의
accounts
배열에는 두 계정에 대한 메타데이터가 포함되어 있습니다.
하나의 명령어가 있는 트랜잭션. 명령어는 accounts 배열에 두 개의 AccountMeta 구조체를 포함합니다.
계정 메타데이터에는 다음 정보가 포함됩니다:
- pubkey: 계정의 공개 키 주소
- is_signer: 계정이 트랜잭션에 서명해야 하는 경우
true
로 설정 - is_writable: 명령어가 계정의 데이터를 수정하는 경우
true
로 설정
명령어가 어떤 계정을 필요로 하는지, 그리고 어떤 계정이 쓰기 가능, 읽기 전용이어야 하는지, 또는 트랜잭션에 서명해야 하는지 알기 위해서는 프로그램에 정의된 명령어의 구현을 참조해야 합니다.
AccountMeta
pub struct AccountMeta {/// An account's public key.pub pubkey: Pubkey,/// True if an `Instruction` requires a `Transaction` signature matching `pubkey`.pub is_signer: bool,/// True if the account data or metadata may be mutated during program execution.pub is_writable: bool,}
데이터
명령어의 data
는 프로그램의 어떤 명령어를 호출할지 지정하는 바이트 배열입니다.
또한 명령어에 필요한 인수도 포함합니다.
명령어 생성 예제
아래 예제는 SOL 전송 명령어의 구조를 보여줍니다.
import { generateKeyPairSigner, lamports } from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";// Generate sender and recipient keypairsconst sender = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();// Define the amount to transferconst LAMPORTS_PER_SOL = 1_000_000_000n;const transferAmount = lamports(LAMPORTS_PER_SOL / 100n); // 0.01 SOL// Create a transfer instruction for transferring SOL from sender to recipientconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount});console.log(JSON.stringify(transferInstruction, null, 2));
Console
Click to execute the code.
아래 코드는 이전 코드 스니펫의 출력을 보여줍니다. SDK에 따라 형식이 다를 수
있지만, 각 명령에는 동일한 세 가지 필수 정보가 포함되어 있습니다:
program_id
, accounts
,
data
.
{"accounts": [{"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC","role": 3,"signer": {"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC","keyPair": {"privateKey": {},"publicKey": {}}}},{"address": "2mBY6CTgeyJNJDzo6d2Umipw2aGUquUA7hLdFttNEj7p","role": 1}],"programAddress": "11111111111111111111111111111111","data": {"0": 2,"1": 0,"2": 0,"3": 0,"4": 128,"5": 150,"6": 152,"7": 0,"8": 0,"9": 0,"10": 0,"11": 0}}
아래 예제는 전송 명령을 수동으로 구축하는 방법을 보여줍니다.
(Expanded Instruction
탭은 기능적으로 Instruction
탭과 동일합니다.)
실제로는 보통 Instruction
를 수동으로 구성할 필요가 없습니다. 대부분의
프로그램은 명령을 생성하는 헬퍼 함수가 있는 클라이언트 라이브러리를
제공합니다. 라이브러리를 사용할 수 없는 경우 수동으로 명령을 구축할 수
있습니다.
const transferAmount = 0.01; // 0.01 SOLconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount * LAMPORTS_PER_SOL});
Is this page helpful?