Accounts
システムアカウントの作り方
System Programが所有するアカウントを作成します。Solanaランタイムは、アカウントの所有者に、そのデータへの書き込みアクセスまたはランポートの転送アクセスを許可します。 アカウントを作成するとき、固定バイトストレージ (space
) と、家賃をカバーするのに十分なランポートを事前に割り当てる必要があります Rentは、Solana でアカウントを維持するために発生する費用です
import {
SystemProgram,
Keypair,
Transaction,
sendAndConfirmTransaction,
Connection,
clusterApiUrl,
LAMPORTS_PER_SOL,
} from "@solana/web3.js";
(async () => {
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
const fromPubkey = Keypair.generate();
// Airdrop SOL for transferring lamports to the created account
const airdropSignature = await connection.requestAirdrop(
fromPubkey.publicKey,
LAMPORTS_PER_SOL
);
await connection.confirmTransaction(airdropSignature);
// amount of space to reserve for the account
const space = 0;
// Seed the created account with lamports for rent exemption
const rentExemptionAmount =
await connection.getMinimumBalanceForRentExemption(space);
const newAccountPubkey = Keypair.generate();
const createAccountParams = {
fromPubkey: fromPubkey.publicKey,
newAccountPubkey: newAccountPubkey.publicKey,
lamports: rentExemptionAmount,
space,
programId: SystemProgram.programId,
};
const createAccountTransaction = new Transaction().add(
SystemProgram.createAccount(createAccountParams)
);
await sendAndConfirmTransaction(connection, createAccountTransaction, [
fromPubkey,
newAccountPubkey,
]);
})();
const createAccountParams = {
fromPubkey: fromPubkey.publicKey,
newAccountPubkey: newAccountPubkey.publicKey,
lamports: rentExemptionAmount,
space,
programId: SystemProgram.programId,
};
const createAccountTransaction = new Transaction().add(
SystemProgram.createAccount(createAccountParams)
);
await sendAndConfirmTransaction(connection, createAccountTransaction, [
fromPubkey,
newAccountPubkey,
]);
use solana_client::rpc_client::RpcClient;
use solana_program::system_instruction;
use solana_sdk::commitment_config::CommitmentConfig;
use solana_sdk::native_token::LAMPORTS_PER_SOL;
use solana_sdk::signature::{Keypair, Signer};
fn main() {
let rpc_url = String::from("https://api.devnet.solana.com");
let connection = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
let from_keypair = Keypair::new();
let from_pubkey = Signer::pubkey(&from_keypair);
match connection.request_airdrop(&from_pubkey, LAMPORTS_PER_SOL) {
Ok(sig) => loop {
if let Ok(confirmed) = connection.confirm_transaction(&sig) {
if confirmed {
println!("Transaction: {} Status: {}", sig, confirmed);
break;
}
}
},
Err(_) => println!("Error requesting airdrop"),
};
let space = 0;
let rent_exemption_amount = connection
.get_minimum_balance_for_rent_exemption(space)
.unwrap();
let new_account_keypair = Keypair::new();
let new_account_pubkey = Signer::pubkey(&new_account_keypair);
let create_account_ix = system_instruction::create_account(
&from_pubkey,
&new_account_pubkey,
rent_exemption_amount,
space as u64,
&from_pubkey,
);
let (recent_blockhash, _) = connection.get_recent_blockhash().unwrap();
let create_account_tx = solana_sdk::transaction::Transaction::new_signed_with_payer(
&[create_account_ix],
Some(&from_pubkey),
&[&from_keypair, &new_account_keypair],
recent_blockhash,
);
match connection.send_and_confirm_transaction(&create_account_tx) {
Ok(sig) => loop {
if let Ok(confirmed) = connection.confirm_transaction(&sig) {
if confirmed {
println!("Transaction: {} Status: {}", sig, confirmed);
break;
}
}
},
Err(_) => println!("Error creating system account"),
};
}
let create_account_ix = system_instruction::create_account(
&from_pubkey,
&new_account_pubkey,
rent_exemption_amount,
space as u64,
&from_pubkey,
);
let (recent_blockhash, _) = connection.get_recent_blockhash().unwrap();
let create_account_tx = solana_sdk::transaction::Transaction::new_signed_with_payer(
&[create_account_ix],
Some(&from_pubkey),
&[&from_keypair, &new_account_keypair],
recent_blockhash,
);
match connection.send_and_confirm_transaction(&create_account_tx) {
Ok(sig) => loop {
if let Ok(confirmed) = connection.confirm_transaction(&sig) {
if confirmed {
println!("Transaction: {} Status: {}", sig, confirmed);
break;
}
}
},
Err(_) => println!("Error creating system account"),
};
アカウント費用の計算方法
Solana でアカウントを維持すると、rentと呼ばれるストレージ コストが発生します。 口座は、少なくとも 2 年分のrentを入金することにより、rentの徴収を完全に免除することができます。 計算には、アカウントに保存する予定のデータの量を考慮が必要です。
import { Connection, clusterApiUrl } from "@solana/web3.js";
(async () => {
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// length of data in the account to calculate rent for
const dataLength = 1500;
const rentExemptionAmount =
await connection.getMinimumBalanceForRentExemption(dataLength);
console.log({
rentExemptionAmount,
});
})();
use solana_client::rpc_client::RpcClient;
use solana_sdk::commitment_config::CommitmentConfig;
fn main() {
let rpc_url = String::from("https://api.devnet.solana.com");
let connection = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
let data_length = 1500;
let rent_exemption_amount = connection
.get_minimum_balance_for_rent_exemption(data_length)
.unwrap();
println!("rent exemption amount: {}", rent_exemption_amount);
}
solana rent 1500
シード付きアカウントを作成する方法
さまざまなキーペアを作成する代わりに、createAccountWithSeed
を使用してアカウントを管理できます。
生成
import { PublicKey, SystemProgram } from "@solana/web3.js";
(async () => {
let basePubkey = new PublicKey(
"G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY"
);
let seed = "robot001";
let programId = SystemProgram.programId;
console.log(
`${(
await PublicKey.createWithSeed(basePubkey, seed, programId)
).toBase58()}`
);
})();
PublicKey.createWithSeed(basePubkey, seed, programId);
use solana_program::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, Signer};
fn main() {
let base_pubkey = Keypair::new().pubkey();
let seed = "robot001";
let program_id = solana_program::system_program::id();
let derived_pubkey = Pubkey::create_with_seed(&base_pubkey, seed, &program_id).unwrap();
println!("account pubkey: {:?}", derived_pubkey);
}
use solana_program::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, Signer};
fn main() {
let base_pubkey = Keypair::new().pubkey();
let seed = "robot001";
let program_id = solana_program::system_program::id();
let derived_pubkey = Pubkey::create_with_seed(&base_pubkey, seed, &program_id).unwrap();
println!("account pubkey: {:?}", derived_pubkey);
}
作成
import {
PublicKey,
SystemProgram,
Connection,
clusterApiUrl,
Transaction,
Keypair,
sendAndConfirmTransaction,
LAMPORTS_PER_SOL,
} from "@solana/web3.js";
import * as bs58 from "bs58";
(async () => {
// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
const feePayer = Keypair.fromSecretKey(
bs58.decode(
"588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
)
);
// G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
const base = Keypair.fromSecretKey(
bs58.decode(
"4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
)
);
let basePubkey = base.publicKey;
let seed = "robot001";
let programId = SystemProgram.programId;
let derived = await PublicKey.createWithSeed(basePubkey, seed, programId);
const tx = new Transaction().add(
SystemProgram.createAccountWithSeed({
fromPubkey: feePayer.publicKey, // funder
newAccountPubkey: derived,
basePubkey: basePubkey,
seed: seed,
lamports: 1e8, // 0.1 SOL
space: 0,
programId: programId,
})
);
console.log(
`txhash: ${await sendAndConfirmTransaction(connection, tx, [
feePayer,
base,
])}`
);
})();
const tx = new Transaction().add(
SystemProgram.createAccountWithSeed({
fromPubkey: feePayer.publicKey, // funder
newAccountPubkey: derived,
basePubkey: basePubkey,
seed: seed,
lamports: 1e8, // 0.1 SOL
space: 0,
programId: owner,
})
);
console.log(
`txhash: ${await sendAndConfirmTransaction(connection, tx, [feePayer, base])}`
);
use solana_client::rpc_client::RpcClient;
use solana_program::pubkey::Pubkey;
use solana_program::system_instruction;
use solana_sdk::commitment_config::CommitmentConfig;
use solana_sdk::native_token::LAMPORTS_PER_SOL;
use solana_sdk::signature::{Keypair, Signer};
fn main() {
let rpc_url = String::from("https://api.devnet.solana.com");
let connection = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
let fee_payer_keypair = Keypair::new();
let fee_payer_pubkey = Signer::pubkey(&fee_payer_keypair);
let base_keypair = Keypair::new();
let base_pubkey = Signer::pubkey(&base_keypair);
let seed = "robot001";
let program_id = solana_program::system_program::id();
let derived_pubkey = Pubkey::create_with_seed(&base_pubkey, seed, &program_id).unwrap();
match connection.request_airdrop(&fee_payer_pubkey, LAMPORTS_PER_SOL) {
Ok(sig) => loop {
if let Ok(confirmed) = connection.confirm_transaction(&sig) {
if confirmed {
println!("Transaction: {} Status: {}", sig, confirmed);
break;
}
}
},
Err(_) => println!("Error requesting airdrop"),
};
let ix = system_instruction::create_account_with_seed(
&fee_payer_pubkey,
&derived_pubkey,
&base_pubkey,
seed,
LAMPORTS_PER_SOL / 10,
0,
&program_id,
);
let (recent_blockhash, _) = connection.get_recent_blockhash().unwrap();
let tx = solana_sdk::transaction::Transaction::new_signed_with_payer(
&[ix],
Some(&fee_payer_pubkey),
&[&fee_payer_keypair, &base_keypair],
recent_blockhash,
);
match connection.send_and_confirm_transaction(&tx) {
Ok(sig) => loop {
if let Ok(confirmed) = connection.confirm_transaction(&sig) {
if confirmed {
println!("Transaction: {} Status: {}", sig, confirmed);
break;
}
}
},
Err(_) => println!("Error creating account with seed"),
};
}
let derived_pubkey = Pubkey::create_with_seed(&base_pubkey, seed, &program_id).unwrap();
let ix = system_instruction::create_account_with_seed(
&fee_payer_pubkey,
&derived_pubkey,
&base_pubkey,
seed,
LAMPORTS_PER_SOL / 10,
0,
&program_id,
);
let tx = solana_sdk::transaction::Transaction::new_signed_with_payer(
&[ix],
Some(&fee_payer_pubkey),
&[&fee_payer_keypair, &base_keypair],
recent_blockhash,
);
送信
import {
PublicKey,
SystemProgram,
Connection,
clusterApiUrl,
Transaction,
Keypair,
sendAndConfirmTransaction,
LAMPORTS_PER_SOL,
} from "@solana/web3.js";
import * as bs58 from "bs58";
(async () => {
// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
const feePayer = Keypair.fromSecretKey(
bs58.decode(
"588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
)
);
// G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
const base = Keypair.fromSecretKey(
bs58.decode(
"4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
)
);
let basePubkey = base.publicKey;
let seed = "robot001";
let programId = SystemProgram.programId;
let derived = await PublicKey.createWithSeed(basePubkey, seed, programId);
const tx = new Transaction().add(
SystemProgram.transfer({
fromPubkey: derived,
basePubkey: basePubkey,
toPubkey: Keypair.generate().publicKey, // create a random receiver
lamports: 0.01 * LAMPORTS_PER_SOL,
seed: seed,
programId: programId,
})
);
console.log(
`txhash: ${await sendAndConfirmTransaction(connection, tx, [
feePayer,
base,
])}`
);
})();
const tx = new Transaction().add(
SystemProgram.transfer({
fromPubkey: derived,
basePubkey: basePubkey,
toPubkey: Keypair.generate().publicKey, // create a random receiver
lamports: 0.01 * LAMPORTS_PER_SOL,
seed: seed,
programId: programId,
})
);
console.log(
`txhash: ${await sendAndConfirmTransaction(connection, tx, [feePayer, base])}`
);
TIP
システムプログラムが所有するアカウントのみ、システムプログラム経由で移行できます。
PDA の作成方法
Program derived address(PDA) は、通常のアドレスと似ていますが、次の違いがあります:
- ed25519 曲線上に存在しない(オフカーブである)
- 秘密鍵の代わりにプログラムを使用して署名する
Note: アカウントは、プログラムでのみ作成できます。アドレスはクライアント側で作成できます。
TIP
PDA はプログラム ID によって派生しますが、PDA が同じプログラムによって所有されているという意味ではありません。 (例を挙げると、トークン プログラムが所有するアカウントであるトークン アカウントとして PDA を初期化できます)
PDAの生成
findProgramAddress
は、シードの最後に余分なバイトを追加します。 255 から 0 まで開始し、オフカーブの最初の公開鍵を返します。 同じプログラム ID とシードを渡すと、常に同じ結果が得られます。
import { PublicKey } from "@solana/web3.js";
(async () => {
const programId = new PublicKey(
"G1DCNUQTSGHehwdLCAmRyAG8hf51eCHrLNUqkgGKYASj"
);
let [pda, bump] = await PublicKey.findProgramAddress(
[Buffer.from("test")],
programId
);
console.log(`bump: ${bump}, pubkey: ${pda.toBase58()}`);
// you will find the result is different from `createProgramAddress`.
// It is expected because the real seed we used to calculate is ["test" + bump]
})();
use solana_program::pubkey::Pubkey;
use std::str::FromStr;
fn main() {
let program_id = Pubkey::from_str("G1DCNUQTSGHehwdLCAmRyAG8hf51eCHrLNUqkgGKYASj").unwrap();
let (pda, bump_seed) = Pubkey::find_program_address(&[b"test"], &program_id);
println!("pda: {}, bump: {}", pda, bump_seed);
}
Create a PDA
以下は、プログラムが所有する PDA アカウントを作成するためのサンプル プログラムと、クライアントでプログラムを呼び出すためのサンプルです。
Program
以下は、単一の instruction system_instruction::create_account
を示しています。これは、割り当てられた space
, rent_lamports
の量のPDAを作成します。これは上記と同様に、invoke_signed
を使用してPDAで署名されます。
use solana_program::{
account_info::next_account_info, account_info::AccountInfo, entrypoint,
entrypoint::ProgramResult, program::invoke_signed, pubkey::Pubkey, system_instruction, sysvar::{rent::Rent, Sysvar}
};
entrypoint!(process_instruction);
fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let payer_account_info = next_account_info(account_info_iter)?;
let pda_account_info = next_account_info(account_info_iter)?;
let rent_sysvar_account_info = &Rent::from_account_info(next_account_info(account_info_iter)?)?;
// find space and minimum rent required for account
let space = instruction_data[0];
let bump = instruction_data[1];
let rent_lamports = rent_sysvar_account_info.minimum_balance(space.into());
invoke_signed(
&system_instruction::create_account(
&payer_account_info.key,
&pda_account_info.key,
rent_lamports,
space.into(),
program_id
),
&[
payer_account_info.clone(),
pda_account_info.clone()
],
&[&[&payer_account_info.key.as_ref(), &[bump]]]
)?;
Ok(())
}
invoke_signed(
&system_instruction::create_account(
&payer_account_info.key,
&pda_account_info.key,
rent_lamports,
space.into(),
program_id
),
&[
payer_account_info.clone(),
pda_account_info.clone()
],
&[&[&payer_account_info.key.as_ref(), &[bump]]]
)?;
Client
import {
clusterApiUrl,
Connection,
Keypair,
Transaction,
SystemProgram,
PublicKey,
TransactionInstruction,
LAMPORTS_PER_SOL,
SYSVAR_RENT_PUBKEY,
} from "@solana/web3.js";
(async () => {
// program id
const programId = new PublicKey(
"7ZP42kRwUQ2zgbqXoaXzAFaiQnDyp6swNktTSv8mNQGN"
);
// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// setup fee payer
const feePayer = Keypair.generate();
const feePayerAirdropSignature = await connection.requestAirdrop(
feePayer.publicKey,
LAMPORTS_PER_SOL
);
await connection.confirmTransaction(feePayerAirdropSignature);
// setup pda
let [pda, bump] = await PublicKey.findProgramAddress(
[feePayer.publicKey.toBuffer()],
programId
);
console.log(`bump: ${bump}, pubkey: ${pda.toBase58()}`);
const data_size = 0;
let tx = new Transaction().add(
new TransactionInstruction({
keys: [
{
pubkey: feePayer.publicKey,
isSigner: true,
isWritable: true,
},
{
pubkey: pda,
isSigner: false,
isWritable: true,
},
{
pubkey: SYSVAR_RENT_PUBKEY,
isSigner: false,
isWritable: false,
},
{
pubkey: SystemProgram.programId,
isSigner: false,
isWritable: false,
},
],
data: Buffer.from(new Uint8Array([data_size, bump])),
programId: programId,
})
);
console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer])}`);
})();
let tx = new Transaction().add(
new TransactionInstruction({
keys: [
{
pubkey: feePayer.publicKey,
isSigner: true,
isWritable: true,
},
{
pubkey: pda,
isSigner: false,
isWritable: true,
},
{
pubkey: SYSVAR_RENT_PUBKEY,
isSigner: false,
isWritable: false,
},
{
pubkey: SystemProgram.programId,
isSigner: false,
isWritable: false,
},
],
data: Buffer.from(new Uint8Array([data_size, bump])),
programId: programId,
})
);
console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer])}`);
PDAで署名する方法
PDA は、プログラム内でのみ署名できます。以下は、PDA で署名し、クライアントでプログラムを呼び出すプログラムの例です。
Program
以下は、シード escrow
によって派生した PDA から渡されたアカウントに SOL を転送する単一の instruction を示しています。 invoke_signed
は、PDA での署名に使用されます。
use solana_program::{
account_info::next_account_info, account_info::AccountInfo, entrypoint,
entrypoint::ProgramResult, program::invoke_signed, pubkey::Pubkey, system_instruction,
};
entrypoint!(process_instruction);
fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let pda_account_info = next_account_info(account_info_iter)?;
let to_account_info = next_account_info(account_info_iter)?;
let system_program_account_info = next_account_info(account_info_iter)?;
// pass bump seed for saving compute budget
let bump_seed = instruction_data[0];
invoke_signed(
&system_instruction::transfer(
&pda_account_info.key,
&to_account_info.key,
100_000_000, // 0.1 SOL
),
&[
pda_account_info.clone(),
to_account_info.clone(),
system_program_account_info.clone(),
],
&[&[b"escrow", &[bump_seed]]],
)?;
Ok(())
}
invoke_signed(
&system_instruction::transfer(
&pda_account_info.key,
&to_account_info.key,
100_000_000, // 0.1 SOL
),
&[
pda_account_info.clone(),
to_account_info.clone(),
system_program_account_info.clone(),
],
&[&[b"escrow", &[bump_seed]]],
)?;
Client
import {
clusterApiUrl,
Connection,
Keypair,
Transaction,
SystemProgram,
PublicKey,
TransactionInstruction,
LAMPORTS_PER_SOL,
} from "@solana/web3.js";
import * as bs58 from "bs58";
(async () => {
// program id
const programId = new PublicKey(
"4wQC2yuVt4rbcPeYLK8WngqbYLg7UAahVjRFrK3NBjP6"
);
// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// setup fee payer
const feePayer = Keypair.generate();
const feePayerAirdropSignature = await connection.requestAirdrop(
feePayer.publicKey,
LAMPORTS_PER_SOL
);
await connection.confirmTransaction(feePayerAirdropSignature);
// setup pda
let [pda, bump] = await PublicKey.findProgramAddress(
[Buffer.from("escrow")],
programId
);
console.log(`bump: ${bump}, pubkey: ${pda.toBase58()}`);
// require 1 SOL for the transfering in the program
const pdaAirdropSignature = await connection.requestAirdrop(
pda,
LAMPORTS_PER_SOL
);
await connection.confirmTransaction(pdaAirdropSignature);
// create a random `to`
const to = Keypair.generate();
console.log(`receiver: ${to.publicKey.toBase58()}`);
let tx = new Transaction().add(
new TransactionInstruction({
keys: [
{
pubkey: pda,
// Leave `false` here although we need a pda as a signer.
// It will be escalated on program if we use invoke_signed.
isSigner: false,
isWritable: true,
},
{
pubkey: to.publicKey,
isSigner: false,
isWritable: true,
},
{
pubkey: SystemProgram.programId,
isSigner: false,
isWritable: false,
},
],
data: Buffer.from(new Uint8Array([bump])),
programId: programId,
})
);
console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer])}`);
})();
let tx = new Transaction().add(
new TransactionInstruction({
keys: [
{
pubkey: pda,
// Leave `false` here although we need a pda as a signer.
// It will be escalated on program if we use invoke_signed.
isSigner: false,
isWritable: true,
},
{
pubkey: to.publicKey,
isSigner: false,
isWritable: true,
},
{
pubkey: SystemProgram.programId,
isSigner: false,
isWritable: false,
},
],
data: Buffer.from(new Uint8Array([bump])),
programId: programId,
})
);
console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer])}`);
program accountの取得方法
programが所有するすべてのアカウントを返します。getProgramAccounts
とその構成の詳細については、guides sectionを参照してください。
import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js";
(async () => {
const MY_PROGRAM_ID = new PublicKey(
"6a2GdmttJdanBkoHt7f4Kon4hfadx4UTUgJeRkCaiL3U"
);
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
const accounts = await connection.getProgramAccounts(MY_PROGRAM_ID);
console.log(`Accounts for program ${MY_PROGRAM_ID}: `);
console.log(accounts);
/*
// Output
Accounts for program 6a2GdmttJdanBkoHt7f4Kon4hfadx4UTUgJeRkCaiL3U:
[
{
account: {
data: <Buffer 60 06 66 ca 2c 1d c7 85 04 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 fc>,
executable: false,
lamports: 1064880,
owner: [PublicKey],
rentEpoch: 228
},
pubkey: PublicKey {
_bn: <BN: 82fc5b91154dc5c840cb464ba6a89212d0fd789367c0a1488fb1941d78f9727a>
}
},
{
account: {
data: <Buffer 60 06 66 ca 2c 1d c7 85 03 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 fd>,
executable: false,
lamports: 1064880,
owner: [PublicKey],
rentEpoch: 229
},
pubkey: PublicKey {
_bn: <BN: 404dc1fe368cf194f20cf3c681a071c61893ced98f65cda12ba5a147e984e669>
}
}
]
*/
})();
use solana_client::rpc_client::RpcClient;
use solana_program::pubkey::Pubkey;
use solana_sdk::commitment_config::CommitmentConfig;
use std::str::FromStr;
fn main() {
let rpc_url = String::from("https://api.devnet.solana.com");
let connection = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
let program_id = Pubkey::from_str("6a2GdmttJdanBkoHt7f4Kon4hfadx4UTUgJeRkCaiL3U").unwrap();
let accounts = connection.get_program_accounts(&program_id).unwrap();
println!("accounts for {}, {:?}", program_id, accounts);
}
curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '
{"jsonrpc":"2.0", "id":1, "method":"getProgramAccounts", "params":["6a2GdmttJdanBkoHt7f4Kon4hfadx4UTUgJeRkCaiL3U"]}
'
# Output
# {"jsonrpc":"2.0","result":[{"account":{"data":"fe2kiXpgfrjWQjCPX3n5MB339Ayqav75ej","executable":false,"lamports":1064880,"owner":"6a2GdmttJdanBkoHt7f4Kon4hfadx4UTUgJeRkCaiL3U","rentEpoch":228},"pubkey":"9pKBrUtJU9GNmct6T2BQtiKqvubtjS9D2if2bm1P8TQd"},{"account":{"data":"fe2kiXpgfrjVs7hiZJNVFsbJUuhXhFx3pQ","executable":false,"lamports":1064880,"owner":"6a2GdmttJdanBkoHt7f4Kon4hfadx4UTUgJeRkCaiL3U","rentEpoch":229},"pubkey":"5L1rztbopmgGMWPKb2efoGyhGnrBJm6K53Hf9S4nxdHr"}],"id":1}
accountの閉鎖
すべての SOL を削除することで、アカウントを閉じる(すべての保存データを消去する)ことができます。(詳細については、rentを参照してください)
Program
use solana_program::{
account_info::next_account_info, account_info::AccountInfo, entrypoint,
entrypoint::ProgramResult, pubkey::Pubkey,
};
entrypoint!(process_instruction);
fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let source_account_info = next_account_info(account_info_iter)?;
let dest_account_info = next_account_info(account_info_iter)?;
let dest_starting_lamports = dest_account_info.lamports();
**dest_account_info.lamports.borrow_mut() = dest_starting_lamports
.checked_add(source_account_info.lamports())
.unwrap();
**source_account_info.lamports.borrow_mut() = 0;
let mut source_data = source_account_info.data.borrow_mut();
source_data.fill(0);
Ok(())
}
let dest_starting_lamports = dest_account_info.lamports();
**dest_account_info.lamports.borrow_mut() = dest_starting_lamports
.checked_add(source_account_info.lamports())
.unwrap();
**source_account_info.lamports.borrow_mut() = 0;
let mut source_data = source_account_info.data.borrow_mut();
source_data.fill(0);
Client
import {
Keypair,
Connection,
Transaction,
SystemProgram,
TransactionInstruction,
PublicKey,
clusterApiUrl,
LAMPORTS_PER_SOL,
} from "@solana/web3.js";
(async function () {
// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// setup fee payer
const feePayer = Keypair.generate();
const feePayerAirdropSignature = await connection.requestAirdrop(
feePayer.publicKey,
LAMPORTS_PER_SOL
);
await connection.confirmTransaction(feePayerAirdropSignature);
// remember to deploy your program first
const programId = new PublicKey(
"An47uBJ8kY7hzKPzDyRoFSsDHkZFY9vkfUGpTViWqLFz"
);
// 1. create an account to your program
let newAccount = Keypair.generate();
console.log(`new account: ${newAccount.publicKey.toBase58()}`);
let createNewAccountTx = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: feePayer.publicKey,
newAccountPubkey: newAccount.publicKey,
lamports: 1e8, // 0.1 SOL
space: 10, // a random value
programId: programId,
})
);
console.log(
`create account txhash: ${await connection.sendTransaction(
createNewAccountTx,
[feePayer, newAccount]
)}`
);
// 2. close your account
let closeAccountTx = new Transaction().add(
new TransactionInstruction({
keys: [
{
pubkey: newAccount.publicKey,
isSigner: false,
isWritable: true,
},
{
pubkey: feePayer.publicKey,
isSigner: false,
isWritable: true,
},
],
programId: programId,
})
);
console.log(
`close account txhash: ${await connection.sendTransaction(closeAccountTx, [
feePayer,
])}`
);
})();
// 1. create an account to your program
let createNewAccountTx = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: feePayer.publicKey,
newAccountPubkey: newAccount.publicKey,
lamports: 1e8, // 0.1 SOL
space: 10, // a random value
programId: programId,
})
);
// 2. close your account
let closeAccountTx = new Transaction().add(
new TransactionInstruction({
keys: [
{
pubkey: newAccount.publicKey,
isSigner: false,
isWritable: true,
},
{
pubkey: feePayer.publicKey,
isSigner: false,
isWritable: true,
},
],
programId: programId,
})
);
accountの残高を取得する方法
import {
clusterApiUrl,
Connection,
PublicKey,
LAMPORTS_PER_SOL,
} from "@solana/web3.js";
(async () => {
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
let wallet = new PublicKey("G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY");
console.log(
`${(await connection.getBalance(wallet)) / LAMPORTS_PER_SOL} SOL`
);
})();
console.log(`${(await connection.getBalance(wallet)) / LAMPORTS_PER_SOL} SOL`);
use solana_client::rpc_client::RpcClient;
use solana_program::native_token::LAMPORTS_PER_SOL;
use solana_program::pubkey::Pubkey;
use solana_sdk::commitment_config::CommitmentConfig;
use std::str::FromStr;
fn main() {
let rpc_url = String::from("https://api.devnet.solana.com");
let connection = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
let wallet = Pubkey::from_str("G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY").unwrap();
let balance = connection.get_balance(&wallet).unwrap();
println!(
"The account {}, has {} SOL ",
wallet,
balance / LAMPORTS_PER_SOL
);
}
connection.get_balance(&wallet).unwrap();
from solders.keypair import Keypair
from solana.rpc.api import Client
client = Client("https://api.devnet.solana.com")
key_pair = Keypair()
public_key = key_pair.pubkey()
print(client.get_balance(public_key))
client = Client("https://api.devnet.solana.com")
key_pair = Keypair()
public_key = key_pair.pubkey()
client.get_balance(public_key)
// clang++ get_balance.cpp -o get_balance -std=c++17 -lssl -lcrypto -lsodium
#include "solana.hpp"
using namespace many::solana;
int main() {
Connection connection("https://api.devnet.solana.com");
auto key_pair = Keypair::generate();
auto public_key = key_pair.public_key;
std::cout << "public_key = " << public_key.to_base58() << std::endl;
uint64_t balance = connection.get_balance(public_key).unwrap();
std::cout << "balance = " << balance << std::endl;
return 0;
}
Connection connection("https://api.devnet.solana.com");
auto key_pair = Keypair::generate();
auto public_key = key_pair.public_key;
uint64_t balance = connection.get_balance(public_key).unwrap();
TIP
トークンの残高を取得したい場合は、トークンアカウントのアドレスを知る必要があります。詳細については、Token Referencesを参照してください。