/bba-did-method-handler-ts

A handler for the bba DID method written in TypeScript

Primary LanguageTypeScriptMIT LicenseMIT

bba-did-method-handler-ts

A handler for the bba DID method written in TypeScript.

Table of Contents

click to expand


Background

This library implements a handler for the bba DID method to enable the Ardor Blockchain to act as a DPKI (Public Utility) within the Trust over IP Stack for Self-Sovereign Identity (SSI).

Install

npm install @blobaa/bba-did-method-handler-ts

Usage

Create and Register DID and DID Document

import { DIDDocKey, DIDDocRelationship, DIDDocRelationshipType, DIDDocument } from "@blobaa/did-document-ts";
import { CreateDIDParams, bbaMethodHandler } from "@blobaa/bba-did-method-handler-ts";


const createDID = async(): Promise<void> => {

    /* Even though not necessary, it is recommended to create a DID document Template with
      the @blobaa/did-document-ts package.
    */

    /* create or import DID document public keys  */
    const key = new DIDDocKey();
    await key.generate();
    const publicKey = key.publish();

    /* create verification relationships */
    const authentication = new DIDDocRelationship({
        relationshipType: DIDDocRelationshipType.AUTHENTICATION,
        publicKeys: [ publicKey ]
    });

    /* create document template */
    const document = new DIDDocument({
        relationships: [ authentication ]
    });

    const didDocTsTemplate = document.publish();


    /* You can also use an otherwise created template */
    const didDocTemplate = {
        "@context": [ "https://www.w3.org/ns/did/v1", "https://w3id.org/security/v1" ],
        id: "", // already existing DIDs will be overwritten in the resolution process
        authentication: [
            {
                id: "#z6Mkq9uAju2ezpgoT8q88pqMDLcZ4wJQXZiNKpT4SyJ8xCDQ",
                type: "Ed25519VerificationKey2018",
                publicKeyBase58: "Bhe89enDfHCLLdzRTFsWNF4ZFN2Z7gU1doY8chL82yS2"
            }
        ]
    };


    /* set parameters */
    const params: CreateDIDParams = {
        didDocumentTemplate: didDocTemplate,
        passphrase: "<controller account passphrase>",
        isTestnetDid: true
    };

    try {

        /* create and register DID and DID document */
        const response = await bbaMethodHandler.createDID("https://testardor.jelurida.com", params);

        console.log("DID:", response.did); // did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e
        console.log("DID document:", JSON.stringify(response.didDocument, undefined, 4));
        /*
        {
            "@context": [
                "https://www.w3.org/ns/did/v1",
                "https://w3id.org/security/v1"
            ],
            "id": "did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e",
            "authentication": [
                {
                    "id": "did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e#z6Mkq9uAju2ezpgoT8q88pqMDLcZ4wJQXZiNKpT4SyJ8xCDQ",
                    "type": "Ed25519VerificationKey2018",
                    "publicKeyBase58": "Bhe89enDfHCLLdzRTFsWNF4ZFN2Z7gU1doY8chL82yS2"
                }
            ]
        }
        */

    } catch (e) { /* see error handling */ }
};

createDID();

Resolve DID

import { ResolveDIDParams, bbaMethodHandler } from "@blobaa/bba-did-method-handler-ts";


const resolveDID = async(): Promise<void> => {

    /* set parameters */
    const params: ResolveDIDParams = {
        did:"did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e"
    };

    try {

        /* resolve DID */
        const response = await bbaMethodHandler.resolveDID("https://testardor.jelurida.com", params);

        console.log("DID:", response.did); // did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e
        console.log("DID document", JSON.stringify(response.didDocument, undefined, 4));
        /*
        {
            "@context": [
                "https://www.w3.org/ns/did/v1",
                "https://w3id.org/security/v1"
            ],
            "id": "did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e",
            "authentication": [
                {
                    "id": "did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e#z6Mkq9uAju2ezpgoT8q88pqMDLcZ4wJQXZiNKpT4SyJ8xCDQ",
                    "type": "Ed25519VerificationKey2018",
                    "publicKeyBase58": "Bhe89enDfHCLLdzRTFsWNF4ZFN2Z7gU1doY8chL82yS2"
                }
            ]
        }
        */

    } catch (e) { /* see error handling */ }
};

resolveDID();

Update DID Document

import { DIDDocKey, DIDDocRelationship, DIDDocRelationshipType, DIDDocument } from "@blobaa/did-document-ts";
import { bbaMethodHandler, UpdateDIDDocumentParams } from "@blobaa/bba-did-method-handler-ts";


const updateDIDDocument = async(): Promise<void> => {

    /* create new DID document template */
    const key = new DIDDocKey();
    await key.generate();
    const publicKey = key.publish();

    const authentication = new DIDDocRelationship({
        relationshipType: DIDDocRelationshipType.AUTHENTICATION,
        publicKeysAsRef: [ publicKey ]
    });

    const assertion = new DIDDocRelationship({
        relationshipType: DIDDocRelationshipType.ASSERTION_METHOD,
        publicKeysAsRef: [ publicKey ]
    });

    const document = new DIDDocument({
        relationships: [ authentication, assertion ],
        publicKeys: [ publicKey ]
    });

    const didDocTsTemplate = document.publish();


    /* set parameters */
    const params: UpdateDIDDocumentParams = {
        did:"did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e",
        newDidDocumentTemplate: didDocTsTemplate,
        passphrase: "<controller account passphrase>"
    };

    try {

        /* update DID document */
        const response = await bbaMethodHandler.updateDIDDocument("https://testardor.jelurida.com", params);

        console.log("DID:", response.did); // did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e
        console.log("new DID document", JSON.stringify(response.newDidDocument, undefined, 4));
        /*
        {
            "@context": [
                "https://www.w3.org/ns/did/v1",
                "https://w3id.org/security/v1"
            ],
            "id": "did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e",
            "publicKey": [
                {
                    "id": "did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e#z6MkpM57tyJhB47CwL5mPE8T7C87Sj35dQ1mWZvRyw4TKt3B",
                    "type": "Ed25519VerificationKey2018",
                    "publicKeyBase58": "Atp5Jj4FqWcjpqF4hfAcG6a7d9mEDWmQpZ1W9f6SQfFo"
                }
            ],
            "authentication": [
                "did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e#z6MkpM57tyJhB47CwL5mPE8T7C87Sj35dQ1mWZvRyw4TKt3B"
            ],
            "assertionMethod": [
                "did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e#z6MkpM57tyJhB47CwL5mPE8T7C87Sj35dQ1mWZvRyw4TKt3B"
            ]
        }
        */

    } catch (e) { /* see error handling */ }
};

updateDIDDocument();

Update DID Controller Account

import { bbaMethodHandler, UpdateDIDControllerParams } from "@blobaa/bba-did-method-handler-ts";


const updateDIDController = async(): Promise<void> => {

    /* set parameters */
    const params: UpdateDIDControllerParams = {
        did:"did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e",
        passphrase: "<old controller account passphrase>",
        newPassphrase: "<new controller account passphrase>"
    };

    try {

        /* update DID Controller Account */
        const response = await bbaMethodHandler.updateDIDController("https://testardor.jelurida.com", params);

        console.log("DID:", response.did); // did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e
        console.log("old Account:", response.oldControllerAccount); // "ARDOR-S27P-EHWT-8D2L-937R7"
        console.log("new Account:", response.newControllerAccount); // "ARDOR-YQ26-W5RK-6ATW-G9HRT"

    } catch (e) { /* see error handling */ }
};

updateDIDController();

Deactivate DID

import { DeactivateDIDParams, bbaMethodHandler } from "@blobaa/bba-did-method-handler-ts";


const deactivateDID = async(): Promise<void> => {

    /* set parameters */
    const params: DeactivateDIDParams = {
        did:"did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e",
        passphrase: "<controller account passphrase>",
    };

    try {

        /* deactivate DID */
        const response = await bbaMethodHandler.deactivateDID("https://testardor.jelurida.com", params);

        console.log("deactivated DID:", response.deactivatedDid); // did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e

    } catch (e) { /* see error handling */ }
};

deactivateDID();

Error Handling

There is an unified error handling for all APIs. Every API throws an error in case of any failures or unmet conditions. Every error implements the 'Error' interface of this library. The interface consist of two data fields. The code field contains a value of the 'ErrorCode' enum to indicate the error reason. The description field contains a human readable description of the error reason.

import { bbaMethodHandler, Error, ErrorCode, ResolveDIDParams } from "@blobaa/bba-did-method-handler-ts";


const errorHandlingExample = async(): Promise<void> => {

    const params: ResolveDIDParams = {
        did:"did:bba:t:0239684aef4c0d597b4ca5588f69327bed1fedfd576de35e5099c32807bb520e"
    };

    try {

        /* resolve DID */
        await bbaMethodHandler.resolveDID("https://testardor.jelurida.com", params);

    } catch (e) {

        /* all errors implement the library's Error interface */
        const error = e as Error;

        /* every error has an error code that corresponds to the ErrorCode enum */
        if (error.code === ErrorCode.DID_DEACTIVATED) {
            //  handle did deactivated error here
        }

        console.log(error.code);
        console.log(error.description);
    }
};

errorHandlingExample();

Module Instantiation

The handler module is pre-instantiated and importable via the lower case module name. If you need the class definition, import it via the upper case name.

import { bbaMethodHandler, BBAMethodHandler, ResolveDIDParams } from "@blobaa/bba-did-method-handler-ts";


const moduleInstantiationExample = async (): Promise<void> => {

    const params: ResolveDIDParams = {
        did:"did:bba:t:45e6df15dc0a7d91dcccd24fda3b52c3983a214fb0eed0938321c11ec99403cf"
    };

    try {

        /* use the default instance */
        const response = await bbaMethodHandler.resolveDID("https://testardor.jelurida.com", params);
        console.log(response);

        /* use your own instance */
        const myBBAMethodHandler = new BBAMethodHandler();
        const response = await myBBAMethodHandler.resolveDID("https://testardor.jelurida.com", params);
        console.log(response);

    } catch (e) { /* error handling */}
};

moduleInstantiationExample();

API

The library provides a bba method handler module for handling the CRUD operations. You can import the class definition with the upper case notation BBAMethodHandler or use the pre-instantiated bbaMethodHandler object. It provides the following five asynchronous functions:

createDID

The createDID function lets you create a bba DID. It has the following signature:

type CreateDIDParams = {
    didDocumentTemplate: objectAny; // DDOT used for the DID document
    passphrase: string; // DID controller passphrase
    isTestnetDid?: boolean; // network type selector
    fee?: number; // fees in IGNIS
    feeNQT?: number; // fees in IGNIS NQT
    // automatic fee calculation is used if no fee is specified
}

type CreateDIDResponse = {
    did: string; // created DID
    didDocument: objectAny; // DID document linked to the DID
}

async createDID(url: string, params: CreateDIDParams): Promise<CreateDIDResponse>

resolveDID

The resolveDID function lets you resolve a bba DID. It has the following signature:

type ResolveDIDParams = {
    did: string; // DID to be resolved
}

type ResolveDIDResponse = {
    did: string; // resolved DID
    didDocument: objectAny; // resolved DID document
}

async resolveDID(url: string, params: ResolveDIDParams): Promise<ResolveDIDResponse>

updateDIDDocument

The updateDIDDocument function lets you update a DID document. It has the following signature:

type UpdateDIDDocumentParams = {
    newDidDocumentTemplate: objectAny; // new DDOT
    passphrase: string; // DID controller passphrase
    did: string; // DID to be updated
    fee?: number; // fees in IGNIS
    feeNQT?: number; // fees in IGNIS NQT
    // automatic fee calculation is used if no fee is specified
}

type UpdateDIDDocumentResponse = {
    did: string; // updated DID
    newDidDocument: objectAny; // updated DID document
}

async updateDIDDocument(url: string, params: UpdateDIDDocumentParams): Promise<UpdateDIDDocumentResponse>

updateDIDController

The updateDIDController function lets you update a DID controller. It has the following signature:

type UpdateDIDControllerParams = {
    passphrase: string; // current DID controller passphrase
    newPassphrase: string; // new DID controller passphrase
    did: string; // DID to be updated
    fee?: number; // fees in IGNIS
    feeNQT?: number; // fees in IGNIS NQT
    // automatic fee calculation is used if no fee is specified
}

type UpdateDIDControllerResponse = {
    did: string; // DID to be updated
    newControllerAccount: string; // new DID controller account
    oldControllerAccount: string; // old DID controller account
}

async updateDIDController(url: string, params: UpdateDIDControllerParams): Promise<UpdateDIDControllerResponse>

deactivateDID

The deactivateDID function lets you deactivate a DID. It has the following signature:

type DeactivateDIDParams = {
    did: string; // DID to be deactivated
    passphrase: string; // DID controller passphrase
    fee?: number; // fees in IGNIS
    feeNQT?: number; // fees in IGNIS NQT
    // automatic fee calculation is used if no fee is specified
}

type DeactivateDIDResponse = {
    deactivatedDid: string; // deactivated DID
};

async deactivateDID(url: string, params: DeactivateDIDParams): Promise<DeactivateDIDResponse>

Contributing

PRs accepted.

If editing the Readme, please conform to the standard-readme specification.

License

MIT © Attila Aldemir