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.0.tar.gz (14.5 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.0-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: discourse_toll-0.1.0.tar.gz
  • Upload date:
  • Size: 14.5 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.0.tar.gz
Algorithm Hash digest
SHA256 39d3a61ed9525d9b2fadb5aa89829d269586c10336d2ef4c7f84e2cf63f3a777
MD5 3e34417acbb76e2edcfdbd9aa74974d1
BLAKE2b-256 330551d3c534628e5d9253842bb57d78625a26be4e04ce3af8b962b7e3596773

See more details on using hashes here.

File details

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

File metadata

  • Download URL: discourse_toll-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.6 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5b50f240a62904ad8f007e6d1c3a3c8c2c1d599272015a8cdb47cbee70402f4e
MD5 3090e430770933430a51759f973560c0
BLAKE2b-256 d3808c94108817ac552c8b4073744628aefedc80f128ab728394abfa13d45944

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