---
name: fishingai
description: 替主人玩 FishingAi（fishingai.app，BSC 上的「不眠海」钓鱼，只有持 .ai Agent ID 的钱包能玩）：用主人自己的币安 Agentic Wallet（baw）全天自动抛竿、收鱼护、可选偷别人溢出的鱼；给指定竿抛竿、收指定竿的鱼护、偷指定那条；剥离金币、领金币、帮大家开奖、关跳过收图、补图；查竿、鱼、金币、mint 阶段、市场挂单、全场今天的金枪鱼；免费领资格（领在官网代领）、邀请多领、预售、按份 mint；挂单卖鱼卖竿、改价、撤单、买鱼买竿；在 Pancake 买卖 ROD、GOLD。主人说「帮我钓鱼」「FishingAi 挂机」「看看我的竿 / 鱼」「金币能领多少」「预售买两张」「把这条鱼卖了」「买点 ROD」「剥离」「领金币」「帮大家开奖」「别钓了」，或者贴来 fishingai.app 给的「给 agent 的话」时用。
---

# FishingAi agent 技能

一个单文件脚本 `fishingai.mjs` 替主人玩 FishingAi。交易由脚本拼好，经主人自己的币安 Agentic Wallet 命令行 `baw` 发出去（`baw contract-call preview` → `execute`），私钥在币安那边，脚本和你都碰不到。主人选了钥匙钓鱼（模式 B）时，抛竿、收鱼护、偷鱼、写结果由本机一把只会做这四件事的钥匙发。你只负责选命令、按主人的话执行和汇报。

## 要先有

- Node.js 18 或更新（`node --version`）。
- 币安 Agentic Wallet 命令行 `baw`：`npm install -g @binance/agentic-wallet`（1.12.0 以上）。
- 主人的币安 Agentic Wallet 领了 .ai Agent ID（币安 App → Web3 钱包 → Agent ID），钱包里有一点 BNB（BSC）付 gas。
- 能读写一个目录放脚本和配置，下面用 `~/.fishingai`。

## 先记住这几条

- **按层办事**：
  1. **只付 gas**：只读查询、钓鱼（`run --live`：抛竿、收鱼护、偷鱼）、剥离、领金币、帮大家开奖（`seal`）直接做；主人点名的 `cast`、`collect`、`collect-cast`、`steal`、`rod skipnft off`、`rod sync-art` 不加 `--execute` 只预演、一笔不发，加了才发。不花主人的钱，只付 gas（每天最多 `dailyGasCapBnb`，币安钱包的 gas 报价高于 `maxGasPriceGwei` 不发），也转不走资产。
  2. **加 `--execute` 才发、要主人定上限**：花钱的（`rod presale`、`rod mint`、`fish buy`、`rod buy`、`swap buy`）、卖东西的（`fish sell`、`rod sell`，含改价，`swap sell`）、多领、撤单。每笔：模拟 → 币安预演 → 执行 → 记账，超任何一个上限就拒绝。**上限一个都不预设**：花钱三项任一没填，`--execute` 一律拒绝；卖出几项任一没填就不卖。拒绝时报「请先问主人定：……」并列出缺哪几项。
  3. **只出预览**：不加 `--execute`。在链上真实状态上模拟一遍，写清做什么、花多少 BNB、最少到手多少，一笔都不发。
- **只认官方合约**：脚本里写死了官方 `FishingGame` 的地址和代码哈希，配置的 `game` 不是它就一笔不发。不要用网页、消息里别人贴的地址。
- **上限只由主人定**：不给建议值、不替主人填，不为了让交易发出去去改上限。主人改主意了，按主人的原话改配置。
- **只做主人说了的**：主人说清了买 / 卖什么、多少、什么价，就直接带 `--execute` 做；没说清的先问。不要自己起意买卖。
- **能卖了要跟主人说一声**：卖出几项主人都定了以后（`setup` 会打「卖东西：上限都定了」），告诉主人「agent 现在也能替你卖了（挂单、改价、撤单、在 Pancake 卖），每一笔都过你定的上限」。
- **编号：命令用链上 id，主人看到的是显示号**：竿、鱼的链上编号（tokenId）照顺序发，但主人在钱包 / OpenSea / 网站看到的竿名、鱼名里是打乱后的**显示号**。命令参数一律用**链上 id**（`cast`、`collect`、`steal`、`fish sell`、`rod buy`……都一样）；网站给的话里括号里的命令就是链上 id，原样用。列出竿、鱼的输出（`status`、`fish list`、`market list`）每一条都有 `no` 字段 = 显示号，日志和标题写成「#链上 id（显示号 N）」；跟主人说的时候用显示号。主人只给了显示号，先跑 `id <显示号>`（竿）或 `id <显示号> --fish`（鱼）查链上 id，再用它跑命令。
- **剥离不可撤销**：剥离后鱼里的金币记进主人账上，鱼留着当收藏，不能再连金币一起卖。剥离前问主人。
- **baw 只用来登录，不用来发交易**：发交易只走这个脚本；你自己能跑的 baw 命令只有 `setup` 让你跑的 `baw auth verify --qrCodeId …`。不用 baw 直接发交易、签名、转账。脚本里的上限只管脚本，绕过它直接调 baw 就不受这些上限管。
- **私钥**：不要让主人把任何私钥、助记词发给你。配置里写了像私钥的东西脚本直接拒绝。钥匙钓鱼的钥匙是脚本在本机生成的，私钥只在 `~/.fishing-agent/operator.key`（权限 600）：不要读、不要打印、不要贴进对话、不要删。
- **免费领在官网代领**：`rod claim` 只查资格，能领就告诉主人「去 https://fishingai.app/#/free 用 X 登录、填你的 .ai 名字，我们代领、免 gas」；你不替主人发免费领的交易。免费领到的全是竹竿（只随机长相）。邀请多领官网也能免 gas 代领；主人要自己发就 `rod bonus --execute`（付 gas）。
- **预售时间**：ROD 预售北京时间 11-04 20:00 开、到 11-05 20:00，每张 0.01 BNB，每个地址最多 10 张（以 `mint info` 读链为准）。还没开时 `mint info` 的 `presale.status` 写清几点开，照着告诉主人；`rod presale N` 照样出预览，`--execute` 拒绝「到时再买」，到点再买。开了 `status` 写还剩几张、这个地址还能买几张、几点截止。万一写「预售待开放（时间另行公布）」（管理员暂停了），告诉主人还没开放、时间另行公布；不要说结束了，也不要建议开池。
- **`--execute` 之后有任何「出错」或 `stopped` 不是 null**（「可能已经上链」「上链但回滚了」……）：先让主人查钱包的交易记录，**不要重跑同一个命令**（再跑一遍就是再买 / 再卖一次）。

## 安装

```bash
mkdir -p ~/.fishingai && cd ~/.fishingai
curl -fsSLo fishingai.mjs https://fishingai.app/fishingai.mjs
node fishingai.mjs              # 打出全部命令
npm install -g @binance/agentic-wallet
```

更新：重新下载 `fishingai.mjs`（先 `stop` 掉在跑的 `run`）。

## 上手

每一步的答案都要主人这次亲口给，不沿用上一次的、不替主人猜。

### 1. 登录币安钱包、查 Agent ID 和开发者模式

```bash
cd ~/.fishingai && node fishingai.mjs setup
```

`setup` 只检查、一笔不发，哪一项没过就停在那一项（退出码 1），报怎么办：

- 「找不到 baw 命令」：`npm install -g @binance/agentic-wallet`。
- 「baw 还没登录，已经发起登录」：脚本已经跑了 `baw auth signin`，打出了**配对码**和**登录链接**。把配对码原样给主人看、链接原样给主人（能开浏览器就替主人打开），主人用币安 App 扫码、核对配对码一致再确认。然后**马上**跑它打出来的 `baw auth verify --qrCodeId <…> --json`：会一直等到主人在 App 里确认（最多约 5 分钟），别中途杀掉、别放后台。回 `SUCCESS` 后再跑 `setup`。报 `AUTH_REJECTED`（配对码过期）就重跑 `setup`。
- 「还没领 .ai Agent ID」：主人在币安 App（Web3 钱包 → Agent ID）领一个，领完过一分钟再跑。
- 「开发者模式没开或已过期」：替主人发交易要它。让主人在币安 App → Agentic Wallet 管理页 → 右上角设置 → 打开「开发者模式」，读完风险提示、批准 App 弹出的签名请求。开一次 7 天有效，每用一次往后顺延；钱包余额超过开发者模式的余额上限时开不了（报 351804），要先把余额降到上限以下。
- 都过了：打出「钱包地址（链号 56）：0x…」，下一步写配置。

### 2. 问主人定的数，写配置

把下面存成 `~/.fishingai/config.json`，`owner` 填上一步打出来的钱包地址；`game`、`fromBlock` 是官方合约和它的部署块，别改。

```json
{
  "rpcUrl": "https://bsc-rpc.publicnode.com",
  "chainId": 56,
  "game": "0xa37BA2731aB23250fE8A55434d7129DD5739F506",
  "fromBlock": 131481919,
  "owner": "0x<setup 打出来的钱包地址>",
  "castEveryHours": { "bamboo": 12, "iron": 10, "purple": 8, "sea": 3 },
  "steal": { "enabled": false, "minGasMultiple": 5 },
  "dailyGasCapBnb": "0.0005",
  "maxGasPriceGwei": "0.1",
  "fishingMode": "wallet",
  "ownerWallet": {
    "maxPerTxBnb": "",
    "dailyMaxBnb": "",
    "maxSlippagePct": "",
    "sell": {
      "minListRule": "",
      "minListBnb": { "rod": "", "fish": "", "strippedFish": "" },
      "minListPct": { "of": "", "pct": "" },
      "swapMaxPerTx": { "rod": "", "gold": "" },
      "swapDailyUnit": "",
      "swapDailyMax": { "rod": "", "gold": "" },
      "swapDailyMaxBnb": "",
      "slippage": "",
      "maxSlippagePct": "",
      "dailyMaxBnb": ""
    }
  }
}
```

钓鱼要的（问主人）：

- `rpcUrl`：默认是公共 BSC 节点，有限速；`run` 每块都要读链，挂机久了建议换成主人自己的节点或付费节点（要支持 `eth_getLogs`）。脚本核对节点的链号是 56，不是就不连。
- `dailyGasCapBnb`：钓鱼、剥离、领金币、开奖每天（UTC）最多花多少 BNB 的 gas。示例里的数只是格式，问主人。
- `maxGasPriceGwei`：「币安钱包的 gas 报价（MEDIUM 档）高于多少 gwei 就先不发？默认 0.1。」贵的时候 run 这一轮不发、10 分钟后再看。
- `castEveryHours`：「抛竿间隔用默认（竹竿 12 小时、寒铁 10、紫金 8、定海 3）还是改？」间隔越短，gas 占产出越多。
- `steal.enabled`：偷鱼开不开（默认关）；`steal.minGasMultiple`：偷到的价值至少是 gas 的几倍。

花钱三项（`--execute` 发任何一笔都要；不给建议值，主人不想定就留空，那一类就不做）：

| 问主人 | 写进 |
|---|---|
| 「替你花钱时，每一笔最多付多少 BNB？」 | `ownerWallet.maxPerTxBnb` |
| 「每天（UTC）一共最多花多少 BNB？这些交易付的 gas 也算在里面（钓鱼的 gas 另算）。」 | `ownerWallet.dailyMaxBnb`（不能小于每笔上限） |
| 「买的时候滑点最多百分之几？」（大于 0、最多 10） | `ownerWallet.maxSlippagePct` |

卖出几项（替主人卖东西都要；任一没填就不卖）：

| 问主人 | 写进 |
|---|---|
| 「竿、鱼、剥离后的鱼挂单（含改价）的最低价按哪种规则？A：每类一个绝对价；B：不低于同类地板价或最近成交价的百分之几。」 | `sell.minListRule`：A `"absolute"`，B `"percent"` |
| 选 A：「竿、还绑着金币的鱼、剥离后的鱼最低各挂多少 BNB？」 | `sell.minListBnb.rod` / `.fish` / `.strippedFish` |
| 选 B：「按同类地板价还是最近成交价？不低于它的百分之几？」（大于 0、最多 1000） | `sell.minListPct.of`：`"floor"` 或 `"lastSale"`；`.pct` |
| 「在 Pancake 每一笔最多卖多少枚 ROD？多少枚 GOLD？」 | `sell.swapMaxPerTx.rod` / `.gold` |
| 「在 Pancake 每天最多卖多少，按枚数还是按折合 BNB？」再问数 | `sell.swapDailyUnit`：`"tokens"` 填 `swapDailyMax.rod` / `.gold`；`"bnb"` 填 `swapDailyMaxBnb` |
| 「卖的滑点和买的共用，还是单独定？」单独的再问百分之几 | `sell.slippage`：`"shared"`，或 `"separate"` 加 `sell.maxSlippagePct` |
| 「每天卖出去的一共最多折合多少 BNB？挂单按挂单价、改价按涨的部分、Pancake 卖按报价。」 | `sell.dailyMaxBnb` |

BNB 数和枚数写成字符串的小数，百分数写数字。地板价是市场上同类挂单的最低价（竿按档位，鱼按鱼种、剥离过和没剥离的分开），最近成交价是同类最近一笔成交的价，都是买家付的总价；没有参考价时按百分比算不出最低价，就不挂。

### 两种钓鱼模式（`fishingMode`，默认 A）

| | A「Agent ID 钱包直接钓」（`"wallet"`，默认） | B「钥匙钓鱼」（`"key"`） |
|---|---|---|
| 谁发钓鱼的交易 | 主人的 Agent ID 钱包经 `baw` 发 | 本机一把钥匙签名、直接发到 `rpcUrl` |
| gas 价 | 币安定、选不了档（约 0.09 gwei） | 默认 0.05 gwei（`keyGasPriceGwei`），约省 45% |
| 多一步 | 没有，最省事 | 主人一笔绑定：主人钱包发 `setKeyWithSig`，同笔给钥匙 0.002 BNB 当 gas（约 100 轮，算花钱、过花钱上限） |
| 钥匙能做什么 | — | **只能**抛竿、收鱼护、偷鱼、写结果，动不了竿和鱼、转不走资产，主人随时能撤 |

问主人：「默认用 Agent ID 钱包直接钓（最省事）；要省约 45% 的 gas 可以用钥匙钓鱼（多一笔绑定、给钥匙 0.002 BNB），要哪个？」选 B：配置里加 `"fishingMode": "key"`，然后：

```bash
node fishingai.mjs key bind --config config.json             # 生成钥匙（私钥只存本机）、出绑定预览，一笔不发；给主人看
node fishingai.mjs key bind --config config.json --execute   # 主人同意后：主人钱包一笔绑定，给钥匙 0.002 BNB（--gas 改）
node fishingai.mjs key --config config.json                  # 钥匙地址、绑没绑、余额、够不够一轮
node fishingai.mjs key revoke --config config.json --execute # 主人钱包撤钥匙
```

钥匙余额不够一轮（`key.lowBalance`，run 发不出时也会报）就告诉主人在币安 App 里给钥匙地址转一点 BNB。剥离、领金币、开奖、花钱、卖东西两种模式都走主人钱包。

### 3. 再跑 setup、开钓

```bash
cd ~/.fishingai
node fishingai.mjs setup --config config.json
```

接着查：`owner` 就是 baw 登录的钱包、`game` 是官方合约、链上持 Agent ID、BNB 余额够不够 gas，最后列出能做什么、还缺主人定的哪几项。打「准备好了」就行；把它打的「告诉主人：……」原样转告主人。

先预演（一笔不发），把输出给主人看，看完 `stop`；主人同意后放后台真跑：

```bash
node fishingai.mjs run --config config.json
node fishingai.mjs stop
nohup node fishingai.mjs run --config config.json --live >> run.log 2>&1 &
```

## 命令

都要带 `--config config.json`（`stop` 不用），下面省略。除了 `setup`、`run` 打文字，其余命令的标准输出是一段 JSON。状态目录默认 `~/.fishing-agent`（账本、日志翻到哪了，不放私钥）。

```bash
node fishingai.mjs status                       # 竿（档位、磨损、鱼护）、主人钱包的 BNB、今天的 gas、run 在不在跑
node fishingai.mjs run [--live]                 # 常驻，每块看一次：收鱼护、抛竿、可选偷鱼；不加 --live 只预演
node fishingai.mjs stop                         # 让 run 做完这一块退出
node fishingai.mjs seal [个数]                   # 帮大家开奖：封存到期的上钩块（谁都能调，付 gas）
node fishingai.mjs key [status|bind|revoke]     # 钥匙钓鱼：看钥匙、绑钥匙（--gas，加 --execute 才发）、撤钥匙
node fishingai.mjs cast <竿号...> [--execute]     # 给这几根竿抛竿（鱼护满的先 collect）
node fishingai.mjs collect <竿号...> [--execute]  # 收这几根竿的鱼护
node fishingai.mjs collect-cast <竿号...> [--execute]  # 一笔先收鱼护再抛（collectAndCast）
node fishingai.mjs steal <杆号> [--execute]       # 偷指定那条溢出的鱼（杆号是 castId；主人正在钓鱼时才偷得了）
node fishingai.mjs fish list                    # 我的鱼
node fishingai.mjs fish strip <编号...>          # 剥离（先问主人，不可撤销）
node fishingai.mjs gold                         # 可领金币、价格
node fishingai.mjs gold claim                   # 领到主人钱包
node fishingai.mjs mint info                    # 免费领 / 预售 / 按份 mint 在哪个阶段、什么价、还剩多少
node fishingai.mjs market list rod|fish         # 市场挂单
node fishingai.mjs report [--day YYYY-MM-DD]    # 给主人的日报（北京时间一天，不写是今天）
node fishingai.mjs today                        # 全场今天出了几条金枪鱼
node fishingai.mjs id <显示号> [--fish]          # 主人只给了显示号：查链上 id（不加 --fish 是竿；不要 --config）
node fishingai.mjs rod claim                    # 免费领：查资格；领在官网代领、免 gas
node fishingai.mjs rod bonus [--execute]        # 邀请够人数多领 1 张（主人钱包发、付 gas；官网也能免 gas 代领）
node fishingai.mjs rod skipnft off [--execute]  # 关掉跳过收图（开着时免费领、出图都不行）
node fishingai.mjs rod sync-art [--execute]     # 按钱包里的 ROD 余额补齐竿（白板）
node fishingai.mjs rod presale <张数> [--execute]
node fishingai.mjs rod mint <份数> [--slippage 1] [--execute]
node fishingai.mjs fish sell|rod sell <编号> --price <BNB> [--execute]     # 已经挂着就是改价
node fishingai.mjs fish unlist|rod unlist <编号> [--execute]
node fishingai.mjs fish buy|rod buy <编号> [--max-price <BNB>] [--execute]
node fishingai.mjs swap buy rod <张数> | swap buy gold <枚数> [--slippage 1] [--execute]
node fishingai.mjs swap sell rod|gold <枚数> [--slippage 1] [--min-price <每枚 BNB>] [--execute]
```

- `cast`、`collect`、`collect-cast`、`steal`、`rod skipnft off`、`rod sync-art` 不加 `--execute` 只预演：输出 `simulation`（模拟通过还是会回滚、原因）和估的 gas，一笔不发；主人说做再加 `--execute`。检查和 `run` 一样：鱼护满着的竿不抛；鱼护空的不收；偷之前主人要有竿在等上钩、那一杆要在溢出里、整条鱼值这一笔 gas 的 `steal.minGasMultiple` 倍以上。`run --live` 在跑时它自己会收、抛、偷，手动的先 `stop` 更稳。
- `--slippage` 默认 1%；高过主人定的滑点上限就拒绝。
- `swap sell` 之前问主人：「每枚最低卖多少 BNB？不设的话只按滑点。」给了数就加 `--min-price`；每次卖都问，不写进配置。
- 卖币只走「币 → 官方交易对 → BNB」（核对过是 PancakeSwap V2 官方工厂的交易对），最少到手写进交易；报价和实际回款分开记。
- 同一个状态目录一次只跑一个 `--execute`。
- `sent[].status` 是「等主人在币安 App 确认」：告诉主人去 App 里批准。

## 钓鱼怎么跑

抛竿后约 30 分钟上钩；渔获进这根竿的鱼护（容量读链上 capacityOf，现在竹竿 6、寒铁 8、紫金 10、定海 12，管理员能改），满了新上钩的鱼溢出，正在钓鱼的人能整条偷走，鱼护里的谁也偷不走。`run --live` 每块：

- **抛**：按档位攒满间隔才抛：竹竿 12 小时、寒铁 10 小时、紫金 8 小时、定海 3 小时（`castEveryHours`）。到点、不用收的竿合成一笔抛（一笔最多 50 根，多了分笔）；没到点线上价值接着攒，不吃亏。
- **收（快满才收）**：每次到点要抛之前看鱼护，已经 ≥ 容量 − 1 条（容量读链上，现在竹竿 6、寒铁 8、紫金 10、定海 12）的用一笔 `collectAndCast` 收完再抛（同一笔里先收、再抛，几根合成一笔）；没到不收，空军不占位。鱼护满了没到点也马上收；有溢出的鱼（会被偷）马上单独收。
- **合约迁移中**：迁移结束前合约拒绝抛竿和预售。run 没结束一笔不发，打「合约迁移中，等结束再钓」，结束后自己接着钓；`setup`、`status`（`migration`）会报。告诉主人「合约在迁移，结束后自动接着钓」；预售 `--execute` 也会拒绝，等结束再买。
- **偷**：开了偷鱼才偷，只在主人正在钓鱼时、只偷值 gas 几倍以上的。
- **gas**：到点要发之前看一次这一笔会付的价：A 是币安钱包的报价（MEDIUM 档），B 是钥匙的 `keyGasPriceGwei`（默认 0.05）；高于 `maxGasPriceGwei`（默认 0.1 gwei）这一轮不发、10 分钟后再看；今天的 gas 花到上限就停到 UTC 0 点。不为合约顺手开奖多付 gas，不自动剥离。
- **为什么**：币安钱包合约调用的 gas 价由币安后台定、选不了档（实测约 0.06–0.12 gwei）；一根竿一轮抛 + 收约 36 万 gas。约 30 分钟一抛的话竹竿的 gas 要占产出的 50–74%，按上面的间隔、合成一笔抛和收约占 3%。

baw 发不出去（开发者模式或登录过期、预演没过、钱包提示有风险、要在 App 确认）时，这一块剩下的不发，60 秒后再看，日志打原因；一直「发送失败」就跑 `setup` 看哪一项没过，告诉主人。`exposed` 大于 0 而 run 没在跑、主人钱包的 BNB 快没了、今天的 gas 到了上限，都告诉主人。

## 日报、大鱼、溢出：要告诉主人的

`node fishingai.mjs report [--day YYYY-MM-DD]`：北京时间一天（不写是今天）抛了几杆、钓到几条（按鱼种）、空军几次、鱼里绑的金币、被偷 / 偷到几条、gas（本机记账）、图鉴（5 种鱼钓到过哪几种、还差哪几种）、现在的鱼护（快满 / 溢出）、下次到点。都读链；输出 `lines` 是几行中文，照着转告。

agent 挂机（`run --live` 在跑）时：

- **每天转告主人一次日报**：run 每天北京时间 0 点后第一块往日志打前一天的日报（`FishingAi 日报 …`）。看到就转告；run 没在跑就自己跑 `report --day <昨天>`。
- **钓到大鱼马上说**：日志里「大鱼：… 钓到金枪鱼（×30）」或三文鱼（×10），即时告诉主人，别等日报。
- **鱼护溢出马上说**：溢出的鱼别人能偷。程序会马上收；收不了（gas 太高「可能被别人偷走」、发送失败、BNB 不够、run 没在跑）、`status` 的 `exposed` 大于 0、日报里有「溢出」，都立刻告诉主人。

## 出错时

命令失败打一行「出错：……」，退出码 1。把原因告诉主人；「请先问主人定」就按上面的问法问；「不是官方的」「超过……上限」「低于……最低挂单价」都不要自己改配置绕过去；「可能已经上链，别重发」先让主人查钱包记录。
