Classes
The three core classes that coordinate the s402 protocol flow. Each is a registry of scheme implementations — you register only the schemes you need.
import { s402Client, s402ResourceServer, s402Facilitator } from 's402';s402Client
Client-side scheme registry. Builds payment payloads from server requirements.
register(network, scheme)
Register a scheme implementation for a specific network.
register(network: string, scheme: s402ClientScheme): this;Returns this for chaining:
const client = new s402Client()
.register('sui:mainnet', myExactScheme)
.register('sui:mainnet', myPrepaidScheme);createPayment(requirements)
Build a payment payload for the given requirements. Auto-selects the best scheme — the first scheme in the server's accepts array that the client has a registered implementation for.
async createPayment(
requirements: s402PaymentRequirements | Record<string, unknown>,
): Promise<s402PaymentPayload>;Accepts both typed s402PaymentRequirements and raw Record<string, unknown> (from JSON.parse of untrusted network data). Always runs through normalizeRequirements() for validation.
Throws:
NETWORK_MISMATCH— no schemes registered for the requirements' networkSCHEME_NOT_SUPPORTED— none of the server's accepted schemes are registered
Example:
const requirements = decodePaymentRequired(header);
const payment = await client.createPayment(requirements);
// payment.scheme will be the best match from requirements.acceptssupports(network, scheme)
Check if the client can handle a specific scheme on a specific network.
supports(network: string, scheme: s402Scheme): boolean;s402ResourceServer
Server-side scheme registry. Builds payment requirements for routes and processes incoming payments through a facilitator.
register(network, scheme)
Register a server-side scheme for building requirements.
register(network: string, scheme: s402ServerScheme): this;setFacilitator(facilitator)
Set the facilitator used for verification and settlement.
setFacilitator(facilitator: s402Facilitator): this;buildRequirements(config)
Build payment requirements for a route from a config object.
buildRequirements(config: s402RouteConfig): s402PaymentRequirements;If a registered scheme has a custom builder, it is used. Otherwise, a generic requirements object is built from the config fields.
Example:
const server = new s402ResourceServer();
server.setFacilitator(facilitator);
const requirements = server.buildRequirements({
schemes: ['exact', 'prepaid'],
price: '1000000',
network: 'sui:mainnet',
payTo: '0xrecipient...',
});
// requirements.accepts = ['exact', 'prepaid']verify(payload, requirements)
Verify a payment payload without broadcasting. Delegates to the facilitator.
async verify(
payload: s402PaymentPayload,
requirements: s402PaymentRequirements,
): Promise<s402VerifyResponse>;Throws: FACILITATOR_UNAVAILABLE if no facilitator is set.
settle(payload, requirements)
Settle a pre-verified payment. Delegates to the facilitator.
async settle(
payload: s402PaymentPayload,
requirements: s402PaymentRequirements,
): Promise<s402SettleResponse>;process(payload, requirements)
Recommended path. Expiration-guarded verify + settle in one call. Rejects expired requirements, verifies the payload, then settles.
async process(
payload: s402PaymentPayload,
requirements: s402PaymentRequirements,
): Promise<s402SettleResponse>;s402Facilitator
Scheme dispatcher for verification and settlement. Routes each payment to the correct scheme implementation based on the payload's scheme field.
register(network, scheme)
Register a scheme-specific facilitator for a network.
register(network: string, scheme: s402FacilitatorScheme): this;verify(payload, requirements)
Verify a payment by dispatching to the correct scheme's verify logic.
async verify(
payload: s402PaymentPayload,
requirements: s402PaymentRequirements,
): Promise<s402VerifyResponse>;settle(payload, requirements)
Settle a payment by dispatching to the correct scheme.
async settle(
payload: s402PaymentPayload,
requirements: s402PaymentRequirements,
): Promise<s402SettleResponse>;process(payload, requirements)
Expiration-guarded verify + settle. The recommended path for production use.
async process(
payload: s402PaymentPayload,
requirements: s402PaymentRequirements,
): Promise<s402SettleResponse>;Sequence:
- Check
requirements.expiresAt— reject if expired (REQUIREMENTS_EXPIRED) - Call
scheme.verify()— reject if invalid (VERIFICATION_FAILED) - Call
scheme.settle()— return the settlement result
Atomicity comes from Sui PTBs in the scheme implementation, not from this method. This method provides the temporal guard.
supports(network, scheme)
supports(network: string, scheme: s402Scheme): boolean;supportedSchemes(network)
supportedSchemes(network: string): s402Scheme[];s402RouteConfig
Per-route configuration used by s402ResourceServer.buildRequirements().
interface s402RouteConfig {
schemes: s402Scheme[]; // Which schemes to accept
price: string; // Amount in base units
network: string; // e.g., "sui:mainnet"
payTo: string; // Recipient address
asset?: string; // Coin type (default: SUI)
facilitatorUrl?: string;
settlementMode?: s402SettlementMode;
// Optional scheme-specific config
mandate?: { required: boolean; minPerTx?: string };
protocolFeeBps?: number;
receiptRequired?: boolean;
stream?: { ratePerSecond: string; budgetCap: string; minDeposit: string };
escrow?: { seller: string; arbiter?: string; deadlineMs: string };
seal?: { encryptionId: string; walrusBlobId: string; sealPackageId: string };
prepaid?: { ratePerCall: string; maxCalls?: string; minDeposit: string; withdrawalDelayMs: string };
}Scheme Interfaces
When building your own scheme implementation, implement one of these interfaces depending on the role:
| Interface | Role | Key Method |
|---|---|---|
s402ClientScheme | Client | createPayment(requirements) |
s402ServerScheme | Server | buildRequirements(config) |
s402FacilitatorScheme | Facilitator | verify() + settle() |
s402DirectScheme | Self-sovereign client | settleDirectly(requirements) |
See Design Principles for details on why each scheme has its own verify logic.