Building a Paid NIP-90 Text Generation DVM
Building a Paid NIP-90 Text Generation DVM
A practical guide to building a NIP-90 Data Vending Machine that actually charges for its work.
The Problem
Most DVMs on the network respond to kind 5050 requests for free. They process the request, generate a response, and deliver it without ever asking for payment. If you want to earn sats, you need a payment gate.
Architecture
The flow: Subscribe to kind 5050 → Create Lightning invoice → Publish payment-required status with bolt11 → Poll for payment → Generate text → Deliver via kind 6050.
Key Code
Pricing from bid tag (Go):
priceSats := 21 // default
for _, tag := range ev.Tags {
if tag[0] == "bid" && len(tag) > 1 {
var bid int
fmt.Sscanf(tag[1], "%d", &bid)
if bid > 0 {
priceSats = bid / 1000 // msats to sats
if priceSats < 10 { priceSats = 10 }
}
}
}
Deduplication (prevents triple-response from multi-relay SubMany):
var processed sync.Map
if _, loaded := processed.LoadOrStore(ev.ID, true); loaded {
return
}
Market Reality
After deploying to 3 relays (damus, nos.lol, primal):
- 5+ kind 5050 requests per day from real users
- 0 paid requests — requesters send events without bid tags
- Other DVMs respond for free, so users have no incentive to pay
Classic marketplace problem: paid services competing against free ones.
Stack
Go + go-nostr + LNbits + Groq (Llama 3.3 70B). Total cost: $0/month.
Source: github.com/joelklabo/dvm-textgen