Zusammenfassung
Program Accounts enthalten ausführbaren sBPF-Code. Data Accounts speichern Zustand, der von Programmen verwaltet wird. System Accounts gehören dem System Program. Sysvars bieten clusterweiten Zustand, der über vordefinierte Adressen zugänglich ist.
Das Feld executable bestimmt die
Kategorie eines Konten:
- Program Accounts:
executable=true. Enthält ausführbaren Code. - Data Accounts:
executable=false. Speichert Zustand oder Benutzerdaten.
Diese Trennung von Code und veränderbarem Zustand bedeutet, dass ein Programm einmal deployed wird und beliebig viele Data Accounts verwalten kann.
Program Accounts
Ein Program Account speichert ausführbaren Code. Jeder Program Account gehört einem Loader-Programm. Wenn ein Programm deployed wird, erstellt die Runtime einen Program Account, um dessen Bytecode zu speichern.
Diagramm eines Program Account, seiner 4 Komponenten und seines Loader-Programms.
Program Data Accounts
Programme, die mit loader-v3 deployed wurden (siehe
Loader-Programme),
speichern ausführbaren Bytecode nicht in ihrem eigenen data-Feld. Stattdessen
verweist ihr data auf einen separaten Program Data Account, der den
Programmcode enthält. (Siehe Diagramm unten.)
Ein Program Account mit Daten. Die Daten verweisen auf einen separaten Program Data Account
Während des Programm-Deployments oder bei Upgrades werden Buffer-Accounts verwendet, um den Upload temporär bereitzustellen.
Das folgende Beispiel ruft den Token Program Account ab. Das Feld executable
ist true, was bestätigt, dass es sich um einen Program Account handelt.
import { Address, createSolanaRpc } from "@solana/kit";const rpc = createSolanaRpc("https://api.mainnet.solana.com");const programId = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" as Address;const accountInfo = await rpc.getAccountInfo(programId, { encoding: "base64" }).send();console.log(accountInfo);
Datenkonten
Datenkonten enthalten keinen ausführbaren Code. Sie speichern programmdefinierte Zustände.
Programmzustandskonto
Programme speichern ihren Zustand in Datenkonten. Das Erstellen eines Programmzustandskontos umfasst zwei Schritte:
- Rufen Sie das System Program auf, um das Konto zu erstellen. Das System Program überträgt die Eigentümerschaft an das angegebene Programm.
- Das besitzende Programm initialisiert das
data-Feld des Kontos gemäß seinen Anweisungen.
Diagramm eines Datenkontos, das einem Programmkonto gehört
Das folgende Beispiel erstellt und ruft ein Token-Mint-Konto ab, das dem Token 2022-Programm gehört.
import {airdropFactory,appendTransactionMessageInstructions,createSolanaRpc,createSolanaRpcSubscriptions,createTransactionMessage,generateKeyPairSigner,getSignatureFromTransaction,lamports,pipe,sendAndConfirmTransactionFactory,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,signTransactionMessageWithSigners} from "@solana/kit";import { getCreateAccountInstruction } from "@solana-program/system";import {getInitializeMintInstruction,getMintSize,TOKEN_2022_PROGRAM_ADDRESS,fetchMint} from "@solana-program/token-2022";// Create Connection, local validator in this exampleconst rpc = createSolanaRpc("http://localhost:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");// Generate keypairs for fee payerconst feePayer = await generateKeyPairSigner();// Fund fee payerawait airdropFactory({ rpc, rpcSubscriptions })({recipientAddress: feePayer.address,lamports: lamports(1_000_000_000n),commitment: "confirmed"});// Generate keypair to use as address of mintconst mint = await generateKeyPairSigner();// Get default mint account size (in bytes), no extensions enabledconst space = BigInt(getMintSize());// Get minimum balance for rent exemptionconst rent = await rpc.getMinimumBalanceForRentExemption(space).send();// Instruction to create new account for mint (token 2022 program)// Invokes the system programconst createAccountInstruction = getCreateAccountInstruction({payer: feePayer,newAccount: mint,lamports: rent,space,programAddress: TOKEN_2022_PROGRAM_ADDRESS});// Instruction to initialize mint account data// Invokes the token 2022 programconst initializeMintInstruction = getInitializeMintInstruction({mint: mint.address,decimals: 9,mintAuthority: feePayer.address});const instructions = [createAccountInstruction, initializeMintInstruction];// Get latest blockhash to include in transactionconst { value: latestBlockhash } = await rpc.getLatestBlockhash().send();// Create transaction messageconst transactionMessage = pipe(createTransactionMessage({ version: 0 }), // Create transaction message(tx) => setTransactionMessageFeePayerSigner(feePayer, tx), // Set fee payer(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), // Set transaction blockhash(tx) => appendTransactionMessageInstructions(instructions, tx) // Append instructions);// Sign transaction message with required signers (fee payer and mint keypair)const signedTransaction =await signTransactionMessageWithSigners(transactionMessage);// Send and confirm transactionawait sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction,{ commitment: "confirmed" });// Get transaction signatureconst transactionSignature = getSignatureFromTransaction(signedTransaction);console.log("Mint Address:", mint.address);console.log("Transaction Signature:", transactionSignature);const accountInfo = await rpc.getAccountInfo(mint.address).send();console.log(accountInfo);const mintAccount = await fetchMint(rpc, mint.address);console.log(mintAccount);
Systemkonten
Konten, die nach der Erstellung im Besitz des System Program bleiben, werden als Systemkonten bezeichnet. Das erstmalige Senden von SOL an eine neue Adresse erstellt ein neues Konto unter dieser Adresse, das dem System Program gehört.
Alle Wallet-Konten sind Systemkonten. Der Fee-Zahler einer Transaktion muss ein Systemkonto sein, da nur Konten im Besitz des System Program Transaktionsgebühren zahlen können.
Ein Wallet im Besitz des System Program mit 1.000.000 Lamports
Das folgende Beispiel generiert ein neues Keypair, finanziert es mit SOL und
ruft das Konto ab. Das owner-Feld ist 11111111111111111111111111111111 (das
System Program).
import {airdropFactory,createSolanaRpc,createSolanaRpcSubscriptions,generateKeyPairSigner,lamports} from "@solana/kit";// Create a connection to Solana clusterconst rpc = createSolanaRpc("http://localhost:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");// Generate a new keypairconst keypair = await generateKeyPairSigner();console.log(`Public Key: ${keypair.address}`);// Funding an address with SOL automatically creates an accountconst signature = await airdropFactory({ rpc, rpcSubscriptions })({recipientAddress: keypair.address,lamports: lamports(1_000_000_000n),commitment: "confirmed"});const accountInfo = await rpc.getAccountInfo(keypair.address).send();console.log(accountInfo);
Sysvar-Konten
Sysvar-Konten sind spezielle Konten mit vordefinierten Adressen, die schreibgeschützten Zugriff auf Cluster-Zustandsdaten ermöglichen. Sie werden dynamisch in jedem Slot aktualisiert.
| Sysvar | Adresse | Zweck |
|---|---|---|
| Clock | SysvarC1ock11111111111111111111111111111111 | Aktueller Slot, Epoch und Unix-Zeitstempel |
| EpochSchedule | SysvarEpochSchedu1e111111111111111111111111 | Epoch-Planungskonstanten, die in Genesis festgelegt wurden |
| EpochRewards | SysvarEpochRewards1111111111111111111111111 | Status und Fortschritt der Epoch-Belohnungsverteilung |
| Rent | SysvarRent111111111111111111111111111111111 | Mietsatz und Befreiungsschwelle |
| SlotHashes | SysvarS1otHashes111111111111111111111111111 | Neueste Hashes der übergeordneten Banken des Slots |
| StakeHistory | SysvarStakeHistory1111111111111111111111111 | Stake-Aktivierungen und -Deaktivierungen pro Epoch |
| LastRestartSlot | SysvarLastRestartS1ot1111111111111111111111 | Letzter Cluster-Neustart-Slot |
| Instructions | Sysvar1nstructions1111111111111111111111111 | Serialisierte Anweisungen der aktuellen Transaktion |
| SlotHistory | SysvarS1otHistory11111111111111111111111111 | Aufzeichnung darüber, welche Slots in der letzten Epoch produziert wurden |
Das folgende Beispiel ruft das Sysvar-Clock-Konto ab und deserialisiert es.
import { createSolanaRpc } from "@solana/kit";import { fetchSysvarClock, SYSVAR_CLOCK_ADDRESS } from "@solana/sysvars";const rpc = createSolanaRpc("https://api.mainnet.solana.com");const accountInfo = await rpc.getAccountInfo(SYSVAR_CLOCK_ADDRESS, { encoding: "base64" }).send();console.log(accountInfo);// Automatically fetch and deserialize the account dataconst clock = await fetchSysvarClock(rpc);console.log(clock);
Is this page helpful?