npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rsksmart/rsk-contract-parser

v2.2.4

Published

A tool to parse/interact with contracts and decode events from the Rootstock blockchain.

Readme

RSK-contract-parser

NodeJS module to interact with smart contracts and native RSK contracts.

Overview

rsk-contract-parser is a comprehensive tool for parsing, analyzing, and interacting with smart contracts on the Rootstock (RSK) blockchain. It provides functionalities for decoding contract methods, events, and identifying contract interfaces (such as ERC standards), with special support for RSK native contracts.

Features

  • Contract Analysis: Identify implemented ERC standards and interface support
  • Event Decoding: Parse and decode event logs from transactions
  • Proxy Detection: Identify and analyze proxy patterns
  • Method Decoding: Decode contract method calls from transaction data
  • RSK Native Contracts: Special handling for RSK-specific contracts and event formats
  • Blockchain Interaction: Easy contract interaction through the included Contract class

Requirements

  • Node.js >= 20

Installation

npm install @rsksmart/rsk-contract-parser

Usage

Creating a ContractParser instance

The ContractParser class is the main class. It can be used to parse contracts, decode events, and interact with contracts on the blockchain by instantiating Contract instances.

import { ContractParser, createRskNodeProvider } from '@rsksmart/rsk-contract-parser';

// You can use the default provider (public rsk nodes)
const nod3 = createRskNodeProvider('testnet');
const parser = new ContractParser({ nod3 });

Note: If an abi is not provided, ContractParser will use a default one that covers most standards. However, it's strongly recommended to provide the contract's ABI to fully allow contract interactions and events decoding.

Working with Token Contracts

You can use the ContractParser class to retrieve default token data from a contract:

import { ContractParser, createRskNodeProvider } from '@rsksmart/rsk-contract-parser';

const nod3 = createRskNodeProvider('mainnet');
const parser = new ContractParser({ nod3 });

const tokenAddress = '0x3A15461d8aE0F0Fb5Fa2629e9DA7D66A794a6e37'; // USDRIF on Mainnet
const blockNumber = 7376491;

// Set the contract instance for the parser using the current set ABI
const contract = parser.makeContract(tokenAddress);

// Call contract methods
const name = await contract.call('name', [], { blockNumber }); // 'RIF US Dollar'
const symbol = await contract.call('symbol', [], { blockNumber }); // 'USDRIF'
const decimals = await contract.call('decimals', [], { blockNumber }); // 18
const totalSupply = await contract.call('totalSupply', [], { blockNumber }); // BigInt('0xhexValue')

// parser.getDefaultTokenData() can also be used to retrieve the default token data at a specific block
const tokenData = await parser.getDefaultTokenData(contract, blockNumber);
console.log(tokenData);

Result:

{
  name: 'RIF US Dollar',
  symbol: 'USDRIF',
  decimals: 18,
  totalSupply: BigInt('0xhexValue')
}

parser.makeContract() method returns a Contract instance. You can use it directly like in the following example:

import { Contract, createRskNodeProvider } from '@rsksmart/rsk-contract-parser';

const nod3 = createRskNodeProvider('mainnet');

const abi = undefined; // Not required. Default parser ABI already supports ERC20 interface.
const address = '0x3A15461d8aE0F0Fb5Fa2629e9DA7D66A794a6e37'; // USDRIF on Mainnet

const contract = new Contract(abi, { address, nod3 });

// Call contract methods. Methods without params can skip the params argument
const name = await contract.call('name'); // 'RIF US Dollar'
const symbol = await contract.call('symbol'); // 'USDRIF'
const decimals = await contract.call('decimals'); // 18
const totalSupply = await contract.call('totalSupply'); // BigInt('0xhexValue')

// with params...
const params = ['0xaddress'];
const balance = await contract.call('balanceOf', params); // BigInt('0xhexValue')

// with specific call options...
const options = {
  txData: {},
  blockNumber: 'latest'
}

const balance = await contract.call('balanceOf', params, options); // BigInt('0xhexValue')

Analyzing Contract Details

The ContractParser class also allows to get detailed information about a contract:

import { ContractParser, createRskNodeProvider } from '@rsksmart/rsk-contract-parser';

const nod3 = createRskNodeProvider('mainnet');
const parser = new ContractParser({ nod3 });

const contractAddress = '0x3A15461d8aE0F0Fb5Fa2629e9DA7D66A794a6e37'; // USDRIF on Mainnet

// Get contract details for latest block
const contractDetails = await parser.getContractDetails(contractAddress);
console.log(contractDetails);

Result:

{
  address: '0x3A15461d8aE0F0Fb5Fa2629e9DA7D66A794a6e37',
  isProxy: true,
  implementationAddress: '0xabb96fc7d16bbbae444e913cc6729694a4a4d69f',
  beaconAddress: null,
  proxyType: 'ERC1967 Normal',
  methods: [
    'allowance(address,address)',
    'approve(address,uint256)',
    'balanceOf(address)',
    'decimals()',
    'decreaseAllowance(address,uint256)',
    'increaseAllowance(address,uint256)',
    'mint(address,uint256)',
    'name()',
    'symbol()',
    'totalSupply()',
    'transfer(address,uint256)',
    'transferFrom(address,address,uint256)',
    'supportsInterface(bytes4)',
    'burn(address,uint256)'
  ],
  interfaces: [ 'ERC20', 'ERC165', 'ERC1967' ]
}

Note: It is recommended to set the verified ABI to retrieve the full contract details (in case of proxies, the implementation contract ABI). Using USDRIF verified abi, the result will be something like this:

{
  address: '0x3A15461d8aE0F0Fb5Fa2629e9DA7D66A794a6e37',
  isProxy: true,
  implementationAddress: '0xabb96fc7d16bbbae444e913cc6729694a4a4d69f',
  beaconAddress: null,
  proxyType: 'ERC1967 Normal',
  methods: [
      'DEFAULT_ADMIN_ROLE()',
      'allowance(address,address)',
      'approve(address,uint256)',
      'balanceOf(address)',
      'burn(address,uint256)',
      'changeGovernor(address)',
      'decimals()',
      'decreaseAllowance(address,uint256)',
      'getRoleAdmin(bytes32)',
      'getRoleMember(bytes32,uint256)',
      'getRoleMemberCount(bytes32)',
      'governor()',
      'grantRole(bytes32,address)',
      'hasRole(bytes32,address)',
      'increaseAllowance(address,uint256)',
      'initialize(string,string,address,address)',
      'mint(address,uint256)',
      'name()',
      'proxiableUUID()',
      'renounceRole(bytes32,address)',
      'revokeRole(bytes32,address)',
      'supportsInterface(bytes4)',
      'symbol()',
      'totalSupply()',
      'transfer(address,uint256)',
      'transferAllRoles(address)',
      'transferFrom(address,address,uint256)',
      'upgradeTo(address)',
      'upgradeToAndCall(address,bytes)'
    ],
  interfaces: [ 'ERC20', 'ERC165', 'ERC1967' ]
}

You can also retrieve the contract details at a specific block number:

const contractDetails = await parser.getContractDetails(contractAddress, 100);

Result:

{
  address: '0x3A15461d8aE0F0Fb5Fa2629e9DA7D66A794a6e37',
  isProxy: false,
  implementationAddress: null,
  beaconAddress: null,
  proxyType: null,
  methods: [],
  interfaces: []
}

Working with Native Contracts

The ContractParser class allows interaction with Rootstock native contracts like the Bridge and Remasc.

import {
  ContractParser,
  getRskReleaseByBlockNumber,
  RSK_RELEASES,
  createRskNodeProvider,
  publicRskNodeUrls
} from '@rsksmart/rsk-contract-parser';

const network = 'mainnet';
const nod3 = createRskNodeProvider(network);
const initConfig = {
  net: {
    id: '30' // '30' for RSK Mainnet, '31' for RSK Testnet
  }
}

const parser = new ContractParser({ nod3, initConfig });

// Get RSK native contract addresses (both networks)
const bridgeAddress = parser.getNativeContractAddress('bridge'); // '0x0000000000000000000000000000000001000006'
const remascAddress = parser.getNativeContractAddress('remasc'); // '0x0000000000000000000000000000000001000008'

// To interact with the bridge and decode its events, we need to get the correct rsk release for the specified block and network, which contains the proper bridge ABI
const bridgeRelease = getRskReleaseByBlockNumber(7338024, network);

// Each network has its own RSK releases values.
console.log(RSK_RELEASES[network]);

Bridge specific

You can retrieve the latest bridge ABI and methods supported by the parser like the following:

import { getLatestBridgeMethods, getLatestBridgeAbi } from '@rsksmart/rsk-contract-parser';

const bridgeAbi = getLatestBridgeAbi();
const bridgeMethods = getLatestBridgeMethods();

Another way to do this is by retrieving the latest rsk release using the getRskReleaseByBlockNumber method:

import { getRskReleaseByBlockNumber } from '@rsksmart/rsk-contract-parser';

const latestRskRelease = getRskReleaseByBlockNumber('latest', 'mainnet');
console.log(latestRskRelease);

Result:

{
  name // <rsk-release-name>,
  height // <activation-block-number>,
  abi // <bridge-abi>
}

Parsing Transaction Logs

The ContractParser class allows to parse transaction logs.

import { ContractParser, createRskNodeProvider } from '@rsksmart/rsk-contract-parser';

const nod3 = createRskNodeProvider('mainnet');
const parser = new ContractParser({ nod3 });

// Transaction receipt
const txReceipt = await nod3.eth.getTransactionReceipt('0xTransactionHash');

// Parse transaction logs from a transaction using the current set ABI
const events = parser.parseTxLogs(txReceipt.logs);

Example

For mainnet tx 0x833ff7250b7b6f0d1e0e048bdf0417af16ea6e0dd5e22929da12d9ea9a68cbff, we have the following log:

{
  logIndex: 0,
  blockNumber: 7389136,
  blockHash: '0x304f91fe91075cf228bf6365cd54e147836b5b1cd56e253d7d928a36b3edb851',
  transactionHash: '0x833ff7250b7b6f0d1e0e048bdf0417af16ea6e0dd5e22929da12d9ea9a68cbff',
  transactionIndex: 3,
  address: '0x2acc95758f8b5f583470ba265eb685a8f45fc9d5',
  data: '0x000000000000000000000000000000000000000000000659a719ccc43e100000',
  topics: [
    '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
    '0x0000000000000000000000007ef673bedb238526168c44885797d117921c66cc',
    '0x000000000000000000000000804c44cec51b24e9f20447f8d21ba153403280d1'
  ]
}

After parsing the log, the result would be:

{
  logIndex: 0,
  blockNumber: 7389136,
  blockHash: '0x304f91fe91075cf228bf6365cd54e147836b5b1cd56e253d7d928a36b3edb851',
  transactionHash: '0x833ff7250b7b6f0d1e0e048bdf0417af16ea6e0dd5e22929da12d9ea9a68cbff',
  transactionIndex: 3,
  address: '0x2acc95758f8b5f583470ba265eb685a8f45fc9d5',
  data: '0x000000000000000000000000000000000000000000000659a719ccc43e100000',
  topics: [
    '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
    '0x0000000000000000000000007ef673bedb238526168c44885797d117921c66cc',
    '0x000000000000000000000000804c44cec51b24e9f20447f8d21ba153403280d1'
  ],
  // Event signature. It's always the first log topic.
  // This value can also be used to construct the method selector, in this case: `0xddf252ad`
  signature: 'ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
  // Event name
  event: 'Transfer',
  // Event arguments
  args: [
    '0x7ef673bedb238526168c44885797d117921c66cc',
    '0x804c44cec51b24e9f20447f8d21ba153403280d1',
    '0x0659a719ccc43e100000'
  ],
  // abi fragment that decodes this event
  abi: {
    type: 'event',
    anonymous: false,
    name: 'Transfer',
    inputs: [
      { type: 'address', name: 'from', indexed: true },
      { type: 'address', name: 'to', indexed: true },
      { type: 'uint256', name: 'value', indexed: false }
    ]
  },
  // involved addresses in the event
  _addresses: [
    '0x7ef673bedb238526168c44885797d117921c66cc',
    '0x804c44cec51b24e9f20447f8d21ba153403280d1'
  ]
}

Blockchain searches

The BcSearch class allows to search specific data on the blockchain.

Deployments:

import { BcSearch, createRskNodeProvider } from '@rsksmart/rsk-contract-parser';

const nod3 = createRskNodeProvider('mainnet');

// Initialize blockchain search helper
const bcSearch = BcSearch(nod3);

// Get deployment tx for a contract
const contractAddress = '0x3A15461d8aE0F0Fb5Fa2629e9DA7D66A794a6e37'; // USDRIF
const deployment = await bcSearch.deploymentTx(contractAddress);