đŸĒŸExternal Events

Introduction

Guardian will publish a number of events to the NATS server to hook into those events, which extends the function that is suitable to the solution.

Hooks to an external event

To hook into Guardian events, we need to have a client, that is connected to the same NATS instance with Guardian and implement the response function for a specific event.

Below is the sample for .NodeJs and in the case of other languages please refer to Nats.io for complete documentation.

publish/subscribe to events

The events with type=publish is publish/subscribe pattern so that the same message can be received by multiple clients. If there are multiple clients make sure it is handled by duplicate message processing.

import { connect, JSONCodec } from "nats";

(async () => {
  const nc = await connect({ servers: "localhost:4222" });

  const c = JSONCodec();
  const sub = nc.subscribe("externals-events.ipfs_added_file");

  (async () => {
    for await (const m of sub) {
      console.log(`[${sub.getProcessed()}]`, c.decode(m.data));
    }
    console.log("subscription closed");
  })();
})();

To get more information please click https://github.com/nats-io/nats.js#publish-and-subscribe

request/reply events

Some event has a type=request for which we need to subscribe and respond to the event.

Example:

For the before/after IPFS event, if the listener responds with an error then the IPFS service will be skipped and upload/respond to the actual content. This same scenario also happens when we do not have a listener to an event. For example, we can use this to encrypt/decrypt IPFS content file

const responseToIpfsEvent = (type: string, cb: (data: Buffer) => Buffer) => {
        const sub = nc.subscribe(type);
        console.log("√ Listening to IPFS event: %s", type);
        (async () => {
            for await (const m of sub) {
                console.log(`[${sub.getProcessed()} - ${m.subject}]`);
                try {
                    const payload = c.decode(m.data) as any;
                    const body = cb(Buffer.from(payload.content, 'base64'));
                    const responseMessage = { body: body.toString('base64') }
                    const archResponse = zlib.deflateSync(JSON.stringify(responseMessage)).toString('binary');
                    m.respond(StringCodec().encode(archResponse));
                } catch (e) {
                    // It is important that you should handle the content to make sure that is your encrypted/decrypted, skip if that is system ipds file
                    const archResponse = zlib.deflateSync(JSON.stringify({ error: e.message })).toString('binary');
                    m.respond(StringCodec().encode(archResponse));
                }

            }
            console.log("Subscription closed");
        })();
    };

External events list

eventtypepayloadnotes

externals-events.ipfs_added_file

publish

{cid, url}

Event is published when an IPFS file is added

external-events.token_minted

publish

{ tokenId, tokenValue, memo }

When token is minted successfully

external-events.error_logs

publish

{message, type, attributes}

When an error is sent to logger service

external-events.block_run_action_event

publish

{blockType, blockTag, uuid ,data, result}

After runAction is finished, events are called by these blocks:

  1. aggregateDocumentBlock

  2. mintDocumentBlock

  3. sendToGuardianBlock

  4. timerBlock after runAction finish

external-events.ipfs_before_upload_content

request

{content}

The base64 of the content (buffer) to be hooked and modified

external-events.ipfs_after_read_content

request

{content}

The base64 of the content (buffer) to be modified/processed

Example

This example demonstrates the implementation of encryption/decryption of simple IPFS content.

Please refer to https://github.com/hashgraph/guardian/blob/main/common/src/mq/sample-external-client.ts

Last updated