Skip to content

Conversation

@KINGH242
Copy link
Contributor

This pull request introduces enhanced support for Bech32 encoding/decoding for representing DRep credentials, committee credentials, pool operators, and governance action IDs. These changes also include support for both CIP105 and CIP129 variations.

Governance and DRep credential improvements:

  • Added new classes: GovernanceCredential and GovernanceKeyType, with support for Bech32 encoding/decoding, hex representation, and credential type identification. Also updated DRepCredential to inherit from GovernanceCredential. [1] [2]
  • Enhanced the DRep class with methods for encoding/decoding DRep IDs in Bech32 and hex formats, and improved error handling. [1] [2]

Governance action and committee credential enhancements:

  • Added CommitteeHotCredential and updated CommitteeColdCredential to inherit from GovernanceCredential, supporting Bech32 encoding. [1] [2]
  • Implemented encoding/decoding methods for GovActionId, allowing Bech32 and hex representations for governance action IDs.

Pool operator improvements:

  • Introduced the PoolOperator class with Bech32 encoding/decoding, hex representation, and primitive conversion methods for pool key hashes. [1] [2]

Supporting changes:

  • Added constant for CIP129_PAYLOAD_SIZE to support new credential formats. [1] [2]
  • Updated imports and error handling throughout affected files. [1] [2] [3] [4]

@codecov
Copy link

codecov bot commented Nov 29, 2025

Codecov Report

❌ Patch coverage is 90.00000% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.61%. Comparing base (2fa3213) to head (371c5c8).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
pycardano/certificate.py 90.19% 4 Missing and 6 partials ⚠️
pycardano/governance.py 80.00% 4 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #473      +/-   ##
==========================================
- Coverage   90.65%   90.61%   -0.05%     
==========================================
  Files          33       33              
  Lines        5007     5155     +148     
  Branches      758      782      +24     
==========================================
+ Hits         4539     4671     +132     
- Misses        297      305       +8     
- Partials      171      179       +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Collaborator

@cffls cffls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much for adding this feature! Overall looks pretty good in terms of implementation. Only a few comments regarding the interfaces.

)
"""The credential associated with this DRep, if applicable"""

def id(self, id_format: IdFormat = IdFormat.CIP129) -> str:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move id_format to an internal field of DRep. Doing so would lead to a better alignment with how Address type work today.

For example, an address has the following usage pattern:

>>> addr = Address.from_primitive("addr_test1vr2p8st5t5cxqglyjky7vk98k7jtfhdpvhl4e97cezuhn0cqcexl7")
addr
addr_test1vr2p8st5t5cxqglyjky7vk98k7jtfhdpvhl4e97cezuhn0cqcexl7
>>> bytes(addr)
b'`\xd4\x13\xc1t]0`#\xe4\x95\x89\xe6X\xa7\xb7\xa4\xb4\xdd\xa1e\xff\\\x97\xd8\xc8\xb9y\xbf'
>>> bytes(addr).hex()
'60d413c1745d306023e49589e658a7b7a4b4dda165ff5c97d8c8b979bf'
>>> str(addr)
'addr_test1vr2p8st5t5cxqglyjky7vk98k7jtfhdpvhl4e97cezuhn0cqcexl7'

There are two essential calls: str(addr) and bytes(addr).

str(addr) is implemented by __repr__, and bytes(addr) is implemented by __bytes__.

Similarly, it would be great if DRep could stick to this usage pattern.

Something like this:

>>> drep = DRep(..., IdFormat.CIP105)
>>> bytes(drep).hex()
'4828a2dadba97ca9fd0cdc99975899470c219bdc0d828cfa6ddf6d69'
>>> str(drep)
'drep1fq529kkm4972nlgvmjvewkyeguxzrx7upkpge7ndmakkjnstaxx'

"""
return self.encode(id_format)

def id_hex(self, id_format: IdFormat = IdFormat.CIP129) -> str:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above, this seems a bit redundant, as user could simply call bytes(drep).hex() instead.

Comment on lines 118 to 128
def id(self) -> str:
"""
Get the governance action ID in Bech32 format.
"""
return self.encode()

def id_hex(self) -> str:
"""
Get the governance action ID in hexadecimal format.
"""
return bytes(self).hex()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to DRep, let's use the same interface (bytes and str) to get the representations.

@KINGH242
Copy link
Contributor Author

KINGH242 commented Dec 2, 2025

Thanks for the feedback. I will work on this today.

@KINGH242 KINGH242 requested a review from cffls December 3, 2025 14:06
Copy link
Collaborator

@cffls cffls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Thank you for making this happen!

@cffls cffls merged commit 40e18d5 into Python-Cardano:main Dec 5, 2025
11 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants