dcid 1.0.0
dcid: ^1.0.0 copied to clipboard
A Dart library for working with Content Identifiers (CIDs) according to the CID specification. Supports CIDv0 and CIDv1, multiple codecs, and hash algorithms.
dcid #
A Dart library for working with Content Identifiers (CIDs) according to the CID specification.
Overview #
Content Identifiers (CIDs) are self-describing content-addressed identifiers used in distributed systems like IPFS. They uniquely identify content using cryptographic hashes and include metadata about the content's encoding and hash algorithm.
This library provides a complete implementation for:
- Creating CIDs from raw data
- Parsing CIDs from strings or bytes
- Converting between CID versions (v0 and v1)
- Supporting multiple multicodecs and multihash algorithms
- Full compliance with the CID specification
Features #
- ✅ CIDv0 and CIDv1 Support - Full support for both CID versions
- ✅ Multiple Codecs - Support for dag-pb, raw, dag-cbor, and many more
- ✅ Multiple Hash Algorithms - SHA2-256, SHA2-512, and extensible for others
- ✅ String Parsing - Parse CIDs from Base58btc (CIDv0) and Base32 (CIDv1 canonical)
- ✅ Binary Serialization - Convert CIDs to/from binary format
- ✅ Version Conversion - Convert between CIDv0 and CIDv1 when possible
- ✅ Comprehensive Testing - Full test coverage with edge cases
- ✅ Type Safety - Full Dart type safety with proper error handling
Installation #
Add dcid
to your pubspec.yaml
:
dependencies:
dcid: ^1.0.0
Then run:
dart pub get
Quick Start #
import 'package:dcid/dcid.dart';
import 'dart:convert';
import 'dart:typed_data';
void main() {
// Create a CIDv1 from data
final data = utf8.encode('Hello World!');
final cid = CID.fromData(CID.V1, 'dag-pb', Uint8List.fromList(data));
print('Created CID: ${cid.toString()}');
// Output: bafybeid7qoywk77r7rj3slobqfekdvs57qwuwh5d2z3sqsw52iabe3mqne
// Parse an existing CID string
final parsedCid = CID.fromString('QmWvQxTqbG2Z9HPJgG57jjwR154cKhbtJenbyYTWkjgF3e');
print('Parsed CID version: ${parsedCid.version}');
print('Parsed CID codec: ${parsedCid.codecName}');
}
Usage Examples #
Creating CIDs from Data #
import 'package:dcid/dcid.dart';
import 'dart:convert';
import 'dart:typed_data';
// Create CIDv1 with dag-pb codec (default for IPFS)
final data = utf8.encode('Hello IPFS!');
final cidV1 = CID.fromData(CID.V1, 'dag-pb', Uint8List.fromList(data));
print(cidV1.toString()); // bafybeid7qoywk77r7rj3slobqfekdvs57qwuwh5d2z3sqsw52iabe3mqne
// Create CIDv1 with raw codec
final cidRaw = CID.fromData(CID.V1, 'raw', Uint8List.fromList(data));
print(cidRaw.toString()); // bafkreid7qoywk77r7rj3slobqfekdvs57qwuwh5d2z3sqsw52iabe3mqne
// Create CIDv0 (only supports dag-pb + sha2-256)
final cidV0 = CID.fromData(CID.V0, 'dag-pb', Uint8List.fromList(data));
print(cidV0.toString()); // QmWvQxTqbG2Z9HPJgG57jjwR154cKhbtJenbyYTWkjgF3e
Parsing CIDs #
// Parse CIDv0 (Base58btc encoded)
final cidV0 = CID.fromString('QmWvQxTqbG2Z9HPJgG57jjwR154cKhbtJenbyYTWkjgF3e');
print('Version: ${cidV0.version}'); // 0
print('Codec: ${cidV0.codecName}'); // dag-pb
// Parse CIDv1 (Base32 encoded, canonical form)
final cidV1 = CID.fromString('bafybeid7qoywk77r7rj3slobqfekdvs57qwuwh5d2z3sqsw52iabe3mqne');
print('Version: ${cidV1.version}'); // 1
print('Codec: ${cidV1.codecName}'); // dag-pb
// Parse CIDv1 (Base58btc encoded, alternative form)
final cidV1Alt = CID.fromString('zdj7We1fKtuSjWA1zhER12jc7mydHG43F22AyC8eLrBaBF9Da');
print('Version: ${cidV1Alt.version}'); // 1
Working with Binary Data #
// Convert CID to binary format
final cid = CID.fromString('bafybeid7qoywk77r7rj3slobqfekdvs57qwuwh5d2z3sqsw52iabe3mqne');
final bytes = cid.toBytes();
print('Binary length: ${bytes.length}');
// Parse CID from binary format
final parsedCid = CID.fromBytes(bytes);
print(parsedCid.toString()); // Same as original
Version Conversion #
// Convert CIDv0 to CIDv1
final cidV0 = CID.fromString('QmWvQxTqbG2Z9HPJgG57jjwR154cKhbtJenbyYTWkjgF3e');
final cidV1 = cidV0.toV1();
print(cidV1.toString()); // bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyke
// Convert CIDv1 to CIDv0 (only if compatible)
final compatibleCidV1 = CID.fromString('bafybeid7qoywk77r7rj3slobqfekdvs57qwuwh5d2z3sqsw52iabe3mqne');
final convertedV0 = compatibleCidV1.toV0();
print(convertedV0.toString()); // QmWvQxTqbG2Z9HPJgG57jjwR154cKhbtJenbyYTWkjgF3e
// Incompatible CIDv1 cannot be converted to v0
final rawCidV1 = CID.fromString('bafkreid7qoywk77r7rj3slobqfekdvs57qwuwh5d2z3sqsw52iabe3mqne');
try {
rawCidV1.toV0(); // Throws FormatException
} catch (e) {
print('Cannot convert: $e');
}
Advanced Usage #
// Create CID with custom multihash
final data = utf8.encode('Hello World!');
final cid = CID.fromData(CID.V1, 'raw', Uint8List.fromList(data), 'sha2-512');
print(cid.toString());
// Access CID properties
final cid = CID.fromString('bafybeid7qoywk77r7rj3slobqfekdvs57qwuwh5d2z3sqsw52iabe3mqne');
print('Version: ${cid.version}');
print('Codec: ${cid.codec}'); // Integer code
print('Codec Name: ${cid.codecName}'); // String name
print('Multihash: ${cid.multihash}'); // Raw bytes
// Compare CIDs
final cid1 = CID.fromString('QmWvQxTqbG2Z9HPJgG57jjwR154cKhbtJenbyYTWkjgF3e');
final cid2 = CID.fromString('QmWvQxTqbG2Z9HPJgG57jjwR154cKhbtJenbyYTWkjgF3e');
print(cid1 == cid2); // true
API Reference #
CID Class #
The main class for working with Content Identifiers.
Constants
CID.V0
- CID Version 0 constantCID.V1
- CID Version 1 constant
Properties
version
- The CID version (0 or 1)codec
- The multicodec integer codecodecName
- The multicodec string namemultihash
- The raw multihash bytes
Constructors
CID(version, codec, multihash)
- Create CID from componentsCID.create(version, codecName, multihash)
- Create CID with string codec nameCID.fromData(version, codecName, data, [multihashName])
- Create CID from dataCID.fromString(s)
- Parse CID from stringCID.fromBytes(bytes)
- Parse CID from binary data
Methods
toString()
- Convert to string representationtoBytes()
- Convert to binary representationtoV0()
- Convert to CIDv0 (if possible)toV1()
- Convert to CIDv1operator ==
- Compare CIDs for equalityhashCode
- Get hash code for CIDs
Supported Codecs #
The library supports many multicodecs including:
dag-pb
(0x70) - IPFS MerkleDAG protobufraw
(0x55) - Raw binary datadag-cbor
(0x71) - IPFS MerkleDAG CBORcbor
(0x51) - CBORprotobuf
(0x50) - Protocol Buffersjson
(0x0200) - JSONgit-raw
(0x78) - Git raw objects- And many more...
Supported Hash Algorithms #
Currently supported for automatic hashing:
sha2-256
(default)sha2-512
Additional algorithms can be supported by providing pre-computed multihashes.
Error Handling #
The library provides comprehensive error handling:
try {
final cid = CID.fromString('invalid-cid');
} on FormatException catch (e) {
print('Invalid CID format: $e');
} on ArgumentError catch (e) {
print('Invalid argument: $e');
}
Common error scenarios:
- Invalid CID string format
- Unsupported multibase encoding
- Invalid multihash structure
- Incompatible version conversions
- Unknown codec names
Testing #
Run the test suite:
dart test
The library includes comprehensive tests covering:
- CID creation and parsing
- Version conversion
- Error handling
- Edge cases
- Binary serialization
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
License #
This project is licensed under the MIT License - see the LICENSE file for details.
Related Projects #
- dart_multihash - Multihash implementation for Dart
- IPFS - Distributed file system that uses CIDs
- Multiformats - Self-describing data formats
Changelog #
See CHANGELOG.md for a list of changes and version history.