Docs / Guides / Sell capacity
Guides

Sell capacity

Offer a model to the network and get paid per token.

A node becomes a provider when it offers one model source to the network, reachable at a public HTTPS URL, and is paid in USDG through the escrow. Buyer and seller are two views of the same node.

Honest status: the pieces below are real and tested on the Robinhood testnet with the test token MockUSDG (paid trades settled locally, between two nodes, and once through a Cloudflare tunnel). A seller backed by a real model reached from a second machine on another network has not been run yet. Mainnet is untouched. Read STATUS first.

What you need#

Need Notes
A model source Ollama on the same machine is the simple path: OLLAMA
A public HTTPS URL for /p2p/* Caddy or a Cloudflare tunnel in front of the node. Without it you cannot be reached (no relay or NAT traversal yet)
Testnet ETH in the node wallet Gas for redeeming vouchers; you pay it. Faucets are listed in Payments (login required, a human step)
A payout address ELYRA_PAYOUT: where swept USDG goes. Without it earnings stay in the node wallet
Backups The data dir holds identity and wallet; set ELYRA_PASSPHRASE and back it up

Steps#

  1. Install and run the node as a service: INSTALL. Use --no-demo so no simulated peers appear.
  2. Attach the model source (Connect → Detect local, or ELYRA_UPSTREAM_URL).
  3. Expose only /p2p/* and /healthz over HTTPS:
    text
    seller.example.com {
      @p2p path /p2p/* /healthz
      handle @p2p { reverse_proxy 127.0.0.1:8545 }
      respond 404
    }
    
    The panel text mentions --host 0.0.0.0; prefer this loopback + proxy layout. The node's own guard blocks /api and /v1 from non-loopback, but do not rely on one guard.
  4. Configure: ELYRA_PUBLIC_URL, ELYRA_PROVIDE=1, ELYRA_PROVIDE_PRICE, ELYRA_PAYOUT, ELYRA_NETWORK, ELYRA_ESCROW (CONFIGURATION); or use the Provide view.
  5. Fund the wallet with testnet ETH (address on Payments).
  6. Verify from outside: curl https://seller.example.com/p2p/hello returns signed JSON listing your model; curl -i https://seller.example.com/api/status must return 404 (not data, not 403).
  7. From a buyer node: Network → add https://seller.example.com; it should appear LIVE with your model. Deposit mock USDG, send a request, and check the receipt and an on-chain redeem (explorer link under Payments).

How you are paid#

  1. The buyer's node sends a sealed, signed request; you answer and return a signed receipt (model, tokens, price, amount).
  2. The buyer verifies it (signature, parties, price within 5% of the quote, amount = price x tokens, token count not inflated) before signing a cumulative voucher.
  3. You redeem the latest voucher on-chain; the escrow pays you exactly that amount of USDG.

Money is USD per million tokens, rounded to 1e-8, settled in 6-decimal USDG: no oracle, no exchange rate. Gas is ETH.

Risk controls (provider side)#

Control Default Why
creditUsd $0.50 A consumer can drain its own deposit through a second address (documented limitation F3), so you never serve more unpaid usage per wallet than you can lose, including the next request's worst case
autoRedeem / autoRedeemUsd on / $0.25, plus a 60 s sweeper Keeps unredeemed exposure small
On-chain deposit check always, fail-closed Before creating any state your node reads the wallet's deposit; if the RPC is down it answers 503
maxConcurrent, ratePerMin, deny 4, 120, none Capacity and abuse limits

On SIGTERM the node redeems what it holds (bounded to 20 s) before exiting.

Privacy: what you can and cannot claim#

A normal seller can read prompts: label it none. Do not set the TEE claim unless you really run the official image in Google Confidential Space; even then buyers only treat you as private when a Google-signed attestation passes their trust list, and that path has only been proven against a simulated Google (TEE). Sealed transport hides prompts from the network, not from you.

Pricing#

Your price per MTok must exceed your cost per MTok actually served. Start on a cheap CPU box with a small model; rent a GPU only after a buyer exists. A 1B model on 8 CPU cores answered a short prompt in about 1 s warm.

Things that bite#

  • Gossip refuses private/LAN peer URLs unless --allow-private-peers (operator-typed peers are exempt).
  • Both sides must use the same escrow or there is no route.
  • Real USDG (mainnet) is unaudited territory: the escrow is unaudited and the USDG supply controller can burn from any address. Mainnet needs --allow-mainnet and your informed decision.
  • Mock USDG is minted by anyone and has no value.