npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nickthelegend69/webrtc-payment-sdk-core

v0.2.1

Published

Core SDK for paywalled WebRTC streams — rail-agnostic provider/consumer peers, gating, and DataChannel payment protocol.

Readme

@nickthelegend69/webrtc-payment-sdk-core

Rail-agnostic core for pay-per-second WebRTC streams. Stream live video peer-to-peer and charge the viewer per segment, with each payment settled on-chain by a pluggable payment rail.

npm

This is the transport- and payment-agnostic engine. It knows about WebRTC, gating, segments, and an abstract PaymentRail interface — but nothing about Casper, x402, or any specific chain. Pair it with a rail like @nickthelegend69/webrtc-payment-rail-x402 to settle payments on Casper Network.

npm install @nickthelegend69/webrtc-payment-sdk-core

What it does

A provider captures a MediaStream and broadcasts it over WebRTC. A consumer connects and pays — every few seconds — to keep watching. The SDK:

  • Manages one RTCPeerConnection per viewer + the signaling handshake.
  • Opens a casper-pay DataChannel and runs a small payment protocol over it.
  • Requests a payment each segment, verifies it (gate), then settles it on-chain via the rail — one real transaction per paid segment.
  • Suspends a viewer's stream the moment they stop paying.

It supports three enforcement modes (see Gating modes).

Not just streaming. The same engine ships an x402-over-HTTP layer — gate any API route behind a Casper micropayment and have clients auto-pay:

// server: one middleware
app.get("/premium", paymentMiddleware({ rail, amount: "100000000", payTo }), handler);
// client: one wrapped fetch — 402s are paid + retried invisibly
const pay = wrapFetch(fetch, { rail, signFn, maxValue: "1000000000" });

See docs/X402.md and the runnable examples/paid-api.


Quick start

Provider (the streamer)

import { PaywalledRTCProvider } from "@nickthelegend69/webrtc-payment-sdk-core";

const provider = new PaywalledRTCProvider({
  paymentRail: rail,                      // from a rail package
  gating: {
    mode: "track",                        // pay-per-segment
    segmentDurationSeconds: 15,
    pricePerSegment: "150000000",         // base units charged each segment
  },
  signalingServerUrl: "ws://localhost:3001",
});

provider.on("consumer:joined",  (id)               => console.log("viewer", id));
provider.on("consumer:paid",    (id, amt, seg)     => console.log("paid", seg, amt));
provider.on("consumer:settled", (id, seg, txHash)  => console.log("on-chain", txHash));
provider.on("earnings:update",  (motes)            => render(motes));

const media = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
await provider.startStream(media);

// Share this with viewers:
const link = `https://your.app/watch?room=${provider.room}`;

Consumer (the viewer)

import { PaywalledRTCConsumer } from "@nickthelegend69/webrtc-payment-sdk-core";

const consumer = new PaywalledRTCConsumer({
  paymentRail: rail,
  signalingServerUrl: "ws://localhost:3001",
  walletAddress: "account-hash-…",        // payer
  signFn,                                 // async (digestHex) => signatureHex
});

consumer.enableAutoPayment({
  maxTotalSpend: "1000000000",            // hard cap — never exceeded
  onPayment:     (amt, i) => console.log("paid segment", i),
  onMaxReached:  ()       => console.log("cap hit — stream pauses"),
});

consumer.on("stream:started",   (s)            => (videoEl.srcObject = s));
consumer.on("payment:confirmed", (seg, txHash) => console.log("settled", txHash));

const { stream } = await consumer.joinStream(`ws://localhost:3001?room=${room}`);

Gating modes

| Mode | How it's enforced | Cost on chain | Best for | |-------------|-------------------------------------------------------------|---------------|-----------------------------------| | signaling | Pay once before the SDP offer is sent. | 1 tx | Ticketed / one-off access. | | track | Pay every N seconds; the media track is toggled off if a payment is missed. | N txs | Pay-per-second streaming. | | crypto | RTP frames are AES-GCM encrypted; the per-segment key is delivered only after payment. | N txs | Trust-free enforcement — bytes are useless without paying. |

Set the mode in gating.mode. track and crypto run entirely over the WebRTC DataChannel; signaling is enforced before the connection forms.


The signer (signFn)

The consumer never holds rail logic — it just signs a digest:

type SignFn = (typedDataDigestHex: string) => Promise<string>;

Plug in anything:

  • Browser / production — a wallet (e.g. CSPR.click) signs the EIP-712 typed data.
  • Agents / servers — a raw key signer (e.g. makeEd25519SignFn from the x402 rail).

The rail package builds the digest and assembles the on-the-wire payload; the core SDK only routes signFn to the rail at payment time.


API

PaywalledRTCProvider

| Member | Signature | Notes | |--------|-----------|-------| | new PaywalledRTCProvider(config) | ProviderConfig | paymentRail, gating, signalingServerUrl, optional iceServers, room. | | startStream(media) | (MediaStream) => Promise<void> | Begins broadcasting + paywalling. | | room | string | Room id viewers join with ?room=. | | listViewers() | () => ViewerState[] | Current viewers + paid/enabled state. | | totalEarnings() | () => string | Settled base units this session. | | stop() | () => void | Tears down every peer + signaling. |

Events: consumer:joined, consumer:paid, consumer:settled, consumer:settle_failed, consumer:defaulted, consumer:left, earnings:update, error.

PaywalledRTCConsumer

| Member | Signature | Notes | |--------|-----------|-------| | new PaywalledRTCConsumer(config) | ConsumerConfig | paymentRail, signalingServerUrl, walletAddress, signFn, optional iceServers, cryptoMode. | | joinStream(url) | (string) => Promise<{ stream, sessionId }> | URL includes ?room=. | | enableAutoPayment(cfg) | (AutoPaymentConfig) => void | maxTotalSpend, onPayment, onMaxReached. | | totalSpentMotes() | () => string | Running spend. | | disconnect() | () => void | Closes the connection. |

Events: stream:started, stream:paused, stream:resumed, payment:sent, payment:confirmed, error.

Also exported

PaymentGate, SessionManager, SignalingClient, TypedEmitter, the DataChannel protocol (dc, encodeDC, decodeDC, DC_LABEL), the AES-GCM crypto helpers (generateSegmentKey, installSenderEncryption, installReceiverDecryption, …), and every shared type (PaymentRail, PaymentRequirements, PaymentPayload, GatingConfig, ViewerState, SignFn, DEFAULT_ICE_SERVERS, …).


Writing your own rail

Implement four methods and you can settle on any chain:

interface PaymentRail {
  buildRequirements(opts): PaymentRequirements;                    // provider: what to charge
  buildPayload(req, signFn): Promise<PaymentPayload>;              // consumer: sign it
  verify(payload): Promise<{ valid: boolean; error?: string }>;    // provider: gate
  settle(payload): Promise<{ txHash: string }>;                    // provider: on-chain
}

Notes

  • Pure ESM, TypeScript types included. Targets modern browsers (provider/consumer) and Node 18+ (rail/agent side).
  • crypto mode needs WebRTC Encoded Transforms (Chromium-based browsers).
  • For the full end-to-end guide, all events, replay protection, and a runnable reference app, see the repo docs/USAGE.md.

MIT