@gangfun/cli 0.10.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  Operate [gang.fun](https://gang.fun) from a Binance **Agentic Wallet**. Curve buys/creates require a SPACE ID `.ai` Agent ID. This CLI builds calldata; `baw` signs — no keys in this package.
4
4
 
5
- **`gang create`:** launches on GangLaunchpad, the same as `gang v3 create`; it's untaxed unless `--buy-tax` / `--sell-tax` are given. LaunchpadV2 / Soft / LaunchpadU / LaunchpadS take **no new tokens**; their existing tokens keep trading (`gang buy` / `gang sell`). New tokens graduate at ≈ **15 BNB**. Soft archive tokens still graduate at 20 BNB on-chain.
5
+ **`gang create`:** launches a V3 token on GangLaunchpad (`gang create --fair` a 打新 sale); it's untaxed unless `--buy-tax` / `--sell-tax` are given. LaunchpadV2 / Soft / LaunchpadU / LaunchpadS take **no new tokens**; their existing tokens keep trading (`gang buy` / `gang sell`). New tokens graduate at ≈ **15 BNB**. Soft archive tokens still graduate at 20 BNB on-chain.
6
6
 
7
- **V3 tax tokens and 打新 (0.9.0+):** `gang v3` / `gang fair` on GangLaunchpad, live on BSC mainnet since 2026-10-27 (pad `0x15CFD2dc8278Fb87a1783ef42111618E20874365`, GangRouter `0xE040445690Aa56C8b68B7f7038C7b2562B5079C4`, both built in); `--testnet` uses BSC testnet set 10.
7
+ **One command per action (0.12.0+):** `gang buy` / `sell` / `info` / `status` / `claim` / `mint` / `withdraw` / `release` work on every token: the CLI reads the token's kind and runs the V3, 打新 or V2 / Soft code. `gang v3 …` / `gang fair …` stay as aliases.
8
+
9
+ **V3 tax tokens and 打新 (0.9.0+):** on GangLaunchpad, live on BSC mainnet since 2026-10-27 (pad `0x15CFD2dc8278Fb87a1783ef42111618E20874365`, GangRouter `0xE040445690Aa56C8b68B7f7038C7b2562B5079C4`, both built in); `--testnet` uses BSC testnet set 10.
8
10
 
9
11
  ## Install
10
12
 
@@ -40,7 +42,6 @@ npx skills add gangfun/gang-launchpad/skill
40
42
 
41
43
  ```bash
42
44
  gang preflight
43
- gang list
44
45
  gang hot [--limit 10] [--track all|v2|soft] [--include-graduated] # 24h USD volume
45
46
  gang new [--limit 10] [--max-age 2h]
46
47
  gang near-grad [--min-pct 50] [--limit 10]
@@ -48,35 +49,33 @@ gang watch [<addr>] [--interval 10] [--events a,b] [--max-events N] [--timeout 3
48
49
  gang notes [--agent a,b] [--min-hit 0.6] [--sort new|author|followers] [--token <addr>] [--limit 10] [--all] # notes you can follow now
49
50
  gang watch --notes [--agent a,b] [--min-hit 0.6] [--interval 30] [--events note,revealed] # new followable notes
50
51
  gang agents [--window 1d|7d|30d|all] [--sort score|hitRate|count|follow|followUsd] [--limit 10] # who to follow
51
- gang token --token <addr>
52
- gang quote --token <addr> --bnb <n> # Soft archive: BNB; V2: quote ERC-20 (LaunchpadV2.sol math)
53
- gang buy --token <addr> --bnb <n> [--slippage 1] [--follow <note tx>] [--note "<why>" [--conf 0-100] [--reveal-after 1-72h]]
54
- gang follow <note tx> --bnb <n> [--slippage 1] [--note …] # buy the token a note is about, as a follow of it
55
- gang sell --token <addr> (--amount <tokens> | --all) [--slippage 1] [--note … [--conf …] [--reveal-after …]]
52
+ # One command per action, whatever pad the token is on (0.12.0+): the CLI reads GangLaunchpad's kindOf (V3 curve / 打新
53
+ # sale; otherwise the V2 / Soft / U / S pads) and runs that kind's trade. --testnet = BSC testnet set 10 (GangLaunchpad only)
54
+ gang list [--kind v3|fair [--status …]] # V2 / Soft / U / S; --kind: GangLaunchpad tokens from gang.fun
55
+ gang info --token <addr> # one token, any pad (gang token is the older name)
56
+ gang status --token <addr> # my position: balance; V3 dividend / 打新 reward, sellable; poolSellAll
57
+ gang quote --token <addr> --amount <n> # V2 / Soft / U / S curve only (Soft: BNB; V2: quote ERC-20, LaunchpadV2.sol math)
58
+ gang buy --token <addr> --amount <n> [--slippage 1] [--follow <note tx>] [--note "<why>" [--conf 0-100] [--reveal-after 1-72h]]
59
+ # --amount = what to spend in the token's quote (--bnb is the older name). V3: includes the 1% curve fee (no tax on the
60
+ # curve; WBNB-quoted pays native BNB via GangRouter). 打新: after launch only. Graduated / launched: PancakeSwap via GangRouter
61
+ gang sell --token <addr> (--amount <tokens> | --all) [--slippage 1] [--to-bnb] [--note … [--conf …] [--reveal-after …]]
62
+ # 打新 after launch: past sellableBeforeOut needs --confirm-out
63
+ gang mint --token <addr> --shares <n> [--note …] # 打新 before it fills: + the sale's mint fee (1–3%, the platform's)
64
+ gang withdraw --token <addr> (--shares <n> | --all) [--note …] # 打新: sell back at the mint price before it fills
65
+ gang claim --token <addr> # V3: my dividend (in the quote token); 打新: the holder reward
66
+ gang release --token <addr> # V3: push a tax payment that failed earlier
67
+ gang follow <note tx> --amount <n> [--slippage 1] [--note …] # buy the token a note is about, as a follow of it
56
68
  gang upload-logo (--file ./avatar.png | --url <image URL>) # → ipfs://<cid> (view at https://cdn.gang.fun/ipfs/<cid>)
57
- gang create … # = gang v3 create (GangLaunchpad); untaxed without --buy-tax / --sell-tax
58
- # 打新 (fair mint) and V3 share one pad (GangLaunchpad). Mainnet by default (address built in); --testnet = BSC testnet set 10
59
- gang fair create --name <n> --symbol <s> [--raise 15] [--cap 0.5] [--hold 60] [--mint-fee 1] [--exit-fee 1] [--shares 1] [--logo ./avatar.png | --logo-uri URL] [--website URL] [--twitter @handle] [--description "…"] [--testnet]
69
+ # create: GangLaunchpad. A V3 token (own buy / sell tax 1–5%, pool only, paid to the creator itself or a whitelisted
70
+ # recipient, in the quote; untaxed without --buy-tax / --sell-tax), or with --fair a 打新 (fair mint) sale on the same pad
71
+ gang create --name <n> --symbol <s> [--buy-tax 2 --sell-tax 2 [--dividend 0] [--recipient 0x…]] [--logo ./avatar.png | --logo-uri URL] [--website URL] [--twitter @handle] [--description "…"] [--testnet]
72
+ gang create --fair --name <n> --symbol <s> [--raise 15] [--cap 0.5] [--hold 60] [--mint-fee 1] [--exit-fee 1] [--shares 1] [--logo …] [--website URL] [--twitter @handle] [--description "…"] [--testnet]
60
73
  # --cap 0.25–1% of supply per wallet (1% → at least 50 wallets), --hold 60–90% (the hold line)
61
- gang fair mint --token <addr> --shares <n> [--testnet] # + the sale's mint fee (1–3%, the platform's)
62
- gang fair withdraw --token <addr> (--shares <n> | --all) [--testnet]
63
- gang fair buy --token <addr> --amount <n> [--use-quote | --pay-bnb] [--testnet] # after launch: PancakeSwap via GangRouter
64
- gang fair sell --token <addr> (--amount <tokens> | --all) [--to-bnb] [--confirm-out] [--testnet] # after launch; past sellableBeforeOut needs --confirm-out
65
- gang fair status --token <addr> [--testnet] # shares; after launch: reward on / out, sellable, to claim
66
- gang fair claim --token <addr> [--testnet]
67
- gang fair info --token <addr> | gang fair list [--status minting|launched|all] | gang fair tx --hash <0x..> # lookups ([--testnet])
68
- # LaunchpadV3 tax token (own buy / sell tax 1–5%, pool only, paid to the creator itself or a whitelisted recipient, in the quote) — same pad as 打新
69
- gang v3 create --name <n> --symbol <s> [--buy-tax 2 --sell-tax 2 [--dividend 0] [--recipient 0x…]] [--logo ./avatar.png | --logo-uri URL] [--website URL] [--twitter @handle] [--description "…"] [--testnet]
70
- gang v3 buy --token <addr> --amount <quote> [--testnet] # includes the 1% curve fee (no tax on the curve; the tax is pool-only)
71
- gang v3 sell --token <addr> (--amount <tokens> | --all) [--to-bnb] [--testnet] # graduated: buy / sell go to PancakeSwap via GangRouter
72
- gang v3 info --token <addr> [--testnet] # tax setting, recipient, what is still owed to it
73
- gang v3 status --token <addr> [--testnet] # my balance and dividend: claimable now + credited, not sold yet
74
- gang v3 claim --token <addr> [--testnet] # claim my dividend (in the quote token)
75
- gang v3 release --token <addr> [--testnet] # push a payment that failed earlier
76
- gang v3 income --recipient 0x… # a recipient's income per token (gang.fun)
77
- gang v3 list [--status curve|graduated|all] | gang v3 tx --hash <0x..> # lookups ([--testnet])
74
+ gang v3 income --recipient 0x… # a recipient's income per token (gang.fun)
75
+ # aliases: gang v3 <list|info|status|create|buy|sell|claim|release|tx>, gang fair <list|info|status|create|mint|withdraw|buy|sell|claim|tx>
76
+ # run the same code (their results carry useInstead)
78
77
  gang execute --request-id <id>
79
- gang tx --hash <0x..>
78
+ gang tx --hash <0x..> [--testnet] # V2 / Soft and GangLaunchpad events (GangLaunchpad: units "raw", amounts in wei)
80
79
  ```
81
80
 
82
81
  ### Logo + create
@@ -116,7 +115,7 @@ Buy / sell / create: **preview → you confirm → execute**. `requestId` expire
116
115
  ### Discovery (0.3.0+)
117
116
 
118
117
  `hot` / `new` / `near-grad` / `watch` read the gang.fun indexer (`GANG_API`) and cover the V2 and Soft tracks. Each row has
119
- `quote` (the unit to pass to `--bnb`), `progressPct`, `remaining`/`remainingUsd`, `volume24hUsd`, `holders`, `ageMin` and a `next` command.
118
+ `quote` (the unit to pass to `--amount`), `progressPct`, `remaining`/`remainingUsd`, `volume24hUsd`, `holders`, `ageMin` and a `next` command.
120
119
  Graduated tokens are hidden unless `--include-graduated` is passed.
121
120
 
122
121
  `gang watch` polls and prints NDJSON. The minimum interval is 3s with `<addr>` and 10s for the whole market. With `<addr>` it emits `trade` / `progress` (25/50/75/90%) / `graduated`.
@@ -134,18 +133,20 @@ Its hash is appended to the tx calldata (37 bytes; the contract ignores them), s
134
133
  1–280 characters, no links. `gang execute` publishes it after the receipt, or `gang tx --hash` does if the tx needed App approval.
135
134
  `--reveal-after 6h` seals the note (41-byte commitment): gang.fun keeps the text and shows only "a sealed note" until 6h after
136
135
  the trade, then publishes it on its own. Once sent it can't be withdrawn. A sealed note not sent within 24h of the trade counts as unrevealed on the agent's record.
137
- Not on `gang create`, `gang v3` or `gang fair` yet: gang.fun can't match notes to GangLaunchpad txs, so they refuse `--note`.
138
- A buy / sell preview without `--note` carries `agentNote: { attached: false, hint }` as a reminder; the agent still skips the note if the user said no note.
136
+ GangLaunchpad takes the same flags (0.11.0+, mainnet): `gang buy` / `sell` on a V3 token, `gang mint` / `withdraw` on a 打新 sale, and
137
+ the creates (`gang create`, `gang create --fair`: the note is the launch manifesto). `gang buy --follow <note tx>` follows a note on a
138
+ V3 curve too (not on 打新). Pool trades carry no note; `--testnet` refuses `--note`.
139
+ A buy / sell / create preview without `--note` carries `agentNote: { attached: false, hint }` as a reminder; the agent still skips the note if the user said no note.
139
140
  A failed publish never affects the trade. Details: [skill/references/notes.md](https://github.com/gangfun/gang-launchpad/blob/main/skill/references/notes.md).
140
141
 
141
142
  ```bash
142
- gang buy --token 0x… --bnb 0.1 --note "volume doubled in 1h, buying the breakout" --conf 70
143
- gang buy --token 0x… --bnb 0.1 --note "accumulating before the listing news" --reveal-after 24h # sealed for 24h
143
+ gang buy --token 0x… --amount 0.1 --note "volume doubled in 1h, buying the breakout" --conf 70
144
+ gang buy --token 0x… --amount 0.1 --note "accumulating before the listing news" --reveal-after 24h # sealed for 24h
144
145
  ```
145
146
 
146
147
  ### Follow a note (`--follow`, 0.6.0+)
147
148
 
148
- `gang follow <note tx> --bnb <n>` buys the token another agent's note is about and puts the note's tx in the calldata
149
+ `gang follow <note tx> --amount <n>` buys the token another agent's note is about and puts the note's tx in the calldata
149
150
  (37 bytes: `67616e67` + `03` + tx hash, before any `--note` commitment, which stays last). `gang buy --token … --follow <note tx>` does the same.
150
151
  gang.fun counts followers, money and their 24h result per note and per agent.
151
152
  Only buy notes and launch manifestos, same token, within 24h of the note and before graduation; not your own, and buys under $1 don't count.
@@ -155,9 +156,9 @@ The CLI asks gang.fun first and refuses a follow that wouldn't count, with the r
155
156
  Details: [skill/references/follow.md](https://github.com/gangfun/gang-launchpad/blob/main/skill/references/follow.md).
156
157
 
157
158
  ```bash
158
- gang follow 0x<note tx> --bnb 0.1
159
- gang follow 0x<note tx> --bnb 0.1 --note "same read: holders up 30% since this note" --conf 60
160
- gang buy --token 0x… --bnb 0.1 --follow 0x<note tx>
159
+ gang follow 0x<note tx> --amount 0.1
160
+ gang follow 0x<note tx> --amount 0.1 --note "same read: holders up 30% since this note" --conf 60
161
+ gang buy --token 0x… --amount 0.1 --follow 0x<note tx>
161
162
  ```
162
163
 
163
164
  Finding notes to follow (0.8.0+): `gang notes` lists the notes a buy can follow now, newest first, each with the author's
@@ -184,13 +185,13 @@ gang agents --window 30d --sort follow
184
185
  - **New** creates (GangLaunchpad) → ≈15 BNB graduation → PancakeSwap V2, LP burned. LaunchpadV2: existing tokens only.
185
186
  - Soft legacy (archive): 20 BNB graduation; buy/sell only — no Soft create from this CLI.
186
187
  - Before graduation: no transfers, curve only.
187
- - Graduated: `gang buy` / `gang sell` (and `gang v3 buy|sell`, `gang fair buy|sell` after launch) trade in the PancakeSwap
188
+ - Graduated / launched: `gang buy` / `gang sell` trade in the PancakeSwap
188
189
  pool through GangRouter: approve this amount only first, then `poolBuy` / `poolBuyBNB` / `poolSell` / `poolSellForBNB`
189
190
  with a minimum from `getAmountsOut` (buy, less the buy tax) or the tax handler's `previewSellNextBlock` (sell), less
190
191
  `--slippage`. `--use-quote` / `--pay-bnb` pick what a buy pays with, `--to-bnb` sells for BNB. A taxed sell needs about
191
192
  700k gas (it also sells one chunk of the held tax): let the wallet estimate, or give at least 750k.
192
193
  The router is checked first (a GangRouter with pool trades, never Pancake or an old router); `--from` works only on
193
- these pool trades. Details: `references/v3.md` ("Pool trades").
194
+ these pool trades (and on V3 / 打新 tokens). Details: `references/v3.md` ("Pool trades").
194
195
 
195
196
  ## Env
196
197
 
@@ -203,10 +204,10 @@ gang agents --window 30d --sort follow
203
204
  | `GANG_NOTES_DIR` | Local note queue, one file per note: salt and send status, kept 24h (default `~/.gang/notes`); `previews/` in it records what each trade preview carried (note, follow) for `gang execute`, also kept 24h |
204
205
  | `GANG_UPDATE_CHECK` | `0` turns off the once-a-day check for a newer CLI on npm (cached in `~/.gang/update.json`) |
205
206
  | `GANG_UPDATE_URL` | Where that check asks, default `https://registry.npmjs.org/@gangfun/cli/latest`; set an npm mirror's `…/@gangfun/cli/latest` if npmjs is slow or blocked |
206
- | `GANG_PAD` / `GANG_TESTNET_PAD` | Override the merged GangLaunchpad (mainnet / testnet) behind both `gang v3` and `gang fair` (defaults: mainnet `0x15CF…4365`, testnet set 10 `0xFebF…5BB1`). Old names `GANG_V3_PAD` / `GANG_FAIR_PAD`, `GANG_V3_TESTNET_PAD` / `GANG_FAIR_TESTNET_PAD` still work as aliases |
207
+ | `GANG_PAD` / `GANG_TESTNET_PAD` | Override the merged GangLaunchpad (mainnet / testnet) behind V3 and 打新 (defaults: mainnet `0x15CF…4365`, testnet set 10 `0xFebF…5BB1`). Old names `GANG_V3_PAD` / `GANG_FAIR_PAD`, `GANG_V3_TESTNET_PAD` / `GANG_FAIR_TESTNET_PAD` still work as aliases |
207
208
  | `GANG_TESTNET_RPC_URL` | Testnet RPC; old names `GANG_V3_TESTNET_RPC_URL` / `GANG_FAIR_TESTNET_RPC_URL` still work |
208
209
  | `GANG_ROUTER` / `GANG_TESTNET_ROUTER` | GangRouter proxy (native-BNB V3 buys / mints, and every PancakeSwap trade of a graduated token); old name `GANG_ROUTER_TESTNET` still works. Defaults: mainnet `0xE040…79C4`, testnet set 10 `0x6bB6…C9F6` |
209
210
 
210
211
  ## Version
211
212
 
212
- `0.10.1` · repo [gangfun/cli](https://github.com/gangfun/cli) · published to [npm](https://www.npmjs.com/package/@gangfun/cli) on push to `main`
213
+ `0.12.0` · repo [gangfun/cli](https://github.com/gangfun/cli) · published to [npm](https://www.npmjs.com/package/@gangfun/cli) on push to `main`
package/README.zh-CN.md CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  用 Binance **Agentic Wallet** 操作 [gang.fun](https://gang.fun)。内盘买入/发币需要 SPACE ID `.ai` Agent ID。本 CLI 只组 calldata,签名走 `baw`,不持有私钥。
4
4
 
5
- **`gang create`:** 发到 GangLaunchpad,等同 `gang v3 create`;不带 `--buy-tax` / `--sell-tax` 就是无税币。LaunchpadV2 / Soft / LaunchpadU / LaunchpadS **不再发新币**,存量币照常交易(`gang buy` / `gang sell`)。新币毕业 ≈ **15 BNB**。Soft 存量链上仍为 20 BNB 毕业。
5
+ **`gang create`:** 在 GangLaunchpad 上发 V3 币(`gang create --fair` 发打新);不带 `--buy-tax` / `--sell-tax` 就是无税币。LaunchpadV2 / Soft / LaunchpadU / LaunchpadS **不再发新币**,存量币照常交易(`gang buy` / `gang sell`)。新币毕业 ≈ **15 BNB**。Soft 存量链上仍为 20 BNB 毕业。
6
6
 
7
- **V3 税收币和打新(0.9.0+):** `gang v3` / `gang fair` 走 GangLaunchpad,2026-10-27 起在 BSC 主网运行(内盘 `0x15CFD2dc8278Fb87a1783ef42111618E20874365`,GangRouter `0xE040445690Aa56C8b68B7f7038C7b2562B5079C4`,都已内置);`--testnet` 走 BSC 测试网第 10 套。
7
+ **一个动作一条命令(0.12.0+):** `gang buy` / `sell` / `info` / `status` / `claim` / `mint` / `withdraw` / `release` 对所有币都能用:CLI 先读出这个币的类型,再执行 V3、打新或 V2 / Soft 的逻辑。`gang v3 …` / `gang fair …` 保留为别名。
8
+
9
+ **V3 税收币和打新(0.9.0+):** 走 GangLaunchpad,2026-10-27 起在 BSC 主网运行(内盘 `0x15CFD2dc8278Fb87a1783ef42111618E20874365`,GangRouter `0xE040445690Aa56C8b68B7f7038C7b2562B5079C4`,都已内置);`--testnet` 走 BSC 测试网第 10 套。
8
10
 
9
11
  ## 安装
10
12
 
@@ -30,7 +32,6 @@ Skill:`npx skills add gangfun/gang-launchpad/skill`
30
32
 
31
33
  ```bash
32
34
  gang preflight
33
- gang list
34
35
  gang hot [--limit 10] [--track all|v2|soft] [--include-graduated] # 按 24h USD 成交量
35
36
  gang new [--limit 10] [--max-age 2h]
36
37
  gang near-grad [--min-pct 50] [--limit 10]
@@ -38,35 +39,33 @@ gang watch [<addr>] [--interval 10] [--events a,b] [--max-events N] [--timeout 3
38
39
  gang notes [--agent a,b] [--min-hit 0.6] [--sort new|author|followers] [--token <addr>] [--limit 10] [--all] # 现在能跟的想法
39
40
  gang watch --notes [--agent a,b] [--min-hit 0.6] [--interval 30] [--events note,revealed] # 新出现的可跟想法
40
41
  gang agents [--window 1d|7d|30d|all] [--sort score|hitRate|count|follow|followUsd] [--limit 10] # 跟谁
41
- gang token --token <addr>
42
- gang quote --token <addr> --bnb <n>
43
- gang buy --token <addr> --bnb <n> [--slippage 1] [--follow <附言 tx>] [--note "<理由>" [--conf 0-100] [--reveal-after 1-72h]]
44
- gang follow <附言 tx> --bnb <n> [--slippage 1] [--note …] # 跟单:买附言里的币,并标明跟的是哪条
45
- gang sell --token <addr> (--amount <tokens> | --all) [--slippage 1] [--note … [--conf …] [--reveal-after …]]
42
+ # 一个动作一条命令,不管币在哪个内盘(0.12.0+):CLI 读 GangLaunchpad 的 kindOf(V3 内盘 / 打新;都不是就走
43
+ # V2 / Soft / U / S),再执行对应的交易。--testnet 走 BSC 测试网第 10 套(只有 GangLaunchpad)
44
+ gang list [--kind v3|fair [--status …]] # V2 / Soft / U / S;--kind:从 gang.fun 列 GangLaunchpad 的币
45
+ gang info --token <addr> # 任意内盘的一个币(gang token 是旧名)
46
+ gang status --token <addr> # 我的持仓:余额;V3 分红 / 打新奖励、还能卖多少;poolSellAll
47
+ gang quote --token <addr> --amount <n> # 只算 V2 / Soft / U / S 内盘(Soft:BNB;V2:报价币 ERC-20)
48
+ gang buy --token <addr> --amount <n> [--slippage 1] [--follow <附言 tx>] [--note "<理由>" [--conf 0-100] [--reveal-after 1-72h]]
49
+ # --amount 是要花的报价币数量(--bnb 是旧名)。V3:含内盘 1% 手续费(内盘不收税;WBNB 报价经 GangRouter 直接付 BNB)。
50
+ # 打新:只能在发射后买。已毕业 / 已发射:经 GangRouter 在 PancakeSwap 买
51
+ gang sell --token <addr> (--amount <枚数> | --all) [--slippage 1] [--to-bnb] [--note … [--conf …] [--reveal-after …]]
52
+ # 打新发射后:卖过 sellableBeforeOut 须加 --confirm-out
53
+ gang mint --token <addr> --shares <n> [--note …] # 打新填满前:另收该币的打新费(1–3%,归平台、不退)
54
+ gang withdraw --token <addr> (--shares <n> | --all) [--note …] # 打新填满前按打新价卖回
55
+ gang claim --token <addr> # V3:领取分红(以报价币到账);打新:领持有奖励
56
+ gang release --token <addr> # V3:补转之前打款失败的税
57
+ gang follow <附言 tx> --amount <n> [--slippage 1] [--note …] # 跟单:买附言里的币,并标明跟的是哪条
46
58
  gang upload-logo (--file ./avatar.png | --url <图片地址>)
47
- gang create … # = gang v3 create(GangLaunchpad);不带 --buy-tax / --sell-tax 即无税
48
- # 打新和 V3 共用一个内盘合约(GangLaunchpad)。默认走主网(地址已内置);--testnet 走 BSC 测试网第 10 套
49
- gang fair create --name <n> --symbol <s> [--raise 15] [--cap 0.5] [--hold 60] [--mint-fee 1] [--exit-fee 1] [--shares 1] [--logo ./avatar.png | --logo-uri URL] [--website URL] [--twitter @handle] [--description "…"] [--testnet]
59
+ # 建币:GangLaunchpad。默认是 V3 币(买 / 卖税各 1–5%,只在外盘收,用报价币打给接收地址:发币人自己,或白名单里的
60
+ # 合作方;不带 --buy-tax / --sell-tax 即无税);加 --fair 是同一个内盘上的打新
61
+ gang create --name <n> --symbol <s> [--buy-tax 2 --sell-tax 2 [--dividend 0] [--recipient 0x…]] [--logo ./avatar.png | --logo-uri URL] [--website URL] [--twitter @handle] [--description "…"] [--testnet]
62
+ gang create --fair --name <n> --symbol <s> [--raise 15] [--cap 0.5] [--hold 60] [--mint-fee 1] [--exit-fee 1] [--shares 1] [--logo …] [--website URL] [--twitter @handle] [--description "…"] [--testnet]
50
63
  # --cap 单地址上限 0.25–1%(1% 时至少 50 个地址),--hold 出局线 60–90%
51
- gang fair mint --token <addr> --shares <n> [--testnet] # 另收该币的打新费(1–3%,归平台、不退)
52
- gang fair withdraw --token <addr> (--shares <n> | --all) [--testnet]
53
- gang fair buy --token <addr> --amount <数量> [--use-quote | --pay-bnb] [--testnet] # 发射后:经 GangRouter 在 PancakeSwap 买
54
- gang fair sell --token <addr> (--amount <枚数> | --all) [--to-bnb] [--confirm-out] [--testnet] # 发射后;卖过 sellableBeforeOut 须加 --confirm-out
55
- gang fair status --token <addr> [--testnet] # 份数;发射后:是否出局、还能卖多少、待领奖励
56
- gang fair claim --token <addr> [--testnet]
57
- gang fair info --token <addr> | gang fair list [--status minting|launched|all] | gang fair tx --hash <0x..> # 查询(可加 --testnet)
58
- # LaunchpadV3 税收币(买 / 卖税各 1–5%,只在外盘收,用报价币打给接收地址:发币人自己,或白名单里的合作方)— 和打新同一个内盘合约
59
- gang v3 create --name <n> --symbol <s> [--buy-tax 2 --sell-tax 2 [--dividend 0] [--recipient 0x…]] [--logo ./avatar.png | --logo-uri URL] [--website URL] [--twitter @handle] [--description "…"] [--testnet]
60
- gang v3 buy --token <addr> --amount <报价币数量> [--testnet] # 含内盘 1% 手续费(内盘不收税,税只在外盘收)
61
- gang v3 sell --token <addr> (--amount <枚数> | --all) [--to-bnb] [--testnet] # 已毕业:buy / sell 经 GangRouter 走 PancakeSwap
62
- gang v3 info --token <addr> [--testnet] # 税率、接收地址、还欠接收地址多少
63
- gang v3 status --token <addr> [--testnet] # 我的持仓和分红:现在可领 + 已记账、还没卖出的部分
64
- gang v3 claim --token <addr> [--testnet] # 领取分红(以报价币到账)
65
- gang v3 release --token <addr> [--testnet] # 补转之前打款失败的税
66
- gang v3 income --recipient 0x… # 接收地址按币统计的到账(读 gang.fun)
67
- gang v3 list [--status curve|graduated|all] | gang v3 tx --hash <0x..> # 查询(可加 --testnet)
64
+ gang v3 income --recipient 0x… # 接收地址按币统计的到账(读 gang.fun)
65
+ # 别名:gang v3 <list|info|status|create|buy|sell|claim|release|tx>、gang fair <list|info|status|create|mint|withdraw|buy|sell|claim|tx>
66
+ # 跑的是同一套代码(结果里带 useInstead)
68
67
  gang execute --request-id <id>
69
- gang tx --hash <0x..>
68
+ gang tx --hash <0x..> [--testnet] # 解析 V2 / Soft 和 GangLaunchpad 的事件(GangLaunchpad 的带 units "raw",金额是 wei)
70
69
  ```
71
70
 
72
71
  ### Logo + 发币
@@ -100,7 +99,7 @@ x.com / twitter.com 链接(主页、帖子、社区),统一存成 `https:/
100
99
 
101
100
  ### 发现(0.3.0+)
102
101
 
103
- `hot` / `new` / `near-grad` / `watch` 读 gang.fun indexer(`GANG_API`),同时覆盖 V2 与 Soft。每行带 `quote`(`--bnb` 的单位)、
102
+ `hot` / `new` / `near-grad` / `watch` 读 gang.fun indexer(`GANG_API`),同时覆盖 V2 与 Soft。每行带 `quote`(`--amount` 的单位)、
104
103
  `progressPct`、`remaining`/`remainingUsd`、`volume24hUsd`、`holders`、`ageMin` 和 `next` 命令;已毕业默认隐藏(`--include-graduated` 显示)。
105
104
 
106
105
  `gang watch` 轮询并输出 NDJSON(最短间隔:单币 3s,全市场 10s):带 `<addr>` 推 `trade` / `progress`(25/50/75/90%)/ `graduated`;不带则推 `new_token` / `near_grad`(越过 `--min-pct`)/ `graduated`。
@@ -113,18 +112,20 @@ x.com / twitter.com 链接(主页、帖子、社区),统一存成 `https:/
113
112
  附言限 1–280 字,不能含链接。`gang execute` 在拿到回执后自动公开;如果交易需要 App 确认,就在确认后用 `gang tx --hash` 补发。
114
113
  加 `--reveal-after 6h` 就是密封想法(41 字节承诺):gang.fun 先保管正文,期间别人只看到"有一条密封想法",交易后 6 小时自动公开。
115
114
  提交后不能撤回;交易后 24 小时内没提交的密封想法,会记为"未兑现"。
116
- `gang create`、`gang v3`、`gang fair` 暂不支持:gang.fun 还匹配不了 GangLaunchpad 上的交易,带 `--note` 会被拒绝。
117
- buy / sell 没带 `--note` 时,preview 里会有 `agentNote: { attached: false, hint }` 提醒;用户说过不要想法的,Agent 照样不写。
115
+ GangLaunchpad 上同样可用(0.11.0+,仅主网):V3 币的 `gang buy` / `sell`、打新的 `gang mint` / `withdraw`,以及建币(`gang create`、
116
+ `gang create --fair`,这时附言就是建币宣言)。`gang buy --follow <附言 tx>` 在 V3 内盘上同样可以跟单(打新不行)。
117
+ 外盘交易不带附言;`--testnet` 会拒绝 `--note`。
118
+ buy / sell / 建币没带 `--note` 时,preview 里会有 `agentNote: { attached: false, hint }` 提醒;用户说过不要想法的,Agent 照样不写。
118
119
  公开失败不影响交易本身。详见 [skill/references/notes.md](https://github.com/gangfun/gang-launchpad/blob/main/skill/references/notes.md)。
119
120
 
120
121
  ```bash
121
- gang buy --token 0x… --bnb 0.1 --note "1 小时量能翻倍,买突破" --conf 70
122
- gang buy --token 0x… --bnb 0.1 --note "消息面发酵前先建仓" --reveal-after 24h # 密封 24 小时
122
+ gang buy --token 0x… --amount 0.1 --note "1 小时量能翻倍,买突破" --conf 70
123
+ gang buy --token 0x… --amount 0.1 --note "消息面发酵前先建仓" --reveal-after 24h # 密封 24 小时
123
124
  ```
124
125
 
125
126
  ### 跟单(`--follow`,0.6.0+)
126
127
 
127
- `gang follow <附言 tx> --bnb <n>` 买入别的 Agent 附言里的那个币,并把这条附言的 tx 写进 calldata
128
+ `gang follow <附言 tx> --amount <n>` 买入别的 Agent 附言里的那个币,并把这条附言的 tx 写进 calldata
128
129
  (37 字节:`67616e67` + `03` + tx hash,放在 `--note` 的承诺前面,附言承诺始终在最末尾)。`gang buy --token … --follow <附言 tx>` 效果相同。
129
130
  gang.fun 会按附言和 Agent 统计跟单人数、金额,以及跟单者 24 小时后是否赚钱。
130
131
  只能跟买入附言和发币宣言,且是同一个币;附言之后 24 小时内、毕业前的内盘买入才算;不能跟自己,单笔不足 $1 不计入。
@@ -134,9 +135,9 @@ preview 里有 `follow.followableUntil`(可跟至,本地时间)和 `blind`
134
135
  详见 [skill/references/follow.md](https://github.com/gangfun/gang-launchpad/blob/main/skill/references/follow.md)。
135
136
 
136
137
  ```bash
137
- gang follow 0x<附言 tx> --bnb 0.1
138
- gang follow 0x<附言 tx> --bnb 0.1 --note "同样的判断:这条附言之后持有人涨了 30%" --conf 60
139
- gang buy --token 0x… --bnb 0.1 --follow 0x<附言 tx>
138
+ gang follow 0x<附言 tx> --amount 0.1
139
+ gang follow 0x<附言 tx> --amount 0.1 --note "同样的判断:这条附言之后持有人涨了 30%" --conf 60
140
+ gang buy --token 0x… --amount 0.1 --follow 0x<附言 tx>
140
141
  ```
141
142
 
142
143
  发现跟单机会(0.8.0+):`gang notes` 列出现在买入还能算跟单的想法,新的在前。每条带作者近 30 天的战绩(说中率、信心校准分、
@@ -160,10 +161,10 @@ gang agents --window 30d --sort follow
160
161
 
161
162
  - 内盘每钱包 1%;多付同笔退回。
162
163
  - **新**发币(GangLaunchpad)≈15 BNB 毕业。LaunchpadV2 只剩存量币。Soft 存量归档:20 BNB,仅买卖。
163
- - 毕业前不可转账;毕业后走 PancakeSwap:`gang buy` / `gang sell`(以及 `gang v3 buy|sell`、发射后的 `gang fair buy|sell`)
164
+ - 毕业前不可转账;毕业(或打新发射)后走 PancakeSwap:`gang buy` / `gang sell`
164
165
  经 GangRouter 在外盘成交。先只授权本次用量,再发 `poolBuy` / `poolBuyBNB` / `poolSell` / `poolSellForBNB`;最少到手:买入按
165
166
  `getAmountsOut` 扣买入税,卖出按税 handler 的 `previewSellNextBlock`,再扣 `--slippage`。`--use-quote` / `--pay-bnb` 选买入用什么付,
166
- `--to-bnb` 卖成 BNB。带税的卖出约需 70 万 gas(会顺带换一块税):让钱包自动估算,或者至少给 75 万。生成任何步骤前先核对路由是带外盘功能的 GangRouter(不会是 Pancake 或旧路由);`--from` 只对外盘交易生效。详见 `references/v3.md`「Pool trades」。
167
+ `--to-bnb` 卖成 BNB。带税的卖出约需 70 万 gas(会顺带换一块税):让钱包自动估算,或者至少给 75 万。生成任何步骤前先核对路由是带外盘功能的 GangRouter(不会是 Pancake 或旧路由);`--from` 只对外盘交易(以及 V3 / 打新的币)生效。详见 `references/v3.md`「Pool trades」。
167
168
 
168
169
  ## 环境变量
169
170
 
@@ -176,10 +177,10 @@ gang agents --window 30d --sort follow
176
177
  | `GANG_NOTES_DIR` | 附言的本地队列,每条一个文件,记着 salt 和提交状态,保留 24 小时(默认 `~/.gang/notes`);其中的 `previews/` 记着每次交易 preview 带了什么(附言、跟单),供 `gang execute` 使用,也保留 24 小时 |
177
178
  | `GANG_UPDATE_CHECK` | 设为 `0` 关闭每天一次的新版本检查(查 npm,缓存在 `~/.gang/update.json`) |
178
179
  | `GANG_UPDATE_URL` | 新版本检查查询的地址,默认 `https://registry.npmjs.org/@gangfun/cli/latest`;npmjs 慢或打不开时,可以换成 npm 镜像的 `…/@gangfun/cli/latest` |
179
- | `GANG_PAD` / `GANG_TESTNET_PAD` | 覆盖合并后的内盘合约 GangLaunchpad(主网 / 测试网),`gang v3` 和 `gang fair` 共用(默认:主网 `0x15CF…4365`,测试网第 10 套 `0xFebF…5BB1`)。旧名 `GANG_V3_PAD` / `GANG_FAIR_PAD`、`GANG_V3_TESTNET_PAD` / `GANG_FAIR_TESTNET_PAD` 仍可用(别名) |
180
+ | `GANG_PAD` / `GANG_TESTNET_PAD` | 覆盖合并后的内盘合约 GangLaunchpad(主网 / 测试网),V3 和打新共用(默认:主网 `0x15CF…4365`,测试网第 10 套 `0xFebF…5BB1`)。旧名 `GANG_V3_PAD` / `GANG_FAIR_PAD`、`GANG_V3_TESTNET_PAD` / `GANG_FAIR_TESTNET_PAD` 仍可用(别名) |
180
181
  | `GANG_TESTNET_RPC_URL` | 测试网 RPC;旧名 `GANG_V3_TESTNET_RPC_URL` / `GANG_FAIR_TESTNET_RPC_URL` 仍可用 |
181
182
  | `GANG_ROUTER` / `GANG_TESTNET_ROUTER` | GangRouter 代理(用原生 BNB 买 V3 / 打新,以及已毕业币的所有外盘买卖);旧名 `GANG_ROUTER_TESTNET` 仍可用。默认:主网 `0xE040…79C4`,测试网第 10 套 `0x6bB6…C9F6` |
182
183
 
183
184
  ## 版本
184
185
 
185
- `0.10.1` · [gangfun/cli](https://github.com/gangfun/cli) · push 到 `main` 自动发布到 [npm](https://www.npmjs.com/package/@gangfun/cli)
186
+ `0.12.0` · [gangfun/cli](https://github.com/gangfun/cli) · push 到 `main` 自动发布到 [npm](https://www.npmjs.com/package/@gangfun/cli)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gangfun/cli",
3
- "version": "0.10.1",
3
+ "version": "0.12.0",
4
4
  "description": "Gang launchpad CLI for Binance Agentic Wallet agents: create on GangLaunchpad (untaxed or tax tokens), 打新 fair mint, PancakeSwap pool trades, LaunchpadV2 and legacy Soft/U/S trade.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/chain.js CHANGED
@@ -32,8 +32,8 @@ const PADS = [
32
32
  ]
33
33
 
34
34
  const GANG_POINTER = {
35
- v3: (t) => `a GangLaunchpad V3 (bonding-curve) token: use gang v3 (gang v3 info|buy|sell|status --token ${t})`,
36
- fair: (t) => `a GangLaunchpad 打新 (fair-mint) token: use gang fair (gang fair info|status --token ${t}; before launch mint / withdraw, after it buy / sell)`,
35
+ v3: (t) => `a GangLaunchpad V3 (bonding-curve) token: gang info|buy|sell|status --token ${t} trade it (re-run if this was an RPC hiccup)`,
36
+ fair: (t) => `a GangLaunchpad 打新 (fair-mint) token: gang info|status --token ${t}; before launch gang mint / withdraw, after it gang buy / sell (re-run if this was an RPC hiccup)`,
37
37
  }
38
38
 
39
39
  /** Resolve which pad hosts `token` by probing curves(token).creator != 0; a GangLaunchpad token is pointed at its command. */
@@ -261,13 +261,36 @@ export const calldata = {
261
261
  wrap: () => encodeFunctionData({ abi: WBNB_ABI, functionName: 'deposit' }),
262
262
  }
263
263
 
264
- export async function decodeTx(hash) {
264
+ /**
265
+ * Events of the logs that decode with one of `abis`, each with the emitting contract: GangLaunchpad logs, which `gang tx`
266
+ * reads beside the V2 / Soft / U / S pads'. Integers stay as on chain (strings), marked `units: 'raw'`: amounts are in wei
267
+ * (18 decimals), bps / shares / counts as they are; the V2 / Soft events are formatted (no `units`).
268
+ */
269
+ export function decodeLogs(logs, abis) {
270
+ const events = []
271
+ for (const log of logs) {
272
+ for (const abi of abis) {
273
+ try {
274
+ const ev = decodeEventLog({ abi, data: log.data, topics: log.topics })
275
+ events.push({ event: ev.eventName, contract: log.address, units: 'raw', ...Object.fromEntries(Object.entries(ev.args).map(([k, v]) => [k, typeof v === 'bigint' ? v.toString() : v])) })
276
+ break
277
+ } catch { /* other contract / event */ }
278
+ }
279
+ }
280
+ return events
281
+ }
282
+
283
+ /** `extraAbis`: decoders for logs not from the V2 / Soft / U / S pads (see decodeLogs). */
284
+ export async function decodeTx(hash, extraAbis = []) {
265
285
  const r = await client.waitForTransactionReceipt({ hash, timeout: 120_000 })
266
286
  const events = []
267
287
  const known = new Map(PADS.map((p) => [p.address.toLowerCase(), p]))
268
288
  for (const log of r.logs) {
269
289
  const pad = known.get(log.address.toLowerCase())
270
- if (!pad) continue
290
+ if (!pad) {
291
+ events.push(...decodeLogs([log], extraAbis))
292
+ continue
293
+ }
271
294
  try {
272
295
  const ev = decodeEventLog({ abi: pad.abi, data: log.data, topics: log.topics })
273
296
  const a = Object.fromEntries(Object.entries(ev.args).map(([k, v]) => {
package/src/fair.js CHANGED
@@ -3,7 +3,7 @@ import { bawAddress } from './baw.js'
3
3
  import { defaultRefPool, dividendOf, fundingStep as fund, parseAmount, parseIntIn, parseNum, poolSellQuote, POOL_SELL_HINT, revertOf as revertIn, ROUTER_ABI, ROUTER_HINTS, routerDeadline, step, swapBackState, units, viaRouter, GAS_RESERVE } from './steps.js'
4
4
  import { API } from './discover.js'
5
5
  import { UA } from './version.js'
6
- import { MERGED_ERRORS_ABI, MERGED_HINTS, NOT_ON_MAINNET, noteFlagError, notThisKind, padNets } from './gangpad.js'
6
+ import { MERGED_ERRORS_ABI, MERGED_HINTS, NOT_ON_MAINNET, notThisKind, padNets } from './gangpad.js'
7
7
  import { poolPayBnb, poolTrade } from './pool.js'
8
8
 
9
9
  /**
@@ -81,7 +81,7 @@ const STATUS = ['none', 'minting', 'launched']
81
81
  const HINTS = {
82
82
  BadConfig: 'a rule is out of bounds: see reason',
83
83
  NotAgent: 'this wallet holds no Agent ID; fair mint is Agent-only',
84
- NotMinting: 'the sale already launched: trade the token in the pool with gang fair buy / gang fair sell',
84
+ NotMinting: 'the sale already launched: trade the token in the pool with gang buy / gang sell',
85
85
  WalletCapReached: 'this wallet already holds the per-wallet cap of shares',
86
86
  Slippage: 'fewer shares are left than --min-shares (someone filled first)',
87
87
  BadAmount: '--shares is more than this wallet holds in the sale',
@@ -104,6 +104,9 @@ const HINTS = {
104
104
  VaultFloorTooHigh: 'the platform\'s dividend vault requires a larger holding than fair-mint rewards allow, so no sale can be created right now; ask gang to fix the vault setting',
105
105
  }
106
106
 
107
+ /** What `gang tx` decodes a 打新 trade's logs with (the pad, the holder-reward vault). */
108
+ export const FAIR_EVENT_ABIS = [PAD_ABI, VAULT_ABI]
109
+
107
110
  export function fairCtx(testnet) {
108
111
  const net = FAIR_NETS[testnet ? 'testnet' : 'mainnet']
109
112
  if (!net.pad) throw new Error(NOT_ON_MAINNET)
@@ -227,19 +230,16 @@ async function positionOf(ctx, token, me, sale, slippage) {
227
230
  }
228
231
 
229
232
  /**
230
- * Entry for `gang fair <sub>`. io: { args, opt, flag, out, fail, summarize } from index.js
231
- * (summarize = summarizePreview, so previews look like every other command's).
233
+ * Entry for `gang fair <sub>`. io: { opt, flag, out, fail, summarize, resolveLogo, checkMeta, resolveMeta, notes } from
234
+ * index.js (summarize = summarizePreview, so previews look like every other command's; notes = padNotes: --note).
232
235
  */
233
236
  const SUBS = ['list', 'info', 'status', 'create', 'mint', 'withdraw', 'buy', 'sell', 'claim', 'tx']
234
237
  /** withdraw reverts below the preview minus this (bps): it catches an exit fee coming back (≥ 1%). */
235
238
  const WITHDRAW_TOLERANCE_BPS = 10n
236
239
  const USAGE = 'usage: gang fair <list|info|status|create|mint|withdraw|buy|sell|claim|tx> [--testnet] — see gang help'
237
240
 
238
- export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLogo, checkMeta, resolveMeta }) {
241
+ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLogo, checkMeta, resolveMeta, notes }) {
239
242
  if (!SUBS.includes(sub)) return fail(USAGE, { got: sub ?? null })
240
- // agent notes are matched to curve trades / creates on the server; fair-mint txs are not indexed there yet
241
- const noteError = noteFlagError(flag, 'gang fair', 'a fair-mint tx')
242
- if (noteError) return fail(noteError)
243
243
  const testnet = flag('testnet')
244
244
  const rawOnly = flag('calldata')
245
245
  if (sub === 'list') {
@@ -247,7 +247,7 @@ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLog
247
247
  if (!['minting', 'launched', 'all'].includes(status)) fail('--status must be minting, launched or all')
248
248
  const r = await fetch(`${API}/fair/sales?status=${status}&limit=30`, { headers: { 'user-agent': UA }, signal: AbortSignal.timeout(10_000) })
249
249
  .then((x) => (x.ok ? x.json() : { error: x.status })).catch((e) => ({ error: e.message }))
250
- if (r.error) return out({ success: false, error: `gang.fun fair list unavailable (${r.error})`, hint: `use gang fair info --token <addr>${testnet ? ' --testnet' : ''} for one sale` })
250
+ if (r.error) return out({ success: false, error: `gang.fun fair list unavailable (${r.error})`, hint: `use gang info --token <addr>${testnet ? ' --testnet' : ''} for one sale` })
251
251
  return out({ success: true, status, items: (r.items || []).map((x) => ({
252
252
  token: x.address, symbol: x.symbol, status: x.status, sold: x.sold, participants: x.participants,
253
253
  sharePrice: x.sharePrice && formatUnits(BigInt(x.sharePrice), 18), quote: x.quoteSymbol, chainId: x.chainId,
@@ -311,7 +311,7 @@ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLog
311
311
  const need = sharePrice * BigInt(devShares) + fee
312
312
  const me = walletFor(ctx, opt('from'))
313
313
  const pre = await fundingStep(ctx, me, quote, need, sym, rawOnly, summarize)
314
- if (pre) return out(pre)
314
+ if (pre) return out(pre.success ? { ...pre, ...notes.skipped() } : pre)
315
315
  // logoURI is permanent on-chain: same handling as `gang create` (--logo file upload, other hosts copied to gang.fun).
316
316
  // Done after the setup steps so a wrap / approve round does not upload the image twice.
317
317
  const createData = (logoURI, metaURI) => encodeFunctionData({
@@ -323,14 +323,14 @@ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLog
323
323
  const logo = await resolveLogo()
324
324
  const meta = await resolveMeta({ name, symbol, logoURI: logo.logoURI })
325
325
  const data = createData(logo.logoURI, meta.metaURI)
326
- return out(step(ctx, { from: me, to: ctx.pad, data }, {
326
+ return out(notes.step(ctx, { from: me, to: ctx.pad, data }, {
327
327
  step: 'create', chainId: Number(ctx.chainId), name, symbol, logoURI: logo.logoURI, ...(logo.uploaded && { uploaded: true }),
328
328
  metaURI: meta.metaURI, metadata: meta.metadata, quote: sym || quote,
329
329
  raise: await units(ctx, quote, raiseQuote), sharePrice: await units(ctx, quote, sharePrice),
330
330
  capShares: cfg.capBps * 2, minWallets: Math.ceil(10_000 / (cfg.capBps * 2)), holdPct, mintFeePct, exitFeePct, devShares,
331
331
  devCost: await units(ctx, quote, need),
332
332
  note: 'no deadline: the sale stays open until all 10,000 shares are minted, then launches. Minters can sell shares back at the mint price (minus the exit fee; none after 7 days without progress, i.e. fewer than 10 new shares). The mint fee is the platform\'s and is not returned.',
333
- }, rawOnly, summarize))
333
+ }, 'create'))
334
334
  }
335
335
 
336
336
  if (sub === 'mint') {
@@ -339,7 +339,7 @@ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLog
339
339
  const sale = await saleOf(ctx, token)
340
340
  if (!sale) return notFair(token)
341
341
  if (sale.status !== 'minting') {
342
- return fail(`sale is ${sale.status}, not minting`, { hint: `it launched: buy in the pool with gang fair buy --token ${token} --amount <quote>${testnet ? ' --testnet' : ''}` })
342
+ return fail(`sale is ${sale.status}, not minting`, { hint: `it launched: buy in the pool with gang buy --token ${token} --amount <quote>${testnet ? ' --testnet' : ''}` })
343
343
  }
344
344
  const me = walletFor(ctx, opt('from'))
345
345
  if (sale.gate !== zeroAddress && (await ctx.read(sale.gate, ERC721_ABI, 'balanceOf', [me])) === 0n) {
@@ -368,14 +368,14 @@ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLog
368
368
  const data = encodeFunctionData({ abi: ROUTER_ABI, functionName: 'fairMintBNB', args: [token, accepted, BigInt(minShares), routerDeadline()] })
369
369
  const dry = await dryRun(ctx, me, ctx.router, data, need)
370
370
  if (dry) return out({ success: false, step: 'mint', via: 'router', ...dry })
371
- return out(step(ctx, { from: me, to: ctx.router, data, value: need }, { ...extra, via: 'router', payBnb: formatUnits(need, 18) }, rawOnly, summarize))
371
+ return out(notes.step(ctx, { from: me, to: ctx.router, data, value: need }, { ...extra, via: 'router', payBnb: formatUnits(need, 18) }, 'buy'))
372
372
  }
373
373
  const pre = await fundingStep(ctx, me, sale.quote, need, sale.quoteSymbol, rawOnly, summarize)
374
- if (pre) return out(pre)
374
+ if (pre) return out(pre.success ? { ...pre, ...notes.skipped() } : pre)
375
375
  const data = encodeFunctionData({ abi: PAD_ABI, functionName: 'mint', args: [token, accepted, BigInt(minShares)] })
376
376
  const dry = await dryRun(ctx, me, ctx.pad, data)
377
377
  if (dry) return out({ success: false, step: 'mint', ...dry })
378
- return out(step(ctx, { from: me, to: ctx.pad, data }, extra, rawOnly, summarize))
378
+ return out(notes.step(ctx, { from: me, to: ctx.pad, data }, extra, 'buy'))
379
379
  }
380
380
 
381
381
  if (sub === 'withdraw') {
@@ -385,7 +385,7 @@ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLog
385
385
  if (sale.status !== 'minting') {
386
386
  return fail(`sale is ${sale.status}: withdraw only while minting`, sale.launched ? {
387
387
  pair: sale.pair,
388
- hint: `it launched: sell in the pool with \`gang fair sell --token ${token} (--amount <tokens> | --all)${testnet ? ' --testnet' : ''}${opt('from') ? ` --from ${opt('from')}` : ''} [--slippage 1] [--to-bnb]\``
388
+ hint: `it launched: sell in the pool with \`gang sell --token ${token} (--amount <tokens> | --all)${testnet ? ' --testnet' : ''}${opt('from') ? ` --from ${opt('from')}` : ''} [--slippage 1] [--to-bnb]\``
389
389
  + ' (through GangRouter; minOut from the tax handler\'s previewSellNextBlock)',
390
390
  } : {})
391
391
  }
@@ -400,7 +400,7 @@ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLog
400
400
  const data = encodeFunctionData({ abi: PAD_ABI, functionName: 'withdraw', args: [token, BigInt(shares), minPayout] })
401
401
  const dry = await dryRun(ctx, me, ctx.pad, data)
402
402
  if (dry) return out({ success: false, step: 'withdraw', ...dry })
403
- return out(step(ctx, { from: me, to: ctx.pad, data }, {
403
+ return out(notes.step(ctx, { from: me, to: ctx.pad, data }, {
404
404
  step: 'withdraw', chainId: Number(ctx.chainId), token, shares,
405
405
  receive: await units(ctx, sale.quote, payout), minReceive: await units(ctx, sale.quote, minPayout),
406
406
  exitFee: await units(ctx, sale.quote, fee), quote: sale.quoteSymbol,
@@ -408,7 +408,7 @@ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLog
408
408
  note: sale.stale
409
409
  ? `no progress for 7 days: no exit fee, the full mint price back; the ${sale.mintFeePct}% paid at mint is not returned`
410
410
  : `mint price − ${sale.exitFeeNowPct}% exit fee (none after 7 days without 10 new shares); the ${sale.mintFeePct}% paid at mint is not returned`,
411
- }, rawOnly, summarize))
411
+ }, 'sell'))
412
412
  }
413
413
 
414
414
  if (sub === 'buy' || sub === 'sell') {
@@ -417,8 +417,8 @@ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLog
417
417
  const sale = await saleOf(ctx, token)
418
418
  if (!sale) return notFair(token)
419
419
  if (!sale.launched || !sale.pair) {
420
- return fail(`sale is ${sale.status}: gang fair ${sub} trades the token in its pool after launch`, {
421
- hint: sub === 'buy' ? 'while minting, buy shares with gang fair mint --shares <n>' : 'while minting, sell shares back with gang fair withdraw (--shares <n> | --all)',
420
+ return fail(`sale is ${sale.status}: gang ${sub} trades the token in its pool after launch`, {
421
+ hint: sub === 'buy' ? `while minting, buy shares with gang mint --token ${token} --shares <n>` : `while minting, sell shares back with gang withdraw --token ${token} (--shares <n> | --all)`,
422
422
  })
423
423
  }
424
424
  const slippage = parseNum(fail, 'slippage', opt('slippage', '1'), 0, 50)
@@ -461,7 +461,7 @@ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLog
461
461
  side: sub, token, quote: sale.quote, me, slippage, buyTaxBps: Number(buyTaxBps), sellTaxBps: Number(sellTaxBps), handler,
462
462
  amount: sub === 'sell' && flag('all') ? null : parseAmount(fail, 'amount', opt('amount')), all: sub === 'sell' && flag('all'),
463
463
  swapBackGas: Number(sellTaxBps) > 0, payBnb: sub === 'buy' && poolPayBnb(ctx, sale.quote, flag), toBnb: flag('to-bnb'),
464
- base: { kind: 'fair', pair: sale.pair, ...(outWarning && { ...outWarning, confirmedOut: true }) },
464
+ base: { kind: 'fair', pair: sale.pair, ...notes.pool, ...(outWarning && { ...outWarning, confirmedOut: true }) },
465
465
  }, { rawOnly, summarize, revertOf }))
466
466
  }
467
467
 
@@ -476,7 +476,7 @@ export async function runFair(sub, { opt, flag, out, fail, summarize, resolveLog
476
476
  if (r.claimableRaw === 0n) {
477
477
  return fail('nothing to claim yet', {
478
478
  ...(unsold && { creditedUnsoldEstimate: r.creditedUnsoldEstimate, note: r.note }),
479
- hint: `gang fair status --token ${token}${testnet ? ' --testnet' : ''}`,
479
+ hint: `gang status --token ${token}${testnet ? ' --testnet' : ''}`,
480
480
  })
481
481
  }
482
482
  const data = encodeFunctionData({ abi: VAULT_ABI, functionName: 'claim', args: [token] })
package/src/follow.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Follow trades: a buy that names the note it follows (follow ref in the calldata, see notes.js).
3
3
  * gang.fun checks whether the note can still be followed (GET /api/notes/:tx/followable) and scores the follow later.
4
4
  */
5
- import { formatEther } from 'viem'
5
+ import { formatUnits } from 'viem'
6
6
  import { API } from './discover.js'
7
7
  import { fetchError, statusError, why } from './logo.js'
8
8
  import { UA } from './version.js'
@@ -63,15 +63,18 @@ export function checkFollow(noteTx, trader, token) {
63
63
  })
64
64
  }
65
65
 
66
+ // gang.fun's token page per track: Soft (BNB), the LaunchpadV2 family, GangLaunchpad V3
67
+ const TRACK_PATH = { soft: '/tokens', v2: '/stocks/tokens', v3: '/v3/tokens' }
68
+
66
69
  /**
67
- * Rough USD value of paying `wei` of the token's quote (BNB on Soft), from gang.fun's prices; null if unknown.
68
- * Best effort with a short timeout: it only decides whether the preview warns, never whether it's made.
70
+ * Rough USD value of paying `wei` of the token's quote (BNB on Soft; `decimals` of the quote), from gang.fun's prices;
71
+ * null if unknown. Best effort with a short timeout: it only decides whether the preview warns, never whether it's made.
69
72
  */
70
- export async function amountUsd(token, soft, wei) {
73
+ export async function amountUsd(token, track, wei, decimals = 18) {
71
74
  try {
72
- const { status, body } = await getJson(`${soft ? '/tokens' : '/stocks/tokens'}/${token.toLowerCase()}`, 3_000)
73
- const unit = Number(soft ? body?.bnbUsd : body?.quoteUsd)
74
- const usd = Number(formatEther(wei)) * unit
75
+ const { status, body } = await getJson(`${TRACK_PATH[track]}/${token.toLowerCase()}`, 3_000)
76
+ const unit = Number(track === 'soft' ? body?.bnbUsd : body?.quoteUsd)
77
+ const usd = Number(formatUnits(wei, decimals)) * unit
75
78
  if (status !== 200 || !Number.isFinite(usd) || !(unit > 0)) return null
76
79
  // cents above $1; two significant digits below, so a tiny buy doesn't read as $0
77
80
  return usd >= 1 ? Math.round(usd * 100) / 100 : Number(usd.toPrecision(2))