Skip to content

Commit d8097bf

Browse files
committed
Canonical URLs on fizzl.eu
The services now answer on their own domain (Render custom domains, CNAME at Strato); the onrender.com addresses keep working. Every place that names a service URL moves to the new host (MCP server.json, discovery, OpenAPI, web pages and cross-links, workflows, README): - x402-doctor.onrender.com -> x402-doctor.fizzl.eu - presign-guard.onrender.com -> presign-guard.fizzl.eu - ichimoku-signal.onrender.com -> ichimoku-signal.fizzl.eu - smartcontractexplainer.onrender.com -> plaintext.fizzl.eu Unchanged on purpose: media/explainer (describes the recorded videos) and existing agentic.market listing URLs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TsD5haPKxeWjYmErHzvU48
1 parent b898112 commit d8097bf

10 files changed

Lines changed: 105 additions & 105 deletions

File tree

‎.github/workflows/explainer-video.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454
npx playwright install --with-deps chromium
5555
- name: Wake the live services
5656
run: |
57-
curl -s -o /dev/null --retry 6 --retry-delay 10 --retry-all-errors --max-time 90 https://smartcontractexplainer.onrender.com/api/health || true
57+
curl -s -o /dev/null --retry 6 --retry-delay 10 --retry-all-errors --max-time 90 https://plaintext.fizzl.eu/api/health || true
5858
- name: Record
5959
run: node record.js
6060
- name: Mix and encode

‎.github/workflows/keep-alive.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ jobs:
1414
steps:
1515
- name: Ping health endpoint
1616
run: |
17-
curl -sf -m 30 https://smartcontractexplainer.onrender.com/api/health
17+
curl -sf -m 30 https://plaintext.fizzl.eu/api/health

‎.github/workflows/publish-mcp.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ jobs:
1818
# listing look dead to the first visitors; wake it and check /mcp.
1919
- name: Check the live MCP endpoint
2020
run: |
21-
curl -s -o /dev/null --retry 5 --retry-delay 10 --max-time 90 https://smartcontractexplainer.onrender.com/api/health
22-
curl -sf --max-time 60 https://smartcontractexplainer.onrender.com/mcp \
21+
curl -s -o /dev/null --retry 5 --retry-delay 10 --max-time 90 https://plaintext.fizzl.eu/api/health
22+
curl -sf --max-time 60 https://plaintext.fizzl.eu/mcp \
2323
-H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
2424
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | tee tools.json
2525
grep -q check_wallet_approvals tools.json

‎.github/workflows/smoke.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
smoke:
1313
runs-on: ubuntu-latest
1414
env:
15-
SITE: https://smartcontractexplainer.onrender.com
15+
SITE: https://plaintext.fizzl.eu
1616
steps:
1717
- name: Wake up
1818
run: curl -s -o /dev/null --retry 5 --retry-delay 10 --max-time 90 "$SITE/api/health"

‎README.md‎

Lines changed: 92 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,92 @@
1-
# PlainText — wallet approval translator
2-
3-
> **Moving:** the paid wallet approval check now lives in [presign-guard](https://github.com/Fizzl13/presign-guard) as `GET /v1/approvals?chain=…&address=…` ($0.02 USDC on Base or Solana, a verdict per approval and the ones to revoke, also as the MCP tool `wallet_approvals`). `/api/explain` overlaps with presign-guard's `POST /v1/check/explain`. PlainText's paid routes keep working for now.
4-
5-
A small Node.js app that looks up a wallet's token/NFT approvals via the
6-
GoPlus Security API and asks Claude to explain them in plain language.
7-
8-
[![PlainText in a minute](https://raw.githubusercontent.com/Fizzl13/SmartContractExplainer/explainer-video/poster.jpg)](https://smartcontractexplainer.onrender.com/media/explainer.mp4)
9-
10-
▶ [Watch the 1-minute explainer](https://smartcontractexplainer.onrender.com/media/explainer.mp4) · Live: https://smartcontractexplainer.onrender.com
11-
12-
## Project structure
13-
14-
```
15-
plaintext-wallet/
16-
├── server.js Express backend (GoPlus + Anthropic calls)
17-
├── media.js Serves the explainer video from the explainer-video branch
18-
├── media/explainer/ Script and pipeline for the explainer video
19-
├── package.json
20-
├── render.yaml Render deploy config (optional, see below)
21-
├── .env.example Copy to .env for local dev
22-
└── public/
23-
└── index.html Frontend (wallet check + demo scenarios)
24-
```
25-
26-
## 1. Run it locally first
27-
28-
```bash
29-
cd plaintext-wallet
30-
npm install
31-
cp .env.example .env
32-
# edit .env and paste your ANTHROPIC_API_KEY
33-
npm start
34-
```
35-
36-
Open http://localhost:3000 — try the "Try a sample" tab first (no API keys
37-
needed besides Anthropic), then "Check a wallet" with a real address once
38-
you're happy it works.
39-
40-
## 2. Deploy to Render
41-
42-
**Option A — one-click via render.yaml (Blueprint)**
43-
1. Push this folder to a new GitHub repo.
44-
2. In the Render dashboard: **New +** → **Blueprint** → select your repo.
45-
Render reads `render.yaml` automatically and creates the web service.
46-
3. When prompted, fill in the environment variables:
47-
- `ANTHROPIC_API_KEY` — required, from console.anthropic.com
48-
- `GOPLUS_ACCESS_TOKEN` — optional, only needed if you outgrow GoPlus's
49-
free 30 calls/minute limit (see console.gopluslabs.io)
50-
4. Click **Apply** — Render builds and deploys automatically.
51-
52-
**Option B — manual web service (no render.yaml needed)**
53-
1. Push this folder to a GitHub repo.
54-
2. Render dashboard → **New +** → **Web Service** → connect your repo.
55-
3. Settings:
56-
- **Environment**: Node
57-
- **Build Command**: `npm install`
58-
- **Start Command**: `npm start`
59-
- **Instance Type**: Free (fine for a prototype)
60-
4. Under **Environment Variables**, add `ANTHROPIC_API_KEY` (and optionally
61-
`GOPLUS_ACCESS_TOKEN`).
62-
5. Click **Create Web Service**. Render gives you a `https://<name>.onrender.com`
63-
URL once the build finishes.
64-
65-
Render's free tier spins the service down after inactivity — the first
66-
request after idling will take ~30-50 seconds to wake up. That's normal
67-
and fine for a prototype you're sharing for feedback.
68-
69-
## Notes on the GoPlus integration
70-
71-
- The wallet check calls `token_approval_security` or `nft721_approval_security`
72-
under `https://api.gopluslabs.io/api/v2/...`. This is documented but the
73-
GoPlus docs site is JS-rendered, so **before you rely on this in front of
74-
real users, do one manual test call** (e.g. with `curl`) against a wallet
75-
you control, and compare the actual JSON shape to what `server.js` expects
76-
— field names occasionally shift between GoPlus API versions.
77-
- The free GoPlus tier is capped at 30 calls/minute — plenty for early
78-
testing, but rate-limit errors will surface as a plain error message in
79-
the UI if you exceed it.
80-
- No user data is stored anywhere in this app — every check is a stateless
81-
round trip. If you later add accounts, saved wallets, or history, update
82-
this note (and your own privacy policy) accordingly.
83-
84-
## Costs to expect
85-
86-
- **Render free tier**: $0/month, with the cold-start behavior above. A paid
87-
tier ($7/month "Starter") removes the spin-down if this gets real usage.
88-
- **Anthropic API**: pay-per-use, billed to whatever key you provide. A
89-
single explanation call is small (well under 1K tokens), so cost per
90-
check will be a fraction of a cent — but keep an eye on your usage
91-
dashboard if this gets shared widely, since there's no rate limiting
92-
built into this prototype yet.
1+
# PlainText — wallet approval translator
2+
3+
> **Moving:** the paid wallet approval check now lives in [presign-guard](https://github.com/Fizzl13/presign-guard) as `GET /v1/approvals?chain=…&address=…` ($0.02 USDC on Base or Solana, a verdict per approval and the ones to revoke, also as the MCP tool `wallet_approvals`). `/api/explain` overlaps with presign-guard's `POST /v1/check/explain`. PlainText's paid routes keep working for now.
4+
5+
A small Node.js app that looks up a wallet's token/NFT approvals via the
6+
GoPlus Security API and asks Claude to explain them in plain language.
7+
8+
[![PlainText in a minute](https://raw.githubusercontent.com/Fizzl13/SmartContractExplainer/explainer-video/poster.jpg)](https://plaintext.fizzl.eu/media/explainer.mp4)
9+
10+
▶ [Watch the 1-minute explainer](https://plaintext.fizzl.eu/media/explainer.mp4) · Live: https://plaintext.fizzl.eu
11+
12+
## Project structure
13+
14+
```
15+
plaintext-wallet/
16+
├── server.js Express backend (GoPlus + Anthropic calls)
17+
├── media.js Serves the explainer video from the explainer-video branch
18+
├── media/explainer/ Script and pipeline for the explainer video
19+
├── package.json
20+
├── render.yaml Render deploy config (optional, see below)
21+
├── .env.example Copy to .env for local dev
22+
└── public/
23+
└── index.html Frontend (wallet check + demo scenarios)
24+
```
25+
26+
## 1. Run it locally first
27+
28+
```bash
29+
cd plaintext-wallet
30+
npm install
31+
cp .env.example .env
32+
# edit .env and paste your ANTHROPIC_API_KEY
33+
npm start
34+
```
35+
36+
Open http://localhost:3000 — try the "Try a sample" tab first (no API keys
37+
needed besides Anthropic), then "Check a wallet" with a real address once
38+
you're happy it works.
39+
40+
## 2. Deploy to Render
41+
42+
**Option A — one-click via render.yaml (Blueprint)**
43+
1. Push this folder to a new GitHub repo.
44+
2. In the Render dashboard: **New +** → **Blueprint** → select your repo.
45+
Render reads `render.yaml` automatically and creates the web service.
46+
3. When prompted, fill in the environment variables:
47+
- `ANTHROPIC_API_KEY` — required, from console.anthropic.com
48+
- `GOPLUS_ACCESS_TOKEN` — optional, only needed if you outgrow GoPlus's
49+
free 30 calls/minute limit (see console.gopluslabs.io)
50+
4. Click **Apply** — Render builds and deploys automatically.
51+
52+
**Option B — manual web service (no render.yaml needed)**
53+
1. Push this folder to a GitHub repo.
54+
2. Render dashboard → **New +** → **Web Service** → connect your repo.
55+
3. Settings:
56+
- **Environment**: Node
57+
- **Build Command**: `npm install`
58+
- **Start Command**: `npm start`
59+
- **Instance Type**: Free (fine for a prototype)
60+
4. Under **Environment Variables**, add `ANTHROPIC_API_KEY` (and optionally
61+
`GOPLUS_ACCESS_TOKEN`).
62+
5. Click **Create Web Service**. Render gives you a `https://<name>.onrender.com`
63+
URL once the build finishes.
64+
65+
Render's free tier spins the service down after inactivity — the first
66+
request after idling will take ~30-50 seconds to wake up. That's normal
67+
and fine for a prototype you're sharing for feedback.
68+
69+
## Notes on the GoPlus integration
70+
71+
- The wallet check calls `token_approval_security` or `nft721_approval_security`
72+
under `https://api.gopluslabs.io/api/v2/...`. This is documented but the
73+
GoPlus docs site is JS-rendered, so **before you rely on this in front of
74+
real users, do one manual test call** (e.g. with `curl`) against a wallet
75+
you control, and compare the actual JSON shape to what `server.js` expects
76+
— field names occasionally shift between GoPlus API versions.
77+
- The free GoPlus tier is capped at 30 calls/minute — plenty for early
78+
testing, but rate-limit errors will surface as a plain error message in
79+
the UI if you exceed it.
80+
- No user data is stored anywhere in this app — every check is a stateless
81+
round trip. If you later add accounts, saved wallets, or history, update
82+
this note (and your own privacy policy) accordingly.
83+
84+
## Costs to expect
85+
86+
- **Render free tier**: $0/month, with the cold-start behavior above. A paid
87+
tier ($7/month "Starter") removes the spin-down if this gets real usage.
88+
- **Anthropic API**: pay-per-use, billed to whatever key you provide. A
89+
single explanation call is small (well under 1K tokens), so cost per
90+
check will be a fraction of a cent — but keep an eye on your usage
91+
dashboard if this gets shared widely, since there's no rate limiting
92+
built into this prototype yet.

‎public/index.html‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ <h1>Before you sign,<br>know what you're signing.</h1>
139139
<p>Check a real wallet's approvals, or try a sample scenario — either way, get a plain-language explanation of what each permission actually does.</p>
140140
</header>
141141

142-
<p class="moved"><strong>For agents and developers:</strong> the paid wallet check now lives in <a href="https://presign-guard.onrender.com">presign-guard</a>: <code>GET /v1/approvals?chain=base&amp;address=…</code>, $0.02 on Base or Solana, with a verdict per approval and the ones to revoke. The paid routes here keep working for now.</p>
142+
<p class="moved"><strong>For agents and developers:</strong> the paid wallet check now lives in <a href="https://presign-guard.fizzl.eu">presign-guard</a>: <code>GET /v1/approvals?chain=base&amp;address=…</code>, $0.02 on Base or Solana, with a verdict per approval and the ones to revoke. The paid routes here keep working for now.</p>
143143

144144
<div class="tabs">
145145
<button class="tab active" data-tab="wallet">Check a wallet</button>
@@ -223,7 +223,7 @@ <h2 id="videoTitle">See it in a minute</h2>
223223
<footer>
224224
<strong>Self-hosted instance.</strong> Wallet checks call the GoPlus Security API for live approval data, then Claude for the plain-language translation. Nothing is stored — each check is stateless.
225225
<br><br>
226-
Built and debugged with <a href="https://x402-doctor.onrender.com" style="color: inherit;">x402 Doctor</a>, a free diagnostic tool for x402 payment flows.
226+
Built and debugged with <a href="https://x402-doctor.fizzl.eu" style="color: inherit;">x402 Doctor</a>, a free diagnostic tool for x402 payment flows.
227227
</footer>
228228
<p class="by-fizzl"><a href="https://github.com/Fizzl13" title="Fizzl: pay-per-call tools for AI agents">by <svg viewBox="-6 -14 236 126" role="img" aria-label="fizzl"><g fill="none" stroke="currentColor" stroke-width="16" stroke-linecap="round" stroke-linejoin="round"><path d="M44 12 A20 20 0 0 0 20 32 V100"/><path d="M6 48 H38"/><path d="M64 56 V100"/><path d="M88 52 H124 L88 100 H124"/><path d="M144 52 H180 L144 100 H180"/><path d="M200 8 V84 A16 16 0 0 0 216 100"/></g><g class="b"><circle cx="64" cy="26" r="9"/><circle cx="78" cy="10" r="5"/><circle cx="90" cy="-2" r="3"/></g></svg></a></p>
229229
</div>

‎public/openapi.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"contact": { "email": "frits.zwager@gmail.com" },
88
"x-guidance": "Use POST /api/check-wallet when you have an EVM wallet address and want to know whether its current token/NFT approvals are safe. Example: {\"address\":\"0x6B0F4651eD42893ab58139938175E4a69f175F25\",\"chain\":\"base\",\"kind\":\"token\"} — chain defaults to \"ethereum\" and kind defaults to \"token\" if omitted, so a call can be as small as {\"address\":\"0x...\"}. Use POST /api/explain instead when you already have a specific approval/permission JSON payload (from a scanner, a dapp prompt, etc.) and just want it translated to plain language, without an on-chain lookup. Both return {verdict: SAFE|CAUTION|RISK, explanation: string} so downstream agents can branch on verdict without parsing prose."
99
},
10-
"servers": [{ "url": "https://smartcontractexplainer.onrender.com" }],
10+
"servers": [{ "url": "https://plaintext.fizzl.eu" }],
1111
"paths": {
1212
"/api/check-wallet": {
1313
"post": {

‎server.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ app.set('trust proxy', trustProxyHops());
2525
app.use(express.json());
2626

2727
// Usage log: every call with what was filled in, for the dashboard at
28-
// x402-doctor.onrender.com/admin/usage. Does nothing without USAGE_LOG_TOKEN.
28+
// x402-doctor.fizzl.eu/admin/usage. Does nothing without USAGE_LOG_TOKEN.
2929
app.use(createUsageLog({ service: 'plaintext' }).middleware(describePlainTextCall));
3030

3131
// x402 v2 identifies networks by CAIP-2 chain id rather than a network name.
@@ -517,7 +517,7 @@ app.all('/mcp', async (req, res) => {
517517
// out-of-band so clients/indexers can discover it without prior config.
518518
// x402scan and similar indexers read {version: 1, resources: [url, ...]};
519519
// methods, prices and schemas come from /openapi.json (x-payment-info).
520-
const PUBLIC_ORIGIN = 'https://smartcontractexplainer.onrender.com';
520+
const PUBLIC_ORIGIN = 'https://plaintext.fizzl.eu';
521521
const X402_WELL_KNOWN_MANIFEST = {
522522
version: 1,
523523
resources: [`${PUBLIC_ORIGIN}/api/check-wallet`, `${PUBLIC_ORIGIN}/api/explain`],

‎server.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
"remotes": [
88
{
99
"type": "streamable-http",
10-
"url": "https://smartcontractexplainer.onrender.com/mcp"
10+
"url": "https://plaintext.fizzl.eu/mcp"
1111
}
1212
],
1313
"repository": {
1414
"url": "https://github.com/Fizzl13/SmartContractExplainer",
1515
"source": "github"
1616
},
17-
"websiteUrl": "https://smartcontractexplainer.onrender.com"
17+
"websiteUrl": "https://plaintext.fizzl.eu"
1818
}

‎usage.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// What each PlainText call was about, for the usage log (usage-log.js):
2-
// the dashboard at x402-doctor.onrender.com/admin/usage. Null = not logged.
2+
// the dashboard at x402-doctor.fizzl.eu/admin/usage. Null = not logged.
33
const { mcpToolCall } = require('./usage-log');
44

55
// Calls from this site's own page vs. agents and scripts.

0 commit comments

Comments
 (0)