@faremeter/payment-solana/flex/facilitator and @faremeter/flex-solana/facilitator. For the protocol-level model, see Flex Concepts.
Two layers of API
If you’re standing up a Faremeter facilitator service that already speaks x402, start with the plug-in. If you’re embedding Flex into a non-Faremeter system, use the building blocks directly.
The plug-in: createFacilitatorHandler
FlexFacilitator is a FacilitatorHandler (so it slots into Faremeter’s facilitator service) plus three extras:
flush()— drain settled in-memory holds to chain immediately.getHoldManager()— inspect the in-memory hold state (debugging, metrics).stop()— cancel the background flush interval.
flushIntervalMs), so most operators never need to call flush() themselves.
Verify and settle
The handler implements the standard Faremeterverify / settle lifecycle:
-
verify— decodes the client’sFlexPaymentPayload, checks the Ed25519 signature, fetches escrow + session-key state, runstryHoldon the in-memory hold manager, and returns success if the reservation took. The hold initially reserves the fullmaxAmount;settlereduces it later. Plan escrow capacity against the ceiling, not the expected actual cost. -
settle— the middleware reports the actual amount consumed. The handler updates the hold’ssettleAmount(must be<=the previously heldmaxAmount), marks itsettled, and the next flush pushes it on-chain. The handler returns the x402 settle response immediately; on-chain confirmation is asynchronous. -
flush(background) — collects allsettledholds, buildssubmit_authorizationinstructions in batches, signs them with the facilitator key, and tracks confirmation. Once submitted, holds becomesubmitted. After the refund window closes, the handler buildsfinalizeinstructions to release funds.
PERMANENT_SUBMIT_ERRORS (expired authorizations, invalid signatures, expiry-too-far, etc.) are not retried — the hold is dropped and an error is logged. Transient errors retry up to maxSubmitRetries times with submitRetryDelayMs between attempts.
Middleware integration: createUptoHandler
For variable-amount endpoints (the canonical Flex use case), @faremeter/payment-solana/flex/hono exposes createUptoHandler. It takes an authorize callback that decides the maximum amount for a given request, then a handle callback that does the work and reports the actual amount via a settle function.
Building blocks: hold manager
UsecreateHoldManager directly if you’re building outside the Faremeter middleware abstraction.
The manager enforces two invariants when accepting new holds: the sum of all unsubmitted hold amounts (per escrow + mint) must fit in the vault balance minus on-chain commitments, and the total pending count (in-memory + on-chain) must stay below
MAX_PENDING_SETTLEMENTS = 16.
Building blocks: accounting
fetchEscrowAccounting is the snapshot you take from chain to feed the hold manager:
snapshotMaxAgeMs, default 10 seconds) to avoid hammering RPC.
Building blocks: split merging
When the merchant runs the same recipient through multiple split entries (for example, a base fee + a referral kick-back going to the same operator),mergeSplits collapses duplicates:
FLEX_ERROR__DUPLICATE_SPLIT_RECIPIENT).
Operational considerations
- Activity tracking.
last_activity_slotis only updated bysubmit_authorizationandrefund(both require facilitator signatures).finalizeis permissionless — even cranking it forever doesn’t keep the deadman timer alive. Make sure your facilitator submits or refunds at least once perdeadman_timeout_slots, even on quiet escrows. - Refund-window hygiene. Honor refund requests from middleware (failed deliveries, disputes) by issuing
refundinstructions during the window. Once the window closes,finalizeis the only remaining lever. - Pending-count headroom. With the cap at 16, a busy escrow saturates fast. Submit and finalize aggressively so middleware verify calls don’t get rejected for capacity.
- Session-key grace period. The facilitator should surface a documented submission SLA so clients can pick a
revocation_grace_period_slotsthat’s at least 2x the SLA. The default minimum the plug-in enforces is150slots (~1 minute).
Further reading
- Concepts — the protocol-level model.
- Program Reference — on-chain instructions, accounts, and constraints.
- API Reference — the full
@faremeter/flex-solanasurface. - Facilitators — how facilitators fit into Faremeter overall.