Skip to content

Credential Service

The Credential module provides tools to create, issue, revoke, and manage Verifiable Credentials (VCs) on the IDCHAIN blockchain. It simplifies the process of issuing W3C-compliant credentials tied to DIDs and UID Document Schemas.

Overview

Credential Service allows developers to:

  • Request an attestation (prepare an unsigned credential for an attester to sign).
  • Issue a credential (sign and store it on-chain).
  • Revoke a credential (mark it as invalid).
  • Manage credential IDs and interact with publicCredentials.

All issued credentials follow IDCHAIN's VC format (UidCredentialV1) for interoperability across applications.

API Reference

Request Attestation

Credential.requestAttestation(claimerDid, uidDocument, content, attesterDid): Promise<UnsignedVc>

Creates an unsigned Verifiable Credential (VC) for the claimer, ready for attester to sign.

Parameters:

  • claimerDid (Uid): DID URI of the credential subject (the user/claimer).
  • uidDocument (IUidDocument): Schema document for the credential.
  • content (object): Data fields for the credential subject.
  • attesterDid (Uid): DID URI of the attester (issuer).

Returns:

  • UnsignedVc: A verifiable credential object without a proof.

Example:

const unsignedVc = await Credential.requestAttestation(
  userDid.uri,
  schema,
  {
    NIK: "123456789",
    Nama: "John Doe",
    TTL: "2001-01-01",
    status: "Married by choice",
  },
  attesterDid.uri
);
console.log("Unsigned Credential:", unsignedVc);

Issue Attestation

Credential.issueAttestation(credential, submitterDid, submitterAccount): Promise<VerifiableCredential>

Signs and issues a Verifiable Credential on the blockchain.

Parameters:

  • credential (UnsignedVc): The unsigned credential to issue.
  • submitterDid (UidDocument): The attester’s DID Document.
  • submitterAccount (UidKeyringPair): Blockchain account authorized to sign.

Returns:

  • VerifiableCredential: Fully signed and verifiable credential.

Example:

const vc = await Credential.issueAttestation(
  unsignedVc,
  attesterDid,
  accountAttester
);
console.log("Issued Credential:", vc);

Revoke Credential

Credential.revokeCredential(verifier, verifierAccount, credential): Promise<VerifiableCredential>

Marks a credential as revoked on the blockchain.

Parameters:

  • verifier (UidDocument): DID Document of the revoker (issuer).
  • verifierAccount (UidKeyringPair): Blockchain account of the verifier.
  • credential (VerifiableCredential): Credential to revoke.

Returns:

  • VerifiableCredential: Updated credential with revoked status.

Throws:

  • Error("Failed to revoke credential: ...") if the chain operation fails.

Example:

await Credential.revokeCredential(attesterDid, accountAttester, vc);
console.log("Credential revoked");

Revoke Credential By ID

Credential.revokeCredentialById(verifier, verifierAccount, credentialID): Promise<VerifiableCredential>

Marks a credential as revoked on the blockchain.

Parameters:

  • verifier (UidDocument): DID Document of the revoker (issuer).
  • verifierAccount (UidKeyringPair): Blockchain account of the verifier.
  • credentialID (idchain:${string}): it can get from credentialStatus from verifiableCredential

Returns:

  • VerifiableCredential: Updated credential with revoked status.

Throws:

  • Error("Failed to revoke credential: ...") if the chain operation fails.

Example:

await Credential.revokeCredentialById(attesterDid, accountAttester, `idchain:${...}`);
console.log("Credential revoked");

Full Usage Example

import {
  Credential,
  UidDocumentSchema,
  AccountService,
  DidService,
  fromProperties,
  Uid,
  UidDocument,
} from "@idchain-sdk";

async function issueAndRevokeCredential() {
  // Generate accounts and DIDs
  const { mnemonic: attesterMnemonic, account: attester } =
    await AccountService.generateAccount();
  const { mnemonic: userMnemonic, account: user } =
    await AccountService.generateAccount();

  const attesterDid = await DidService.createDidAttester(
    attester,
    {
      authentication: { publicKey: attester.publicKey, type: "ed25519" },
      keyAgreement: { publicKey: attester.publicKey, type: "x25519" },
      assertionMethod: { publicKey: attester.publicKey, type: "ed25519" },
      capabilityDelegation: { publicKey: attester.publicKey, type: "ed25519" },
    },
    async ({ data }) => ({
      keyType: "ed25519",
      signature: attester.sign(data),
    })
  );

  const userDidInfo = await DidService.createDidClaimer(
    user,
    {
      authentication: { publicKey: user.publicKey, type: "ed25519" },
    },
    async ({ data }) => ({
      keyType: "ed25519",
      signature: user.sign(data),
    })
  );

  // Create and store schema
  const schema = fromProperties(
    "KTP Schema",
    {
      NIK: { type: "string" },
      Nama: { type: "string" },
      TTL: { type: "string" },
      status: { type: "string" },
    },
    "V1"
  );
  await UidDocumentSchema.storeSchema(attester, attesterDid.uri, schema);

  // Request credential
  const unsignedVc = await Credential.requestAttestation(
    userDidInfo.document.uri as Uid,
    schema,
    { NIK: "987654321", Nama: "Alice", TTL: "1998-05-10", status: "Single" },
    attesterDid.uri as Uid
  );

  // Issue credential
  const vc = await Credential.issueAttestation(
    unsignedVc,
    attesterDid as UidDocument,
    attester
  );
  console.log("Credential issued:", vc);

  // Revoke credential
  await Credential.revokeCredential(attesterDid as UidDocument, attester, vc);
  console.log("Credential revoked");
}

Error Handling

  • Revocation failure: Throws with details from the blockchain (e.g., if the credential hash is invalid).
  • Unresolved DIDs: Any DID operation (issue or revoke) will fail if the DID cannot be resolved.
  • Signature errors: Will throw if signersForDid cannot produce valid signatures.