Skip to main content

discourse-toll (Python)

L402 micropayment middleware for discourse. Trust-weighted, progressive pricing for forums and APIs.

Python port of discourse-toll (Node.js).

The thesis: Karma selects for popularity. Rate limiting is indiscriminate. Economic cost selects for intentionality.

Install

pip install discourse-toll

With FastAPI support:

pip install discourse-toll[fastapi]

FastAPI Server

from fastapi import FastAPI, Depends
from discourse_toll import create_toll, TollConfig, PricingConfig, MockWallet

app = FastAPI()
mock = MockWallet()  # Replace with real wallet in production

toll = create_toll(TollConfig(
    secret="your-hmac-secret",
    wallet=mock,
    pricing=PricingConfig(
        base_sats=1,
        progressive_multiplier=1.5,
        progressive_cap=50,
    ),
))

@app.post("/api/comments")
async def post_comment(
    request: Request,
    paid: bool = Depends(toll(context_from="body.thread_id")),
):
    return {"ok": True}

Client

from discourse_toll import create_discourse_client

client = create_discourse_client(
    pay_fn=my_wallet.pay_invoice,  # async (invoice) -> {"preimage": str}
    max_sats=50,
    agent_id="my-nostr-pubkey",
)

result = await client.post(
    "https://forum.example/api/comments",
    json={"text": "Worth paying for", "thread_id": "abc"},
)
print(result.paid, result.sats)  # True, 1

How pricing works

Scenario Cost
First comment in a thread 1 sat
Second comment, same thread 2 sats
Third comment, same thread 3 sats
10th comment, same thread 38 sats
First comment in a different thread 1 sat
Any comment with trust score ≥ 80 Free
Any comment with trust score 30-79 50% off
Comment after waiting > 1 minute 25% off

Trust integration

from discourse_toll import static_resolver, api_resolver

# Static (testing)
toll = create_toll(TollConfig(
    secret="test",
    wallet=mock,
    trust=static_resolver({"pubkey-1": 90, "pubkey-2": 40}),
))

# ai.wot REST API (production)
toll = create_toll(TollConfig(
    secret="test",
    wallet=mock,
    trust=api_resolver("https://wot.jeletor.cc"),
))

Wallet backend

Implement the wallet protocol:

class MyWallet:
    async def create_invoice(self, sats: int, description: str) -> dict:
        """Return {"invoice": "lnbc...", "payment_hash": "hex"}"""
        ...

    async def lookup_invoice(self, payment_hash: str) -> dict:
        """Return {"paid": bool, "preimage": "hex" | None}"""
        ...

Or use MockWallet for testing (no Lightning needed).

Security

  • Only give the server wallet make_invoice and lookup_invoice permissions
  • Macaroon caveats are locked to: expiry, endpoint, method, context, agent
  • Fail open on errors (availability > enforcement)
  • Preimage verification: SHA256(preimage) must equal payment_hash

Stack

Python port of the Node.js ecosystem:

License

MIT

Metadata

Release files for discourse-toll 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for discourse-toll 0.1.1
File Size Uploaded
discourse_toll-0.1.1.tar.gz 14.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for discourse-toll 0.1.1
File Interpreter ABI Platform
discourse_toll-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 28.6 kB

Release files / discourse_toll-0.1.1.tar.gz

Download URL discourse_toll-0.1.1.tar.gz
Size 14.7 kB
Tags Source
SHA-256 checksum
How to use checksums
ddb83b64e135eca80649c59d7639f20431e41242d13b2d25c76530b064b2d350
BLAKE2b-256 checksum
How to use checksums
7e9d9a186ccffb6384fb1a0a3ab63dbf8a325c54e5e00f4e81d02119ee1711f7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.23

Release files / discourse_toll-0.1.1-py3-none-any.whl

Download URL discourse_toll-0.1.1-py3-none-any.whl
Size 13.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
01c205fd8fbfe33b42cff746e48dd4ce621ffac178c7f4765be2f8c03975ae1f
BLAKE2b-256 checksum
How to use checksums
342d654bdb935b4792752986c5374d3a3e9ec73af282154a7f9ac737d1616628
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.23

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page