import { GenericKeypair } from '../GenericKeypair'; import { MamWriter, MAM_MODE, MamReader} from 'mam.ts'; import { DIDReader } from '../DecentralizedIdentifier/DIDReader'; import { DID } from './DID'; interface MAM_Object{ "payload":string; "root":string; "address":string; } export class DIDWriter { private uuid : string; //private didMamStreamRoot : string; //private nextMamStreamRoot : string; private writer : MamWriter; private mamResults : MAM_Object[]; private previousRootes : string[]; private rootOfTheRootes : string; private amountOfDIDKeys : number; private provider : string; private didState : DID; private IsDIDRetrieved: Boolean; //Private account data private seed : string; //private keys : Keypair[]; static async createDIDWriter(provider: string, seed: string) : Promise { let writer : DIDWriter = new DIDWriter(provider, seed); let reader = new DIDReader(provider,writer.GetRootofRoots()); if( !await reader.QueryDID() ) { return null; } writer.didState = reader.GetState(); return writer; } private constructor(provider: string, seed: string) { //Check for empty string on didMamStreamRoot. Empty string means that no DID stream exists so a new stream needs to be created this.provider = provider; this.seed = seed; //initialize variables this.mamResults = []; this.previousRootes = []; // Current amount of keys from reader state this.amountOfDIDKeys = 0; this.didState = null; this.writer = new MamWriter(provider, seed, MAM_MODE.PUBLIC); this.writer.catchUpThroughNetwork() .then( (previousRootes)=> { this.previousRootes = previousRootes; }) .catch( (err) => { console.log(err); }); this.rootOfTheRootes = this.writer.getNextRoot(); this.uuid = this.writer.getNextRoot(); } /** * Publishes the new DID state to the ledger. This function makes the changes made to the DID permanant on the ledger, use with caution. * If this function is never called, the changes wi * ll not be permanent. */ public async PublishChanges() : Promise { return new Promise (async (resolve, reject) => { let addresses : Array = []; //for each DID in our array, publish the did on the iota ledger. for(let i = 0; i < this.mamResults.length; i++){ let transactions = await this.writer.attach(this.mamResults[i].payload,this.mamResults[i].address); for(let k = 0; k < transactions.length; k++) { addresses.push(transactions[k].address); } } resolve(addresses); }); } /** * Creates the format of the DID Create that will be put on iota. */ public CreateNewDID(keypair : GenericKeypair) { //Controle if(!this.didState == null){ console.log("Cannot create a new DID while a DID already exists.") return; } this.rootOfTheRootes = this.writer.getNextRoot(); // Create the layout for the DID Create on Iota let didCreate ={ "version" : "0.1.0", "command" : "createDID", "data" : { "@context" : "https://w3id.org/did/v1", "did" : "did:iota:main:"+this.uuid, "publicKey" : [ { "id" : "did:iota:main:"+this.uuid+"#keys-"+(this.amountOfDIDKeys+1), "type" : "RsaVerificationKey2018", "publicKeyPem": keypair.GetPublicKey() } ], "authentication" : [ { "type" : "MAM", "publicKey" : "did:iota:main:"+this.uuid+"#mamstream-"+1 } ] } }; //Pushing the newly created DID to our array. this.mamResults.push(this.writer.create(JSON.stringify(didCreate))); } /** * Adds a keypair to the DID. * Remember to PublishChanges to publish the changes permanently to the Ledger. * @param keypair The keypair to add to the DID. */ public AddKeypair( keypair : GenericKeypair) { let didKeyPair ={ "version" : "0.1.0", "command" : "addKeyPair", "data" : { "publicKey" : [ { "id" : "did:iota:main:"+this.uuid+"#keys-"+this.amountOfDIDKeys+1, "type" : "RsaVerificationKey2018", "publicKeyPem": keypair.GetPublicKey() } ] } }; //this.didState.addPublicKey(didKeyPair.data.publicKey[0].id,didKeyPair.data.publicKey[0].type,didKeyPair.data.publicKey[0].id, didKeyPair.data.publicKey[0].) //Pushing the newly created keyPair to our array. this.mamResults.push(this.writer.create(JSON.stringify(didKeyPair))); } /** * Removes a keypair from the DID. If the keypair is used in an Authentication Protocol, the protocol will be removed aswell. If the keypair is not part of the DID, the function does nothing. * Remember to PublishChanges to publish the changes permanently to the Ledger. * @param keypair The keypair to remove from the DID. * @returns Succes of the function. Returns false if the keypair was never part of the DID. */ public RemoveKeypair( keypair : GenericKeypair ) : boolean { return true; } /** * Template function is incomplete */ public AddDIDAuthentication() { } /** * Template function is incomplete */ public RemoveDIDAuthentication() { } /** * Template function is incomplete */ public AddServicePoint(name : string, type : string, url : string) { let didServicePoint ={ "version" : "0.1.0", "command" : "addServicePoint", "data" : { "service" : [ { "id" : "did:iota:main:"+this.uuid+name, "type" : type, "serviceEndpoint": url } ] } }; //this.didState.addPublicKey(didKeyPair.data.publicKey[0].id,didKeyPair.data.publicKey[0].type,didKeyPair.data.publicKey[0].id, didKeyPair.data.publicKey[0].) //Pushing the newly created keyPair to our array. this.mamResults.push(this.writer.create(JSON.stringify(didServicePoint))); } /** * Template function is incomplete */ public RemoveServicePoint() { } public GetRootofRoots() : string { return this.rootOfTheRootes; } }