Skip to main content
Source: packages/oracle-runtime/src/plugins/credits/

Summary

Owns the full credit lifecycle:
  • Enforcement — per-request middleware that aborts model calls when the user is out of credits (createCreditsMiddleware + TokenLimiter).
  • Settlement — background cron that converts held credits into on-chain claims, shipped via ClaimProcessingModule.
Silent (no agent-visible tools). When loaded, this plugin also activates the runtime’s Tier-0 SubscriptionMiddleware, which gates the HTTP request before the graph even runs.

Environment variables

What it contributes

  • Tools: none.
  • Sub-agents: none.
  • Middleware: createCreditsMiddleware (aborts the agent run when the user is out of credits).
  • Nest modules (when Redis is configured at construct time):
    • ClaimProcessingModule — cron that settles held credits on chain.
    • FileProcessingSinkModuleFILE_PROCESSING_CREDIT_SINK so pre-flight file-processing LLM usage bills the per-user budget.
    • SubscriptionSinkModuleSUBSCRIPTION_CREDIT_SINK so the subscription middleware mirrors per-DID subscription payload + balance into Redis on every authenticated request.
  • HTTP routes: none directly.
  • Shared state: none.

Production constructor

The bundled singleton is for inspect / test only. Production needs a Redis client and the network:
Without a Redis client the middleware loads in pass-through mode and the cron modules are skipped.

Observing claim settlement

The settlement cron emits structured logs under the [Credits/Claims] prefix — grep for that tag to trace a claim end-to-end.
  • Boot — one line at startup with the effective settings, e.g. Claim processing initialized: network=… denom=… minimumClaimThreshold=… disableCredits=… matrixAccountRoomId=set|MISSING. Use it to confirm the threshold override and required config actually applied.
  • Per tick — one summary line, Cron tick: N user(s) at/above threshold T, then a user=… heldAmount=… — evaluating line per candidate, an explicit SKIP user=… — <reason> for each user the cron drops (below threshold, no subscription payload in Redis, missing oracleClaimsCollectionId, insufficient available credits), and a closing Cron tick complete: submitted=X skipped=Y failed=Z counter.
  • Per claim — for every settled claim, the 4-step workflow logs [step 1/4 submitIntent][step 2/4 saveToMatrix][step 3/4 submitToChain][step 4/4 sendToSubsApi], each marked OK or FAILED and carrying the intentTxHash, claimCid, and on-chain chainTxHash values. A successful claim finishes with ✔ SUBMITTED user=… claimCid=…. When held credits exceed the oracle’s per-claim ceiling, the split is announced with heldAmount=… exceeds per-claim max … — splitting into N chunks: ….
  • Pricing source — before submitting, the cron logs pricing: fetched on-chain oracle pricing list … and cost: claiming heldAmount=… <denom> | per-claim ceiling maxAmount=… <denom>, so you can confirm the chain-side pricing feeding the split.
The credit-charging path (TokenLimiter.creditsForUsage) also logs a source= marker on every request so you can see which of the three pricing fallbacks priced a call: Each line includes costUsd=$… and → N credits (network=…), which makes it easy to spot sub-1-credit charges rounding to 0.

Opt out / Opt in

Add a middleware

The pattern createCreditsMiddleware uses.

Identity and auth

How subscription payloads reach the request.