トランザクションの送信

SOLの送金方法

SOL を送信するには、SystemProgramopen in new windowと対話する必要があります。

Press </> button to view full source
import {
  Connection,
  Keypair,
  SystemProgram,
  LAMPORTS_PER_SOL,
  Transaction,
  sendAndConfirmTransaction,
} from "@solana/web3.js";

(async () => {
  const fromKeypair = Keypair.generate();
  const toKeypair = Keypair.generate();

  const connection = new Connection(
    "https://api.devnet.solana.com",
    "confirmed"
  );

  const airdropSignature = await connection.requestAirdrop(
    fromKeypair.publicKey,
    LAMPORTS_PER_SOL
  );

  await connection.confirmTransaction(airdropSignature);

  const lamportsToSend = 1_000_000;

  const transferTransaction = new Transaction().add(
    SystemProgram.transfer({
      fromPubkey: fromKeypair.publicKey,
      toPubkey: toKeypair.publicKey,
      lamports: lamportsToSend,
    })
  );

  await sendAndConfirmTransaction(connection, transferTransaction, [
    fromKeypair,
  ]);
})();
from solana.rpc.api import Client
from solders.keypair import Keypair
from solana.transaction import Transaction
from solders.system_program import TransferParams, transfer

LAMPORT_PER_SOL = 1000000000

client: Client = Client("https://api.devnet.solana.com")

sender = Keypair()
receiver = Keypair()

airdrop = client.request_airdrop(sender.pubkey(), 1 * LAMPORT_PER_SOL)
airdrop_signature = airdrop.value
client.confirm_transaction(airdrop_signature)

transaction = Transaction().add(transfer(TransferParams(
    from_pubkey=sender.pubkey(),
    to_pubkey=receiver.pubkey(),
    lamports=1_000_000)
))

client.send_transaction(transaction, sender)
import { WalletNotConnectedError } from "@solana/wallet-adapter-base";
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Keypair, SystemProgram, Transaction } from "@solana/web3.js";
import React, { FC, useCallback } from "react";

export const SendTenLamportToRandomAddress: FC = () => {
  const { connection } = useConnection();
  const { publicKey, sendTransaction } = useWallet();

  const onClick = useCallback(async () => {
    if (!publicKey) throw new WalletNotConnectedError();

    const transaction = new Transaction().add(
      SystemProgram.transfer({
        fromPubkey: publicKey,
        toPubkey: Keypair.generate().publicKey,
        lamports: 1_000_000,
      })
    );

    const signature = await sendTransaction(transaction, connection);

    await connection.confirmTransaction(signature, "processed");
  }, [publicKey, sendTransaction, connection]);

  return (
    <button onClick={onClick} disabled={!publicKey}>
      Send 1 lamport to a random address!
    </button>
  );
};
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};
use solana_sdk::transaction::Transaction;

fn main() {
    let from = Keypair::new();
    let frompubkey = Signer::pubkey(&from);

    let to = Keypair::new();
    let topubkey = Signer::pubkey(&to);

    let lamports_to_send = 1_000_000;

    let rpc_url = String::from("https://api.devnet.solana.com");
    let connection = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());

    ///Airdropping some Sol to the 'from' account
    match connection.request_airdrop(&frompubkey, 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"),
    };

    ///Creating the transfer sol instruction
    let ix = system_instruction::transfer(&frompubkey, &topubkey, lamports_to_send);

    ///Putting the transfer sol instruction into a transaction
    let recent_blockhash = connection.get_latest_blockhash().expect("Failed to get latest blockhash.");
    let txn = Transaction::new_signed_with_payer(&[ix], Some(&frompubkey), &[&from], recent_blockhash);

    ///Sending the transfer sol transaction
    match connection.send_and_confirm_transaction(&txn){
        Ok(sig) => loop {
            if let Ok(confirmed) = connection.confirm_transaction(&sig) {
                if confirmed {
                    println!("Transaction: {} Status: {}", sig, confirmed);
                    break;
                }
            }
        },
        Err(e) => println!("Error transferring Sol:, {}", e),
    }

}
solana transfer --from <KEYPAIR> <RECIPIENT_ACCOUNT_ADDRESS> 0.001 --allow-unfunded-recipient --url https://api.devnet.solana.com --fee-payer <KEYPAIR>

SPL-Tokenの送信方法

Token Programopen in new windowを利用し、SPL-Tokenを送信します。SPL-tokenを送信するには、そのSPL-Tokenのアカウントアドレスを知る必要があります。次の例では、アドレスの取得とトークンの送信の両方を行うことができます。

Press </> button to view full source
const web3 = require("@solana/web3.js");
const splToken = require("@solana/spl-token");

(async () => {
  // Connect to cluster
  const connection = new web3.Connection(
    web3.clusterApiUrl("devnet"),
    "confirmed"
  );

  // Generate a new wallet keypair and airdrop SOL
  const fromWallet = web3.Keypair.generate();
  const fromAirdropSignature = await connection.requestAirdrop(
    fromWallet.publicKey,
    web3.LAMPORTS_PER_SOL
  );
  // Wait for airdrop confirmation
  await connection.confirmTransaction(fromAirdropSignature);

  // Generate a new wallet to receive newly minted token
  const toWallet = web3.Keypair.generate();

  // Create new token mint
  const mint = await splToken.createMint(
    connection,
    fromWallet,
    fromWallet.publicKey,
    null,
    9,
    splToken.TOKEN_PROGRAM_ID
  );

  // Get the token account of the fromWallet Solana address, if it does not exist, create it
  const fromTokenAccount = await mint.getOrCreateAssociatedAccountInfo(
    fromWallet.publicKey
  );

  //get the token account of the toWallet Solana address, if it does not exist, create it
  const toTokenAccount = await mint.getOrCreateAssociatedAccountInfo(
    toWallet.publicKey
  );

  // Minting 1 new token to the "fromTokenAccount" account we just returned/created
  await mint.mintTo(
    fromTokenAccount.address,
    fromWallet.publicKey,
    [],
    1000000000 // it's 1 token, but in lamports
  );

  // Add token transfer instructions to transaction
  const transaction = new web3.Transaction().add(
    splToken.createTransferInstruction(
      splToken.TOKEN_PROGRAM_ID,
      fromTokenAccount.address,
      toTokenAccount.address,
      fromWallet.publicKey,
      [],
      1
    )
  );

  // Sign transaction, broadcast, and confirm
  await web3.sendAndConfirmTransaction(connection, transaction, [fromWallet]);
})();
import { WalletNotConnectedError } from "@solana/wallet-adapter-base";
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Keypair, SystemProgram, Transaction } from "@solana/web3.js";
import { TOKEN_PROGRAM_ID, createTransferInstruction } from "@solana/spl-token";
import React, { FC, useCallback } from "react";

export const SendSPLTokenToAddress: FC = (
  fromTokenAccount,
  toTokenAccount,
  fromWallet
) => {
  const { connection } = useConnection();
  const { publicKey, sendTransaction } = useWallet();

  const onClick = useCallback(async () => {
    if (!publicKey) throw new WalletNotConnectedError();

    const transaction = new Transaction().add(
      createTransferInstruction(
        fromTokenAccount.address,
        toTokenAccount.address,
        fromWallet.publicKey,
        1,
        [],
        TOKEN_PROGRAM_ID
      )
    );

    const signature = await sendTransaction(transaction, connection);

    await connection.confirmTransaction(signature, "processed");
  }, [publicKey, sendTransaction, connection]);

  return (
    <button onClick={onClick} disabled={!publicKey}>
      Send 1 lamport to a random address!
    </button>
  );
};
$ spl-token transfer AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 50 vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg
Transfer 50 tokens
  Sender: 7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi
  Recipient: vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg
  Recipient associated token account: F59618aQB8r6asXeMcB9jWuY6NEx1VduT9yFo1GTi1ks

Signature: 5a3qbvoJQnTAxGPHCugibZTbSu7xuTgkxvF4EJupRjRXGgZZrnWFmKzfEzcqKF2ogCaF4QKVbAtuFx7xGwrDUcGd

トランザクションコストの計算方法

トランザクションに必要な署名の数は、トランザクションコストの計算に使用されますアカウントを作成していない限り、これが最終的な取引コストになります。アカウントを作成するための費用について詳しくは、 calculating rent exemptionをご覧ください。

以下の 2 つの例は、推定トランザクション コストを計算するために現在利用できる 2 つの方法を示しています。

最初の例では、 Transactionクラスの新しいメソッドであるgetEstimatedFeeを使用しています。2番目の例では、Connection クラスのgetFeeCalculatorForBlockhashを置き換えるgetFeeForMessageを使用しています。

getEstimatedFee

Press </> button to view full source
import {
  clusterApiUrl,
  Connection,
  Keypair,
  SystemProgram,
  Transaction,
} from "@solana/web3.js";

(async () => {
  // Connect to cluster
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");

  const payer = Keypair.generate();
  const payee = Keypair.generate();

  const recentBlockhash = await connection.getLatestBlockhash();

  const transaction = new Transaction({
    recentBlockhash: recentBlockhash.blockhash, 
    feePayer: payer.publicKey
  }).add(
    SystemProgram.transfer({
      fromPubkey: payer.publicKey,
      toPubkey: payee.publicKey,
      lamports: 10,
    })
  );

  const fees = await transaction.getEstimatedFee(connection);
  console.log(`Estimated SOL transfer cost: ${fees} lamports`);
  // Estimated SOL transfer cost: 5000 lamports
})();

getFeeForMessage

Press </> button to view full source
import {
  clusterApiUrl,
  Connection,
  Keypair,
  Message,
  SystemProgram,
  SYSTEM_INSTRUCTION_LAYOUTS,
  Transaction,
} from "@solana/web3.js";
import bs58 from "bs58";

(async () => {
  // Connect to cluster
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");

  const payer = Keypair.generate();
  const payee = Keypair.generate();

  const type = SYSTEM_INSTRUCTION_LAYOUTS.Transfer;
  const data = Buffer.alloc(type.layout.span);
  const layoutFields = Object.assign({ instruction: type.index });
  type.layout.encode(layoutFields, data);

  const recentBlockhash = await connection.getLatestBlockhash();

  const messageParams = {
    accountKeys: [
      payer.publicKey.toString(),
      payee.publicKey.toString(),
      SystemProgram.programId.toString(),
    ],
    header: {
      numReadonlySignedAccounts: 0,
      numReadonlyUnsignedAccounts: 1,
      numRequiredSignatures: 1,
    },
    instructions: [
      {
        accounts: [0, 1],
        data: bs58.encode(data),
        programIdIndex: 2,
      },
    ],
    recentBlockhash: recentBlockhash.blockhash,
  };

  const message = new Message(messageParams);

  const fees = await connection.getFeeForMessage(message);
  console.log(`Estimated SOL transfer cost: ${fees.value} lamports`);
  // Estimated SOL transfer cost: 5000 lamports
})();

トランザクションへのメモの追加方法

memo programopen in new windowを利用して、どのトランザクションでもメッセージを追加できます。 現在、メモ プログラムの Memo Program programIDMemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHrを手動で追加する必要があります。

Press </> button to view full source
import {
  Connection,
  Keypair,
  SystemProgram,
  LAMPORTS_PER_SOL,
  PublicKey,
  Transaction,
  TransactionInstruction,
  sendAndConfirmTransaction,
} from "@solana/web3.js";

(async () => {
  const fromKeypair = Keypair.generate();
  const toKeypair = Keypair.generate();

  const connection = new Connection(
    "https://api.devnet.solana.com",
    "confirmed"
  );

  const airdropSignature = await connection.requestAirdrop(
    fromKeypair.publicKey,
    LAMPORTS_PER_SOL
  );

  await connection.confirmTransaction(airdropSignature);

  const lamportsToSend = 10;

  const transferTransaction = new Transaction().add(
    SystemProgram.transfer({
      fromPubkey: fromKeypair.publicKey,
      toPubkey: toKeypair.publicKey,
      lamports: lamportsToSend,
    })
  );

  await transferTransaction.add(
    new TransactionInstruction({
      keys: [
        { pubkey: fromKeypair.publicKey, isSigner: true, isWritable: true },
      ],
      data: Buffer.from("Data to send in transaction", "utf-8"),
      programId: new PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"),
    })
  );

  await sendAndConfirmTransaction(connection, transferTransaction, [
    fromKeypair,
  ]);
})();
import { WalletNotConnectedError } from "@solana/wallet-adapter-base";
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import {
  Keypair,
  PublicKey,
  SystemProgram,
  Transaction,
  TransactionInstruction,
} from "@solana/web3.js";
import React, { FC, useCallback } from "react";

export const SendTenLamportToRandomAddress: FC = () => {
  const { connection } = useConnection();
  const { publicKey, sendTransaction } = useWallet();

  const onClick = useCallback(async () => {
    if (!publicKey) throw new WalletNotConnectedError();

    const transaction = new Transaction().add(
      SystemProgram.transfer({
        fromPubkey: publicKey,
        toPubkey: Keypair.generate().publicKey,
        lamports: 10,
      })
    );

    await transaction.add(
      new TransactionInstruction({
        keys: [{ pubkey: publicKey, isSigner: true, isWritable: true }],
        data: Buffer.from("Data to send in transaction", "utf-8"),
        programId: new PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"),
      })
    );

    const signature = await sendTransaction(transaction, connection);

    await connection.confirmTransaction(signature, "processed");
  }, [publicKey, sendTransaction, connection]);

  return (
    <button onClick={onClick} disabled={!publicKey}>
      Send 1 lamport to a random address!
    </button>
  );
};
solana transfer --from <KEYPAIR> <RECIPIENT_ACCOUNT_ADDRESS> 0.5 --allow-unfunded-recipient --url https://api.devnet.solana.com --fee-payer <KEYPAIR> --with-memo <MEMO>

トランザクションの計算予算、料金、および優先度を変更する方法

トランザクション (TX) の優先順位は、基本手数料に加えて優先手数料を支払うことによって達成されます。デフォルトでは、コンピューティング予算は 200,000 コンピューティング ユニット (CU) * 命令数の積であり、最大 1.4M CU です。基本料金は 5,000 lamportです。 microLamport は 0.000001 lamportです。

1つの TX の合計コンピューティング予算または優先順位付け料金は、ComputeBudgetProgram からの命令を追加することで変更できます。

ComputeBudgetProgram.setComputeUnitPrice({ microLamports: number }) は、基本料金 (5,000 lamport) の上に優先料金を追加します。 microLamportsで提供される値にCU予算を掛けて、Lamports の優先料金を決定します。 たとえば、CU 予算が 100 万 CU で、1 つの microLamport/CU を追加する場合、優先料金は 1 lamport (1M * 0.000001) になります。合計料金は 5001 lamport になります。

ComputeBudgetProgram.setComputeUnitLimit({ units: number }) 使用して、新しいコンピューティング予算を設定します。 指定された値は、デフォルト値を置き換えます。 トランザクションは、スループットを最大化する、または手数料を最小化するために、実行に必要な最小量の CU を要求する必要があります。

Press </> button to view full source
import { BN } from "@project-serum/anchor";
import {
  Keypair,
  Connection,
  LAMPORTS_PER_SOL,
  sendAndConfirmTransaction,
  ComputeBudgetProgram,
  SystemProgram,
  Transaction,
} from "@solana/web3.js";

(async () => {
  const payer = Keypair.generate();
  const toAccount = Keypair.generate().publicKey;

  const connection = new Connection("http://127.0.0.1:8899", "confirmed");

  const airdropSignature = await connection.requestAirdrop(
    payer.publicKey,
    LAMPORTS_PER_SOL
  );

  await connection.confirmTransaction(airdropSignature);

  const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({ 
    units: 1000000 
  });

  const addPriorityFee = ComputeBudgetProgram.setComputeUnitPrice({ 
    microLamports: 1 
  });

  // Total fee will be 5,001 Lamports for 1M CU
  const transaction = new Transaction()
    .add(modifyComputeUnits)
    .add(addPriorityFee)
    .add(
      SystemProgram.transfer({
        fromPubkey: payer.publicKey,
        toPubkey: toAccount,
        lamports: 10000000,
      })
    );

  const signature = await sendAndConfirmTransaction(connection, transaction, [
    payer,
  ]);
  console.log(signature);
  const result = await connection.getParsedTransaction(signature);
  console.log(result);
})();
//! @brief Example Budget Management

use solana_client::rpc_client::RpcClient;
use solana_program::{instruction::Instruction, message::Message, pubkey::Pubkey};
use solana_sdk::{
    compute_budget::ComputeBudgetInstruction,
    pubkey,
    signature::{Keypair, Signature},
    signer::Signer,
    transaction::Transaction,
};

/// Submits the program instruction as per the instruction definition
fn submit_transaction(
    rpc_client: &RpcClient,
    wallet_signer: &dyn Signer,
    instructions: Vec<Instruction>,
) -> Result<Signature, Box<dyn std::error::Error>> {
    let mut transaction =
        Transaction::new_unsigned(Message::new(&instructions, Some(&wallet_signer.pubkey())));
    let recent_blockhash = rpc_client
        .get_latest_blockhash()
        .map_err(|err| format!("error: unable to get recent blockhash: {}", err))?;
    transaction
        .try_sign(&vec![wallet_signer], recent_blockhash)
        .map_err(|err| format!("error: failed to sign transaction: {}", err))?;
    let signature = rpc_client
        .send_and_confirm_transaction(&transaction)
        .map_err(|err| format!("error: send transaction: {}", err))?;
    Ok(signature)
}

const PROG_KEY: Pubkey = pubkey!("PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc");

/// Increase the Transaction Budget and call normal instruction(s)
/// Here we send redundant transactions to witness Compute Budget drawdown
fn send_instructions_demo(
    rpc_client: &RpcClient,
    wallet_signer: &dyn Signer,
) -> Result<(), Box<dyn std::error::Error>> {{
    let accounts = &[];
    let txn = submit_transaction(
        &connection,
        &wallet_signer,
        // Array of instructions: 0: Set Compute Unit Limt, 1: Set Prioritization Fee, 
        // 2: Do something, 3: Do something else
        [ComputeBudgetInstruction::set_compute_unit_limit(1_000_000u32),
        ComputeBudgetInstruction::set_compute_unit_price(1u32),
        Instruction::new_with_borsh(PROG_KEY, &0u8, accounts.to_vec()),
        Instruction::new_with_borsh(PROG_KEY, &0u8, accounts.to_vec())].to_vec(),
    )?;
    println!("{:?}", txn);
    Ok(())
}

プログラムログの例 ( Exploreropen in new window ):

[ 1] Program ComputeBudget111111111111111111111111111111 invoke [1]
[ 2] Program ComputeBudget111111111111111111111111111111 success
[ 3]
[ 4] Program ComputeBudget111111111111111111111111111111 invoke [1]
[ 5] Program ComputeBudget111111111111111111111111111111 success
Last Updated:
Contributors: PokoPoko2ry