1. Install

pip install digirails
npm install digirails

2. Buy a service

Discover a seller, request an invoice, pay, and receive the result — all in one call.

import asyncio
from digirails import Agent, REGTEST

async def main():
    async with Agent.generate(
        network=REGTEST,
        rpc_url="http://digirails:digirails@127.0.0.1:18443",
    ) as buyer:
        result = await buyer.request_service(
            seller_url="http://127.0.0.1:9001",
            service_id="echo",
            params={"message": "Hello from DigiRails!"},
            max_amount="0.01",
        )
        print(result.result)

asyncio.run(main())
import { Agent, REGTEST } from 'digirails';

const buyer = Agent.generate({
  network: REGTEST,
  rpcUrl: 'http://127.0.0.1:18443',
  rpcUsername: 'digirails',
  rpcPassword: 'digirails',
});

const result = await buyer.requestService({
  sellerUrl: 'http://127.0.0.1:9001',
  serviceId: 'echo',
  serviceParams: { message: 'Hello from DigiRails!' },
  maxAmount: '0.01',
});
console.log(result.result);

await buyer.close();

3. Sell a service

Register a handler function, set a price, and start serving. The SDK handles manifest generation, invoice creation, and payment verification.

import asyncio
from digirails import Agent, ServiceCategory, REGTEST

def handle_echo(params: dict) -> dict:
    return {"echo": params.get("message", "")}

async def main():
    seller = Agent.generate(
        network=REGTEST,
        rpc_url="http://digirails:digirails@127.0.0.1:18443",
    )
    seller.register_service(
        service_id="echo",
        handler=handle_echo,
        price="0.001",
        category=ServiceCategory.GENERAL_COMPUTE,
    )
    await seller.serve(port=9001)
    await asyncio.Event().wait()

asyncio.run(main())
import { Agent, ServiceCategory, REGTEST } from 'digirails';

const seller = Agent.generate({
  network: REGTEST,
  rpcUrl: 'http://127.0.0.1:18443',
  rpcUsername: 'digirails',
  rpcPassword: 'digirails',
});

seller.registerService({
  serviceId: 'echo',
  handler: async (params) => ({ echo: params?.message ?? '' }),
  price: '0.001',
  category: ServiceCategory.GENERAL_COMPUTE,
});

await seller.serve('0.0.0.0', 9001);

4. What happens under the hood

The SDK handles the full 4-message DR-Pay flow automatically. Here's the sequence:

Buyer                                Seller
  |                                    |
  |  GET /.well-known/digirails.json   |
  |----------------------------------->|  1. Discover manifest
  |<-----------------------------------|     (services, pricing, payment terms)
  |                                    |
  |  POST /drpay/request               |
  |----------------------------------->|  2. SERVICE_REQUEST
  |<-----------------------------------|  3. PAYMENT_INVOICE
  |                                    |     (amount, address, invoice_id)
  |  [build, sign, broadcast tx]       |
  |                                    |
  |  POST /drpay/broadcast             |
  |----------------------------------->|  4. PAYMENT_BROADCAST
  |                                    |     (raw signed transaction)
  |                                    |
  |                                    |     Verify payment + Execute service
  |<-----------------------------------|  5. SERVICE_DELIVERY
  |                                    |     (result payload)

Light mode vs. full mode

Light mode requires no infrastructure. Install the SDK, generate a key pair, and connect to public RPC endpoints. Setup takes seconds. This mode trusts the RPC provider for chain data — a bounded, explicit tradeoff appropriate for development and micropayments.

Full mode runs a local DigiByte node and independently verifies all chain data. No trust required. For production sellers and high-value payments. Both modes expose an identical API — agent code doesn't change when switching between them.