import { hashToBuffer , SchemaValidationError } from "../shared/utils" ; import { MerkleTree } from "../shared/merkle" ; import { SchemaId } from "../shared/@types/document" ; import { WrappedDocument } from "./types" ; import { digestCredential } from "../3.0/digest" ; import { validateSchema as validate } from "../shared/validate" ; import { WrapDocumentOptionV3 } from "../shared/@types/wrap" ; import { OpenAttestationDocument } from "../__generated__/schema.3.0" ; import { encodeSalt , salt } from "./salt" ; import { validateW3C } from "./validate" ; import { getSchema } from "../shared/ajv" ; const getExternalSchema = ( schema ? ) => ( schema ? { schema } : { } ) ; export const wrapDocument = async < T extends OpenAttestationDocument > ( credential , options ) : Promise < WrappedDocument < T > > => { const document = { version : SchemaId . v3 as SchemaId . v3 , ... getExternalSchema ( options . externalSchemaId ) , ... credential , } ; if ( ! document [ "@context" ] ) { document [ "@context" ] = [ "https://www.w3.org/2018/credentials/v1" ] ; } if ( Array . isArray ( document [ "@context" ] ) && ! document [ "@context" ] . includes ( "https://schemata.openattestation.com/com/openattestation/1.0/OpenAttestation.v3.json" ) ) { document [ "@context" ] . push ( "https://schemata.openattestation.com/com/openattestation/1.0/OpenAttestation.v3.json" ) ; } const salts = salt ( document ) ; const digest = digestCredential ( document , salts , [ ] ) ; const batchBuffers = [ digest ] . map ( hashToBuffer ) ; const merkleTree = new MerkleTree ( batchBuffers ) ; const merkleRoot = merkleTree . getRoot ( ) . toString ( "hex" ) ; const merkleProof = merkleTree . getProof ( hashToBuffer ( digest ) ) . map ( ( buffer ) => buffer . toString ( "hex" ) ) ; const verifiableCredential = { ... document , proof : { type : "OpenAttestationMerkleProofSignature2018" , proofPurpose : "assertionMethod" , targetHash : digest , proofs : merkleProof , merkleRoot , salts : encodeSalt ( salts ) , privacy : { obfuscated : [ ] , } , } , } ; const errors = validate ( verifiableCredential , getSchema ( SchemaId . v3 ) ) ; if ( errors . length > 0 ) { throw new SchemaValidationError ( "Invalid document" , errors , verifiableCredential ) ; } await validateW3C ( verifiableCredential ) ; return verifiableCredential ; } ; export const wrapDocuments = async < T extends OpenAttestationDocument > ( documents , options ) : Promise < WrappedDocument < T > [ ] > => { const verifiableCredentials = await Promise . all ( documents . map ( ( document ) => wrapDocument ( document , options ) ) ) ; const merkleTree = new MerkleTree ( verifiableCredentials . map ( ( verifiableCredential ) => verifiableCredential . proof . targetHash ) . map ( hashToBuffer ) ) ; const merkleRoot = merkleTree . getRoot ( ) . toString ( "hex" ) ; return verifiableCredentials . map ( ( verifiableCredential ) => { const digest = verifiableCredential . proof . targetHash ; const merkleProof = merkleTree . getProof ( hashToBuffer ( digest ) ) . map ( ( buffer ) => buffer . toString ( "hex" ) ) ; return { ... verifiableCredential , proof : { ... verifiableCredential . proof , proofs : merkleProof , merkleRoot , } , } ; } ) ; } ;