Skip to main content

L402 micropayment middleware for discourse — trust-weighted, progressive pricing for forums and APIs

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

discourse_toll-0.1.1.tar.gz (14.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

discourse_toll-0.1.1-py3-none-any.whl (13.8 kB view details)

Uploaded Python 3

File details

Details for the file discourse_toll-0.1.1.tar.gz.

File metadata

  • Download URL: discourse_toll-0.1.1.tar.gz
  • Upload date:
  • Size: 14.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.23

File hashes

Hashes for discourse_toll-0.1.1.tar.gz
Algorithm Hash digest
SHA256 ddb83b64e135eca80649c59d7639f20431e41242d13b2d25c76530b064b2d350
MD5 90318d1e4ee1e05c149b7673bc63ba86
BLAKE2b-256 7e9d9a186ccffb6384fb1a0a3ab63dbf8a325c54e5e00f4e81d02119ee1711f7

See more details on using hashes here.

File details

Details for the file discourse_toll-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: discourse_toll-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 13.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.23

File hashes

Hashes for discourse_toll-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 01c205fd8fbfe33b42cff746e48dd4ce621ffac178c7f4765be2f8c03975ae1f
MD5 92d804734e33088bdf7ade3c41d755c7
BLAKE2b-256 342d654bdb935b4792752986c5374d3a3e9ec73af282154a7f9ac737d1616628

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page