copybot: push mode — Alchemy webhook + heartbeat + backstop poll
Setting ALCHEMY_SIGNING_KEY on the worker switches start.sh to webhook mode: instant copies on POST /alchemy (signature-verified), a 60s housekeeping heartbeat (settle, feed, summary), and a full backstop poll every 5 min so a dropped push costs minutes, not a silent miss. Webhook mode now baselines at boot and publishes an initial feed like poll mode. No signing key -> classic 60s poll, unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+29
-2
@@ -914,8 +914,35 @@ def main():
|
||||
signing_key = (os.environ.get("ALCHEMY_SIGNING_KEY")
|
||||
or cfg.get("alchemy_signing_key", ""))
|
||||
port = int(os.environ.get("PORT", 8080))
|
||||
log(f"listening on :{port} · POST /alchemy · "
|
||||
f"signature-verify {'ON' if signing_key else 'OFF'}")
|
||||
bot.baseline()
|
||||
|
||||
# webhook mode is event-driven, but the book must not depend on the next
|
||||
# push arriving: a heartbeat thread settles resolved positions, refreshes
|
||||
# the feed, and logs the summary every 60s — plus a FULL backstop poll of
|
||||
# every wallet each 5th tick, so a dropped/misconfigured push costs at most
|
||||
# ~5 minutes of lag instead of a silent miss.
|
||||
def _heartbeat():
|
||||
cycle = 0
|
||||
while True:
|
||||
time.sleep(60)
|
||||
cycle += 1
|
||||
try:
|
||||
bot.settle_resolved()
|
||||
if cycle % 5 == 0:
|
||||
for w in cfg.get("watchlist", []):
|
||||
bot.on_wallet_activity(w)
|
||||
bot.summary(cycle)
|
||||
bot.write_feed()
|
||||
bot.publish_feed()
|
||||
except Exception as e:
|
||||
log(f"heartbeat error: {e}")
|
||||
threading.Thread(target=_heartbeat, daemon=True).start()
|
||||
|
||||
log(f"push mode · listening on :{port} · POST /alchemy · "
|
||||
f"signature-verify {'ON' if signing_key else 'OFF'} · "
|
||||
f"heartbeat 60s · backstop poll 300s")
|
||||
bot.write_feed()
|
||||
bot.publish_feed()
|
||||
ThreadingHTTPServer(("0.0.0.0", port), make_handler(bot, signing_key)).serve_forever()
|
||||
|
||||
|
||||
|
||||
+19
-8
@@ -11,9 +11,13 @@
|
||||
# GITHUB_TOKEN fine-grained PAT with Contents: read+write on
|
||||
# jaxperro/winning-wallet-finder (the push credential)
|
||||
# Optional env:
|
||||
# DISCORD_WEBHOOK ping on every placement
|
||||
# POLL_SECONDS poll cadence (default 60 — keep well under the bot's
|
||||
# 600s stale window so no trade is skipped)
|
||||
# ALCHEMY_SIGNING_KEY presence switches the bot to PUSH mode: it serves
|
||||
# POST /alchemy for the Alchemy address-activity
|
||||
# webhook (~2-5s detection) with a 60s housekeeping
|
||||
# heartbeat + 5min backstop poll. Requires the service
|
||||
# to have a public domain. Absent -> classic poll mode.
|
||||
# POLL_SECONDS poll cadence in poll mode (default 60 — keep well
|
||||
# under the bot's 600s stale window)
|
||||
#
|
||||
# Railway setup (one time):
|
||||
# 1. New service -> Deploy from GitHub repo -> jaxperro/winning-wallet-finder
|
||||
@@ -34,8 +38,15 @@ cd "$DIR"
|
||||
git config user.name "copybot[bot]"
|
||||
git config user.email "copybot@users.noreply.github.com"
|
||||
|
||||
# paper config is committed (no secrets); state resumes from the last commit
|
||||
exec python3 copybot.py \
|
||||
--config live/copybot.paper.json \
|
||||
--state copybot_state.json \
|
||||
--poll "${POLL_SECONDS:-60}"
|
||||
# paper config is committed (no secrets); state resumes from the last commit.
|
||||
# ALCHEMY_SIGNING_KEY set -> push mode (webhook server); else 60s poll mode.
|
||||
if [ -n "${ALCHEMY_SIGNING_KEY:-}" ]; then
|
||||
exec python3 copybot.py \
|
||||
--config live/copybot.paper.json \
|
||||
--state copybot_state.json
|
||||
else
|
||||
exec python3 copybot.py \
|
||||
--config live/copybot.paper.json \
|
||||
--state copybot_state.json \
|
||||
--poll "${POLL_SECONDS:-60}"
|
||||
fi
|
||||
|
||||
@@ -58,6 +58,8 @@ for i in $(seq 1 15); do
|
||||
railway logs --service copybot 2>/dev/null | grep -E "watching|floor\[" | tail -12
|
||||
echo "$tail5" | tail -1
|
||||
echo "✅ bot rebooted with the new follow set"
|
||||
echo " (push mode? remember: the Alchemy webhook's address list must match"
|
||||
echo " the follow set — update it at dashboard.alchemy.com → Webhooks)"
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user