アカウント

Solanaネットワーク上のすべてのデータはアカウントに保存されています。Solanaネットワークを単一のアカウントテーブルを持つ公開データベースと考えることができます。アカウントとそのアドレスの関係は、キーがアドレスで値がアカウントであるキーと値のペアに似ています。

各アカウントは同じ基本的な構造を持ち、そのアドレスを使用して見つけることができます。

3つのアカウントとそのアドレスの図。アカウント構造の定義を含む。3つのアカウントとそのアドレスの図。アカウント構造の定義を含む。

アカウントアドレス

アカウントのアドレスは、Solanaブロックチェーン上でアカウントを特定するための32バイトの一意のIDです。アカウントアドレスはよくbase58でエンコードされた文字列として表示されます。ほとんどのアカウントはアドレスとしてEd25519公開鍵を使用していますが、SolanaはProgram Derived Addressもサポートしているため、これは必須ではありません。

base58でエンコードされた公開鍵アドレスを持つアカウントbase58でエンコードされた公開鍵アドレスを持つアカウント

公開鍵

以下の例は、Solana SDKを使用してkeypairを作成する方法を示しています。Keypairには以下が含まれます:

  • アカウントアドレスとして機能する公開鍵
  • トランザクションの署名に使用される秘密鍵
import { generateKeyPairSigner } from "@solana/kit";
// Kit does not enable extractable private keys
const keypairSigner = await generateKeyPairSigner();
console.log(keypairSigner);
Console
Click to execute the code.

Program derived address

Program derived address(PDA)は、プログラムIDと1つ以上のオプション入力(シード)を使用して決定論的に導出されるアドレスです。以下の例は、Solana SDKを使用してProgram derived addressを作成する方法を示しています。

import { Address, getProgramDerivedAddress } from "@solana/kit";
const programAddress = "11111111111111111111111111111111" as Address;
const seeds = ["helloWorld"];
const [pda, bump] = await getProgramDerivedAddress({
programAddress,
seeds
});
console.log(`PDA: ${pda}`);
console.log(`Bump: ${bump}`);
Console
Click to execute the code.

アカウント構造

すべてのAccountは最大サイズが10MiBで、以下の情報を含んでいます:

  • lamports: アカウント内のlamportの数
  • data: アカウントのデータ
  • owner: アカウントを所有するプログラムのID
  • executable: アカウントが実行可能なバイナリを含むかどうかを示す
  • rent_epoch: 非推奨のrent epochフィールド
Account
pub struct Account {
/// lamports in the account
pub lamports: u64,
/// data held in this account
#[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
pub data: Vec<u8>,
/// the program that owns this account. If executable, the program that loads this account.
pub owner: Pubkey,
/// this account's data contains a loaded program (and is now read-only)
pub executable: bool,
/// the epoch at which this account will next owe rent
pub rent_epoch: Epoch,
}

Lamports

アカウントの残高(lamport単位)。

すべてのアカウントは、rentと呼ばれる最小限のlamport残高を持つ必要があります。これによりデータをオンチェーンに保存できます。rentはアカウントのサイズに比例します。

この残高はrentと呼ばれていますが、アカウントが閉鎖されると全額が回収できるため、実際にはデポジットのように機能します。(「rent」という名前は、現在は非推奨となったrent epochフィールドに由来しています。)

最小残高の計算式と適用される定数を参照してください。)

データ

このフィールドは一般的に「アカウントデータ」と呼ばれています。このフィールドのdataは任意のバイト列を含むことができるため、任意と見なされます。各プログラムがこのフィールドに格納されるデータの構造を定義します。

  • program account: このフィールドには、実行可能なプログラムコードか、実行可能なプログラムコードを格納するプログラムデータアカウントのアドレスが含まれます。
  • データアカウント: このフィールドには一般的に、読み取り用の状態データが格納されます。

Solanaアカウントからデータを読み取るには、次の2つのステップが必要です:

  1. アドレスを使用してアカウントを取得する
  2. アカウントのdataフィールドを、アカウントを所有するプログラムによって定義された適切なデータ構造に、生のバイトからデシリアライズする

所有者

このフィールドには、アカウントの所有者のプログラムIDが含まれています。

すべてのSolanaアカウントには、所有者として指定されたプログラムがあります。アカウントの所有者は、プログラムの指示に従って、アカウントのdataを変更したりlamportsを差し引いたりできる唯一のプログラムです。

(program accountの場合、所有者はそのローダープログラムです。)

実行可能

このフィールドは、アカウントがprogram accountデータアカウントかを示します

  • trueの場合:アカウントはprogram accountです
  • falseの場合:アカウントはデータアカウントです

rentエポック

rent_epochフィールドは非推奨です。

過去には、このフィールドはアカウントがrentを支払う必要がある時期を追跡していました。しかし、このrent徴収メカニズムはその後非推奨となりました。

Lamports

アカウントの残高(lamport単位)。

すべてのアカウントは、rentと呼ばれる最小限のlamport残高を持つ必要があります。これによりデータをオンチェーンに保存できます。rentはアカウントのサイズに比例します。

この残高はrentと呼ばれていますが、アカウントが閉鎖されると全額が回収できるため、実際にはデポジットのように機能します。(「rent」という名前は、現在は非推奨となったrent epochフィールドに由来しています。)

最小残高の計算式と適用される定数を参照してください。)

データ

このフィールドは一般的に「アカウントデータ」と呼ばれています。このフィールドのdataは任意のバイト列を含むことができるため、任意と見なされます。各プログラムがこのフィールドに格納されるデータの構造を定義します。

  • program account: このフィールドには、実行可能なプログラムコードか、実行可能なプログラムコードを格納するプログラムデータアカウントのアドレスが含まれます。
  • データアカウント: このフィールドには一般的に、読み取り用の状態データが格納されます。

Solanaアカウントからデータを読み取るには、次の2つのステップが必要です:

  1. アドレスを使用してアカウントを取得する
  2. アカウントのdataフィールドを、アカウントを所有するプログラムによって定義された適切なデータ構造に、生のバイトからデシリアライズする

所有者

このフィールドには、アカウントの所有者のプログラムIDが含まれています。

すべてのSolanaアカウントには、所有者として指定されたプログラムがあります。アカウントの所有者は、プログラムの指示に従って、アカウントのdataを変更したりlamportsを差し引いたりできる唯一のプログラムです。

(program accountの場合、所有者はそのローダープログラムです。)

実行可能

このフィールドは、アカウントがprogram accountデータアカウントかを示します

  • trueの場合:アカウントはprogram accountです
  • falseの場合:アカウントはデータアカウントです

rentエポック

rent_epochフィールドは非推奨です。

過去には、このフィールドはアカウントがrentを支払う必要がある時期を追跡していました。しかし、このrent徴収メカニズムはその後非推奨となりました。

Account Examples
// Example Token Mint Account
Account {
lamports: 1461600,
data.len: 82,
owner: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb,
executable: false,
rent_epoch: 0,
data: 010000001e213c90625a7e643d9555bb01b6c3fe6416d7afd523ce8c7ddd9b923ceafb9d00000000000000000901010000001e213c90625a7e643d9555bb01b6,
}
// Example Token Program Account
Account {
lamports: 4513200894,
data.len: 134080,
owner: BPFLoader2111111111111111111111111111111111,
executable: true,
rent_epoch: 18446744073709551615,
data: 7f454c460201010000000000000000000300f70001000000d8f90000000000004000000000000000800902000000000000000000400038000400400009000800,
}

アカウントの種類

アカウントは基本的に次の2つのカテゴリに分類されます:

プログラムのコードとその状態を分離することは、Solanaのアカウントモデルの重要な特徴です。(オペレーティングシステムと同様に、通常はプログラムとそのデータに対して別々のファイルを持ちます。)

プログラムアカウント

すべてのプログラムはローダープログラムによって所有され、これはアカウントのデプロイと管理に使用されます。新しいプログラムがデプロイされると、その実行可能コードを格納するためのアカウントが作成されます。これをプログラムアカウントと呼びます。(簡単に言えば、プログラムアカウントをプログラム自体と考えることができます。)

以下の図では、ローダープログラムがプログラムアカウントをデプロイするために使用されているのがわかります。プログラムアカウントのdataには実行可能なプログラムコードが含まれています。

プログラムアカウント、その4つのコンポーネント、およびそのローダープログラムの図プログラムアカウント、その4つのコンポーネント、およびそのローダープログラムの図

プログラムデータアカウント

loader-v3を使用してデプロイされたプログラムは、そのdataフィールドにプログラムコードを含みません。代わりに、そのdataは、プログラムコードを含む別のプログラムデータアカウントを指します。(以下の図を参照してください。)

データを持つプログラムアカウント。データは別のプログラムデータアカウントを指していますデータを持つプログラムアカウント。データは別のプログラムデータアカウントを指しています

プログラムのデプロイやアップグレード中、バッファアカウントはアップロードを一時的にステージングするために使用されます。

以下の例ではToken Programアカウントを取得しています。executableフィールドがtrueに設定されていることに注目してください。これはアカウントがプログラムであることを示しています。

import { Address, createSolanaRpc } from "@solana/kit";
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const programId = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" as Address;
const accountInfo = await rpc
.getAccountInfo(programId, { encoding: "base64" })
.send();
console.log(accountInfo);
Console
Click to execute the code.

データアカウント

データアカウントは実行可能なコードを含みません。代わりに、情報を保存します。

プログラム状態アカウント

プログラムはデータアカウントを使用して状態を維持します。そのためには、まず新しいデータアカウントを作成する必要があります。プログラム状態アカウントの作成プロセスは多くの場合抽象化されていますが、基本的なプロセスを理解することは役立ちます。

状態を管理するために、新しいプログラムは以下を行う必要があります:

  1. System Programを呼び出してアカウントを作成します。(System Programはその後、所有権を新しいプログラムに転送します。)
  2. instructionsで定義されているように、アカウントデータを初期化します。

プログラムアカウントが所有するデータアカウントの図プログラムアカウントが所有するデータアカウントの図

以下の例では、Token 2022プログラムが所有するToken Mintアカウントを作成して取得します。

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 example
const rpc = createSolanaRpc("http://localhost:8899");
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");
// Generate keypairs for fee payer
const feePayer = await generateKeyPairSigner();
// Fund fee payer
await airdropFactory({ rpc, rpcSubscriptions })({
recipientAddress: feePayer.address,
lamports: lamports(1_000_000_000n),
commitment: "confirmed"
});
// Generate keypair to use as address of mint
const mint = await generateKeyPairSigner();
// Get default mint account size (in bytes), no extensions enabled
const space = BigInt(getMintSize());
// Get minimum balance for rent exemption
const rent = await rpc.getMinimumBalanceForRentExemption(space).send();
// Instruction to create new account for mint (token 2022 program)
// Invokes the system program
const createAccountInstruction = getCreateAccountInstruction({
payer: feePayer,
newAccount: mint,
lamports: rent,
space,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
});
// Instruction to initialize mint account data
// Invokes the token 2022 program
const initializeMintInstruction = getInitializeMintInstruction({
mint: mint.address,
decimals: 9,
mintAuthority: feePayer.address
});
const instructions = [createAccountInstruction, initializeMintInstruction];
// Get latest blockhash to include in transaction
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
// Create transaction message
const 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 transaction
await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(
signedTransaction,
{ commitment: "confirmed" }
);
// Get transaction signature
const 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);
Console
Click to execute the code.

システムアカウント

System Programによって作成されたすべてのアカウントが、作成後に新しい所有者に割り当てられるわけではありません。System Programが所有するアカウントはシステムアカウントと呼ばれます。すべてのウォレットアカウントはシステムアカウントであり、取引手数料を支払うことができます。

System Programが所有する1,000,000 lamportsを含むウォレットSystem Programが所有する1,000,000 lamportsを含むウォレット

SOLが初めて新しいアドレスに送信されると、そのアドレスにSystem Programが所有するアカウントが作成されます。

以下の例では、新しいkeypairが生成され、SOLで資金提供されます。コードを実行した後、アカウントのownerのアドレスが11111111111111111111111111111111System Program)であることがわかります。

import {
airdropFactory,
createSolanaRpc,
createSolanaRpcSubscriptions,
generateKeyPairSigner,
lamports
} from "@solana/kit";
// Create a connection to Solana cluster
const rpc = createSolanaRpc("http://localhost:8899");
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");
// Generate a new keypair
const keypair = await generateKeyPairSigner();
console.log(`Public Key: ${keypair.address}`);
// Funding an address with SOL automatically creates an account
const 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);
Console
Click to execute the code.

Sysvarアカウント

Sysvarアカウントは事前に定義されたアドレスに存在し、クラスターの状態データへのアクセスを提供します。これらはネットワーククラスターに関するデータで動的に更新されます。Sysvarアカウントの完全なリストをご覧ください。

以下の例では、Sysvar Clockアカウントからデータを取得し、デシリアライズします。

import { createSolanaRpc } from "@solana/kit";
import { fetchSysvarClock, SYSVAR_CLOCK_ADDRESS } from "@solana/sysvars";
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const accountInfo = await rpc
.getAccountInfo(SYSVAR_CLOCK_ADDRESS, { encoding: "base64" })
.send();
console.log(accountInfo);
// Automatically fetch and deserialize the account data
const clock = await fetchSysvarClock(rpc);
console.log(clock);
Console
Click to execute the code.

Is this page helpful?

管理運営

© 2025 Solana Foundation.
無断転載を禁じます。