UNPKG

@hirosystems/chainhook-client

Version:
94 lines 4.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildServer = exports.BadPayloadRequestError = void 0; const compiler_1 = require("@sinclair/typebox/compiler"); const fastify_1 = require("fastify"); const undici_1 = require("undici"); const logger_1 = require("./util/logger"); const helpers_1 = require("./util/helpers"); const payload_1 = require("./schemas/payload"); const predicates_1 = require("./predicates"); /** * Throw this error when processing a Chainhook Payload if you believe it is a bad request. This * will cause the server to return a `400` status code. */ class BadPayloadRequestError extends Error { constructor(message) { super(message); this.name = this.constructor.name; } } exports.BadPayloadRequestError = BadPayloadRequestError; /** * Build the Chainhook Fastify event server. * @param observer - Event observer options * @param chainhook - Chainhook node options * @param predicates - Predicates to register * @param callback - Event callback function * @returns Fastify instance */ async function buildServer(observer, chainhook, predicates, callback) { async function waitForNode() { logger_1.logger.info(`ChainhookEventObserver looking for chainhook node at ${chainhook.base_url}`); while (true) { try { await (0, undici_1.request)(`${chainhook.base_url}/ping`, { method: 'GET', throwOnError: true }); break; } catch (error) { logger_1.logger.error(error, 'ChainhookEventObserver chainhook node not available, retrying...'); await (0, helpers_1.timeout)(1000); } } } async function isEventAuthorized(request, reply) { if (!(observer.validate_token_authorization ?? true)) return; const authHeader = request.headers.authorization; if (authHeader && authHeader === `Bearer ${observer.auth_token}`) { return; } await reply.code(403).send(); } const ChainhookEventObserver = (fastify, options, done) => { const CompiledPayloadSchema = compiler_1.TypeCompiler.Compile(payload_1.PayloadSchema); fastify.addHook('preHandler', isEventAuthorized); fastify.post('/payload', async (request, reply) => { if ((observer.validate_chainhook_payloads ?? false) && !CompiledPayloadSchema.Check(request.body)) { logger_1.logger.error([...CompiledPayloadSchema.Errors(request.body)], `ChainhookEventObserver received an invalid payload`); await reply.code(422).send(); return; } try { await callback(request.body); await reply.code(200).send(); } catch (error) { if (error instanceof BadPayloadRequestError) { logger_1.logger.error(error, `ChainhookEventObserver bad payload`); await reply.code(400).send(); } else { logger_1.logger.error(error, `ChainhookEventObserver error processing payload`); await reply.code(500).send(); } } }); done(); }; const fastify = (0, fastify_1.default)({ trustProxy: true, logger: logger_1.PINO_CONFIG, pluginTimeout: 0, bodyLimit: observer.body_limit ?? 41943040, // 40MB default }).withTypeProvider(); if (observer.wait_for_chainhook_node ?? true) fastify.addHook('onReady', waitForNode); fastify.addHook('onReady', async () => (0, predicates_1.registerAllPredicatesOnObserverReady)(predicates, observer, chainhook)); fastify.addHook('onClose', async () => (0, predicates_1.removeAllPredicatesOnObserverClose)(observer, chainhook)); await fastify.register(ChainhookEventObserver); return fastify; } exports.buildServer = buildServer; //# sourceMappingURL=server.js.map