diff --git a/package.json b/package.json index 52c0711..4ab15e8 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test:prep:contracts": "node test/prep/setup-contracts.mjs", "test:prep": "run-s test:prep:contracts test", "test:concurrently": "run-p test:prep:blockchain test:prep", - "test": "vitest --run", + "test": "npx vitest --reporter=basic", "test:ci": "vitest --run --coverage", "build": "npm run clean && npm run build:cjs && npm run build:esm && npm run build:type", "build:cjs": "tsc --module commonjs --outDir dist/cjs", @@ -58,5 +58,8 @@ "commitizen": { "path": "./node_modules/cz-conventional-changelog" } + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } } diff --git a/src/constants/VerificationErrorMessages.ts b/src/constants/VerificationErrorMessages.ts new file mode 100644 index 0000000..fc8aaec --- /dev/null +++ b/src/constants/VerificationErrorMessages.ts @@ -0,0 +1,89 @@ +export const TYPES = { + REVOKED: 'REVOKED', + ISSUED: 'ISSUED', + HASH: 'HASH', + IDENTITY: 'IDENTITY', + INVALID: 'INVALID', + ADDRESS_INVALID: 'ADDRESS_INVALID', + NETWORK_INVALID: 'NETWORK_INVALID', + CONTRACT_NOT_FOUND: 'CONTRACT_NOT_FOUND', + INVALID_ARGUMENT: 'INVALID_ARGUMENT', + SERVER_ERROR: 'SERVER_ERROR', + ETHERS_UNHANDLED_ERROR: 'ETHERS_UNHANDLED_ERROR', + CLIENT_NETWORK_ERROR: 'CLIENT_NETWORK_ERROR', +} + +export const MESSAGES = { + [TYPES.REVOKED]: { + failureTitle: 'Document revoked', + successTitle: 'Document has not been revoked', + failureMessage: + 'This document has been revoked by the issuing authority. Please contact them for more details.', + }, + [TYPES.ISSUED]: { + failureTitle: 'Document not issued', + successTitle: 'Document has been issued', + failureMessage: + 'This document cannot be found. Please contact your issuing authority for help or issue the document before trying again.', + }, + [TYPES.HASH]: { + failureTitle: 'Document has been tampered with', + successTitle: 'Document has not been tampered with', + failureMessage: + 'The contents of this document are inaccurate and have been tampered with.', + }, + [TYPES.IDENTITY]: { + failureTitle: 'Document issuer identity is invalid', + successTitle: 'Document issuer has been identified', + failureMessage: 'This document was issued by an invalid issuer.', + }, + [TYPES.INVALID]: { + failureTitle: 'Document is invalid', + successTitle: '', + failureMessage: + 'This document is not valid. Please upload a valid document.', + }, + [TYPES.ADDRESS_INVALID]: { + failureTitle: 'Document store or Token registry address is invalid', + successTitle: '', + failureMessage: + 'Please inform the issuer of this document that they have misconfigured their Document store or Token registry address.', + }, + [TYPES.NETWORK_INVALID]: { + failureTitle: "Document's network field is invalid", + successTitle: '', + failureMessage: + 'This document has an invalid network field. Please contact your issuing authority for help or re-issue the document with a valid network field before trying again.', + }, + [TYPES.CONTRACT_NOT_FOUND]: { + failureTitle: + 'Document store or Token registry address cannot be found', + successTitle: '', + failureMessage: + 'Please inform the issuer of this document that they have misconfigured their Document store or Token registry address.', + }, + [TYPES.INVALID_ARGUMENT]: { + failureTitle: "Document's merkle root is invalid", + successTitle: '', + failureMessage: + 'Please inform the issuer of this document that the merkle root is invalid, or it may have been tampered with.', + }, + [TYPES.SERVER_ERROR]: { + failureTitle: 'Unable to connect to the Ethereum network', + successTitle: '', + failureMessage: + 'We are unable to connect to the Ethereum network, please try again later. If this issue persists, contact us using the feedback link below.', + }, + [TYPES.ETHERS_UNHANDLED_ERROR]: { + failureTitle: "Whoops! It's not you, it's us", + successTitle: '', + failureMessage: + 'We encountered an internal error and cannot determine the cause, please try again later. If this issue persists, contact us using the feedback link below.', + }, + [TYPES.CLIENT_NETWORK_ERROR]: { + failureTitle: + 'Whoops! There seems to be an error verifying the document', + successTitle: '', + failureMessage: 'Please check your network and try again', + }, +} diff --git a/src/index.ts b/src/index.ts index 14045e4..b7188d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,2 @@ -export * from './verify' +export * from './verify/verify' +export * from './utils' diff --git a/src/utils/fragments.test.ts b/src/utils/fragments.test.ts new file mode 100644 index 0000000..b63f732 --- /dev/null +++ b/src/utils/fragments.test.ts @@ -0,0 +1,197 @@ +import { VerificationFragment } from '@tradetrust-tt/tt-verify' +import { interpretFragments, errorMessageHandling } from './fragments' +import { describe, it, expect } from 'vitest' +import { + whenDocumentHashInvalidAndNotIssued, + whenDocumentNotIssued, + whenDocumentValidAndIssuedByDns, + whenDocumentValidAndIssuedByDid, + whenDocumentHashInvalid, + whenDocumentIssuedAndRevokedByEthereumDocStore, + whenDocumentRevokedAndIdentifiedByDnsDid, + whenDocumentIssuerIdentityInvalidDnsTxt, + whenDocumentIssuerIdentityInvalidDid, + whenTransferableDocumentVerified, + whenDocumentAddressInvalid, + whenDocumentNotFound, + whenServerError, + whenUnhandledError, +} from '../../test/fixtures/verify/fragments/verifier-response' + +describe('interpretFragments', () => { + it('should interpret whenDocumentHashInvalidAndNotIssued correctly', () => { + expect( + interpretFragments( + whenDocumentHashInvalidAndNotIssued as VerificationFragment[] + ) + ).toEqual({ + hashValid: false, + issuedValid: false, + identityValid: false, + }) + }) + it('should interpret whenDocumentNotIssued correctly', () => { + expect( + interpretFragments(whenDocumentNotIssued as VerificationFragment[]) + ).toEqual({ + hashValid: true, + issuedValid: false, + identityValid: true, + }) + }) + it('should interpret whenDocumentValidAndIssuedByDns correctly', () => { + expect( + interpretFragments( + whenDocumentValidAndIssuedByDns as VerificationFragment[] + ) + ).toEqual({ + hashValid: true, + issuedValid: true, + identityValid: true, + }) + }) + it('should interpret whenDocumentValidAndIssuedByDid correctly', () => { + expect( + interpretFragments( + whenDocumentValidAndIssuedByDid as VerificationFragment[] + ) + ).toEqual({ + hashValid: true, + issuedValid: true, + identityValid: true, + }) + }) + it('should interpret whenDocumentHashInvalid correctly', () => { + expect( + interpretFragments( + whenDocumentHashInvalid as VerificationFragment[] + ) + ).toEqual({ + hashValid: false, + issuedValid: true, + identityValid: true, + }) + }) + it('should interpret whenDocumentIssuedAndRevokedByEthereumDocStore correctly', () => { + expect( + interpretFragments( + whenDocumentIssuedAndRevokedByEthereumDocStore as VerificationFragment[] + ) + ).toEqual({ + hashValid: true, + issuedValid: false, + identityValid: true, + }) + }) + it('should interpret whenDocumentRevokedAndIdentifiedByDnsDid correctly', () => { + expect( + interpretFragments( + whenDocumentRevokedAndIdentifiedByDnsDid as VerificationFragment[] + ) + ).toEqual({ + hashValid: true, + issuedValid: false, + identityValid: true, + }) + }) + it('should interpret whenDocumentIssuerIdentityInvalidDnsTxt correctly', () => { + expect( + interpretFragments( + whenDocumentIssuerIdentityInvalidDnsTxt as VerificationFragment[] + ) + ).toEqual({ + hashValid: true, + issuedValid: true, + identityValid: false, + }) + }) + it('should interpret whenDocumentIssuerIdentityInvalidDid correctly', () => { + expect( + interpretFragments( + whenDocumentIssuerIdentityInvalidDid as VerificationFragment[] + ) + ).toEqual({ + hashValid: true, + issuedValid: true, + identityValid: false, + }) + }) + it('should interpret whenTransferableDocumentVerified correctly', () => { + expect( + interpretFragments( + whenTransferableDocumentVerified as VerificationFragment[] + ) + ).toEqual({ + hashValid: true, + issuedValid: true, + identityValid: true, + }) + }) +}) + +describe('errorMessageHandling', () => { + it('should return all errors when fragments have multiple errors', () => { + expect( + errorMessageHandling( + whenDocumentHashInvalidAndNotIssued as VerificationFragment[] + ) + ).toStrictEqual(['HASH', 'IDENTITY', 'ISSUED']) + }) + + it('should return hash error when fragments integrity invalid', () => { + expect( + errorMessageHandling( + whenDocumentHashInvalid as VerificationFragment[] + ) + ).toStrictEqual(['HASH']) + }) + + it('should return identity error when fragments identity invalid', () => { + expect( + errorMessageHandling( + whenDocumentIssuerIdentityInvalidDnsTxt as VerificationFragment[] + ) + ).toStrictEqual(['IDENTITY']) + }) + + it('should return revoked error when fragments indicate revoked (issued and revoked with ethereum doc store)', () => { + expect( + errorMessageHandling( + whenDocumentIssuedAndRevokedByEthereumDocStore as VerificationFragment[] + ) + ).toStrictEqual(['REVOKED']) + }) + it('should return revoked error when fragments indicate revoked (identified by DNS-DID but revoked with ethereum doc store)', () => { + expect( + errorMessageHandling( + whenDocumentRevokedAndIdentifiedByDnsDid as VerificationFragment[] + ) + ).toStrictEqual(['REVOKED']) + }) + + it('should return invalid address error when fragments contain invalid address', () => { + expect( + errorMessageHandling( + whenDocumentAddressInvalid as VerificationFragment[] + ) + ).toStrictEqual(['ADDRESS_INVALID']) + }) + + it('should return contract not found error when fragments contain contract not found error message', () => { + expect( + errorMessageHandling(whenDocumentNotFound as VerificationFragment[]) + ).toStrictEqual(['CONTRACT_NOT_FOUND']) + }) + + it('should return server error when fragments contain server error', () => { + expect( + errorMessageHandling(whenServerError as VerificationFragment[]) + ).toStrictEqual(['SERVER_ERROR']) + }) + + it('should return unhandled error when fragments contain an error that was not handled', () => { + expect( + errorMessageHandling(whenUnhandledError as VerificationFragment[]) + ).toStrictEqual(['ETHERS_UNHANDLED_ERROR']) + }) +}) diff --git a/src/utils/fragments.ts b/src/utils/fragments.ts new file mode 100644 index 0000000..0d1c23e --- /dev/null +++ b/src/utils/fragments.ts @@ -0,0 +1,78 @@ +import { + VerificationFragment, + isValid, + utils, + OpenAttestationEthereumDocumentStoreStatusCode, +} from '@tradetrust-tt/tt-verify' +import { TYPES } from '../constants/VerificationErrorMessages' + +interface interpretFragmentsReturnTypes { + hashValid: boolean + issuedValid: boolean + identityValid: boolean +} + +const certificateRevokedOnDidIdentified = ( + fragments: VerificationFragment[] +) => { + const didSignedDocumentStatusFragment = + utils.getOpenAttestationDidSignedDocumentStatusFragment(fragments) + return ( + didSignedDocumentStatusFragment?.reason?.code === + OpenAttestationEthereumDocumentStoreStatusCode.DOCUMENT_REVOKED + ) +} + +export const errorMessageHandling = ( + fragments: VerificationFragment[] +): string[] => { + const { hashValid, issuedValid, identityValid } = + interpretFragments(fragments) + const errors = [] + + if (utils.isDocumentStoreAddressOrTokenRegistryAddressInvalid(fragments)) { + // if the error is because the address is invalid, only return this one + return [TYPES.ADDRESS_INVALID] + } + if (utils.contractNotFound(fragments)) { + // if the error is because the contract cannot be found, only return this one + return [TYPES.CONTRACT_NOT_FOUND] + } + if (utils.serverError(fragments)) { + // if the error is because cannot connect to Ethereum, only return this one + return [TYPES.SERVER_ERROR] + } + + if (!hashValid) errors.push(TYPES.HASH) + if (!identityValid) errors.push(TYPES.IDENTITY) + if (!issuedValid) { + if ( + utils.certificateRevoked(fragments) || + certificateRevokedOnDidIdentified(fragments) + ) + errors.push(TYPES.REVOKED) + else if (utils.invalidArgument(fragments)) { + // this error is caused when the merkle root is wrong, and should always be shown with the DOCUMENT_INTEGRITY error + errors.push(TYPES.INVALID_ARGUMENT) + } else if (utils.certificateNotIssued(fragments)) + errors.push(TYPES.ISSUED) + else if (!hashValid && !identityValid) { + // this error is caused when the document is invalid, only keep this one + return [TYPES.INVALID] + } else { + // if it's some unhandled error that we didn't foresee, only keep this one + return [TYPES.ETHERS_UNHANDLED_ERROR] + } + } + + return errors +} + +export const interpretFragments = ( + fragments: VerificationFragment[] +): interpretFragmentsReturnTypes => { + const hashValid = isValid(fragments, ['DOCUMENT_INTEGRITY']) + const issuedValid = isValid(fragments, ['DOCUMENT_STATUS']) + const identityValid = isValid(fragments, ['ISSUER_IDENTITY']) + return { hashValid, issuedValid, identityValid } +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..c29e81b --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1 @@ +export * from './fragments' diff --git a/src/verify/verfiy.v2.dns-txt-doc-store.integration.test.ts b/src/verify/verfiy.v2.dns-txt-doc-store.integration.test.ts index 68b6dbd..879dadd 100644 --- a/src/verify/verfiy.v2.dns-txt-doc-store.integration.test.ts +++ b/src/verify/verfiy.v2.dns-txt-doc-store.integration.test.ts @@ -5,9 +5,9 @@ import { dnsTxtDocStoreIncorrectDNS, dnsTxtDocStoreIncorrectDocumentStore, dnsTxtDocStoreObfuscated, -} from '../../test/fixtures/v2/dns-txt-doc-store' +} from '../../test/fixtures/verify/v2/dns-txt-doc-store' import { describe, it, expect } from 'vitest' -import { verify, isValid } from '.' +import { verify, isValid } from './verify' import { ethers } from 'ethers' const localProvider = new ethers.providers.JsonRpcProvider( diff --git a/src/verify/index.ts b/src/verify/verify.ts similarity index 83% rename from src/verify/index.ts rename to src/verify/verify.ts index f1ebd58..f7a215d 100644 --- a/src/verify/index.ts +++ b/src/verify/verify.ts @@ -8,7 +8,6 @@ import { DocumentsToVerify, VerificationBuilderOptions, } from '@tradetrust-tt/tt-verify/dist/types/src/types/core' -import { interpretFragments } from '@tradetrust-tt/tradetrust-utils' const verificationBuilder = (builderOptions: VerificationBuilderOptions) => { return originalVerificationBuilder( @@ -24,4 +23,4 @@ const verify = ( return verificationBuilder(builderOptions)(document) } -export { verificationBuilder, verify, interpretFragments, isValid } +export { verificationBuilder, verify, isValid } diff --git a/src/verify/verify.v2.dns-did.integration.test.ts b/src/verify/verify.v2.dns-did.integration.test.ts index 4bd408c..c59c258 100644 --- a/src/verify/verify.v2.dns-did.integration.test.ts +++ b/src/verify/verify.v2.dns-did.integration.test.ts @@ -2,9 +2,9 @@ import { dnsDidSignedAndTampered, dnsDidUnSigned, dnsDidSigned, -} from '../../test/fixtures/v2/dns-did' +} from '../../test/fixtures/verify/v2/dns-did' import { describe, it, expect } from 'vitest' -import { isValid, verify } from '.' +import { isValid, verify } from './verify' import { ethers } from 'ethers' import { v3 } from '@tradetrust-tt/tradetrust' diff --git a/src/verify/verify.v2.dns-txt-token-reg.integration.test.ts b/src/verify/verify.v2.dns-txt-token-reg.integration.test.ts index af26793..9e6696b 100644 --- a/src/verify/verify.v2.dns-txt-token-reg.integration.test.ts +++ b/src/verify/verify.v2.dns-txt-token-reg.integration.test.ts @@ -4,9 +4,9 @@ import { dnsTxtTokenRegTampered, dnsTxtTokenRegIncorrectDNS, dnsTxtTokenRegIncorrectTokenReg, -} from '../../test/fixtures/v2/dns-txt-token-reg' +} from '../../test/fixtures/verify/v2/dns-txt-token-reg' import { describe, it, expect } from 'vitest' -import { verify, isValid } from '.' +import { verify, isValid } from './verify' import { ethers } from 'ethers' const localProvider = new ethers.providers.JsonRpcProvider( diff --git a/src/verify/verify.v3.dns-did.integration.test.ts b/src/verify/verify.v3.dns-did.integration.test.ts index 33332ac..e06707a 100644 --- a/src/verify/verify.v3.dns-did.integration.test.ts +++ b/src/verify/verify.v3.dns-did.integration.test.ts @@ -2,9 +2,9 @@ import { dnsDidSignedAndTampered, dnsDidUnSigned, dnsDidSigned, -} from '../../test/fixtures/v3/dns-did' +} from '../../test/fixtures/verify/v3/dns-did' import { describe, it, expect } from 'vitest' -import { isValid, verify } from '.' +import { isValid, verify } from './verify' import { ethers } from 'ethers' const localProvider = new ethers.providers.JsonRpcProvider( diff --git a/src/verify/verify.v3.dns-txt-doc-store.integration.test.ts b/src/verify/verify.v3.dns-txt-doc-store.integration.test.ts index 69cbdf1..54adc98 100644 --- a/src/verify/verify.v3.dns-txt-doc-store.integration.test.ts +++ b/src/verify/verify.v3.dns-txt-doc-store.integration.test.ts @@ -5,9 +5,9 @@ import { dnsTxtDocStoreIncorrectDNS, dnsTxtDocStoreIncorrectDocumentStore, dnsTxtDocStoreObfuscated, -} from '../../test/fixtures/v3/dns-txt-doc-store' +} from '../../test/fixtures/verify/v3/dns-txt-doc-store' import { describe, it, expect } from 'vitest' -import { verify, isValid } from '.' +import { verify, isValid } from './verify' import { ethers } from 'ethers' const localProvider = new ethers.providers.JsonRpcProvider( diff --git a/src/verify/verify.v3.dns-txt-token-reg.integration.test.ts b/src/verify/verify.v3.dns-txt-token-reg.integration.test.ts index a0bf838..f77977f 100644 --- a/src/verify/verify.v3.dns-txt-token-reg.integration.test.ts +++ b/src/verify/verify.v3.dns-txt-token-reg.integration.test.ts @@ -4,9 +4,9 @@ import { dnsTxtTokenRegTampered, dnsTxtTokenRegIncorrectDNS, dnsTxtTokenRegIncorrectTokenReg, -} from '../../test/fixtures/v3/dns-txt-token-reg' +} from '../../test/fixtures/verify/v3/dns-txt-token-reg' import { describe, it, expect } from 'vitest' -import { verify, isValid } from '.' +import { verify, isValid } from './verify' import { ethers } from 'ethers' const localProvider = new ethers.providers.JsonRpcProvider( diff --git a/test/fixtures/verify/fragments/verifier-response.ts b/test/fixtures/verify/fragments/verifier-response.ts new file mode 100644 index 0000000..a1b4295 --- /dev/null +++ b/test/fixtures/verify/fragments/verifier-response.ts @@ -0,0 +1,994 @@ +// Verification Responses + +export const whenDocumentHashInvalidAndNotIssued = [ + { + data: false, + reason: { + code: 0, + codeString: "DOCUMENT_TAMPERED", + message: "Certificate has been tampered with", + }, + status: "INVALID", + name: "OpenAttestationHash", + type: "DOCUMENT_INTEGRITY", + }, + { + data: { + details: [ + { + address: "0x20bc9C354A18C8178A713B9BcCFFaC2152b53991", + reason: { + code: 2, + codeString: "CONTRACT_ADDRESS_INVALID", + message: "Contract address 0x20bc9C354A18C8178A713B9BcCFFaC2152b53991 is invalid", + }, + issued: false, + }, + ], + issuedOnAll: false, + }, + reason: { + code: 2, + codeString: "CONTRACT_ADDRESS_INVALID", + message: "Contract address 0x20bc9C354A18C8178A713B9BcCFFaC2152b53991 is invalid", + }, + status: "INVALID", + name: "OpenAttestationEthereumDocumentStoreIssued", + type: "DOCUMENT_STATUS", + }, + { + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + name: "OpenAttestationEthereumTokenRegistryMinted", + status: "SKIPPED", + type: "DOCUMENT_STATUS", + }, + { + name: "OpenAttestationEthereumDocumentStoreStatus", + type: "DOCUMENT_STATUS", + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + issued: false, + reason: { + code: 1, + codeString: "DOCUMENT_NOT_ISSUED", + message: + "Certificate 0xda7a25d51e62bc50e1c7cfa17f7be0e5df3428b96f584e5d021f0cd8da97306d has not been issued under contract 0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + }, + }, + ], + issuedOnAll: false, + }, + reason: { + code: 1, + codeString: "DOCUMENT_NOT_ISSUED", + message: + "Certificate 0xda7a25d51e62bc50e1c7cfa17f7be0e5df3428b96f584e5d021f0cd8da97306d has not been issued under contract 0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + }, + status: "INVALID", + }, + { + reason: { + code: 2, + codeString: "SKIPPED", + message: `Document issuers doesn't have "documentStore" / "tokenRegistry" property or doesn't use DNS-TXT type`, + }, + status: "SKIPPED", + name: "OpenAttestationDnsTxtIdentityProof", + type: "ISSUER_IDENTITY", + }, + { + reason: { + code: 0, + codeString: "SKIPPED", + message: `Document was not issued using DNS-DID`, + }, + status: "SKIPPED", + name: "OpenAttestationDnsDidIdentityProof", + type: "ISSUER_IDENTITY", + }, + { + reason: { + code: 0, + codeString: "SKIPPED", + message: `Document is not using DID as top level identifier`, + }, + status: "SKIPPED", + name: "OpenAttestationDidIdentityProof", + type: "ISSUER_IDENTITY", + }, +]; + +export const whenDocumentNotIssued = [ + { + name: "OpenAttestationEthereumDocumentStoreStatus", + type: "DOCUMENT_STATUS", + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + issued: false, + reason: { + code: 1, + codeString: "DOCUMENT_NOT_ISSUED", + message: + "Certificate 0xda7a25d51e62bc50e1c7cfa17f7be0e5df3428b96f584e5d021f0cd8da97306d has not been issued under contract 0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + }, + }, + ], + issuedOnAll: false, + }, + reason: { + code: 1, + codeString: "DOCUMENT_NOT_ISSUED", + message: + "Certificate 0xda7a25d51e62bc50e1c7cfa17f7be0e5df3428b96f584e5d021f0cd8da97306d has not been issued under contract 0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + }, + status: "INVALID", + }, + { + data: true, + status: "VALID", + name: "OpenAttestationHash", + type: "DOCUMENT_INTEGRITY", + }, + { + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + name: "OpenAttestationEthereumTokenRegistryMinted", + status: "SKIPPED", + type: "DOCUMENT_STATUS", + }, + { + name: "OpenAttestationDnsTxtIdentityProof", + type: "ISSUER_IDENTITY", + data: [ + { + status: "VALID", + location: "example.tradetrust.io", + value: "0xe59877ac86c0310e9ddaeb627f42fdee5f793fbe", + }, + ], + status: "VALID", + }, +]; + +export const whenDocumentValidAndIssuedByDns = [ + { + data: true, + status: "VALID", + name: "OpenAttestationHash", + type: "DOCUMENT_INTEGRITY", + }, + { + name: "OpenAttestationEthereumDocumentStoreStatus", + type: "DOCUMENT_STATUS", + data: { + issuedOnAll: true, + revokedOnAny: false, + details: { + issuance: [ + { + issued: true, + address: "0xF02F69B0c9F9Fc74110545E20a4A8CE7e0575fb4", + }, + ], + revocation: [ + { + revoked: false, + address: "0xF02F69B0c9F9Fc74110545E20a4A8CE7e0575fb4", + }, + ], + }, + }, + status: "VALID", + }, + { + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + name: "OpenAttestationEthereumTokenRegistryMinted", + status: "SKIPPED", + type: "DOCUMENT_STATUS", + }, + { + name: "OpenAttestationDnsTxtIdentityProof", + type: "ISSUER_IDENTITY", + data: [ + { + status: "VALID", + location: "example.tradetrust.io", + value: "0xe59877ac86c0310e9ddaeb627f42fdee5f793fbe", + }, + ], + status: "VALID", + }, +]; + +export const whenDocumentValidAndIssuedByDid = [ + { + data: true, + status: "VALID", + name: "OpenAttestationHash", + type: "DOCUMENT_INTEGRITY", + }, + { + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + issued: true, + }, + ], + issuedOnAll: true, + }, + status: "VALID", + name: "OpenAttestationEthereumDocumentStoreIssued", + type: "DOCUMENT_STATUS", + }, + { + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + name: "OpenAttestationEthereumTokenRegistryMinted", + status: "SKIPPED", + type: "DOCUMENT_STATUS", + }, + { + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + revoked: false, + }, + ], + revokedOnAny: false, + }, + status: "VALID", + name: "OpenAttestationEthereumDocumentStoreRevoked", + type: "DOCUMENT_STATUS", + }, + { + name: "OpenAttestationDidIdentityProof", + type: "ISSUER_IDENTITY", + data: [ + { + status: "VALID", + did: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + }, + ], + status: "VALID", + }, +]; + +export const whenDocumentHashInvalid = [ + ...whenDocumentValidAndIssuedByDns.filter((fragment) => fragment.type !== "DOCUMENT_INTEGRITY"), + { + data: false, + reason: { + code: 0, + codeString: "DOCUMENT_TAMPERED", + message: "Certificate has been tampered with", + }, + status: "INVALID", + name: "OpenAttestationHash", + type: "DOCUMENT_INTEGRITY", + }, +]; + +export const whenDocumentRevokedAndIdentifiedByDnsDid = [ + { + type: "DOCUMENT_INTEGRITY", + name: "OpenAttestationHash", + data: true, + status: "VALID", + }, + { + status: "SKIPPED", + type: "DOCUMENT_STATUS", + name: "OpenAttestationEthereumTokenRegistryStatus", + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + }, + { + status: "SKIPPED", + type: "DOCUMENT_STATUS", + name: "OpenAttestationEthereumDocumentStoreStatus", + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "documentStore" or "certificateStore" property or DOCUMENT_STORE method', + }, + }, + { + name: "OpenAttestationDidSignedDocumentStatus", + type: "DOCUMENT_STATUS", + data: { + issuedOnAll: true, + revokedOnAny: true, + details: { + issuance: [ + { + issued: true, + did: "did:ethr:0x1245e5B64D785b25057f7438F715f4aA5D965733", + }, + ], + revocation: [ + { + revoked: true, + address: "0x49b2969bF0E4aa822023a9eA2293b24E4518C1DD", + reason: { + message: + "Document 0x3752f29527952e7ccc6bf4da614d80f2fec9e5bd8b71adf10beb4e6763e6c233 has been revoked under contract 0x49b2969bF0E4aa822023a9eA2293b24E4518C1DD", + code: 5, + codeString: "DOCUMENT_REVOKED", + }, + }, + ], + }, + }, + status: "INVALID", + reason: { + message: + "Document 0x3752f29527952e7ccc6bf4da614d80f2fec9e5bd8b71adf10beb4e6763e6c233 has been revoked under contract 0x49b2969bF0E4aa822023a9eA2293b24E4518C1DD", + code: 5, + codeString: "DOCUMENT_REVOKED", + }, + }, + { + status: "SKIPPED", + type: "ISSUER_IDENTITY", + name: "OpenAttestationDnsTxtIdentityProof", + reason: { + code: 2, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "documentStore" / "tokenRegistry" property or doesn\'t use DNS-TXT type', + }, + }, + { + name: "OpenAttestationDnsDidIdentityProof", + type: "ISSUER_IDENTITY", + data: [ + { + location: "demo-tradetrust.openattestation.com", + key: "did:ethr:0x1245e5B64D785b25057f7438F715f4aA5D965733#controller", + status: "VALID", + }, + ], + status: "VALID", + }, +]; + +export const whenDocumentIssuedAndRevokedByEthereumDocStore = [ + { + type: "DOCUMENT_INTEGRITY", + name: "OpenAttestationHash", + data: true, + status: "VALID", + }, + { + status: "SKIPPED", + type: "DOCUMENT_STATUS", + name: "OpenAttestationEthereumTokenRegistryStatus", + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + }, + { + name: "OpenAttestationEthereumDocumentStoreStatus", + type: "DOCUMENT_STATUS", + data: { + issuedOnAll: true, + revokedOnAny: true, + details: { + issuance: [ + { + issued: true, + address: "0xF02F69B0c9F9Fc74110545E20a4A8CE7e0575fb4", + }, + ], + revocation: [ + { + revoked: true, + address: "0xF02F69B0c9F9Fc74110545E20a4A8CE7e0575fb4", + reason: { + message: + "Document 0x1268951303ad546f18d00f26344b1841d4f6a4f432cec898308a3535ba7f9bdd has been revoked under contract 0xF02F69B0c9F9Fc74110545E20a4A8CE7e0575fb4", + code: 5, + codeString: "DOCUMENT_REVOKED", + }, + }, + ], + }, + }, + reason: { + message: + "Document 0x1268951303ad546f18d00f26344b1841d4f6a4f432cec898308a3535ba7f9bdd has been revoked under contract 0xF02F69B0c9F9Fc74110545E20a4A8CE7e0575fb4", + code: 5, + codeString: "DOCUMENT_REVOKED", + }, + status: "INVALID", + }, + { + status: "SKIPPED", + type: "DOCUMENT_STATUS", + name: "OpenAttestationDidSignedDocumentStatus", + reason: { + code: 0, + codeString: "SKIPPED", + message: "Document was not signed by DID directly", + }, + }, + { + name: "OpenAttestationDnsTxtIdentityProof", + type: "ISSUER_IDENTITY", + data: [ + { + status: "VALID", + location: "inc-brown-jaguar.sandbox.fyntech.io", + value: "0xF02F69B0c9F9Fc74110545E20a4A8CE7e0575fb4", + }, + ], + status: "VALID", + }, + { + status: "SKIPPED", + type: "ISSUER_IDENTITY", + name: "OpenAttestationDnsDidIdentityProof", + reason: { + code: 0, + codeString: "SKIPPED", + message: "Document was not issued using DNS-DID", + }, + }, + { + status: "SKIPPED", + type: "ISSUER_IDENTITY", + name: "OpenAttestationDidIdentityProof", + reason: { + code: 0, + codeString: "SKIPPED", + message: "Document is not using DID as top level identifier or has not been wrapped", + }, + }, +]; + +export const whenDocumentIssuerIdentityInvalidDnsTxt = [ + { + data: true, + status: "VALID", + name: "OpenAttestationHash", + type: "DOCUMENT_INTEGRITY", + }, + { + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + issued: true, + }, + ], + issuedOnAll: true, + }, + status: "VALID", + name: "OpenAttestationEthereumDocumentStoreIssued", + type: "DOCUMENT_STATUS", + }, + { + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + name: "OpenAttestationEthereumTokenRegistryMinted", + status: "SKIPPED", + type: "DOCUMENT_STATUS", + }, + { + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + revoked: false, + }, + ], + revokedOnAny: false, + }, + status: "VALID", + name: "OpenAttestationEthereumDocumentStoreRevoked", + type: "DOCUMENT_STATUS", + }, + { + reason: { + code: 2, + codeString: "SKIPPED", + message: `Document issuers doesn't have "documentStore" / "tokenRegistry" property or doesn't use DNS-TXT type`, + }, + status: "SKIPPED", + name: "OpenAttestationDnsTxtIdentityProof", + type: "ISSUER_IDENTITY", + }, +]; + +export const whenDocumentIssuerIdentityInvalidDid = [ + { + data: true, + status: "VALID", + name: "OpenAttestationHash", + type: "DOCUMENT_INTEGRITY", + }, + { + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + issued: true, + }, + ], + issuedOnAll: true, + }, + status: "VALID", + name: "OpenAttestationEthereumDocumentStoreIssued", + type: "DOCUMENT_STATUS", + }, + { + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + name: "OpenAttestationEthereumTokenRegistryMinted", + status: "SKIPPED", + type: "DOCUMENT_STATUS", + }, + { + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + revoked: false, + }, + ], + revokedOnAny: false, + }, + status: "VALID", + name: "OpenAttestationEthereumDocumentStoreRevoked", + type: "DOCUMENT_STATUS", + }, + { + reason: { + code: 2, + codeString: "SKIPPED", + message: `Document is not using DID as top level identifier`, + }, + status: "SKIPPED", + name: "OpenAttestationDidIdentityProof", + type: "ISSUER_IDENTITY", + }, +]; + +export const whenTransferableDocumentVerified = [ + { type: "DOCUMENT_INTEGRITY", name: "OpenAttestationHash", data: true, status: "VALID" }, + { + status: "SKIPPED", + type: "DOCUMENT_STATUS", + name: "OpenAttestationEthereumDocumentStoreIssued", + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "documentStore" or "certificateStore" property or DOCUMENT_STORE method', + }, + }, + { + name: "OpenAttestationEthereumTokenRegistryMinted", + type: "DOCUMENT_STATUS", + data: { mintedOnAll: true, details: [{ minted: true, address: "0xc3E9eBc6aDA9BA4B4Ce65D71901Cb2307e9670cE" }] }, + status: "VALID", + }, + { + status: "SKIPPED", + type: "DOCUMENT_STATUS", + name: "OpenAttestationEthereumDocumentStoreRevoked", + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "documentStore" or "certificateStore" property or DOCUMENT_STORE method', + }, + }, + { + name: "OpenAttestationDnsTxtIdentityProof", + type: "ISSUER_IDENTITY", + data: [ + { + status: "VALID", + location: "demo-tradetrust.openattestation.com", + value: "0xc3E9eBc6aDA9BA4B4Ce65D71901Cb2307e9670cE", + }, + ], + status: "VALID", + }, +]; + +export const whenDocumentInvalid = [ + { + status: "SKIPPED", + type: "DOCUMENT_INTEGRITY", + name: "OpenAttestationHash", + reason: { + code: 2, + codeString: "SKIPPED", + message: "Document does not have merkle root, target hash or data.", + }, + }, + { + status: "SKIPPED", + type: "DOCUMENT_STATUS", + name: "OpenAttestationEthereumTokenRegistryStatus", + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + }, + { + status: "SKIPPED", + type: "DOCUMENT_STATUS", + name: "OpenAttestationEthereumDocumentStoreStatus", + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "documentStore" or "certificateStore" property or DOCUMENT_STORE method', + }, + }, + { + status: "SKIPPED", + type: "DOCUMENT_STATUS", + name: "OpenAttestationDidSignedDocumentStatus", + reason: { + code: 0, + codeString: "SKIPPED", + message: "Document was not signed by DID directly", + }, + }, + { + status: "SKIPPED", + type: "ISSUER_IDENTITY", + name: "OpenAttestationDnsTxtIdentityProof", + reason: { + code: 2, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "documentStore" / "tokenRegistry" property or doesn\'t use DNS-TXT type', + }, + }, + { + status: "SKIPPED", + type: "ISSUER_IDENTITY", + name: "OpenAttestationDnsDidIdentityProof", + reason: { + code: 0, + codeString: "SKIPPED", + message: "Document was not issued using DNS-DID", + }, + }, + { + status: "SKIPPED", + type: "ISSUER_IDENTITY", + name: "OpenAttestationDidIdentityProof", + reason: { + code: 0, + codeString: "SKIPPED", + message: "Document is not using DID as top level identifier or has not been wrapped", + }, + }, +]; + +export const whenDocumentAddressInvalid = [ + { + type: "DOCUMENT_INTEGRITY", + name: "OpenAttestationHash", + data: true, + status: "VALID", + }, + { + status: "SKIPPED", + type: "DOCUMENT_STATUS", + name: "OpenAttestationEthereumTokenRegistryStatus", + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + }, + { + name: "OpenAttestationEthereumDocumentStoreStatus", + type: "DOCUMENT_STATUS", + data: { + issuedOnAll: true, + revokedOnAny: true, + details: { + issuance: [ + { + issued: true, + address: "0xF02F69B0c9F9Fc74110545E20a4A8CE7e0575fb4", + }, + ], + revocation: [ + { + revoked: true, + address: "0xF02F69B0c9F9Fc74110545E20a4A8CE7e0575fb4", + reason: { + message: "Invalid document store address", + code: 1, + codeString: "DOCUMENT_STORE_ADDRESS_INVALID", + }, + }, + ], + }, + }, + reason: { + code: 1, + codeString: "DOCUMENT_STORE_ADDRESS_INVALID", + message: "Invalid document store address", + }, + status: "INVALID", + }, + { + status: "SKIPPED", + type: "DOCUMENT_STATUS", + name: "OpenAttestationDidSignedDocumentStatus", + reason: { + code: 0, + codeString: "SKIPPED", + message: "Document was not signed by DID directly", + }, + }, + { + name: "OpenAttestationDnsTxtIdentityProof", + type: "ISSUER_IDENTITY", + data: [ + { + status: "VALID", + location: "inc-brown-jaguar.sandbox.fyntech.io", + value: "0xF02F69B0c9F9Fc74110545E20a4A8CE7e0575fb4", + }, + ], + status: "VALID", + }, + { + status: "SKIPPED", + type: "ISSUER_IDENTITY", + name: "OpenAttestationDnsDidIdentityProof", + reason: { + code: 0, + codeString: "SKIPPED", + message: "Document was not issued using DNS-DID", + }, + }, + { + status: "SKIPPED", + type: "ISSUER_IDENTITY", + name: "OpenAttestationDidIdentityProof", + reason: { + code: 0, + codeString: "SKIPPED", + message: "Document is not using DID as top level identifier or has not been wrapped", + }, + }, +]; + +export const whenDocumentNotFound = [ + { + data: true, + status: "VALID", + name: "OpenAttestationHash", + type: "DOCUMENT_INTEGRITY", + }, + { + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + name: "OpenAttestationEthereumTokenRegistryMinted", + status: "SKIPPED", + type: "DOCUMENT_STATUS", + }, + { + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + revoked: false, + }, + ], + revokedOnAny: false, + }, + status: "INVALID", + name: "OpenAttestationEthereumDocumentStoreStatus", + type: "DOCUMENT_STATUS", + reason: { + code: 1, + codeString: "1", + message: "Contract is not found", + }, + }, + { + name: "OpenAttestationDnsTxtIdentityProof", + type: "ISSUER_IDENTITY", + data: [ + { + status: "VALID", + location: "example.tradetrust.io", + value: "0xe59877ac86c0310e9ddaeb627f42fdee5f793fbe", + }, + ], + status: "VALID", + }, +]; + +export const whenInvalidCallArgument = [ + { + data: true, + status: "INVALID", + name: "OpenAttestationHash", + type: "DOCUMENT_INTEGRITY", + }, + { + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + name: "OpenAttestationEthereumTokenRegistryMinted", + status: "SKIPPED", + type: "DOCUMENT_STATUS", + }, + { + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + revoked: false, + }, + ], + revokedOnAny: false, + }, + status: "INVALID", + name: "OpenAttestationEthereumDocumentStoreStatus", + type: "DOCUMENT_STATUS", + reason: { + code: 1, + codeString: "1", + message: "Invalid call arguments", + }, + }, + { + name: "OpenAttestationDnsTxtIdentityProof", + type: "ISSUER_IDENTITY", + data: [ + { + status: "VALID", + location: "example.tradetrust.io", + value: "0xe59877ac86c0310e9ddaeb627f42fdee5f793fbe", + }, + ], + status: "VALID", + }, +]; + +export const whenServerError = [ + { + data: true, + status: "VALID", + name: "OpenAttestationHash", + type: "DOCUMENT_INTEGRITY", + }, + { + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + name: "OpenAttestationEthereumTokenRegistryMinted", + status: "SKIPPED", + type: "DOCUMENT_STATUS", + }, + { + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + revoked: false, + }, + ], + revokedOnAny: false, + }, + status: "INVALID", + name: "OpenAttestationEthereumDocumentStoreStatus", + type: "DOCUMENT_STATUS", + reason: { + code: 500, + codeString: "SERVER_ERROR", + message: "Server error", + }, + }, + { + name: "OpenAttestationDnsTxtIdentityProof", + type: "ISSUER_IDENTITY", + data: [ + { + status: "VALID", + location: "example.tradetrust.io", + value: "0xe59877ac86c0310e9ddaeb627f42fdee5f793fbe", + }, + ], + status: "VALID", + }, +]; + +export const whenUnhandledError = [ + { + data: true, + status: "VALID", + name: "OpenAttestationHash", + type: "DOCUMENT_INTEGRITY", + }, + { + reason: { + code: 4, + codeString: "SKIPPED", + message: 'Document issuers doesn\'t have "tokenRegistry" property or TOKEN_REGISTRY method', + }, + name: "OpenAttestationEthereumTokenRegistryMinted", + status: "SKIPPED", + type: "DOCUMENT_STATUS", + }, + { + data: { + details: [ + { + address: "0x8Fc57204c35fb9317D91285eF52D6b892EC08cD3", + revoked: false, + }, + ], + revokedOnAny: false, + }, + status: "INVALID", + name: "OpenAttestationEthereumDocumentStoreStatus", + type: "DOCUMENT_STATUS", + reason: { + code: 3, + codeString: "UNHANDLED_ERROR", + message: "Unhandled error", + }, + }, + { + name: "OpenAttestationDnsTxtIdentityProof", + type: "ISSUER_IDENTITY", + data: [ + { + status: "VALID", + location: "example.tradetrust.io", + value: "0xe59877ac86c0310e9ddaeb627f42fdee5f793fbe", + }, + ], + status: "VALID", + }, +]; diff --git a/test/fixtures/v2/dns-did.ts b/test/fixtures/verify/v2/dns-did.ts similarity index 100% rename from test/fixtures/v2/dns-did.ts rename to test/fixtures/verify/v2/dns-did.ts diff --git a/test/fixtures/v2/dns-txt-doc-store.ts b/test/fixtures/verify/v2/dns-txt-doc-store.ts similarity index 100% rename from test/fixtures/v2/dns-txt-doc-store.ts rename to test/fixtures/verify/v2/dns-txt-doc-store.ts diff --git a/test/fixtures/v2/dns-txt-token-reg.ts b/test/fixtures/verify/v2/dns-txt-token-reg.ts similarity index 100% rename from test/fixtures/v2/dns-txt-token-reg.ts rename to test/fixtures/verify/v2/dns-txt-token-reg.ts diff --git a/test/fixtures/v3/dns-did.ts b/test/fixtures/verify/v3/dns-did.ts similarity index 100% rename from test/fixtures/v3/dns-did.ts rename to test/fixtures/verify/v3/dns-did.ts diff --git a/test/fixtures/v3/dns-txt-doc-store.ts b/test/fixtures/verify/v3/dns-txt-doc-store.ts similarity index 100% rename from test/fixtures/v3/dns-txt-doc-store.ts rename to test/fixtures/verify/v3/dns-txt-doc-store.ts diff --git a/test/fixtures/v3/dns-txt-token-reg.ts b/test/fixtures/verify/v3/dns-txt-token-reg.ts similarity index 100% rename from test/fixtures/v3/dns-txt-token-reg.ts rename to test/fixtures/verify/v3/dns-txt-token-reg.ts