Skip to content
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 .md to the URL or sending Accept: 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.

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:

Terminal window
ARETE_TRANSACTIONS_ENABLED=true \
ARETE_TRANSACTION_RPC_URL=https://your-dedicated-solana-rpc.example \
cargo run --release

Or 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?;
RouteRequired scopeSolana RPC method
POST /transactions/v1/latest-blockhashtransaction:inspectgetLatestBlockhash
POST /transactions/v1/feetransaction:inspectgetFeeForMessage
POST /transactions/v1/simulatetransaction:inspectsimulateTransaction
POST /transactions/v1/signature-statustransaction:inspectgetSignatureStatuses
POST /transactions/v1/block-heighttransaction:inspectgetBlockHeight
POST /transactions/v1/sendtransaction:sendsendTransaction

Routes accept validated JSON schemas and reject unknown fields. Solana u64 values are decimal strings over HTTP.

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.

VariableDefaultPurpose
ARETE_TRANSACTIONS_ENABLEDfalseExpose transaction routes
ARETE_TRANSACTION_RPC_URLunsetPreferred upstream transaction RPC
SOLANA_RPC_URL / RPC_URLunsetLegacy transaction RPC fallback
ARETE_TRANSACTION_MAX_BODY_BYTES4096Maximum JSON request body
ARETE_TRANSACTION_MAX_BYTES1232Maximum decoded message/transaction bytes
ARETE_TRANSACTION_INSPECT_TIMEOUT_MS10000Inspection upstream timeout
ARETE_TRANSACTION_SEND_TIMEOUT_MS15000Submission upstream timeout
ARETE_TRANSACTION_STATUS_TIMEOUT_MS10000Status/block-height timeout
ARETE_TRANSACTION_INSPECT_CONCURRENCY64Global inspect concurrency
ARETE_TRANSACTION_SEND_CONCURRENCY16Global send concurrency
ARETE_TRANSACTION_INSPECT_REQUESTS_PER_MINUTE600Server inspect clamp
ARETE_TRANSACTION_SEND_REQUESTS_PER_MINUTE60Server send clamp
ARETE_TRANSACTION_STATUS_REQUESTS_PER_MINUTE600Server status clamp
ARETE_TRUSTED_PROXY_CIDRSemptyComma-separated trusted proxy networks
ARETE_TRANSACTION_USAGE_ENABLEDfalseEnable transaction usage delivery
ARETE_TRANSACTION_USAGE_ENDPOINTunsetUsage ingestion endpoint
ARETE_TRANSACTION_USAGE_TOKENunsetUsage ingestion bearer token
ARETE_TRANSACTION_USAGE_SPOOL_CAPACITY1000In-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.

The send route:

  • accepts only bounded base64 wire transactions
  • requires nonzero signatures
  • derives the first transaction signature before contacting upstream
  • calls upstream sendTransaction once
  • 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.

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.

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.total
  • arete.transaction.request.duration
  • arete.transaction.request.bytes
  • arete.transaction.upstream.total
  • arete.transaction.inflight
  • arete.transaction.denials.total
  1. Use a dedicated HTTPS transaction RPC.
  2. Configure signed-session HTTP auth and exact scopes.
  3. Configure trusted proxy CIDRs correctly.
  4. Keep one replica in V1.
  5. Alert on upstream timeouts and ambiguous submissions.
  6. Alert on usage queue drops when usage tracking is enabled.
  7. Exercise a signed test transaction before enabling browser traffic.
  8. Preserve routes during rollback until issued transaction tokens expire.

The most valuable follow-up work is:

  1. Durable, batched usage delivery with a dead-letter path.
  2. Shared rate/admission state for horizontal scaling.
  3. Configurable circuit breaking and provider failover for inspect/status calls only.
  4. A reusable transport conformance test suite.
  5. Validator-backed release tests and hosted browser canaries.
  6. Grafana dashboards and alerts for transaction-specific metrics.

See Using transactions for application integration and error handling.