WIP: CIP67 and CIP68 Support#297
Conversation
…to bugfix/extended-cip8
Bugfix/bytestring
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #297 +/- ##
==========================================
+ Coverage 89.94% 90.62% +0.68%
==========================================
Files 33 36 +3
Lines 4855 5261 +406
Branches 733 797 +64
==========================================
+ Hits 4367 4768 +401
+ Misses 315 308 -7
- Partials 173 185 +12 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
So we just need some kind of extension of this? pycardano/pycardano/serialization.py Line 806 in 3d27786
Have any examples? I just did a query of all cip68 reference tokens and found that 99.99% of them are nfts. I'm trying to figure out a good set of test cases for it. I could use the example in the CIP68 docs, but those are extremely sparse. Ideally I could get a range of different examples. |
|
I would rather extend the support of type annotations for fields of PlutusData here: Line 681 in 3d27786 Also for the CIP68 datum I meant the deserialization happening when submitting a transaction with a CIP68 Datum attached - you can try this yourself easily. But don't have any examples at hand right now except for https://preprod.cardanoscan.io/transaction/36f79154eff88d73c21caaf9c5e1bedfc1ff641e39f7f80381dbdba0c104bc50 |
|
I'll be working on finishing this off. Todo:
|
…al/pycardano into feat/cip67-cip68
Feat/cip67 cip68
- Switched to TypedDicts for metadata classes - Added PlutusData wrapper class and tests
…dano into feat/cip67-cip68
Feat/cip67 cip68
|
@cffls We are close to having something ready. Just need to get builds passing. |
Cip67 & 68 build fixes
import Required from typing_extensions to support older python version
- qa: add `isort --check-only` (was only checking black) - add `check: qa test` to run all static analyses and unit tests - run `make format` over cip67/cip68 modules and tests to satisfy flake8/black Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restore Makefile to its original state per request; keep CIP formatting fixes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces initial support for Cardano CIP-0067 (token name labels/checksums) and CIP-0068 (reference NFT/user token names and inline datum metadata) within pycardano, aiming to streamline parsing/validation and provide CBOR/PlutusData helpers for CIP-68 metadata.
Changes:
- Add
CIP67TokenNamefor CIP-67 label + CRC8 validation and label extraction. - Add CIP-68 token-name subclasses and a
CIP68DatumPlutusDatawrapper with metadata key normalization and CBOR shaping. - Add initial pytest coverage for CIP-67/68 behavior and update dependencies/config (e.g.,
crc8, Poetry config), plus a small serialization tweak forIndefiniteListhandling.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
pycardano/cip/cip67.py |
Implements CIP-67 token naming validation and label extraction. |
pycardano/cip/cip68.py |
Adds CIP-68 token-name helpers and a CIP68Datum PlutusData wrapper for inline datum metadata. |
pycardano/cip/__init__.py |
Exposes new CIP-67/68 modules from the pycardano.cip package. |
pycardano/serialization.py |
Adjusts IndefiniteList init to handle FrozenList inputs. |
pyproject.toml |
Adds crc8 dependency required by CIP-67 checksum validation. |
poetry.lock |
Locks crc8 and updates lock metadata after dependency changes. |
poetry.toml |
Configures Poetry to create virtualenvs in-project. |
test/pycardano/test_cip67.py |
Adds tests for CIP-67 parsing/labeling and invalid token handling. |
test/pycardano/test_cip68.py |
Adds tests for CIP-68 token-name/reference-token behavior and datum roundtrips. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def __init__(self, data: Union[bytes, str, AssetName]): | ||
| if isinstance(data, AssetName): | ||
| data = data.payload | ||
|
|
||
| if isinstance(data, bytes): | ||
| data = data.hex() | ||
|
|
||
| if data[0] != "0" or data[7] != "0": | ||
| raise InvalidCIP67Token( | ||
| "The first and eighth hex values must be 0. Instead found:\n" | ||
| + f"first={data[0]}\n" | ||
| + f"eigth={data[7]}" | ||
| ) |
| checksum = crc8(bytes.fromhex(data[1:5])).hexdigest() | ||
| if data[5:7] != checksum: | ||
| raise InvalidCIP67Token( | ||
| f"Token label {data[1:5]} does not match token checksum.\n" | ||
| + f"expected={checksum}\n" | ||
| + f"received={data[5:7]}" | ||
| ) | ||
|
|
||
| super().__init__(bytes.fromhex(data)) |
| if self.label != 333: | ||
| raise InvalidCIP68ReferenceNFT("User NFT must have label 333.") | ||
|
|
| if self.label != 444: | ||
| raise InvalidCIP68ReferenceNFT("User NFT must have label 444.") | ||
|
|
| converted_metadata[key] = v | ||
| self.metadata = converted_metadata |
| value = [value[0], value[1], extra] | ||
| return CBORTag(121, value) |
| pytest.param( | ||
| ("000643b", None), # Too short | ||
| marks=pytest.mark.xfail(raises=(InvalidCIP67Token, IndexError)), | ||
| id="too_short", | ||
| ), |
| metadata: Dict[bytes, Any] | ||
| version: int | ||
| extra: Any # This should be PlutusData or Unit() for empty PlutusData |
This PR is a first pass implementation at handling classes for CIP67 and CIP68. These classes will streamline handling and parsing tokens utilizing these standards. This approach attempts to extend
AssetNameby providing additional validation to ensure CIP68 compliance for token names, as well as associated cbor classes for parsing associated metadata.Feedback on implementation details and additional functionality is welcomed.
Todo:
urifields)