Skip to main content

Documentation Index

Fetch the complete documentation index at: https://visualsign.dev/llms.txt

Use this file to discover all available pages before exploring further.

Embed VisualSign parsing directly in your application without network calls. The parser is available as Rust crates that can be compiled into your application.

When to use library integration

Library integration is ideal when:
  • You’re building a Rust application (CLI tool, backend service)
  • Parsing should happen without external service dependencies
  • Network latency is unacceptable
  • You want the smallest deployment footprint

Trade-offs

AdvantageConsideration
No network latencyNo attestation (trust your process)
Works offlineLarger binary size
Simpler deploymentUpdates require app releases

Rust integration

Dependencies

Add the required crates to your Cargo.toml. The parser_app crate provides the full parser registry with all chain support:
[dependencies]
parser_app = { git = "https://github.com/anchorageoss/visualsign-parser", package = "parser_app" }
visualsign = { git = "https://github.com/anchorageoss/visualsign-parser", package = "visualsign" }
generated = { git = "https://github.com/anchorageoss/visualsign-parser", package = "generated" }

Basic usage

use parser_app::registry::create_registry;
use visualsign::registry::Chain;
use visualsign::vsptrait::{VisualSignOptions, DeveloperConfig};
use generated::parser::{ChainMetadata, EthereumMetadata, chain_metadata::Metadata};

fn main() {
    // Create the parser registry (includes all supported chains)
    let registry = create_registry();

    // Raw transaction hex (with or without 0x prefix)
    // This is a complete EIP-1559 transaction
    let raw_tx = "0x02f901..."; // Your full transaction hex

    // Configure parsing options
    let options = VisualSignOptions {
        decode_transfers: true,
        metadata: Some(ChainMetadata {
            metadata: Some(Metadata::Ethereum(EthereumMetadata {
                network_id: Some("ETHEREUM_MAINNET".to_string()), // Ethereum Mainnet
                abi: None,
                abi_mappings: Default::default(),
            })),
        }),
        developer_config: Some(DeveloperConfig {
            allow_signed_transactions: true,
        }),
        ..Default::default()
    };

    // Parse the transaction
    match registry.convert_transaction(&Chain::Ethereum, raw_tx, options) {
        Ok(payload) => {
            println!("Title: {}", payload.title);
            println!("Fields: {:?}", payload.fields);
        }
        Err(e) => eprintln!("Parse error: {:?}", e),
    }
}

Working with the SignablePayload

The parser returns a SignablePayload containing structured fields:
use visualsign::{SignablePayload, SignablePayloadField};

fn display_payload(payload: &SignablePayload) {
    println!("Transaction: {}", payload.title);

    if let Some(subtitle) = &payload.subtitle {
        println!("  {}", subtitle);
    }

    for field in &payload.fields {
        match field {
            SignablePayloadField::TextV2 { common, text_v2 } => {
                println!("  {}: {}", common.label, text_v2.text);
            }
            SignablePayloadField::AmountV2 { common, amount_v2 } => {
                println!("  {}: {} {}",
                    common.label,
                    amount_v2.amount,
                    amount_v2.abbreviation.as_deref().unwrap_or("")
                );
            }
            SignablePayloadField::AddressV2 { common, address_v2 } => {
                println!("  {}: {}", common.label, address_v2.address);
            }
            _ => {
                // Handle other field types as needed
            }
        }
    }
}

Supported chains

The registry includes parsers for:
  • Ethereum — Mainnet and L2s (Arbitrum, Optimism, Base, Polygon)
  • Solana — With IDL support for program parsing
  • Sui — Move-based transactions
  • Tron — TRC-20 and smart contracts
Use the Chain enum to specify which parser to use:
use visualsign::registry::Chain;

let chain = Chain::Ethereum;  // or Chain::Solana, Chain::Sui, Chain::Tron

Adding custom ABIs (Ethereum)

For Ethereum transactions, you can provide custom ABIs to improve parsing of unrecognized contracts:
use std::collections::HashMap;
use generated::parser::{Abi, ChainMetadata, EthereumMetadata, chain_metadata::Metadata};

// Load ABI JSON from file
let abi_json = std::fs::read_to_string("/path/to/abi.json")
    .expect("failed to read ABI file");

// Create ABI mapping keyed by contract address
let mut abi_mappings = HashMap::new();
abi_mappings.insert(
    "0xdAC17F958D2ee523a2206206994597C13D831ec7".to_string(), // Replace with your contract address
    Abi {
        value: abi_json,
        signature: None, // Optional: include signature for validation
    },
);

let options = VisualSignOptions {
    metadata: Some(ChainMetadata {
        metadata: Some(Metadata::Ethereum(EthereumMetadata {
            network_id: Some("ETHEREUM_MAINNET".to_string()),
            abi: None,
            abi_mappings,
        })),
    }),
    ..Default::default()
};

// Parse using the standard registry — ABIs are extracted from metadata automatically
let registry = create_registry();
let payload = registry.convert_transaction(&Chain::Ethereum, raw_tx, options)
    .expect("failed to parse transaction");

Adding custom IDLs (Solana)

For Solana transactions, provide Anchor IDLs to parse program instructions:
use std::collections::HashMap;
use generated::parser::{ChainMetadata, SolanaMetadata, Idl, SolanaIdlType, chain_metadata::Metadata};

// Load IDL JSON from file
let idl_json = std::fs::read_to_string("/path/to/idl.json")
    .expect("failed to read IDL file");

// Create IDL mapping
let mut idl_mappings = HashMap::new();
idl_mappings.insert(
    "YourProgramId1111111111111111111111111111111".to_string(),
    Idl {
        value: idl_json,
        idl_type: Some(SolanaIdlType::Anchor as i32),
        idl_version: None,
        signature: None,
        program_name: Some("MyProgram".to_string()),
    },
);

let options = VisualSignOptions {
    metadata: Some(ChainMetadata {
        metadata: Some(Metadata::Solana(SolanaMetadata {
            network_id: None,
            idl: None,
            idl_mappings,
        })),
    }),
    ..Default::default()
};

Testing your integration

Use the CLI to verify expected output before integrating:
# From the src/ directory
cargo run --bin parser_cli --release -- \
  --chain ethereum \
  --network ETHEREUM_MAINNET \
  --output json \
  -t "0x02f901..."
Compare the CLI’s JSON output with your integration to ensure consistent parsing.

Complete example

A working example that demonstrates library integration is available in the repository: Run it with:
# From the src/ directory
cargo run -p library_integration_test

Next steps