import { keccak256 } from "js-sha3" ; import { OpenAttestationDocument as OpenAttestationDocumentV2 , TemplateObject } from "../../__generated__/schema.2.0" ; import { OpenAttestationDocument as OpenAttestationDocumentV3 } from "../../__generated__/schema.3.0" ; import { WrappedDocument as WrappedDocumentV2 } from "../../2.0/types" ; import { WrappedDocument as WrappedDocumentV3 } from "../../3.0/types" ; import { unsaltData } from "../../2.0/salt" ; import { ErrorObject } from "ajv" ; import { isRawV2Document , isRawV3Document , isWrappedV2Document , isWrappedV3Document } from "./guard" ; import { OpenAttestationDocument , WrappedDocument } from "../@types/document" ; export type Hash = string | Buffer ; type Extract < P > = P extends WrappedDocumentV2 < infer T > ? T : never ; export const getData = < T extends WrappedDocumentV2 < OpenAttestationDocumentV2 > > ( document ) : Extract < T > => { return unsaltData ( document . data ) ; } ; /**
 * Sorts the given Buffers lexicographically and then concatenates them to form one continuous Buffer
 */ export function bufSortJoin ( ... args ) { return Buffer . concat ( [ ... args ] . sort ( Buffer . compare ) ) ; } export function hashToBuffer ( hash ) { return Buffer . isBuffer ( hash ) && hash . length === 32 ? hash : Buffer . from ( hash , "hex" ) ; } export function toBuffer ( element ) { return Buffer . isBuffer ( element ) && element . length === 32 ? element : hashToBuffer ( keccak256 ( JSON . stringify ( element ) ) ) ; } /**
 * Turns array of data into sorted array of hashes
 */ export function hashArray ( arr ) { return arr . map ( ( i ) => toBuffer ( i ) ) . sort ( Buffer . compare ) ; } /**
 * Returns the keccak hash of two buffers after concatenating them and sorting them
 * If either hash is not given, the input is returned
 */ export function combineHashBuffers ( first ? , second ? ) { if ( ! second ) { return first ! ; } if ( ! first ) { return second ; } return hashToBuffer ( keccak256 ( bufSortJoin ( first , second ) ) ) ; } param first param second returns export function combineHashString ( first ? , second ? ) { return first && second ? combineHashBuffers ( hashToBuffer ( first ) , hashToBuffer ( second ) ) . toString ( "hex" ) : ( first || second ) ! ; } export function getIssuerAddress ( document ) { if ( isWrappedV2Document ( document ) ) { const data = getData ( document ) ; return data . issuers . map ( ( issuer ) => issuer . certificateStore || issuer . documentStore || issuer . tokenRegistry ) ; } else if ( isWrappedV3Document ( document ) ) { return document . openAttestationMetadata . proof . value ; } throw new Error ( "Unsupported document type: Only can retrieve issuer address from wrapped OpenAttestation v2 & v3 documents." ) ; } export const getMerkleRoot = ( document ) : string => { switch ( true ) { case isWrappedV2Document ( document ) : return document . signature . merkleRoot ; case isWrappedV3Document ( document ) : return document . proof . merkleRoot ; default : throw new Error ( "Unsupported document type: Only can retrieve merkle root from wrapped OpenAttestation v2 & v3 documents." ) ; } } ; export const getTargetHash = ( document ) : string => { switch ( true ) { case isWrappedV2Document ( document ) : return document . signature . targetHash ; case isWrappedV3Document ( document ) : return document . proof . targetHash ; default : throw new Error ( "Unsupported document type: Only can retrieve target hash from wrapped OpenAttestation v2 & v3 documents." ) ; } } ; export const getTemplateURL = ( document ) : string | undefined => { switch ( true ) { case isWrappedV2Document ( document ) : return ( getData ( document ) . $template as TemplateObject ) . url ; case isRawV2Document ( document ) : return document . $template . url ; case isRawV3Document ( document ) || isWrappedV3Document ( document ) : return document . openAttestationMetadata . template . url ; default : throw new Error ( "Unsupported document type: Only can retrieve template url from OpenAttestation v2 & v3 documents." ) ; } } ; export const getDocumentData = ( document ) : OpenAttestationDocument => { if ( isWrappedV3Document ( document ) ) { const omit = ( keys , obj ) : any => Object . fromEntries ( Object . entries ( obj ) . filter ( ( [ k ] ) => ! keys . includes ( k ) ) ) ; return omit ( [ "proof" ] , document ) ; } else if ( isWrappedV2Document ( document ) ) { return getData ( document ) ; } else { throw "Unsupported document type: Only can retrieve document data for wrapped OpenAttestation v2 & v3 documents." ; } } ; export const isTransferableAsset = ( document ) : boolean => { return ( ! ! getData ( document ) ?. issuers [ 0 ] ?. tokenRegistry || document ?. openAttestationMetadata ?. proof ?. method === "TOKEN_REGISTRY" ) ; } ; export const isDocumentRevokable = ( document ) : boolean => { switch ( true ) { case isTransferableAsset ( document ) : return false ; case isWrappedV2Document ( document ) : const issuer = getData ( document ) ?. issuers [ 0 ] ; return ! ! issuer . certificateStore || ! ! issuer . documentStore || issuer . revocation ?. type === "REVOCATION_STORE" ; case isWrappedV3Document ( document ) : const isDidRevokable = document . openAttestationMetadata . proof . method === "DID" && document . openAttestationMetadata . proof . revocation ?. type === "REVOCATION_STORE" ; const isDocumentStoreRevokable = document . openAttestationMetadata . proof . method === "DOCUMENT_STORE" && ! ! document . openAttestationMetadata . proof . value ; return isDidRevokable || isDocumentStoreRevokable ; default : return false ; } } ; export const getAssetId = ( document ) : string => { if ( isTransferableAsset ( document ) ) { return getTargetHash ( document ) ; } throw new Error ( "Unsupported document type: Only can retrieve asset id from wrapped OpenAttestation v2 & v3 transferable documents." ) ; } ; export class SchemaValidationError extends Error { constructor ( message , public validationErrors , public document ) { super ( message ) ; } } export const isSchemaValidationError = ( error ) : error is SchemaValidationError => { return ! ! error . validationErrors ; } ; export { keccak256 } from "js-sha3" ; export const isObfuscated = ( document ) : boolean => { if ( isWrappedV3Document ( document ) ) { return ! ! document . proof . privacy ?. obfuscated ?. length ; } if ( isWrappedV2Document ( document ) ) { return ! ! document . privacy ?. obfuscatedData ?. length ; } throw new Error ( "Unsupported document type: Can only check if there are obfuscated data from wrapped OpenAttestation v2 & v3 documents." ) ; } ; export const getObfuscatedData = ( document ) : string [ ] => { if ( isWrappedV3Document ( document ) ) { return document . proof . privacy ?. obfuscated ; } if ( isWrappedV2Document ( document ) ) { return document . privacy ?. obfuscatedData || [ ] ; } throw new Error ( "Unsupported document type: Can only retrieve obfuscated data from wrapped OpenAttestation v2 & v3 documents." ) ; } ;