Registro del DID desde la API
Esta página cubre los pasos 3 al 6 del onboarding: crear la transacción de inserción, firmarla off-chain y enviarla a la red. Es el modo directo para integradores que ya tienen el DID y la clave pública generados (pasos 1 y 2 de Onboarding del DID).
Todos los endpoints de escritura devuelven una transacción sin firmar. La firma ocurre siempre en el cliente, nunca en el servidor.
Requisitos previos
- DID, clave pública y proof ya generados (ver Onboarding del DID → pasos 1 y 2).
- Una librería de firma de transacciones EVM: ethers.js (Node.js),
eth_account(Python), o el binario internocli-tx-savesi el equipo de ISBE te lo ha proporcionado. - La URL del Swagger del entorno (ver Entornos).
3. Crear la transacción de inserción
Abre la Swagger UI del entorno y localiza la operación:
POST /api/v1/contract/insertFirstDidDocument
Cuerpo de la petición:
{
"did": "did:isbe:uc:z12kVar5p6bD5WCjEJcQ18Zyt8XV",
"vMethodId": "9lfZ28jdUsYo75lVHmGNIc6oUpkjSFtxiCLjDGn28IM",
"proof": "0x70bc9d8cdf399369f0b213a7da5985e5cd533d85bb5562615c98bfb5ac33d40e491436a3086a87ccaae773cbc20a098ef70928dc24b2c636dc8413965f2959a51c",
"publicKeyType": "secp256k1",
"publicKey": "0x041243f50ac70fc996ccc92a2119ce64b6f70bbf4ca1fd3b292fffa8939d06c4f75143e0f7e23b32139cce3a33d2207f937c0b85714d207877e3eca7137dc33214",
"notBefore": 1774602263,
"notAfter": 2090221463,
"alsoKnownAs": "urn:oid:organizationIdentifier:ISBE",
"from": "0xAe0E493C67f75381b0954644836A3C16c79D0dFD"
}
Significado de cada campo
| Campo | Descripción |
|---|---|
did | El DID generado en el paso 2. |
baseDocument (opcional) | JSON con el @context del DID Document. Si se omite, se aplica el contexto por defecto. |
vMethodId | Identificador del verification method. 32 bytes aleatorios en base64url (43 caracteres sin padding). Recomendado: thumbprint JWK de la clave pública. |
proof | Firma ECDSA con la clave privada secp256k1 sobre el material que enlaza el DID con la clave pública. La devuelve directamente did-gen did y demuestra al smart contract que quien envía la transacción controla efectivamente la clave que pretende registrar bajo ese DID. |
publicKeyType | Para el primer registro siempre secp256k1. |
publicKey | Clave pública hexadecimal sin comprimir (con prefijo 0x04). |
notBefore | Timestamp Unix (segundos) desde el que la clave es válida. Habitualmente ahora. |
notAfter | Timestamp Unix de expiración. Recomendado: ~10 años en el futuro. |
alsoKnownAs | Identificador alternativo. Para entidades organizativas usa urn:oid:organizationIdentifier:<TU_CODIGO>. |
from | EOA derivada de tu secp256k1. |
Usa epochconverter.com para obtener notBefore (ahora) y notAfter (futuro).
Respuesta
La API devuelve una transacción sin firmar lista para ser firmada:
{
"to": "0x00000000000000000000000000000000000015Be",
"data": "0x648b2748...",
"gasLimit": "0x4c4b40",
"gasPrice": "0xfa0",
"chainId": "0x8131",
"nonce": "0xe",
"value": "0x0",
"from": "0xAe0E493C67f75381b0954644836A3C16c79D0dFD"
}
Cópialo entero para el siguiente paso.
4. Firmar la transacción
La transacción devuelta por la API ya viene con todos los campos necesarios (to, data, gasLimit, gasPrice, chainId, nonce, value, from) en formato hexadecimal JSON-RPC. Solo hay que firmarla con la clave privada de la EOA from. A continuación tienes dos ejemplos equivalentes — usa el que encaje con tu stack.
Opción A — Node.js con ethers.js
npm install ethers
import { Wallet, Transaction } from "ethers";
const PRIVATE_KEY = "0x<PRIVATE_KEY>";
const raw = {
to: "0x00000000000000000000000000000000000015Be",
data: "0x648b2748...",
gasLimit: "0x4c4b40",
gasPrice: "0xfa0",
chainId: "0x8131",
nonce: "0xe",
value: "0x0",
from: "0xAe0E493C67f75381b0954644836A3C16c79D0dFD",
};
const wallet = new Wallet(PRIVATE_KEY);
// `from` no forma parte de la tx serializada — se descarta antes de firmar
const tx = Transaction.from({ ...raw, from: undefined });
const signedRawTransaction = await wallet.signTransaction(tx);
console.log(signedRawTransaction);
// 0x01f9034c8281310e820fa0834c4b40...
Este es exactamente el patrón que usan los scripts internos del repositorio isbe-identity-did-api (scripts/addVM.ts, scripts/initialize.ts).
Opción B — Python con eth_account
pip install eth-account
from eth_account import Account
PRIVATE_KEY = "0x<PRIVATE_KEY>"
raw = {
"to": "0x00000000000000000000000000000000000015Be",
"data": "0x648b2748...",
"gasLimit": "0x4c4b40",
"gasPrice": "0xfa0",
"chainId": "0x8131",
"nonce": "0xe",
"value": "0x0",
}
acct = Account.from_key(PRIVATE_KEY)
# eth_account usa los nombres en snake_case esperados por web3.py
tx = {
"to": raw["to"],
"data": raw["data"],
"gas": int(raw["gasLimit"], 16),
"gasPrice": int(raw["gasPrice"], 16),
"chainId": int(raw["chainId"], 16),
"nonce": int(raw["nonce"], 16),
"value": int(raw["value"], 16),
}
signed = acct.sign_transaction(tx)
print(signed.raw_transaction.hex())
# 01f9034c8281310e820fa0834c4b40...
Opción C — CLI interno cli-tx-save
Si el equipo de ISBE te ha proporcionado el binario cli-tx-save, el comando equivalente es:
./sign-tx sign -p 0x<PRIVATE_KEY> -t '<RESPONSE_BODY>'
Donde <RESPONSE_BODY> es la respuesta JSON completa del paso 3, entre comillas simples.
Resultado
En cualquier caso obtienes una signed raw transaction del tipo:
0x01f9034c8281310e820fa0834c4b40...
Guarda esa cadena completa: es lo que necesitarás en el siguiente paso.
5. Enviar la transacción
En la Swagger UI, localiza:
POST /api/v1/transactions/send
Cuerpo:
{
"signedRawTransaction": "0x01f9034c8281310e820fa0834c4b40..."
}
Respuesta esperada (éxito):
{
"tx_hash": "0xb508e46adfc36822e48dde1d9f1f5d2122a1ce6852cf5e0afe6c978da04648c5",
"receipt": {
"blockHash": "0x52afb6108087cdca826289da40cc7339a4e190922f8480afd924c0ddd9d31109",
"blockNumber": 3907283,
"status": 1,
"from": "0xAe0E493C67f75381b0954644836A3C16c79D0dFD",
"to": "0x00000000000000000000000000000000000015Be",
"gasUsed": "221678",
"logs": [
{
"address": "0x00000000000000000000000000000000000015Be",
"topics": ["0x78c431540f7778eb787241a03d7401cd2c95ddb232c918f172f86e4c804d5439"]
}
]
}
}
200 OK— Transacción minada y recibo disponible.206 Partial Content— Transacción enviada pero el recibo todavía no está disponible (caso de redes con latencia). Eltx_hashya es válido para consultas.400 Bad Request— La transacción no se ha podido procesar. Revisa la firma, elnoncey los fondos.
6. Verificar el resultado
Para confirmar que el DID está registrado correctamente, resuelve el DID Document:
GET /api/v1/identifiers/{did}
Llama con Accept: application/did+ld+json o application/did+json. La respuesta debe incluir tu verificationMethod recién registrado.
curl -H "Accept: application/did+ld+json" \
https://did-registry.portal.redisbe.com/api/v1/identifiers/did:isbe:uc:z12kVar5p6bD5WCjEJcQ18Zyt8XV
Próximos pasos
Una vez registrado el DID:
- Añadir una clave P-256 — Necesaria para emitir credenciales verificables.
- Crear la cadena de confianza — Si la entidad va a actuar como TAO o TI.
- Resolver DIDs — Para verificar credenciales emitidas por terceros.