Metadata-Version: 2.5
Name: velkr
Version: 0.3.0
Summary: Async Python SDK for policy-governed Velkr payments on Solana
Author: Velkr
License: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx<1,>=0.28.1
Requires-Dist: solders<0.30,>=0.29.0
Provides-Extra: dev
Requires-Dist: build<2,>=1.2.2; extra == 'dev'
Requires-Dist: mypy<2,>=1.17; extra == 'dev'
Requires-Dist: pytest-asyncio<2,>=1.1; extra == 'dev'
Requires-Dist: pytest<9,>=8.4; extra == 'dev'
Requires-Dist: respx<1,>=0.22; extra == 'dev'
Requires-Dist: ruff<1,>=0.12; extra == 'dev'
Requires-Dist: twine<7,>=6.1; extra == 'dev'
Provides-Extra: openai-example
Requires-Dist: openai-agents<1,>=0.2; extra == 'openai-example'
Description-Content-Type: text/markdown

# `velkr` Python SDK

`velkr` is the official async Python 3.11+ client for the Velkr Devnet/localnet MVP. It matches the important `@velkr/sdk` semantics: backend-only policy decisions, Artifact V2, exact Solana execution, receipt-first recovery, framework-neutral agent tools, and the Velkr x402 v2 receipt profile.

Velkr is pre-audit MVP software. Mainnet and production customer funds are unsupported.

```bash
python -m pip install velkr
```

```python
import os
from velkr import Velkr

async with Velkr(
    api_key=os.environ["VELKR_API_KEY"],
    network="devnet",
    fee_payer=application_owned_signer,
) as velkr:
    agent = velkr.agent(os.environ["VELKR_AGENT_ID"])
    payment = await agent.pay(
        amount="0.25",
        destination=merchant_token_account,
        purpose="purchase_data",
    )
```

The signer is injected as an object with `pubkey()` and `sign_message(bytes)`. The SDK never loads key files, accepts seed phrases, or reads private-key environment variables. The signer pays Solana transaction fees; it does not control the PDA-owned vault.

## Public API

```python
await agent.get()
await agent.get_policy()
await agent.authorize(...)
await agent.pay(...)
await agent.get_authorizations(...)
await agent.resume_payment(authorization_id)

agent.tools()
agent.x402(max_payment="1")

await velkr.authorizations.get(authorization_id)
await velkr.approvals.get(approval_id)
await velkr.approvals.list(agent_id=agent_id, status="pending")
```

`authorize()` returns typed `AuthorizationResult` objects for ALLOW, DENY, and REQUIRE_APPROVAL. It never evaluates policy locally. `pay()` turns a permitted request into the exact existing flow:

```text
authorize → prepare Artifact V2 → validate immutable bytes
→ build Ed25519 + execute_payment → simulate → sign → submit
→ confirm → verify receipt → reconcile backend
```

If a human approves a pending request, `resume_payment(authorization_id)` continues that authorization. It does not create another authorization. It accepts only an authorization bound to that `AgentClient` in `reserved` or already `consumed` state.

## Money and errors

Use decimal strings. Binary floats are rejected.

```python
from velkr import parse_usdc, format_usdc

parse_usdc("17.50")       # 17500000
format_usdc(17_500_000)   # "17.5"
```

The package exports typed exceptions including `VelkrAuthenticationError`, `VelkrDeniedError`, `VelkrApprovalRequiredError`, `VelkrArtifactError`, `VelkrExecutionError`, `VelkrReceiptVerificationError`, `VelkrReconciliationError`, and x402-specific errors. API keys are not included in their messages.

## Agent tools

```python
tools = agent.tools()
tools.definitions()

result = await tools.pay.execute({
    "amount": "0.25",
    "destination": merchant_token_account,
    "purpose": "purchase_search_results",
})
```

The tools are `velkr_pay`, `velkr_check_budget`, and `velkr_payment_status`. Their schemas reject unknown fields. Agent, workspace, API key, network, program, vault, and mint are bound by trusted SDK configuration and cannot be supplied by an LLM. Normal denial and approval-required decisions return machine-readable outcomes; infrastructure failures raise.

## x402

```python
async with agent.x402(max_payment="0.25") as paid:
    response = await paid.get(
        "https://merchant.example/data",
        economic_id="research-job-42-source-a",
    )
```

The client matches Developer Phase 2: canonical v2 `PAYMENT-REQUIRED`, exact resource/network/mint/destination binding, 16 KiB header ceiling, local amount ceiling, one payment, one retry, manual redirects, and no Velkr credential forwarding. `economic_id` is the caller-persisted identity for crash recovery. Reusing it after a crash reuses the backend idempotency key and deterministic receipt; a new value is explicit new intent.

Velkr requires `extra.assetTransferMethod="velkr-vault-v1"` and `paymentFlow="upfront"`. The retry carries a `velkr-receipt-v1` proof. This is not the standard exact-SVM partially-signed facilitator flow.

## Development and evidence boundaries

```bash
python -m pip install -e '.[dev]'
python -m pytest
ruff check src tests examples
mypy src/velkr
python -m build
```

Unit and simulated workflow tests do not move funds. Backend integration tests are opt-in. The local-validator test is also opt-in and requires an externally injected `velkr_e2e_fee_payer` pytest fixture; it never loads secrets itself. A transaction must be simulated and explicitly approved by the operator before that test is run.

