Architecture
Urblock is a multi-tenant SaaS platform that abstracts blockchain complexity behind a REST API. It handles signing, gas estimation, nonce management, and on-chain confirmation so your application can integrate blockchain flows without operating its own transaction pipeline.
System Overview
┌─────────────────────────────────────────────────────────────────────────┐
│ Client (SDK / curl) │
└──────────────────────────────────┬──────────────────────────────────────┘
│ HTTPS
┌──────────────────────────────────▼──────────────────────────────────────┐
│ API Platform │
│ ┌─────────┐ ┌────────────┐ ┌────────────┐ ┌───────────────────┐ │
│ │ Auth │ │ Validation │ │ Services │ │ Data Layer │ │
│ │ Guard │ │ │ │ (Logic) │ │ │ │
│ └────┬────┘ └─────┬──────┘ └─────┬──────┘ └────────┬──────────┘ │
│ │ │ │ │ │
│ Rate Limiter class-validator Orchestration tenant_id scope │
└──────────────────────────┬──────────────────────────────────────────────┘
│
┌────────────────┼────────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌──────────────┐
│ Data Store │ │ Cache │ │ Async Jobs │
│ │ │ │ │ │
└────────────┘ └────────────┘ └──────┬───────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────────┐
│tx-submit │ │tx-confirm│ │ webhook-send │
│ worker │ │ worker │ │ worker │
└────┬─────┘ └────┬─────┘ └──────┬───────┘
│ │ │
▼ ▼ ▼
Blockchain Blockchain Tenant's
RPC RPC webhook URL
Request Flow
Client Request
→ API Gateway (rate limiting, auth)
→ API controller (input validation)
→ Service (business logic, orchestration)
→ Data layer
→ Async job queue (for blockchain operations)
→ Response: { status: "pending", id: "tx_..." }
Background Workers
→ tx-submit: build, sign, submit transaction to RPC
→ tx-confirm: wait for on-chain confirmation
→ webhook-send: notify tenant via HTTP callback
Example: Token Deploy
POST /v1/tokens→ Controller validates DTO- Service computes constructor args and encoded bytecode
- Repository saves token record (
status: "deploying") and transaction record (status: "pending") - Async job enqueued for submission
- API returns
{ id: "tok_abc123", status: "deploying" }immediately tx-submitworker: resolves nonce, estimates gas, signs with HD wallet, sends to RPCtx-confirmworker: polls for receipt, updatesstatus: "confirmed", setscontract_addresswebhook-sendworker: firestoken.deployedevent to registered webhooks
Async-First Design
All blockchain operations are asynchronous. The API returns immediately with a pending status, and the actual on-chain execution happens in background workers.
Transaction Lifecycle
| Status | Meaning |
|---|---|
pending | Saved to DB, queued for submission |
submitted | Sent to the blockchain RPC, has a tx_hash |
confirmed | Included in a block, has block_number and gas_used |
failed | Transaction reverted or timed out |
Component Stack
| Layer | Technology Class | Role |
|---|---|---|
| API | HTTP application layer | Request handling, validation, routing |
| Database | Relational storage | Persistent resource and transaction state |
| Cache | In-memory coordination | Rate limiting, caching, short-lived state |
| Queue | Background processing | Submission, confirmation, retries |
| Blockchain | EVM interaction layer | RPC communication and transaction lifecycle |
| Smart Contracts | Audited token and protocol contracts | On-chain execution surface |
| Observability | Logs, traces, metrics | Operability and incident visibility |
Multi-Tenant Isolation
Every request and resource lookup is scoped to a tenant context. Data does not cross tenant boundaries.
- Each API key belongs to exactly one tenant
- Resource access is resolved in tenant context
- Signing and transaction state stay isolated per tenant
- Background processing preserves tenant ownership metadata
Security Model
| Asset | Protection |
|---|---|
| Wallet root material | Managed server-side and never returned by the API |
| Private keys | AES-256-GCM encrypted at rest |
| API keys | bcrypt hashed in DB, plain key shown only at creation |
| Inputs | class-validator on every DTO |
| Rate limiting | Per tenant, 100 req/min (configurable) |
| Sensitive headers | Never logged |
Idempotency
All write operations accept an idempotency_key. If the same key is submitted twice, the second request returns the original result without re-executing. This prevents double-spends and duplicate deploys.
Background Jobs
| Job | Retries | Backoff | Priority |
|---|---|---|---|
tx-submit | 3 | Exponential 5s | High |
tx-confirm | 10 | Exponential 10s | High |
webhook-send | 5 | Exponential 30s | Medium |
contract-deploy | 3 | Exponential 10s | High |
Dead Letter Queue
Jobs that exhaust all retries move into an inspection path for internal recovery workflows. Failed webhook deliveries are also recorded so tenants can diagnose delivery outcomes.
Observability
| Signal | Implementation |
|---|---|
| Logs | Structured application logs |
| Traces | Request and background-job tracing |
| Metrics | Request, queue, and transaction health metrics |
| Health | GET /health (liveness) + GET /v1/status (dependency-aware status) |
Next Steps
- Async Operations — how pending transactions work
- Security Model — detailed security architecture
- Authentication — API keys vs JWTs
- Errors — error types and codes
- Health API — monitoring endpoints