uuid256 🔑

UUID ↔ EVM uint256 bridge. UUID is canonical; tokenId encodes it in lower 128 bits.

test-lib npm package downloads

`uuid256` makes UUID the canonical application identifier and bridges to EVM `uint256` by packing the UUID into the lower 128 bits. The upper 128 bits MUST be zero. This preserves off‑chain compatibility (databases and APIs that use UUIDs) and stays interoperable with ERC‑721/1155 `tokenId`. Supports all [RFC 4122](https://www.rfc-editor.org/rfc/rfc4122) UUID versions for validation and bridging (v7 recommended for new IDs). - Contracts: `packages/contracts` (see `Uuid256.sol`) - Library (Deno/TypeScript): `packages/lib` (this package) - Examples: `packages/examples` ## Background & Motivation ### Problem Off‑chain systems (databases, APIs) use UUIDs. ERC‑721/1155 use `uint256` token IDs. This ID format mismatch forces custom mapping logic and tight coupling between off‑chain and on‑chain data. Common workarounds have trade‑offs: 1. Maintain UUID↔`uint256` mapping tables → more code, more failure points 2. Switch to integers everywhere → lose UUID features (collision resistance, time‑ordering) 3. Put UUIDs on‑chain → breaks ERC compatibility ### Solution `uuid256` provides a deterministic, bidirectional, stateless bridge: - ✅ UUID remains the recommended canonical ID - ✅ Deterministic encoding into lower 128 bits (upper 128 bits always zero) - ✅ Fully reversible - ✅ No mapping tables (pure algorithm) - ✅ Compatible with ERC‑721/1155 `tokenId` is the UUID, encoded into `uint256`. --- ### Install npm ```bash npm i uuid256 ``` pnpm ```bash pnpm add uuid256 ``` Bun ```bash bun add uuid256 ``` Deno ```bash deno add jsr:posaune0423/uuid256 ``` ### Quick start ```ts import { generateUuidV7, u256ToUuid, uuidToU256 } from "uuid256"; const uuid = generateUuidV7(); const tokenId = uuidToU256(uuid); // 0x + 64 hex (lower 128 = uuid, upper 128 = 0) const back = u256ToUuid(tokenId); // validates upper 128 bits are zero ``` ### Numeric example - UUID (string): `01234567-89ab-7cde-8f01-23456789abcdef` - Remove dashes, lowercase (32 hex): `0123456789ab7cde8f0123456789abcdef` - Bridge to `uint256`: - Lower 128 bits = `0x0123456789ab7cde8f0123456789abcdef` - Upper 128 bits = `0x00000000000000000000000000000000` - Canonical `uint256` (0x + 64 hex): `0x000000000000000000000000000000000123456789ab7cde8f0123456789abcdef` - Reverse bridge validates upper 128 == 0 and returns the UUID string again. ### Representation | Form | Type | Size | Example | | ---------------- | ------------- | -------: | ---------------------------------------- | | UUID (canonical) | string | 36 chars | `01234567-89ab-7cde-8f01-23456789abcdef` | | Bridged id | `uint256` hex | 66 chars | `0x0000…0000` + 32 hex (see above) | --- ## Specification ### Status Defines a bidirectional bridge between UUID (RFC 4122) and EVM `uint256` (v7 recommended). ### Terminology The key words “MUST”, “MUST NOT”, “SHOULD”, “MAY” are to be interpreted as described in RFC 2119. ### Canonical identifier - The canonical identifier is UUID (v7 recommended). Applications MUST treat the UUID string as the primary key. ### Bridged representation - A bridged identifier is an EVM `uint256` whose upper 128 bits are all zero and whose lower 128 bits equal the UUID bytes `(big‑endian)`. Implementations MUST produce a canonical lowercase hex string with the `0x` prefix and exactly 64 hex digits. ### Encoding and decoding - Encoding (UUID → `uint256`): lower128 = UUID; upper128 = 0. - Decoding (`uint256` → UUID): implementations MUST reject inputs that are not `0x` + 64 lowercase hex (`INVALID_U256_FORMAT`) or have upper128 ≠ 0 (`UPPER128_NOT_ZERO`). ### Validation - UUID inputs MUST be valid RFC 4122 UUIDs (any version) with the `8-4-4-4-12` pattern and correct variant bits. - Implementations MAY downcase hex. On failure, they MUST throw `INVALID_UUID_FORMAT`. ### Errors | Code | When | | --------------------- | --------------------------------------- | | `INVALID_UUID_FORMAT` | Input string does not match UUID syntax | | `INVALID_U256_FORMAT` | Not `0x` + 64 hex | | `UPPER128_NOT_ZERO` | Reverse bridge and upper 128 bits ≠ 0 | ### Security - UUID generation MUST use a CSPRNG for non‑timestamp bits where applicable. - Reverse bridging MUST validate upper 128 bits are zero. --- ## API - `generateUuidV7(): Uuid` — Create a UUID string (v7, lowercase). Uses CSPRNG. - `generateUuidV5(namespace: string, data: string | Uint8Array): Promise` — Deterministic name‑based UUID. - `isUuid(s: string): s is Uuid` — Accepts any RFC 4122 UUID version. - `isUuidV7(s: string): s is Uuid` — Validates UUID (v7) specifically. - `asUuid(s: string): Uuid` — throws `INVALID_UUID_FORMAT` on failure - `asUuidV7(s: string): Uuid` — throws `INVALID_UUID_FORMAT` on failure - `uuidToU256(uuid: string): U256Hex` — returns canonical `0x` + 64 lowercase hex (upper 128 bits are zero) - `u256ToUuid(id: string): Uuid` — throws `INVALID_U256_FORMAT` or `UPPER128_NOT_ZERO` - `toCanonicalU256Hex(x: bigint): U256Hex` — returns canonical `0x` + 64 lowercase hex ## Examples See `packages/examples` for Node, Browser, Bun, and Edge workers.