https://github.com/edjcase/motoko_multiformats
A multiformats library for Motoko covering multibase, multicodec, multihash, ...
https://github.com/edjcase/motoko_multiformats
Last synced: 5 months ago
JSON representation
A multiformats library for Motoko covering multibase, multicodec, multihash, ...
- Host: GitHub
- URL: https://github.com/edjcase/motoko_multiformats
- Owner: edjCase
- License: mit
- Created: 2025-06-19T20:26:16.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-09-06T20:34:16.000Z (10 months ago)
- Last Synced: 2025-09-06T22:22:08.463Z (10 months ago)
- Language: Motoko
- Size: 82 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Motoko Multiformats
A comprehensive Motoko library for working with Multiformats, including multicodec, multihash, multibase, and variable-length integers. This library provides IPFS/IPLD-compatible implementations for encoding and decoding various data formats.
## Features
- **MultiBase**: Encode/decode data with various base encodings (Base58, Base32, Base64, Base16) with proper prefix handling
- **MultiCodec**: Support for IPFS/IPLD codec types and cryptographic key formats
- **MultiHash**: Hash algorithm identification and multihash format support
## Installation
### MOPS
```bash
mops install multiformats
```
To setup MOPS package manager, follow the instructions from the [MOPS Site](https://j4mwm-bqaaa-aaaam-qajbq-cai.ic0.app/)
## Usage
```motoko
import Multiformats "mo:multiformats";
// Access individual modules
let { MultiBase; MultiCodec; MultiHash; VarInt } = Multiformats;
```
## API Reference
### MultiBase
MultiBase provides encoding and decoding for various base formats with standardized prefixes.
#### Types
**`MultiBase`**
Represents the multibase encoding format with its character prefix:
```motoko
public type MultiBase = {
#base58btc; // 'z' prefix
#base32; // 'b' prefix
#base32Upper; // 'B' prefix
#base64; // 'm' prefix
#base64Url; // 'u' prefix
#base64UrlPad; // 'U' prefix
#base16; // 'f' prefix
#base16Upper; // 'F' prefix
};
```
**`MultiBaseOrIdentity`**
Extends MultiBase to include identity encoding (no encoding):
```motoko
public type MultiBaseOrIdentity = MultiBase or {
#identity; // 0x00 byte prefix (no encoding)
};
```
#### Functions
**`toText(bytes: Iter.Iter, encoding: MultiBase): Text`**
Converts bytes to multibase text with proper prefix:
```motoko
let bytes: [Nat8] = [0x01, 0x02, 0x03];
let text = MultiBase.toText(bytes.vals(), #base58btc);
// Returns: "z3mJ" (example base58btc encoding)
```
**`fromText(text: Text): Result.Result<([Nat8], MultiBase), Text>`**
Converts multibase text back to bytes and encoding type:
```motoko
let text = "z3mJ"; // Example base58btc encoding
let result = MultiBase.fromText(text);
// Returns: #ok(([0x01, 0x02, 0x03], #base58btc))
```
**`fromTextWithoutPrefix(text: Text, encoding: MultiBase): Result.Result<[Nat8], Text>`**
Converts base text to bytes using a specific encoding type (without prefix):
```motoko
let text = "3mJ"; // Base58 encoded data without prefix
let result = MultiBase.fromTextWithoutPrefix(text, #base58btc);
// Returns: #ok([0x01, 0x02, 0x03])
```
**`fromEncodedBytes(bytes: Iter.Iter): Result.Result<([Nat8], MultiBaseOrIdentity), Text>`**
Converts multibase-encoded bytes to their original bytes with encoding type. Used for CID byte decoding in DAGCBOR:
```motoko
let encodedBytes: [Nat8] = [0x5a, 0x33, 0x6d, 0x4a]; // 'z' prefix + base58 data
let result = MultiBase.fromEncodedBytes(encodedBytes.vals());
// Returns: #ok(([0x01, 0x02, 0x03], #base58btc))
let identityBytes: [Nat8] = [0x00, 0x01, 0x02, 0x03]; // identity prefix + raw data
let result2 = MultiBase.fromEncodedBytes(identityBytes.vals());
// Returns: #ok(([0x01, 0x02, 0x03], #identity))
```
**`toEncodedBytes(bytes: Iter.Iter, encoding: MultiBaseOrIdentity): [Nat8]`**
Converts bytes to multibase-encoded bytes with encoding type prefix. Complement to `fromEncodedBytes`:
```motoko
let bytes: [Nat8] = [0x01, 0x02, 0x03];
let encodedBytes = MultiBase.toEncodedBytes(bytes.vals(), #base58btc);
// Returns: [0x5a, 0x33, 0x6d, 0x4a] ('z' prefix + base58 data as UTF-8)
let identityBytes = MultiBase.toEncodedBytes(bytes.vals(), #identity);
// Returns: [0x00, 0x01, 0x02, 0x03] (identity prefix + raw data)
```
**`baseFromByte(byte: Nat8): ?MultiBaseOrIdentity`**
Converts a byte value to its corresponding MultiBase encoding type:
```motoko
let encoding = MultiBase.baseFromByte(0x5a); // 'z' as byte
// Returns: ?#base58btc
let identity = MultiBase.baseFromByte(0x00); // identity (no encoding)
// Returns: ?#identity
```
**`baseToByte(encoding: MultiBaseOrIdentity): Nat8`**
Converts a MultiBase encoding type to its corresponding byte value:
```motoko
let byte = MultiBase.baseToByte(#base58btc);
// Returns: 0x5a ('z' as byte)
let identityByte = MultiBase.baseToByte(#identity);
// Returns: 0x00
```
**`baseFromChar(char: Char): ?MultiBase`**
Converts a character prefix to its corresponding MultiBase encoding type:
```motoko
let encoding = MultiBase.baseFromChar('z');
// Returns: ?#base58btc
let invalid = MultiBase.baseFromChar('x');
// Returns: null
```
**`baseToChar(encoding: MultiBase): Char`**
Converts a MultiBase encoding type to its corresponding character prefix:
```motoko
let char = MultiBase.baseToChar(#base58btc);
// Returns: 'z'
let base32Char = MultiBase.baseToChar(#base32);
// Returns: 'b'
```
### MultiCodec
MultiCodec provides support for IPFS/IPLD codec identification and cryptographic key formats.
#### Types
**`Codec`**
Represents various codec types used in IPFS/IPLD and cryptographic keys:
```motoko
public type Codec = {
// Content/Data Codecs
#raw; // 0x55 - Raw binary data
#dagPb; // 0x70 - DAG-PB (Protocol Buffers)
#dagCbor; // 0x71 - DAG-CBOR
#dagJson; // 0x0129 - DAG-JSON
// Cryptographic Key Codecs
#ed25519Pub; // 0xed - Ed25519 public key
#secp256k1Pub; // 0xe7 - secp256k1 public key
#p256Pub; // 0x1200 - P-256 public key
#p384Pub; // 0x1201 - P-384 public key
#p521Pub; // 0x1202 - P-521 public key
#ed448Pub; // 0xee - Ed448 public key
#x25519Pub; // 0xec - X25519 public key
#x448Pub; // 0xef - X448 public key
#rsaPub; // 0x1205 - RSA public key
#bls12381G1Pub; // 0xea - BLS12-381 G1 public key
#bls12381G2Pub; // 0xeb - BLS12-381 G2 public key
// Hash Algorithm Codecs (for multihash compatibility)
#sha2256; // 0x12 - SHA-256
#sha2512; // 0x13 - SHA-512
#blake2b256; // 0xb220 - Blake2b-256
#blake2s256; // 0xb260 - Blake2s-256
#sha3256; // 0x16 - SHA3-256
#sha3512; // 0x14 - SHA3-512
};
```
#### Functions
**`toBytes(codec: Codec): [Nat8]`**
Encodes a codec as its multicodec varint representation:
```motoko
let bytes = MultiCodec.toBytes(#ed25519Pub);
// Returns: [0xed] (varint-encoded 237)
```
**`toBytesBuffer(buffer: Buffer.Buffer, codec: Codec)`**
Encodes a codec as its multicodec varint representation into a buffer:
```motoko
let buffer = Buffer.Buffer(10);
MultiCodec.toBytesBuffer(buffer, #ed25519Pub);
// buffer now contains: [0xed]
```
**`fromBytes(bytes: Iter.Iter): Result.Result`**
Decodes a multicodec varint from bytes:
```motoko
let bytes: [Nat8] = [0xed];
let result = MultiCodec.fromBytes(bytes.vals());
// Returns: #ok(#ed25519Pub)
```
### MultiHash
MultiHash provides hash algorithm identification and multihash format support.
#### Types
**`Algorithm`**
Represents hash algorithms supported in multihash format:
```motoko
public type Algorithm = {
#sha2256; // SHA-256 (32 bytes)
#sha2512; // SHA-512 (64 bytes)
#blake2b256; // Blake2b-256 (32 bytes)
#blake2s256; // Blake2s-256 (32 bytes)
#sha3256; // SHA3-256 (32 bytes)
#sha3512; // SHA3-512 (64 bytes)
};
```
**`MultiHash`**
Represents a multihash with algorithm and digest:
```motoko
public type MultiHash = {
algorithm: Algorithm;
digest: Blob;
};
```
#### Functions
**`toBytes(multihash: MultiHash): [Nat8]`**
Encodes a multihash to its binary representation:
```motoko
let multihash: MultiHash = {
algorithm = #sha2256;
digest = "\E3\B0\C4\42...";
};
let bytes = MultiHash.toBytes(multihash);
// Returns: [0x12, 0x20, 0xE3, 0xB0, ...]
```
**`toBytesBuffer(buffer: Buffer.Buffer, multihash: MultiHash)`**
Encodes a multihash to its binary representation into a buffer:
```motoko
let multihash: MultiHash = {
algorithm = #sha2256;
digest = "\E3\B0\C4\42...";
};
let buffer = Buffer.Buffer(multihash.digest.size() + 10);
MultiHash.toBytesBuffer(buffer, multihash);
// buffer now contains: [0x12, 0x20, 0xE3, 0xB0, ...]
```
**`fromBytes(bytes: Iter.Iter): Result.Result`**
Decodes a multihash from bytes:
```motoko
let bytes: [Nat8] = [0x12, 0x20, 0xE3, 0xB0, ...];
let result = MultiHash.fromBytes(bytes.vals());
// Returns: #ok({ algorithm = #sha2256; digest = ... })
```
### VarInt
VarInt provides variable-length integer encoding and decoding.
#### Functions
**`fromBytes(bytes: Iter.Iter): Result.Result`**
Decodes a variable-length integer from a byte iterator:
```motoko
let bytes: [Nat8] = [0xAC, 0x02]; // 300 encoded as varint
let result = VarInt.fromBytes(bytes.vals());
// Returns: #ok(300)
```
**`toBytes(n: Nat): [Nat8]`**
Encodes a natural number as a variable-length integer:
```motoko
let encoded = VarInt.toBytes(300);
// Returns: [0xAC, 0x02]
```
**`toBytesBuffer(buffer: Buffer.Buffer, n: Nat)`**
Encodes a natural number as a variable-length integer into a buffer:
```motoko
let buffer = Buffer.Buffer(10);
VarInt.toBytesBuffer(buffer, 300);
// buffer now contains: [0xAC, 0x02]
```
## Testing
```bash
mops test
```
## License
MIT License - see LICENSE file for details.
## Contributing
Contributions are welcome! Please feel free to submit issues and pull requests.