Files
winning-wallet-finder/live/deploy_bot.sh
T
jaxperro b7b1487175 copybot: migrate Railway (US region, geo-blocked) -> Fly.io arn Stockholm
Polymarket geoblocks order placement by IP and Railway ran the worker in a
US region — fine for the paper bot (reads only) but a dead end for going
live. Fly arn (Sweden, unrestricted, ~25ms from the CLOB's eu-west-2
primaries) passes: geocheck VERDICT TRADABLE, pm geoblock blocked:false.

- host/geocheck.py: 3-probe geo-gate verdict (ipinfo, pm /api/geoblock,
  unauth CLOB order POST); --idle keeps a test machine up
- host/start.sh: geocheck at boot (GEOCHECK_ONLY=1 = probe-and-idle test
  mode, no second book-writer); warns loudly if a region is blocked
- fly.toml/fly.Dockerfile: wwf-copybot, single machine, http_service :8080
  for the Alchemy push webhook (now wh_blf4qjjvfdbqs9mc -> fly.dev domain)
- deploy_bot.sh: railway redeploy -> flyctl apps restart + banner wait

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 16:02:06 -04:00

84 lines
3.6 KiB
Bash
Executable File

#!/bin/bash
# One-command deploy of the paper copybot's follow set.
#
# 1. edit live/copybot.paper.json — add/remove/reclass entries in "wallets":
# {"wallet": "0x…", "name": "…", "class": "volume"|"whale", "floor": 123}
# ("floor" optional: volume wallets without one get an auto p80 at boot;
# whales ignore floors — they're followed on every trade)
# 2. ./live/deploy_bot.sh
#
# Validates the config (a malformed JSON = crash-looping container), previews
# the follow set, commits+pushes just the config, restarts the Fly.io worker
# (wwf-copybot, Stockholm — start.sh clones main at boot, so a restart IS the
# deploy for config changes; `flyctl deploy` only needed when host/ or
# fly.toml change), and waits for the fresh boot banner.
set -e
cd "$(dirname "$0")"
python3 - <<'PY'
import json, sys
c = json.load(open("copybot.paper.json"))
ws = c.get("wallets") or []
if not ws:
sys.exit("copybot.paper.json has no wallets[] — nothing to follow")
seen = set()
for w in ws:
a = w.get("wallet", "")
assert a.startswith("0x") and len(a) == 42, f"bad address: {w}"
assert a.lower() not in seen, f"duplicate wallet: {a}"
seen.add(a.lower())
assert w.get("class", "volume") in ("volume", "whale"), f"bad class: {w}"
if w.get("floor") is not None:
assert float(w["floor"]) >= 0, f"bad floor: {w}"
pct = (c.get("follow") or {}).get("class_pct") or {}
print(f"config OK · {len(ws)} wallets:")
for w in ws:
cls = w.get("class", "volume")
fl = ("follow-all" if cls == "whale"
else f"floor ${w['floor']:,.0f}" if w.get("floor") is not None
else "floor auto (p80 at boot)")
print(f" {w.get('name', w['wallet'][:10]):<18} {cls:<7} "
f"{pct.get(cls, 0.04)*100:.0f}%/bet · {fl}")
PY
git add copybot.paper.json
if git diff --cached --quiet; then
echo "no config changes — redeploying anyway (picks up current main)"
else
git commit -m "copybot: follow-set update (deploy_bot.sh)"
git pull --rebase --autostash -q
git push -q
echo "pushed."
fi
# push mode: keep the Alchemy webhook's address list matched to the follow set
python3 sync_webhook.py || echo "⚠ webhook sync failed — update the address list manually"
flyctl apps restart wwf-copybot
echo "restart triggered — waiting for the new container…"
python3 - <<'PY'
# wait for a boot banner logged AFTER the restart (fly log lines are ANSI-
# colored and ISO-stamped; strip + parse here rather than in bash)
import re, subprocess, sys, time
t0 = time.time() - 30 # restart just happened
for _ in range(15):
time.sleep(20)
raw = subprocess.run(["flyctl", "logs", "--app", "wwf-copybot", "--no-tail"],
capture_output=True, text=True).stdout
lines = [re.sub(r"\x1b\[[0-9;]*m", "", l) for l in raw.splitlines()]
for l in reversed(lines):
if "watching" in l and "wallets" in l:
m = re.match(r"(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})Z", l)
ts = time.mktime(time.strptime(m.group(1), "%Y-%m-%dT%H:%M:%S")) - time.timezone if m else 0
if ts >= t0:
print("\n".join(x for x in lines[-40:]
if re.search(r"watching|floor\[|push mode|VERDICT", x)))
print("✅ bot rebooted with the new follow set")
print(" (Alchemy address list synced above — if it warned, update"
" manually at dashboard.alchemy.com → Webhooks)")
sys.exit(0)
break
print("⚠ no fresh boot banner within 5min — check: flyctl logs --app wwf-copybot")
sys.exit(1)
PY