Параметры
Подпись транзакции (в кодировке base-58)
Объект конфигурации, содержащий:Уровень подтверждения (processed, confirmed, finalized)
Кодирование для данных транзакции (base58, base64, jsonParsed)
maxSupportedTransactionVersion
Максимальная поддерживаемая версия транзакции
Ответ
Объект, содержащий:Слот, в котором была обработана транзакция
Количество обязательных подписей
numReadonlySignedAccounts
Количество подписанных счетов только для чтения
numReadonlyUnsignedAccounts
Количество неподписанных счетов только для чтения
Массив открытых ключей счетов (в кодировке base-58)
Недавний blockhash, используемый для транзакции
Массив объектов инструкций, содержащих:ID программы (в кодировке base-58)
Данные инструкции (в кодировке base-58)
Массив подписей транзакции (в кодировке 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": "getTransaction",
"params": [
"5VERv8NMvzbJMEkV8xnrLkUaQwJJ9C9zV5uZ6cKf7Kq9",
{
"encoding": "jsonParsed"
}
]
}'
Использование web3.js
import { Connection, Transaction } from '@solana/web3.js';
const connection = new Connection('https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY');
// Get transaction
const signature = '5VERv8NMvzbJMEkV8xnrLkUaQwJJ9C9zV5uZ6cKf7Kq9';
const transaction = await connection.getTransaction(signature, {
encoding: 'jsonParsed'
});
console.log('Transaction:', transaction);
// Get transaction with analysis
async function getTransactionWithAnalysis(
signature: string,
config: { commitment?: string; encoding?: string }
) {
const transaction = await connection.getTransaction(signature, config);
return {
transaction,
analysis: {
success: !transaction.meta.err,
fee: transaction.meta.fee,
balanceChanges: transaction.meta.postBalances.map((post, index) => ({
account: transaction.transaction.message.accountKeys[index],
change: post - transaction.meta.preBalances[index]
})),
tokenBalanceChanges: transaction.meta.postTokenBalances?.map((post, index) => ({
account: post.account,
mint: post.mint,
change: BigInt(post.uiTokenAmount.amount) - BigInt(transaction.meta.preTokenBalances![index].uiTokenAmount.amount)
})),
metadata: {
timestamp: Date.now(),
commitment: config.commitment
}
}
};
}
Примечания
- Возвращает детали транзакции по заданной подписи
- Транзакция должна быть подтверждена, чтобы её можно было вернуть
- Ответ содержит подробную информацию о транзакции
- Транзакция может быть разобрана в различных кодировках
- Подпись транзакции должна быть корректной
Рекомендации
- Используйте подходящий уровень подтверждения в зависимости от ваших потребностей
- Кэшируйте результаты там, где это уместно, для снижения нагрузки на RPC
- Отслеживайте изменения статуса транзакции
- Рассмотрите использование подписки на websocket для обновлений в реальном времени
- Обрабатывайте сетевые ошибки и выполняйте повторные попытки при необходимости
Распространённые ошибки
| Код | Сообщение | Решение |
|---|
| -32601 | Method not found | Убедитесь, что вы подключены к узлу Solana RPC |
| -32602 | Invalid params | Проверьте подпись и конфигурацию |
| -32007 | Transaction not found | Убедитесь, что транзакция существует |
| -32008 | Invalid encoding | Убедитесь, что кодирование корректно |
Сценарии использования
-
Анализ транзакции
interface TransactionAnalysis {
signature: string;
transaction: {
success: boolean;
fee: number;
balanceChanges: Array<{
account: string;
change: number;
}>;
tokenBalanceChanges?: Array<{
account: string;
mint: string;
change: bigint;
}>;
instructions: Array<{
programId: string;
accounts: string[];
data: string;
}>;
};
metrics: {
totalBalanceChange: number;
totalTokenBalanceChange?: bigint;
instructionCount: number;
accountCount: number;
};
metadata: {
timestamp: number;
commitment?: string;
};
}
class TransactionAnalyzer {
async analyzeTransaction(
signature: string,
config: { commitment?: string; encoding?: string }
): Promise<TransactionAnalysis> {
const transaction = await connection.getTransaction(signature, config);
return {
signature,
transaction: {
success: !transaction.meta.err,
fee: transaction.meta.fee,
balanceChanges: transaction.meta.postBalances.map((post, index) => ({
account: transaction.transaction.message.accountKeys[index],
change: post - transaction.meta.preBalances[index]
})),
tokenBalanceChanges: transaction.meta.postTokenBalances?.map((post, index) => ({
account: post.account,
mint: post.mint,
change: BigInt(post.uiTokenAmount.amount) - BigInt(transaction.meta.preTokenBalances![index].uiTokenAmount.amount)
})),
instructions: transaction.transaction.message.instructions.map(ix => ({
programId: transaction.transaction.message.accountKeys[ix.programIdIndex],
accounts: ix.accounts.map(index => transaction.transaction.message.accountKeys[index]),
data: ix.data
}))
},
metrics: {
totalBalanceChange: transaction.meta.postBalances.reduce((sum, post, index) =>
sum + (post - transaction.meta.preBalances[index]), 0),
totalTokenBalanceChange: transaction.meta.postTokenBalances?.reduce((sum, post, index) =>
sum + (BigInt(post.uiTokenAmount.amount) - BigInt(transaction.meta.preTokenBalances![index].uiTokenAmount.amount)), BigInt(0)),
instructionCount: transaction.transaction.message.instructions.length,
accountCount: transaction.transaction.message.accountKeys.length
},
metadata: {
timestamp: Date.now(),
commitment: config.commitment
}
};
}
}
-
Мониторинг транзакций
interface TransactionChange {
signature: string;
changes: {
status: 'confirmed' | 'failed' | 'dropped';
previousStatus?: 'confirmed' | 'failed' | 'dropped';
error?: any;
};
metadata: {
timestamp: number;
};
}
class TransactionMonitor {
private previousTransactions: Map<string, {
status: 'confirmed' | 'failed' | 'dropped';
error?: any;
}> = new Map();
async monitorTransaction(
signature: string,
config: { commitment?: string; encoding?: string }
): Promise<TransactionChange | null> {
const transaction = await connection.getTransaction(signature, config);
const currentStatus = transaction ? (transaction.meta.err ? 'failed' : 'confirmed') : 'dropped';
const previous = this.previousTransactions.get(signature);
if (previous && (previous.status !== currentStatus || previous.error !== transaction?.meta.err)) {
this.previousTransactions.set(signature, {
status: currentStatus,
error: transaction?.meta.err
});
return {
signature,
changes: {
status: currentStatus,
previousStatus: previous.status,
error: transaction?.meta.err
},
metadata: {
timestamp: Date.now()
}
};
}
this.previousTransactions.set(signature, {
status: currentStatus,
error: transaction?.meta.err
});
return null;
}
}
-
Планирование транзакций
interface TransactionPlan {
signature: string;
transaction: {
success: boolean;
fee: number;
balanceChanges: Array<{
account: string;
change: number;
}>;
tokenBalanceChanges?: Array<{
account: string;
mint: string;
change: bigint;
}>;
};
recommendations: Array<{
type: 'optimize' | 'retry' | 'cancel';
reason: string;
}>;
metadata: {
timestamp: number;
};
}
class TransactionPlanner {
private readonly maxFee = 1000000; // 0.001 SOL
private readonly minBalance = 1000000; // 0.001 SOL
async planTransaction(
signature: string,
config: { commitment?: string; encoding?: string }
): Promise<TransactionPlan> {
const transaction = await connection.getTransaction(signature, config);
const recommendations: Array<{
type: 'optimize' | 'retry' | 'cancel';
reason: string;
}> = [];
// Check for high fees
if (transaction.meta.fee > this.maxFee) {
recommendations.push({
type: 'optimize',
reason: `Transaction fee (${transaction.meta.fee}) exceeds maximum (${this.maxFee})`
});
}
// Check for low balances
const lowBalanceAccounts = transaction.meta.postBalances
.map((post, index) => ({
account: transaction.transaction.message.accountKeys[index],
balance: post
}))
.filter(acc => acc.balance < this.minBalance);
if (lowBalanceAccounts.length > 0) {
recommendations.push({
type: 'optimize',
reason: `Accounts with low balances: ${lowBalanceAccounts.map(acc => acc.account).join(', ')}`
});
}
// Check for failed transaction
if (transaction.meta.err) {
recommendations.push({
type: 'retry',
reason: `Transaction failed with error: ${JSON.stringify(transaction.meta.err)}`
});
}
return {
signature,
transaction: {
success: !transaction.meta.err,
fee: transaction.meta.fee,
balanceChanges: transaction.meta.postBalances.map((post, index) => ({
account: transaction.transaction.message.accountKeys[index],
change: post - transaction.meta.preBalances[index]
})),
tokenBalanceChanges: transaction.meta.postTokenBalances?.map((post, index) => ({
account: post.account,
mint: post.mint,
change: BigInt(post.uiTokenAmount.amount) - BigInt(transaction.meta.preTokenBalances![index].uiTokenAmount.amount)
}))
},
recommendations,
metadata: {
timestamp: Date.now()
}
};
}
}