sdk

The SDK docs should be read as integration setup, not as a loose API dump. Start with the Express middleware if you are integrating a provider endpoint. Reach for HalotClientonly when you are building requester-side automation or a custom client flow.


Installation

bash
$ npm install @halot/sdk

Middleware

halot() is the exported provider integration path. It handles quote challenges, receipt verification, and result reporting against the facilitator endpoints. A production route needs a registered serviceIdand provider-signed report headers.

That serviceId must already exist on Halot. The real order is: register the provider, register the service under that provider, then use the returned service ID in middleware.

ts
import { Wallet } from 'ethers';
import { createActorAuthHeaders, halot, nowIso } from '@halot/sdk';
import express from 'express';

const app = express();
app.use(express.json());

const providerId = process.env.HALOT_PROVIDER_ID!;
const providerWallet = new Wallet(process.env.HALOT_PROVIDER_PRIVATE_KEY!);

app.post('/jobs', halot({
  serviceId: 'svc_research',
  providerHeaders: async (_req, context) => {
    if (context.providerId !== providerId) {
      throw new Error('Provider assignment mismatch');
    }

    return createActorAuthHeaders(providerWallet, {
      actorId: providerId,
      role: 'provider',
      method: 'POST',
      path: '/facilitator/report',
      timestamp: nowIso(),
    });
  },
}), (req, res) => {
  const { jobId, providerId: assignedProviderId, requesterAddress } = req.halot;
  const text = runProviderLogic(req.body, { jobId, providerId: assignedProviderId, requesterAddress });
  res.json({ text, model: 'gpt-5.4' });
});

HALOT_PROVIDER_IDis the provider ID returned by provider registration. HALOT_PROVIDER_PRIVATE_KEYis the private key for that provider actor authority. You can load those values from a secret manager or the CLI-generated authority file instead of env; the important part is that /facilitator/reportis signed by the same provider actor that owns the registered service.

The middleware uses the hosted Halot target by default. For a local Halot server, pass target: 'local'.

If one route can serve multiple registered services, pass a resolver instead of a fixed string. That keeps the canonical Halot service identity while still letting the provider branch on request data.

ts
app.post('/generate', halot({
  serviceId: (req) => {
    switch (req.body.model) {
      case 'gpt-5.4':
        return 'svc_text_gpt54';
      case 'gpt-5.4-mini':
        return 'svc_text_gpt54mini';
      case 'gpt-5.4-nano':
        return 'svc_text_gpt54nano';
      default:
        throw new Error('Unsupported model');
    }
  },
  providerHeaders: async (_req, context) => {
    if (context.providerId !== providerId) {
      throw new Error('Provider assignment mismatch');
    }

    return createActorAuthHeaders(providerWallet, {
      actorId: providerId,
      role: 'provider',
      method: 'POST',
      path: '/facilitator/report',
      timestamp: nowIso(),
    });
  },
}), async (req, res) => {
  const text = await runProviderLogic(req.body);
  res.json({ text, model: req.body.model });
});

Requester Client

HalotClientis the optional requester-side helper. It automates the requester flow: trigger a 402 challenge, sign the payment requirement, prepare the job, fund the prepared job through your adapter, confirm the funding transaction, then retry the target endpoint with x-halot-receipt.

ts
import { HalotClient } from '@halot/sdk';
import { Wallet } from 'ethers';

const wallet = new Wallet(process.env.HALOT_PRIVATE_KEY!);

const client = new HalotClient({
  wallet: {
    address: wallet.address,
    signMessage: (message) => wallet.signMessage(message),
  },
  funding: {
    async fund(preparedJob) {
      const transactionHash = await fundPreparedJobOnChain(preparedJob);
      return { transactionHash };
    },
  },
  defaultNetwork: '0g:mainnet',
});

const response = await client.request('https://provider.example/jobs', {
  method: 'POST',
  body: { query: 'halot' },
});

Auth & Payment Helpers

The SDK also exports helpers for actor-signed provider or verifier requests and for x402 requirement encoding and signing.

ts
import {
  createActorAuthHeaders,
  decodePaymentRequirement,
  encodePaymentRequirement,
  signPaymentRequirement,
} from '@halot/sdk';

Types & Schemas

Shared types such as Quote, PreparedJob, Job, and the Zod schemas behind them are exported for runtime validation and custom integrations.

ts
import {
  JobSchema,
  PaymentAuthorizationSchema,
  PaymentRequirementSchema,
  QuoteSchema,
} from '@halot/sdk';
Note: AggregatorClientis an internal helper used by the middleware. The public SDK exports are halot, HalotClient, auth helpers, payment helpers, and shared types. Provider routes may also pass a request-based serviceId resolver when one endpoint fronts multiple registered services.