For the complete documentation index optimized for AI agents, see llms.txt or llms-full.txt. A markdown version of this page is available by appending.mdto the URL or sendingAccept: text/markdown.
Transaction Relay
For AI agents: the documentation index is at llms.txt (full corpus: llms-full.txt). A markdown source for this page is /a4-server/transaction-relay.md.
arete-server can expose a purpose-built Solana transaction transport on the same HTTP origin as stack reads. It is disabled by default, even when an RPC URL is configured.
The relay provides six fixed routes. It is not a generic JSON-RPC proxy, and it never receives signing keys or signs transactions.
Enable the HTTP server
Section titled “Enable the HTTP server”The relay requires the server’s HTTP listener:
use arete_server::Server;
Server::builder() .spec(my_stack::spec()) .websocket() .bind("[::]:8877".parse()?) .http() .health_monitoring() .start() .await?;Enable transaction routes through environment configuration:
ARETE_TRANSACTIONS_ENABLED=true \ARETE_TRANSACTION_RPC_URL=https://your-dedicated-solana-rpc.example \cargo run --releaseOr configure them programmatically:
use arete_server::{Server, TransactionConfig};
Server::builder() .spec(my_stack::spec()) .websocket() .http() .transactions_config(TransactionConfig { enabled: true, rpc_url: Some(transaction_rpc_url), ..TransactionConfig::default() }) .start() .await?;Routes and scopes
Section titled “Routes and scopes”| Route | Required scope | Solana RPC method |
|---|---|---|
POST /transactions/v1/latest-blockhash | transaction:inspect | getLatestBlockhash |
POST /transactions/v1/fee | transaction:inspect | getFeeForMessage |
POST /transactions/v1/simulate | transaction:inspect | simulateTransaction |
POST /transactions/v1/signature-status | transaction:inspect | getSignatureStatuses |
POST /transactions/v1/block-height | transaction:inspect | getBlockHeight |
POST /transactions/v1/send | transaction:send | sendTransaction |
Routes accept validated JSON schemas and reject unknown fields. Solana u64 values are decimal strings over HTTP.
Authentication
Section titled “Authentication”For production, configure SignedSessionAuthPlugin through the HTTP auth plugin boundary. Read, inspect, and send scopes are independent. A read-only token cannot inspect or submit transactions.
Do not expose a production relay with development allow_all behavior. Self-hosted local development may deliberately omit the plugin when the listener is not publicly reachable.
When running behind a trusted proxy, configure ARETE_TRUSTED_PROXY_CIDRS. Forwarded client IP headers are ignored unless the direct peer belongs to one of those networks.
Configuration reference
Section titled “Configuration reference”| Variable | Default | Purpose |
|---|---|---|
ARETE_TRANSACTIONS_ENABLED | false | Expose transaction routes |
ARETE_TRANSACTION_RPC_URL | unset | Preferred upstream transaction RPC |
SOLANA_RPC_URL / RPC_URL | unset | Legacy transaction RPC fallback |
ARETE_TRANSACTION_MAX_BODY_BYTES | 4096 | Maximum JSON request body |
ARETE_TRANSACTION_MAX_BYTES | 1232 | Maximum decoded message/transaction bytes |
ARETE_TRANSACTION_INSPECT_TIMEOUT_MS | 10000 | Inspection upstream timeout |
ARETE_TRANSACTION_SEND_TIMEOUT_MS | 15000 | Submission upstream timeout |
ARETE_TRANSACTION_STATUS_TIMEOUT_MS | 10000 | Status/block-height timeout |
ARETE_TRANSACTION_INSPECT_CONCURRENCY | 64 | Global inspect concurrency |
ARETE_TRANSACTION_SEND_CONCURRENCY | 16 | Global send concurrency |
ARETE_TRANSACTION_INSPECT_REQUESTS_PER_MINUTE | 600 | Server inspect clamp |
ARETE_TRANSACTION_SEND_REQUESTS_PER_MINUTE | 60 | Server send clamp |
ARETE_TRANSACTION_STATUS_REQUESTS_PER_MINUTE | 600 | Server status clamp |
ARETE_TRUSTED_PROXY_CIDRS | empty | Comma-separated trusted proxy networks |
ARETE_TRANSACTION_USAGE_ENABLED | false | Enable transaction usage delivery |
ARETE_TRANSACTION_USAGE_ENDPOINT | unset | Usage ingestion endpoint |
ARETE_TRANSACTION_USAGE_TOKEN | unset | Usage ingestion bearer token |
ARETE_TRANSACTION_USAGE_SPOOL_CAPACITY | 1000 | In-memory usage queue capacity |
Transaction traffic never falls back to ARETE_READ_RPC_URL. Use a dedicated provider credential when possible so read and transaction quotas are isolated.
Submission safety
Section titled “Submission safety”The send route:
- accepts only bounded base64 wire transactions
- requires nonzero signatures
- derives the first transaction signature before contacting upstream
- calls upstream
sendTransactiononce - forces provider
maxRetries: 0 - verifies that the provider returns the expected signature
- marks timeout/transport uncertainty with the derived signature
Clients must reconcile an ambiguous signature rather than resubmit it blindly.
Limits and scaling
Section titled “Limits and scaling”The server clamps request size, concurrency, and per-minute operation counts. Signed-session claims can impose lower limits per subject. Rate buckets and subject concurrency are process-local in V1.
Keep a transaction-enabled deployment at one replica until admission state is externalized. Scaling replicas multiplies effective per-process limits.
Usage and observability
Section titled “Usage and observability”Optional transaction usage delivery sends operation, result, identity, byte count, and latency metadata. It excludes transaction bytes, account lists, program logs, credentials, and full signatures.
V1 uses a bounded in-memory queue with bounded retries. It is not a durable billing queue. Alert on queue saturation and failed delivery logs.
With the otel feature, monitor:
arete.transaction.requests.totalarete.transaction.request.durationarete.transaction.request.bytesarete.transaction.upstream.totalarete.transaction.inflightarete.transaction.denials.total
Operational checklist
Section titled “Operational checklist”- Use a dedicated HTTPS transaction RPC.
- Configure signed-session HTTP auth and exact scopes.
- Configure trusted proxy CIDRs correctly.
- Keep one replica in V1.
- Alert on upstream timeouts and ambiguous submissions.
- Alert on usage queue drops when usage tracking is enabled.
- Exercise a signed test transaction before enabling browser traffic.
- Preserve routes during rollback until issued transaction tokens expire.
Improvements still needed
Section titled “Improvements still needed”The most valuable follow-up work is:
- Durable, batched usage delivery with a dead-letter path.
- Shared rate/admission state for horizontal scaling.
- Configurable circuit breaking and provider failover for inspect/status calls only.
- A reusable transport conformance test suite.
- Validator-backed release tests and hosted browser canaries.
- Grafana dashboards and alerts for transaction-specific metrics.
See Using transactions for application integration and error handling.