1.1.0 • Published 7 months ago

@bcoders.gr/abi-codec v1.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

High-Performance ABI Codec

A blazing-fast Node.js module for encoding/decoding Ethereum ABI data compatible with Geth. Optimized for maximum performance with zero-copy Buffer operations.

Features

  • Function encoding/decoding - All Solidity types supported
  • Event log decoding - Individual logs and full receipts
  • Receipt processing - Decode all matching logs from transaction receipts
  • Maximum performance - Direct Buffer operations, minimal hex conversions
  • Geth compatibility - 100% compatible with Ethereum node outputs
  • Minimal dependencies - Only ethers.js utils for keccak256

Installation

npm install

Quick Start

const { ABICodec } = require('./index');

// Your contract ABI
const contractABI = [
  {
    "type": "function",
    "name": "transfer",
    "inputs": [
      {"name": "to", "type": "address"},
      {"name": "amount", "type": "uint256"}
    ],
    "outputs": [{"name": "success", "type": "bool"}]
  },
  {
    "type": "event",
    "name": "Transfer",
    "inputs": [
      {"name": "from", "type": "address", "indexed": true},
      {"name": "to", "type": "address", "indexed": true},
      {"name": "value", "type": "uint256", "indexed": false}
    ]
  }
];

const codec = new ABICodec(contractABI);

API Reference

Function Encoding/Decoding

// Encode function call
const calldata = codec.encodeFunction('transfer', [
  '0x742d35Cc6634C0532925a3b8D8e9eED89B7A6de6',
  BigInt('1000000000000000000')
]);

// Decode function call
const params = codec.decodeFunction('transfer', calldata);
// Returns: ['0x742d35Cc6634C0532925a3b8D8e9eED89B7A6de6', 1000000000000000000n]

// Decode function result
const result = codec.decodeFunctionResult('transfer', '0x0000...0001');
// Returns: [true]

Event Log Decoding

// Decode single event log
const decodedLog = codec.decodeLog(logData, topics, 'Transfer');
// Returns: { name: 'Transfer', args: { from: '0x...', to: '0x...', value: 1000n } }

// Decode all logs from a transaction receipt
const decodedLogs = codec.decodeReceiptLogs(receipt);
// Returns: Array of decoded logs that match ABI events

// Decode multiple receipts at once
const allLogs = codec.decodeMultipleReceipts([receipt1, receipt2, receipt3]);

// Filter logs by event name
const transferLogs = codec.filterLogsByEvent(decodedLogs, 'Transfer');

Utility Functions

// Get function selector (4-byte signature)
const selector = codec.getFunctionSelector('transfer');
// Returns: '0xa9059cbb'

// Get event selector (32-byte topic hash)
const eventTopic = codec.getEventSelector('Transfer');
// Returns: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'

// Get all event topics this codec can decode
const knownTopics = codec.getKnownEventTopics();
// Returns: ['0xddf252...', '0x8c5be1...', ...]

Supported Types

Solidity TypeSupportedNotes
uint8 to uint256Including uint (defaults to uint256)
int8 to int256Including int (defaults to int256)
bool
address
bytes1 to bytes32Fixed-size byte arrays
bytesDynamic byte arrays
stringUTF-8 encoded
uint256[]Dynamic arrays
uint256[5]Fixed-size arrays
tuple🔄Coming soon (structs)

Performance

Benchmarked on typical hardware:

  • 10,000 function encodings: ~96ms (0.0096ms per encoding)
  • 1,000 receipt decodings: ~12ms (0.012ms per receipt)
  • Zero-copy operations where possible for maximum speed

Real-World Usage

Processing Transaction Receipts

// Process multiple transaction receipts
function processTransactions(receipts, codec) {
  const results = {
    totalLogs: 0,
    decodedLogs: 0,
    events: {}
  };
  
  for (const receipt of receipts) {
    results.totalLogs += receipt.logs?.length || 0;
    
    const decoded = codec.decodeReceiptLogs(receipt);
    results.decodedLogs += decoded.length;
    
    // Count events by type
    decoded.forEach(log => {
      results.events[log.name] = (results.events[log.name] || 0) + 1;
    });
  }
  
  return results;
}

const stats = processTransactions(receipts, codec);
console.log(\`Decoded \${stats.decodedLogs}/\${stats.totalLogs} logs\`);

Event Filtering and Analysis

// Get all Transfer events from multiple receipts
const allLogs = codec.decodeMultipleReceipts(receipts);
const transfers = codec.filterLogsByEvent(allLogs, 'Transfer');

// Analyze transfer patterns
const transferAnalysis = transfers.map(log => ({
  from: log.args.from,
  to: log.args.to,
  amount: log.args.value,
  blockNumber: log.blockNumber,
  txHash: log.transactionHash
}));

Error Handling

The codec throws descriptive errors for invalid inputs:

try {
  const result = codec.encodeFunction('unknownFunction', []);
} catch (error) {
  console.error('Function not found:', error.message);
}

try {
  const result = codec.decodeReceiptLogs(invalidReceipt);
} catch (error) {
  console.error('Invalid receipt format:', error.message);
}

Testing

Run the test suite:

# Basic functionality tests
node test/basic.test.js

# Receipt decoding tests  
node test/receipt.test.js

# Usage examples
node example.js
node receipt-example.js

License

MIT

Contributing

This module is optimized for performance. When contributing:

  1. Maintain zero-copy Buffer operations where possible
  2. Avoid unnecessary hex string conversions
  3. Pre-compile and cache expensive operations
  4. Add performance benchmarks for new features

Built for maximum performance with Ethereum/Geth compatibility in mind. 🚀