This repo is no longer maintained.
elem
with Ethereum and IPFS[OUTDATED] Click below image for demo video.
See also ion, sidetree, sidetree-ethereum.
git clone git@github.com:decentralized-identity/element.git
cd element
npm install
Element follows the Mono Repo structure. Running npm install
will install dependencies in the top level npm project as well as in the following packages:
cd packages/element-lib
In order to run the tests, you need to start Element services
npm run services:start
This will start 3 services:
Check that services are properly initalized with
npm run services:healthcheck
Then you can run the tests (note that running this command will initialize the services if they have not been initialized)
npm test
When you are done, you can stop the Element services by running
npm run services:stop
In order to use element-lib in node or in the browser, you will need to initalize the Sidetree class by providing three interfaces:
A db
interface: this is where all the caching artifacts will be stored. While caching is not technically required for Element to work, CRUD operations will be prohibitively slow without it. To initialize, chose one db adapter (several options are available here):
A storage
interface: the Content Addressed Storage layer where Sidetree operation data will be stored. To initialize, chose one storage adapter (several options are available here):
A blockchain
interface: An interface for the decentralized ledger to be used for anchoring Sidetree operations. Element may only be used with the Ethereum interface, however feel free to reuse this codebase to implement a did method that uses a different ledger.
A parameter
object. Currently the supported parameters are:
did:elem:ropsten
for Element testneterror
would log all the logs, while silly
would only capture the most unimportant onesSee several examples for how to initialize the Sidetree class:
Once you have an instance of the Sidetree class with the suitable adapters, you can access all the helper functions (sidetree.func
) and perform CRUD operations (sidetree.op
). Here are a few code snippet to get you started:
const { Sidetree, MnemonicKeySystem } = require("@transmute/element-lib");
// Instantiate the Sidetree class
const element = new Sidetree(/* See previous section for how to initialize the Sidetree class*/);
// Generate a simple did document model
const mks = new MnemonicKeySystem(MnemonicKeySystem.generateMnemonic());
const primaryKey = await mks.getKeyForPurpose("primary", 0);
const recoveryKey = await mks.getKeyForPurpose("recovery", 0);
const didDocumentModel = element.op.getDidDocumentModel(
primaryKey.publicKey,
recoveryKey.publicKey
);
// Generate Sidetree Create payload
const createPayload = element.op.getCreatePayload(didDocumentModel, primaryKey);
// Create the Sidetree transaction.
// This can potentially take a few minutes if you're not on a local network
const createTransaction = await element.batchScheduler.writeNow(createPayload);
const didUniqueSuffix = element.func.getDidUniqueSuffix(createPayload);
const did = `did:elem:ropsten:${didUniqueSuffix}`;
console.log(`${did} was successfully created`);
const didDocument = await element.resolve(didUniqueSuffix, true);
console.log(
`${did} was successfully resolved into ${JSON.stringify(
didDocument,
null,
2
)}`
);
Add a new key to the did document
// Get last operation data
const operations = await element.db.readCollection(didUniqueSuffix);
const lastOperation = operations.pop();
// Generate update payload for adding a new key
const newKey = await mks.getKeyForPurpose("primary", 1);
const newPublicKey = {
id: "#newKey",
usage: "signing",
type: "Secp256k1VerificationKey2018",
publicKeyHex: newKey.publicKey,
};
const updatePayload = await element.op.getUpdatePayloadForAddingAKey(
lastOperation,
newPublicKey,
primaryKey.privateKey
);
// Create the Sidetree transaction.
const updateTransaction = await element.batchScheduler.writeNow(updatePayload);
const newDidDocument = await element.resolve(didUniqueSuffix, true);
console.log(`${JSON.stringify(newDidDocument, null, 2)} has a new publicKey`);
How to recover a did document using the recovery key if the private key is lost:
// Generate a recovery payload with the inital did document model
const recoveryPayload = await element.op.getRecoverPayload(
didUniqueSuffix,
didDocumentModel,
recoveryKey.privateKey
);
// Send Sidetree transaction
const recoveryTransaction = await element.batchScheduler.writeNow(
recoveryPayload
);
const recoveredDidDocument = await element.resolve(didUniqueSuffix, true);
console.log(`${JSON.stringify(recoveredDidDocument, null, 2)} was recovered`);
// Generate a delete payload this will brick the did forever
const deletePayload = await element.op.getDeletePayload(
didUniqueSuffix,
recoveryKey.privateKey
);
// Send Sidetree transaction
const deleteTransaction = await element.batchScheduler.writeNow(deletePayload);
const deletedDidDocument = await element.resolve(didUniqueSuffix, true);
console.log(`${JSON.stringify(deletedDidDocument, null, 2)} was deleted`);
In the root level directory copy the example config
cp example.env .env
then fill the following values:
http://localhost:8545
for connecting with local ganache network or use an Infura URL that should look like this https://ropsten.infura.io/v3/<API_TOKEN>
/ip4/127.0.0.1/tcp/5001
for connecting with local IPFS node or /dns4/ipfs.infura.io/tcp/5001/https
for connecting through InfuraThen run the following create the api config file
cd packages/element-api
npm run env:create:prod
You may now start the API by running
npm run start # if you have setup a firebase project
npm run start:standalone # to run the standalone express version of the API
All config is checked into source so you can run the app by:
npm run start
npm i
npm run test:contracts
npm run test
npm run lint
npm run coverage
If you have 2fa enabled for npm (and you should!).
lerna version patch
NPM_CONFIG_OTP=123456 lerna publish
npm i -g http-server
serve ./docs
See .travis.yml for setup and test commands for linux.
To run the APP in docker, run
docker run --rm -p 80:80 gjgd/element-app:latest
To run the API in docker, run
docker run --rm -p 80:5002 gjgd/element-api:latest
cd packages/element-app
.env.production
to the API_URL you want to usedocker build -t my-tag .
docker run --rm -p 80:5002 my-tag
lerna publish