{
  "service": "rug watch",
  "what": "Register a BSC token you hold and an https callback of your own. Every 15 minutes the token is read again with the same preflight bsc_token_preflight answers with (brainonbnb.com/api/preflight), compared with the read before and with the watch's own history of the last 24 h; when something dangerous changed — the classic rug (sell blocked, liquidity pulled, tax up, owner or proxy changed) or today's (fake volume from a handful of wallets, a pump and the dump after it, a slow rug where the price bleeds while insiders sell) — your callback is POSTed at once. Webhook only — no Telegram, no browser, no mail.",
  "cadence": "every 15 minutes, on this worker's cron",
  "register": {
    "how": "POST https://agent.brainonbnb.com/rug-watch",
    "body": {
      "token": "0x… (the BSC token)",
      "callback": "https://… (your endpoint; https, public, not ours)",
      "wallet": "optional — holder tier",
      "signature": "optional — holder tier",
      "issued": "optional — holder tier"
    },
    "answer": "watch (the id), secret (shown ONCE — keep it: it signs every alert and cancels the watch), tier, expires_at, baseline (the snapshot every later read is compared with), status_url",
    "refused": "a token the preflight cannot read as a pool (still on its four.meme curve, no pool, not a token) is refused with the preflight's own code"
  },
  "tiers": {
    "free": {
      "watches": 1,
      "per": "caller (the connecting address, IPv6 by /64; over MCP the MCP caller's)",
      "all_free_watches": 50
    },
    "holder": {
      "line": "1,000,000 $BOBAI (token 0x245c386dcfed896f5c346107596141e5edcbffff, 18 decimals) in the wallet",
      "watches": 25,
      "honest_note": "\"Unlimited\" means 25 active watches per holder wallet.",
      "proof": {
        "method": "EIP-191 personal_sign by the wallet — a signature, no transaction, nothing spent",
        "message": "BOBAI rug watch\nwallet: <lowercase address>\nissued: <ISO 8601 UTC time, e.g. new Date().toISOString()>",
        "lines": [
          "BOBAI rug watch",
          "wallet: <lowercase address>",
          "issued: <ISO 8601 UTC time>"
        ],
        "joined_by": "one line feed (LF) between lines, none at the end; the address in lower case; issued exactly as sent in the body",
        "example_message": "BOBAI rug watch\nwallet: 0x1234567890abcdef1234567890abcdef12345678\nissued: 2026-10-09T12:00:00.000Z",
        "send": "{\"token\":\"0x…\",\"callback\":\"https://…\",\"wallet\":\"<the address>\",\"signature\":\"0x…\",\"issued\":\"<the same time string>\"}",
        "issued_within": "10 minutes before the request"
      },
      "recheck": "the balance is read on registration and once a day after. Under the line, the wallet's oldest watch keeps running as its free one and the others pause (each callback gets a holder_line warning); they resume when the wallet holds the line again, and a watch still paused at the next daily read (a day under the line) is ended. Paused watches take no place under the caps."
    }
  },
  "limits": {
    "active_watches_in_all": 200,
    "days": 30,
    "renew": "register the same token to the same callback again (same caller, or same wallet) — the watch keeps its id and secret and runs another 30 days"
  },
  "detects": [
    {
      "code": "sell_blocked",
      "level": "critical",
      "when": "the preflight newly stops on not_sellable: a test sell from a fresh address no longer goes through"
    },
    {
      "code": "buy_blocked",
      "level": "critical",
      "when": "newly not_buyable"
    },
    {
      "code": "round_trip_loss",
      "level": "critical",
      "when": "newly round_trip: an immediate buy and sell loses half or more"
    },
    {
      "code": "not_quotable / sell_not_quotable / <any new stop code>",
      "level": "critical",
      "when": "any stop code the previous read did not have — and that was not there one read before it either (a code that vanished for one read and came back is not new)"
    },
    {
      "code": "liquidity_pulled",
      "level": "critical",
      "when": "the pool's liquidity fell by half or more since the previous read — the hard side measured against the price: in a constant-product pool the hard side moves with the square root of the price, so a sell-off alone is not a pull — or the pool that held money is gone (no pool, or nothing quotes it for two reads in a row). Compared only when both reads measured the same pool."
    },
    {
      "code": "liquidity_falling",
      "level": "warning",
      "when": "the pool's liquidity fell by a quarter or more since the previous read, against the price as above; also a hard side down a quarter or more when the price could not be read in both reads"
    },
    {
      "code": "lp_withdrawn",
      "level": "critical",
      "when": "the burned share of the LP of the same pool fell by 5 points or more, or the preflight newly reports lp_withdrawn; a fall to about zero in one read (what a failed read of the burn address looks like) is sent only when the next tick reads it too"
    },
    {
      "code": "buy_tax_up / sell_tax_up",
      "level": "critical at 10% or more, else warning",
      "when": "a tax rose by 2 points or more since the previous read"
    },
    {
      "code": "owner_changed",
      "level": "critical",
      "when": "owner() / getOwner() names another address — renounced to an owner again is said to be the worst case"
    },
    {
      "code": "owner_renounced",
      "level": "info",
      "when": "the owner gave the contract up (the zero or dead address) — good news, sent so you know"
    },
    {
      "code": "proxy_upgraded",
      "level": "critical",
      "when": "the EIP-1967 implementation changed"
    },
    {
      "code": "dev_selling / top_holder_selling",
      "level": "warning",
      "when": "newly in the preflight's caution list"
    },
    {
      "code": "tax_can_change",
      "level": "warning",
      "when": "newly in the preflight's caution list"
    },
    {
      "code": "fake_volume",
      "level": "warning",
      "when": "the last hour read looks like wash trading: 20+ swaps by at most max(3, swaps / 10) wallets with the hour's volume at least 5% of the pool's hard side, or the hour's volume 2x the pool's hard side or more from 10 wallets or fewer (a router or aggregator trading for many wallets counts as one address, so this can also be a market that trades through one)"
    },
    {
      "code": "pump",
      "level": "warning",
      "when": "the price at the $250 test size rose 40% or more on its lowest of the last 6 h — you are holding into a pump; buys against wallets are named"
    },
    {
      "code": "dump",
      "level": "critical when insiders sold over the day, else warning",
      "when": "the price fell 30% or more from its high of the last 24 h, and that high came out of a pump (40%+ within 6 h)"
    },
    {
      "code": "slow_rug",
      "level": "critical",
      "when": "over the last 24 h (6 h of history at least): the price down 25% or more with no single step of 25% between two stored reads, sells outnumbering buys in 60% of the reads, and insiders (the deployer, wallets it funded, top holders) selling"
    },
    {
      "code": "liquidity_draining",
      "level": "warning",
      "when": "the pool's liquidity (the hard side against the square root of the price) down 30% or more over the last 24 h with no single step of 25%"
    },
    {
      "code": "insider_selling",
      "level": "warning",
      "when": "the deployer, wallets it funded and top holders sold $1,000 or 5% of the pool's hard side (whichever is lower) in all across the last 24 h of reads; within a day of the last one, sent again only when the total grew by half"
    },
    {
      "code": "unreadable",
      "level": "warning",
      "when": "the token could not be read 4 checks in a row (one failed read is never an alert)"
    },
    {
      "code": "holder_line",
      "level": "warning",
      "when": "a holder wallet fell under 1,000,000 $BOBAI"
    }
  ],
  "repeats": "the same code is sent at most once per 6 hours per watch",
  "confirmed": "no critical event is sent on one read: the token is read a second time within the same check and the event must be there again (or, when no second read could be made, at the check before). A read whose critical event the second read does not confirm sends nothing.",
  "history": "the trend alerts (fake_volume, pump, dump, slow_rug, liquidity_draining, insider_selling) read a series the watch keeps of its own reads: the price per token at the $250 test size (pool fee, tax and slippage included — only relative changes are used), the pool's hard side, the last hour's buys, sells, swaps, wallets and volume, and what insiders sold. Every read is compared with it, but a point is stored only once an hour (and at every alert), 96 at most, 24 h kept — so a move between two stored points is seen at the read it happens in, and a slow trend at hourly resolution.",
  "callback": {
    "method": "POST, application/json, one attempt, 5 s timeout, redirects not followed",
    "body": {
      "watch": "<id>",
      "token": "0x…",
      "symbol": "…",
      "events": [
        {
          "code": "sell_blocked",
          "level": "critical",
          "what": "one sentence with the figures before and after",
          "before": null,
          "after": "not_sellable",
          "at": "<ISO time>"
        }
      ],
      "snapshot": "<the read that fired>",
      "baseline_at": "<ISO time of the registration read>",
      "at": "<ISO time>",
      "docs": "https://agent.brainonbnb.com/rug-watch"
    },
    "signature": {
      "header": "x-bobai-signature: sha256=<hex>",
      "how": "HMAC-SHA256 of the raw request body, keyed with the watch's secret; compare before parsing",
      "node": "crypto.createHmac('sha256', secret).update(rawBody).digest('hex') === header.slice(7)"
    },
    "also": "x-bobai-watch: <id>. The last delivery (time, HTTP status) is in the status."
  },
  "status": "GET https://agent.brainonbnb.com/rug-watch/<id> — the baseline, the current reference snapshot, the events sent, checks, failed reads in a row and the last delivery. Never the secret.",
  "cancel": "DELETE https://agent.brainonbnb.com/rug-watch/<id> with the header x-rug-watch-secret: <secret>",
  "mcp": "bsc_rug_watch on https://brainonbnb.com/mcp registers the same watch",
  "cannot_see": "what happens between two reads: a rug inside 15 minutes is reported after it happened. It reads what the preflight reads — not the team, not the socials. Fake volume from many fresh wallets, each trading a little, looks like a busy market here; and a wallet count is a count of addresses, not of people.",
  "disclaimer": "Measurement, not advice. An event says what changed between two reads; no event is not a promise."
}