0.0
No release in over 3 years
A small, focused Ruby library for encoding and decoding Cardano Bech32 identifiers. The gem intentionally limits its scope to specification-compliant Bech32 handling and avoids higher-level ledger or transaction concerns.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 3.13

Runtime

~> 1.5.0
 Project Readme

cardano-bech32

A small, focused Ruby library for encoding and decoding Cardano Bech32 identifiers. This gem deliberately avoids higher-level ledger concerns and focuses solely on specification-compliant Bech32 handling.

Supported Identifiers

  • Governance CIP-0129
    • GovAction IDs
    • DRep IDs
    • CC hot/cold
  • Addresses
    • Base Address
    • Enterprise Address
    • Pointer Address
    • Stake Address
  • Stake Pool IDs

The API is designed to grow conservatively as additional Cardano Improvement Proposals (CIPs) are implemented.

Installation

Add to your Gemfile:

gem "cardano-bech32"

And then execute:

bundle install

Or install directly:

gem install cardano-bech32

Usage

Governance Credentials (CIP-0129)

Cardano governance identifiers defined in CIP-0129 are Bech32-encoded binary payloads used throughout on-chain governance.

This library supports all CIP-0129 governance identifiers, including:

  • Constitutional Committee credentials (hot & cold)
  • DRep credentials
  • Governance Action IDs

Constitutional Committee & DRep Credentials

Governance credentials consist of:

header (1 byte) || credential hash (N bytes)

The header byte is authoritative and encodes:

  • Credential type (CC Hot, CC Cold, DRep)
  • Key type (key hash or script hash)

The HRP is derived from the header and validated during decoding.

Decode a governance credential

require "cardano/bech32"

cred = Cardano::Bech32::GovCredentials.decode(
  "cc_cold1zvqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6kflvs"
)

cred.credential      # => :cc_cold
cred.hash_bytes      # => [0, 0, 0, ...]
cred.header_byte     # => 19
cred.hrp             # => "cc_cold"
cred.key_type        # => :script
cred.payload_bytes   # => [19, 0, 0, ...]
cred.payload_hex     # => "1300000000..."

The returned object is one of:

  • Cardano::Bech32::GovCredentials::Cc
  • Cardano::Bech32::GovCredentials::Drep

Both inherit from AbstractCredential and expose a uniform interface.

Encode a governance credential

payload_hex = "130000000000000000000000000000000000000000000000000000000000"

bech32 = Cardano::Bech32::GovCredentials.encode(payload_hex)
# => "cc_cold1zvqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6kflvs"

The encoder:

  • Accepts raw bytes or hex
  • Infers HRP from the header byte

Governance Action IDs

Governance Action IDs identify a governance action on-chain and consist of:

tx_id (32 bytes) || index (1 byte)

They are encoded as Bech32 using HRP gov_action.

require "cardano/bech32"

txref = "b2a591ac219ce6dcca5847e0248015209c7cb0436aa6bd6863d0c1f152a60bc5#0"
bech32 = Cardano::Bech32::GovAction.encode(txref)
# => "gov_action1k2jertppnnndejjcglszfqq4yzw8evzrd2nt66rr6rqlz54xp0zsq05ecsn"

gov_action = Cardano::Bech32::GovAction.decode(bech32)
gov_action.tx_id          # => "b2a591ac219ce6dcca5847e0248015209c7cb0436aa6bd6863d0c1f152a60bc5"
gov_action.index          # => 0
gov_action.payload_bytes  # => [178, 165, 145, 172, ...]
gov_action.hrp            # => "gov_action"

Cardano::Bech32::GovAction.valid?(bech32)
# => true

All decoding/validation failures for GovAction raise explicit, typed errors:

  • Cardano::Bech32::GovAction::InvalidFormat — malformed input, wrong HRP, invalid Bech32
  • Cardano::Bech32::GovAction::InvalidPayload — incorrect payload length, invalid index
begin
  Cardano::Bech32::GovAction.decode("invalid")
rescue Cardano::Bech32::GovAction::InvalidFormat,
       Cardano::Bech32::GovAction::InvalidPayload => e
  puts e.message
end

Stake Pool IDs

Stake Pool IDs are Bech32-encoded 28-byte hashes identifying a registered stake pool.

pool_hash = "6e90911fdb579e203f556f3f24aca5b8714be049ccf716008ab849fd"
Cardano::Bech32::StakePool.encode(pool_hash)
# => pool1d6gfz87m270zq064duljft99hpc5hczfenm3vqy2hpyl67tteq9

pool_id = "pool1d6gfz87m270zq064duljft99hpc5hczfenm3vqy2hpyl67tteq9"
Cardano::Bech32::StakePool.decode(pool_id)
# => { bytes: "\x8C\xB8\...", hex: "6e90911..." }

Cardano::Bech32::StakePool.valid?(pool_id)
# => true

Addresses

# Decode a Cardano Address
addr_bech32 = "addr1qx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3n0d3vllmyqwsx5wktcd8cc3sq835lu7drv2xwl2wywfgse35a3x"
address = CardanoBech32::Address.decode(addr_bech32)

address.address_type         # => :base, :stake, :pointer, or :enterprise
address.payment_credential   # => :key or :script (nil for stake/pointer-only addresses)
address.stake_credential     # => :key or :script (nil if not applicable)
address.network              # => network string derived from HRP

Bech32 and Cardano Addresses

Some Bech32 libraries may report the variant incorrectly (Bech32 / Bech32m), but for Cardano this does not affect validity.

This library validates addresses based on:

  • The HRP (addr, addr_test, stake, etc.)
  • The header byte
  • The network id encoded in the payload

Checksum and payload parsing are fully specification-compliant.

Development

After checking out the repo:

bin/setup       # install dependencies
rake spec       # run tests
bin/console     # interactive console

To install locally:

bundle exec rake install

To release a new version:

# update version.rb
bundle exec rake release

This creates a git tag, pushes commits, and uploads the gem to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/lacepool/cardano-bech32. Please follow the code of conduct.

License

The gem is available as open source under the terms of the MIT License.