🛠 Velarum Docs V0 — Phase-0 testnet only(per ADR-NC-027),内容陆续填入中。
QuickstartFirst Payment

Your first testnet payment

This is the whole loop: register a payment intent, sign it in your wallet, and watch it settle on testnet. Velarum never sees your key.

Before you start

You need a project API key, a testnet wallet with a little gas + test USDC (see Testnet faucets), and a Signer that talks to that wallet. The Signer is the only place your key is ever used — Velarum just calls it.

The code

import asyncio
from velarum import (VelarumClient, CreateAgentPaymentRequest,
                     InitiatorType, IntentSummary, PaymentIntentDetails,
                     BroadcastHintRequest)
from my_wallet import WalletSigner  # YOU implement this; Velarum never sees your key
 
async def main():
    # `signer` is explicit and required — there is no default signer (HC-NC-1).
    async with VelarumClient(api_key="vlk_test_...", signer=WalletSigner()) as client:
        # 1) Register the intent — Velarum returns it at `intent_created`.
        payment = await client.payments.create(CreateAgentPaymentRequest(
            agent_id="agt_123", initiator_type=InitiatorType.HUMAN,
            payment_intent=PaymentIntentDetails(
                amount="1.00", asset_id="base_sepolia_usdc",
                settlement_chain_id="base-sepolia", destination="0xRecipient")))
 
        # 2) YOU sign + broadcast in your wallet (Velarum never holds the key).
        _signed, tx_hash = await client.signer.sign_and_broadcast(
            chain_id="base-sepolia", unsigned_tx=b"<assembled-by-velarum>",
            intent_summary=IntentSummary(
                amount="1.00", destination="0xRecipient",
                asset_id="base_sepolia_usdc", chain_id="base-sepolia"))
 
        # 3) Tell the worker which tx_hash to observe.
        await client.payments.submit_broadcast_hint(
            payment.id, BroadcastHintRequest(chain_id="base-sepolia", tx_hash=tx_hash))
 
        # 4) Watch authoritative status until terminal.
        async for s in client.payments.watch_until_terminal(payment.id):
            print(s.status)  # chain_pending → … → settled
 
asyncio.run(main())

What just happened

payments.create registered an intent at intent_created. Then your WalletSigner.sign_and_broadcast — not Velarum — signed and broadcast the transaction and returned its tx_hash. submit_broadcast_hint hands that hash to the worker, which observes the transaction on-chain and advances the status; without this hint the intent would stay at intent_created and watch_until_terminal would never finish. watch_until_terminal re-fetches authoritative status each poll until a terminal state — it never treats a local cache as truth.

You hold the keys (HC-NC-1)

Notice the signer=WalletSigner() argument: it is explicit and mandatory. Velarum assembles the unsigned transaction, but signing and broadcasting happen inside your WalletSigner. There is no path where Velarum holds or uses your key.

Run it end-to-end

Want to run the exact SDK flow with zero setup? The repo ships a self-contained, mocked version (a stub signer + a mocked backend) you can execute immediately:

pip install "velarum[dev]"   # respx is a dev dependency used to mock the API
python apps/docs-site/examples/quickstart/first_payment.py
# status progression: ['chain_pending', 'settled']