SkillAgentSearch skills...

Solfail

Decode Solana transaction failures with clear explanations, actionable fixes, and confidence scores. CLI, HTTP API, and TypeScript library.

Install / Use

/learn @adityajha2005/Solfail
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

SOLFAIL Banner

SOLFAIL

npm version npm downloads license

Demo Video | Token CA | npm

Decode Solana transaction failures into clear explanations and actionable fixes.

Solfail is a minimal, infra-grade backend for decoding Solana transaction failures with simulateTransaction RPC. It turns raw runtime errors into stable categories, plain-English explanations, and practical next steps for wallets, dApps, monitoring systems, and CI pipelines.

Problem -> Solution

Solana failures are often technically correct but hard to use in product workflows.

Raw RPC responses like:

{"InstructionError":[0,["Custom",6001]]}

do not tell a wallet what to show a user, do not tell a developer what broke, and do not tell infrastructure what to alert on.

Solfail converts those failures into readable diagnostics with:

  • Stable error categories
  • Plain-English explanations
  • Actionable fix suggestions
  • Confidence labels for downstream automation

Quick Example

Input

{"InstructionError":[0,["Custom",6001]]}

Output

{
  "status": "FAILURE_DETECTED",
  "failureCategory": "anchor_constraint_owner",
  "confidence": "high",
  "explanation": "Anchor constraint violation: account owner does not match expected program.",
  "likelyFix": "Verify the account is owned by the correct program or initialize it properly."
}

CLI Demo

npx solfail decode tx.json --devnet

Sample output:

{
  "status": "FAILURE_DETECTED",
  "failureCategory": "missing_signer",
  "confidence": "high",
  "explanation": "A required signer account was not included when submitting the transaction.",
  "likelyFix": "Ensure the missing account signs the transaction before sending.",
  "rawError": "{\"InstructionError\":[0,[\"MissingRequiredSignature\",{}]]}",
  "matchedBy": "errorMessage",
  "mappingSource": "core"
}

Demo Video

Watch the product demo on X:

Solfail demo video

How It Works

Failed Transaction
      ↓
simulateTransaction RPC
      ↓
Solfail Parser
      ↓
Error Mapping Engine
      ↓
Human Explanation + Fix

Why Solfail

  • Improves developer productivity by translating cryptic runtime failures into understandable root causes
  • Designed for infra-grade decoding with stable categories that are safe to depend on programmatically
  • Available as a CLI, HTTP API, and TypeScript library
  • Supports multiple Solana networks for local testing, staging, and production workflows

Use Cases

  • Wallet UX improvements
  • dApp debugging
  • CI/CD transaction validation
  • Blockchain monitoring

Installation

npm install solfail

Or install globally for CLI usage:

npm install -g solfail

Setup

npm install
npm run build
npm start

Or for development:

npm run dev

Quick Start

Option 1: Use as a Library (Recommended for Projects)

// Import the decoder function and types
import { decodeTransactionFailure } from 'solfail';
import type { DecodeRequest, DecodeResponse } from 'solfail';

// In your code
const request: DecodeRequest = {
  transactionBase64: failedTxBase64,
  network: 'devnet',
  strongMode: true
};

const result: DecodeResponse = await decodeTransactionFailure(request);

if (result.status === 'FAILURE_DETECTED') {
  console.log(`Error: ${result.failureCategory}`);
  console.log(`Fix: ${result.likelyFix}`);

  // Use stable category IDs in your logic
  if (result.failureCategory === 'missing_signer') {
    // Handle missing signer
  }
}

Option 2: CLI Tool (Developer Workflow)

# Using signature (fetches from RPC)
echo '{"signature":"2Fnq3DTWf7wQcYCMCbV7L5z9Nxxrvh8kFgTfohmB3z59uyRV4HdmhvNq7AqrWNLhYpvk2kTqJ7dFwPXgkrvk2PUU","network":"devnet"}' | solfail decode --devnet

# Using transaction file
solfail decode tx.json --devnet

# Or with npx (no install needed)
npx solfail decode tx.json --devnet --strong

# Pipe to jq for filtering
solfail decode tx.json | jq '.failureCategory'

Option 3: HTTP API (Microservice)

# Start the server
npm start

# Or run as a service
node dist/index.js

Then call from any language:

# Using transaction signature (fetches from RPC automatically)
curl -X POST http://localhost:3000/decode \
  -H "Content-Type: application/json" \
  -d '{"signature": "2Fnq3DTWf7wQcYCMCbV7L5z9Nxxrvh8kFgTfohmB3z59uyRV4HdmhvNq7AqrWNLhYpvk2kTqJ7dFwPXgkrvk2PUU", "network": "devnet"}'

# Or using base64 transaction
curl -X POST http://localhost:3000/decode \
  -H "Content-Type: application/json" \
  -d '{"transactionBase64": "YOUR_FAILED_TX_BASE64", "network": "devnet"}'

What you get: Instead of cryptic error codes like {"InstructionError": [0, ["Custom", 6001]]}, you get:

  • Clear error category (anchor_constraint_owner)
  • Plain English explanation
  • Actionable fix suggestion
  • Confidence level

Library Usage

Installation

# As a dependency in your project
npm install solfail

# Or globally for CLI usage
npm install -g solfail

1. Use as a TypeScript/JavaScript Library

// Import the decoder function and types
import { decodeTransactionFailure } from 'solfail';
import type { DecodeRequest, DecodeResponse } from 'solfail';

async function handleFailedTransaction(txBase64: string) {
  const request: DecodeRequest = {
    transactionBase64: txBase64,
    network: 'devnet',
    strongMode: true
  };

  const result: DecodeResponse = await decodeTransactionFailure(request);

  if (result.status === 'FAILURE_DETECTED') {
    // Use stable category IDs for conditional logic
    switch (result.failureCategory) {
      case 'missing_signer':
        return showSignerPrompt(result.likelyFix);
      case 'account_not_rent_exempt':
        return showFundingDialog(result.explanation);
      case 'compute_budget_exceeded':
        return suggestOptimization(result.likelyFix);
      default:
        return showGenericError(result.explanation);
    }
  }

  return { success: true };
}

2. In a Wallet Application

import { decodeTransactionFailure } from 'solfail';
import { Connection } from '@solana/web3.js';

async function onTransactionError(signature: string, connection: Connection) {
  // Decode failure directly from signature (fetches transaction automatically)
  const decoded = await decodeTransactionFailure({
    signature: signature,
    network: 'mainnet-beta'
  });

  // Show user-friendly error
  if (decoded.status === 'FAILURE_DETECTED') {
    showErrorToast({
      title: decoded.failureCategory.replace(/_/g, ' '),
      message: decoded.explanation,
      action: decoded.likelyFix
    });
  }
}

3. In a dApp (Frontend)

// React/Next.js example
async function handleTransactionError(txBase64: string) {
  const response = await fetch('http://your-decoder-service:3000/decode', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      transactionBase64: txBase64,
      network: 'devnet'
    })
  });

  const result = await response.json();

  if (result.status === 'FAILURE_DETECTED') {
    // Update UI based on error category
    setError({
      type: result.failureCategory,
      message: result.explanation,
      fix: result.likelyFix,
      confidence: result.confidence
    });
  }
}

Wallet Integration

async function handleTransactionError(failedTx, network = 'mainnet-beta') {
  const response = await fetch('http://localhost:3000/decode', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      transactionBase64: failedTx,
      network: network // 'mainnet-beta', 'testnet', or 'devnet'
    })
  });

  const decoded = await response.json();

  if (decoded.status === 'SIMULATION_OK') {
    return; // No error to handle
  }

  if (decoded.failureCategory === 'missing_signer') {
    // Prompt user to sign with missing account
    return promptSigner(decoded.likelyFix);
  }

  if (decoded.failureCategory === 'account_not_rent_exempt') {
    // Show funding UI
    return showFundingDialog(decoded.explanation);
  }

  // Display user-friendly error
  showError(decoded.explanation, decoded.likelyFix);
}

Example 5: Node.js Backend Service

// Your backend service
import { decodeTransactionFailure } from 'solfail';
import express from 'express';

const app = express();

app.post('/api/transaction/analyze', async (req, res) => {
  const { transactionBase64, network } = req.body;

  try {
    const result = await decodeTransactionFailure({
      transactionBase64,
      network: network || 'mainnet-beta'
    });

    res.json(result);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

CLI Usage

The CLI tool is a thin wrapper around the decoder logic with no duplicated mapping logic.

# Help
npm run cli -- --help

# From file
npm run cli -- -f transaction.json

# From stdin (pipe)
cat tx.json | npm run cli -- --stdin

# Auto-detect stdin when not TTY
echo '{"transactionBase64":"..."}' | npm run cli --

# Network selection (devnet)
npm run cli -- -f tx.json -n devnet

# Network selection (testnet)
npm run cli -- -f tx.json -n testnet

# Custom RPC endpoint for specific network
DEVNET_RPC_URL=https://custom-devnet-rpc.com npm run cli -- -f tx.json -n devnet

# Custom timeout
RPC_TIMEOUT_MS=60000 npm run cli -- -f tx.json

Input Format (JSON file or stdin):

{
  "transactionBase64": "base64EncodedTra

Related Skills

View on GitHub
GitHub Stars4
CategoryDevelopment
Updated23d ago
Forks0

Languages

TypeScript

Security Score

70/100

Audited on Mar 16, 2026

No findings