@hirosystems/chainhook-client
Version:
Chainhook TypeScript client
94 lines • 4.03 kB
JavaScript
;
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