npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@red-isbe/did-isbe-registry

v1.3.6

Published

https://github.com/alastria/isbe-contracts/tree/main/contracts/identity/didregistry

Downloads

38

Readme

Alcance y fuentes de documentación

Esta librería es un wrapper TypeScript para facilitar el consumo de los smart contracts ISBE DID desde aplicaciones Node.js. Su objetivo es simplificar la interacción técnica (construcción de transacciones, llamadas view, mapeo de estructuras y normalización de datos), no reemplazar ni duplicar la lógica de negocio completa definida en los contratos.

Qué cubre esta librería

  • Encapsulación de llamadas a contratos ISBE.
  • Construcción segura de transacciones (rawTx) y llamadas de solo lectura.
  • Normalización de datos (bytes32 ↔ fragment, hex ↔ JWK, etc.).
  • Validaciones técnicas y operativas básicas necesarias para el uso correcto de la API.
  • Exposición de las reglas más relevantes y visibles para el consumidor de la librería.

Qué no cubre esta librería

  • Reglas completas de negocio del protocolo DID ISBE.
  • Validaciones internas profundas del smart contract.
  • Políticas avanzadas, invariantes on-chain o restricciones de gobernanza.
  • Detalles de implementación interna del contrato.

Estas reglas no se duplican aquí por diseño, para evitar inconsistencias entre cliente y contrato.


Documentación oficial y referencias

Para un entendimiento completo del comportamiento del sistema, se recomienda consultar:


Package & entorno de ejecución

Esta librería está publicada como ESM (ECMAScript Modules) y está pensada para ejecutarse en Node.js moderno con TypeScript.

Requisitos

  • Node.js ≥ 18
  • TypeScript ≥ 5.9
  • Entorno compatible con ESM ("type": "module")

Dependencias principales

  • ethers v6 – Interacción con contratos inteligentes.
  • bs58 – Codificación/decodificación base58 para fragmentos DID.
  • elliptic – Soporte criptográfico para curvas elípticas.
  • web3 – Compatibilidad con tooling adicional del ecosistema Ethereum.

Scripts disponibles

{
  "test": "npm run test:unit; npm run test:esm",
  "test:unit": "jest --config jest.config.ts",
  "test:esm": "NODE_OPTIONS=--experimental-vm-modules jest -c jest.esm.config.ts",
  "build": "tsc",
  "start": "node dist/index.js"
}

Tests

  • test:unit Ejecuta los tests unitarios estándar (CommonJS / Jest clásico).

  • test:esm Ejecuta tests específicos que requieren ESM real, usando:

    NODE_OPTIONS=--experimental-vm-modules

Algunos módulos (por ejemplo ConfigManager) interactúan con el sistema de archivos y ESM, por lo que requieren un runner específico para garantizar aislamiento y cobertura completa.


Instalación

npm install @red-isbe/did-isbe-registry

Configuración central (ConfigManager)

La librería utiliza un singleton de configuración para centralizar:

  • Dirección del contrato DID Registry
  • ABI del contrato
  • modelDeployId (usado para reconstruir DIDs legibles)
  • Provider RPC compartido

Archivo config.json

Existe en la raíz/src del proyecto y sigue esta estructura general:

{
  "modelDeployId": "model-x",
  "didRegistry": {
    "address": "0x...",
    "abiPath": "./IDidRegistry.json"
  }
}

ConfigManager

Responsabilidades principales:

  • Cargar config.json desde disco.
  • Instanciar el contrato ethers.Contract.
  • Exponer getters consistentes para toda la librería.
  • Permitir actualización dinámica en runtime (útil en entornos de test o multired).

Ejemplo de uso interno

const configManager = ConfigManager.getInstance(provider);

const contract = configManager.getContract();
const modelDeployId = configManager.getModelDeployId();

Nota de diseño: ConfigManager es un singleton deliberado. La librería asume una única configuración activa por proceso, alineada con el despliegue del contrato.


Utilidades de conversión DID / Verification Method

La carpeta utils contiene funciones puras y testeadas que normalizan los formatos exigidos por los contratos.

didAndVmethodConversion.ts

Este módulo encapsula toda la lógica de conversión entre formatos humanos y bytes32 on-chain, evitando duplicación y errores sutiles.

didToBytes32(did: string): string

Convierte correctamente:

  • DID completo did:isbe:<model>:<hex>
  • DID con fragmento did:isbe:...#fragment
  • Hex directo
  • Fragmento base58

Siempre retorna un bytes32 left-aligned + zero-padded, como esperan los contratos Solidity.

vMethodIdToBytes32(vMethodId: string): string

Convierte un identificador de método de verificación (did#fragment) a bytes32.


Validaciones incluidas

Estas funciones fallan temprano si el input es inválido:

  • Hex no válido
  • Fragmentos base58 corruptos
  • Longitudes > 32 bytes
  • Valores incompatibles con Solidity

Esto reduce errores on-chain y fallos difíciles de depurar.


Filosofía de diseño

  • Una sola fuente de verdad para conversiones binarias.
  • Errores explícitos en lugar de silencios peligrosos.
  • Cero dependencia de estado (excepto ConfigManager).
  • Totalmente testeadas con cobertura de ramas y errores.

Utilidades criptográficas (jwkConversion)

Este módulo convierte claves públicas entre:

  • JWK (JsonWebKey) usado en APIs / DID Core
  • HEX (XY concatenado) usado por los contratos (64 bytes = 32 X + 32 Y)

jwkToHex(jwk)

Convierte un objeto JWK EC a 0x... (64 bytes XY). Valida:

  • Formato de objeto
  • Existencia de x y y
  • Tamaño exacto: 32 bytes cada uno (curvas secp256k1 / secp256r1)

Si la curva no es reconocida, imprime un warning pero exporta igualmente.

hexToJwk(hex, ellipticType)

Convierte 0x + 64 bytes a JWK EC. La curva se determina por ellipticType:

  • 0none
  • 1secp256k1
  • 2secp256r1

Nota: el contrato define la semántica de curva por ellipticType, el formato binario XY es el mismo.


Construcción y envío de transacciones (sendTransaction)

Este módulo abstrae la construcción de transacciones “listas para firmar” y su envío posterior.

buildRawTransaction(contract, method, args, provider)

  • Codifica calldata usando contract.interface.encodeFunctionData.
  • Resuelve to con contract.getAddress().
  • Estima gas con provider.estimateGas, con fallback a 5_000_000.
  • Obtiene chainId con provider.getNetwork().
  • Construye una transacción EIP-155 y retorna el unsignedSerialized.

Implementación actual: gasPrice se fija como BigInt(4000).

sendSignedTransaction(rawTx, provider)

  • Emite el rawTx firmado con provider.broadcastTransaction.
  • Espera confirmación con .wait().
  • Retorna TransactionReceipt (o null si el provider lo retorna así).

Módulo: IDidController

IDidController encapsula operaciones relacionadas con controladores de un DID, incluyendo:

  • Construcción de transacciones para agregar / revocar controllers.
  • Consultas de controladores autorizados.
  • Consulta paginada de DIDs asociados a un controller.

Métodos

Transaccionales (devuelven rawTx)

  • buildAddControllerTx(did, controller): Promise<string>
  • buildRevokeControllerTx(did, controller): Promise<string>
  • sendSignedTransaction(rawTx): Promise<...>

Ambos builders convierten did y controller a bytes32 usando didToBytes32(...), y delegan en buildRawTransaction(...).

Lectura (view)

  • checkController(did, controller): Promise<boolean>

    • Usa el selector del contrato: "checkController(bytes32,address)"
  • checkControllerBytes(didBytes, controller): Promise<boolean>

    • Variante bytes: "checkController(bytes,address)"
  • getDidsByController(controller, page, pageSize): Promise<GetDidsByControllerResult>

    • Hace encodeFunctionData + provider.call y decodifica el resultado.
    • Reconstruye DIDs legibles con el modelDeployId de config.json.

Tipo de retorno para paginación

export type GetDidsByControllerResult = {
  items: string[];
  total: string;
  howMany: string;
  prev: string;
  next: string;
};

Ejemplo rápido de uso: controllers

import { JsonRpcProvider } from "ethers";
import IDidController from "did-isbe-registry/dist/identity/did-isbe-lib/IDidController.js";

const provider = new JsonRpcProvider("https://tu-nodo-rpc");
const ctrl = new IDidController(provider);

// 1) Crear rawTx para agregar un controller
const rawTx = await ctrl.buildAddControllerTx(
  "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567",
  "did:isbe:model-x:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
);

// 2) Enviar una transacción firmada
// (la firma se hace fuera de la lib; aquí solo se emite el rawTx ya firmado)
const receipt = await ctrl.sendSignedTransaction("0xSIGNED_RAW_TX");

// 3) Consultar
const ok = await ctrl.checkController(
  "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567",
  "0xabc123...def456" // address EVM del controller
);

// 4) Paginación
const dids = await ctrl.getDidsByController(
  "did:isbe:model-x:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  0,
  10
);
console.log(dids.items);

Módulo: IDidVerificationMethod

IDidVerificationMethod encapsula la gestión de Verification Methods de un DID (alta, revocación, expiración y rotación), y construye transacciones listas para firmar (rawTx).

Métodos

Transaccionales (devuelven rawTx)

  • buildAddVerificationMethodTx(did, vMethodId, publicKey, ellipticType): Promise<string>

    • publicKey debe ser un string JSON válido representando un JWK.
    • Convierte publicKey (JWK)pubHex (0xXY) usando jwkToHex.
    • Convierte did y vMethodId a bytes32 usando didToBytes32 y vMethodIdToBytes32.
    • Construye la tx para addVerificationMethod(didBytes32, vMethodIdBytes32, pubHex, ellipticType).
  • buildRevokeVerificationMethodTx(did, vMethodId, notAfter): Promise<string>

    • Construye la tx para revokeVerificationMethod(didBytes32, vMethodIdBytes32, notAfter).
  • buildExpireVerificationMethodTx(did, vMethodId, notAfter): Promise<string>

    • Construye la tx para expireVerificationMethod(didBytes32, vMethodIdBytes32, notAfter).
  • buildRollVerificationMethodTx(args: RollArgs): Promise<string>

    • Construye la tx para rollVerificationMethod(rollStruct) (struct).
    • Antes de construirla, aplica una validación de política (ver abajo).
  • sendSignedTransaction(rawTx): Promise<...>

    • Delegación a sendSignedTransaction(rawTx, provider).

Tipo RollArgs

export type RollArgs = {
  did: string;
  vMethodId: string;      // nuevo vMethodId (did#fragment o fragment)
  publicKey: string;      // JWK en string JSON
  ellipticType: number;   // 0=NONE, 1=K1, 2=R1 (según contrato)
  notBefore: number;
  notAfter: number;
  oldVMethodId: string;   // vMethodId actual a rotar
  duration: number;
};

Regla de negocio aplicada en rotación (política)

Al ejecutar buildRollVerificationMethodTx, la librería aplica una política específica:

  • Solo si el oldVMethodId pertenece a la relación capabilityInvocation, entonces:

    • No se permite cambiar la curva (ellipticType) durante la rotación.
    • Si intenta rotar a otra curva, lanza:

Rotación inválida: el método <oldVMethodId> pertenece a 'capabilityInvocation' con curva <currentCurve>, no puede rotarse a <newEllipticType>.

Esto se valida consultando el DID Document crudo vía getDidDocument y reconstruyendo:

  • vMethodIdsText (did#fragment) desde bytes32→base58 (helper interno bytes32ToFragment)
  • vRelationships para detectar si el método está vinculado a capabilityInvocation
  • vMethods[idx].ellipticType para comparar la curva actual vs nueva

Importante: si el método no es capabilityInvocation, la librería no aplica restricción (se permite cambiar curva).

Ejemplo: add / revoke / expire

import { JsonRpcProvider } from "ethers";
import IDidVerificationMethod from "did-isbe-registry/dist/identity/did-isbe-lib/IDidVerificationMethod.js";

const provider = new JsonRpcProvider("https://tu-rpc");
const vm = new IDidVerificationMethod(provider);

const rawAdd = await vm.buildAddVerificationMethodTx(
  "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567",
  "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567#zQm...",
  JSON.stringify({ kty:"EC", crv:"secp256k1", x:"...", y:"..." }),
  1
);

const rawRevoke = await vm.buildRevokeVerificationMethodTx(
  "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567",
  "did:isbe:model-x:...#zQm...",
  1735689600
);

const rawExpire = await vm.buildExpireVerificationMethodTx(
  "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567",
  "did:isbe:model-x:...#zQm...",
  1735689600
);

Ejemplo: roll (rotación)

const rawRoll = await vm.buildRollVerificationMethodTx({
  did: "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567",
  vMethodId: "did:isbe:model-x:...#NEW_FRAG",
  publicKey: JSON.stringify({ kty:"EC", crv:"secp256k1", x:"...", y:"..." }),
  ellipticType: 1,
  notBefore: 1700000000,
  notAfter: 1800000000,
  oldVMethodId: "did:isbe:model-x:...#OLD_FRAG",
  duration: 31536000,
});

Módulo: IDidVerificationRelationship

IDidVerificationRelationship permite crear relaciones de verificación (authentication, assertionMethod, capabilityInvocation, etc.) entre un DID y un Verification Method, y consultar DIDs asociados a un método/relación de forma paginada.

Tipos

export type DidWithPeriod = {
  did: string;
  notBefore: string;
  notAfter: String; // (nota: en el código es String)
};

export type GetDidsByVerificationRelationshipResult = {
  items: DidWithPeriod[];
  total: number;
  howMany: number;
  prev: number;
  next: number;
};

Métodos

Transaccionales (devuelven rawTx)

  • buildAddVerificationRelationshipTx(did, name, vMethodId, notBefore, notAfter): Promise<string>

    • Convierte did y vMethodId a bytes32

    • Construye la tx:

      • addVerificationRelationship(didBytes32, name, vMethodIdBytes32, notBefore, notAfter)
  • sendSignedTransaction(rawTx): Promise<...>

    • Delegación a sendSignedTransaction(rawTx, provider).

Lectura (view)

  • getDidsByVerificationRelationship(vMethodId, name, page, pageSize): Promise<GetDidsByVerificationRelationshipResult>

    • Llama a getDidsByVerificationRelationship(vMethodIdBytes32, name, page, pageSize).
    • Reconstruye did:isbe:<modelDeployId>:<hex> desde bytes32 (removiendo trailing zeros).
    • Retorna paginación (total/howMany/prev/next) como number.

Ejemplo: crear relación

import { JsonRpcProvider } from "ethers";
import IDidVerificationRelationship from "did-isbe-registry/dist/identity/did-isbe-lib/IDidVerificationRelationship.js";

const provider = new JsonRpcProvider("https://tu-rpc");
const rel = new IDidVerificationRelationship(provider);

const rawTx = await rel.buildAddVerificationRelationshipTx(
  "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567",
  "authentication",
  "did:isbe:model-x:...#zQmFragment",
  1700000000,
  1800000000
);

Ejemplo: consulta paginada

const result = await rel.getDidsByVerificationRelationship(
  "did:isbe:model-x:...#zQmFragment",
  "authentication",
  0,
  10
);

console.log(result.items); // [{ did, notBefore, notAfter }, ...]

Módulo: IDidDocumentDetailed

IDidDocumentDetailed es el wrapper de más alto nivel para inicializar el registro, insertar/actualizar DID Documents y consultar DID Documents (en formato interno y en formato W3C).

A diferencia de los otros módulos que reciben un JsonRpcProvider, este módulo recibe un rpcUrl y crea internamente un ethers.JsonRpcProvider.

Tipos principales

  • DidDocument: representación interna (mapeada directo desde el contrato).
  • DidW3CDocument: documento compatible con W3C DID Core, construido a partir del interno.
  • GetDidsResult: paginación de DIDs existentes.

Métodos

Inicialización / escritura (transaccionales → devuelven rawTx)

  • buildInitializeDiDRegistryTx(ellipticType): Promise<string>

    • Construye tx para initializeDiDRegistry(ellipticType).
  • buildInsertDidDocumentTx(did, baseDocument, fragment, publicKey, ellipticType, notBefore, notAfter): Promise<string>

    • publicKey debe ser un string JSON válido representando un JWK.
    • Convierte publicKey (JWK)pubHex (0xXY) usando jwkToHex.
    • did se convierte a bytes32 (requiere method-specific-id de 40 hex).
    • fragment se interpreta como base58, se decodifica y se paddea a bytes32.
  • buildInsertFirstDidDocumentTx(did, baseDocument, fragment, proof, publicKey, ellipticType, notBefore, notAfter, alsoKnownAs): Promise<string>

    • Variante “first insert” que incluye proof y alsoKnownAs.
  • buildUpdateBaseDocumentTx(did, baseDocument): Promise<string>

    • Tx para updateBaseDocument(didBytes32, baseDocument).
  • buildUpdateAlsoKnownAsTx(did, alsoKnownAs): Promise<string>

    • Tx para updateAlsoKnownAs(didBytes32, alsoKnownAs).
  • sendSignedTransaction(rawTx)

    • Delegación a sendSignedTransaction(rawTx, provider).

Lectura / consultas

  • getDids(page, pageSize): Promise<GetDidsResult>

    • Llama el método view getDids.
    • Reconstruye did:isbe:<modelDeployId>:<hex> quitando trailing zeros del bytes32.
  • getDidDocument(did): Promise<DidW3CDocument>

    • Obtiene el documento en estructura interna (getDidDocumentW3C) y lo transforma a W3C con “now” = Date.now()/1000.
  • getDidDocumentByTimestamp(did, timestamp): Promise<DidW3CDocument>

    • Igual que getDidDocument, pero el filtrado de relaciones se hace con el timestamp dado.
  • getDidDocumentW3C(did): Promise<DidDocument>

    • Llama el método view getDidDocument(didBytes32) y mapea a estructura interna.
  • getDidDocumentByTimestampW3C(did, timestamp): Promise<DidDocument>

    • Llama el método view getDidDocumentByTimestamp(didBytes32, timestamp) y mapea a estructura interna.

Helpers públicos (útiles para tests / integraciones)

  • didToBytes32(did)
  • fragmentToBytes32(fragment)
  • bytes32ToFragment(b32)
  • buildVMethodId(did, fragment)${did}#${fragment}

Formatos y validaciones relevantes

DID → bytes32

  • didToBytes32 exige:

    • DID no vacío
    • method-specific-id en el último : y debe ser 40 hex
  • Se convierte a bytes32 con padding a la derecha.

Ejemplo de DID válido: did:isbe:model-x:0123456789abcdef0123456789abcdef01234567

fragment (base58) → bytes32

  • fragmentToBytes32(fragment):

    • decodifica base58
    • valida longitud <= 32 bytes
    • padRight a 32 bytes
  • Si excede 32 bytes lanza:

    • Fragmento demasiado largo (>32 bytes)

bytes32 → fragment (base58)

  • bytes32ToFragment elimina trailing zeros antes de codificar base58.

Transformación a W3C DID Document (DidW3CDocument)

Cuando llamas getDidDocument o getDidDocumentByTimestamp, la librería:

  1. Parsea baseDocument (que viene como JSON string desde contrato) y lo “mezcla” (...baseObj) en el retorno.

  2. Convierte controllers (bytes/hex) a DID legible:

    • did:isbe:<modelDeployId>:<first40hex>
  3. Construye verificationMethod con JsonWebKey2020:

    • id = internal.vMethodIds[i]
    • publicKeyJwk = vm.publicKey (ya convertido desde hexToJwk)
  4. Construye relaciones DID Core de forma dinámica:

    • Solo incluye relaciones permitidas:

      • authentication, assertionMethod, keyAgreement, capabilityInvocation, capabilityDelegation
    • Filtra por ventana activa:

      • se incluye solo si now ∈ [notBefore, notAfter]
    • Ignora relaciones no estándar.

Nota: alsoKnownAs solo se incluye si viene con elementos (si el array viene vacío, el campo no aparece en el resultado).


Ejemplos de uso

Insert / update

import IDidDocumentDetailed from "did-isbe-registry/dist/identity/did-isbe-lib/IDidDocumentDetailed.js";

const lib = new IDidDocumentDetailed("https://tu-rpc");

// initialize
const rawInit = await lib.buildInitializeDiDRegistryTx(1);

// insert
const rawInsert = await lib.buildInsertDidDocumentTx(
  "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567",
  JSON.stringify({ "@context": ["https://www.w3.org/ns/did/v1"] }),
  "zQmFragmentBase58",
  JSON.stringify({ kty:"EC", crv:"secp256k1", x:"...", y:"..." }),
  1,
  1700000000,
  1800000000
);

// update baseDocument
const rawUpdateBase = await lib.buildUpdateBaseDocumentTx(
  "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567",
  JSON.stringify({ "@context": ["https://www.w3.org/ns/did/v1"], custom: "v2" })
);

Get DID Document (W3C)

const w3cDoc = await lib.getDidDocument(
  "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567"
);

console.log(w3cDoc.id);
console.log(w3cDoc.verificationMethod);
console.log(w3cDoc.authentication);

Get DID Document by timestamp

const ts = 1_700_000_000;
const w3cDocAtTs = await lib.getDidDocumentByTimestamp(
  "did:isbe:model-x:0123456789abcdef0123456789abcdef01234567",
  ts
);

// relaciones ya filtradas según ts
console.log(w3cDocAtTs.capabilityInvocation);

Notas finales

  • Esta librería asume que el contrato ISBE DID Registry ya está desplegado y accesible vía RPC.

  • El archivo config.json es la pieza central de configuración, ya que define:

    • modelDeployId
    • dirección del contrato DID Registry
    • ruta al ABI correspondiente
  • Las validaciones realizadas en la librería son estructurales y de formato, no de consenso ni de autorización final.

  • Para comprender qué está permitido o prohibido a nivel de identidad, controladores, relaciones o rotaciones de clave, consulta siempre:


© Licencia

Apache-2.0

Copyright © 2025 Comunidad de Madrid & Alastria