Skip to content
This repository has been archived by the owner on Dec 13, 2024. It is now read-only.

Commit

Permalink
feat: migrate interpretFragments function from tradetrust-utils
Browse files Browse the repository at this point in the history
  • Loading branch information
MinHtet-O committed Feb 21, 2024
1 parent 005c7e7 commit ebea287
Show file tree
Hide file tree
Showing 20 changed files with 1,378 additions and 16 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -58,5 +58,8 @@
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"optionalDependencies": {
"fsevents": "^2.3.2"
}
}
89 changes: 89 additions & 0 deletions src/constants/VerificationErrorMessages.ts
Original file line number Diff line number Diff line change
@@ -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',
},
}
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './verify'
export * from './verify/verify'
export * from './utils'
197 changes: 197 additions & 0 deletions src/utils/fragments.test.ts
Original file line number Diff line number Diff line change
@@ -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'])
})
})
78 changes: 78 additions & 0 deletions src/utils/fragments.ts
Original file line number Diff line number Diff line change
@@ -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 }
}
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './fragments'
Loading

0 comments on commit ebea287

Please sign in to comment.