RPC Proxy
Deploy a secure RPC proxy to hide your API keys in browser applications
FortiBlox RPC Proxy
The FortiBlox RPC Proxy is a lightweight, secure proxy that allows you to hide your FortiBlox API keys from client-side applications. Deploy it to Cloudflare Workers, Vercel Edge Functions, or your own infrastructure in minutes.
Status: Coming Q1 2025. The RPC proxy is currently under development. Sign up for early access at nexus.fortiblox.com/rpc-proxy
The Problem
When building browser-based X1 Blockchain applications, you face a security dilemma:
// ❌ This exposes your API key to anyone using DevTools
const connection = new Connection(
`https://nexus.fortiblox.com/rpc?api-key=${apiKey}` // Visible in network tab!
);Anyone can:
- Open browser DevTools → Network tab
- See your API key in plain text
- Copy it and abuse your credits
- Exhaust your rate limits
The Solution
The FortiBlox RPC Proxy acts as a secure intermediary:
Browser → Your Proxy (with API key) → FortiBlox RPCYour API key stays on the server-side, never exposed to clients.
Features
Planned Features
-
One-Click Deployment
- Cloudflare Workers (recommended)
- Vercel Edge Functions
- Netlify Functions
- AWS Lambda
- Self-hosted Docker
-
Security Features
- API key hidden from clients
- Domain whitelisting (CORS)
- IP allowlisting
- Request rate limiting
- Request method filtering
- Custom authentication
-
Performance
- Edge deployment (low latency)
- WebSocket support
- Request caching
- Automatic retries
- Load balancing
-
Developer Experience
- Zero configuration defaults
- Environment variable management
- Detailed logging
- Metrics dashboard
- Error tracking
Deployment Options
Option 1: Cloudflare Workers (Recommended)
Why Cloudflare Workers?
- Global edge network (200+ cities)
- Zero cold starts
- Free tier: 100,000 requests/day
- Built-in DDoS protection
- WebSocket support
Deployment (Coming Soon):
# 1. Install Wrangler CLI
npm install -g wrangler
# 2. Clone the proxy repo
git clone https://github.com/fortiblox/fortiblox-rpc-proxy
cd fortiblox-rpc-proxy
# 3. Configure your API key
wrangler secret put FORTIBLOX_API_KEY
# Enter your API key when prompted
# 4. Deploy
wrangler deploy
# Output:
# ✨ Deployed to: https://fortiblox-proxy.your-subdomain.workers.devConfiguration:
# wrangler.toml
name = "fortiblox-rpc-proxy"
main = "src/index.js"
compatibility_date = "2025-01-01"
[vars]
# Allowed origins (comma-separated)
ALLOWED_ORIGINS = "https://myapp.com,https://*.myapp.com"
# Rate limiting (requests per minute)
RATE_LIMIT = "60"
# Enable request logging
DEBUG = "false"Option 2: Vercel Edge Functions
Deployment (Coming Soon):
# 1. Install Vercel CLI
npm install -g vercel
# 2. Clone and deploy
git clone https://github.com/fortiblox/fortiblox-rpc-proxy
cd fortiblox-rpc-proxy
vercel deploy
# 3. Set environment variables
vercel env add FORTIBLOX_API_KEY
# Enter your API key when prompted
# Output:
# ✨ Deployed to: https://fortiblox-proxy.vercel.appOption 3: Self-Hosted Docker
Deployment:
# Coming soon - Docker image will be available at:
docker pull fortiblox/rpc-proxy:latest
docker run -d \
-p 3000:3000 \
-e FORTIBLOX_API_KEY=your_api_key_here \
-e ALLOWED_ORIGINS=https://myapp.com \
fortiblox/rpc-proxy:latestUsage
Once deployed, use your proxy URL instead of the FortiBlox API directly:
import { Connection } from '@solana/web3.js';
// ✅ Use your proxy URL (no API key exposed!)
const connection = new Connection(
'https://fortiblox-proxy.your-subdomain.workers.dev',
'confirmed'
);
// Make RPC calls as normal
const slot = await connection.getSlot();
const health = await connection.getHealth();
// Send transactions
const signature = await connection.sendTransaction(transaction, [signer]);from solana.rpc.api import Client
# ✅ Use your proxy URL (no API key exposed!)
client = Client("https://fortiblox-proxy.your-subdomain.workers.dev")
# Make RPC calls as normal
slot = client.get_slot()
health = client.get_health()
# Send transactions
signature = client.send_transaction(transaction)import { Connection } from '@solana/web3.js';
import { useMemo } from 'react';
function App() {
// ✅ Use your proxy URL (no API key exposed!)
const connection = useMemo(
() => new Connection(
'https://fortiblox-proxy.your-subdomain.workers.dev',
'confirmed'
),
[]
);
async function fetchData() {
const slot = await connection.getSlot();
console.log('Current slot:', slot);
}
return (
<div>
<button onClick={fetchData}>Fetch Slot</button>
</div>
);
}import { Connection } from '@solana/web3.js';
import { ref, onMounted } from 'vue';
export default {
setup() {
// ✅ Use your proxy URL (no API key exposed!)
const connection = new Connection(
'https://fortiblox-proxy.your-subdomain.workers.dev',
'confirmed'
);
const slot = ref(null);
async function fetchSlot() {
slot.value = await connection.getSlot();
}
onMounted(fetchSlot);
return { slot, fetchSlot };
}
};Configuration
Environment Variables
# Required
FORTIBLOX_API_KEY=fbx_your_api_key_here
# Optional
ALLOWED_ORIGINS=https://myapp.com,https://*.myapp.com
ALLOWED_METHODS=POST,GET
RATE_LIMIT=60
CACHE_TTL=60
DEBUG=false
ENABLE_WEBSOCKET=trueAdvanced Configuration
Rate Limiting:
// wrangler.toml or .env
RATE_LIMIT=60 // 60 requests per minute
RATE_LIMIT_WINDOW=60 // 60 second window
RATE_LIMIT_BY=ip // Rate limit by: ip, origin, or custom-headerRequest Filtering:
// Only allow specific RPC methods
ALLOWED_METHODS=getAccountInfo,getBalance,sendTransaction
// Block specific RPC methods
BLOCKED_METHODS=getProgramAccounts,getTokenAccountsByOwnerCustom Headers:
// Add custom headers to responses
CUSTOM_HEADERS={
"X-Powered-By": "FortiBlox",
"X-Proxy-Version": "1.0.0"
}Security Best Practices
1. Enable CORS Restrictions
// Restrict to your domains only
ALLOWED_ORIGINS=https://myapp.com,https://www.myapp.com
// ✅ Requests from myapp.com - Allowed
// ❌ Requests from attacker.com - Blocked2. Implement Rate Limiting
// Prevent abuse
RATE_LIMIT=60 // 60 requests per minute per IP
BURST_LIMIT=10 // Allow short bursts
// When exceeded:
// HTTP 429: Too Many Requests
// Retry-After: 303. Use Request Authentication (Optional)
Add custom authentication:
// Require custom auth header
REQUIRE_AUTH_HEADER=true
AUTH_HEADER_NAME=X-App-Secret
AUTH_HEADER_VALUE=your_secret_value
// In your frontend:
fetch('https://your-proxy.com', {
headers: {
'X-App-Secret': 'your_secret_value'
}
});4. Monitor Usage
Track proxy usage in Cloudflare/Vercel dashboard:
- Total requests
- Blocked requests
- Error rates
- Response times
- Geographic distribution
WebSocket Support
The proxy supports WebSocket connections for real-time data:
import { Connection } from '@solana/web3.js';
const connection = new Connection(
'https://fortiblox-proxy.your-subdomain.workers.dev',
'confirmed'
);
// Subscribe to account changes
const subscriptionId = connection.onAccountChange(
publicKey,
(accountInfo) => {
console.log('Account updated:', accountInfo);
}
);
// WebSocket connection goes through proxy securelyTroubleshooting
CORS Errors
Access to fetch has been blocked by CORS policySolution: Add your domain to ALLOWED_ORIGINS:
wrangler secret put ALLOWED_ORIGINS
# Enter: https://myapp.com,https://www.myapp.comRate Limit Errors
429 Too Many Requests
Retry-After: 60Solution: Increase rate limit or implement client-side throttling:
// Implement exponential backoff
async function makeRequestWithRetry(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error.status === 429 && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
}Proxy Not Responding
Checklist:
- Is the proxy deployed? Check deployment status
- Is
FORTIBLOX_API_KEYset correctly? - Are you making requests from an allowed origin?
- Check proxy logs for errors
Comparison with Alternatives
FortiBlox RPC Proxy vs DIY Backend
| Feature | FortiBlox Proxy | DIY Backend |
|---|---|---|
| Setup Time | 5 minutes | Hours |
| Infrastructure | Managed (Cloudflare) | Self-managed |
| Global Edge | ✅ 200+ locations | ❌ Single region |
| Cold Starts | ✅ None | ❌ Possible |
| Cost | Free (100K req/day) | Server costs |
| Maintenance | ✅ None | ❌ Ongoing |
| WebSocket | ✅ Supported | Requires work |
| Updates | ✅ Automatic | ❌ Manual |
FortiBlox vs Helius RPC Proxy
| Feature | FortiBlox | Helius |
|---|---|---|
| Open Source | ✅ Yes | ✅ Yes |
| Cloudflare Workers | ✅ Yes | ✅ Yes |
| Vercel Edge | ✅ Yes | ❌ No |
| Docker | ✅ Yes | ❌ No |
| Rate Limiting | ✅ Built-in | ⚠️ Basic |
| Request Filtering | ✅ Advanced | ⚠️ Basic |
| Custom Auth | ✅ Yes | ❌ No |
| Analytics | ✅ Built-in | ⚠️ Basic |
Roadmap
Q1 2025
- ✅ Core proxy functionality
- ✅ Cloudflare Workers support
- ✅ Basic rate limiting
- ✅ CORS configuration
Q2 2025
- ⏳ Vercel Edge Functions support
- ⏳ Advanced rate limiting (per-user)
- ⏳ Request analytics dashboard
- ⏳ Custom authentication hooks
Q3 2025
- ⏳ AWS Lambda support
- ⏳ Docker image
- ⏳ Load balancing
- ⏳ Automatic failover
Q4 2025
- ⏳ Redis-based rate limiting
- ⏳ Request caching
- ⏳ GraphQL support
- ⏳ Multi-key load balancing
Get Early Access
Sign up for early access to the FortiBlox RPC Proxy:
- Visit nexus.fortiblox.com/rpc-proxy
- Enter your email
- We'll notify you when it's ready (Q1 2025)
Early access benefits:
- Beta access before public launch
- Priority support
- Feature requests
- Extended free tier
Temporary Solution: Build Your Own
While the official proxy is in development, you can build a simple proxy:
// server.js
const express = require('express');
const fetch = require('node-fetch');
require('dotenv').config();
const app = express();
app.use(express.json());
// CORS
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://yourdomain.com');
res.header('Access-Control-Allow-Methods', 'POST');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
// Proxy endpoint
app.post('/rpc', async (req, res) => {
try {
const response = await fetch(
`https://nexus.fortiblox.com/rpc?api-key=${process.env.FORTIBLOX_API_KEY}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(req.body)
}
);
const data = await response.json();
res.json(data);
} catch (error) {
res.status(500).json({ error: 'Proxy error' });
}
});
app.listen(3000, () => console.log('Proxy running on port 3000'));// src/index.js
export default {
async fetch(request, env) {
// CORS preflight
if (request.method === 'OPTIONS') {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': 'https://yourdomain.com',
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Headers': 'Content-Type'
}
});
}
// Only allow POST
if (request.method !== 'POST') {
return new Response('Method not allowed', { status: 405 });
}
try {
// Forward to FortiBlox
const response = await fetch(
`https://nexus.fortiblox.com/rpc?api-key=${env.FORTIBLOX_API_KEY}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: await request.text()
}
);
// Return response with CORS
return new Response(await response.text(), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'https://yourdomain.com'
}
});
} catch (error) {
return new Response(
JSON.stringify({ error: 'Proxy error' }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
}
};Support
Questions about the RPC Proxy?
- Documentation: You're reading it!
- Discord: discord.gg/fortiblox - #rpc-proxy channel
- Email: [email protected]
- GitHub: github.com/fortiblox/fortiblox-rpc-proxy (coming soon)