mppx.session.serveWebSocket
WebSocket session payments
Choose a signing account
Create a server-only wallet.ts module, then import account wherever an example creates a local signing account.
import { privateKeyToAccount } from 'viem/accounts'
export const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)Bridges a WebSocket connection to a Tempo Session using the method's configured store and settlement schedule.
Usage
import { , , } from 'mppx/server'
import { } from 'viem/accounts'
const = ['hello', 'world']
const = .()
const = .({
: [
.({
: ('0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'),
: '0x20c0000000000000000000000000000000000000', // pathUSD on Tempo
: { : 100 },
,
}),
],
})
const = .({ : '0.001', : 'word' })
declare const : <typeof ..>[0]['socket']
// In your WebSocket handler:
await ..({
: async function* () {
for (const of ) {
await .()
yield
}
},
,
,
: 'wss://api.example.com/stream',
})The helper shares the Store and settlementSchedule configured by tempo.session(). It applies the schedule after every committed WebSocket charge.
Return type
type ReturnType = Promise<void>Resolves when the WebSocket session completes or the connection closes.
Parameters
amount (optional)
- Type:
string
Expected per-tick amount. When set, Credentials with mismatched amounts are rejected.
generate
- Type:
AsyncIterable<string> | ((stream: SessionController) => AsyncIterable<string>)
Async iterable that produces application messages. When passed as a function, receives a SessionController with a charge() method for requesting payment before yielding each value. Each yielded string is sent to the client as an application message frame.
pollIntervalMs (optional)
- Type:
number - Default:
100
Polling interval in milliseconds for voucher balance checks.
route
- Type:
Parameters<typeof mppx.session.serveWebSocket>[0]['route']
Session route handler. Receives synthetic POST requests constructed from in-band authorization frames. The synthetic request carries only the Authorization header—no cookies, bodies, query parameters, or other headers from the original WebSocket upgrade request.
import { , } from 'mppx/server'
import { } from 'viem/accounts'
const = .({
: [
.({
: ('0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'),
}),
],
})
const : <typeof ..>[0]['route'] =
.({ : '0.001', : 'word' })socket
- Type:
Parameters<typeof mppx.session.serveWebSocket>[0]['socket']
WebSocket instance. Accepts a browser WebSocket, a ws library socket, or any object implementing send/close with either addEventListener/removeEventListener or on/off.
url
- Type:
string
URL used for constructing synthetic route requests. ws:// and wss:// schemes are normalized to http:// and https://.
Advanced options
Use tempo.Ws.serve() when a custom integration manages its own store or post-charge behavior. Pass onChargeCommitted to run a hook after each nonzero stream charge commits. The legacy settleScheduled option remains as a deprecated alias.
import { , , } from 'mppx/server'
import { } from 'viem/accounts'
const = .()
const = .({
: [
.({
: ('0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'),
: { : 100 },
,
}),
],
})
const = .({ : '0.001', : 'word' })
declare const : <typeof ..>[0]['socket']
await ..({
: async function* () {
await .()
yield 'hello'
await .()
yield 'world'
},
: ..,
,
,
,
: 'wss://api.example.com/stream',
})Credential verification routes each in-band authorization frame through route as a synthetic POST request carrying only the Authorization header. It doesn't include cookies, bodies, query parameters, or other headers from the original WebSocket upgrade request.
Helper functions
tempo.Ws.parseMessage
Parses a raw WebSocket message string into a typed Message.
const message = tempo.Ws.parseMessage(raw)tempo.Ws.formatAuthorizationMessage
Formats an authorization string into a message frame.
const frame = tempo.Ws.formatAuthorizationMessage(authorization)tempo.Ws.formatApplicationMessage
Formats application data into a message frame.
const frame = tempo.Ws.formatApplicationMessage(data)tempo.Ws.formatCloseRequestMessage
Formats a close request message frame.
const frame = tempo.Ws.formatCloseRequestMessage()tempo.Ws.formatReceiptMessage
Formats a Receipt into a message frame.
const frame = tempo.Ws.formatReceiptMessage(receipt)tempo.Ws.formatErrorMessage
Formats an error into a message frame.
const frame = tempo.Ws.formatErrorMessage({ message, status })Types
Message
type Message =
| { mpp: 'authorization'; authorization: string }
| { mpp: 'message'; data: string }
| { mpp: 'payment-close-request' }
| { mpp: 'payment-close-ready'; data: SessionReceipt }
| { mpp: 'payment-error'; status: number; message: string }
| { mpp: 'payment-need-voucher'; data: NeedVoucherEvent }
| { mpp: 'payment-receipt'; data: SessionReceipt }Socket
type Socket = {
close(code?: number, reason?: string): unknown
send(data: string): unknown
addEventListener?: (type: string, listener: (event: any) => void) => unknown
removeEventListener?: (type: string, listener: (event: any) => void) => unknown
on?: (type: string, listener: (...args: any[]) => void) => unknown
off?: (type: string, listener: (...args: any[]) => void) => unknown
}SessionRoute
type SessionRouteResult =
| { status: 402; challenge: Response }
| { status: 200; withReceipt(response?: Response): Response }
type SessionRoute = (request: Request) => Promise<SessionRouteResult>