Skip to main content
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,
        transaction_name: None,
        metadata: Some(ChainMetadata {
            metadata: Some(Metadata::Ethereum(EthereumMetadata {
                network_id: Some("1".to_string()), // Ethereum Mainnet
                abi: None,
            })),
        }),
        developer_config: Some(DeveloperConfig {
            allow_signed_transactions: true,
        }),
        abi_registry: None,
    };

    // 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::sync::Arc;
use visualsign_ethereum::abi_registry::AbiRegistry;
use visualsign_ethereum::embedded_abis::load_and_map_abi;

// Create an ABI registry
let mut abi_registry = AbiRegistry::new();

// Load an ABI from a JSON file and map it to a contract address
load_and_map_abi(
    &mut abi_registry,
    "MyContract",              // Name for the ABI
    "/path/to/abi.json",       // Path to ABI JSON file
    1,                         // Chain ID
    "0x1234...abcd",           // Contract address
).expect("Failed to load ABI");

// Use the registry in options
let options = VisualSignOptions {
    // ... other options
    abi_registry: Some(Arc::new(abi_registry)),
    ..Default::default()
};

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")?;

// 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