From 1e015ef5c9017bcf6b22ae11c1eae0891b0654c1 Mon Sep 17 00:00:00 2001 From: amonsosanz Date: Thu, 22 Aug 2024 16:52:38 +0200 Subject: [PATCH] Feature: Replace JSONObject type with JsonDocumentObject (#258) * Replace json object type with json document object * 1.17.5 --- package-lock.json | 4 +-- package.json | 2 +- src/credentials/models.ts | 3 ++- src/credentials/utils.ts | 4 +-- src/iden3comm/handlers/common.ts | 14 +++++------ src/iden3comm/handlers/credential-proposal.ts | 6 ++--- src/iden3comm/types/packer.ts | 15 +++++++++++ src/iden3comm/types/protocol/auth.ts | 8 +++--- src/iden3comm/types/protocol/credentials.ts | 4 +-- .../types/protocol/proposal-request.ts | 6 ++--- src/identity/identity-wallet.ts | 1 + src/proof/common.ts | 6 ++--- src/proof/proof-service.ts | 7 +++--- src/proof/verifiers/pub-signals-verifier.ts | 12 ++++----- src/utils/object.ts | 22 +++++++++------- src/verifiable/credential.ts | 3 ++- src/verifiable/presentation.ts | 25 +++++++++++-------- src/verifiable/proof.ts | 4 +-- tests/utils/utils.test.ts | 8 +++--- 19 files changed, 90 insertions(+), 64 deletions(-) diff --git a/package-lock.json b/package-lock.json index d0662365..ec64ca9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@0xpolygonid/js-sdk", - "version": "1.17.4", + "version": "1.17.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@0xpolygonid/js-sdk", - "version": "1.17.4", + "version": "1.17.5", "license": "MIT or Apache-2.0", "dependencies": { "@noble/curves": "^1.4.0", diff --git a/package.json b/package.json index 503e1814..ef0b4923 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@0xpolygonid/js-sdk", - "version": "1.17.4", + "version": "1.17.5", "description": "SDK to work with Polygon ID", "main": "dist/node/cjs/index.js", "module": "dist/node/esm/index.js", diff --git a/src/credentials/models.ts b/src/credentials/models.ts index 0c259a5f..a13b49e9 100644 --- a/src/credentials/models.ts +++ b/src/credentials/models.ts @@ -1,3 +1,4 @@ +import { JsonDocumentObject } from '../iden3comm'; import { CredentialStatusType, MerklizedRootPosition, @@ -32,7 +33,7 @@ export interface CredentialRequest { /** * Credential subject, usually contains claims and identifier */ - credentialSubject: { [key: string]: string | object | number | boolean }; + credentialSubject: JsonDocumentObject; /** * expiration time */ diff --git a/src/credentials/utils.ts b/src/credentials/utils.ts index 00be0862..61a294d0 100644 --- a/src/credentials/utils.ts +++ b/src/credentials/utils.ts @@ -27,8 +27,8 @@ export const getKMSIdByAuthCredential = (credential: W3CCredential): KmsKeyId => if (!credential.type.includes('AuthBJJCredential')) { throw new Error("can't sign with not AuthBJJCredential credential"); } - const x = credential.credentialSubject['x'] as unknown as string; - const y = credential.credentialSubject['y'] as unknown as string; + const x = credential.credentialSubject['x'] as string; + const y = credential.credentialSubject['y'] as string; const pb: PublicKey = new PublicKey([BigInt(x), BigInt(y)]); const kp = keyPath(KmsKeyType.BabyJubJub, pb.hex()); diff --git a/src/iden3comm/handlers/common.ts b/src/iden3comm/handlers/common.ts index fc277791..d35cbd5e 100644 --- a/src/iden3comm/handlers/common.ts +++ b/src/iden3comm/handlers/common.ts @@ -1,6 +1,6 @@ import { getRandomBytes } from '@iden3/js-crypto'; import { - JSONObject, + JsonDocumentObject, JWSPackerParams, ZeroKnowledgeProofRequest, ZeroKnowledgeProofResponse @@ -18,11 +18,11 @@ import { Signer } from 'ethers'; * Returns a Map where the key is the groupId and the value is an object containing the query and linkNonce. * * @param requestScope - An array of ZeroKnowledgeProofRequest objects. - * @returns A Map representing the grouped queries. + * @returns A Map representing the grouped queries. */ const getGroupedQueries = ( requestScope: ZeroKnowledgeProofRequest[] -): Map => +): Map => requestScope.reduce((acc, proofReq) => { const groupId = proofReq.query.groupId as number | undefined; if (!groupId) { @@ -39,8 +39,8 @@ const getGroupedQueries = ( } const credentialSubject = mergeObjects( - existedData.query.credentialSubject as JSONObject, - proofReq.query.credentialSubject as JSONObject + existedData.query.credentialSubject as JsonDocumentObject, + proofReq.query.credentialSubject as JsonDocumentObject ); acc.set(groupId, { @@ -48,13 +48,13 @@ const getGroupedQueries = ( query: { skipClaimRevocationCheck: existedData.query.skipClaimRevocationCheck || proofReq.query.skipClaimRevocationCheck, - ...(existedData.query as JSONObject), + ...existedData.query, credentialSubject } }); return acc; - }, new Map()); + }, new Map()); /** * Processes zero knowledge proof requests. diff --git a/src/iden3comm/handlers/credential-proposal.ts b/src/iden3comm/handlers/credential-proposal.ts index 457db815..ae2496ec 100644 --- a/src/iden3comm/handlers/credential-proposal.ts +++ b/src/iden3comm/handlers/credential-proposal.ts @@ -4,7 +4,7 @@ import { CredentialOffer, CredentialsOfferMessage, IPackageManager, - JSONObject, + JsonDocumentObject, PackerParams } from '../types'; @@ -25,8 +25,8 @@ import { AbstractMessageHandler, IProtocolMessageHandler } from './message-handl /** @beta ProposalRequestCreationOptions represents proposal-request creation options */ export type ProposalRequestCreationOptions = { credentials: ProposalRequestCredential[]; - metadata?: { type: string; data?: JSONObject }; - did_doc?: JSONObject; + metadata?: { type: string; data?: JsonDocumentObject }; + did_doc?: JsonDocumentObject; }; /** diff --git a/src/iden3comm/types/packer.ts b/src/iden3comm/types/packer.ts index 379f518c..ab1dccf7 100644 --- a/src/iden3comm/types/packer.ts +++ b/src/iden3comm/types/packer.ts @@ -23,6 +23,21 @@ export type JSONObject = { [x: string]: JSONValue; }; +/** + * JSON document object + */ +export type JsonDocumentObject = { [key: string]: JsonDocumentObjectValue }; + +/** + * JSON document object allowed values + */ +export type JsonDocumentObjectValue = + | string + | number + | boolean + | JsonDocumentObject + | JsonDocumentObjectValue[]; + export type BasicMessage = { id: string; typ?: MediaType; diff --git a/src/iden3comm/types/protocol/auth.ts b/src/iden3comm/types/protocol/auth.ts index 73143a9b..30e3e4b9 100644 --- a/src/iden3comm/types/protocol/auth.ts +++ b/src/iden3comm/types/protocol/auth.ts @@ -1,5 +1,5 @@ import { ZKProof } from '@iden3/js-jwz'; -import { BasicMessage, JSONObject } from '../packer'; +import { BasicMessage, JsonDocumentObject } from '../packer'; import { PROTOCOL_MESSAGE_TYPE } from '../../constants'; /** AuthorizationResponseMessage is struct the represents iden3message authorization response */ @@ -12,7 +12,7 @@ export type AuthorizationResponseMessage = BasicMessage & { /** AuthorizationMessageResponseBody is struct the represents authorization response data */ export type AuthorizationMessageResponseBody = { - did_doc?: JSONObject; + did_doc?: JsonDocumentObject; message?: string; scope: Array; }; @@ -29,7 +29,7 @@ export type AuthorizationRequestMessageBody = { callbackUrl: string; reason?: string; message?: string; - did_doc?: JSONObject; + did_doc?: JsonDocumentObject; scope: Array; }; @@ -38,7 +38,7 @@ export type ZeroKnowledgeProofRequest = { id: number; circuitId: string; optional?: boolean; - query: JSONObject; + query: JsonDocumentObject; params?: { nullifierSessionId?: string | number; }; diff --git a/src/iden3comm/types/protocol/credentials.ts b/src/iden3comm/types/protocol/credentials.ts index 2dcc0bb9..099a7832 100644 --- a/src/iden3comm/types/protocol/credentials.ts +++ b/src/iden3comm/types/protocol/credentials.ts @@ -1,12 +1,12 @@ import { W3CCredential } from '../../../verifiable'; import { PROTOCOL_MESSAGE_TYPE } from '../../constants'; -import { BasicMessage, JSONObject } from '../packer'; +import { BasicMessage, JsonDocumentObject } from '../packer'; import { ContractInvokeTransactionData } from './contract-request'; /** CredentialIssuanceRequestMessageBody represents data for credential issuance request */ export type CredentialIssuanceRequestMessageBody = { schema: Schema; - data: JSONObject; + data: JsonDocumentObject; expiration: number; }; diff --git a/src/iden3comm/types/protocol/proposal-request.ts b/src/iden3comm/types/protocol/proposal-request.ts index 2439b07f..300d2046 100644 --- a/src/iden3comm/types/protocol/proposal-request.ts +++ b/src/iden3comm/types/protocol/proposal-request.ts @@ -1,4 +1,4 @@ -import { BasicMessage, JSONObject } from '../'; +import { BasicMessage, JsonDocumentObject } from '../'; import { PROTOCOL_MESSAGE_TYPE } from '../../constants'; /** @beta ProposalRequestMessage is struct the represents proposal-request message */ @@ -10,8 +10,8 @@ export type ProposalRequestMessage = BasicMessage & { /** @beta ProposalRequestMessageBody is struct the represents body for proposal-request */ export type ProposalRequestMessageBody = { credentials: ProposalRequestCredential[]; - metadata?: { type: string; data?: JSONObject }; - did_doc?: JSONObject; + metadata?: { type: string; data?: JsonDocumentObject }; + did_doc?: JsonDocumentObject; }; /** @beta ProposalMessage is struct the represents proposal message */ diff --git a/src/identity/identity-wallet.ts b/src/identity/identity-wallet.ts index 47811325..cd05362f 100644 --- a/src/identity/identity-wallet.ts +++ b/src/identity/identity-wallet.ts @@ -1518,6 +1518,7 @@ export class IdentityWallet implements IIdentityWallet { txId = await this.transitState(did, oldTreeState, isOldStateGenesis, ethSigner, prover); break; } catch (err) { + // eslint-disable-next-line no-console console.warn( `Error while transiting state, retrying state transition, attempt: ${attempt}`, err diff --git a/src/proof/common.ts b/src/proof/common.ts index ac46de5e..cee4c43f 100644 --- a/src/proof/common.ts +++ b/src/proof/common.ts @@ -18,7 +18,7 @@ import { } from '../verifiable'; import { Merklizer, Options, Path } from '@iden3/js-jsonld-merklization'; import { byteEncoder } from '../utils'; -import { JSONObject } from '../iden3comm'; +import { JsonDocumentObject } from '../iden3comm'; import { Claim } from '@iden3/js-iden3-core'; import { poseidon } from '@iden3/js-crypto'; @@ -112,7 +112,7 @@ export type QueryMetadata = PropertyQuery & { merklizedSchema: boolean; }; -export const parseCredentialSubject = (credentialSubject?: JSONObject): PropertyQuery[] => { +export const parseCredentialSubject = (credentialSubject?: JsonDocumentObject): PropertyQuery[] => { // credentialSubject is empty if (!credentialSubject) { return [{ operator: QueryOperators.$noop, fieldName: '' }]; @@ -240,7 +240,7 @@ export const parseQueryMetadata = async ( export const parseQueriesMetadata = async ( credentialType: string, ldContextJSON: string, - credentialSubject: JSONObject, + credentialSubject: JsonDocumentObject, options: Options ): Promise => { const queriesMetadata = parseCredentialSubject(credentialSubject); diff --git a/src/proof/proof-service.ts b/src/proof/proof-service.ts index d75e56c6..3bb8bcbd 100644 --- a/src/proof/proof-service.ts +++ b/src/proof/proof-service.ts @@ -39,7 +39,8 @@ import { JSONObject, ZeroKnowledgeProofRequest, ZeroKnowledgeProofResponse, - PROTOCOL_CONSTANTS + PROTOCOL_CONSTANTS, + JsonDocumentObject } from '../iden3comm'; import { cacheLoader } from '../schema-processor'; import { ICircuitStorage, IStateStorage } from '../storage'; @@ -286,7 +287,7 @@ export class ProofService implements IProofService { } const propertiesMetadata = parseCredentialSubject( - proofReq.query.credentialSubject as JSONObject + proofReq.query.credentialSubject as JsonDocumentObject ); if (!propertiesMetadata.length) { throw new Error('no queries in zkp request'); @@ -428,7 +429,7 @@ export class ProofService implements IProofService { const [first, ...rest] = queryMetadata.fieldName.split('.'); let v = credential.credentialSubject[first]; for (const part of rest) { - v = (v as JSONObject)[part]; + v = (v as JsonDocumentObject)[part]; } if (typeof v === 'undefined') { throw new Error(`credential doesn't contain value for field ${queryMetadata.fieldName}`); diff --git a/src/proof/verifiers/pub-signals-verifier.ts b/src/proof/verifiers/pub-signals-verifier.ts index 81a06622..e8565f6e 100644 --- a/src/proof/verifiers/pub-signals-verifier.ts +++ b/src/proof/verifiers/pub-signals-verifier.ts @@ -32,7 +32,7 @@ import { parseQueriesMetadata, QueryMetadata } from '../common'; import { Operators } from '../../circuits'; import { calculateQueryHashV3 } from './query-hash'; import { JsonLd } from 'jsonld/jsonld-spec'; -import { PROTOCOL_CONSTANTS, JSONObject } from '../../iden3comm'; +import { PROTOCOL_CONSTANTS, JSONObject, JsonDocumentObject } from '../../iden3comm'; /** * Verify Context - params for pub signal verification @@ -257,7 +257,7 @@ export class PubSignalsVerifier { const queriesMetadata = await parseQueriesMetadata( query.type, JSON.stringify(context), - query.credentialSubject as JSONObject, + query.credentialSubject as JsonDocumentObject, { documentLoader: loader } @@ -423,15 +423,15 @@ export class PubSignalsVerifier { ); // verify query - let schema: JSONObject; + let schema: JsonDocumentObject; const ldOpts = { documentLoader: this._documentLoader }; try { - schema = (await ldOpts.documentLoader(query.context || '')).document as JSONObject; + schema = (await ldOpts.documentLoader(query.context || '')).document as JsonDocumentObject; } catch (e) { throw new Error(`can't load schema for request query`); } const ldContextJSON = JSON.stringify(schema); - const credentialSubject = query.credentialSubject as JSONObject; + const credentialSubject = query.credentialSubject as JsonDocumentObject; const schemaId: string = await Path.getTypeIDFromContext( ldContextJSON, query.type || '', @@ -540,7 +540,7 @@ export class PubSignalsVerifier { const queriesMetadata = await parseQueriesMetadata( query.type, JSON.stringify(context), - query.credentialSubject as JSONObject, + query.credentialSubject as JsonDocumentObject, { documentLoader: loader } diff --git a/src/utils/object.ts b/src/utils/object.ts index 7705213b..e69e06e7 100644 --- a/src/utils/object.ts +++ b/src/utils/object.ts @@ -5,10 +5,14 @@ * @param otherCredSubject - The second object to merge. * @returns A new object with the merged properties. */ -type obj = { [k: string]: unknown }; -export function mergeObjects(credSubject: obj, otherCredSubject: obj) { - let result = {} as obj; +import { JsonDocumentObject } from '../iden3comm'; + +export function mergeObjects( + credSubject: JsonDocumentObject, + otherCredSubject: JsonDocumentObject +) { + let result = {} as JsonDocumentObject; const credSubjectKeys = Object.keys(credSubject); for (const key of credSubjectKeys) { @@ -16,17 +20,17 @@ export function mergeObjects(credSubject: obj, otherCredSubject: obj) { if (typeof credSubject[key] !== 'object' && typeof otherCredSubject[key] !== 'object') { throw new Error('Invalid query'); } - const subjectProperty = credSubject[key] as obj; - const otherSubjectProperty = otherCredSubject[key] as obj; + const subjectProperty = credSubject[key] as JsonDocumentObject; + const otherSubjectProperty = otherCredSubject[key] as JsonDocumentObject; const propertyOperators = Object.keys(subjectProperty); - const subjectPropertyResult: obj = {}; + const subjectPropertyResult: JsonDocumentObject = {}; for (const operatorKey of propertyOperators) { if (typeof otherSubjectProperty[operatorKey] !== 'undefined') { - const operatorValue1 = subjectProperty[operatorKey] as obj; + const operatorValue1 = subjectProperty[operatorKey] as JsonDocumentObject; const operatorValue2 = otherSubjectProperty[operatorKey]; subjectPropertyResult[operatorKey] = [ ...new Set([ - ...((subjectPropertyResult[operatorKey] as Array) ?? []), + ...((subjectPropertyResult[operatorKey] as Array) ?? []), operatorValue1, ...(Array.isArray(operatorValue2) ? operatorValue2 : [operatorValue2]) ]) @@ -36,7 +40,7 @@ export function mergeObjects(credSubject: obj, otherCredSubject: obj) { } } result[key] = { - ...(otherCredSubject[key] as obj), + ...(otherCredSubject[key] as JsonDocumentObject), ...subjectPropertyResult }; } diff --git a/src/verifiable/credential.ts b/src/verifiable/credential.ts index 8f5f2bc8..7c635d3b 100644 --- a/src/verifiable/credential.ts +++ b/src/verifiable/credential.ts @@ -29,6 +29,7 @@ import { import * as jsonld from 'jsonld/lib'; import * as ldcontext from 'jsonld/lib/context'; +import { JsonDocumentObject } from '../iden3comm'; /** * W3C Verifiable credential @@ -45,7 +46,7 @@ export class W3CCredential { refreshService?: RefreshService; displayMethod?: DisplayMethod; issuanceDate?: string; - credentialSubject: { [key: string]: object | string | number | boolean } = {}; + credentialSubject: JsonDocumentObject = {}; credentialStatus!: CredentialStatus; issuer = ''; credentialSchema!: CredentialSchema; diff --git a/src/verifiable/presentation.ts b/src/verifiable/presentation.ts index 7d3448bb..6496d9e9 100644 --- a/src/verifiable/presentation.ts +++ b/src/verifiable/presentation.ts @@ -2,7 +2,7 @@ import { VerifiableConstants } from './constants'; import { Options, Path } from '@iden3/js-jsonld-merklization'; import { W3CCredential } from './credential'; import { QueryMetadata } from '../proof'; -import { JSONObject } from '../iden3comm'; +import { JsonDocumentObject } from '../iden3comm'; export const stringByPath = (obj: { [key: string]: unknown }, path: string): string => { const parts = path.split('.'); @@ -36,13 +36,13 @@ export const buildFieldPath = async ( return path; }; -export const findValue = (fieldName: string, credential: W3CCredential): JSONObject => { +export const findValue = (fieldName: string, credential: W3CCredential): JsonDocumentObject => { const [first, ...rest] = fieldName.split('.'); let v = credential.credentialSubject[first]; for (const part of rest) { - v = (v as JSONObject)[part]; + v = (v as JsonDocumentObject)[part]; } - return v as JSONObject; + return v as JsonDocumentObject; }; export const createVerifiablePresentation = ( @@ -72,15 +72,18 @@ export const createVerifiablePresentation = ( } }; - let result: JSONObject = {}; + let result: JsonDocumentObject = {}; for (const query of queries) { const parts = query.fieldName.split('.'); - const current: JSONObject = parts.reduceRight((acc: JSONObject, part: string) => { - if (result[part]) { - return { [part]: { ...(result[part] as JSONObject), ...acc } }; - } - return { [part]: acc }; - }, findValue(query.fieldName, credential) as JSONObject); + const current: JsonDocumentObject = parts.reduceRight( + (acc: JsonDocumentObject, part: string) => { + if (result[part]) { + return { [part]: { ...(result[part] as JsonDocumentObject), ...acc } }; + } + return { [part]: acc }; + }, + findValue(query.fieldName, credential) as JsonDocumentObject + ); result = { ...result, ...current }; } diff --git a/src/verifiable/proof.ts b/src/verifiable/proof.ts index 2867c505..cb196dd8 100644 --- a/src/verifiable/proof.ts +++ b/src/verifiable/proof.ts @@ -8,7 +8,7 @@ import { import { TreeState } from '../circuits'; import { Hex, Signature } from '@iden3/js-crypto'; import { Claim, DID } from '@iden3/js-iden3-core'; -import { JSONObject } from '../iden3comm'; +import { JsonDocumentObject, JSONObject } from '../iden3comm'; /** * Represents the published state of the issuer @@ -220,7 +220,7 @@ export class BJJSignatureProof2021 { */ export interface ProofQuery { allowedIssuers?: string[]; - credentialSubject?: { [key: string]: unknown }; + credentialSubject?: JsonDocumentObject; schema?: string; // string url claimId?: string; credentialSubjectId?: string; diff --git a/tests/utils/utils.test.ts b/tests/utils/utils.test.ts index 9c25419e..65b38769 100644 --- a/tests/utils/utils.test.ts +++ b/tests/utils/utils.test.ts @@ -1,10 +1,10 @@ import { expect } from 'chai'; -import { buildDIDFromEthPubKey, JSONObject, mergeObjects } from '../../src'; +import { buildDIDFromEthPubKey, JsonDocumentObject, mergeObjects } from '../../src'; import { Blockchain, buildDIDType, DidMethod, NetworkId } from '@iden3/js-iden3-core'; describe('merge credential subjects to create query', () => { - it('should merge two valid JSONObjects correctly', () => { - const testCases: JSONObject[] = [ + it('should merge two valid JsonDocumentObjects correctly', () => { + const testCases: JsonDocumentObject[] = [ { subj1: { documentType: { @@ -145,7 +145,7 @@ describe('merge credential subjects to create query', () => { for (const testCase of testCases) { expect( - mergeObjects(testCase.subj1 as JSONObject, testCase.subj2 as JSONObject) + mergeObjects(testCase.subj1 as JsonDocumentObject, testCase.subj2 as JsonDocumentObject) ).to.deep.equal(testCase.expectedResult); } });