feat: add HTTPS RPC proxy for MetaMask mobile support
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
Nginx SSL reverse proxy (port 8443) in front of Geth using Let's Encrypt cert via Cloudflare DNS challenge. MetaMask mobile requires HTTPS for custom RPC URLs. Also adds AFC token icon served from bridge API static files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -134,6 +134,17 @@ services:
|
|||||||
limits:
|
limits:
|
||||||
memory: 1G
|
memory: 1G
|
||||||
|
|
||||||
|
rpc-ssl:
|
||||||
|
image: nginx:alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- geth
|
||||||
|
volumes:
|
||||||
|
- ./nginx/rpc-ssl.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
- certbot_etc:/etc/letsencrypt:ro
|
||||||
|
ports:
|
||||||
|
- "8443:8443"
|
||||||
|
|
||||||
afc-bridge:
|
afc-bridge:
|
||||||
build:
|
build:
|
||||||
context: ../services/afc-bridge
|
context: ../services/afc-bridge
|
||||||
@@ -160,3 +171,6 @@ volumes:
|
|||||||
minecraft_ftb_data:
|
minecraft_ftb_data:
|
||||||
geth_data:
|
geth_data:
|
||||||
afc_bridge_data:
|
afc_bridge_data:
|
||||||
|
certbot_etc:
|
||||||
|
external: true
|
||||||
|
name: docker_certbot_etc
|
||||||
|
|||||||
32
docker/nginx/rpc-ssl.conf
Normal file
32
docker/nginx/rpc-ssl.conf
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
events {
|
||||||
|
worker_connections 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
server {
|
||||||
|
listen 8443 ssl;
|
||||||
|
server_name play.consultoria-as.com;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/play.consultoria-as.com/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/play.consultoria-as.com/privkey.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
|
||||||
|
# Geth JSON-RPC proxy
|
||||||
|
location / {
|
||||||
|
proxy_pass http://geth:8545;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header Content-Type application/json;
|
||||||
|
|
||||||
|
# CORS for MetaMask
|
||||||
|
add_header Access-Control-Allow-Origin * always;
|
||||||
|
add_header Access-Control-Allow-Methods "POST, GET, OPTIONS" always;
|
||||||
|
add_header Access-Control-Allow-Headers "Content-Type" always;
|
||||||
|
|
||||||
|
if ($request_method = OPTIONS) {
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ COPY package.json package-lock.json* ./
|
|||||||
RUN npm install --production
|
RUN npm install --production
|
||||||
|
|
||||||
COPY contracts/ ./contracts/
|
COPY contracts/ ./contracts/
|
||||||
|
COPY public/ ./public/
|
||||||
COPY src/ ./src/
|
COPY src/ ./src/
|
||||||
|
|
||||||
EXPOSE 3001
|
EXPOSE 3001
|
||||||
|
|||||||
158
services/afc-bridge/public/afc-icon.svg
Normal file
158
services/afc-bridge/public/afc-icon.svg
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
|
||||||
|
<defs>
|
||||||
|
<!-- Main gradient - dark teal to cyan -->
|
||||||
|
<linearGradient id="coinGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#0D1B2A"/>
|
||||||
|
<stop offset="50%" stop-color="#1B2D45"/>
|
||||||
|
<stop offset="100%" stop-color="#0D1B2A"/>
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<!-- Rim gradient -->
|
||||||
|
<linearGradient id="rimGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#00E5CC"/>
|
||||||
|
<stop offset="25%" stop-color="#00BFA6"/>
|
||||||
|
<stop offset="50%" stop-color="#00E5CC"/>
|
||||||
|
<stop offset="75%" stop-color="#00BFA6"/>
|
||||||
|
<stop offset="100%" stop-color="#00E5CC"/>
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<!-- Inner glow gradient -->
|
||||||
|
<radialGradient id="innerGlow" cx="50%" cy="45%" r="50%">
|
||||||
|
<stop offset="0%" stop-color="#00E5CC" stop-opacity="0.15"/>
|
||||||
|
<stop offset="100%" stop-color="#0D1B2A" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
|
||||||
|
<!-- Phoenix flame gradient -->
|
||||||
|
<linearGradient id="phoenixGrad" x1="50%" y1="100%" x2="50%" y2="0%">
|
||||||
|
<stop offset="0%" stop-color="#00BFA6"/>
|
||||||
|
<stop offset="40%" stop-color="#00E5CC"/>
|
||||||
|
<stop offset="70%" stop-color="#4DFFD2"/>
|
||||||
|
<stop offset="100%" stop-color="#AAFFF0"/>
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
<!-- Subtle glow filter -->
|
||||||
|
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
|
||||||
|
<feGaussianBlur stdDeviation="4" result="blur"/>
|
||||||
|
<feComposite in="SourceGraphic" in2="blur" operator="over"/>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<filter id="softGlow" x="-30%" y="-30%" width="160%" height="160%">
|
||||||
|
<feGaussianBlur stdDeviation="8" result="blur"/>
|
||||||
|
<feMerge>
|
||||||
|
<feMergeNode in="blur"/>
|
||||||
|
<feMergeNode in="SourceGraphic"/>
|
||||||
|
</feMerge>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<!-- Drop shadow for depth -->
|
||||||
|
<filter id="coinShadow" x="-10%" y="-10%" width="130%" height="130%">
|
||||||
|
<feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#000" flood-opacity="0.4"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Background circle shadow -->
|
||||||
|
<circle cx="256" cy="260" r="230" fill="#000" opacity="0.3" filter="url(#coinShadow)"/>
|
||||||
|
|
||||||
|
<!-- Outer coin body -->
|
||||||
|
<circle cx="256" cy="256" r="230" fill="url(#coinGrad)" stroke="url(#rimGrad)" stroke-width="6"/>
|
||||||
|
|
||||||
|
<!-- Inner rim -->
|
||||||
|
<circle cx="256" cy="256" r="210" fill="none" stroke="#00E5CC" stroke-width="1.5" opacity="0.5"/>
|
||||||
|
<circle cx="256" cy="256" r="205" fill="none" stroke="#00E5CC" stroke-width="0.5" opacity="0.25"/>
|
||||||
|
|
||||||
|
<!-- Inner glow -->
|
||||||
|
<circle cx="256" cy="256" r="210" fill="url(#innerGlow)"/>
|
||||||
|
|
||||||
|
<!-- Decorative ring with dashes -->
|
||||||
|
<circle cx="256" cy="256" r="195" fill="none" stroke="#00E5CC" stroke-width="1" stroke-dasharray="3 8" opacity="0.35"/>
|
||||||
|
|
||||||
|
<!-- Central phoenix/afterlife symbol - stylized rising flame/phoenix wing -->
|
||||||
|
<g transform="translate(256,256)" filter="url(#softGlow)">
|
||||||
|
<!-- Central rising flame / phoenix shape -->
|
||||||
|
<path d="
|
||||||
|
M 0,-95
|
||||||
|
C 15,-80 25,-55 20,-35
|
||||||
|
C 18,-20 8,-5 0,10
|
||||||
|
C -8,-5 -18,-20 -20,-35
|
||||||
|
C -25,-55 -15,-80 0,-95
|
||||||
|
Z
|
||||||
|
" fill="url(#phoenixGrad)" opacity="0.9"/>
|
||||||
|
|
||||||
|
<!-- Left wing -->
|
||||||
|
<path d="
|
||||||
|
M -5,0
|
||||||
|
C -20,-15 -50,-40 -65,-55
|
||||||
|
C -75,-65 -80,-60 -75,-48
|
||||||
|
C -68,-35 -45,-15 -25,5
|
||||||
|
C -15,15 -8,12 -5,0
|
||||||
|
Z
|
||||||
|
" fill="url(#phoenixGrad)" opacity="0.75"/>
|
||||||
|
|
||||||
|
<!-- Right wing -->
|
||||||
|
<path d="
|
||||||
|
M 5,0
|
||||||
|
C 20,-15 50,-40 65,-55
|
||||||
|
C 75,-65 80,-60 75,-48
|
||||||
|
C 68,-35 45,-15 25,5
|
||||||
|
C 15,15 8,12 5,0
|
||||||
|
Z
|
||||||
|
" fill="url(#phoenixGrad)" opacity="0.75"/>
|
||||||
|
|
||||||
|
<!-- Left outer wing -->
|
||||||
|
<path d="
|
||||||
|
M -25,5
|
||||||
|
C -40,-5 -70,-25 -88,-32
|
||||||
|
C -98,-36 -100,-30 -92,-22
|
||||||
|
C -82,-12 -55,5 -35,18
|
||||||
|
C -25,25 -18,18 -25,5
|
||||||
|
Z
|
||||||
|
" fill="#00E5CC" opacity="0.45"/>
|
||||||
|
|
||||||
|
<!-- Right outer wing -->
|
||||||
|
<path d="
|
||||||
|
M 25,5
|
||||||
|
C 40,-5 70,-25 88,-32
|
||||||
|
C 98,-36 100,-30 92,-22
|
||||||
|
C 82,-12 55,5 35,18
|
||||||
|
C 25,25 18,18 25,5
|
||||||
|
Z
|
||||||
|
" fill="#00E5CC" opacity="0.45"/>
|
||||||
|
|
||||||
|
<!-- Small flame tip accent -->
|
||||||
|
<path d="
|
||||||
|
M 0,-95
|
||||||
|
C 5,-105 3,-115 0,-120
|
||||||
|
C -3,-115 -5,-105 0,-95
|
||||||
|
Z
|
||||||
|
" fill="#AAFFF0" opacity="0.8"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- "AFC" text -->
|
||||||
|
<text x="256" y="330"
|
||||||
|
font-family="'Orbitron', 'Rajdhani', 'Exo 2', 'Segoe UI', sans-serif"
|
||||||
|
font-size="52"
|
||||||
|
font-weight="700"
|
||||||
|
fill="#00E5CC"
|
||||||
|
text-anchor="middle"
|
||||||
|
letter-spacing="14"
|
||||||
|
filter="url(#glow)">AFC</text>
|
||||||
|
|
||||||
|
<!-- "AFTERCOIN" subtitle -->
|
||||||
|
<text x="256" y="360"
|
||||||
|
font-family="'Orbitron', 'Rajdhani', 'Exo 2', 'Segoe UI', sans-serif"
|
||||||
|
font-size="14"
|
||||||
|
font-weight="400"
|
||||||
|
fill="#00BFA6"
|
||||||
|
text-anchor="middle"
|
||||||
|
letter-spacing="8"
|
||||||
|
opacity="0.7">AFTERCOIN</text>
|
||||||
|
|
||||||
|
<!-- Top decorative dots -->
|
||||||
|
<circle cx="206" cy="385" r="2" fill="#00E5CC" opacity="0.4"/>
|
||||||
|
<circle cx="256" cy="390" r="2" fill="#00E5CC" opacity="0.4"/>
|
||||||
|
<circle cx="306" cy="385" r="2" fill="#00E5CC" opacity="0.4"/>
|
||||||
|
|
||||||
|
<!-- Subtle circuit-like lines at bottom -->
|
||||||
|
<line x1="220" y1="400" x2="292" y2="400" stroke="#00E5CC" stroke-width="0.5" opacity="0.2"/>
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 5.0 KiB |
@@ -1,3 +1,4 @@
|
|||||||
|
const path = require("path");
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
const config = require("./config");
|
const config = require("./config");
|
||||||
const db = require("./db");
|
const db = require("./db");
|
||||||
@@ -11,6 +12,9 @@ const walletRouter = require("./routes/wallet");
|
|||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
// Serve static files (token icon, etc.)
|
||||||
|
app.use(express.static(path.join(__dirname, "..", "public")));
|
||||||
|
|
||||||
// Parse JSON request bodies
|
// Parse JSON request bodies
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user