quota-protocol-sdk
v0.1.0
Published
TypeScript SDK for the Quota Protocol gateway — route external API calls through your prepaid, on-chain quota.
Downloads
168
Maintainers
Readme
quota-protocol-sdk
TypeScript client for the Quota Protocol gateway. Route your external API
calls through a prepaid, on-chain quota: the gateway meters every request and
debits the forward you bought in USDC. Swap your baseURL, pass your key, and
handle balance/limit errors with typed exceptions.
Devnet preview. The gateway and contracts run on Solana devnet.
Install
npm install quota-protocol-sdkRequires Node 18+ (uses the global fetch). For older runtimes, pass a fetch
implementation in the options.
Quick start
import { QuotaClient, QuotaError } from "quota-protocol-sdk";
const quota = new QuotaClient({
baseUrl: "https://gateway.quota.xyz", // your gateway, not the vendor
apiKey: process.env.QUOTA_KEY!, // qk_devnet_...
tier: "gpt-4o-mini-standard", // the tier your key buys against
});
try {
const { data, quota: q } = await quota.post("/v1/chat/completions", {
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello!" }],
});
console.log(data);
console.log(`debited ${q.debited}, ${q.remaining} calls left`);
} catch (err) {
if (err instanceof QuotaError && err.isQuotaExhausted) {
console.warn("Out of quota — buy or top up a forward.");
} else {
throw err;
}
}Use with the official OpenAI SDK
The gateway is OpenAI/REST-compatible — point the OpenAI client's baseURL at
your tier and use your Quota key:
import OpenAI from "openai";
import { QuotaClient } from "quota-protocol-sdk";
const quota = new QuotaClient({ baseUrl, apiKey, tier: "gpt-4o-mini-standard" });
const openai = new OpenAI({
apiKey, // your Quota gateway key
baseURL: `${quota.gatewayUrl}/v1`, // -> https://.../gateway/<tier>/v1
});
const res = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "hi" }],
});The buyer's Quota key never reaches the vendor — the gateway strips it and injects the protocol's upstream credential server-side.
API
new QuotaClient(options)
| Option | Type | Default | Notes |
| ----------------- | --------------- | ------- | -------------------------------------------------- |
| baseUrl | string | — | Gateway base URL (no /gateway/...). |
| apiKey | string | — | Your gateway key (qk_devnet_...). |
| tier | string | — | Tier slug, e.g. gpt-4o-mini-standard. |
| callsPerRequest | number | 1 | Calls metered per proxied request. |
| timeoutMs | number | 30000 | Per-request timeout. |
| fetch | typeof fetch | global | Inject for testing / non-global-fetch runtimes. |
Methods
get gatewayUrl→${baseUrl}/gateway/${tier}. Append a vendor path, or add/v1for the OpenAI SDKbaseURL.request(path, init?)→QuotaResponse— low-level proxied call. Returns the raw vendorResponseplusquota({ debited, remaining }).get<T>(path, init?)/post<T>(path, body?, init?)→QuotaJsonResponse<T>— convenience wrappers that parse the vendor body as JSON.meter(calls?)→MeterResult— metering-only (no upstream); debits quota and returns{ ok, tier, requested, debited, remaining }.
Errors
request/get/post/meter throw a QuotaError for gateway-level
failures. A vendor's own status code (incl. its 4xx/5xx) is returned as a normal
response, not thrown.
| code | HTTP | Helper | Meaning |
| ---------------------- | ---- | --------------------- | ---------------------------------------- |
| missing_api_key | 401 | isAuthError | No key supplied. |
| invalid_key | 401 | isAuthError | Key invalid or revoked. |
| no_position | 404 | isNoPosition | No active position for the tier. |
| quota_exhausted | 429 | isQuotaExhausted | Balance depleted — top up. |
| no_upstream | 501 | isUpstreamProblem | Tier has no vendor wired (metering-only).|
| upstream_unavailable | 502 | isUpstreamProblem | Vendor unreachable — no quota spent. |
| http_error | — | — | Couldn't reach the gateway / other. |
Development
npm install
npm test # vitest
npm run build # tsc -> dist (JS + .d.ts)License
MIT
