docs / gate a fastify route

Gate a Fastify route

Use the framework-agnostic assertOc primitive inside an onRequest hook.

Install

npm install fastify @orangecheck/gate

Minimum working example

import Fastify from 'fastify';
import { assertOc } from '@orangecheck/gate';

const app = Fastify();

app.addHook('onRequest', async (req, reply) => {
  if (!req.url.startsWith('/protected')) return;

  const decision = await assertOc(req.raw, {
    minSats: 100_000,
    minDays: 30,
    address: { from: 'header' },
  });

  if (!decision.ok) {
    reply.code(403).send({ error: decision.reason });
  }
});

app.post('/protected/post', async () => ({ ok: true }));
app.listen({ port: 3000 });

Per-route gate as a preHandler

Prefer the gate at route-level? Use preHandler:

app.post(
  '/post',
  {
    preHandler: async (req, reply) => {
      const decision = await assertOc(req.raw, {
        minSats: 100_000,
        address: { from: 'header' },
      });
      if (!decision.ok) {
        reply.code(403).send({ error: decision.reason });
      }
    },
  },
  async () => ({ ok: true }),
);

Attach the decision to the request

declare module 'fastify' {
  interface FastifyRequest {
    orangecheck?: import('@orangecheck/sdk').CheckResult;
  }
}

app.addHook('preHandler', async (req, reply) => {
  const decision = await assertOc(req.raw, {
    minSats: 100_000,
    address: { from: 'header' },
  });
  if (!decision.ok) {
    reply.code(403).send({ error: decision.reason });
    return;
  }
  req.orangecheck = decision.check;
});

app.post('/post', async (req) => ({ sats: req.orangecheck!.sats }));

Further