Digital Twin

Class Name DigitalTwin
Extends Logger
Source digital-twin.ts
Examples digital-twin.spec.ts

TL;DR: usage examples and a data flow can be found here.

A DigitalTwin is a wrapper, that holds data or references to data. This data can be

  • a Container - This is the most common use case, actual data is stored in the container and the DigitalTwin merely holds a reference to the container.
  • an DigitalTwin - DigitalTwins can be linked together, so an entry can be another DigitalTwin, which allows to navigate through twins to retrieve data properties from linked twins, see getEntry
  • an identity/account address / a contract address
  • bytes32 hashes (e.g. file hashes)

constructor

new DigitalTwin(options, config);

Create new DigitalTwin instance. This will not create a smart contract contract but is used to load existing digital twins. To create a new contract, use the static create function.

Parameters

  1. options - DigitalTwinOptions: runtime-like object with required modules
  2. config - DigitalTwinConfig: digital twin related config
    • accountId - string: identity or account of user, that interacts with digital twin
    • containerConfig - ContainerConfig: address of a DigitalTwin instance, can be ENS or contract address
    • address - string (optional): address of an DigitalTwin instance, can be ENS or contract address
    • description - string: description has to be passed to .create to apply it to to contract
    • factoryAddress - string (optional): factory address can be passed to .create for customer digital twin factory

Returns

DigitalTwin instance

Example

const digitalTwin = new DigitalTwin(
  runtime,
  {
    accountId: '0x0000000000000000000000000000000000000000',
    address: 'sample-digital-twin.somewhere.evan',
  },
);

= Creating Digital Identities =

create

DigitalTwin.create(runtime, config);

Create digital twin contract.

Note, that this function is static. It is used on the DigitalTwin class object and returns a DigitalTwin class instance.

The options argument has the same structure as the options object that is passed to the constructor as it is used for the new DigitalTwin instance. The config argument requires a proper value for the property description.

Parameters

  1. options - ContainerOptions: runtime-like object with required modules
  2. config - DigitalTwinConfig: digital twin related config
    • accountId - string: identity or account of user, that interacts with digital twin
    • containerConfig - ContainerConfig: config, that will be used, when containers are created
    • address - string (optional): ENS address used for digital twin
    • description - string: description has to be passed to .create to apply it to to contract
    • factoryAddress - string (optional): factory address can be passed to .create for customer digital twin factory
    • plugins - { [pluginName: string]: ContainerPlugin } (optional): set of container plugins that should be applied to the twin directly with the creationg (will be passed to the createContainers function)

Returns

Promise returns DigitalTwin: new instance bound to new DigitalTwin

Example

const digitalTwin = await DigitalTwin.create(options, config);
console.log(await digitalTwin.getContractAddress());
// Output:
// 0x0000000000000000000000000000000000001234

= Container =

createContainers

digitalTwin.createContainers(containers);

Create new Container instances and add them as entry to twin.

When a container entry fetched with getEntry or getEntry, the value will become a Container instance and can be used as such.

Parameters

  1. containers - { [id: string]: Partial<ContainerConfig> }: object with containers to create, name is used as entry name in twin

Returns

Promise returns { [id: string]: Container }: map with Container instances

Example

const containers = await twin.createContainers({
  entry1: { template: 'metadata' },
  entry2: { template: 'metadata' },
});

= Entries =

setEntry

digitalTwin.setEntry(name, value, entryType);

Set entry in index contract; entries are unique, setting the same name a second time will overwrite the first value.

Parameters

  1. name - string: entry name
  2. value - string: value to set
  3. entryType - DigitalTwinType: type of given value

Returns

Promise returns void: resolved when done

Example

await digitalTwin.setEntry('myId', accountId, DigitalTwinEntryType.AccountId);
console.log((await digitalTwin.getEntry('myId')).value);
// Output:
// 0x0000000000000000000000000000000000000001

setEntries

digitalTwin.setEntries(arguments);

Set multiple entries at index contract.

Parameters

  1. entries - {[id: string]: DigitalTwinIndexEntry}: entries to set

Returns

Promise returns void: resolved when done

Example

const sampleContractId = '0x00000000000000000000000000000000c0274ac7';
await digitalTwin.setEntries({
  'account':  { value: accountId, entryType: DigitalTwinEntryType.AccountId },
  'contract':  { value: sampleContractId, entryType: DigitalTwinEntryType.GenericContract },
});

const result = (await digitalTwin.getEntries()).map(entry => value);
console.log(result.account.value);
// Output:
// 0x0000000000000000000000000000000000000001
console.log(result.contract.value);
// Output:
// 0x00000000000000000000000000000000c0274ac7

getEntry

digitalTwin.getEntry(name);

Get single entry from index contract.

When this twin has other twins as its entries, properties from those can be selected by building a path of properties.

For example a twin called car may have a link to another twin under the name tire. The twin tire has an entry called metadata. It is possible to retrieve this entry from the twin car with:

const tireMetadata = await car.getEntry('tire/metadata');

Parameters

  1. name - string: entry name or path to data in linked twin

Returns

Promise returns DigitalTwinIndexEntry: entry object

Example

await digitalTwin.setEntry('myId', accountId, DigitalTwinEntryType.AccountId);
console.log((await digitalTwin.getEntry('myId')).value);
// Output:
// 0x0000000000000000000000000000000000000001

getEntries

digitalTwin.getEntries();

Get all entries from index contract.

Returns

Promise returns {[id: string]: DigitalTwinIndexEntry}: key-value map with all entries

Example

const sampleContractId = '0x00000000000000000000000000000000c0274ac7';
await digitalTwin.setEntries({
  'account':  { value: accountId, entryType: DigitalTwinEntryType.AccountId },
  'contract':  { value: sampleContractId, entryType: DigitalTwinEntryType.GenericContract },
});

const result = (await digitalTwin.getEntries()).map(entry => value);
console.log(result.account.value);
// Output:
// 0x0000000000000000000000000000000000000001
console.log(result.contract.value);
// Output:
// 0x00000000000000000000000000000000c0274ac7

= Verifications =

addVerifications

digitalTwin.addVerifications(verifications);

Add verifications to this twin; this will also add verifications to contract description.

If the calling account is the owner of the identity of the digital twin

  • the description will is automatically updated with tags for verifications
  • verifications issued with this function will be accepted automatically

See interface DigitalTwinVerificationEntry for input data format.

Parameters

  1. verifications - DigitalTwinVerificationEntry[]: list of verifications to add

Returns

Promise returns void: resolved when done

Example

await digitalTwin.addVerifications([{ topic: 'exampleVerification' }]);

getVerifications

digitalTwin.getVerifications();

Gets verifications from description and fetches list of verifications for each of them.

See Verifications documentation for details on output data format.

Returns

Promise returns any: list of verification lists from Verifications, getVerifications

Example

await digitalTwin.addVerifications([{ topic: 'exampleVerification' }]);
const verifications = await digitalTwin.getVerifications());

= Descriptions =

getDescription

digitalTwin.getDescription();

Returns description from digital twin.

Returns

Promise returns any: public part of the description

Example

const description = await container.getDescription();
console.dir(description);
// Output:
// { name: 'test twin',
//   description: 'twin from test run',
//   author: 'evan GmbH',
//   version: '0.1.0',
//   dbcpVersion: 2,
//   tags: [ 'evan-digital-twin' ],
//   identity:
//    '0x1a496043385fec8d52f61e2b700413f8e12eb6e7e11649f80c8f4716c1063d06' }

setDescription

digitalTwin.setDescription(description);

Write given description to digital twins DBCP.

Parameters

  1. description - any: description (public part)

Returns

Promise returns void: resolved when done

Example

// get current description
const description = await digitalTwin.getDescription();
console.dir(description);
// Output:
// { name: 'test twin',
//   description: 'twin from test run',
//   author: 'evan GmbH',
//   version: '0.1.0',
//   dbcpVersion: 2,
//   tags: [ 'evan-digital-twin' ],
//   identity:
//    '0x1a496043385fec8d52f61e2b700413f8e12eb6e7e11649f80c8f4716c1063d06' }

// update description
description.version = '0.1.1';
await digitalTwin.setDescription(description);

// fetch again
console.dir(await digitalTwin.getDescription());
// Output:
// { name: 'test twin',
//   description: 'twin from test run',
//   author: 'evan GmbH',
//   version: '0.1.1',
//   dbcpVersion: 2,
//   tags: [ 'evan-digital-twin' ],
//   identity:
//    '0x1a496043385fec8d52f61e2b700413f8e12eb6e7e11649f80c8f4716c1063d06' }

= Profile =

addAsFavorite

digitalTwin.addAsFavorite();

Add the digital twin with given address to profile.

Returns

Promise returns void: resolved when done

Example

const digitalTwin = new DigitalTwin(options.config);
if (await digitalTwin.isFavorite()) {
  console.log('I know this digital twin!');
} else {
  await digitalTwin.addToFavorites();
  console.log('bookmarked digital twin');
}

getFavorites

DigitalTwin.getFavorites();

Gets bookmarked twins from profile.

Note, that this function is called on the Class DigitalTwin and not on an instance of it.

Parameters

  1. options - ContainerOptions: runtime-like object with required modules

Returns

Promise returns void: resolved when done

Example

const favorites = await DigitalTwin.getFavorites(options);
console.dir(favorites);
// Output:
// [
//  'example.somewhere.evan',
//  'another.example.somewhere.else.evan',
//  '0x0000000000000000000000000000000000001234'
// ]

isFavorite

digitalTwin.isFavorite();

Check if this digital twin is bookmarked in profile.

Returns

Promise returns boolean: true if bookmarked

Example

const digitalTwin = new DigitalTwin(options.config);
if (await digitalTwin.isFavorite()) {
  console.log('I know this digital twin!');
} else {
  await digitalTwin.addToFavorites();
  console.log('bookmarked digital twin');
}

removeFromFavorites

digitalTwin.removeFromFavorites();

Removes the current twin from the favorites in profile.

Returns

Promise returns void: resolved when done

Example

const digitalTwin = new DigitalTwin(options.config);
if (await digitalTwin.isFavorite()) {
  await digitalTwin.removeFromFavorites();
  console.log('removed digital twin from favorites');
}

= Utilities =

getValidity

DigitalTwin.getValidity(options, ensAddress);

Check if a valid contract is located under the specified address, which allows to check for twins before actually loading them.

Return value properties have the following meaning:

  • valid: true if contract could not be found or if it doesn’t have the tag “evan-digital-twin”
  • exists: true if a contract address could be found at given ENS address
  • error: an error object, if one of the other properties is false

Note, that this function is called on the Class DigitalTwin and not on an instance of it.

Parameters

  1. options - DigitalTwinOptions: twin runtime options
  2. ensAddress - string: ens address that should be checked

Returns

Promise returns { valid: boolean, exists: boolean, error: Error }: resolved when done

Example

const { valid } = await DigitalTwin.getValidity(runtime, address);
if (!valid) {
  throw new Error(`no valid digital twin found at "${address}"`);
}

ensureContract

digitalTwin.ensureContract();

Check if digital twin contract already has been loaded, load from address / ENS if required. Throws if contract could not be loaded.

This function is more commonly used for internal checks in the DigitalTwin module. For checking, if a given address can be used, it is recommended to use getValidity.

Returns

Promise returns void: resolved when done

Example

let digitalTwin;
try {
  digitalTwin = new DigitalTwin(options, config);
  await digitalTwin.ensureContract();
  // use digital twin
} catch (ex) {
  console.error(`could use digital twin; ${ex.message || ex}`);
}

exportAsTemplate

digitalTwin.exportAsTemplate();

Exports the twin template definition for this twin. Includes the twins dbcp descriptions and all plugins, created out of the twin containers definitions. Can also export container values within the plugin definitions.

You can find a sample twin template here: TwinTemplate

Returns

Promise returns DigitalTwinTemplate: digital twin template definition
  • descriptions - any: digital twin description
  • plugins - `` { [pluginName: string]: ContainerPlugin }``: plugins for all containers

Example

const configWithTemplate = {
  ...defaultConfig,
  ...twinTemplate,
};
const twin = await DigitalTwin.create(runtime, configWithTemplate);
const template = await twin.exportAsTemplate();

console.log(template);
// {
//   "description": { ... },
//   "plugins": {
//     "plugin1": {
//       "description": {
//         ...
//       },
//       "template": {
//         ...
//       }
//     },
//     "pluginX": {
//       ...
//     }
//   }
// }

getContractAddress

digitalTwin.getContractAddress();

Get contract address of underlying DigitalTwin.

Returns

Promise returns string: contract address

Example

const digitalTwin = new DigitalTwin(options, config);
console.log(await digitalTwin.getContractAddress());
// Output:
// 0x000000000000000000000000000000001d327171

Additional Components

Public Properties

defaultDescription (static)

Default description used when no specific description is given to .create.

console.dir(DigitalTwin.defaultDescription);
// Output:
// {
//   name: 'Digital Identity',
//   description: 'Digital Identity Contract',
//   author: '',
//   version: '0.1.0',
//   dbcpVersion: 2
// }

Enums

DigitalTwinEntryType

possible entry types for entries in index

  1. AccountId
  2. Container
  3. FileHash
  4. GenericContract
  5. Hash
  6. DigitalTwin

Interfaces

DigitalTwinConfig

config for digital twin

  1. accountId - string: account id of user, that interacts with digital twin
  2. containerConfig - ContainerConfig: address of a DigitalTwin instance, can be ENS or contract address
  3. address - string (optional): address of an DigitalTwin instance, can be ENS or contract address
  4. description - string (optional): description has to be passed to .create to apply it to to contract
  5. factoryAddress - string (optional): factory address can be passed to .create for customer digital twin factory

DigitalTwinIndexEntry

container for digital twin entry values

  1. entryType - DigitalTwinEntryType (optional): type of entry in index
  2. raw - any (optional): raw value (bytes32 hash)
  3. value - any (optional): decrypted/loaded value

DigitalTwinVerificationEntry

data for verifications for digital twins

  1. topic - string: name of the verification (full path)
  2. descriptionDomain - string (optional): domain of the verification, this is a subdomain under ‘verifications.evan’, so passing ‘example’ will link verifications
  3. disableSubVerifications - boolean (optional): if true, verifications created under this path are invalid, defaults to false
  4. expirationDate - number (optional): expiration date, for the verification, defaults to 0 (does not expire)
  5. verificationValue - any (optional): json object which will be stored in the verification