Skip to content

evmts/z-ens-normalize

Repository files navigation

z-ens-normalize

A Zig implementation of ENS (Ethereum Name Service) name normalization.

Description

z-ens-normalize is a robust Zig library for normalizing and validating ENS names according to ENSIP-15 specifications. It handles Unicode normalization, validation, and beautification of ENS names ensuring correct, consistent and idempotent behavior.

Requirements

  • Zig 0.14.0 or later

Installation

Using Zig Package Manager

Install the dependency using the Zig CLI:

zig fetch --save https://github.com/evmts/z-ens-normalize/archive/main.tar.gz

This will automatically add the dependency to your build.zig.zon file.

Then in your build.zig:

const z_ens_normalize = b.dependency("z_ens_normalize", .{
    .target = target,
    .optimize = optimize,
});

exe.root_module.addImport("ens_normalize", z_ens_normalize.module("ens_normalize"));

Alternative: Specific Version

To install a specific version or tag:

zig fetch --save https://github.com/evmts/z-ens-normalize/archive/v0.1.0.tar.gz

Local Development

git clone https://github.com/evmts/z-ens-normalize.git
cd z-ens-normalize
zig build

Usage

const std = @import("std");
const ens_normalize = @import("ens_normalize");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Using normalizer to reuse preloaded data
    var normalizer = try ens_normalize.EnsNameNormalizer.init(allocator);
    defer normalizer.deinit();
    
    const name = "🅰️🅱.eth";
    const processed = try normalizer.process(name);
    defer processed.deinit();
    
    const beautified_name = try processed.beautify();
    defer allocator.free(beautified_name);
    
    const normalized_name = try processed.normalize();
    defer allocator.free(normalized_name);

    std.debug.print("Original: {s}\n", .{name});
    std.debug.print("Normalized: {s}\n", .{normalized_name});
    std.debug.print("Beautified: {s}\n", .{beautified_name});

    // Using normalize directly
    const normalized = try normalizer.normalize("Levvv.eth");
    defer allocator.free(normalized);
    std.debug.print("Direct normalize: {s}\n", .{normalized});

    // Handling errors
    const invalid_result = normalizer.normalize("Levvv..eth");
    if (invalid_result) |result| {
        defer allocator.free(result);
        std.debug.print("Unexpected success: {s}\n", .{result});
    } else |err| {
        std.debug.print("Expected error: {}\n", .{err});
    }
}

Convenience Functions

For simple one-off operations, you can use the convenience functions:

const std = @import("std");
const ens_normalize = @import("ens_normalize");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Direct normalization
    const normalized = try ens_normalize.normalize(allocator, "Example.eth");
    defer allocator.free(normalized);
    
    // Direct beautification
    const beautified = try ens_normalize.beautify_fn(allocator, "example.eth");
    defer allocator.free(beautified);
    
    // Full processing
    const processed = try ens_normalize.process(allocator, "Example.eth");
    defer processed.deinit();
}

Testing

The crate contains several types of tests:

To run all tests:

zig build test

To run specific test files:

zig test tests/ens_tests.zig

Building

Library

zig build

C-Compatible Library

This project also provides a C-compatible interface:

zig build c-lib

Development

For development with debug information:

zig build -Doptimize=Debug

Roadmap

  • Tokenization
  • Normalization
  • Beautification
  • ENSIP-15 Validation Tests
  • NSM (Non-Spacing Mark) Validation
  • Combining Marks Validation
  • Basic Confusable Detection
  • Trie-based Emoji Matching - See design doc for implementation plan
  • Unicode Normalization Tests
  • Fenced Character Validation
  • Enhanced Error Types (matching Java reference)
  • CLI to update specs.json and nf.json
  • analog of ens_cure function
  • analog of ens_normalizations function

TODO

High Priority

  • Trie-based Emoji Matching: Replace current O(n²) hash map emoji matching with O(n) trie-based approach following Java reference implementation. See detailed design document for:
    • Complete implementation plan with Zig code examples
    • Performance analysis and benchmarking strategy
    • Comprehensive fuzz testing approach
    • Test cases extracted from Java reference implementation
    • Memory safety considerations and migration strategy

Medium Priority

  • Enhanced Error Types: Add specific error types matching Java reference (NSM_DUPLICATE, CM_AFTER_EMOJI, etc.)
  • Fenced Character Validation: Complete implementation of fenced character detection and validation
  • Performance Optimization: Memory pool allocation for frequently allocated structures

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

A C-compatible Zig implementation of ENS (Ethereum Name Service) name normalization.

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages