Skip to content

nlgal/s402-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

S402 BTC-Earning API Server

Earn Bitcoin passively by running pay-per-use API endpoints on the Spark Network.

Every time an AI agent or automated client calls one of your endpoints, they pay sats directly to your Spark wallet — zero fees, instant settlement.

Built on the S402 protocol which uses the HTTP 402 Payment Required status code.


How It Works

Client → POST /api/price
         ← 402 + { quote_id, amount_sats, spark_address }

Client pays sats via Spark → gets txId

Client → POST /api/price
         headers: X-Spark-Payment: <txId>
         body: { ..., quote_id: "q_..." }
         ← 200 + result

Endpoints & Prices

Endpoint Method Price Description
/api/echo POST 100 sats Echo test — confirms payment flow works
/api/price POST 200 sats Live crypto prices (BTC, ETH, SOL, etc.)
/api/text POST 500 sats AI text generation (GPT-4o-mini)
/api/wallet/info GET Free Server info, endpoint list, payment instructions
/api/wallet/balance GET Free Your current BTC balance

Setup

1. Install dependencies

npm install

2. Configure

cp .env.example .env

Edit .env:

SPARK_NETWORK=MAINNET   # or REGTEST for testing
OPENAI_API_KEY=         # optional — only needed for /api/text
PORT=3000

3. Generate your Spark wallet

npm run setup-wallet

This will:

  • Generate a new Spark wallet (or load one from SPARK_MNEMONIC)
  • Print your mnemonicsave this somewhere safe
  • Print your Spark address (where clients pay you)
  • Print your Bitcoin deposit address (to fund from L1)
  • Auto-update your .env file

4. Fund your wallet (optional but recommended)

Send some BTC to your deposit address from any Bitcoin wallet. This isn't required to receive payments, but it proves the wallet is working.

5. Start the server

npm start

Testing the Payment Flow

Quick test (REGTEST — free fake sats)

# In .env, set: SPARK_NETWORK=REGTEST
# Then:
npm run setup-wallet   # generates a REGTEST wallet
npm start              # start the server
node src/test-client.js  # runs full payment flow

Manual test (MAINNET)

# 1. Get a quote
curl -X POST http://localhost:3000/api/price \
  -H "Content-Type: application/json" \
  -d '{"symbols": ["BTC", "ETH"]}'

# You'll get:
# {
#   "payment": {
#     "quote_id": "q_abc123...",
#     "amount_sats": 200,
#     "spark_address": "spark1q...",
#     "expires_at": 1234567890
#   }
# }

# 2. Send 200 sats to spark_address from your Spark wallet
#    Copy the transaction ID

# 3. Retry with payment proof
curl -X POST http://localhost:3000/api/price \
  -H "Content-Type: application/json" \
  -H "X-Spark-Payment: <your-txId>" \
  -d '{"symbols": ["BTC", "ETH"], "quote_id": "q_abc123..."}'

Endpoint Details

POST /api/echo — 100 sats

Request:  { "message": "hello world" }
Response: { "success": true, "you_sent": { "message": "hello world" }, "paid_sats": 100 }

POST /api/price — 200 sats

Request:  { "symbols": ["BTC", "SOL"], "currency": "usd" }
Response: {
  "prices": {
    "BTC": { "price": 85000, "change_24h": 2.3 },
    "SOL": { "price": 142, "change_24h": -1.1 }
  }
}

Supported symbols: BTC, ETH, SOL, DOGE, ADA, MATIC, AVAX, LINK

POST /api/text — 500 sats

Request:  { "prompt": "Write a haiku about Bitcoin", "max_tokens": 100 }
Response: { "result": "Satoshis flow free..." }

Requires OPENAI_API_KEY in .env. Runs in demo mode without it.


Deploying (Earn From Real Clients)

Railway / Render / Fly.io

  1. Push this repo to GitHub
  2. Create a new service pointing to your repo
  3. Set environment variables:
    • SPARK_MNEMONIC — your 12-word mnemonic
    • SPARK_NETWORK=MAINNET
    • OPENAI_API_KEY (optional)
  4. Deploy

Register with S402 Directories

Once live, post your server URL in:

  • utxo.fun community
  • Spark Discord / Twitter
  • AI agent directories that support S402

Adding Custom Endpoints

Copy any route file and customize:

// src/routes/my-endpoint.js
import { Router } from 'express';
import { requirePayment } from '../middleware/s402.js';

const router = Router();

router.post('/', requirePayment({ sats: 1000 }), async (req, res) => {
  // Your logic here — payment is already verified
  res.json({ success: true, result: 'your data' });
});

export default router;

Then register it in server.js:

import myRouter from './routes/my-endpoint.js';
app.use('/api/my-endpoint', myRouter);

Stack

  • Spark SDK — Bitcoin L2 wallet + payments
  • S402 Protocol — HTTP 402 payment standard
  • Express.js — HTTP server
  • Node.js 18+

Security Notes

  • Never commit your .env file or mnemonic
  • Quote IDs expire in 5 minutes — prevents stale payment attacks
  • Transaction IDs are tracked to prevent replay attacks
  • For production, swap the in-memory payment store for Redis or a DB

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors