Skip to main content

Overview

The transaction status can be retrieved from the response of sendSignedTransaction, which waits for the transaction to be finalized and returns the complete transaction outcome.
The NEAR API TypeScript library automatically waits for transaction finalization when using sendSignedTransaction. The transaction status is included in the response.

Transaction Status Response

When you send a signed transaction, the response includes comprehensive status information:
const result = await client.sendSignedTransaction({
  signedTransaction: signedTx,
});

if (result.ok) {
  const status = result.value.rawRpcResult.status;
  // Status will be one of: SuccessValue, SuccessReceiptId, or Failure
}
Source: packages/near-api-ts/universal/src/client/methods/transaction/sendSignedTransaction/handleResult/handleResult.ts:29-39

Status Types

Success Status

SuccessValue
string
Transaction succeeded and returned a value (base64-encoded)
if ('SuccessValue' in status) {
  const returnValue = Buffer.from(status.SuccessValue, 'base64');
  console.log('Return value:', returnValue.toString());
}
SuccessReceiptId
string
Transaction succeeded and generated a receipt
if ('SuccessReceiptId' in status) {
  console.log('Receipt ID:', status.SuccessReceiptId);
}

Failure Status

Failure
object
Transaction failed during execution
ActionError
object
Details about which action failed and why
index
number
Index of the action that failed
kind
object
The specific error that occurred
if ('Failure' in status && 'ActionError' in status.Failure) {
  const error = status.Failure.ActionError;
  console.error(`Action ${error.index} failed:`, error.kind);
}

Transaction Outcome Details

The response includes detailed information about transaction execution:
transaction_outcome
object
Outcome of the transaction itself
id
string
Transaction hash
outcome
object
gas_burnt
string
Amount of gas burned during execution
tokens_burnt
string
Amount of tokens burned as fees (in yoctoNEAR)
status
object
Status of the transaction outcome
logs
string[]
Log messages emitted during execution
receipt_ids
string[]
IDs of receipts generated by this transaction
receipts_outcome
array
Array of outcomes for all receipts generated by the transactionEach receipt outcome contains:
  • id - Receipt ID
  • outcome - Execution outcome (gas, tokens, logs, status)
  • block_hash - Block where receipt was executed

Examples

Check Transaction Success

import { createClient, mainnet } from '@near-js/client';

const client = createClient({ network: mainnet });

const result = await client.sendSignedTransaction({
  signedTransaction: signedTx,
});

if (!result.ok) {
  console.error('Transaction failed to send:', result.error.kind);
  process.exit(1);
}

const { rawRpcResult } = result.value;
const { status } = rawRpcResult;

// Check if transaction succeeded
if ('SuccessValue' in status || 'SuccessReceiptId' in status) {
  console.log('✅ Transaction succeeded!');
  console.log('Transaction hash:', rawRpcResult.transaction.hash);
} else if ('Failure' in status) {
  console.error('❌ Transaction failed:', status.Failure);
}

Extract Return Value

const result = await client.sendSignedTransaction({
  signedTransaction: signedTx,
});

if (result.ok) {
  const { status } = result.value.rawRpcResult;
  
  if ('SuccessValue' in status) {
    // Decode base64 return value
    const returnValueBytes = Buffer.from(status.SuccessValue, 'base64');
    
    // Parse JSON if the contract returns JSON
    try {
      const returnValue = JSON.parse(returnValueBytes.toString());
      console.log('Contract returned:', returnValue);
    } catch {
      console.log('Raw return value:', returnValueBytes.toString());
    }
  }
}

Analyze Gas Usage

const result = await client.sendSignedTransaction({
  signedTransaction: signedTx,
});

if (result.ok) {
  const { transaction_outcome, receipts_outcome } = result.value.rawRpcResult;
  
  // Gas used by transaction
  const txGas = BigInt(transaction_outcome.outcome.gas_burnt);
  console.log('Transaction gas:', txGas.toString());
  
  // Gas used by receipts
  let totalReceiptGas = 0n;
  for (const receipt of receipts_outcome) {
    totalReceiptGas += BigInt(receipt.outcome.gas_burnt);
  }
  console.log('Receipt gas:', totalReceiptGas.toString());
  
  // Total gas
  const totalGas = txGas + totalReceiptGas;
  console.log('Total gas burned:', totalGas.toString());
  
  // Calculate cost in NEAR (1 TGas ≈ 0.0001 NEAR)
  const gasCostNear = Number(totalGas) / 1e12 * 0.0001;
  console.log('Approximate cost:', gasCostNear.toFixed(6), 'NEAR');
}

Handle Action Errors

const result = await client.sendSignedTransaction({
  signedTransaction: signedTx,
});

if (result.ok) {
  const { status } = result.value.rawRpcResult;
  
  if ('Failure' in status && 'ActionError' in status.Failure) {
    const actionError = status.Failure.ActionError;
    
    console.error(`Action #${actionError.index} failed`);
    
    // Handle specific error types
    const { kind } = actionError;
    
    if ('FunctionCallError' in kind) {
      console.error('Function call failed:', kind.FunctionCallError);
    } else if ('AccountAlreadyExists' in kind) {
      console.error('Account already exists:', kind.AccountAlreadyExists);
    } else if ('LackBalanceForState' in kind) {
      console.error('Insufficient balance:', kind.LackBalanceForState);
    } else {
      console.error('Unknown error:', kind);
    }
  }
}

Extract Logs

const result = await client.sendSignedTransaction({
  signedTransaction: signedTx,
});

if (result.ok) {
  const { transaction_outcome, receipts_outcome } = result.value.rawRpcResult;
  
  // Logs from transaction
  console.log('Transaction logs:', transaction_outcome.outcome.logs);
  
  // Logs from receipts
  for (const receipt of receipts_outcome) {
    if (receipt.outcome.logs.length > 0) {
      console.log(`Receipt ${receipt.id} logs:`, receipt.outcome.logs);
    }
  }
}

Track Cross-Contract Calls

const result = await client.sendSignedTransaction({
  signedTransaction: signedTx,
});

if (result.ok) {
  const { receipts_outcome } = result.value.rawRpcResult;
  
  console.log(`Transaction generated ${receipts_outcome.length} receipts`);
  
  for (const [index, receipt] of receipts_outcome.entries()) {
    console.log(`\nReceipt #${index + 1}:`);
    console.log('  ID:', receipt.id);
    console.log('  Block:', receipt.block_hash);
    console.log('  Gas burned:', receipt.outcome.gas_burnt);
    console.log('  Status:', receipt.outcome.status);
    
    if (receipt.outcome.logs.length > 0) {
      console.log('  Logs:', receipt.outcome.logs);
    }
  }
}

Common Error Patterns

Function Call Errors

if ('Failure' in status) {
  const failure = status.Failure;
  
  if ('ActionError' in failure) {
    const { kind } = failure.ActionError;
    
    if ('FunctionCallError' in kind) {
      const fnError = kind.FunctionCallError;
      
      if ('ExecutionError' in fnError) {
        console.error('Contract panic:', fnError.ExecutionError);
      } else if ('MethodResolveError' in fnError) {
        console.error('Method not found:', fnError.MethodResolveError);
      }
    }
  }
}

Insufficient Balance

if ('Failure' in status && 'ActionError' in status.Failure) {
  const { kind } = status.Failure.ActionError;
  
  if ('LackBalanceForState' in kind) {
    const { balance, amount } = kind.LackBalanceForState;
    console.error(
      `Insufficient balance: have ${balance}, need ${amount}`
    );
  }
}

Transaction Finality

The sendSignedTransaction method waits for FINAL status by default:
// Source: packages/near-api-ts/universal/src/client/methods/transaction/sendSignedTransaction/sendSignedTransaction.ts:43
wait_until: 'FINAL'
This means:
  • Transaction is included in a block
  • Block is finalized (irreversible)
  • All receipts are executed
  • Final status is known
Typically takes 2-3 seconds on NEAR.

Notes

  • Transaction status is always available in sendSignedTransaction response
  • No separate “get status” API call is needed
  • Status includes all receipt outcomes (cross-contract calls)
  • Failed transactions still appear on-chain and consume gas
  • Logs and return values are base64-encoded
  • Gas amounts are in gas units (not NEAR)
  • Token amounts are in yoctoNEAR (10^-24 NEAR)