import { EventName, EventInput } from './dto/shared.dto' if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer const DEFAULT_METRICS_URL = 'https://affinity-metrics.dev.affinity-project.org' let fetch: any if (!fetch) { fetch = require('node-fetch') } const keccak256 = require('keccak256') class Metrics { _linksDescriptionByEventName(eventName: string) { switch (eventName) { case EventName.BLOOM_VAULT_READ: case EventName.BLOOM_VAULT_WRITE: return { linkDescription: 'apiKey', secondaryLinkDescription: 'numberOfVCs' } case EventName.USER_ONBOARDED: return { linkDescription: 'apiKey' } case EventName.VC_VERIFIED: return { linkDescription: 'holderDid' } case EventName.VC_VERIFIED_PER_PARTY: return { linkDescription: 'verifierDid', secondaryLinkDescription: 'vcId' } case EventName.VP_VERIFIED: case EventName.VP_VERIFIED_JWT: return { linkDescription: 'holderDid' } case EventName.VC_SAVED: case EventName.VC_ISSUE_INITIATED: case EventName.SHARED_MESSAGE_CREATED: return { linkDescription: 'vcId', secondaryLinkDescription: 'issuerId' } case EventName.VC_SIGNED: return { linkDescription: 'holderDid', secondaryLinkDescription: 'VcId' } case EventName.VP_SIGNED: case EventName.VP_SIGNED_JWT: return { linkDescription: 'holderDid', secondaryLinkDescription: 'VpId' } case EventName.VC_REVOKED: return { linkDescription: 'issuerDid' } case EventName.DID_CREATED: case EventName.DID_UPDATED: return { linkDescription: 'did' } default: // a safe guard return { linkDescription: 'not implemented' } } } _prepareEventParams(event: EventInput) { // TODO: To check event's `link` and `secondaryLink` values if those are and should be DIDs // const regexDID = /^did:[\w|\d]{2,}:[\w|\d|:|;|\-|=]{10,}/ const { link } = event const linkBuffer = Buffer.from(link) const hashedLinkBuffer = keccak256(linkBuffer) const { name } = event const { linkDescription, secondaryLinkDescription } = this._linksDescriptionByEventName(name) return Object.assign({}, event, { link: hashedLinkBuffer.toString('hex'), linkDescription, ...(secondaryLinkDescription ? { secondaryLinkDescription } : {}) }) } async send( eventInput: any, apiKeyHash: string, metricsUrl?: string, topic: string = 'createEvent', ): Promise { try { metricsUrl = metricsUrl || DEFAULT_METRICS_URL const url = `${metricsUrl}/api/v1/events/${topic}` let event if (topic === 'createEvent') { event = this._prepareEventParams(eventInput) } else { event = eventInput } const body = JSON.stringify(event, null, 2) const headers = { Accept: 'application/json', 'Content-Type': 'application/json', 'Api-Key': apiKeyHash } const response = await fetch(url, { method: 'POST', headers, body }) const result = await response.json() if (response.status.toString().startsWith('2')) { return result } else { throw new Error(result) } } catch (error) { //TODO: error handler and reporter return { error } } } } export const metrics = new Metrics()