diff --git a/examples/chatbot/data.ts b/examples/chatbot/data.ts index 9110fc6..dd70776 100644 --- a/examples/chatbot/data.ts +++ b/examples/chatbot/data.ts @@ -23,6 +23,10 @@ export const rootContextMenu = { title: 'Issue credential', id: 'issue', }, + { + title: 'Revoke credential', + id: 'revoke', + }, { title: 'Request proof', id: 'proof', @@ -40,6 +44,7 @@ export const rootMenuAsQA = { { id: 'poll', text: '⚽ World Cup poll' }, { id: 'rocky', text: '💪 Rocky quotes' }, { id: 'issue', text: 'Issue credential' }, + { id: 'revoke', text: 'Revoke credential' }, { id: 'proof', text: 'Request proof' }, { id: 'help', text: '🆘 Help' }, ], diff --git a/examples/chatbot/index.ts b/examples/chatbot/index.ts index fecbbb3..703dc26 100644 --- a/examples/chatbot/index.ts +++ b/examples/chatbot/index.ts @@ -4,6 +4,7 @@ import { ContextualMenuSelectMessage, ContextualMenuUpdateMessage, CredentialIssuanceMessage, + CredentialRevocationMessage, EMrtdDataRequestMessage, EMrtdDataSubmitMessage, IdentityProofRequestMessage, @@ -58,6 +59,8 @@ app.set('json spaces', 2) const expressHandler = new ExpressEventHandler(app) let phoneNumberCredentialDefinitionId: string | undefined +let phoneNumberRevocationDefinitionId: string | undefined +let phoneNumberRevocationCount: number = 0 type OngoingCall = { wsUrl: string @@ -84,8 +87,11 @@ const server = app.listen(PORT, async () => { try { phoneNumberCredentialDefinitionId = - phoneNumberCredentialType?.id ?? (await apiClient.credentialTypes.import(phoneCredDefData)).id + phoneNumberCredentialType?.id ?? credentialDefinition.id + phoneNumberRevocationDefinitionId = + phoneNumberCredentialType?.revocationId ?? credentialDefinition.revocationId logger.info(`phoneNumberCredentialDefinitionId: ${phoneNumberCredentialDefinitionId}`) + logger.info(`phoneNumberRevocationDefinitionId: ${phoneNumberRevocationDefinitionId}`) } catch (error) { logger.error(`Could not create or retrieve phone number credential type: ${error}`) } @@ -154,7 +160,8 @@ const handleMenuSelection = async (options: { connectionId: string; item: string // Issue credential if (selectedItem === 'issue' || selectedItem === 'Issue credential') { - if (!phoneNumberCredentialDefinitionId || phoneNumberCredentialDefinitionId === '') { + if (!phoneNumberCredentialDefinitionId || phoneNumberCredentialDefinitionId === '' || + !phoneNumberRevocationDefinitionId || phoneNumberRevocationDefinitionId === '') { await sendTextMessage({ connectionId, content: 'Service not available', @@ -170,6 +177,24 @@ const handleMenuSelection = async (options: { connectionId: string; item: string value: '+5712345678', }, ], + revocationDefinitionId: phoneNumberRevocationDefinitionId, + revocationRegistryIndex: phoneNumberRevocationCount += 1, + }) + await apiClient.messages.send(body) + } + } + + if (selectedItem === 'revoke' || selectedItem === 'Revoke credential') { + if (!phoneNumberCredentialDefinitionId || phoneNumberCredentialDefinitionId === '' || + !phoneNumberRevocationDefinitionId || phoneNumberRevocationDefinitionId === '') { + await sendTextMessage({ + connectionId, + content: 'Service not available', + }) + } else { + const body = new CredentialRevocationMessage({ + connectionId, + revocationDefinitionId: phoneNumberRevocationDefinitionId, }) await apiClient.messages.send(body) } diff --git a/packages/main/src/controllers/message/MessageService.ts b/packages/main/src/controllers/message/MessageService.ts index 2f4376f..21817b4 100644 --- a/packages/main/src/controllers/message/MessageService.ts +++ b/packages/main/src/controllers/message/MessageService.ts @@ -241,18 +241,19 @@ export class MessageService { } else if (messageType === CredentialRevocationMessage.type) { const msg = JsonTransformer.fromJSON(message, CredentialRevocationMessage) - this.logger.debug!(`CredentialRevocationMessage: ${JSON.stringify(message)}`) - const credential = (await agent.credentials.getAll()).find(item => item.threadId === message.threadId) + const credential = (await agent.credentials.getAll()).find( + item => + item.getTag('anonCredsRevocationRegistryId') === msg.revocationDefinitionId && + item.connectionId === msg.connectionId, + ) if (credential) { await agent.credentials.sendRevocationNotification({ credentialRecordId: credential.id, revocationFormat: 'anoncreds', - revocationId: `${msg.revocationDefinitionId}::${msg.revocationRegistryIndex}`, + revocationId: `${credential.getTag('anonCredsRevocationRegistryId')}::${credential.getTag('anonCredsCredentialRevocationId')}`, }) } else { - throw new Error( - `No credentials were found for revocation associated with the provided credentialDefinitionId: ${msg.credentialDefinitionId}.`, - ) + throw new Error(`No credentials were found for connection: ${msg.connectionId}.`) } } else if (messageType === InvitationMessage.type) { const msg = JsonTransformer.fromJSON(message, InvitationMessage) diff --git a/packages/model/src/messages/CredentialRevocationMessage.ts b/packages/model/src/messages/CredentialRevocationMessage.ts index f6732f5..b4d6399 100644 --- a/packages/model/src/messages/CredentialRevocationMessage.ts +++ b/packages/model/src/messages/CredentialRevocationMessage.ts @@ -1,13 +1,11 @@ import { Expose } from 'class-transformer' -import { IsString, IsNumber } from 'class-validator' +import { IsString } from 'class-validator' import { BaseMessage, BaseMessageOptions } from './BaseMessage' import { MessageType } from './MessageType' export interface CredentialRevocationMessageOptions extends BaseMessageOptions { - credentialDefinitionId: string revocationDefinitionId: string - revocationRegistryIndex: number } export class CredentialRevocationMessage extends BaseMessage { @@ -19,24 +17,14 @@ export class CredentialRevocationMessage extends BaseMessage { this.threadId = options.threadId this.timestamp = options.timestamp ?? new Date() this.connectionId = options.connectionId - this.credentialDefinitionId = options.credentialDefinitionId this.revocationDefinitionId = options.revocationDefinitionId - this.revocationRegistryIndex = options.revocationRegistryIndex } } public readonly type = CredentialRevocationMessage.type public static readonly type = MessageType.CredentialRevocationMessage - @Expose() - @IsString() - public credentialDefinitionId!: string - @Expose() @IsString() public revocationDefinitionId!: string - - @Expose() - @IsNumber() - public revocationRegistryIndex!: number }