Thank you for your interest in contributing to the Initia Transaction Decoder! This document will help you get started with development and understand our contribution process.
Prerequisites: Node.js 20+, pnpm
git clone https://github.com/initia-labs/tx-decoder.git
cd tx-decoder
pnpm install# Testing
pnpm test # Run all tests
pnpm test src/tests/specific.test.ts # Run specific test
# Code Quality
pnpm typecheck # TypeScript check
pnpm lint # ESLint with auto-fix
pnpm build # Build library with tsup
# Development Workflow
pnpm clean # Clean build artifacts
pnpm prepare # Setup git hooksThe tx-decoder is organized into several key directories:
src/decoder.ts: Main decoder orchestration and transaction processing logicsrc/decoder-registry.ts: Registry for managing and routing message decoderssrc/balance-changes.ts: Core balance change calculation logicsrc/metadata-resolver.ts: Resolves metadata for tokens and denomssrc/message-types.ts: Supported message type definitionssrc/validation.ts: Transaction and message validation utilities
Message type decoders transform raw transaction messages into normalized formats:
src/decoders/cosmos/: Cosmos SDK message decodersbank.ts- Bank transfersdistribution.ts- Reward distributionmstaking.ts- Multi-token staking operationsmove/: Move script decoders (DEX, liquidity, NFT, etc.)
src/decoders/ethereum/: Ethereum transaction decoderssrc/decoders/protocols/: Cross-chain protocol decoders
Balance change processors extract balance changes from transaction events:
src/processors/move/: Move event processorsmint.ts,burn.ts,deposit.ts,withdraw.ts,object-transfer.ts
src/processors/evm/: EVM event processorstransfer.ts- ERC20/ERC721 transfer events
src/processors/wasm/: WASM contract event processors
src/interfaces/: TypeScript interfaces and type definitionscosmos.ts- Cosmos message typesethereum.ts- Ethereum transaction typesbalance-changes.ts- Balance change typesdecoder.ts- Decoder interface definitionsmetadata.ts- Metadata type definitionsprocessor.ts- Processor interface definitions
src/schema/: Zod schemas for runtime validationcosmos/: Cosmos message schemasethereum/: Ethereum transaction schemasprotocols/: Protocol-specific schemasapi/: API response schemas
src/utils/: Common utility functionsdenom.ts- Denomination handling and conversioncoins.ts- Coin amount utilitiesmerge-balances.ts- Balance merging logicfind-attributes.ts,find-move-events.ts- Event extraction helpersattach-tx-logs.ts- Transaction log processingdecoder-helpers.ts- Decoder utility functions
src/constants/: Project-wide constantsevm-abis.ts- EVM contract ABIsmodule-addresses.ts- Module address mappingsbalance-changes.ts- Balance change constants
src/api/: External API client and service integrationsapi.ts- Main API clientservices/: API service implementations
src/tests/: Comprehensive test suite with real transaction fixturescosmos/: Cosmos transaction testsethereum/: Ethereum transaction testserc20/,erc721/: Token testscontract-creation/: Contract deployment testscosmos-mirror/: Cosmos-EVM mirror tests
protocols/: Cross-chain protocol tests_shared/helpers/: Shared test utilities and initialization
Adding a decoder for a new message type is the most common way to contribute. Here's how to do it:
Find a real transaction containing the message you want to support. Add the JSON response for that transaction to a new file in the appropriate test directory, next to where you'll create your test file. Using real data is crucial for accurate testing.
Examples:
src/tests/cosmos/move/bank.fixture.ts(for simple cases)src/tests/cosmos/move/dex/swap.fixture.ts(for grouped features)
If the message has a unique type URL (e.g., "/initia.mstaking.v1.MsgDelegate"), add it to the SUPPORTED_MESSAGE_TYPES array in src/message-types.ts.
Note: You can skip this step for generic messages like Move scripts, which are identified by their function name instead of the message type URL.
Create a new file in the /src/decoders directory for your message. A decoder is an object that contains two functions:
check(message, log): Returnstrueif the decoder should handle the message. It typically checks the message's@typebut may also validate its structure for complex cases.decode(message, log, apiClient): Transforms a raw message into a normalizedDecodedMessage. This function validates the message, extracts data, and returns a promise that resolves with the result.
See existing decoders in /src/decoders for examples of how to implement both check and decode functions.
Validation: Define a Zod schema for your message's expected structure in the /src/schema directory. This ensures the data is valid before processing.
Interfaces: Add or update TypeScript interfaces in /src/interfaces if your new message introduces new data shapes.
In src/decoder.ts, import your new decoder function and add it to the list of handlers. The TxDecoder will now use it when it encounters the corresponding message type.
Create a new test file in the appropriate /src/tests subdirectory, next to the fixture you created in step 1. Import the fixture and write a test case that asserts:
- The
decodedMessageoutput matches the expected format. - The
balanceChangesare calculated correctly.
Examples:
src/tests/cosmos/move/bank.test.ts(for simple cases)src/tests/cosmos/move/dex/swap.test.ts(for grouped features)
- Type Safety: Strong TypeScript types with proper interfaces
- Validation: Use Zod schemas for runtime validation
- Real Data: Always use real transaction data for testing
- Modularity: Keep decoders focused and single-purpose
- Error Handling: Graceful handling of edge cases and invalid data
- Use ESLint and Prettier (configured via
eslint.config.mjs) - Follow TypeScript best practices
- Write descriptive test names
- Use conventional commit messages
- Comprehensive test coverage for new functionality
- Test edge cases and error conditions
- Use real transaction fixtures
- Deterministic tests with descriptive names
-
Branch: Create a feature branch
git checkout -b feat/new-message-type # or git checkout -b fix/bug-description -
Develop: Follow coding standards, add tests, update docs
-
Commit: Use conventional commit format
feat:New features (new message types, decoders)fix:Bug fixesdocs:Documentation updatestest:Test additions or improvementsrefactor:Code refactoringchore:Maintenance tasks
-
Validate: Run all checks before submitting
pnpm typecheck && pnpm lint && pnpm test && pnpm build
-
Pull Request: Create PR against
mainwith:- Clear description of changes
- Reference to any related issues
- Test results showing all tests pass
If you have questions or need help:
- Check existing decoders and tests for examples
- Review the README for detailed implementation guides
- Open an issue for questions or bug reports
Thank you for contributing to the Initia Transaction Decoder! 🚀