Перейти к основному содержанию

Параметры

transaction
string
обязательно
Полностью подписанная транзакция в виде строки в кодировке base-64
config
object
Объект конфигурации, содержащий:
encoding
string
Формат кодирования транзакции (base58, base64, json)
commitment
string
Уровень подтверждения (processed, confirmed, finalized)
preflightCommitment
string
Уровень подтверждения для предварительной проверки (processed, confirmed, finalized)
skipPreflight
boolean
Если true, пропустить предварительные проверки транзакции
maxRetries
number
Максимальное количество попыток RPC-узла повторно отправить транзакцию лидеру
minContextSlot
number
Минимальный слот, при котором может быть оценён запрос

Ответ

result
string
Первая подпись транзакции, встроенная в транзакцию (в кодировке base-58)

Примеры кода

Базовый запрос

curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "sendTransaction",
  "params": [
    "4hXTCkRzt9WyecNzV1XPgCDfGAZzQKNxLXgynz5QDuWWPSAZBZSHptvWRL3BjCvzUXRdKvHL2b7yGrRQcWyaqsaBCncVG7BFggS8w9snUts67BSh3EqKpXLUm5UMHfD7ZBe9GhARjbNQMLJ1QD3Spr6oMTFNhyKNMr3WNFCrXgDS7uV7u",
    {
      "encoding": "base64",
      "commitment": "confirmed"
    }
  ]
}'

Использование web3.js

import { Connection, Transaction, PublicKey, SystemProgram } from '@solana/web3.js';

const connection = new Connection('https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY');

// Create and send transaction
const transaction = new Transaction().add(
  SystemProgram.transfer({
    fromPubkey: new PublicKey('83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri'),
    toPubkey: new PublicKey('J7rBdM6AecPDEZp8aPq5tPmsPzPhQG4HD6YtAcQBDfJj'),
    lamports: 1000000000
  })
);

const signature = await connection.sendTransaction(transaction, [signer]);
console.log('Transaction signature:', signature);

// Send transaction with confirmation
async function sendTransactionWithConfirmation(
  transaction: Transaction,
  signers: Array<Signer>,
  config: { 
    commitment?: string;
    preflightCommitment?: string;
    skipPreflight?: boolean;
    maxRetries?: number;
  }
) {
  const signature = await connection.sendTransaction(
    transaction,
    signers,
    config
  );
  
  // Wait for confirmation
  const confirmation = await connection.confirmTransaction(signature, config.commitment);
  
  return {
    signature,
    confirmation: {
      status: confirmation.value.err ? 'failed' : 'success',
      slot: confirmation.context.slot
    },
    transaction: {
      recentBlockhash: transaction.recentBlockhash,
      feePayer: transaction.feePayer?.toBase58(),
      instructions: transaction.instructions.length
    },
    metadata: {
      timestamp: Date.now(),
      commitment: config.commitment
    }
  };
}

Примечания

  1. Отправляет подписанную транзакцию в кластер
  2. Транзакция должна быть полностью подписана
  3. Ответ — это подпись транзакции
  4. Транзакция должна быть подтверждена перед применением изменений
  5. Транзакция должна содержать актуальный blockhash

Рекомендации

  1. Используйте подходящий уровень подтверждения в зависимости от ваших потребностей
  2. Дождитесь подтверждения транзакции перед продолжением работы
  3. Обрабатывайте ограничения запросов и сетевые ошибки
  4. Отслеживайте статус транзакции на предмет сбоев
  5. Рассмотрите использование предварительных проверок для валидации

Распространённые ошибки

КодСообщениеРешение
-32601Method not foundУбедитесь, что вы подключены к узлу Solana RPC
-32602Invalid paramsПроверьте формат транзакции и кодирование
-32003Transaction simulation failedПроверьте корректность транзакции и балансы счетов
-32004Blockhash not foundИспользуйте более актуальный blockhash
-32005Node is behindПопробуйте другой узел RPC
-32006Transaction already processedТранзакция уже была отправлена
-32007Transaction signature verification failedПроверьте подписи транзакции

Сценарии использования

  1. Управление транзакциями
    interface TransactionRequest {
      transaction: {
        signature: string;
        blockhash: string;
        feePayer: string;
        instructions: number;
      };
      status: {
        state: 'pending' | 'success' | 'failed';
        confirmations: number;
        slot?: number;
        error?: string;
      };
      metadata: {
        timestamp: number;
        commitment?: string;
        retries: number;
      };
    }
    
    class TransactionManager {
      private readonly maxRetries = 3;
      private readonly confirmationTimeout = 30000; // 30 seconds
      
      async sendTransaction(
        transaction: Transaction,
        signers: Array<Signer>,
        config: { 
          commitment?: string;
          preflightCommitment?: string;
          skipPreflight?: boolean;
        }
      ): Promise<TransactionRequest> {
        let retries = 0;
        let signature: string;
        
        while (retries < this.maxRetries) {
          try {
            // Get a new blockhash if retrying
            if (retries > 0) {
              const { blockhash } = await connection.getRecentBlockhash();
              transaction.recentBlockhash = blockhash;
            }
            
            signature = await connection.sendTransaction(
              transaction,
              signers,
              config
            );
            
            // Wait for confirmation
            const confirmation = await connection.confirmTransaction(signature, config.commitment);
            
            if (!confirmation.value.err) {
              return {
                transaction: {
                  signature,
                  blockhash: transaction.recentBlockhash,
                  feePayer: transaction.feePayer?.toBase58(),
                  instructions: transaction.instructions.length
                },
                status: {
                  state: 'success',
                  confirmations: 1,
                  slot: confirmation.context.slot
                },
                metadata: {
                  timestamp: Date.now(),
                  commitment: config.commitment,
                  retries
                }
              };
            }
            
            throw new Error(confirmation.value.err.toString());
          } catch (error) {
            retries++;
            if (retries === this.maxRetries) {
              return {
                transaction: {
                  signature,
                  blockhash: transaction.recentBlockhash,
                  feePayer: transaction.feePayer?.toBase58(),
                  instructions: transaction.instructions.length
                },
                status: {
                  state: 'failed',
                  confirmations: 0,
                  error: error.message
                },
                metadata: {
                  timestamp: Date.now(),
                  commitment: config.commitment,
                  retries
                }
              };
            }
            await new Promise(resolve => setTimeout(resolve, 1000));
          }
        }
      }
    }
    
  2. Мониторинг транзакций
    interface TransactionStatus {
      transaction: {
        signature: string;
        slot?: number;
      };
      status: {
        confirmations: number;
        err: any;
      };
      history: Array<{
        timestamp: number;
        confirmations: number;
        error?: string;
      }>;
    }
    
    class TransactionMonitor {
      private transactions: Map<string, TransactionStatus> = new Map();
      
      async monitorTransaction(
        signature: string
      ): Promise<TransactionStatus> {
        let status = this.transactions.get(signature);
        const now = Date.now();
        
        const confirmation = await connection.getSignatureStatus(signature);
        
        if (!status) {
          status = {
            transaction: {
              signature,
              slot: confirmation?.slot
            },
            status: {
              confirmations: confirmation?.confirmations || 0,
              err: confirmation?.err
            },
            history: [{
              timestamp: now,
              confirmations: confirmation?.confirmations || 0,
              error: confirmation?.err?.toString()
            }]
          };
        } else {
          status.status.confirmations = confirmation?.confirmations || 0;
          status.status.err = confirmation?.err;
          status.history.push({
            timestamp: now,
            confirmations: confirmation?.confirmations || 0,
            error: confirmation?.err?.toString()
          });
        }
        
        this.transactions.set(signature, status);
        return status;
      }
    }
    
  3. Планирование транзакций
    interface TransactionPlan {
      transaction: {
        instructions: number;
        signers: number;
        estimatedFee: number;
      };
      recommendations: Array<{
        type: 'proceed' | 'split' | 'abort';
        reason: string;
      }>;
      metadata: {
        timestamp: number;
      };
    }
    
    class TransactionPlanner {
      private readonly maxInstructions = 10;
      private readonly maxSigners = 8;
      
      async planTransaction(
        transaction: Transaction
      ): Promise<TransactionPlan> {
        const { feeCalculator } = await connection.getRecentBlockhash();
        const estimatedFee = feeCalculator.lamportsPerSignature * transaction.signatures.length;
        
        const recommendations: Array<{
          type: 'proceed' | 'split' | 'abort';
          reason: string;
        }> = [];
        
        if (transaction.instructions.length > this.maxInstructions) {
          recommendations.push({
            type: 'split',
            reason: `Transaction has ${transaction.instructions.length} instructions, exceeding maximum of ${this.maxInstructions}`
          });
        }
        
        if (transaction.signatures.length > this.maxSigners) {
          recommendations.push({
            type: 'split',
            reason: `Transaction has ${transaction.signatures.length} signers, exceeding maximum of ${this.maxSigners}`
          });
        }
        
        if (recommendations.length === 0) {
          recommendations.push({
            type: 'proceed',
            reason: 'Transaction is within limits'
          });
        }
        
        return {
          transaction: {
            instructions: transaction.instructions.length,
            signers: transaction.signatures.length,
            estimatedFee
          },
          recommendations,
          metadata: {
            timestamp: Date.now()
          }
        };
      }
    }